Skip to content

Commit eb379be

Browse files
google-genai-botxuanyang15
authored andcommitted
feat: Add user.id to gen_ai.user.message log records for telemetry
Merge: #5796 ORIGINAL_AUTHOR=Achuth Narayan Rajagopal <achuth.narayan@gmail.com> GitOrigin-RevId: ec8265e Change-Id: Ib77c4e2ad3df29a7ca734f142b9dc42d0890f429
1 parent a4f394e commit eb379be

4 files changed

Lines changed: 182 additions & 18 deletions

File tree

src/google/adk/telemetry/_experimental_semconv.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,14 @@ def _to_system_instructions(
434434
def set_operation_details_common_attributes(
435435
operation_details_common_attributes: MutableMapping[str, AttributeValue],
436436
attributes: Mapping[str, AttributeValue],
437-
):
437+
log_only_attributes: Mapping[str, AttributeValue] | None = None,
438+
) -> None:
438439
operation_details_common_attributes.update(attributes)
440+
if log_only_attributes and get_content_capturing_mode() in (
441+
'EVENT_ONLY',
442+
'SPAN_AND_EVENT',
443+
):
444+
operation_details_common_attributes.update(log_only_attributes)
439445

440446

441447
async def set_operation_details_attributes_from_request(

src/google/adk/telemetry/tracing.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666

6767
from .. import version
6868
from ..utils.model_name_utils import is_gemini_model
69+
from ._experimental_semconv import get_content_capturing_mode
6970
from ._experimental_semconv import is_experimental_semconv
7071
from ._experimental_semconv import maybe_log_completion_details
7172
from ._experimental_semconv import set_operation_details_attributes_from_request
@@ -556,20 +557,26 @@ def use_generate_content_span(
556557
common_attributes = {
557558
GEN_AI_AGENT_NAME: invocation_context.agent.name,
558559
GEN_AI_CONVERSATION_ID: invocation_context.session.id,
559-
USER_ID: invocation_context.session.user_id,
560560
'gcp.vertex.agent.event_id': model_response_event.id,
561561
'gcp.vertex.agent.invocation_id': invocation_context.invocation_id,
562562
}
563+
log_only_common_attributes = {}
564+
if invocation_context.session.user_id is not None:
565+
log_only_common_attributes[USER_ID] = invocation_context.session.user_id
563566
if (
564567
_is_gemini_agent(invocation_context.agent)
565568
and _instrumented_with_opentelemetry_instrumentation_google_genai()
566569
):
567-
with _use_extra_generate_content_attributes(common_attributes):
570+
with _use_extra_generate_content_attributes(
571+
common_attributes,
572+
log_only_extra_attributes=log_only_common_attributes,
573+
):
568574
yield
569575
else:
570576
with _use_native_generate_content_span_stable_semconv(
571577
llm_request=llm_request,
572578
common_attributes=common_attributes,
579+
log_only_common_attributes=log_only_common_attributes,
573580
) as span:
574581
yield span.span
575582

@@ -590,24 +597,32 @@ async def use_inference_span(
590597
common_attributes = {
591598
GEN_AI_AGENT_NAME: invocation_context.agent.name,
592599
GEN_AI_CONVERSATION_ID: invocation_context.session.id,
593-
USER_ID: invocation_context.session.user_id,
594600
'gcp.vertex.agent.event_id': model_response_event.id,
595601
'gcp.vertex.agent.invocation_id': invocation_context.invocation_id,
596602
}
603+
log_only_common_attributes = {}
604+
if invocation_context.session.user_id is not None:
605+
log_only_common_attributes[USER_ID] = invocation_context.session.user_id
597606
if (
598607
_is_gemini_agent(invocation_context.agent)
599608
and _instrumented_with_opentelemetry_instrumentation_google_genai()
600609
):
601-
with _use_extra_generate_content_attributes(common_attributes):
610+
with _use_extra_generate_content_attributes(
611+
common_attributes,
612+
log_only_extra_attributes=log_only_common_attributes,
613+
):
602614
yield
603615
else:
604616
async with _use_native_generate_content_span(
605617
llm_request=llm_request,
606618
common_attributes=common_attributes,
619+
log_only_common_attributes=log_only_common_attributes,
607620
) as gc_span:
608621
if is_experimental_semconv():
609622
set_operation_details_common_attributes(
610-
gc_span.operation_details_common_attributes, common_attributes
623+
gc_span.operation_details_common_attributes,
624+
common_attributes,
625+
log_only_attributes=log_only_common_attributes,
611626
)
612627
try:
613628
yield gc_span
@@ -664,6 +679,7 @@ def _instrumented_with_opentelemetry_instrumentation_google_genai() -> bool:
664679
@contextmanager
665680
def _use_extra_generate_content_attributes(
666681
extra_attributes: Mapping[str, AttributeValue],
682+
log_only_extra_attributes: Mapping[str, AttributeValue] | None = None,
667683
):
668684
try:
669685
from opentelemetry.instrumentation.google_genai import GENERATE_CONTENT_EXTRA_ATTRIBUTES_CONTEXT_KEY
@@ -675,13 +691,25 @@ def _use_extra_generate_content_attributes(
675691
+ ' Please upgrade to version to 0.6b0 or above.'
676692
)
677693
yield
694+
678695
return
679696

680-
tok = otel_context.attach(
681-
otel_context.set_value(
682-
GENERATE_CONTENT_EXTRA_ATTRIBUTES_CONTEXT_KEY, extra_attributes
683-
)
697+
ctx = otel_context.set_value(
698+
GENERATE_CONTENT_EXTRA_ATTRIBUTES_CONTEXT_KEY, extra_attributes
684699
)
700+
if log_only_extra_attributes:
701+
try:
702+
from opentelemetry.instrumentation.google_genai import GENERATE_CONTENT_EVENT_ONLY_EXTRA_ATTRIBUTES_CONTEXT_KEY
703+
704+
ctx = otel_context.set_value(
705+
GENERATE_CONTENT_EVENT_ONLY_EXTRA_ATTRIBUTES_CONTEXT_KEY,
706+
log_only_extra_attributes,
707+
context=ctx,
708+
)
709+
except (ImportError, AttributeError):
710+
pass
711+
712+
tok = otel_context.attach(ctx)
685713
try:
686714
yield
687715
finally:
@@ -713,6 +741,7 @@ def _set_common_generate_content_attributes(
713741
def _use_native_generate_content_span_stable_semconv(
714742
llm_request: LlmRequest,
715743
common_attributes: Mapping[str, AttributeValue],
744+
log_only_common_attributes: Mapping[str, AttributeValue] | None = None,
716745
) -> Iterator[GenerateContentSpan]:
717746
with tracer.start_as_current_span(
718747
f"generate_content {llm_request.model or ''}"
@@ -734,12 +763,18 @@ def _use_native_generate_content_span_stable_semconv(
734763
attributes={GEN_AI_SYSTEM: _guess_gemini_system_name()},
735764
)
736765
)
766+
user_message_attributes = {GEN_AI_SYSTEM: _guess_gemini_system_name()}
767+
if _should_log_prompt_response_content() and log_only_common_attributes:
768+
user_id = log_only_common_attributes.get(USER_ID)
769+
if user_id is not None:
770+
user_message_attributes[USER_ID] = user_id
771+
737772
for content in llm_request.contents:
738773
otel_logger.emit(
739774
LogRecord(
740775
event_name='gen_ai.user.message',
741776
body={'content': _serialize_content_with_elision(content)},
742-
attributes={GEN_AI_SYSTEM: _guess_gemini_system_name()},
777+
attributes=user_message_attributes,
743778
)
744779
)
745780

@@ -750,10 +785,13 @@ def _use_native_generate_content_span_stable_semconv(
750785
async def _use_native_generate_content_span(
751786
llm_request: LlmRequest,
752787
common_attributes: Mapping[str, AttributeValue],
788+
log_only_common_attributes: Mapping[str, AttributeValue] | None = None,
753789
) -> AsyncIterator[GenerateContentSpan]:
754790
if not is_experimental_semconv():
755791
with _use_native_generate_content_span_stable_semconv(
756-
llm_request, common_attributes
792+
llm_request,
793+
common_attributes,
794+
log_only_common_attributes=log_only_common_attributes,
757795
) as gc_span:
758796
yield gc_span
759797
return

tests/unittests/telemetry/test_node_functional.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@ async def some_node(ctx, node_input):
255255
),
256256
'gen_ai.request.model': 'mock',
257257
'gen_ai.system': 'gemini',
258-
'user.id': 'some_user',
259258
},
260259
children=[
261260
SpanDigest(
@@ -327,7 +326,6 @@ async def some_node(ctx, node_input):
327326
),
328327
'gen_ai.request.model': 'mock',
329328
'gen_ai.system': 'gemini',
330-
'user.id': 'some_user',
331329
},
332330
),
333331
],

0 commit comments

Comments
 (0)