Skip to content

Commit 8d2d890

Browse files
docs: document custom SpanProcessor filtering in A365 migration guide (#96)
* docs: document custom SpanProcessor filtering in A365 migration guide Add section showing how to use span_processors parameter to filter console/exporter output to only A365 observability scopes (invoke_agent, chat, execute_tool, output_messages). Addresses #86. * fix: use on_end filtering with wrapped processor per review feedback - Move span filtering from on_start to on_end where gen_ai.operation.name is finalized - Replace private span._context mutation with a wrapper SpanProcessor pattern - Set enable_console=False and manage ConsoleSpanExporter internally * Update span processor * Fix imports * Update * enable console exporter * Update api --------- Co-authored-by: Radhika Gupta <guptaradhika@microsoft.com>
1 parent 5a6cf33 commit 8d2d890

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

MIGRATION_A365.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,67 @@ use_microsoft_opentelemetry(
350350
When `enable_a365=False` (the default), all supported instrumentations
351351
remain enabled by default.
352352

353+
## Custom SpanProcessors — Filtering Console Output
354+
355+
By default, when `enable_console=True` (or any additional exporter is
356+
configured), **all** spans are exported — including framework-level spans
357+
(`agents.app.*`, `agents.turn.*`, `agents.connector.*`,
358+
`agents.authentication.*`). This can make local development noisy when you
359+
only care about the 4 A365 observability scopes:
360+
361+
- `invoke_agent`
362+
- `chat` (InferenceScope)
363+
- `execute_tool` (ExecuteToolScope)
364+
- `output_messages` (OutputScope)
365+
366+
To filter output to only A365 scopes, pass a custom `SpanProcessor` via the
367+
`span_processors` parameter:
368+
369+
```python
370+
from opentelemetry.trace import SpanContext, TraceFlags
371+
from opentelemetry.sdk.trace import SpanProcessor, ReadableSpan
372+
373+
from microsoft.opentelemetry import use_microsoft_opentelemetry
374+
375+
376+
class A365OnlyConsoleSpanProcessor(SpanProcessor):
377+
"""Send only A365 observability spans to the console exporter."""
378+
379+
A365_OPS = {"invoke_agent", "chat", "execute_tool", "output_messages"}
380+
381+
def on_start(self, span, parent_context=None):
382+
op = (span.attributes or {}).get("gen_ai.operation.name")
383+
if op not in self.A365_OPS:
384+
# Create new SpanContext with trace_flags = 0
385+
span._context = SpanContext(
386+
span.context.trace_id,
387+
span.context.span_id,
388+
span.context.is_remote,
389+
TraceFlags(0), # UNSAMPLED
390+
span.context.trace_state,
391+
)
392+
393+
def on_end(self, span: ReadableSpan):
394+
pass
395+
396+
def shutdown(self):
397+
pass
398+
399+
def force_flush(self, timeout_millis: int = 30000) -> bool:
400+
return True
401+
402+
403+
use_microsoft_opentelemetry(
404+
enable_a365=True,
405+
enable_console=True,
406+
a365_token_resolver=my_token_resolver,
407+
span_processors=[A365OnlyConsoleSpanProcessor()],
408+
)
409+
```
410+
411+
This leverages standard OpenTelemetry `SpanProcessor` APIs — you can adapt
412+
the filter logic to any criteria (span name, attributes, etc.).
413+
353414
## Environment Variable Mapping
354415

355416
| Old env var | New env var | Notes |

0 commit comments

Comments
 (0)