Genocs.Logging Agent Reference

This document is optimized for AI-assisted development sessions.

Genocs.Logging Agent Reference

Purpose

This document is optimized for AI-assisted development sessions. It prioritizes fast retrieval of:

  • What Genocs.Logging is responsible for
  • Which APIs to call for specific logging goals
  • Where source of truth lives for sinks, options, and decorators
  • What constraints and runtime behaviors matter

Quick Facts

KeyValue
PackageGenocs.Logging
Project filesrc/Genocs.Logging/Genocs.Logging.csproj
Target frameworksnet10.0, net9.0, net8.0
Primary roleSerilog-based structured logging with multi-sink support, correlation context enrichment, dynamic log level control, and CQRS handler logging decorators
Core themesSerilog pipeline setup, sink configuration (Console, File, ELK, Seq, Loki, Azure App Insights, OTLP), log level switching at runtime, HTTP request/response body capture, CQRS decorator logging

Use This Package When

  • Bootstrapping Serilog in an ASP.NET Core or Worker host
  • Routing structured logs to Elasticsearch, Seq, Grafana/Loki, or Azure Application Insights simultaneously
  • Enriching logs with OpenTelemetry span IDs, machine name, process/thread IDs, and custom tags
  • Injecting request/response body content into log scopes for debugging HTTP traffic
  • Wrapping command or event handlers with automatic before/after/on-error log entries
  • Exposing a dynamic log-level change HTTP endpoint without restarting the service

Do Not Assume

  • UseLogging() must be called on IHostBuilder — calling it on WebApplicationBuilder.Host is the ASP.NET Core entry path; calling it on a HostBuilder works for Worker services
  • Sinks are opt-in via appsettings.json — every sink block has an Enabled gate; an empty or missing config section leaves all sinks off except what is wired manually
  • StaticLogger.EnsureInitialized() is a bootstrap-only logger — it is intended for use before UseLogging() is called so that startup exceptions are captured; it is not a substitute for configuring the main logger

High-Value Entry Points

Host Setup

Correlation & Middleware

Dynamic Log Level

CQRS Decorator Logging

Configuration Options

Decision Matrix For Agents

GoalPreferred APINotes
Bootstrap Serilog in a hosthostBuilder.UseLogging()Call before builder.Build(); reads logger and app config sections
Capture startup errors before Serilog is readyStaticLogger.EnsureInitialized()Call at the very top of Program.cs, before any Serilog setup
Enrich logs with HTTP baggage and request/response bodiesAddCorrelationContextLogging() + UseCorrelationContextLogging()Opt-in body capture via HttpPayloadOptions.CaptureRequestBody / CaptureResponseBody
Change log level at runtime without restartMapLogLevelHandler(app, "/logging/level")Exposes a POST endpoint; body param level accepts Serilog level names
Add structured log entries around every commandAddCommandHandlersLogging(gnxBuilder)Uses [Decorator] + Scrutor to wrap all ICommandHandler<> in the assembly
Add structured log entries around every event handlerAddEventHandlersLogging(gnxBuilder)Same Scrutor decoration pattern for IEventHandler<>
Customize log message templates per command/eventImplement IMessageToLogTemplateMapperReturn a HandlerLogTemplate with Before, After, and per-exception templates; uses SmartFormat
Route logs to ElasticsearchSet logger:elk:enabled: true and logger:elk:urlSupports basic auth and configurable index format
Route logs to Grafana/LokiSet logger:loki:enabled: true and logger:loki:urlSupports optional credentials and batch posting settings
Route logs to Azure Application InsightsSet logger:azure:enabled: true and logger:azure:connectionStringUses Serilog.Sinks.ApplicationInsights
Send logs over OpenTelemetrySet logger:otlpEndpointWrites to Serilog.Sinks.OpenTelemetry OTLP exporter

Minimal Integration Recipe

Install

dotnet add package Genocs.Logging

