|
1 | 1 | # GenAI Instrumentation — Agent and Contributor Guidelines |
2 | 2 |
|
3 | | -Instrumentation packages here wrap specific libraries (OpenAI, Google GenAI, etc.) and bridge |
4 | | -them to the shared telemetry layer in `util/opentelemetry-util-genai`. |
| 3 | +**GenAI instrumentations are no longer developed in this repository.** They live in |
| 4 | +[opentelemetry-python-genai](https://github.com/open-telemetry/opentelemetry-python-genai), |
| 5 | +which is where new instrumentations, features, and bug fixes go. |
5 | 6 |
|
6 | | -These rules are additive to the shared instrumentation rules in the repo-root |
7 | | -[AGENTS.md](../AGENTS.md). |
| 7 | +The packages still present under this directory are deprecated, receive security patches only, |
| 8 | +and will be removed from this repository in the future. |
8 | 9 |
|
9 | | -## 0. Instrumentations Maintained Elsewhere |
10 | | - |
11 | | -Development and releases for these GenAI instrumentations have moved to the |
12 | | -[opentelemetry-python-genai](https://github.com/open-telemetry/opentelemetry-python-genai) |
13 | | -repository. Direct new development and fixes there, not here: |
14 | | - |
15 | | -- `opentelemetry-instrumentation-genai-anthropic` (anthropic) |
16 | | -- `opentelemetry-instrumentation-genai-claude-agent-sdk` (claude-agent-sdk) |
17 | | -- `opentelemetry-instrumentation-genai-langchain` (langchain) |
18 | | -- `opentelemetry-instrumentation-genai-weaviate-client` (weaviate-client) |
19 | | -- `opentelemetry-instrumentation-genai-openai` (openai; only security patches in this repo, as `opentelemetry-instrumentation-openai-v2`) |
20 | | -- `opentelemetry-instrumentation-genai-openai-agents` (openai-agents; only security patches in this repo, as `opentelemetry-instrumentation-openai-agents-v2`) |
21 | | - |
22 | | -Do not add, modify, or attempt to fix these instrumentations in this repository beyond security |
23 | | -patches for the packages that still live here. Direct any other changes to the |
| 10 | +Do not add, modify, or attempt to fix instrumentations here. Send any change to the |
24 | 11 | `opentelemetry-python-genai` repo instead. |
25 | | - |
26 | | -## 1. Instrumentation Layer Boundary |
27 | | - |
28 | | -Do not call OpenTelemetry APIs (`tracer`, `meter`, `span`, event APIs) directly. |
29 | | -Always go through `TelemetryHandler` and the invocation objects it returns. |
30 | | - |
31 | | -This layer is responsible only for: |
32 | | - |
33 | | -- Patching the library |
34 | | -- Parsing library-specific input/output into invocation fields |
35 | | - |
36 | | -Everything else (span creation, metric recording, event emission, context propagation) |
37 | | -belongs in `util/opentelemetry-util-genai`. |
38 | | - |
39 | | -For GenAI streaming wrappers, prefer the shared `SyncStreamWrapper` and `AsyncStreamWrapper` |
40 | | -helpers from `opentelemetry.util.genai.stream` instead of reimplementing iteration, |
41 | | -close/context-manager, and finalization behavior in provider packages. |
42 | | - |
43 | | -Put provider-specific chunk parsing and telemetry finalization in private hook methods or a |
44 | | -narrow mixin. Do not make async stream wrappers inherit from sync stream wrappers. |
45 | | - |
46 | | -## 2. TelemetryHandler Initialization |
47 | | - |
48 | | -Construct `TelemetryHandler` once inside `_instrument()`, passing all OTel providers and the |
49 | | -completion hook. Always prefer an explicitly injected hook (`kwargs.get("completion_hook")`) |
50 | | -over the entry-point hook loaded by `load_completion_hook()`, so test code can override the |
51 | | -hook without touching the environment. |
52 | | - |
53 | | -```python |
54 | | -from opentelemetry.util.genai.completion_hook import load_completion_hook |
55 | | -from opentelemetry.util.genai.handler import TelemetryHandler |
56 | | - |
57 | | -def _instrument(self, **kwargs): |
58 | | - tracer_provider = kwargs.get("tracer_provider") |
59 | | - meter_provider = kwargs.get("meter_provider") |
60 | | - logger_provider = kwargs.get("logger_provider") |
61 | | - |
62 | | - handler = TelemetryHandler( |
63 | | - tracer_provider=tracer_provider, |
64 | | - meter_provider=meter_provider, |
65 | | - logger_provider=logger_provider, |
66 | | - completion_hook=kwargs.get("completion_hook") or load_completion_hook(), |
67 | | - ) |
68 | | - # pass handler to each patch/wrapper function |
69 | | -``` |
70 | | - |
71 | | -## 3. Invocation Pattern |
72 | | - |
73 | | -Use `start_*()` and control span lifetime manually: |
74 | | - |
75 | | -```python |
76 | | -invocation = handler.start_inference(provider, request_model, server_address=..., server_port=...) |
77 | | -invocation.temperature = ... |
78 | | -try: |
79 | | - response = client.call(...) |
80 | | - invocation.response_model_name = response.model |
81 | | - invocation.finish_reasons = response.finish_reasons |
82 | | - invocation.stop() |
83 | | -except Exception as exc: |
84 | | - invocation.fail(exc) |
85 | | - raise |
86 | | -``` |
87 | | - |
88 | | -Content capture decisions must come from the shared handler, not from instrumentation-local |
89 | | -environment checks or duplicated helper logic. Evaluate the handler's content-capture API once |
90 | | -when creating wrappers (for example, `capture_content = handler.should_capture_content()`) and |
91 | | -pass that value through invocation/request helpers. |
92 | | - |
93 | | -## 4. Semantic conventions |
94 | | - |
95 | | -Attributes, spans, events, and metrics follow the |
96 | | -[GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions/tree/main/docs/gen-ai). |
97 | | -Do not emit signals that are not covered by semconv. |
98 | | - |
99 | | -`gen_ai.*` attribute names and the enums for well-known values (e.g. `GenAiOutputTypeValues` for |
100 | | -`gen_ai.output.type`) live in `opentelemetry.semconv._incubating.attributes.gen_ai_attributes`. |
101 | | - |
102 | | -## 5. Tests |
103 | | - |
104 | | -- Use VCR cassettes for provider calls. Do not skip tests when an API key is missing. |
105 | | -- Cover streaming and non-streaming variants when both exist. |
106 | | -- Cover error scenarios, at minimum: provider error / endpoint unavailable, stream interrupted by |
107 | | - network, stream closed early by the caller. |
108 | | - |
109 | | -## 6. Examples |
110 | | - |
111 | | -New instrumentations ship a minimal example under the package's `examples/` directory, with |
112 | | -both a `manual/` setup and a `zero-code/` (auto-instrumentation) variant. |
0 commit comments