Unomiq uses the unomiq_unit span attribute to link traces to a unit — a logical entity in your application such as a customer ID, app ID, agent ID, or tenant ID. This allows you to view and filter traces by unit in the Unomiq dashboard or Unomiq Engine API.
You can also optionally set unomiq_parent_unit to create a hierarchy of entities, such as linking an app to the organization it belongs to.
This guide shows how to attach the unomiq_unit and unomiq_parent_unit attributes to your spans using the OpenTelemetry SDK.
What is a Unit?
A unit represents the entity that a trace belongs to. Common examples:
| Use case | Unit value |
|---|
| Multi-tenant SaaS | Tenant ID or customer ID |
| Agentic System | Agent ID |
| Per-user tracking | User ID |
| Per-application tracking | Application ID |
The value should be a stable identifier that uniquely represents the entity across requests.
You can optionally set unomiq_parent_unit alongside unomiq_unit to express a parent-child relationship between entities. For example, in a multi-tenant SaaS application you might set unomiq_unit to an app ID and unomiq_parent_unit to the tenant or organization that app belongs to.
Setting unomiq_unit on Individual Spans
The most straightforward approach is to set the attribute directly on a span:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("process-request") as span:
span.set_attribute("unomiq_unit", user_id)
span.set_attribute("unomiq_parent_unit", tenant_id) # optional: parent entity
# ... your code here
unomiq_parent_unit is optional. Set it when you want to place the unit within a broader entity hierarchy.
This works with both manual and automatic instrumentation — as long as you have access to a span, you can set the attribute.
Setting unomiq_unit Automatically with a SpanProcessor
To attach the unit to every span without modifying each call site, use a custom SpanProcessor. This is useful when the unit is available from a request context (e.g., an HTTP header, JWT claim, or path parameter).
from opentelemetry.sdk.trace import SpanProcessor
class UnitSpanProcessor(SpanProcessor):
"""Attaches unomiq_unit to every span from a context resolver."""
def __init__(self, resolve_unit):
"""
Args:
resolve_unit: A callable that returns the current unit value,
or None if no unit is available.
"""
self._resolve_unit = resolve_unit
def on_start(self, span, parent_context=None):
unit = self._resolve_unit()
if unit:
span.set_attribute("unomiq_unit", unit)
def on_end(self, span):
pass
def shutdown(self):
pass
def force_flush(self, timeout_millis=None):
pass
Example: Resolving Unit from a Flask Request
from flask import request, Flask
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
app = Flask(__name__)
def resolve_unit_from_request():
"""Extract the unit from the current request context."""
try:
# Option 1: From a request header
return request.headers.get("X-Customer-Id")
# Option 2: From a JWT claim (after auth middleware)
# return g.current_user.get("tenant_id")
# Option 3: From a path parameter
# return request.view_args.get("customer_id")
except RuntimeError:
# Outside of a request context
return None
# Register the processor with the tracer provider
provider = TracerProvider()
provider.add_span_processor(UnitSpanProcessor(resolve_unit_from_request))
trace.set_tracer_provider(provider)
Example: Resolving Unit from Django
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
# Use threading.local or contextvars to store the unit per-request
import contextvars
_current_unit = contextvars.ContextVar("current_unit", default=None)
# In your Django middleware:
class UnitMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
_current_unit.set(request.headers.get("X-Customer-Id"))
return self.get_response(request)
# Register the processor
provider = TracerProvider()
provider.add_span_processor(UnitSpanProcessor(lambda: _current_unit.get()))
trace.set_tracer_provider(provider)
Summary
| Method | When to use |
|---|
span.set_attribute() | One-off spans where you have the unit value at hand |
UnitSpanProcessor | Automatically attach unit to all spans from request context |
unomiq_unit must be set as a span attribute. Resource attributes and collector-level processors are not supported for this field.