Setup in Program.cs

using Genocs.Common.Configurations;
using Genocs.Core.Builders;
using Genocs.Logging;

// Bootstrap logger for startup diagnostics (before host builds)
StaticLogger.EnsureInitialized();

var builder = WebApplication.CreateBuilder(args);

// Wire Serilog via IHostBuilder
builder.Host.UseLogging();

// Register correlation context middleware (optional)
IGenocsBuilder gnxBuilder = builder.AddGenocs();
gnxBuilder.AddCorrelationContextLogging();

// If using CQRS decorator logging (optional)
// gnxBuilder.AddCommandHandlersLogging();
// gnxBuilder.AddEventHandlersLogging();

gnxBuilder.Build();

var app = builder.Build();

// Activate correlation context enrichment (optional)
app.UseCorrelationContextLogging();

// Expose dynamic log-level endpoint (optional)
app.MapLogLevelHandler("/logging/level");

app.Run();

appsettings.json

{
  "app": {
    "name": "MyService",
    "service": "my-service",
    "instance": "1",
    "version": "1.0.0"
  },
  "logger": {
    "enabled": true,
    "level": "Information",
    "otlpEndpoint": "",
    "console": { "enabled": true, "enableStructured": false },
    "file": { "enabled": false, "path": "logs/logs.txt", "interval": "Day" },
    "elk": { "enabled": false, "url": "http://localhost:9200", "indexFormat": "my-service-{0:yyyy.MM.dd}" },
    "seq": { "enabled": false, "url": "http://localhost:5341" },
    "loki": { "enabled": false, "url": "http://localhost:3100" },
    "azure": { "enabled": false, "connectionString": "" },
    "httpPayload": { "enabled": false, "captureRequestBody": false, "captureResponseBody": false },
    "minimumLevelOverrides": { "Microsoft": "Warning", "System": "Warning" },
    "excludePaths": ["/health", "/metrics"],
    "tags": { "team": "backend" }
  }
}

Behavior Notes That Affect Agent Decisions

  • UseLogging() registers ILoggingService as a singleton automatically; MapLogLevelHandler relies on it — do not forget to call UseLogging() if using the dynamic level endpoint
  • The minimum log level is managed through a shared LoggingLevelSwitch instance; changing the level via SetLoggingLevel() affects all sinks simultaneously
  • AddCommandHandlersLogging / AddEventHandlersLogging discover handlers in Assembly.GetCallingAssembly() by default; pass an explicit Assembly parameter if handlers live in a different project
  • Structured console output (JSON) is activated by console.enableStructured: true — use plain-text console for local dev, structured JSON for production log aggregation
  • Elasticsearch sink uses AutoRegisterTemplate = true with v6 format; explicit indexFormat override is strongly recommended for production to avoid date-partitioned index name collisions
  • CorrelationContextLoggingMiddleware reads Activity.Current.Baggage (W3C trace baggage) and injects it as log scope properties; ensure AddCorrelationContextLogging() is called before gnxBuilder.Build()
  • HTTP body capture is opt-in per direction (CaptureRequestBody, CaptureResponseBody); enabling response body capture buffers the response stream and may affect memory allocation under high load
  • HandlerLogTemplate messages are formatted using SmartFormat.NET syntax, allowing property interpolation from the command/event object (e.g., "Handling order {OrderId}")

Source-Accurate Capability Map

Host & Serilog Pipeline Setup

  • UseLogging(IHostBuilder, ...) — main entry point; reads LoggerOptions from config, applies all enrichers and sink wiring, registers ILoggingService
  • MapOptions(...) — internal; applies enrichers: FromLogContext, WithProperty, WithExceptionDetails, WithMachineName, WithProcessId, WithThreadId, WithSpan, MinimumLevelOverrides, ExcludePaths, Tags
  • Configure(...) — internal; activates each sink based on its Enabled flag; supports Console, File, ELK, Seq, Loki, Azure AI, OTLP

