0
votes

I work on .NET Core 2.2 console application that uses Microsoft.Extensions.Logging and is configured to send logs to Azure Application Insights using Microsoft.ApplicationInsights.Extensibility by:

   services.AddSingleton(x =>
                new TelemetryClient(
                    new TelemetryConfiguration
                    {
                        InstrumentationKey = "xxxx"
                    }));  
...                 
   var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
   loggerFactory.AddApplicationInsights(serviceProvider, logLevel);

It works ok: I can read logs in Application Insights. But the application can be started simultanously in few instances (in different Docker containers). How can I distinguish traces from different instances? I can use source FileName, but I don't know how I should inject it.

I tried to use Scope:

var logger = loggerFactory.CreateLogger<Worker>();                
logger.BeginScope(dto.FileName);
logger.LogInformation($"Start logging.");

It's interesting that my configuration is almost identical as in example: https://github.com/MicrosoftDocs/azure-docs/issues/12673

But in my case I can't see the property "FileName" in Application Insights.

2
for the work id, is it the docker related?Ivan Yang
The application get initial parameters (json) by environmental variable (from azure App Logic). There are the worki id in the parameters (among others). But it can be any other parameter, for example internal ip.Grzesiek Danowski
Try the Cloud role instance property (using analytics: traces | project message , cloud_RoleInstance )Peter Bons
@PeterBons In my case when the application is running on my desktop cloud_RoleInstance contains my desktop name, but when it is running in Azure there is no property with the name.Grzesiek Danowski
How is the container hosted in azure? Is it running on AKS?Peter Bons

2 Answers

1
votes

If you really have no way to distinguish them you can use a custom telemetry initializer like this:

public class CustomInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        telemetry.Context.Cloud.RoleName = Environment.MachineName;
    }
}

and/or you can add a custom property:

public class CustomInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        if(telemetry is ISupportProperties)
        {
            ((ISupportProperties)telemetry).Properties["MyIdentifier"] = Environment.MachineName;
        }
    }
}

In this example I used Environment.MachineName but you can of course use something else if needed. Like this work Id parameter of yours.

the wire it up using:

services.AddSingleton<ITelemetryInitializer, CustomInitializer>();
1
votes

For console project, if you want to use the custom ITelemetryInitializer, you should use this format: .TelemetryInitializers.Add(new CustomInitializer());

Official doc is here.

I test it at my side, and it works. The role name can be set.

Sample code is below:

        static void Main(string[] args)
        {
            TelemetryConfiguration configuration = TelemetryConfiguration.CreateDefault();
            configuration.InstrumentationKey = "xxxxx";
            configuration.TelemetryInitializers.Add(new CustomInitializer());

            var client = new TelemetryClient(configuration);

            ServiceCollection services = new ServiceCollection();
            services.AddSingleton(x => client);
            var provider = services.BuildServiceProvider();

            var loggerFactory = new LoggerFactory();

            loggerFactory.AddApplicationInsights(provider, LogLevel.Information);

            var logger = loggerFactory.CreateLogger<Program>();
            logger.LogInformation("a test message 111...");



            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }

Check the role name in azure portal:

enter image description here