Telemetry
Overview
Provide logging, tracing and metrics for ASP.NET Core.
For application-defined classifications on individual log entries, see Logging. The ASOL.Core.Logging package uses the host's existing logging providers and configuration.
Install
- ASOL.Core.Telemetry.Client.AspNetCore - Logs, tracing and metrics initialization and OTLP export configuration.
- ASOL.Core.Telemetry.Client.Logger - ILogger initialization and configuration.
Usage of third party libraries (NuGets)
- OpenTelemetry.Extensions.Hosting
- OpenTelemetry
- OpenTelemetry.Instrumentation.AspNetCore
- OpenTelemetry.Instrumentation.EntityFrameworkCore
- OpenTelemetry.Instrumentation.Http
- OpenTelemetry.Instrumentation.Runtime
- OpenTelemetry.Exporter.Console
- OpenTelemetry.Exporter.OpenTelemetryProtocol
- Serilog.AspNetCore
- Serilog.Enrichers.Environment
- Serilog.Expressions
- Serilog.Enrichers.Process
- Serilog.Enrichers.Span
- Serilog.Exceptions
- Serilog.Sinks.File
- Elastic.CommonSchema.Serilog
Changelog
- 0.0.1.52330-dev
- fixed incorrect Tenant ID logging
- 0.0.1.48598-dev
- fix application code mapping
- 0.0.1.48471-dev
- Fix filtering unnecessary tracing data while reverse proxy is used
- 0.0.1.45792-dev
- Support for Application Insights has been removed; OpenTelemetry is now used instead. For proper functioning, the minimum required versions are:
ASOL.Core.Messaging*-0.0.1.45790-devASOL.Core.Persistence*-0.0.1.45789-devASOL.Core.Processing-0.0.1.45802-dev
AddTelemetrymethod requiresIConfigurationparameter.
- Support for Application Insights has been removed; OpenTelemetry is now used instead. For proper functioning, the minimum required versions are:
Logger
Call ClearProviders() before AddTelemetry() and AddTelemetryLogger() to remove
the default logging providers and avoid duplicate console output. Calling it after
AddTelemetry() removes the OpenTelemetry logging provider and prevents OTLP log
export.
using ASOL.Core.Telemetry.Client.AspNetCore;
using ASOL.Core.Telemetry.Client.Logger;
using Microsoft.Extensions.Logging;
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.ClearProviders())
.ConfigureServices((context, services) => services.AddTelemetry(context.Configuration))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.AddTelemetryLogger();
or
using ASOL.Core.Telemetry.Client.AspNetCore;
using ASOL.Core.Telemetry.Client.Logger;
using Microsoft.Extensions.Logging;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Services.AddTelemetry(builder.Configuration);
builder.Host.AddTelemetryLogger();
Logs, traces and metrics
using ASOL.Core.Telemetry.Client.AspNetCore;
public class Startup(IConfiguration configuration)
{
public virtual void ConfigureServices(IServiceCollection services)
{
// ..
services.AddTelemetry(Configuration);
// ..
}
}
Configuration
Set Telemetry:ServiceName in appsettings.json.
OTLP export
Select the transport explicitly with Telemetry:OtlpProtocol: Grpc (the default, preserving existing behavior) or HttpProtobuf.
OtlpEndpoint is the shared base endpoint. If a per-signal endpoint is unset, gRPC uses this URL as-is. HTTP/protobuf appends /v1/logs, /v1/traces, or /v1/metrics to the base URL, preserving any configured base path.
A per-signal endpoint overrides the shared endpoint and is used exactly as configured. For HTTP/protobuf, include the complete signal path:
{
"Telemetry": {
"ServiceName": "ASOL.MyOwnProject",
"OtlpProtocol": "HttpProtobuf",
"OtlpEndpoint": "http://collector:4318/otel/",
"EnableOtlpLogging": true,
"OtlpLogsEndpoint": "http://collector:4318/custom/logs",
"OtlpTracesEndpoint": "http://collector:4318/custom/traces",
"OtlpMetricsEndpoint": "http://collector:4318/custom/metrics"
}
}
With the example above, any unset signal endpoint resolves under http://collector:4318/otel/v1/. Traces and metrics are not exported when neither the per-signal endpoint nor the shared endpoint is configured.
AddTelemetry(configuration) configures OTLP export for all three signals and
registers the OpenTelemetry logging provider for Microsoft.Extensions.Logging.ILogger.
When using Serilog, also call AddTelemetryLogger() to configure enrichment and
file/console sinks and forward log events to the registered logging providers.
EnableOtlpLogging defaults to false, preserving the existing Filebeat workflow.
Set it to true to export logs through the OpenTelemetry logging provider using
the OTLP exporter. It requires either OtlpLogsEndpoint or OtlpEndpoint;
enabling it without either throws an InvalidOperationException during
AddTelemetry(configuration) registration.
The logs exporter uses the same endpoint resolution and protocol configuration
as traces and metrics. Existing Serilog file and console sinks remain active;
disable Filebeat ingestion for the same logs if duplicate delivery is unwanted.
AddTelemetryLogger() forwards events to all registered logging providers. Call
ClearProviders() first, as shown above, so the default Microsoft console provider
does not duplicate Serilog console output. Register any additional providers after
clearing the defaults.
Logs share the resource configuration used by traces and metrics, including the
service name, instance ID, build version (when configured), application code, and
deployment.environment. The environment is read from ASPNETCORE_ENVIRONMENT,
with unknown as the fallback. Formatted messages and logging scopes are included.
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"ASOL.Core": "Warning",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning",
"Microsoft.AspNetCore.Hosting": "Warning",
"Microsoft.AspNetCore.Mvc.Internal": "Warning",
"Microsoft.AspNetCore.Authentication": "Warning"
}
},
"Telemetry": {
"ServiceName": "ASOL.MyOwnProject"
}
}
ProblemDetails setup
public class ProblemDetailsOptionsCustomSetup(
IWebHostEnvironment environment,
IHttpContextAccessor httpContextAccessor,
IOptions<ApiBehaviorOptions> apiOptions)
: ProblemDetailsOptionsDefaultSetup(environment, httpContextAccessor, apiOptions)
{
public override void Configure(Hellang.Middleware.ProblemDetails.ProblemDetailsOptions options)
{
...
options.Map<ValidationException>(ex =>
{
Activity.Current?.AddException(ex);
...
});
options.Map<ProcessingCoreException>(ex =>
{
Activity.Current?.AddException(ex);
...
});
}
}
Example of custom trace and metrics
public sealed class InstrumentationSource : IDisposable
{
internal const string ActivitySourceName = "MyOwnProject";
internal const string MeterName = "MyOwnProject";
private readonly Meter meter;
public InstrumentationSource()
{
ActivitySource = new ActivitySource(ActivitySourceName);
meter = new Meter(MeterName);
HighPriceCounter = meter.CreateCounter<long>("myownproject.highprice", description: "The number item with high price");
}
public ActivitySource ActivitySource { get; }
public Counter<long> HighPriceCounter { get; }
public void Dispose()
{
ActivitySource.Dispose();
meter.Dispose();
}
}
Register sources in Startup.cs:
using ASOL.Core.Telemetry.Client.AspNetCore;
public class Startup(IConfiguration configuration)
{
public virtual void ConfigureServices(IServiceCollection services)
{
// ..
services.AddSingleton<InstrumentationSource>();
services.AddTelemetry(configuration, builder => builder
.AddTracingSource(InstrumentationSource.ActivitySourceName)
.AddMeterSource(InstrumentationSource.MeterName)
);
// ..
}
}
Usage:
using var activity = instrumentationSource.ActivitySource.StartActivity("process item");
if (command.Price > 1)
{
instrumentationSource.HighPriceCounter.Add(1);
}
DevOps Monitoring
You can view your application logs in the monitoring section.
Authorization
- The user must be assigned the ASOLEU-Product-AP-.Developer role
- For a concrete application and non-production stages the user must be assigned the
{applicationCode}.Userrole or the{applicationCode}.Ownerrole - For a concrete application and production stages the user must be assigned the
{applicationCode}.Ownerrole