Files:

Correlation Context Middleware

  • CorrelationContextLoggingMiddleware — reads W3C Activity baggage and injects into log scope; optionally captures request/response bodies into log scope and as Activity tags
  • AddCorrelationContextLogging(IGenocsBuilder) — registers middleware as transient DI service
  • UseCorrelationContextLogging(IApplicationBuilder) — adds middleware to HTTP pipeline

Files:

Dynamic Log Level Control

  • ILoggingService / LoggingService — thin service with SetLoggingLevel(string) that updates the shared LoggingLevelSwitch
  • MapLogLevelHandler(IEndpointRouteBuilder, string) — maps a POST endpoint; reads ?level= query param and calls ILoggingService
  • LoggingLevelSwitch — internal Serilog LoggingLevelSwitch instance; updated without restarting the host

Files:

CQRS Handler Logging Decorators

  • AddCommandHandlersLogging(IGenocsBuilder, Assembly?) — discovers all ICommandHandler<> implementations and wraps each in CommandHandlerLoggingDecorator<TCommand> using Scrutor’s TryDecorate
  • AddEventHandlersLogging(IGenocsBuilder, Assembly?) — same for IEventHandler<>
  • CommandHandlerLoggingDecorator<TCommand> — logs Before, After, and per-exception messages using HandlerLogTemplate formatted via SmartFormat; falls back silently if no template is registered
  • EventHandlerLoggingDecorator<TEvent> — identical structure for event handlers

Files:

Message-to-Template Mapping

  • IMessageToLogTemplateMapper — resolves a HandlerLogTemplate for a given message instance; return null to skip logging
  • HandlerLogTemplateBefore, After, and exception-specific template strings; GetExceptionTemplate(Exception) selector method
  • Default behavior: if IMessageToLogTemplateMapper is not registered in DI, the decorator uses an internal no-op mapper and skips log emission

Files:

Sink Configuration Options

  • LoggerOptions — root config: Enabled, Level, OtlpEndpoint, sub-objects per sink, Tags, MinimumLevelOverrides, ExcludePaths, ExcludeProperties
  • ConsoleOptionsEnabled, EnableStructured (JSON formatter for structured output)
  • LocalFileOptionsEnabled, Path, Interval (e.g., "Day", "Hour")
  • ElkOptionsEnabled, Url, BasicAuthEnabled, Username, Password, IndexFormat
  • SeqOptionsEnabled, Url, ApiKey
  • LokiOptionsEnabled, Url, LokiUsername, LokiPassword, BatchPostingLimit, QueueLimit, Period
  • AzureOptionsEnabled, ConnectionString
  • HttpPayloadOptionsEnabled, CaptureRequestBody, CaptureResponseBody

Files:

Dependencies

From src/Genocs.Logging/Genocs.Logging.csproj:

  • Genocs.CoreIGenocsBuilder, GetOptions<T>() configuration helper
  • Serilog.AspNetCore — Serilog / ASP.NET Core integration, UseSerilog() on IHostBuilder
  • Serilog.Sinks.ElasticSearch — Elasticsearch sink
  • Serilog.Sinks.Seq — Seq sink
  • Serilog.Sinks.Grafana.Loki — Grafana/Loki sink
  • Serilog.Sinks.ApplicationInsights — Azure Application Insights sink
  • Serilog.Sinks.OpenTelemetry — OTLP exporter sink
  • Serilog.Sinks.File — rolling file sink
  • Serilog.Sinks.Async — wraps other sinks in async buffered mode
  • Serilog.Enrichers.Environment / .Process / .Thread / .Span — standard enrichers
  • Serilog.ExceptionsWithExceptionDetails() enricher
  • Microsoft.ApplicationInsights — Azure AI telemetry infrastructure
  • SmartFormat.NETSmart.Format(template, command) in CQRS decorators