Integrate Events, Exceptions, and Status into Spans
OpenTelemetry (OTEL) provides support for adding Events, Exceptions, and Status into spans.
About
Spans capture timing and attributes, but they do not automatically record what happened during execution or whether it succeeded. Events, exceptions, and status fill that gap.
- Events: Timestamped messages that mark key moments during a span, similar to log lines.
- Status: Marks the span as OK or ERROR so failures are visible in the dashboard and alerting.
- Exceptions: Attaches full error details (type, message, stack trace) to the span for debugging.
When to use
- Mark key moments during execution: Add events at important steps (e.g. “cache miss”, “retrying request”) to understand what happened inside a span without creating child spans.
- Surface errors in traces: Set an ERROR status on a span so failures are immediately visible when scanning traces in the dashboard.
- Capture full failure context: Record exceptions alongside status so the error type, message, and stack trace are available for debugging.
How to
Add events to a span
Events mark specific moments during a span’s execution. Use them to log readable messages at key points in your code.
from opentelemetry import trace
current_span = trace.get_current_span()
if current_span.is_recording():
current_span.add_event("Attempting the operation!")
# Execute the operation
# For example: result = some_operation()
current_span.add_event("Operation completed!")import { trace, context } from "@opentelemetry/api";
const currentSpan = trace.getSpan(context.active());
if (currentSpan) {
currentSpan.addEvent("Attempting the operation!");
// Execute the operation
// For example: const result = someOperation();
currentSpan.addEvent("Operation completed!");
} Define span status
Set the span status to indicate success or failure of the code executed within the span.
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
current_span = trace.get_current_span()
if current_span.is_recording():
try:
# operation that might fail
# For example: risky_operation()
# If successful, you might explicitly set OK status, though it's often the default.
# current_span.set_status(Status(StatusCode.OK))
pass
except:
current_span.set_status(Status(StatusCode.ERROR, "An error occurred"))import { trace, context, SpanStatusCode } from "@opentelemetry/api";
const currentSpan = trace.getSpan(context.active());
if (currentSpan) {
try {
// operation that might fail
// For example: riskyOperation();
// If successful, you might explicitly set OK status, though it's often the default.
// currentSpan.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
currentSpan.setStatus({ code: SpanStatusCode.ERROR, message: "An error occurred" });
}
} Log exceptions in spans
Record exceptions when they occur, alongside setting the span status, to get full failure context in the trace.
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
current_span = trace.get_current_span()
if current_span.is_recording():
try:
# operation that might fail
# For example: result = 1 / 0
pass
# Consider catching a more specific exception in your code
except Exception as ex:
current_span.set_status(Status(StatusCode.ERROR, str(ex)))
current_span.record_exception(ex)import { trace, context, SpanStatusCode } from "@opentelemetry/api";
const currentSpan = trace.getSpan(context.active());
if (currentSpan) {
try {
// operation that might fail
// For example:
// const riskyCall = () => { throw new Error("Something went wrong!"); };
// riskyCall();
} catch (error) {
// Ensure the error is an instance of Error for proper recording
if (error instanceof Error) {
currentSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
currentSpan.recordException(error);
} else {
// Handle cases where the caught object is not an Error instance
const errorMessage = typeof error === 'string' ? error : 'Unknown error during operation';
currentSpan.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
currentSpan.recordException(errorMessage);
}
}
} Key concepts
add_event()/addEvent():Attaches a timestamped message to the span at the moment it’s called. Useful for logging discrete actions without creating a new span.set_status()/setStatus():Sets the span’s status toOKorERROR. AnERRORstatus with a message surfaces the failure in trace UIs and alerting.record_exception()/recordException():Attaches full exception details (type, message, stack trace) as a span event. Always pair withset_status(ERROR)for complete failure context.is_recording():Guards against no-op spans. Always check before setting attributes or events on a span retrieved fromget_current_span().
Next Steps
Set Up Tracing
Register a tracer provider and add instrumentation.
Add Attributes & Metadata
Attach custom data to spans for filtering and evals.
Get Current Span
Access the active span or tracer at any point in your code.
Instrument with traceAI Helpers
Use FITracer decorators and context managers for typed spans.