Ahmed
Ahmed

Reputation: 11

Azure Function Integration of Serilog with Application Insights, logs visible in Search but are not appearing in Failures events timeline

I am trying to use Serilog with Application Insights sink for logging purposes. I can see the logs in Search bar in Azure Portal (Application Insights) but same logs are not visible if we view the timeline of events in Failures or Performance Tab. Thanks

Below is the code am using for registering Logger in FunctionStartup, which then gets injected in Function for logging:

var logger = new LoggerConfiguration()
                               .Enrich.FromLogContext()
                               .Enrich.WithProperty("ApplicationName", "testApp")
                               .Enrich.WithProperty("Environment", "Dev")                               
                               .WriteTo.ApplicationInsights(GetTelemetryClient("Instrumentationkey"), TelemetryConverter.Traces)
                               .CreateLogger();
builder.Services.AddSingleton<ILogger>(logger);

Telementory Client is getting fetched from a helper method:

public static TelemetryClient GetTelemetryClient(string key)
        {
            var teleConfig = new TelemetryConfiguration { InstrumentationKey = key };

            var teleClient = new TelemetryClient(teleConfig);

            return teleClient;
        }

host.json

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingExcludedTypes": "Request",
            "samplingSettings": {
                "isEnabled": true
            }
        }
    }
}

Upvotes: 0

Views: 2153

Answers (3)

Ahmed
Ahmed

Reputation: 11

In order to use logging using Telemetry Configuration as mentioned in the answer above for Azure Functions, we just need to update the function as in below snippet and on deployment it should fetch Instrumentation key itself

public static TelemetryClient GetTelemetryClient()
 {
   var teleConfig = TelemetryConfiguration.CreateDefault();
    
   var teleClient = new TelemetryClient(teleConfig);
    
   return teleClient;
 }

But to run both locally and after deployment on Azure. We need to add something like this in function Startup and get rid of the Function above.

builder.Services.Configure<TelemetryConfiguration>((o) =>
                {
                   o.InstrumentationKey = "KEY";
                   o.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
                });
        
builder.Services.AddSingleton<ILogger>(sp =>
                {
                var logger = new LoggerConfiguration()
                 .Enrich.FromLogContext()
                 .Enrich.WithProperty("ApplicationName", "TEST")
                 .Enrich.WithProperty("Environment", "DEV")
                 .WriteTo.ApplicationInsights( 
        
                 sp.GetRequiredService<TelemetryConfiguration>(), TelemetryConverter.Traces).CreateLogger(); 
        
                 return logger;
               });

After wards we just need to use typical DI in our classes/azure function to use ILogger

public class Test{
      public ILogger _log;
      public void Test(ILogger log){
        _log=log;
      }
   }

Upvotes: 1

Shabir jan
Shabir jan

Reputation: 2427

You can easily solve this by following the solution provided by Azure Application Insights on their GitHub repo, as per this Github Issue, you can either use the DI to configure TelemetryConfiguration, i.e

services.Configure<TelemetryConfiguration>(
 (o) => {
   o.InstrumentationKey = "123";
   o.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
 });

or you can configure it manually like this:

var config = TelemetryConfiguration.CreateDefault();
var client = new TelemetryClient(config);

So in your code, you have to change your GetTelemetryClient from

public static TelemetryClient GetTelemetryClient(string key)
    {
        var teleConfig = new TelemetryConfiguration { InstrumentationKey = key };

        var teleClient = new TelemetryClient(teleConfig);

        return teleClient;
    }

to this

public static TelemetryClient GetTelemetryClient(string key)
    {
        var teleConfig = TelemetryConfiguration.CreateDefault();

        var teleClient = new TelemetryClient(teleConfig);

        return teleClient;
    }

Upvotes: 0

Tiny Wang
Tiny Wang

Reputation: 16086

I got your mean, and pls allow me to sum up my testing result here.

First, the failure blade is not designed for providing a timeline which used to trace the details(what happened before the exception take place), but to show all the exceptions, how often the error happened, how many users be affected, etc, it's more likely stand in a high place to see the whole program.

And to achieve your goal, I think you can use this kql query in the Logs blade or watching it in transaction blade.

union traces, requests,exceptions
| where operation_Id == "178845c426975d4eb96ba5f7b5f376e1"

enter image description here Basically, we may add many logs in the executing chain, e.g. in the controller, log the input parameter, then log the result of data combining or formatting, log the exception information in catch, so here's my testing code. I can't see any other information in failure blade as you, but in the transaction blade, I can see the timeline.

public class HelloController : Controller
    {
        public string greet(string name)
        {
            Log.Verbose("come to greet function");
            Log.Debug("serilog_debug_info");
            Log.Information("greet name input " + name);
            int count = int.Parse(name);
            Log.Warning("enter greet name is : {0}", count);
            return "hello " + name;
        }
    }

enter image description here

And we can easily find that, the whole chain shares the same operationId, and via all these logs, we can pinpoint the wrong line code. By the way, if I surround the code with try/catch, exception won't be captured in the failure blade.

==================================

Using Serilog integrate app insights, we need to send serilog to application insights, and we will see lots of Traces in transaction search, so it's better to made the MinimumLevel to be information and higher. The sreenshot below is my log details, and we can also use kql query by operationId to see the whole chain.

enter image description here

Upvotes: 1

Related Questions