Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify environment variables #7694

Merged
merged 9 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ public void NoCategorySettings()
IEnvironment? env = Substitute.For<IEnvironment>();
env.GetEnvironmentVariables().Returns(new Dictionary<string, string>() {
{ "NETHERMIND_CLI_SWITCH_LOCAL", "http://localhost:80" },
{ "NETHERMIND_MONITORING_JOB", "nethermindJob" },
{ "NETHERMIND_MONITORING_GROUP", "nethermindGroup" },
{ "NETHERMIND_ENODE_IPADDRESS", "1.2.3.4" },
{ "NETHERMIND_URL", "http://test:80" },
{ "NETHERMIND_CORS_ORIGINS", "*" },
{ "NETHERMIND_CONFIG", "test2.json" },
{ "NETHERMIND_XYZ", "xyz" }, // not existing, should get error
{ "QWER", "qwerty" } // not Nethermind setting, no error
Expand Down
6 changes: 3 additions & 3 deletions src/Nethermind/Nethermind.Config/EnvConfigSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@ public EnvConfigSource(IEnvironment environmentWrapper)
return (null, null);
}

// variables like "NETHERMIND_URL", "NETHERMIND_CONFIG" ...
// variables like "NETHERMIND_CONFIG"
if (a.Length == 2)
{
return (null, a[1]);
}

// VARIABLES like "NETHERMIND_CLI_SWITCH_LOCAL", "NETHERMIND_MONITORING_JOB" ...
// VARIABLES like "NETHERMIND_CLI_SWITCH_LOCAL"
if (a.Length > 2 && !a[1].EndsWith("config", StringComparison.OrdinalIgnoreCase))
{
return (null, string.Join(null, a[1..]));
}

// Variables like "NETHERMIND_JSONRPCCONFIG_ENABLED" ...
// Variables like "NETHERMIND_JSONRPCCONFIG_ENABLED"
return (a[1], a[2]);
});
}
Expand Down
15 changes: 0 additions & 15 deletions src/Nethermind/Nethermind.Config/INoCategoryConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,6 @@ public interface INoCategoryConfig : IConfig
[ConfigItem(Description = "Path to the configuration file.")]
public string Config { get; set; }

[ConfigItem(Description = "Sets the job name for metrics monitoring.", EnvironmentVariable = "NETHERMIND_MONITORING_JOB")]
public string MonitoringJob { get; set; }

[ConfigItem(Description = "Sets the default group name for metrics monitoring.", EnvironmentVariable = "NETHERMIND_MONITORING_GROUP")]
public string MonitoringGroup { get; set; }

[ConfigItem(Description = "Sets the external IP for the node.", EnvironmentVariable = "NETHERMIND_ENODE_IPADDRESS")]
public string EnodeIpAddress { get; set; }

[ConfigItem(Description = "Defines default URL for JSON RPC.", EnvironmentVariable = "NETHERMIND_URL")]
public string Url { get; set; }

[ConfigItem(Description = "Defines CORS origins for JSON RPC.", DefaultValue = "*", EnvironmentVariable = "NETHERMIND_CORS_ORIGINS")]
public string CorsOrigins { get; set; }

[ConfigItem(Description = "Defines host value for CLI function \"switchLocal\".", DefaultValue = "http://localhost", EnvironmentVariable = "NETHERMIND_CLI_SWITCH_LOCAL")]
public string CliSwitchLocal { get; set; }
}
3 changes: 0 additions & 3 deletions src/Nethermind/Nethermind.Config/NoCategoryConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,5 @@ public class NoCategoryConfig : INoCategoryConfig
public string Config { get; set; } = null;
public string MonitoringJob { get; set; }
public string MonitoringGroup { get; set; }
public string EnodeIpAddress { get; set; }
public string Url { get; set; }
public string CorsOrigins { get; set; }
public string CliSwitchLocal { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using Nethermind.Logging;
using Nethermind.JsonRpc.Modules;
Expand All @@ -20,12 +19,6 @@ public void Initialize()

private string[] _enabledModules = null!;

[TearDown]
public void TearDown()
{
Environment.SetEnvironmentVariable("NETHERMIND_URL", null, EnvironmentVariableTarget.Process);
}

[Test]
public void Empty_when_disabled()
{
Expand All @@ -50,24 +43,6 @@ public void Contains_single_default_url()
}, Is.EquivalentTo(urlCollection));
}

