v0.5.0 — Deferred entity ID, tel.trace()
New features
Deferred entity ID on operate()
entity_id is now optional on tel.operate(). Open the trace immediately — before the entity is known — and call token.set_entity_id(id) once it is discovered mid-operation. All logs emitted before the call share the same otelTraceID, making them reachable from the Entity Inspector via the operation's trace link.
with tel.operate("stage-replication") as op:
replicas = await fetch_replicas(storage_id) # inside the trace
if not replicas:
return # no entity → passthrough trace
op.set_entity_id(dataset_name) # now linked to the entity
await deposit_work(replicas)If the span closes without entity_id, a WARNING is logged and the span is forwarded as a plain OTel trace — no entity_operations row is written.
tel.trace() — plain OTel spans
New method for infrastructure work (HTTP handlers, loops, daemons) where log correlation by trace ID is useful but no entity is being tracked. No need to import the raw OTel tracer separately.
with tel.trace("handle-request", attributes={"method": "POST"}):
with tel.child_span("validate"):
...
with tel.child_span("write-db"):
...child_span() calls inside a tel.trace() block automatically inherit the trace context. The herald forwards these spans unchanged.
token.set_entity_id(id)
New convenience method on Token. Equivalent to token.set_attribute("helix.entity.id", id) — both suppress the missing-entity-id warning.
Upgrading
All changes are backwards-compatible. Existing tel.operate(operation, entity_id=...) calls are unaffected.