Integrate Events, Exceptions, and Status into Spans
OpenTelemetry (OTEL) provides support for adding Events, Exceptions, and Status into spans.
What it is
Events, Exceptions, and Status are three OpenTelemetry primitives for enriching spans with runtime signal:
- Events — Readable messages that mark significant moments during a span’s lifecycle, similar to basic logs.
- Status — A success or failure indicator set on the span to surface errors in distributed traces.
- Exceptions — Detailed exception records attached to a span alongside a status update, for comprehensive failure debugging.
Use cases
- Event logging — Capture significant actions in your application’s workflow at specific moments during span execution.
- Error surfacing — Assign an error status to a span when an exception arises so it’s visible when identifying and troubleshooting issues in distributed systems.
- Exception recording — Log detailed exception information alongside span status to get a full view of failures 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.add_event("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().
What you can do next
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.