Skip to content

Commit 5f9559e

Browse files
committed
Mark telemetry as experimental
1 parent 0ec8a42 commit 5f9559e

22 files changed

Lines changed: 291 additions & 215 deletions

File tree

examples/agents/telemetry.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
"""Agent run with telemetry: console adapter + a custom span in a tool.
22
3-
For an out-of-process viewer, run ``python -m ai.telemetry.utils.viewer``
4-
and see ``ai/telemetry/utils/viewer.py`` for the otel exporter setup.
3+
For an out-of-process viewer, run
4+
``python -m ai.experimental_telemetry.utils.viewer`` and see
5+
``ai/experimental_telemetry/utils/viewer.py`` for the otel exporter
6+
setup.
57
"""
68

79
import asyncio
810

911
import ai
10-
from ai.telemetry.utils import console
12+
from ai.experimental_telemetry.utils import console
1113

1214

1315
@ai.tool
1416
async def get_weather(city: str) -> str:
1517
"""Get current weather for a city."""
16-
async with ai.telemetry.span("lookup", city=city) as span:
18+
async with ai.experimental_telemetry.span("lookup", city=city) as span:
1719
await asyncio.sleep(0.1)
1820
span.set(source="cache")
1921
return f"Sunny, 72F in {city}"
2022

2123

2224
async def main() -> None:
23-
ai.telemetry.register(console.ConsoleAdapter())
25+
ai.experimental_telemetry.register(console.ConsoleAdapter())
2426

2527
model = ai.get_model("anthropic/claude-sonnet-4.6")
2628
my_agent = ai.Agent(tools=[get_weather])

