
Logging Best Practices
Apply wide-event structured logging, sampling, and anti-pattern rules so production logs stay debuggable without drowning in noise.
Install
npx skills add https://github.com/ncklrs/startup-os-skills --skill logging-best-practicesWhat is this skill?
- Wide event and canonical log line architecture patterns
- Field guides for high-cardinality, required context, and business context
- Tail sampling after request completion plus always-keep exceptions
- Anti-patterns for scattered logs and string-search-only debugging
- Organized rule sections: Architecture, Field Design, Sampling, Anti-Patterns
Adoption & trust: 1 installs on skills.sh; 27 GitHub stars; 2/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
Recommended Skills
Journey fit
Operate monitoring is the canonical shelf because the rules target production observability and tail-debug workflows after ship. Content emphasizes canonical log lines, tail sampling, and cardinality—core signals you rely on when watching live systems.
Common Questions / FAQ
Is Logging Best Practices safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Logging Best Practices
{ "name": "logging-best-practices", "version": "1.0.0", "author": "Based on Boris Tane's loggingsucks.com", "references": [ { "title": "Logging Sucks", "url": "https://loggingsucks.com/", "description": "Boris Tane's manifesto on production-grade logging" } ], "tags": [ "logging", "observability", "wide-events", "structured-logging", "debugging", "production" ], "keywords": [ "log", "logging", "observability", "wide event", "canonical log line", "structured logging", "cardinality", "sampling", "tail sampling", "opentelemetry", "otel", "debug", "production logging" ] } # Logging Best Practices Rules ## Sections ### Architecture Core architectural patterns for production logging. - `architecture-wide-events.md` - The wide event pattern - `architecture-event-lifecycle.md` - Building events through request lifecycle ### Field Design What to include in your events. - `fields-high-cardinality.md` - Embrace high-cardinality fields - `fields-required-context.md` - Essential fields for every event - `fields-business-context.md` - Capturing business-relevant data ### Sampling Smart sampling strategies. - `sampling-tail-sampling.md` - Sample after completion, not before - `sampling-always-keep.md` - What to never sample away ### Anti-Patterns Common mistakes to avoid. - `antipattern-scattered-logs.md` - Stop scattering log statements - `antipattern-string-search.md` - Design for queries, not grep - `antipattern-otel-silver-bullet.md` - OTel is delivery, not strategy --- title: Anti-Pattern - OTel as Silver Bullet impact: MEDIUM-HIGH tags: anti-pattern, opentelemetry, observability --- ## Anti-Pattern: OpenTelemetry as Silver Bullet **Impact: MEDIUM-HIGH** OpenTelemetry is a **delivery protocol**, not a solution architecture. It doesn't determine what to log, add business context, or fix flawed mental models. ### The Misconception > "We use OpenTelemetry, so observability is solved." **Reality:** Most OTel implementations capture only span names, duration, and status—insufficient for effective debugging. ### What OTel Is vs. Isn't | OTel IS | OTel ISN'T | |---------|------------| | Standardized data export format | A solution for what to log | | Vendor-agnostic wire protocol | Automatic business context | | Trace context propagation | A replacement for wide events | | SDK for instrumentation | A strategy for observability | ### Minimal OTel Implementation (Common) ```javascript // ❌ What most teams end up with // Auto-instrumented, no custom context const tracer = trace.getTracer('checkout-service'); async function checkout(req, res) { const span = tracer.startSpan('checkout'); try { await processPayment(); span.setStatus({ code: SpanStatusCode.OK }); } catch (error) { span.setStatus({ code: SpanStatusCode.ERROR }); span.recordException(error); throw error; } finally { span.end(); } } // Result: You know checkout took 500ms and failed // You DON'T know: which user, what cart value, what payment method, // which feature flags, what error code, is this a VIP customer... ``` ### OTel + Wide Events (Correct) ```javascript // ✅ OTel for tracing, wide events for context const tracer = trace.getTracer('checkout-service'); async function checkout(req, res) { const span = tracer.startSpan('checkout'); // Build wide event alongside span const event = { trace_id: span.spanContext().traceId, span_id: span.spanContext().spanId, request_id: req.id, timestamp: Date.now(), service: 'checkout' }; try { const user = await getUser(req.userId); event.user = { id: user.id, tier: user.tier, ltv_cents: user.ltv }; span.setAttribute('user.tier', user.tier); const cart = await getCart(req.cartId); event.cart = { id: cart.id, total_cents: cart.total, item_count: cart.items.length }; span.setAttribute('cart.total_cents', cart.total);