Lesson 8 / 25
Manual Spans and Attributes
Instrument business logic.
Tracer, spans and context managers
Get a tracer from the API, then start spans around important operations. In Python, with tracer.start_as_current_span("name") creates a child of the current span and ends it automatically. Add attributes describing business context (order value, item count, customer tier, but not personal data), record exceptions and set status. Use clear, low-cardinality span names such as price_quote rather than names containing IDs.
A manual span in Python
Using the OpenTelemetry API (a sketch; assumes the SDK is configured by zero-code instrumentation or at start-up).
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
tracer = trace.get_tracer("orders.pricing")
def quote_price(cart):
with tracer.start_as_current_span("price_quote") as span:
span.set_attribute("app.cart.items", len(cart.items))
span.set_attribute("app.customer.tier", cart.customer_tier)
try:
total = apply_discounts(cart) # child spans created inside are nested
span.set_attribute("app.quote.total", float(total))
return total
except Exception as exc:
span.record_exception(exc)
span.set_status(Status(StatusCode.ERROR, "pricing failed"))
raisePut IDs in attributes, not span names
Span names are grouped for analysis; "GET /orders/{id}" works, "GET /orders/12345" creates endless distinct names.
Quick check: What does start_as_current_span do?
- Sends a metric
- Creates a new trace every time
- Starts a span, makes it the current (parent) context, and ends it when the block exits
- Deletes the parent span
Answer
Starts a span, makes it the current (parent) context, and ends it when the block exits — Children nest automatically.