src/ai/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from . import errors, models, providers, telemetry, ui, util
1+
from . import errors, experimental_telemetry, models, providers, ui, util
22
from .agents import (
33
Agent,
44
AgentTool,
@@ -181,6 +181,7 @@
181181
"deferred_tool_result",
182182
"errors",
183183
"events",
184+
"experimental_telemetry",
184185
"file_part",
185186
"get_hook_registry",
186187
"get_model",
@@ -195,7 +196,6 @@
195196
"resolve_hook",
196197
"stream",
197198
"system_message",
198-
"telemetry",
199199
"text_part",
200200
"thinking",
201201
"tool",

src/ai/agents/agent.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
# Use the typing_extensions backport so this works on 3.12 too.
3636
from typing_extensions import TypeVar
3737

38-
from .. import models, telemetry, type_utils, types, util
38+
from .. import experimental_telemetry as telemetry
39+
from .. import models, type_utils, types, util
3940
from ..types import builders
4041
from ..types import events as events_
4142
from ..types.messages import MessageBundle

src/ai/agents/hooks.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626

2727
import pydantic
2828

29-
from .. import telemetry, types, util
29+
from .. import experimental_telemetry as telemetry
30+
from .. import types, util
3031
from ..types import messages as messages_
3132
from . import _middleware as middleware_
3233
from . import runtime as runtime_
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Telemetry: spans, adapters, and the ambient current span.
22
3+
Experimental: not part of the stable API, may change or be removed.
4+
35
See :mod:`.span` for the full story.
46
"""
57

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
"""OpenTelemetry adapter: forwards spans to an otel tracer.
22
3+
Experimental: not part of the stable API, may change or be removed.
4+
35
::
46
5-
from ai.telemetry import otel
7+
from ai.experimental_telemetry import otel
68
otel.install() # uses the global TracerProvider
79
810
Span names and attributes follow the ``gen_ai`` semantic conventions,
@@ -22,7 +24,8 @@
2224
import json
2325
from typing import TYPE_CHECKING, Any
2426

25-
from .. import errors, telemetry
27+
from .. import errors
28+
from .. import experimental_telemetry as telemetry
2629

2730
try:
2831
from opentelemetry import context as otel_context
Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
"""Telemetry: spans, adapters, and the ambient current span.
22
3+
Experimental: not part of the stable API, may change or be removed.
4+
35
:class:`Span` is a record of work done by the application. It carries
46
start, end, parent, and typed data.
57
68
Same API is used to instrument the framework and define custom spans::
79
8-
async with ai.telemetry.span("retrieval", query=q) as sp:
10+
async with ai.experimental_telemetry.span("retrieval", query=q) as sp:
911
docs = await search(q)
1012
sp.set(count=len(docs))
1113
@@ -19,7 +21,7 @@ async def on_span_start(self, span): ...
1921
async def on_span_end(self, span): ...
2022
async def on_span_event(self, span, event): ...
2123
22-
ai.telemetry.register(MyAdapter())
24+
ai.experimental_telemetry.register(MyAdapter())
2325
2426
Adapters dispatch on the type of ``span.data``. An adapter that crashes
2527
is logged and skipped, it never kills the run.
@@ -97,13 +99,13 @@ def use_clock(now_ns: Callable[[], int]) -> Iterator[None]:
9799
used to plug an approved clock function in durable execution
98100
settings::
99101
100-
with ai.telemetry.use_clock(workflow.time_ns):
102+
with ai.experimental_telemetry.use_clock(workflow.time_ns):
101103
... # spans opened here read time from workflow.time_ns
102104
103105
This can also be used as a decorator on both sync and async
104106
functions::
105107
106-
@ai.telemetry.use_clock(clock.time_ns)
108+
@ai.experimental_telemetry.use_clock(clock.time_ns)
107109
async def run(...):
108110
...
109111
"""
@@ -131,7 +133,8 @@ class RetrievalSpanData:
131133
132134
span_name: ClassVar[str] = "retrieval"
133135
134-
async with ai.telemetry.span(RetrievalSpanData(query=q)) as sp:
136+
data = RetrievalSpanData(query=q)
137+
async with ai.experimental_telemetry.span(data) as sp:
135138
docs = await search(q)
136139
sp.data.count = len(docs) # typed
137140
@@ -289,12 +292,12 @@ class SpanRef(pydantic.BaseModel):
289292
(``model_dump`` / ``model_validate``); restore by opening a span
290293
with ``parent=ref`` on the other side::
291294
292-
ref = ai.telemetry.current_ref()
295+
ref = ai.experimental_telemetry.current_ref()
293296
job = {"task": task, "telemetry": ref.model_dump()}
294297
295298
# elsewhere:
296-
ref = ai.telemetry.SpanRef.model_validate(job["telemetry"])
297-
async with ai.telemetry.span("pickup", parent=ref):
299+
ref = ai.experimental_telemetry.SpanRef.model_validate(job["telemetry"])
300+
async with ai.experimental_telemetry.span("pickup", parent=ref):
298301
... # everything inside continues the original trace
299302
300303
``sampled`` is carried so refs round-trip sampling decisions
@@ -685,7 +688,7 @@ async def vendor(span):
685688
v.log_event(ev.name, timestamp=ev.time_ns)
686689
v.update(output=span.data) # span end
687690
688-
ai.telemetry.register(vendor)
691+
ai.experimental_telemetry.register(vendor)
689692
690693
- A span that ends with an error is thrown into the generator at
691694
the ``yield``, so the vendor context manager sees the failure.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""Debugging helpers: the console adapter and the terminal trace viewer.
2+
3+
Experimental: not part of the stable API, may change or be removed.
4+
5+
Import the submodules directly::
6+
7+
from ai.experimental_telemetry.utils import console
8+
"""

src/ai/telemetry/utils/console.py renamed to src/ai/experimental_telemetry/utils/console.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
"""Console adapter: prints spans to a terminal as they happen.
22
3+
Experimental: not part of the stable API, may change or be removed.
4+
35
Register it like any adapter::
46
5-
from ai.telemetry.utils import console
6-
ai.telemetry.register(console.ConsoleAdapter())
7+
from ai.experimental_telemetry.utils import console
8+
ai.experimental_telemetry.register(console.ConsoleAdapter())
79
810
Prints one ``▸`` line when a span starts (so long runs are visible
911
live) and, when a trace's root span ends, the whole tree with
@@ -15,7 +17,7 @@
1517
import sys
1618
from typing import TYPE_CHECKING
1719

18-
from ... import telemetry
20+
from ... import experimental_telemetry as telemetry
1921

2022
if TYPE_CHECKING:
2123
from typing import TextIO

src/ai/telemetry/utils/viewer.py renamed to src/ai/experimental_telemetry/utils/viewer.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
"""Terminal trace viewer: an OTLP/HTTP server that prints span trees.
22
3+
Experimental: not part of the stable API, may change or be removed.
4+
35
Run::
46
5-
python -m ai.telemetry.utils.viewer [--port 4318]
7+
python -m ai.experimental_telemetry.utils.viewer [--port 4318]
68
79
and point any OTLP/HTTP exporter at ``http://127.0.0.1:4318/v1/traces``::
810
@@ -18,7 +20,7 @@
1820
BatchSpanProcessor(OTLPSpanExporter("http://127.0.0.1:4318/v1/traces"))
1921
)
2022
trace.set_tracer_provider(provider)
21-
ai.telemetry.otel.install()
23+
ai.experimental_telemetry.otel.install()
2224
2325
Spans are buffered per trace, and the tree is printed when the trace's
2426
root span arrives (roots end — and therefore export — last).

0 commit comments

Comments
 (0)