codewithmukesh/dotnet-claude-kit

logging

Observability overview and glue for .NET 10: how the pieces fit together, plus the cross-cutting parts owned here — ASP.NET health check endpoints (/health), correlation IDs, and log-level strategy.

Vedi sorgente
Documento Skill originale

Contenuto dal repository con titoli, esempi, codice, tabelle, link e immagini preservati.

Logging & Observability

Core Principles

  1. Structured logging with Serilog — Every log entry is a structured event with named properties, not a formatted string. This enables searching, filtering, and alerting. All setup (two-stage bootstrap, AddSerilog(), sinks, enrichers) lives in the serilog skill — that skill's AddSerilog()-over-UseSerilog() guidance is canonical.
  2. OpenTelemetry for distributed tracing — Traces connect requests across services; metrics track system health over time. Full setup lives in the opentelemetry skill.
  3. Health checks for operational readiness — Every service exposes /health endpoints for load balancers and orchestrators. Liveness and readiness are separate questions and separate endpoints.
  4. Correlation IDs for request tracing — Every request gets a unique ID that flows through all log entries and downstream service calls, so one user complaint maps to one filtered log stream.

Patterns

How the Pieces Fit Together

ConcernOwnerSkill
Structured application logsSerilog (AddSerilog())serilog
Request summary loggingUseSerilogRequestLogging()serilog
Traces + metrics + OTLP exportOpenTelemetry SDKopentelemetry
Health endpoints, correlation IDs, log-level strategyThis skilllogging

Wire logging first (you need logs to debug the rest), then health checks, then tracing.

Correlation IDs

csharp
// Middleware to set correlation ID
public class CorrelationIdMiddleware(RequestDelegate next)
{
    private const string CorrelationIdHeader = "X-Correlation-Id";

    public async Task InvokeAsync(HttpContext context)
    {
        var correlationId = context.Request.Headers[CorrelationIdHeader].FirstOrDefault()
            ?? Guid.NewGuid().ToString();

        context.Items["CorrelationId"] = correlationId;
        context.Response.Headers[CorrelationIdHeader] = correlationId;

        using (LogContext.PushProperty("CorrelationId", correlationId))
        {
            await next(context);
        }
    }
}

// Program.cs — register early so every downstream log carries the ID
app.UseMiddleware<CorrelationIdMiddleware>();

Why middleware: pushing the property once at the pipeline edge attaches it to every log event in the request scope — no per-call-site plumbing. Propagate the same header on outgoing HttpClient calls via a DelegatingHandler (see the httpclient-factory skill).

Health Checks

csharp
// Program.cs
builder.Services.AddHealthChecks()
    .AddNpgSql(builder.Configuration.GetConnectionString("Default")!,
        name: "database", tags: ["ready"])
    .AddRedis(builder.Configuration.GetConnectionString("Redis")!,
        name: "redis", tags: ["ready"])
    .AddRabbitMQ(builder.Configuration.GetConnectionString("RabbitMq")!,
        name: "rabbitmq", tags: ["ready"]);

// Map endpoints
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
    Predicate = _ => false // No dependency checks — just "am I running?"
});

app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready")
});

Why two endpoints: liveness failing means "restart me"; readiness failing means "stop sending traffic". Conflating them makes a slow database restart your app in a loop.

Log-Level Strategy

LevelUse forEnvironment default
DebugDiagnostic detail, payload dumps (never PII in prod)Development only
InformationBusiness events: order placed, job completedDev + staging
WarningRecoverable anomalies: retry fired, fallback usedEverywhere — production default
ErrorFailed operations that need attentionEverywhere
Fatal/CriticalApp cannot continueEverywhere

Why Warning as the production default: Information-level request noise at scale costs real money in log storage and drowns the signals. Keep Information for genuine business events via namespace overrides (see the serilog skill's MinimumLevel.Override pattern).

Anti-patterns

Don't Log Sensitive Data

csharp
// BAD — logging credentials
logger.LogInformation("User logged in: {Email} with password {Password}", email, password);

// GOOD — log identifiers, never secrets or PII at Information level
logger.LogInformation("User {UserId} logged in", userId);

Don't Skip Health Check Tags

csharp
// BAD — all checks run for liveness AND readiness
app.MapHealthChecks("/health");

// GOOD — separate liveness (am I running?) from readiness (can I serve traffic?)
app.MapHealthChecks("/health/live", new() { Predicate = _ => false });
app.MapHealthChecks("/health/ready", new() { Predicate = c => c.Tags.Contains("ready") });

Don't Re-Implement What the Owning Skill Provides

csharp
// BAD — hand-rolling Serilog bootstrap here from memory
builder.Host.UseSerilog(...);  // legacy API — the serilog skill forbids this

// GOOD — load the serilog skill and use its two-stage AddSerilog() bootstrap
builder.Services.AddSerilog((services, lc) => lc.ReadFrom.Configuration(builder.Configuration)...);

Decision Guide

ScenarioRecommendation
Application logging setupLoad serilogAddSerilog() two-stage bootstrap
Distributed tracing / metricsLoad opentelemetry — OTLP exporter
Custom business metricsIMeterFactory + counters/histograms (opentelemetry skill)
Request tracingCorrelation ID middleware (this skill)
Container health/health/live and /health/ready endpoints (this skill)
Log storageSeq (development), Elastic/Grafana/OTLP backend (production)
Log levelsDebug in dev, Information in staging, Warning default in production
dallo stesso repository

Altri Skills

Tutti gli Skills
codewithmukesh
Community

api-versioning

API versioning strategies for ASP.NET Core. Covers Asp.Versioning library, URL segment, header, and query string strategies, version deprecation, and OpenAPI integration. Load this skill when adding versioning to an API, evolving an API with breaking changes, or when the user mentions "API version", "versioning", "v1/v2", "Asp.Versioning", "deprecation", "breaking change", or "backward compatibility".

installazioni
2
GitHub Stars
692
Aggiornato
7 ago
codewithmukesh
Community

arch-check

Architecture conformance check: verifies an existing codebase against its declared architecture (VSA, Clean Architecture, DDD, Modular Monolith) — dependency direction, layer violations, module boundary leaks, and cycles — using token-cheap Roslyn MCP analysis. Invoke when: "check architecture", "architecture violations", "layer violations", "dependency direction", "module boundaries", "arch check", "is my architecture clean", "enforce architecture", "conformance check". For CHOOSING an architecture, use architecture-advisor instead.

installazioni
2
GitHub Stars
692
Aggiornato
7 ago
codewithmukesh
Community

architecture-advisor

Architecture selection advisor for .NET applications. Asks structured questions about domain complexity, team size, system lifetime, compliance, and integration needs, then recommends the best-fit architecture: Vertical Slice, Clean Architecture, DDD + Clean Architecture, or Modular Monolith. Load this skill when the user asks "which architecture", "choose architecture", "set up project", "new project", "architecture decision", "restructure", or "how should I organize". Always load BEFORE any architecture-specific skill.

installazioni
2
GitHub Stars
692
Aggiornato
7 ago
codewithmukesh
Community

aspire

.NET Aspire for cloud-native orchestration. Covers AppHost configuration, service defaults, resource configuration, service discovery, and the Aspire dashboard. Load this skill when setting up local development orchestration, service discovery, or Aspire-managed infrastructure, or when the user mentions "Aspire", "AppHost", "service defaults", "service discovery", "orchestration", "Aspire dashboard", "AddProject", "WithReference", or "cloud-native .NET".

installazioni
2
GitHub Stars
692
Aggiornato
7 ago