Skip to content

Commit 5cae21d

Browse files
committed
fix: log roles as str, event attrs as objects.
1 parent 6b97539 commit 5cae21d

File tree

2 files changed

+35
-35
lines changed

2 files changed

+35
-35
lines changed

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

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
)
4949
from opentelemetry.semconv.attributes import error_attributes
5050
from opentelemetry.trace.span import Span
51-
from opentelemetry.util.genai.types import ContentCapturingMode
51+
from opentelemetry.util.genai.types import ContentCapturingMode, MessagePart
5252
from opentelemetry.util.genai.upload_hook import load_upload_hook
5353

5454
from .allowlist_util import AllowList
@@ -60,7 +60,7 @@
6060
OutputMessage,
6161
to_input_messages,
6262
to_output_messages,
63-
to_system_instruction,
63+
to_system_instructions,
6464
)
6565
from .otel_wrapper import OTelWrapper
6666
from .tool_call_wrapper import wrapped as wrapped_tool
@@ -259,20 +259,18 @@ def _config_to_system_instruction(
259259
def _create_completion_details_attributes(
260260
input_messages: list[InputMessage],
261261
output_messages: list[OutputMessage],
262-
system_instruction: Union[InputMessage, None],
263-
):
264-
attributes = {
265-
"gen_ai.input.messages": json.dumps(
266-
[dataclasses.asdict(input_message) for input_message in input_messages]
267-
),
268-
"gen_ai.output.messages": json.dumps(
269-
[dataclasses.asdict(output_message) for output_message in output_messages]
270-
),
262+
system_instructions: list[MessagePart],
263+
as_str: bool = False,
264+
) -> dict[str, Any]:
265+
attributes: dict[str, Any] = {
266+
"gen_ai.input.messages": [dataclasses.asdict(input_message) for input_message in input_messages],
267+
"gen_ai.output.messages": [dataclasses.asdict(output_message) for output_message in output_messages],
271268
}
272-
if system_instruction:
273-
attributes["gen_ai.system.instructions"] = json.dumps(
274-
dataclasses.asdict(system_instruction)
275-
)
269+
if system_instructions:
270+
attributes["gen_ai.system.instructions"] = [dataclasses.asdict(sys_instr) for sys_instr in system_instructions]
271+
272+
if as_str:
273+
return {k: json.dumps(v) for k, v in attributes.items()}
276274

277275
return attributes
278276

@@ -449,46 +447,45 @@ def _maybe_log_completion_details(
449447
attributes = {
450448
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
451449
}
452-
system_instruction = None
450+
system_instructions = []
453451
if system_content := _config_to_system_instruction(config):
454-
system_instruction = to_system_instruction(
452+
system_instructions = to_system_instructions(
455453
content=transformers.t_contents(system_content)[0]
456454
)
457455
input_messages = to_input_messages(contents=transformers.t_contents(request))
458456
output_messages = to_output_messages(candidates=response.candidates or [])
459457

460-
completion_details_attributes = _create_completion_details_attributes(
461-
input_messages, output_messages, system_instruction
462-
)
458+
463459

464460
span = None
465461
if self._content_recording_enabled in [
466462
ContentCapturingMode.SPAN_ONLY,
467463
ContentCapturingMode.SPAN_AND_EVENT,
468464
]:
465+
completion_details_attributes = _create_completion_details_attributes(
466+
input_messages, output_messages, system_instructions, as_str=True,
467+
)
469468
span = trace.get_current_span()
470469
span.set_attributes(completion_details_attributes)
471470
if self._content_recording_enabled in [
472471
ContentCapturingMode.EVENT_ONLY,
473472
ContentCapturingMode.SPAN_AND_EVENT,
474473
]:
474+
completion_details_attributes = _create_completion_details_attributes(
475+
input_messages, output_messages, system_instructions,
476+
)
475477
attributes.update(completion_details_attributes)
476478
event = Event(name="gen_ai.completion.details", attributes=attributes)
477479
hook = load_upload_hook()
478480
hook.upload(
479481
inputs=input_messages,
480482
outputs=output_messages,
481-
system_instruction=(
482-
system_instruction.parts if system_instruction else []
483-
),
483+
system_instruction=system_instructions,
484484
span=span,
485485
log_record=event,
486486
)
487-
# TODO Cannot access attribute shutdown for class UploadHook
488-
# hook.shutdown()
489-
self._otel_wrapper.log_completion_details(
490-
event=event,
491-
)
487+
hook.shutdown()
488+
self._otel_wrapper.log_completion_details(event=event)
492489

493490
def _maybe_log_system_instruction(
494491
self, config: Optional[GenerateContentConfigOrDict] = None

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def to_input_messages(
3939
*,
4040
contents: list[genai_types.Content],
4141
) -> list[InputMessage]:
42-
return [_to_input_message(content) for content in contents])
42+
return [_to_input_message(content) for content in contents]
4343

4444
def to_output_messages(
4545
*,
@@ -63,11 +63,14 @@ def content_to_output_message(
6363
)
6464
return [message for message in messages if message is not None]
6565

66-
def to_system_instruction(
66+
def to_system_instructions(
6767
*,
6868
content: genai_types.Content,
69-
) -> InputMessage:
70-
return _to_input_message(content)
69+
) -> list[MessagePart]:
70+
parts = (
71+
_to_part(part, idx) for idx, part in enumerate(content.parts or [])
72+
)
73+
return [part for part in parts if part is not None]
7174

7275
def _to_input_message(
7376
content: genai_types.Content,
@@ -114,11 +117,11 @@ def tool_call_id(name: str | None) -> str:
114117
_logger.info("Unknown part dropped from telemetry %s", part)
115118
return None
116119

117-
def _to_role(role: str | None) -> Role | str:
120+
def _to_role(role: str | None) -> str:
118121
if role == "user":
119-
return Role.USER
122+
return Role.USER.value
120123
if role == "model":
121-
return Role.ASSISTANT
124+
return Role.ASSISTANT.value
122125
return ""
123126

124127

0 commit comments

Comments
 (0)