Typing activity span definition and new zero-code OTEL sample - #555
Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the Microsoft 365 Agents SDK for Python with OpenTelemetry support in two ways: (1) adding a new, explicitly named typing-indicator span in hosting-core, and (2) introducing two runnable OpenTelemetry sample projects (manual “quickstart” and “zero-code” auto-instrumentation) under test_samples/otel.
Changes:
- Added a new
agents.app.send_typingspan (TypingSendTyping) and wrappedTypingIndicator._send_typing()with it. - Added tests to validate typing span creation (unit + telemetry span wrapper coverage).
- Added OpenTelemetry sample projects:
quickstart(explicit SDK setup) andzero-code(env-driven auto-instrumentation), including configs, scripts, and a custom sampler plugin.
Reviewed changes
Copilot reviewed 21 out of 32 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/typing_indicator.py | Wrap typing-indicator send operation in a telemetry span. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/telemetry/spans.py | Add TypingSendTyping span wrapper. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/telemetry/constants.py | Add SPAN_SEND_TYPING span name constant. |
| tests/hosting_core/telemetry/test_app_spans.py | Add unit test validating the new TypingSendTyping span wrapper. |
| tests/hosting_core/app/test_typing_indicator.py | Add integration-style test validating span emission when sending typing. |
| test_samples/otel/requirements.txt | Remove old shared requirements file (samples now use per-project pyproject.toml). |
| test_samples/otel/quickstart/start_dashboard.ps1 | Script to run Aspire dashboard for local OTEL visualization. |
| test_samples/otel/quickstart/src/telemetry.py | Manual OpenTelemetry provider/exporter setup + instrumentation hooks. |
| test_samples/otel/quickstart/src/start_server.py | aiohttp server bootstrap for the quickstart sample. |
| test_samples/otel/quickstart/src/main.py | Quickstart entrypoint wiring telemetry + agent + server startup. |
| test_samples/otel/quickstart/src/get_user_info.py | Helper to call Microsoft Graph /me for the sample. |
| test_samples/otel/quickstart/src/card.py | Helper to build an Adaptive Card profile response. |
| test_samples/otel/quickstart/src/agent.py | Sample agent behavior tweaks (removal of stray return). |
| test_samples/otel/quickstart/src/init.py | Package marker for the quickstart sample. |
| test_samples/otel/quickstart/README.md | Quickstart sample setup/run documentation. |
| test_samples/otel/quickstart/pyproject.toml | Quickstart sample dependencies and local editable SDK wiring. |
| test_samples/otel/quickstart/env.TEMPLATE | Quickstart environment template for auth + OTEL endpoint/config. |
| test_samples/otel/zero-code/tests/test_typing_sampler.py | Tests for custom sampler dropping typing spans/descendants. |
| test_samples/otel/zero-code/start_dashboard.ps1 | Script to run Aspire dashboard for local OTEL visualization. |
| test_samples/otel/zero-code/start_agent.ps1 | Script to run the agent via opentelemetry-instrument. |
| test_samples/otel/zero-code/src/typing_sampler.py | Custom sampler plugin to drop typing spans. |
| test_samples/otel/zero-code/src/start_server.py | aiohttp server bootstrap for the zero-code sample. |
| test_samples/otel/zero-code/src/main.py | Zero-code entrypoint wiring agent + server startup. |
| test_samples/otel/zero-code/src/get_user_info.py | Helper to call Microsoft Graph /me for the sample. |
| test_samples/otel/zero-code/src/card.py | Helper to build an Adaptive Card profile response. |
| test_samples/otel/zero-code/src/agent.py | Zero-code sample agent implementation (behavior + auth flow). |
| test_samples/otel/zero-code/src/init.py | Package marker for the zero-code sample. |
| test_samples/otel/zero-code/README.md | Zero-code sample setup/run documentation (env-based OTEL config). |
| test_samples/otel/zero-code/pyproject.toml | Zero-code sample dependencies + sampler entry point registration. |
| test_samples/otel/zero-code/env.TEMPLATE | Zero-code environment template for auth + OTEL distro config. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…into users/robrandao/typing-span
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 32 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
test_samples/otel/zero-code/env.TEMPLATE:23
- The template enables capturing all HTTP headers (regex ".*") for both server and client requests/responses. This can export secrets like Authorization/Cookie headers into telemetry backends. Safer default is to leave header capture disabled and let users opt in when debugging.
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE=".*"
…into users/robrandao/typing-span
…osoft/Agents-for-python into users/robrandao/typing-span
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 32 changed files in this pull request and generated no new comments.
Suppressed comments (3)
tests/hosting_core/app/test_typing_indicator.py:18
test_telemetryis imported but never used in this module; importingtest_exporteris sufficient to register the fixtures and avoids an unused-import lint warning.
test_samples/otel/zero-code/src/typing_sampler.py:29should_sampledeclaresattributes: Attributes = None, but the SDK passesNoneand type checkers expect the parameter to be optional. UsingAttributes | Nonematches the OpenTelemetry sampler signature and avoids incorrect type hints.
attributes: Attributes = None,
test_samples/otel/zero-code/env.TEMPLATE:23
- These settings capture all HTTP headers (".*"), which can export secrets (e.g.,
Authorization,Cookie) into your OTLP backend. Consider using a conservative allowlist by default so the template is safer out-of-the-box.
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE=".*"
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 32 changed files in this pull request and generated 2 comments.
Suppressed comments (3)
test_samples/otel/zero-code/src/typing_sampler.py:31
should_sampledeclaresattributes: Attributes = None, which is an invalid type/default combination. This should beAttributes | None = Noneto match the OpenTelemetry Sampler signature and avoid type-checker errors.
name: str,
kind: SpanKind | None = None,
attributes: Attributes = None,
links: Sequence[Link] | None = None,
trace_state: TraceState | None = None,
test_samples/otel/zero-code/env.TEMPLATE:23
- These defaults capture all HTTP request/response headers into telemetry. That can easily leak secrets (e.g., Authorization/Cookie) into logs/traces when exporting to OTLP. Safer default is to keep header capture disabled and let users opt in to specific headers.
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE=".*"
tests/hosting_core/app/test_typing_indicator.py:18
test_telemetryis imported but never referenced in this test module (the tests only requesttest_exporter). Removing the unused import avoids lint noise and keeps the test focused.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 32 changed files in this pull request and generated no new comments.
Suppressed comments (4)
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/telemetry/constants.py:9
- SPAN_SEND_TYPING’s value is "agents.app.typing_indicator", which doesn’t match the constant name and contradicts the zero-code sample docs (which reference "agents.app.send_typing"). This makes it easy for downstream tooling (e.g., samplers/filters) to target the wrong span name.
SPAN_DOWNLOAD_FILES = "agents.app.download_files"
SPAN_SEND_TYPING = "agents.app.typing_indicator"
test_samples/otel/zero-code/env.TEMPLATE:23
- These settings capture all HTTP request/response headers (".*"). That can export secrets like Authorization/Bearer tokens and cookies into telemetry backends, even in sample code. Safer defaults should avoid capturing everything; users can opt-in to specific headers when debugging.
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE=".*"
tests/hosting_core/app/test_typing_indicator.py:18
test_telemetryis imported but never used in this module, which adds noise and will be flagged by linters. If the fixture is required, add it as a test parameter; otherwise remove the import.
test_samples/otel/zero-code/src/typing_sampler.py:32attributesis annotated asAttributesbut defaults toNone. This is inconsistent with the type and will trip type checkers; it should beAttributes | NonewhenNoneis a valid value.
name: str,
kind: SpanKind | None = None,
attributes: Attributes = None,
links: Sequence[Link] | None = None,
trace_state: TraceState | None = None,
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 32 changed files in this pull request and generated no new comments.
Suppressed comments (3)
test_samples/otel/zero-code/env.TEMPLATE:24
- The env template enables capturing all HTTP request/response headers (".*"), which can export secrets/PII (e.g., Authorization bearer tokens, cookies) into your telemetry backend. For a sample template, this should be disabled by default or restricted to an explicit safe allow-list.
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE=".*"
test_samples/otel/zero-code/src/typing_sampler.py:32
should_sample()declaresattributes: Attributes = None, but the OpenTelemetry SDK passesattributesas optional. Update the type annotation toAttributes | Noneto match the SDK interface and avoid type-checker warnings.
kind: SpanKind | None = None,
attributes: Attributes = None,
links: Sequence[Link] | None = None,
trace_state: TraceState | None = None,
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/telemetry/constants.py:9
SPAN_SEND_TYPINGis described as a “send typing” span, but the actual span name string isagents.app.typing_indicator. Adding an explicitly-named constant for the string (and aliasing) makes the intent clearer and avoids confusion when referencing span names externally.
SPAN_SEND_TYPING = "agents.app.typing_indicator"
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 33 changed files in this pull request and generated 1 comment.
Suppressed comments (3)
test_samples/otel/zero-code/src/typing_sampler.py:30
- DropTypingSampler.should_sample() types the attributes parameter as Attributes but defaults it to None. This is inconsistent with the method's effective contract (attributes may be absent) and can confuse type checkers/readers.
attributes: Attributes = None,
tests/hosting_core/app/test_typing_indicator.py:18
- These telemetry fixtures are imported to register pytest fixtures, but the file is missing the standard "# noqa: F401" marker used elsewhere in the test suite for fixture-only imports. Without it, flake8/pyflakes will report unused imports.
test_samples/otel/zero-code/env.TEMPLATE:23 - The template enables capturing all HTTP request/response headers (".*"), which can export secrets/PII (e.g., Authorization) into telemetry. Defaulting to a minimal safe set (or leaving unset) is safer for a sample template.
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST=".*"
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE=".*"
This pull request updates the telemetry span logic for sending typing indicators, making the span more informative by including context-specific attributes. The main change is that the
TypingSendTypingspan now requires aturn_contextand records additional metadata, improving observability and traceability. Related tests have also been updated and expanded.Telemetry improvements:
TypingSendTypingto require aturn_contextparameter and to recordACTIVITY_CHANNEL_IDandCONVERSATION_IDas span attributes, providing richer telemetry information.typing_indicator.pyto pass the appropriate context toTypingSendTyping.Testing enhancements:
TypingSendTypingspans, and added a new test to verify that the correct attributes are set on the span.Code cleanup:
_Routeinspans.py.