Следуя последним советам из этой статьи, мы видим промежутки/трассировки для запускаемых действий.
https://nblumhardt.com/2024/04/serilog-net8-0-minimal/
Однако временная шкала в представлении операций App Insights и то, где эти трассировки попадают во время существования HTTP-запроса .NET, не совпадают. При фильтрации компонента действия SerilogTracing не отображаются. Но без фильтрации следы операции существуют.
Просмотр временной шкалы в App Insights
Пример несвязанной трассировки (дочернее действие)
Действие контроллера, трассировка существует в фильтре компонентов (действие контроллера)
Изображение текущего поведения в надежде выровнять иерархию одного действия, являющегося дочерним для запуска вызывающего метода активность. (См. рисунки)
Пример запуска активности в контроллере:
private readonly Serilog.ILogger _logger;
private readonly Service _service;
//Controller Constructor
public RateController(Serilog.ILogger seriLogger, IService service
/*, dependencies...*/
) {
//... assignment of dependencies to private fields
_logger = seriLogger.ForContext();
_service = service ? ?
throw new ArgumentNullException(nameof(service), service);
//...
}
[HttpPost]
public async Task Submit(Message request) {
using LoggerActivity activity = _logger.StartActivity("Rating {@number} from message {@MessageID}", [request.Number ? ?string.Empty, request.MessageID ? ?string.Empty]);
_service.MethodCallThatAlsoCallsStartActivity();...
}
//... Other controller actions
Пример метода, вызываемого контроллером:
private readonly Serilog.ILogger _logger;
public Service(Serilog.ILogger logger
/*dependencies... */
) {
_logger = logger.ForContext();
}
public async Task MethodCallThatAlsoCallsStartActivity() {
using LoggerActivity activity = _logger.StartActivity("New Activity");
...
}
Это фрагмент кода того, как мы регистрируем Serilog и SerilogTracing.
appsettings.json:
{ //appsettings.json
"Serilog": {
"Using": [
"Serilog.Exceptions",
"Serilog.Sinks.Console"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Microsoft.AspNetCore": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"formatter": "Serilog.Formatting.Compact.RenderedCompactJsonFormatter, Serilog.Formatting.Compact",
"outputTemplate": "{Timestamp:o} [{Level:u3}] {SourceContext} ({Application}/{EnvironmentName}/{EnvironmentUserName}/{RequestId}) {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [
"FromLogContext",
"FromGlobalLogContext",
"WithSpan",
"WithDefaultDestructurers",
"WithEnvironmentName",
"WithEnvironmentUserName",
"WithExceptionDetails",
"WithMemoryUsage",
"WithDemystifiedStackTraces",
"WithClientIp",
"WithSpanTiming"
],
"Properties": {
"Application": "Orchestrator Service"
}
},
"AzureMonitor": {
"EnableLiveMetrics": true,
"ConnectionString": "This field was removed but contains a valid Connection String"
}
}
//Program.cs of one microservice
// reused and parameterized across other microservices in dependencies
//... bootstrap logging
WebApplicationBuilder builder = WebApplication.CreateBuilder(new WebApplicationOptions() { Args = args });
//APPLICATIONINSIGHTS_CONNECTION_STRING env var pref way to configure Application Insights
builder.Logging.ClearProviders();
builder.Services.AddSerilog((services, lc) => lc
.ReadFrom.Configuration(builder.Configuration)
.ReadFrom.Services(services), writeToProviders: true);
//... service provider registrations
builder.Logging
.AddOpenTelemetry(loggerOptions =>
{
loggerOptions.IncludeFormattedMessage = true;
loggerOptions.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.UseAzureMonitor();
builder.Services.Configure(options =>
{
options.Filter = (httpContext) =>
{
return !httpContext.Request.Path.Value.Contains("health") &&
!httpContext.Request.Path.Value.Contains("dapr");
};
});
using IDisposable actList = new ActivityListenerConfiguration()
.Instrument.WithDefaultInstrumentation(true)
.Instrument.HttpClientRequests()
.TraceToSharedLogger();
// ... middleware registrations in order of :
// ... exception handler, log context pushes,
app.UseRouting();
app.UseSerilogRequestLogging();
app.UseCloudEvents();
app.MapControllers();
try
{
app.Run();
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Log.Fatal(ex, "{Application} terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
try { actList.Dispose(); } catch { /* ignored */ }
}
Это ответ от LLM, однако он ссылался на старый App Instights SDK, так что это будет моя следующая попытка.
Некоторые LLM дали такую рекомендацию.
Используйте OpenTelemetry для трассировки, Serilog для регистрации.
- Удалите создание интервалов из Serilog
Сохранить:
Serilog.Enrichers.Span (for correlation IDs in logs)
Избегайте:
SerilogTracing.Instrumentation.AspNetCore
TraceToSharedLogger()
WithSpan() //for anything you expect to be a real span - Явное создание интервалов через ActivitySource
Пример шаблона:
new("Pricing.Orchestrator");
using var activity = ActivitySource.StartActivity(
"ResolveRatingDefinition",
ActivityKind.Internal);
- Зарегистрируйте этот источник с помощью OpenTelemetry
.WithTracing(tracing =>
{
tracing
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddSource("Pricing.Orchestrator")
.UseAzureMonitor();
});
Подробнее здесь: https://stackoverflow.com/questions/798 ... ched-spans
Мобильная версия