[Test]
public void Contains_single_default_url_overridden_by_environment_variable()
{
Environment.SetEnvironmentVariable("NETHERMIND_URL", "http://localhost:1234", EnvironmentVariableTarget.Process);

JsonRpcConfig jsonRpcConfig = new JsonRpcConfig()
{
Enabled = true,
EnabledModules = _enabledModules
};

JsonRpcUrlCollection urlCollection = new JsonRpcUrlCollection(Substitute.For<ILogManager>(), jsonRpcConfig, true);
Assert.That(new Dictionary<int, JsonRpcUrl>()
{
{ 1234, new JsonRpcUrl("http", "localhost", 1234, RpcEndpoint.Http | RpcEndpoint.Ws, false, _enabledModules) }
}, Is.EquivalentTo(urlCollection));
}

[Test]
public void Contains_multiple_default_urls_with_different_ws_port()
{
Expand Down
3 changes: 3 additions & 0 deletions src/Nethermind/Nethermind.JsonRpc/IJsonRpcConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,7 @@ public interface IJsonRpcConfig : IConfig

[ConfigItem(Description = "The error margin used in the `eth_estimateGas` JSON-RPC method, in basis points.", DefaultValue = "150")]
int EstimateErrorMargin { get; set; }

[ConfigItem(Description = "The JSON-RPC server CORS origins.", DefaultValue = "*")]
string[] CorsOrigins { get; set; }
}
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.JsonRpc/JsonRpcConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.Linq;
using Nethermind.Core.Extensions;
using Nethermind.JsonRpc.Modules;
Expand Down Expand Up @@ -57,6 +58,7 @@ public int WebSocketsPort
public long? MaxBatchResponseBodySize { get; set; } = 32.MiB();
public long? MaxSimulateBlocksCap { get; set; } = 256;
public int EstimateErrorMargin { get; set; } = 150;
public string[] CorsOrigins { get; set; } = ["*"];
};
};

