void-observability

Enforces structured logging, trace propagation, and error boundaries in production TypeScript code.

Updated May 29, 2026
One-click install
npx skills add https://github.com/voidcorp-core/void-harness --skill void-observability-voidcorp-core
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: void-observability
Source: https://github.com/voidcorp-core/void-harness/tree/main/packages/core/skills/void-observability
Command: npx skills add https://github.com/voidcorp-core/void-harness --skill void-observability-voidcorp-core

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Production bugs are impossible to fix when logs are unstructured strings, trace context is lost across async boundaries, and errors are silently swallowed. This Skill codifies what to log, what to trace, and what must never be logged (PII, secrets) so debugging starts from real signal instead of guesswork. ## Core Features & Use Cases - Structured logging discipline: Mandates pino via @repo/core/logger with object payloads instead of string interpolation, enforced by a no-console-log-grep hook that blocks console.log in business code. - End-to-end trace propagation: Propagates W3C TraceContext IDs across HTTP, service, job, webhook, and queue boundaries using OpenTelemetry-compatible conventions. - Error boundaries and redaction: Requires typed error handling at every async boundary, Sentry integration with anonymized user scope, and logger-level redaction of passwords, tokens, and PII. - Use Case: When adding a checkout flow, the Skill ensures every use case logs structured events with trace IDs, Stripe adapter errors are caught and returned as typed Results, and no email or token ever reaches the log stream. ## Quick Start Ask the agent to add observability to the checkout flow following the void-observability discipline, with structured logs, trace IDs, and error boundaries.

Frequently Asked Questions about void-observability

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I structure logs in Node.js with pino?

Pass an object as the first argument and a short event message as the second, such as logger.info({ userId, orderId }, 'checkout_started'). This keeps logs queryable by field instead of forcing string searches, and a shared logger adapter lets you swap backends later.

How to propagate trace IDs across async jobs and webhooks?

Attach the W3C TraceContext trace ID to the message envelope when enqueueing a job or sending a webhook, then restore it on the consumer side. Child loggers created with logger.child({ traceId }) make every downstream log inherit the same trace.

What should never be logged in production applications?

Never log passwords, tokens, API keys, session IDs, JWTs, full request bodies, unredacted emails, or LLM prompt content. Configure the logger with a redact list such as ['password', 'token', 'apiKey', 'secret', 'authorization'] so slipped fields are dropped at serialization.

Does Sentry user tracking work without exposing PII?

Yes, set the Sentry user scope to a hashed identifier, for example Sentry.setUser({ id: hash(userId) }), and use beforeSend to strip known-secret keys and PII attributes. This preserves per-user filtering while keeping raw identities out of the error tracker.

Why is swallowing errors in catch blocks a problem?

An empty catch block destroys the only signal that a failure occurred, making production bugs invisible. Every caught error must be logged with context and either returned as a typed Result error or rethrown so a top-level handler like Sentry captures it.