From harness-claude
Tracks and correlates errors across distributed services using OpenTelemetry span exceptions, status codes, and events. Useful for error propagation analysis, SLI building, and replacing Sentry.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Track and correlate errors across services with span exceptions, status codes, and error events
Instruments code with OpenTelemetry spans for distributed tracing to visualize request flows across services, debug microservice latency, and correlate logs/errors.
Guides implementing distributed tracing in microservices with OpenTelemetry, covering traces, spans, context propagation, and cross-service debugging.
Instruments apps with OpenTelemetry for distributed tracing and Jaeger/Tempo integration. Debugs latency in microservices, analyzes request flows, correlates traces with logs/metrics.
Share bugs, ideas, or general feedback.
Track and correlate errors across services with span exceptions, status codes, and error events
span.recordException(error) — this adds an exception event with stack trace, type, and message.span.setStatus({ code: SpanStatusCode.ERROR, message }).// Comprehensive error recording
import { trace, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('order-service');
export async function processOrder(orderId: string): Promise<Order> {
return tracer.startActiveSpan('order.process', async (span) => {
span.setAttribute('order.id', orderId);
try {
const order = await db.orders.findById(orderId);
if (!order) {
// Business error — record as exception with context
const error = new NotFoundError(`Order ${orderId} not found`);
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
span.setAttribute('error.type', 'NotFoundError');
span.setAttribute('error.category', 'business');
throw error;
}
try {
await paymentService.charge(order);
} catch (paymentError) {
// Handled error — using fallback
span.addEvent('payment.fallback', {
'error.message': (paymentError as Error).message,
'fallback.strategy': 'retry-queue',
});
await retryQueue.enqueue(order);
span.setAttribute('order.payment_status', 'queued');
return { ...order, paymentStatus: 'queued' };
}
span.setStatus({ code: SpanStatusCode.OK });
return order;
} catch (error) {
if (!span.isRecording()) return; // Span already ended
span.recordException(error as Error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: (error as Error).message,
});
span.setAttribute('error.type', (error as Error).constructor.name);
throw error;
} finally {
span.end();
}
});
}
// Global error handler that enriches the active span
export function handleUnexpectedError(error: Error, context?: Record<string, string>): void {
const span = trace.getActiveSpan();
if (span) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
span.setAttribute('error.unexpected', true);
if (context) {
Object.entries(context).forEach(([key, value]) => {
span.setAttribute(`error.context.${key}`, value);
});
}
}
// Also log for non-trace-aware systems
console.error('Unexpected error', { error, context, traceId: span?.spanContext().traceId });
}
// Express error middleware with tracing
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
const span = trace.getActiveSpan();
if (span) {
span.recordException(err);
span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
span.setAttribute('http.status_code', err instanceof HttpError ? err.status : 500);
}
const status = err instanceof HttpError ? err.status : 500;
res.status(status).json({
error: err.message,
traceId: span?.spanContext().traceId, // Include in response for client-side correlation
});
});
recordException vs setStatus: Both are needed. recordException adds an event with the stack trace and error details. setStatus(ERROR) marks the span as failed in the trace viewer. Without setStatus, the span appears as successful even though an exception was recorded.
Exception event attributes (set automatically by recordException):
exception.type — error class nameexception.message — error messageexception.stacktrace — full stack traceError categorization: Add custom attributes to distinguish error types in dashboards:
span.setAttribute('error.category', 'business'); // vs 'infrastructure', 'validation', 'external'
span.setAttribute('error.retryable', true);
span.setAttribute('error.severity', 'critical'); // vs 'warning', 'info'
Trace ID in API responses: Include the trace ID in error responses so users or support teams can reference it:
{
"error": "Payment failed",
"traceId": "abc123def456",
"message": "Please contact support with this trace ID"
}
Error-based alerting from traces: Most observability backends support alerts on:
NullPointerException in production)https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-spans/