16 changes: 0 additions & 16 deletions src/Nethermind/Nethermind.JsonRpc/JsonRpcUrlCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ namespace Nethermind.JsonRpc
{
public class JsonRpcUrlCollection : Dictionary<int, JsonRpcUrl>, IJsonRpcUrlCollection
{
private const string NethermindUrlVariable = "NETHERMIND_URL";

private readonly ILogger _logger;
private readonly IJsonRpcConfig _jsonRpcConfig;

Expand All @@ -34,20 +32,6 @@ private void BuildUrls(bool includeWebSockets)
{
bool HasEngineApi = _jsonRpcConfig.EnabledModules.Any(m => m.Equals(ModuleType.Engine, StringComparison.InvariantCultureIgnoreCase));
JsonRpcUrl defaultUrl = new(Uri.UriSchemeHttp, _jsonRpcConfig.Host, _jsonRpcConfig.Port, RpcEndpoint.Http, HasEngineApi, _jsonRpcConfig.EnabledModules, HasEngineApi ? SocketClient<WebSocketMessageStream>.MAX_REQUEST_BODY_SIZE_FOR_ENGINE_API : _jsonRpcConfig.MaxRequestBodySize);
string environmentVariableUrl = Environment.GetEnvironmentVariable(NethermindUrlVariable);
if (!string.IsNullOrWhiteSpace(environmentVariableUrl))
{
if (Uri.TryCreate(environmentVariableUrl, UriKind.Absolute, out Uri? uri))
{
defaultUrl.Scheme = uri.Scheme;
defaultUrl.Host = uri.Host;
defaultUrl.Port = !uri.IsDefaultPort ? uri.Port : defaultUrl.Port;
}
else
{
if (_logger.IsWarn) _logger.Warn($"Environment variable '{NethermindUrlVariable}' value '{environmentVariableUrl}' is not valid JSON RPC URL, using default url : '{defaultUrl}'");
}
}

Add(defaultUrl.Port, defaultUrl);

Expand Down
12 changes: 9 additions & 3 deletions src/Nethermind/Nethermind.Monitoring/Config/IMetricsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface IMetricsConfig : IConfig
[ConfigItem(Description = "The IP address to expose Prometheus metrics at. The value of `+` means listening on all available hostnames. Setting this to `localhost` prevents remote access.", DefaultValue = "+")]
string ExposeHost { get; }

[ConfigItem(Description = "The port to expose Prometheus metrics at.", DefaultValue = "null")]
[ConfigItem(Description = "The port to expose Prometheus metrics at.")]
int? ExposePort { get; }

[ConfigItem(Description = "Whether to publish various metrics to Prometheus Pushgateway at a given interval.", DefaultValue = "false")]
Expand All @@ -20,15 +20,21 @@ public interface IMetricsConfig : IConfig
[ConfigItem(Description = "Whether to publish metrics using .NET diagnostics that can be collected with dotnet-counters.", DefaultValue = "false")]
bool CountersEnabled { get; }

[ConfigItem(Description = "The Prometheus Pushgateway instance URL.", DefaultValue = "")]
[ConfigItem(Description = "The Prometheus Pushgateway instance URL.")]
string PushGatewayUrl { get; }

[ConfigItem(DefaultValue = "5", Description = "The frequency of pushing metrics to Prometheus, in seconds.")]
int IntervalSeconds { get; }

[ConfigItem(Description = "The name to display on the Grafana dashboard.", DefaultValue = "\"Nethermind\"")]
[ConfigItem(Description = "The name to display on the Grafana dashboard.", DefaultValue = "Nethermind")]
string NodeName { get; }

[ConfigItem(Description = "Whether to publish database size metrics.", DefaultValue = "true")]
bool EnableDbSizeMetrics { get; }

[ConfigItem(Description = "The Prometheus metrics group name.", DefaultValue = "nethermind")]
string MonitoringGroup { get; }

[ConfigItem(Description = "The Prometheus metrics job name.", DefaultValue = "nethermind")]
string MonitoringJob { get; }
}
4 changes: 3 additions & 1 deletion src/Nethermind/Nethermind.Monitoring/Config/MetricsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ public class MetricsConfig : IMetricsConfig
public int? ExposePort { get; set; } = null;
public bool Enabled { get; set; } = false;
public bool CountersEnabled { get; set; } = false;
public string PushGatewayUrl { get; set; } = "";
public string PushGatewayUrl { get; set; } = null;
public int IntervalSeconds { get; set; } = 5;
public string NodeName { get; set; } = "Nethermind";
public bool EnableDbSizeMetrics { get; set; } = true;
public string MonitoringGroup { get; set; } = "nethermind";
public string MonitoringJob { get; set; } = "nethermind";
}
}
61 changes: 20 additions & 41 deletions src/Nethermind/Nethermind.Monitoring/MonitoringService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,42 +50,42 @@ public MonitoringService(IMetricsController metricsController, IMetricsConfig me
_logger = logManager is null
? throw new ArgumentNullException(nameof(logManager))
: logManager.GetClassLogger();
_options = GetOptions();
_options = GetOptions(metricsConfig);
}

public async Task StartAsync()
{
if (!string.IsNullOrWhiteSpace(_pushGatewayUrl))
if (_pushGatewayUrl is not null)
{
MetricPusherOptions pusherOptions = new MetricPusherOptions
MetricPusherOptions pusherOptions = new()
{
Endpoint = _pushGatewayUrl,
Job = _options.Job,
Instance = _options.Instance,
IntervalMilliseconds = _intervalSeconds * 1000,
AdditionalLabels = new[]
{
new Tuple<string, string>("nethermind_group", _options.Group),
},
AdditionalLabels = [new Tuple<string, string>("nethermind_group", _options.Group)],
OnError = ex =>
{
if (ex.InnerException is SocketException)
{
if (_logger.IsError) _logger.Error("Could not reach PushGatewayUrl, Please make sure you have set the correct endpoint in the configurations.", ex);
if (_logger.IsError) _logger.Error($"Cannot reach Pushgateway at {_pushGatewayUrl}", ex);
return;
}
if (_logger.IsTrace) _logger.Error(ex.Message, ex); // keeping it as Error to log the exception details with it.
}
};
MetricPusher metricPusher = new MetricPusher(pusherOptions);
MetricPusher metricPusher = new(pusherOptions);

metricPusher.Start();
}

if (_exposePort is not null)
{
new NethermindKestrelMetricServer(_exposeHost, _exposePort.Value).Start();
}
await Task.Factory.StartNew(() => _metricsController.StartUpdating(), TaskCreationOptions.LongRunning);

await Task.Factory.StartNew(_metricsController.StartUpdating, TaskCreationOptions.LongRunning);

if (_logger.IsInfo) _logger.Info($"Started monitoring for the group: {_options.Group}, instance: {_options.Instance}");
}

