logging — скилл для Claude Code: health checks и correlation ID
Скилл про наблюдаемость в .NET 10: разводит liveness и readiness, прокидывает correlation ID и задаёт уровни логов.
npx skills add codewithmukesh/dotnet-claude-kit --skill logging -a claude-codeЧто делает logging
Скилл закрывает сквозные куски наблюдаемости, которые не влезают в настройку Serilog или OpenTelemetry. Внутри — middleware для correlation ID: идентификатор берётся из заголовка X-Correlation-Id или генерируется, кладётся в HttpContext.Items, возвращается в ответе и через LogContext.PushProperty цепляется ко всем логам запроса. Регистрируется в начале пайплайна, чтобы идентификатор был у каждого события ниже по стеку.
Второй кусок — health checks. Сервис получает два эндпоинта: /health/live без проверок зависимостей и /health/ready с проверками по тегу ready (база, Redis, RabbitMQ). Смысл в том, что провал liveness означает «перезапусти меня», а провал readiness — «перестань слать трафик». Если свести их в один /health, медленная база начнёт перезапускать приложение по кругу. Это повод проверить, как у вас настроен оркестратор.
Ещё здесь таблица уровней логирования: Debug только в разработке, Information для бизнес-событий, Warning как уровень по умолчанию в продакшене. Глубокая настройка Serilog и трейсы с метриками живут в отдельных скиллах serilog и opentelemetry, этот их только связывает. Секреты и PII в Information-логи писать не стоит — в скилле это разобрано на примерах.
Какие задачи решает
- развести liveness и readiness на отдельные эндпоинты
- прокинуть correlation ID через все логи запроса
- выбрать уровень логирования для продакшена
- подключить проверки базы, Redis и RabbitMQ к readiness
- убрать пароли и PII из логов
Примеры запросов агенту
- Настрой наблюдаемость в .NET 10: health checks и correlation ID
- Добавь /health/live и /health/ready с проверками по тегу ready
- Какой уровень логирования ставить по умолчанию в продакшене?
Как установить logging
1Через Skills CLI (Vercel)
npx skills add codewithmukesh/dotnet-claude-kit --skill logging -a claude-code2Вручную: положить файлы
~/.claude/skills/logging/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/logging/
1Через Skills CLI (Vercel)
npx skills add codewithmukesh/dotnet-claude-kit --skill logging -a codex2Вручную: положить файлы
.agents/skills/logging/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add codewithmukesh/dotnet-claude-kit --skill logging -a cursor2Вручную: положить файлы
.cursor/skills/logging/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install codewithmukesh/dotnet-claude-kit logging2Вручную: положить файлы
.github/skills/logging/SKILL.md1Через Skills CLI (Vercel)
npx skills add codewithmukesh/dotnet-claude-kit --skill logging -a gemini-cli2Командой платформы
gemini skills install https://github.com/codewithmukesh/dotnet-claude-kit --path skills/loggingВручную: положить файлы
.devin/skills/logging/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add codewithmukesh/dotnet-claude-kit --skill logging -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Из того же набора46
Похожие
Вопросы о logging
Как установить logging в Claude?
Выполните npx skills add codewithmukesh/dotnet-claude-kit --skill logging -a claude-code. Файл скилла появится по пути ~/.claude/skills/logging/SKILL.md.
Что делает скилл logging?
Связывает части наблюдаемости в .NET 10 и отвечает за сквозные вещи: эндпоинты health checks, correlation ID и стратегию уровней логирования. Настройку Serilog и OpenTelemetry он передаёт отдельным скиллам.
Чем logging отличается от скиллов serilog и opentelemetry?
Serilog отвечает за структурные логи и AddSerilog(), opentelemetry — за трейсы и метрики с экспортом по OTLP. Здесь только health-эндпоинты, correlation ID и уровни логов.
Исходный текст
SKILL.md · MIT
---
name: logging
description: >
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. For deep Serilog setup
load `serilog`; for traces and metrics load `opentelemetry`. Load this
skill when setting up observability from scratch, wiring health check
endpoints or correlation IDs, or when the user says "logging",
"observability", "monitoring setup", "liveness", "readiness", or "ILogger".
---
# 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
| Concern | Owner | Skill |
|---------|-------|-------|
| Structured application logs | Serilog (`AddSerilog()`) | `serilog` |
| Request summary logging | `UseSerilogRequestLogging()` | `serilog` |
| Traces + metrics + OTLP export | OpenTelemetry SDK | `opentelemetry` |
| Health endpoints, correlation IDs, log-level strategy | This skill | `logging` |
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
| Level | Use for | Environment default |
|-------|---------|---------------------|
| Debug | Diagnostic detail, payload dumps (never PII in prod) | Development only |
| Information | Business events: order placed, job completed | Dev + staging |
| Warning | Recoverable anomalies: retry fired, fallback used | Everywhere — production default |
| Error | Failed operations that need attention | Everywhere |
| Fatal/Critical | App cannot continue | Everywhere |
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
| Scenario | Recommendation |
|----------|---------------|
| Application logging setup | Load `serilog` — `AddSerilog()` two-stage bootstrap |
| Distributed tracing / metrics | Load `opentelemetry` — OTLP exporter |
| Custom business metrics | `IMeterFactory` + counters/histograms (`opentelemetry` skill) |
| Request tracing | Correlation ID middleware (this skill) |
| Container health | `/health/live` and `/health/ready` endpoints (this skill) |
| Log storage | Seq (development), Elastic/Grafana/OTLP backend (production) |
| Log levels | Debug in dev, Information in staging, Warning default in production |
© codewithmukesh · MIT · codewithmukesh/dotnet-claude-kit