Skip to content

Commit c92951f

Browse files
authored
Merge branch 'main' into issue3261
2 parents b1308a0 + a01564c commit c92951f

File tree

24 files changed

+835
-263
lines changed

24 files changed

+835
-263
lines changed

.github/workflows/package-prepare-patch-release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- opentelemetry-sdk-extension-aws
1111
- opentelemetry-instrumentation-openai-v2
1212
- opentelemetry-instrumentation-vertexai
13+
- opentelemetry-instrumentation-google-genai
1314
description: 'Package to be released'
1415
required: true
1516
run-name: "[Package][${{ inputs.package }}] Prepare patch release"

.github/workflows/package-prepare-release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- opentelemetry-sdk-extension-aws
1111
- opentelemetry-instrumentation-openai-v2
1212
- opentelemetry-instrumentation-vertexai
13+
- opentelemetry-instrumentation-google-genai
1314
description: 'Package to be released'
1415
required: true
1516

.github/workflows/package-release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- opentelemetry-sdk-extension-aws
1111
- opentelemetry-instrumentation-openai-v2
1212
- opentelemetry-instrumentation-vertexai
13+
- opentelemetry-instrumentation-google-genai
1314
description: 'Package to be released'
1415
required: true
1516
run-name: "[Package][${{ inputs.package }}] Release"

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
([#3275](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3275))
2626
- `opentelemetry-instrumentation-botocore` Add support for GenAI tool events
2727
([#3302](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3302))
28+
- `opentelemetry-instrumentation-botocore` Add support for GenAI metrics
29+
([#3326](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3326))
2830
- `opentelemetry-instrumentation` make it simpler to initialize auto-instrumentation programmatically
2931
([#3273](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3273))
3032
- Add `opentelemetry-instrumentation-vertexai>=2.0b0` to `opentelemetry-bootstrap`

RELEASING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
> - opentelemetry-sdk-extension-aws
2323
> - opentelemetry-instrumentation-openai-v2
2424
> - opentelemetry-instrumentation-vertexai
25+
> - opentelemetry-instrumentation-google-genai
2526
>
2627
> These libraries are also excluded from the general release.
2728
@@ -79,6 +80,8 @@ The workflow will create a pull request that should be merged in order to procee
7980
> - opentelemetry-resource-detector-azure
8081
> - opentelemetry-sdk-extension-aws
8182
> - opentelemetry-instrumentation-openai-v2
83+
> - opentelemetry-instrumentation-vertexai
84+
> - opentelemetry-instrumentation-google-genai
8285
>
8386
> These libraries are also excluded from the general patch release.
8487

instrumentation-genai/opentelemetry-instrumentation-google-genai/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
## Version 0.1b0 (2025-03-05)
11+
12+
- Add support for async and streaming.
13+
([#3298](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3298))
14+
1015
Create an initial version of Open Telemetry instrumentation for github.com/googleapis/python-genai.
1116
([#3256](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3256))

instrumentation-genai/opentelemetry-instrumentation-google-genai/TODOS.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44

55
Here are some TODO items required to achieve stability for this package:
66

7-
1. Add support for streaming interfaces
8-
2. Add support for async interfaces
9-
3. Add more span-level attributes for request configuration
10-
4. Add more span-level attributes for response information
11-
5. Verify and correct formatting of events:
12-
- Including the 'role' field for message events
13-
- Including tool invocation information
14-
6. Emit events for safety ratings when they block responses
15-
7. Additional cleanup/improvement tasks such as:
16-
- Adoption of 'wrapt' instead of 'functools.wraps'
17-
- Bolstering test coverage
18-
8. Migrate tests to use VCR.py
7+
- Add more span-level attributes for request configuration
8+
- Add more span-level attributes for response information
9+
- Verify and correct formatting of events:
10+
- Including the 'role' field for message events
11+
- Including tool invocation information
12+
- Emit events for safety ratings when they block responses
13+
- Additional cleanup/improvement tasks such as:
14+
- Adoption of 'wrapt' instead of 'functools.wraps'
15+
- Bolstering test coverage
16+
- Migrate tests to use VCR.py
17+
1918
## Future
2019

2120
Beyond the above TODOs, it would also be desirable to extend the

instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/generate_content.py

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,11 @@
4545
_logger = logging.getLogger(__name__)
4646

4747

48-
# Constant used for the value of 'gen_ai.operation.name".
49-
_GENERATE_CONTENT_OP_NAME = "generate_content"
50-
5148
# Constant used to make the absence of content more understandable.
5249
_CONTENT_ELIDED = "<elided>"
5350

54-
# Enable these after these cases are fully vetted and tested
55-
_INSTRUMENT_STREAMING = False
56-
_INSTRUMENT_ASYNC = False
51+
# Constant used for the value of 'gen_ai.operation.name".
52+
_GENERATE_CONTENT_OP_NAME = "generate_content"
5753

5854

5955
class _MethodsSnapshot:
@@ -220,7 +216,9 @@ def __init__(
220216
self._response_index = 0
221217
self._candidate_index = 0
222218

223-
def start_span_as_current_span(self, model_name, function_name):
219+
def start_span_as_current_span(
220+
self, model_name, function_name, end_on_exit=True
221+
):
224222
return self._otel_wrapper.start_as_current_span(
225223
f"{_GENERATE_CONTENT_OP_NAME} {model_name}",
226224
start_time=self._start_time,
@@ -230,6 +228,7 @@ def start_span_as_current_span(self, model_name, function_name):
230228
gen_ai_attributes.GEN_AI_REQUEST_MODEL: self._genai_request_model,
231229
gen_ai_attributes.GEN_AI_OPERATION_NAME: _GENERATE_CONTENT_OP_NAME,
232230
},
231+
end_on_exit=end_on_exit,
233232
)
234233

235234
def process_request(
@@ -543,9 +542,6 @@ def _create_instrumented_generate_content_stream(
543542
snapshot: _MethodsSnapshot, otel_wrapper: OTelWrapper
544543
):
545544
wrapped_func = snapshot.generate_content_stream
546-
if not _INSTRUMENT_STREAMING:
547-
# TODO: remove once this case has been fully tested
548-
return wrapped_func
549545

550546
@functools.wraps(wrapped_func)
551547
def instrumented_generate_content_stream(
@@ -586,9 +582,6 @@ def _create_instrumented_async_generate_content(
586582
snapshot: _MethodsSnapshot, otel_wrapper: OTelWrapper
587583
):
588584
wrapped_func = snapshot.async_generate_content
589-
if not _INSTRUMENT_ASYNC:
590-
# TODO: remove once this case has been fully tested
591-
return wrapped_func
592585

593586
@functools.wraps(wrapped_func)
594587
async def instrumented_generate_content(
@@ -630,9 +623,6 @@ def _create_instrumented_async_generate_content_stream( # pyright: ignore
630623
snapshot: _MethodsSnapshot, otel_wrapper: OTelWrapper
631624
):
632625
wrapped_func = snapshot.async_generate_content_stream
633-
if not _INSTRUMENT_ASYNC or not _INSTRUMENT_STREAMING:
634-
# TODO: remove once this case has been fully tested
635-
return wrapped_func
636626

637627
@functools.wraps(wrapped_func)
638628
async def instrumented_generate_content_stream(
@@ -647,24 +637,38 @@ async def instrumented_generate_content_stream(
647637
self, otel_wrapper, model
648638
)
649639
with helper.start_span_as_current_span(
650-
model, "google.genai.AsyncModels.generate_content_stream"
651-
):
640+
model,
641+
"google.genai.AsyncModels.generate_content_stream",
642+
end_on_exit=False,
643+
) as span:
652644
helper.process_request(contents, config)
653-
try:
654-
async for response in await wrapped_func(
655-
self,
656-
model=model,
657-
contents=contents,
658-
config=config,
659-
**kwargs,
660-
): # pyright: ignore
661-
helper.process_response(response)
662-
yield response # pyright: ignore
663-
except Exception as error:
664-
helper.process_error(error)
645+
try:
646+
response_async_generator = await wrapped_func(
647+
self,
648+
model=model,
649+
contents=contents,
650+
config=config,
651+
**kwargs,
652+
)
653+
except Exception as error: # pylint: disable=broad-exception-caught
654+
helper.process_error(error)
655+
helper.finalize_processing()
656+
with trace.use_span(span, end_on_exit=True):
665657
raise
666-
finally:
667-
helper.finalize_processing()
658+
659+
async def _response_async_generator_wrapper():
660+
with trace.use_span(span, end_on_exit=True):
661+
try:
662+
async for response in response_async_generator:
663+
helper.process_response(response)
664+
yield response
665+
except Exception as error:
666+
helper.process_error(error)
667+
raise
668+
finally:
669+
helper.finalize_processing()
670+
671+
return _response_async_generator_wrapper()
668672

669673
return instrumented_generate_content_stream
670674

instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
# This version should stay below "1.0" until the fundamentals
1818
# in "TODOS.md" have been addressed. Please revisit the TODOs
1919
# listed there before bumping to a stable version.
20-
__version__ = "0.0.1.dev"
20+
__version__ = "0.2b0.dev"

instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/common/otel_mocker.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,16 @@ def get_event_named(self, event_name):
179179
return event
180180
return None
181181

182+
def get_events_named(self, event_name):
183+
result = []
184+
for event in self.get_finished_logs():
185+
event_name_attr = event.attributes.get("event.name")
186+
if event_name_attr is None:
187+
continue
188+
if event_name_attr == event_name:
189+
result.append(event)
190+
return result
191+
182192
def assert_has_event_named(self, name):
183193
event = self.get_event_named(name)
184194
finished_logs = self.get_finished_logs()

0 commit comments

Comments
 (0)