0

We've got an Azure service bus resource that is being logged to by a .net core 5.0 worker service. We have an Azure application insights resource that is configured in the appsettings.json using the following key:

"ApplicationInsights": { "InstrumentationKey": "guid" },

During development, this works well and we can see the service bus dependency and message logs in the application insights.

When this app is deployed by Azure Devops, the application insights key value is saved to an environment variable (app is deployed to AKS). This value is then supposed to be read on startup by the application. However, what we see is that the service when deployed to AKS logs to the development application insights, not the production app insights. We think this is because the service bus is somehow creating it's own logger and reading from the locally deployed appsettings.json file rather than reading from the environment values.

I've had a look at this page, but can't get it to work: https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-end-to-end-tracing?tabs=net-standard-sdk-2

The question is, how can we configure the service bus client to use the correct logger and log to the right application insights resource?

Our sb startup code looks something like this:

        protected void Start(Func<Message, CancellationToken, Task> handler, string name, string connectionString)
        {

            QueueClient = new QueueClient(connectionString, name, ReceiveMode.ReceiveAndDelete);

            var messageHandlerOptions = new MessageHandlerOptions(e => {
                ProcessError(e.Exception);
                return Task.CompletedTask;
            })
            {
                MaxConcurrentCalls = Config.ServiceBus.ConcurrentThreads,
                AutoComplete = false
            };
            QueueClient.RegisterMessageHandler(handler, messageHandlerOptions);

        }

Update

In our application startup, we are doing something like the following:

        public static int Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(Configuration)
                .Enrich.FromLogContext()
                .WriteTo.Debug()
                .WriteTo.Console(
                    outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}")
                .CreateLogger();

            try
            {
                var host = CreateHostBuilder(args).Build();
                host.Services.UseScheduler(scheduler => {
                    scheduler
                        .Schedule<FxRatesInvocableService>()
                        .DailyAtHour(01);
                    
                });
                host.Run();

                return 0;
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Host terminated unexpectedly");
                return 1;
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            var host = Host.CreateDefaultBuilder(args);

            host.ConfigureLogging(
                loggingBuilder =>
                {
                    loggingBuilder.ClearProviders();
                    Serilog.Debugging.SelfLog.Enable(Console.Error); 
                    
                    var result = ConfigureLogger();                    
                    
                    loggingBuilder.AddApplicationInsights(result.Config.ApplicationInsightsKey);

                    var logger = new LoggerConfiguration()
                        .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                        .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Error)
                        .MinimumLevel.Override("System.Net.Http.HttpClient", LogEventLevel.Warning)
                        .WriteTo.ColoredConsole(
                            outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} {Level} {Properties} {Message}{NewLine}{Exception}",
                            restrictedToMinimumLevel: LogEventLevel.Information
                        ) // one of the logger pipeline elements for writing out the log message
                        .WriteTo.File(Path.Combine(Directory.GetCurrentDirectory(), "logs", "logs.txt")
                            , outputTemplate: "{Timestamp:HH:mm:ss} [{EventType:x8} {Level:u3}] {Message:lj}{NewLine}{Exception}"
                            , rollingInterval: RollingInterval.Day
                            , flushToDiskInterval: TimeSpan.FromMinutes(1)
                            , fileSizeLimitBytes: 1_000_000
                            , rollOnFileSizeLimit: true
                            , shared: true)
                        .Enrich.FromLogContext() 

                        .Enrich.WithDemystifiedStackTraces()                       .ReadFrom.Configuration(Configuration.GetSection("Serilog"))
                        .CreateLogger();

                    loggingBuilder.AddSerilog(logger, dispose: true);
                }
            );


            host.ConfigureServices((hostContext, services) =>
            {
...

where the result object above is a configuration object that is created by looking at where the code is running and settings properties appropriately.

It looks to me that there is some code in the Microsoft.Azure.ServiceBus nuget package that is defaulting the ILogger to be one that assumes the read configuration from the appsettings.json file. Just a hunch. But is that the case? Any way we can override this behaviour?

3
  • Could you confirm that as per this doc your expectations are aligning with this statement: An instrumentation key specified in code wins over the environment variable APPINSIGHTS_INSTRUMENTATIONKEY, which wins over other options.? Commented Sep 26, 2021 at 15:05
  • thanks Tom. instrumentation key is not specified in code. It is only either in the appsettings.json file and the environment settings as ApplicationInsights__ InstrumentationKey. Commented Sep 26, 2021 at 16:06
  • if the environment variable is exactly as you've written it there, that may be the source of your problem. It looks like you're mixing syntax between APPINSIGHTS_INSTRUMENTATIONKEY and ApplicationInsights:InstrumentationKey Commented Sep 27, 2021 at 9:13

1 Answer 1

1

We added:

                config.AddEnvironmentVariables();

to the Program startup. This appears to have resolved the issue

i.e.

            host.ConfigureAppConfiguration(
                (hostContext, config) =>
                {
                    config.SetBasePath(Directory.GetCurrentDirectory());
                    config.AddJsonFile("appsettings.json", false, true);
                    config.AddEnvironmentVariables();
                    config.AddCommandLine(args);
                }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.