From harness-claude
Correlates structured logs with distributed traces using OpenTelemetry context for unified observability. Useful for connecting log entries to trace IDs and migrating to structured logging.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:otel-logging-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Correlate structured logs with distributed traces using OpenTelemetry context for unified observability
Correlate structured logs with distributed traces using OpenTelemetry context for unified observability
// logger/otel-logger.ts
import pino from 'pino';
import { trace, context } from '@opentelemetry/api';
function getTraceContext(): Record<string, string> {
const span = trace.getActiveSpan();
if (!span) return {};
const spanContext = span.spanContext();
return {
trace_id: spanContext.traceId,
span_id: spanContext.spanId,
trace_flags: `0${spanContext.traceFlags.toString(16)}`,
};
}
export const logger = pino({
level: process.env.LOG_LEVEL || 'info',
formatters: {
log(object) {
// Automatically inject trace context into every log entry
return { ...object, ...getTraceContext() };
},
},
serializers: {
err: pino.stdSerializers.err,
},
});
// Create child loggers for specific modules
export function createLogger(module: string) {
return logger.child({ module });
}
// Usage in service code
import { createLogger } from '../logger/otel-logger';
const log = createLogger('order-service');
export async function createOrder(userId: string, items: OrderItem[]): Promise<Order> {
log.info({ userId, itemCount: items.length }, 'Creating order');
try {
const order = await db.orders.create({ userId, items });
log.info({ orderId: order.id, userId }, 'Order created successfully');
return order;
} catch (error) {
log.error({ err: error, userId }, 'Failed to create order');
throw error;
}
}
// Output (with trace context automatically injected):
// {"level":"info","time":1700000000,"module":"order-service",
// "trace_id":"abc123","span_id":"def456","trace_flags":"01",
// "userId":"u1","itemCount":3,"msg":"Creating order"}
OpenTelemetry Logs SDK (direct): For sending logs via OTLP without a logging library bridge:
import { logs, SeverityNumber } from '@opentelemetry/api-logs';
const logger = logs.getLogger('order-service');
logger.emit({
severityNumber: SeverityNumber.INFO,
severityText: 'INFO',
body: 'Order created',
attributes: { 'order.id': orderId, 'user.id': userId },
});
Pino + OpenTelemetry instrumentation:
// Auto-instrumentation adds trace context to Pino logs
import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino';
const pinoInstrumentation = new PinoInstrumentation({
logHook: (span, record) => {
record['service.name'] = 'order-service';
},
});
Winston integration:
import winston from 'winston';
import { trace } from '@opentelemetry/api';
const otelFormat = winston.format((info) => {
const span = trace.getActiveSpan();
if (span) {
const ctx = span.spanContext();
info.trace_id = ctx.traceId;
info.span_id = ctx.spanId;
}
return info;
});
const logger = winston.createLogger({
format: winston.format.combine(otelFormat(), winston.format.json()),
transports: [new winston.transports.Console()],
});
Log levels and when to use them:
Correlation in observability backends: With trace ID in logs, you can: search Grafana Loki by trace ID, click from a Jaeger trace to its logs, filter Datadog logs by trace, and build Kibana dashboards that link logs to traces.
https://opentelemetry.io/docs/concepts/signals/logs/
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeInstruments distributed traces with OpenTelemetry spans to visualize request flow across services. Helps debug slow requests, identify latency sources, and correlate logs to traces.
Guides implementing distributed tracing in microservices with OpenTelemetry, covering traces, spans, context propagation, and cross-service debugging.
Instruments applications with OpenTelemetry for distributed tracing: auto/manual instrumentation, context propagation, sampling, integration with Jaeger or Tempo. Debug latency in distributed systems.