Expand All @@ -101,42 +101,21 @@ public Task StopAsync()
return Task.CompletedTask;
}

private Options GetOptions()
=> new Options(GetValueFromVariableOrDefault("JOB", "nethermind"), GetGroup(), GetInstance());

private string GetInstance()
=> _nodeName.Replace("enode://", string.Empty).Split("@").FirstOrDefault();

private string GetGroup()
{
string group = GetValueFromVariableOrDefault("GROUP", "nethermind");
string endpoint = _pushGatewayUrl.Split("/").LastOrDefault();
if (!string.IsNullOrWhiteSpace(endpoint) && endpoint.Contains('-'))
{
group = endpoint.Split("-")[0] ?? group;
}

return group;
}

private static string GetValueFromVariableOrDefault(string variable, string @default)
private Options GetOptions(IMetricsConfig config)
{
string value = Environment.GetEnvironmentVariable($"NETHERMIND_MONITORING_{variable}")?.ToLowerInvariant();
string endpoint = _pushGatewayUrl?.Split("/").Last();
string group = endpoint?.Contains('-', StringComparison.Ordinal) == true
? endpoint.Split("-")[0] : config.MonitoringGroup;
string instance = _nodeName.Replace("enode://", string.Empty).Split("@")[0];

return string.IsNullOrWhiteSpace(value) ? @default : value;
return new(config.MonitoringJob, group, instance);
}

private class Options
private class Options(string job, string group, string instance)
{
public string Job { get; }
public string Instance { get; }
public string Group { get; }
public Options(string job, string @group, string instance)
{
Job = job;
Group = @group;
Instance = instance;
}
public string Job { get; } = job;
public string Instance { get; } = instance;
public string Group { get; } = group;
}
}
}

This file was deleted.

1 change: 0 additions & 1 deletion src/Nethermind/Nethermind.Network/IPResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ private async Task<IPAddress> InitializeExternalIp()
{
IEnumerable<IIPSource> GetIPSources()
{
yield return new EnvironmentVariableIPSource();
yield return new NetworkConfigExternalIPSource(_networkConfig, _logManager);
yield return new WebIPSource("http://ipv4.icanhazip.com", _logManager);
yield return new WebIPSource("http://ipv4bot.whatismyipaddress.com", _logManager);
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public void Metrics_disabled_by_default(string configWildcard)
Test<IMetricsConfig, bool>(configWildcard, c => c.Enabled, false);
Test<IMetricsConfig, string>(configWildcard, c => c.NodeName.ToUpperInvariant(), (cf, p) => cf.Replace("_", " ").Replace(".json", "").ToUpperInvariant().Replace("POACORE", "POA CORE"));
Test<IMetricsConfig, int>(configWildcard, c => c.IntervalSeconds, 5);
Test<IMetricsConfig, string>(configWildcard, c => c.PushGatewayUrl, "");
Test<IMetricsConfig, string>(configWildcard, c => c.PushGatewayUrl, (string)null);
}

[TestCase("^spaceneth ^volta", 50)]
Expand Down
9 changes: 5 additions & 4 deletions src/Nethermind/Nethermind.Runner/JsonRpc/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ public void ConfigureServices(IServiceCollection services)
});
Bootstrap.Instance.RegisterJsonRpcServices(services);

string corsOrigins = Environment.GetEnvironmentVariable("NETHERMIND_CORS_ORIGINS") ?? "*";
services.AddCors(c => c.AddPolicy("Cors",
p => p.AllowAnyMethod().AllowAnyHeader().WithOrigins(corsOrigins)));
services.AddCors(options => options.AddDefaultPolicy(builder => builder
.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins(jsonRpcConfig.CorsOrigins)));

services.AddResponseCompression(options =>
{
Expand All @@ -78,8 +79,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IJsonRpc
app.UseDeveloperExceptionPage();
}

app.UseCors("Cors");
app.UseRouting();
app.UseCors();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UseCors() must come after UseRouting()

app.UseResponseCompression();

IConfigProvider? configProvider = app.ApplicationServices.GetService<IConfigProvider>();
Expand Down
Loading