dotnet-cqrs/docs/observability/logging/README.md

2.2 KiB

Structured Logging

High-performance structured logging with correlation IDs.

Overview

Svrnty.CQRS provides comprehensive structured logging:

  • LoggerMessage Source Generators - Zero-allocation logging
  • Correlation IDs - Distributed tracing
  • Event ID Ranges - Categorized log events
  • Structured Data - Queryable log parameters

Quick Start

using Svrnty.CQRS.Events.Logging;
using Serilog;

// Configure Serilog
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.Seq("http://localhost:5341")
    .CreateLogger();

builder.Host.UseSerilog();

// Use correlation context
using (CorrelationContext.Begin(correlationId))
{
    _logger.LogEventPublished(eventId, eventType, streamName, CorrelationContext.Current);
    await ProcessEventAsync(@event);
    _logger.LogEventConsumed(eventId, eventType, subscriptionId, consumerId, elapsed);
}

Log Event ID Ranges

// 1000-1999: Stream lifecycle
EventIds.StreamCreated = 1001
EventIds.StreamDeleted = 1002

// 2000-2999: Subscription lifecycle
EventIds.SubscriptionRegistered = 2001
EventIds.SubscriptionCancelled = 2002

// 3000-3999: Consumer lifecycle
EventIds.ConsumerConnected = 3001
EventIds.ConsumerLagging = 3004
EventIds.ConsumerStalled = 3005

// 4000-4999: Event publishing
EventIds.EventPublished = 4001
EventIds.EventPublishFailed = 4002

// 5000-5999: Event consumption
EventIds.EventConsumed = 5001
EventIds.EventRetry = 5002
EventIds.EventDeadLettered = 5003

Correlation IDs

public class CorrelationContext
{
    private static readonly AsyncLocal<string?> _correlationId = new();

    public static string? Current => _correlationId.Value;

    public static IDisposable Begin(string correlationId)
    {
        _correlationId.Value = correlationId;
        return new CorrelationScope();
    }

    private class CorrelationScope : IDisposable
    {
        public void Dispose() => _correlationId.Value = null;
    }
}

See Also