Skip to content

Commit

Permalink
Use OpenTelemetry tooling for diagnostics setup (#712)
Browse files Browse the repository at this point in the history
* Add TelemetryHelpers file

* Add Otel and Az Monitor packages to project

* Use OTel and Az Monitor for telemtry setup in Program

* Remove old usings

* Add appsettings file for Prod

* Remove package that was smuggled in through copy/paste from sms-repo

* Add (and use) TelemetryEnrichingMiddleware

* Replace obsolete X509Cert ctor

* Replace obsolete X509Certificate2 ctor

* Remove no-longer-used telemetry classes

* Remove package that was installed by mistake
  • Loading branch information
hggutvik authored Feb 18, 2025
1 parent 4250e40 commit 263dca4
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 123 deletions.
5 changes: 5 additions & 0 deletions src/Altinn.Notifications/Altinn.Notifications.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<ItemGroup>
<PackageReference Include="Altinn.Common.AccessToken" Version="5.0.0" />
<PackageReference Include="FluentValidation" Version="11.11.0" />

<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.3.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.11.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.11.0" />
<PackageReference Include="JWTCookieAuthentication" Version="4.0.4" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
Expand Down

This file was deleted.

46 changes: 0 additions & 46 deletions src/Altinn.Notifications/Health/HealthTelemetryFilter.cs

This file was deleted.

122 changes: 70 additions & 52 deletions src/Altinn.Notifications/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,23 @@
using Altinn.Notifications.Middleware;
using Altinn.Notifications.Models;
using Altinn.Notifications.Persistence.Extensions;
using Altinn.Notifications.Telemetry;
using Altinn.Notifications.Validators;

using AltinnCore.Authentication.JwtCookie;

using Azure.Identity;
using Azure.Monitor.OpenTelemetry.Exporter;
using Azure.Security.KeyVault.Secrets;

using FluentValidation;

using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;

using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerGen;

Expand All @@ -42,9 +43,12 @@

var builder = WebApplication.CreateBuilder(args);

ConfigureSetupLogging();
ConfigureWebHostCreationLogging();

await SetConfigurationProviders(builder.Configuration);
ConfigureLogging(builder.Logging);

ConfigureApplicationLogging(builder.Logging);

ConfigureServices(builder.Services, builder.Configuration);

builder.Services.AddEndpointsApiExplorer();
Expand All @@ -68,6 +72,8 @@

app.UseAuthorization();

app.UseTelemetryEnricher();

app.MapControllers();

app.MapHealthChecks("/health");
Expand All @@ -76,7 +82,7 @@

app.Run();

void ConfigureSetupLogging()
void ConfigureWebHostCreationLogging()
{
var logFactory = LoggerFactory.Create(builder =>
{
Expand All @@ -88,45 +94,54 @@ void ConfigureSetupLogging()
logger = logFactory.CreateLogger<Program>();
}

void ConfigureLogging(ILoggingBuilder logging)
void ConfigureApplicationLogging(ILoggingBuilder logging)
{
// The default ASP.NET Core project templates call CreateDefaultBuilder, which adds the following logging providers:
// Console, Debug, EventSource
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1

// Clear log providers
logging.ClearProviders();

// Setup up application insight if applicationInsightsKey is available
if (!string.IsNullOrEmpty(applicationInsightsConnectionString))
{
// Add application insights https://docs.microsoft.com/en-us/azure/azure-monitor/app/ilogger
logging.AddApplicationInsights(
configureTelemetryConfiguration: (config) => config.ConnectionString = applicationInsightsConnectionString,
configureApplicationInsightsLoggerOptions: (options) => { });

// Optional: Apply filters to control what logs are sent to Application Insights.
// The following configures LogLevel Information or above to be sent to
// Application Insights for all categories.
logging.AddFilter<Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>(string.Empty, LogLevel.Warning);

// Adding the filter below to ensure logs of all severity from Program.cs
// is sent to ApplicationInsights.
logging.AddFilter<Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>(typeof(Program).FullName, LogLevel.Trace);
}
else
logging.AddOpenTelemetry(builder =>
{
// If not application insight is available log to console
logging.AddFilter("Microsoft", LogLevel.Warning);
logging.AddFilter("System", LogLevel.Warning);
logging.AddConsole();
}
builder.IncludeFormattedMessage = true;
builder.IncludeScopes = true;
});
}

void ConfigureServices(IServiceCollection services, IConfiguration config)
{
logger.LogInformation("Program // ConfigureServices");

var attributes = new List<KeyValuePair<string, object>>(2)
{
KeyValuePair.Create("service.name", (object)"platform-notifications"),
};

services.AddOpenTelemetry()
.ConfigureResource(resourceBuilder => resourceBuilder.AddAttributes(attributes))
.WithMetrics(metrics =>
{
metrics.AddAspNetCoreInstrumentation();
metrics.AddMeter(
"Microsoft.AspNetCore.Hosting",
"Microsoft.AspNetCore.Server.Kestrel",
"System.Net.Http");
})
.WithTracing(tracing =>
{
if (builder.Environment.IsDevelopment())
{
tracing.SetSampler(new AlwaysOnSampler());
}

tracing.AddAspNetCoreInstrumentation(configOptions =>
{
configOptions.Filter = (httpContext) => !TelemetryHelpers.ShouldExclude(httpContext.Request.Path);
});

tracing.AddHttpClientInstrumentation();
});

if (!string.IsNullOrEmpty(applicationInsightsConnectionString))
{
AddAzureMonitorTelemetryExporters(services, applicationInsightsConnectionString);
}

services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.WriteIndented = true;
Expand All @@ -139,19 +154,6 @@ void ConfigureServices(IServiceCollection services, IConfiguration config)
services.AddHealthChecks().AddCheck<HealthCheck>("notifications_health_check");

services.AddSingleton(config);
if (!string.IsNullOrEmpty(applicationInsightsConnectionString))
{
services.AddSingleton(typeof(ITelemetryChannel), new ServerTelemetryChannel() { StorageFolder = "/tmp/logtelemetry" });

services.AddApplicationInsightsTelemetry(new ApplicationInsightsServiceOptions
{
ConnectionString = applicationInsightsConnectionString
});

services.AddApplicationInsightsTelemetryProcessor<HealthTelemetryFilter>();
services.AddSingleton<ITelemetryInitializer, CustomTelemetryInitializer>();
logger.LogInformation("// Program // Connected to Application Insights");
}

GeneralSettings generalSettings = config.GetSection("GeneralSettings").Get<GeneralSettings>();
services.Configure<GeneralSettings>(config.GetSection("GeneralSettings"));
Expand Down Expand Up @@ -187,6 +189,22 @@ void ConfigureServices(IServiceCollection services, IConfiguration config)
services.AddPostgresRepositories(config);
}

void AddAzureMonitorTelemetryExporters(IServiceCollection services, string applicationInsightsConnectionString)
{
services.Configure<OpenTelemetryLoggerOptions>(logging => logging.AddAzureMonitorLogExporter(o =>
{
o.ConnectionString = applicationInsightsConnectionString;
}));
services.ConfigureOpenTelemetryMeterProvider(metrics => metrics.AddAzureMonitorMetricExporter(o =>
{
o.ConnectionString = applicationInsightsConnectionString;
}));
services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddAzureMonitorTraceExporter(o =>
{
o.ConnectionString = applicationInsightsConnectionString;
}));
}

void AddAuthorizationRulesAndHandlers(IServiceCollection services, IConfiguration config)
{
services.AddAuthorizationBuilder()
Expand Down
Loading

0 comments on commit 263dca4

Please sign in to comment.