Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
SPAN_BEFORE_TURN = "agents.app.before_turn"
SPAN_AFTER_TURN = "agents.app.after_turn"
SPAN_DOWNLOAD_FILES = "agents.app.download_files"
SPAN_SEND_TYPING = "agents.app.send_typing"

METRIC_TURN_COUNT = "agents.turn.count"
METRIC_TURN_ERROR_COUNT = "agents.turn.error.count"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,11 @@ def _get_attributes(self) -> AttributeMap:
self._turn_context.activity.attachments or []
),
}


class TypingSendTyping(SimpleSpanWrapper):
"""Span for the logic related to sending typing indicators in the TypingIndicator."""

def __init__(self):
"""Initializes the TypingSendTyping SpanWrapper."""
super().__init__(constants.SPAN_SEND_TYPING)
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from microsoft_agents.hosting.core import TurnContext
from microsoft_agents.activity import Activity, ActivityTypes, Channels, EntityTypes

from .telemetry import spans

logger = logging.getLogger(__name__)

DEFAULT_INITIAL_DELAY_MS = 500
Expand Down Expand Up @@ -133,11 +135,14 @@ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:

async def _send_typing(self) -> None:
"""Sends a single typing activity via the adapter, bypassing middleware."""
ref = self._context.activity.get_conversation_reference()
typing_activity = TurnContext.apply_conversation_reference(
Activity(type=ActivityTypes.typing), ref
)
await self._context.adapter.send_activities(self._context, [typing_activity])
with spans.TypingSendTyping():
ref = self._context.activity.get_conversation_reference()
typing_activity = TurnContext.apply_conversation_reference(
Activity(type=ActivityTypes.typing), ref
)
await self._context.adapter.send_activities(
self._context, [typing_activity]
)

async def _run(self) -> None:
"""Sends typing indicators at regular intervals after an initial delay."""
Expand Down
37 changes: 37 additions & 0 deletions test_samples/otel/quickstart/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# OpenTelemetry quickstart sample

This sample configures OpenTelemetry providers and library instrumentation in
application code. See `../zero-code` for the equivalent agent using
OpenTelemetry auto-instrumentation and environment configuration.

## Set up

From this directory, create the project environment and copy the configuration
template:

```powershell
uv sync
Copy-Item env.TEMPLATE .env
```

`uv sync` installs the Microsoft Agents packages in editable mode from this
repository's `libraries/` directory, so local SDK changes are immediately
available to the sample. Set the agent registration and OAuth connection values
in `.env`.

## Run

Start the local Aspire dashboard:

```powershell
.\start_dashboard.ps1
```

In another terminal, start the agent:

```powershell
uv run python -m src.main
```

Open the dashboard at <http://localhost:18888>. The agent listens at
<http://localhost:3978/api/messages>.
35 changes: 35 additions & 0 deletions test_samples/otel/quickstart/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"

[project]
name = "otel-quickstart-sample"
version = "1.0.0"
description = "Microsoft 365 Agents SDK OpenTelemetry quickstart sample"
requires-python = ">=3.10"
dependencies = [
"aiohttp",
"microsoft-agents-activity",
"microsoft-agents-authentication-msal",
"microsoft-agents-hosting-aiohttp",
"microsoft-agents-hosting-core",
"opentelemetry-api",
"opentelemetry-exporter-otlp",
"opentelemetry-instrumentation",
"opentelemetry-instrumentation-aiohttp-client",
"opentelemetry-instrumentation-aiohttp-server",
"opentelemetry-instrumentation-logging",
"opentelemetry-instrumentation-requests",
"opentelemetry-sdk",
"python-dotenv",
"requests",
]

[tool.setuptools]
packages = ["src"]

[tool.uv.sources]
microsoft-agents-activity = { path = "../../../libraries/microsoft-agents-activity", editable = true }
microsoft-agents-authentication-msal = { path = "../../../libraries/microsoft-agents-authentication-msal", editable = true }
microsoft-agents-hosting-aiohttp = { path = "../../../libraries/microsoft-agents-hosting-aiohttp", editable = true }
microsoft-agents-hosting-core = { path = "../../../libraries/microsoft-agents-hosting-core", editable = true }
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ async def on_members_added(context: TurnContext, _state: TurnState):
"Welcome to the empty agent! "
"This agent is designed to be a starting point for your own agent development."
)
return True


@AGENT_APP.message("/logout")
Expand Down
Loading