Reputation: 367
I have a Azure Function app in .NET 6, I am using Microsoft.Extension.Logging
for logging and everything is working perfectly.
Now I have a new requirement to support structured logging so I decided to use Serilog, but after configuring Serilog logs are getting logged twice in Application Insights.
This is my startup.cs
configuration for Serilog
public override void Configure(IFunctionsHostBuilder builder)
{
var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
telemetryConfiguration.ConnectionString = Settings.ApplicationInsightsConnectionString;
// Create and initialize the dependency tracking module
var dependencyModule = new DependencyTrackingTelemetryModule();
dependencyModule.Initialize(telemetryConfiguration);
// Create the custom telemetry processor
var telemetryProcessorChainBuilder = telemetryConfiguration.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
var configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
telemetryProcessorChainBuilder.Use(next => new CustomTelemetryProcessor(next, configuration));
// Build the telemetry processor chain
telemetryProcessorChainBuilder.Build();
Log.Logger = new LoggerConfiguration()
.WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Traces)
.CreateLogger();
builder.Services.AddSingleton(telemetryConfiguration);
builder.Services.AddSingleton(typeof(IAppLogger<>), typeof(AppLogger<>));
// rest of the code...
}
If I remove below code from startup.cs
, then it's not logging twice and only Serilog logs are shown, but I can't remove that code as I also need custom telemetry processor.
So basically when I register custom telemetry processor it also activating Microsoft Logger and that's why I'm getting logs twice as per my understating.
// Create and initialize the dependency tracking module
var dependencyModule = new DependencyTrackingTelemetryModule();
dependencyModule.Initialize(telemetryConfiguration);
// Create the custom telemetry processor
var telemetryProcessorChainBuilder = telemetryConfiguration.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
var configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
telemetryProcessorChainBuilder.Use(next => new CustomTelemetryProcessor(next, configuration));
// Build the telemetry processor chain
telemetryProcessorChainBuilder.Build();
How I can register custom telemetry processor with Serilog, without activating Microsoft logger?
Upvotes: 0
Views: 389
Reputation: 11363
Serilog logs are getting logged twice in Application Insights.
Below code worked for me and logged only required logs and there were no duplicates:
Function1.cs:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
namespace FunctionApp16
{
public class Function1
{
private readonly Rith_Logger<Function1> rith_lg;
public Function1(Rith_Logger<Function1> logger)
{
rith_lg = logger;
}
[FunctionName("Function1")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req)
{
rith_lg.LogInformation("Hello Rithwik Bojja !!!");
var rith_obj = new { Weight = 60, Height = 170 };
var rith_e = 24;
rith_lg.LogInformation("Hello the structered log is {@rith_obj} in {rith_e} age", rith_obj, rith_e);
return new OkObjectResult("Hello Rithwik Bojja !!!");
}
}
}
host.json:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"enableLiveMetricsFilters": true,
"samplingSettings": {
"isEnabled": false,
"excludedTypes": "Request"
}
},
"console": {
"isEnabled": true,
"logLevel": {
"default": "Information"
}
}
}
}
Here samplingSettings is set to false.
Startup.cs:
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Serilog;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.DependencyCollector;
using Microsoft.Extensions.Logging;
using Microsoft.ApplicationInsights.Channel;
[assembly: FunctionsStartup(typeof(FunctionApp16.Startup))]
namespace FunctionApp16
{
internal class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var rith_tc = TelemetryConfiguration.CreateDefault();
rith_tc.ConnectionString = "InstrumentationKey=af34a9dc-f1df-4ff8-9ac9-6c1f0401ef4c;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=ff7a6";
var rith_dm = new DependencyTrackingTelemetryModule();
rith_dm.Initialize(rith_tc);
var rit_tpb = rith_tc.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
var rih_conf = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
rit_tpb.Use(next => new CustomTelemetryProcessor(next, rih_conf));
rit_tpb.Build();
Log.Logger = new LoggerConfiguration()
.WriteTo.ApplicationInsights(rith_tc, TelemetryConverter.Traces)
.CreateLogger();
builder.Services.AddSingleton(rith_tc);
builder.Services.AddSingleton(typeof(Rith_Logger<>), typeof(AppLogger<>));
builder.Services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddSerilog(Log.Logger, dispose: true);
});
}
}
public class CustomTelemetryProcessor : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
private readonly IConfiguration rith_conf;
public CustomTelemetryProcessor(ITelemetryProcessor next, IConfiguration configuration)
{
Next = next;
rith_conf = configuration;
}
public void Process(ITelemetry rit)
{
Next.Process(rit);
}
}
public interface Rith_Logger<T>
{
void LogInformation(string rith_ms, object rith_po, int rith);
void LogInformation(string rith_ms);
}
public class AppLogger<T> : Rith_Logger<T>
{
private readonly ILogger<T> rith_lg;
public AppLogger(ILogger<T> logger)
{
rith_lg = logger;
}
public void LogInformation(string rith_ms, object rith_po, int rith)
{
rith_lg.LogInformation(rith_ms, rith_po, rith);
}
public void LogInformation(string rith_ms)
{
rith_lg.LogInformation(rith_ms);
}
}
}
Output:
My pacakages in csproj:
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.22.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.4.0" />
<PackageReference Include="Serilog.Formatting.Compact" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="4.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.2" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
</ItemGroup>
Upvotes: 1