add Custom Trace Attributes to extend observability (#708)

* add custom trace attributes

* refactor: prefix custom trace attributes and update schema handlers tests configs

* refactor: rename custom_attribute_prefixes to span_attribute_header_prefixes in configuration and related handlers

* docs: add section on custom span attributes

* refactor: update tracing configuration to use span attributes and adjust related handlers

* docs: custom span attributes section to include static attributes and clarify configuration

* add custom trace attributes

* refactor: prefix custom trace attributes and update schema handlers tests configs

* refactor: rename custom_attribute_prefixes to span_attribute_header_prefixes in configuration and related handlers

* docs: add section on custom span attributes

* refactor: update tracing configuration to use span attributes and adjust related handlers

* docs: custom span attributes section to include static attributes and clarify configuration

* refactor: remove TraceCollector usage and enhance logging with structured attributes

* refactor: custom trace attribute extraction to improve clarity

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Musa 2026-02-25 16:27:20 -08:00 committed by GitHub
parent 70ad56a258
commit 2bde21ff57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 353 additions and 9 deletions

View file

@ -142,6 +142,109 @@ In your observability platform (Jaeger, Grafana Tempo, Datadog, etc.), filter tr
For complete details on all available signals, detection methods, and best practices, see the :doc:`../../concepts/signals` guide.
Custom Span Attributes
-------------------------------------------
Plano can automatically attach **custom span attributes** derived from request headers and **static** attributes
defined in configuration. This lets you stamp
traces with identifiers like workspace, tenant, or user IDs without changing application code or adding
custom instrumentation.
**Why This Is Useful**
- **Tenant-aware debugging**: Filter traces by ``workspace.id`` or ``tenant.id``.
- **Customer-specific visibility**: Attribute performance or errors to a specific customer.
- **Low overhead**: No code changes in agents or clients—just headers.
How It Works
~~~~~~~~~~~~
You configure one or more header prefixes. Any incoming HTTP header whose name starts with one of these
prefixes is captured as a span attribute. You can also provide static attributes that are always injected.
- The **prefix is only for matching**, not the resulting attribute key.
- The attribute key is the header name **with the prefix removed**, then hyphens converted to dots.
.. note::
Custom span attributes are attached to LLM spans when handling ``/v1/...`` requests via ``llm_chat``. For orchestrator requests to ``/agents/...``,
these attributes are added to both the orchestrator selection span and to each agent span created by ``agent_chat``.
**Example**
Configured prefix::
tracing:
span_attributes:
header_prefixes:
- x-katanemo-
Incoming headers::
X-Katanemo-Workspace-Id: ws_123
X-Katanemo-Tenant-Id: ten_456
Resulting span attributes::
workspace.id = "ws_123"
tenant.id = "ten_456"
Configuration
~~~~~~~~~~~~~
Add the prefix list under ``tracing`` in your config:
.. code-block:: yaml
tracing:
random_sampling: 100
span_attributes:
header_prefixes:
- x-katanemo-
static:
environment: production
service.version: "1.0.0"
Static attributes are always injected alongside any header-derived attributes. If a header-derived
attribute key matches a static key, the header value overrides the static value.
You can provide multiple prefixes:
.. code-block:: yaml
tracing:
span_attributes:
header_prefixes:
- x-katanemo-
- x-tenant-
static:
environment: production
service.version: "1.0.0"
Notes and Examples
~~~~~~~~~~~~~~~~~~
- **Prefix must match exactly**: ``katanemo-`` does not match ``x-katanemo-`` headers.
- **Trailing dash is recommended**: Without it, ``x-katanemo`` would also match ``x-katanemo-foo`` and
``x-katanemofoo``.
- **Keys are always strings**: Values are captured as string attributes.
**Prefix mismatch example**
Config::
tracing:
span_attributes:
header_prefixes:
- x-katanemo-
Request headers::
X-Other-User-Id: usr_999
Result: no attributes are captured from ``X-Other-User-Id``.
Benefits of Using ``Traceparent`` Headers
-----------------------------------------