How to set APM Configuration outside appsettings?

My application is running in test environment. I see that it throws apm logs, but it does not work in production environment. I think the reason is from the configuration in appsettings.json by default, briefly as follows:

var environmentName = Environment.GetEnvironmentVariable('ASPNETCORE_ENVIRONMENT');
                        var builder = new ConfigurationBuilder()
                        .SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
                        .AddJsonFile('appsettings.json', false)
                        .AddJsonFile($'appsettings.{environmentName}.json', true)
                        .AddEnvironmentVariables();

UseElasticApm(new HttpDiagnosticsSubscriber());

I have 2 different configuration files according to the environment information in which the configuration is active. However, APM seems to be searching for the appsettings.json file by default.

When I check the logs, I see errors like the following.

Elastic.Apm[0] {CentralConfigFetcher} Exception was thrown while fetching configuration from APM Server and parsing it. ETag: <null>'. URL: http://localhost:8200/config/v1/agents?

Elastic.Apm[0] {PayloadSenderV2} Failed sending events. Following events were not transferred successfully to the server (http://localhost:8200/):

By the way, the application is a console application.

Hi @KARAOGLU

This log only means that the agent wasn't able to fetch configs from APM server - maybe central config is just disabled:

Elastic.Apm[0] {CentralConfigFetcher} Exception was thrown while fetching configuration from APM Server and parsing it. ETag: <null>'. URL:

So that's fine.

This second one (below) is a real problem and it means the agent wasn't able to send the data to the APM Server - further parts of the log should have more info:

Elastic.Apm[0] {PayloadSenderV2} Failed sending events. Following events were not transferred successfully to the server (http://localhost:8200/):

Now to the appsettings.json and IConfiguration part: I assume you use the Elastic.Apm.Extensions.Hosting package, right?

In that case the agent will just use the IConfiguration that you configure on the IServiceProvider - you have this var builder = new ConfigurationBuilder(), but then nothing happens with the builder you create - is that the full code?

You should have something like this:

private static IHostBuilder CreateHostBuilder(string[] args) =>
	Host.CreateDefaultBuilder(args)
		.ConfigureServices((context, services) => { services.AddHostedService<HostedService>();
		.ConfigureAppConfiguration((hostContext, configurationBuilder) =>
		{
			var environmentName =Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
			 configurationBuilder.SetBasePath(Directory.GetParent(AppContext.BaseDirectory).Ful
				.AddJsonFile("appsettings.json", false)
				.AddJsonFile($"appsettings.{environmentName}.json", true)
				.AddEnvironmentVariables();
		})
		.UseElasticApm(new HttpDiagnosticsSubscriber());

With this the APM agent will pick up the configurationBuilder you configure here and it'll read from that as any other library does.

Hi @GregKalapos Thank you for your quick reply.

Here is the working part of the application

using Elastic.Apm.DiagnosticSource;
using Elastic.Apm.Extensions.Hosting;

public static IHostBuilder CreateHostBuilder(string[] args) =>

                Host.CreateDefaultBuilder(args)
                .UseSystemd()
                .ConfigureServices((hostContext, services) =>
                {
                    var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                    var builder = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
                    .AddJsonFile("appsettings.json", true)
                    .AddJsonFile($"appsettings.{environmentName}.json", true)
                    .AddEnvironmentVariables();

                    configuration = builder.Build();

                    hostContext.Configuration = configuration;

                    ConsoleHelper.WriteWarningCommandLine($"✓ EnvironmentName bilgisi:{ environmentName}");

                    services.Configure<RabbitMQSettings>(hostContext.Configuration.GetSection(nameof(RabbitMQSettings)));
                    services.Configure<SentimentServiceConfig>(hostContext.Configuration.GetSection(nameof(SentimentServiceConfig)));
                    services.Configure<TurkcellSentimentServiceConfig>(hostContext.Configuration.GetSection(nameof(TurkcellSentimentServiceConfig)));

                    var solrSettings = configuration.GetSection("SolrSettings").Get<SolrSettings>();
                    var serilogSettings = configuration.GetSection("SerilogSettings").Get<SerilogSettings>();

                    services.AddSniffactorRepository();
                    services.AddSniffactorBolts();
                    services.AddLogging(loggingBuilder => loggingBuilder.Services.AddSniffactorSerilog(serilogSettings));
                    services.AddSniffactorNhibernate(hostContext.Configuration.GetConnectionString("OracleConnection"));
                    services.AddSniffactorServiceConnector();

                    services.AddSniffactorSolr(solrSettings);
                    services.AddBusConfiguration();
                    services.AddSingleton(x => hostContext.Configuration);
                    services.AddMemoryCache();
                    services.AddOptions();

                    services.AddMassTransitHostedService();

                    services.AddSingleton<ITracer, Tracer>();

                }).UseElasticApm(new HttpDiagnosticsSubscriber());

Now the error has changed, it says that it sent successfully, but it is trying to send metrics to APM running in the test environment.

Elastic.Apm[0] {PayloadSenderV2} Failed sending events. Following events were not transferred successfully to the server (http://xxx.xx.x.xx:8200/)

So my application is now trying to send it to a real ip and not localhost: 8200, so I see that the config file is working, but it configures according to the information in the fixed appsettings.json file, not the environment information.

Ok, I see. The code itself looks ok to me, the agent should pick up the ConfigurationBuilder you configure in ConfigureServices.

You say

but it configures according to the information in the fixed appsettings.json file, not the environment information.

What's exactly the goal here? Where do you want to read the values from? You configure the 2 .json files, plus the environment variable. Where do you expect the value coming from? And could you show me the content of those files or show me the environment variable? One thing to keep in mind here (and I admit this can be confusing) is that if you set environment variables in this case, then you'll need to follow the IConfiguration format - so e.g. for configuring the server url, you need to set the environment variable ElasticApm:ServerUrl in this case (and not ELASTIC_APM_SERVER_URL).

Another small nit: you have this at the end of the code snippet: services.AddSingleton<ITracer, Tracer>(); - if that's the Elastic.Apm.ITracerer then you can remove it, the .UseElasticApm adds it for you.

@GregKalapos

In short, this is what I want. Environment-based configuration instead of dealing with settings file

appsettings.json:

  "ElasticApm": {
    "ServerUrl": "http://xxx.xx.x.xx:8200",
    "ServiceName": "SnifferService",
    "CloudProvider": "none",
    "Environment": "test"
  },

appsettings.Production.json:

 "ElasticApm": {
    "ServerUrls": "http://yyy.yy.yy.yy:8200",
    "ServiceName": "SnifferService",
    "CloudProvider": "none",
    "Environment": "Production"
  }

I am installing my application in the production environment. The environment information is writing to the screen as "Production". All other external applications (Solr, MassTransit etc.) configure according to the information in appsettings.Production.json, but APM tries to go to the address in appsettings.json.

In the production environment, when I look at the APM logs, I see this.

Elastic.Apm[0] {PayloadSenderV2} Failed sending events. Following events were not transferred successfully to the server (http://xxx.xx.x.xx:8200/):

Hi @GregKalapos I solved it :slight_smile:

Looking carefully, I saw that the "ServerUrls" parameter is incorrect, my fault :pensive:

Great, happy to hear that!

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.