telemetry-dev-google-genai 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: telemetry-dev-google-genai
3
+ Version: 0.1.0
4
+ Summary: Google GenAI (Gemini) integration for telemetry.dev Python SDK
5
+ Keywords: telemetry,opentelemetry,gemini,google-genai,llm,genai,tracing
6
+ Author: telemetry.dev
7
+ License-Expression: MIT
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Typing :: Typed
16
+ Requires-Dist: telemetry-dev>=0.1.0
17
+ Requires-Dist: google-genai>=2,<3
18
+ Requires-Python: >=3.10
19
+ Project-URL: Homepage, https://telemetry.dev
20
+ Project-URL: Repository, https://github.com/telemetry-dev/telemetry.dev
21
+ Description-Content-Type: text/markdown
22
+
23
+ # telemetry-dev-google-genai
24
+
25
+ Google GenAI (Gemini) SDK instrumentation for telemetry.dev. It wraps the official `google-genai` Python SDK and emits telemetry.dev generation and embedding spans through `telemetry-dev`.
26
+
27
+ ## Install
28
+
29
+ ```sh
30
+ pip install telemetry-dev-google-genai
31
+ ```
32
+
33
+ Initialize the core SDK first:
34
+
35
+ ```py
36
+ import telemetry_dev
37
+
38
+ telemetry_dev.init(
39
+ api_key="td_live_...",
40
+ base_url="http://localhost:4318",
41
+ service_name="my-service",
42
+ )
43
+ ```
44
+
45
+ ## Per-client wrapping
46
+
47
+ ```py
48
+ from google import genai
49
+ from telemetry_dev_google_genai import wrap_google_genai
50
+
51
+ client = wrap_google_genai(genai.Client(api_key="..."))
52
+
53
+ client.models.generate_content(
54
+ model="gemini-2.5-flash",
55
+ contents=[{"role": "user", "parts": [{"text": "Tell me a joke about OpenTelemetry"}]}],
56
+ )
57
+ ```
58
+
59
+ Use this when you want explicit control over which clients are instrumented. `wrap_google_genai` patches both sync `client.models` and async `client.aio.models`.
60
+
61
+ ## Global instrumentation
62
+
63
+ ```py
64
+ from google import genai
65
+ from telemetry_dev_google_genai import instrument_google_genai, uninstrument_google_genai
66
+
67
+ instrument_google_genai()
68
+ client = genai.Client(api_key="...")
69
+
70
+ try:
71
+ client.models.generate_content(
72
+ model="gemini-2.5-flash",
73
+ contents="Tell me a joke about OpenTelemetry",
74
+ )
75
+ finally:
76
+ uninstrument_google_genai()
77
+ ```
78
+
79
+ Use this as the app-wide one-liner at startup when all GenAI clients should be instrumented.
80
+
81
+ ## Instrumented surfaces
82
+
83
+ Sync and async variants are covered:
84
+
85
+ - `client.models.generate_content(...)` / `client.aio.models.generate_content(...)`
86
+ - `client.models.generate_content_stream(...)` / `client.aio.models.generate_content_stream(...)`
87
+ - `client.models.embed_content(...)` / `client.aio.models.embed_content(...)`
88
+
89
+ `client.chats.create(...).send_message(...)` and `send_message_stream(...)` are covered automatically because they call the wrapped `models` methods.
90
+
91
+ ## What gets captured
92
+
93
+ | Gemini signal | telemetry.dev field / attribute |
94
+ |---|---|
95
+ | `model` | `model` |
96
+ | `contents` | `input` |
97
+ | `config.system_instruction` | `system_instructions` |
98
+ | sampling params (`temperature`, `top_p`, `top_k`, `seed`, penalties, `max_output_tokens`, `stop_sequences`) | same-named span fields |
99
+ | JSON / schema output config | `output_type` (`json` or `text`) |
100
+ | `config.candidate_count` | `gen_ai.request.choice.count` |
101
+ | `config.tools` | `gen_ai.tool.definitions` |
102
+ | `config.tool_config`, `safety_settings`, `thinking_config`, `labels`, `cached_content`, `response_modalities` | `google_genai.request.*` attributes |
103
+ | response IDs, model version, finish reasons, output messages, usage tokens | mapped span fields |
104
+ | block/safety/grounding/url-context metadata | `google_genai.response.*` attributes |
105
+ | AFC history on the final response | replaces span `input`; sets `google_genai.automatic_function_calling=true` |
106
+
107
+ The integration maps native Gemini request/response shapes directly. It never mutates caller requests.
108
+
109
+ ## Streaming
110
+
111
+ Gemini streams already include cumulative `usage_metadata` on chunks, so no request injection is needed. Stream spans record time-to-first-chunk, aggregate text parts (merging consecutive text with the same `thought` flag), last-seen usage/finish reasons, and end once when the stream completes, errors, or is closed.
112
+
113
+ ## Automatic function calling (AFC)
114
+
115
+ When Python callables are passed in `tools`, the SDK may run an internal AFC loop across multiple transport calls. The integration emits one span for the public `generate_content` call and, when present, sets span input to `automatic_function_calling_history`.
116
+
117
+ ## Embeddings
118
+
119
+ Embedding calls emit `gen_ai.operation.name = "embeddings"`, request model/input, embedding count/dimension attributes, optional token usage, and optional billable character counts. Embedding vectors are not captured as output.
120
+
121
+ ## Provider values
122
+
123
+ - Gemini Developer API clients record provider `gcp.gemini`.
124
+ - Vertex AI clients (`vertexai=True`) record provider `gcp.vertex_ai`.
125
+
126
+ ## Fail-open guarantee
127
+
128
+ Mapping code is defensive; wrapped calls return the SDK response unchanged and re-raise exceptions untouched. Telemetry bugs never break callers.
129
+
130
+ ## Limitations
131
+
132
+ - Not instrumented: `count_tokens`, `compute_tokens`, `generate_images`, `generate_videos`, `live`, `caches`, `files`, `tunings`, `batches`.
133
+ - Deliberately not captured: logprobs, citation metadata, per-modality token detail arrays, `create_time`, `sdk_http_response`.
134
+ - Unconsumed streams end their spans only when the stream is exhausted, errors, or is closed.
@@ -0,0 +1,112 @@
1
+ # telemetry-dev-google-genai
2
+
3
+ Google GenAI (Gemini) SDK instrumentation for telemetry.dev. It wraps the official `google-genai` Python SDK and emits telemetry.dev generation and embedding spans through `telemetry-dev`.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pip install telemetry-dev-google-genai
9
+ ```
10
+
11
+ Initialize the core SDK first:
12
+
13
+ ```py
14
+ import telemetry_dev
15
+
16
+ telemetry_dev.init(
17
+ api_key="td_live_...",
18
+ base_url="http://localhost:4318",
19
+ service_name="my-service",
20
+ )
21
+ ```
22
+
23
+ ## Per-client wrapping
24
+
25
+ ```py
26
+ from google import genai
27
+ from telemetry_dev_google_genai import wrap_google_genai
28
+
29
+ client = wrap_google_genai(genai.Client(api_key="..."))
30
+
31
+ client.models.generate_content(
32
+ model="gemini-2.5-flash",
33
+ contents=[{"role": "user", "parts": [{"text": "Tell me a joke about OpenTelemetry"}]}],
34
+ )
35
+ ```
36
+
37
+ Use this when you want explicit control over which clients are instrumented. `wrap_google_genai` patches both sync `client.models` and async `client.aio.models`.
38
+
39
+ ## Global instrumentation
40
+
41
+ ```py
42
+ from google import genai
43
+ from telemetry_dev_google_genai import instrument_google_genai, uninstrument_google_genai
44
+
45
+ instrument_google_genai()
46
+ client = genai.Client(api_key="...")
47
+
48
+ try:
49
+ client.models.generate_content(
50
+ model="gemini-2.5-flash",
51
+ contents="Tell me a joke about OpenTelemetry",
52
+ )
53
+ finally:
54
+ uninstrument_google_genai()
55
+ ```
56
+
57
+ Use this as the app-wide one-liner at startup when all GenAI clients should be instrumented.
58
+
59
+ ## Instrumented surfaces
60
+
61
+ Sync and async variants are covered:
62
+
63
+ - `client.models.generate_content(...)` / `client.aio.models.generate_content(...)`
64
+ - `client.models.generate_content_stream(...)` / `client.aio.models.generate_content_stream(...)`
65
+ - `client.models.embed_content(...)` / `client.aio.models.embed_content(...)`
66
+
67
+ `client.chats.create(...).send_message(...)` and `send_message_stream(...)` are covered automatically because they call the wrapped `models` methods.
68
+
69
+ ## What gets captured
70
+
71
+ | Gemini signal | telemetry.dev field / attribute |
72
+ |---|---|
73
+ | `model` | `model` |
74
+ | `contents` | `input` |
75
+ | `config.system_instruction` | `system_instructions` |
76
+ | sampling params (`temperature`, `top_p`, `top_k`, `seed`, penalties, `max_output_tokens`, `stop_sequences`) | same-named span fields |
77
+ | JSON / schema output config | `output_type` (`json` or `text`) |
78
+ | `config.candidate_count` | `gen_ai.request.choice.count` |
79
+ | `config.tools` | `gen_ai.tool.definitions` |
80
+ | `config.tool_config`, `safety_settings`, `thinking_config`, `labels`, `cached_content`, `response_modalities` | `google_genai.request.*` attributes |
81
+ | response IDs, model version, finish reasons, output messages, usage tokens | mapped span fields |
82
+ | block/safety/grounding/url-context metadata | `google_genai.response.*` attributes |
83
+ | AFC history on the final response | replaces span `input`; sets `google_genai.automatic_function_calling=true` |
84
+
85
+ The integration maps native Gemini request/response shapes directly. It never mutates caller requests.
86
+
87
+ ## Streaming
88
+
89
+ Gemini streams already include cumulative `usage_metadata` on chunks, so no request injection is needed. Stream spans record time-to-first-chunk, aggregate text parts (merging consecutive text with the same `thought` flag), last-seen usage/finish reasons, and end once when the stream completes, errors, or is closed.
90
+
91
+ ## Automatic function calling (AFC)
92
+
93
+ When Python callables are passed in `tools`, the SDK may run an internal AFC loop across multiple transport calls. The integration emits one span for the public `generate_content` call and, when present, sets span input to `automatic_function_calling_history`.
94
+
95
+ ## Embeddings
96
+
97
+ Embedding calls emit `gen_ai.operation.name = "embeddings"`, request model/input, embedding count/dimension attributes, optional token usage, and optional billable character counts. Embedding vectors are not captured as output.
98
+
99
+ ## Provider values
100
+
101
+ - Gemini Developer API clients record provider `gcp.gemini`.
102
+ - Vertex AI clients (`vertexai=True`) record provider `gcp.vertex_ai`.
103
+
104
+ ## Fail-open guarantee
105
+
106
+ Mapping code is defensive; wrapped calls return the SDK response unchanged and re-raise exceptions untouched. Telemetry bugs never break callers.
107
+
108
+ ## Limitations
109
+
110
+ - Not instrumented: `count_tokens`, `compute_tokens`, `generate_images`, `generate_videos`, `live`, `caches`, `files`, `tunings`, `batches`.
111
+ - Deliberately not captured: logprobs, citation metadata, per-modality token detail arrays, `create_time`, `sdk_http_response`.
112
+ - Unconsumed streams end their spans only when the stream is exhausted, errors, or is closed.
@@ -0,0 +1,58 @@
1
+ [project]
2
+ name = "telemetry-dev-google-genai"
3
+ version = "0.1.0"
4
+ description = "Google GenAI (Gemini) integration for telemetry.dev Python SDK"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ requires-python = ">=3.10"
8
+ authors = [{ name = "telemetry.dev" }]
9
+ keywords = ["telemetry", "opentelemetry", "gemini", "google-genai", "llm", "genai", "tracing"]
10
+ classifiers = [
11
+ "Development Status :: 4 - Beta",
12
+ "Intended Audience :: Developers",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Typing :: Typed",
19
+ ]
20
+ dependencies = [
21
+ "telemetry-dev>=0.1.0",
22
+ "google-genai>=2,<3",
23
+ ]
24
+
25
+ [project.urls]
26
+ Homepage = "https://telemetry.dev"
27
+ Repository = "https://github.com/telemetry-dev/telemetry.dev"
28
+
29
+ [tool.uv.sources]
30
+ telemetry-dev = { path = "../python", editable = true }
31
+
32
+ [dependency-groups]
33
+ dev = [
34
+ "pytest>=8.3",
35
+ "pytest-asyncio>=0.25",
36
+ "ruff>=0.9",
37
+ "pyright>=1.1.390",
38
+ ]
39
+
40
+ [build-system]
41
+ requires = ["uv_build>=0.9.0,<0.10.0"]
42
+ build-backend = "uv_build"
43
+
44
+ [tool.pytest.ini_options]
45
+ asyncio_mode = "auto"
46
+ testpaths = ["tests"]
47
+
48
+ [tool.ruff]
49
+ line-length = 100
50
+ target-version = "py310"
51
+
52
+ [tool.ruff.lint]
53
+ select = ["E", "F", "I", "UP", "B", "RUF"]
54
+
55
+ [tool.pyright]
56
+ include = ["src", "tests"]
57
+ typeCheckingMode = "strict"
58
+ pythonVersion = "3.10"