AgentSkillsCN

logging

为高基数、高维度的可观测性构建宽泛事件与规范日志行。适用于添加日志记录、提升可观测性、调试生产环境中的问题,或审查日志记录代码时使用。

SKILL.md
--- frontmatter
name: logging
description: Implement wide events and canonical log lines for high-cardinality, high-dimensionality observability. Use when adding logging, improving observability, debugging production issues, or reviewing logging code.
references:
  - references/wide-events.md
  - references/implementation.md

Logging

One wide event per request per service. Not 15 scattered log lines.

Should I Use Wide Events?

code
START HERE:
├─ New service/endpoint?
│   → YES. Add wide event middleware. See templates/middleware.ts
├─ Adding a log statement to a handler?
│   → STOP. Enrich the wide event instead.
├─ Debugging production issue?
│   → Check: do events have user_id, request_id, business context?
│   → Missing fields? Add them. See references/wide-events.md
├─ Reviewing existing logging?
│   → Scattered console.log/logger calls? Consolidate to wide events.
│   → Incremental: start with critical paths, don't rewrite everything at once.
└─ Concerned about log volume/cost?
    → See references/implementation.md § Tail Sampling

Quick Reference

Code You SeeWhat To Do
console.log("Payment failed")Enrich event.error with structured details
logger.info("User logged in")Add user context to wide event
5+ log statements in one handlerConsolidate into single wide event
log.debug() scattered everywhereRemove. Enrich the wide event instead
catch (err) { logger.error(err) }Set event.error, let middleware emit
New API endpoint with no loggingAdd middleware, enrich in handler

Non-Negotiable Fields

Every wide event MUST have:

FieldWhy
request_idCorrelation across services
timestampOrdering, time-range queries
duration_msPerformance analysis
service, versionWhere it ran, which deploy
method, path, status_codeWhat happened
user.idWho (even if anonymous session)
outcome"success" or "error"

The Pattern (Any Language)

code
1. Middleware creates mutable event object at request start
2. Attach event to request context (ctx, req, locals, etc.)
3. Handlers enrich event with business context as they process
4. finally{} block: set duration_ms, emit event via structured logger
5. Tail sampling decides what to store

For copy-paste middleware: See templates/middleware.ts For full implementation details: See implementation.md

What Goes In a Wide Event

CategoryExample FieldsWhen to Add
Requestmethod, path, status, duration_ms, request_id, trace_idAlways (middleware)
Servicename, version, region, deployment_idAlways (middleware)
Userid, subscription, account_age_days, lifetime_valueAuth middleware or handler
Businesscart_total, item_count, feature_flags, coupon_codeHandler, domain-specific
Errortype, code, message, retriable, upstream_servicecatch blocks
Dependenciesdb_query_count, cache_hit, external_call_latency_msAfter each dep call

Full field taxonomy and examples: See wide-events.md

Anti-Patterns

Don'tWhyDo Instead
String interpolation in logsUnsearchable, unqueryableStructured key-value fields
Log only on errorsMisses success context for comparisonAlways emit (success AND failure)
Scattered debug statementsNoise, no correlationSingle enriched event
Log sensitive data (passwords, tokens, PII)Security/compliance riskRedact or omit
Convert all logging at onceRisk of breaking existing monitoringIncremental: critical paths first
50+ fields on hot paths synchronouslyPerformance impactAsync emission, buffer

Key Concepts

Cardinality: Unique values per field. High-cardinality (user_id, request_id) = useful for debugging. Low-cardinality (http_method) = useful for aggregation.

Dimensionality: Number of fields per event. More dimensions = more questions answerable without redeployment.

Tail Sampling: Decide AFTER request completes what to keep. Always keep: errors, slow requests (>p99), VIP users, feature flag rollouts. Random sample the rest (1-10%).

Wide Event ≠ Structured Logging: Structured logging is JSON format (table stakes). Wide events are a philosophy: one comprehensive event per request with all context.

OTel is a delivery mechanism: OpenTelemetry standardizes collection/export. It doesn't decide what to capture. You still must instrument with business context.

Wide events complement traces: Tracing = request flow across services. Wide events = context within a service. Best case: wide events ARE enriched trace spans.

In This Reference

FilePurpose
wide-events.mdFull field taxonomy, example events, field naming
implementation.mdMiddleware patterns, enrichment, tail sampling
templates/middleware.tsCopy-paste TypeScript middleware

Reading Order

TaskFiles
New to wide eventsThis file only
Implementing in codebaseThis + templates/middleware.ts
Adding fields / reviewing logsThis + wide-events.md
Full implementation with samplingThis + implementation.md