From 3dad6f9895709d81dfc4c2fb58d718fa639f648f Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Tue, 15 Jul 2025 11:49:27 +0000 Subject: [PATCH 1/8] updated input & output tokens attributes --- .../tests/test_completion.py | 18 ++-- .../tests/test_messages.py | 18 ++-- .../tests/test_prompt_caching.py | 96 +++++++++---------- .../tests/traces/test_prompt_caching.py | 48 +++++----- .../tests/test_chat.py | 18 ++-- .../tests/test_completion.py | 18 ++-- .../opentelemetry/semconv_ai/__init__.py | 4 +- 7 files changed, 110 insertions(+), 110 deletions(-) diff --git a/packages/opentelemetry-instrumentation-alephalpha/tests/test_completion.py b/packages/opentelemetry-instrumentation-alephalpha/tests/test_completion.py index 59e7ce1931..4f81cd6065 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/tests/test_completion.py +++ b/packages/opentelemetry-instrumentation-alephalpha/tests/test_completion.py @@ -35,12 +35,12 @@ def test_alephalpha_completion( together_span.attributes.get("gen_ai.completion.0.content") == response.completions[0].completion ) - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 9 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 9 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") logs = log_exporter.get_finished_logs() assert ( @@ -66,12 +66,12 @@ def test_alephalpha_completion_with_events_with_content( assert together_span.attributes.get("gen_ai.system") == "AlephAlpha" assert together_span.attributes.get("llm.request.type") == "completion" assert together_span.attributes.get("gen_ai.request.model") == "luminous-base" - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 9 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 9 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -116,12 +116,12 @@ def test_alephalpha_completion_with_events_with_no_content( assert together_span.attributes.get("gen_ai.system") == "AlephAlpha" assert together_span.attributes.get("llm.request.type") == "completion" assert together_span.attributes.get("gen_ai.request.model") == "luminous-base" - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 9 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 9 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py index 6b87c0d1c2..10cd7858b7 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py @@ -1291,10 +1291,10 @@ def test_anthropic_tools_legacy( anthropic_span = spans[0] # verify usage - assert anthropic_span.attributes["gen_ai.usage.prompt_tokens"] == 514 + assert anthropic_span.attributes["gen_ai.usage.input_tokens"] == 514 assert ( - anthropic_span.attributes["gen_ai.usage.completion_tokens"] - + anthropic_span.attributes["gen_ai.usage.prompt_tokens"] + anthropic_span.attributes["gen_ai.usage.output_tokens"] + + anthropic_span.attributes["gen_ai.usage.input_tokens"] == anthropic_span.attributes["llm.usage.total_tokens"] ) @@ -1466,10 +1466,10 @@ def test_anthropic_tools_with_events_with_content( anthropic_span = spans[0] # verify usage - assert anthropic_span.attributes["gen_ai.usage.prompt_tokens"] == 514 + assert anthropic_span.attributes["gen_ai.usage.input_tokens"] == 514 assert ( - anthropic_span.attributes["gen_ai.usage.completion_tokens"] - + anthropic_span.attributes["gen_ai.usage.prompt_tokens"] + anthropic_span.attributes["gen_ai.usage.output_tokens"] + + anthropic_span.attributes["gen_ai.usage.input_tokens"] == anthropic_span.attributes["llm.usage.total_tokens"] ) @@ -1602,10 +1602,10 @@ def test_anthropic_tools_with_events_with_no_content( anthropic_span = spans[0] # verify usage - assert anthropic_span.attributes["gen_ai.usage.prompt_tokens"] == 514 + assert anthropic_span.attributes["gen_ai.usage.input_tokens"] == 514 assert ( - anthropic_span.attributes["gen_ai.usage.completion_tokens"] - + anthropic_span.attributes["gen_ai.usage.prompt_tokens"] + anthropic_span.attributes["gen_ai.usage.output_tokens"] + + anthropic_span.attributes["gen_ai.usage.input_tokens"] == anthropic_span.attributes["llm.usage.total_tokens"] ) diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_prompt_caching.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_prompt_caching.py index 8feb9adaa7..fb8b13c645 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_prompt_caching.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_prompt_caching.py @@ -99,8 +99,8 @@ def test_anthropic_prompt_caching_legacy( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1163 ) - # assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1167 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 187 + # assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1167 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 187 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -108,8 +108,8 @@ def test_anthropic_prompt_caching_legacy( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1163 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1167 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 202 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1167 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 202 # verify metrics metrics_data = reader.get_metrics_data() @@ -189,8 +189,8 @@ def test_anthropic_prompt_caching_with_events_with_content( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1163 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1167 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 187 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1167 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 187 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -198,8 +198,8 @@ def test_anthropic_prompt_caching_with_events_with_content( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1163 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1167 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 202 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1167 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 202 # verify metrics metrics_data = reader.get_metrics_data() @@ -377,8 +377,8 @@ def test_anthropic_prompt_caching_with_events_with_no_content( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1163 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1167 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 187 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1167 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 187 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -386,8 +386,8 @@ def test_anthropic_prompt_caching_with_events_with_no_content( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1163 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1167 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 202 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1167 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 202 # verify metrics metrics_data = reader.get_metrics_data() @@ -507,8 +507,8 @@ async def test_anthropic_prompt_caching_async_legacy( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1165 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 207 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 207 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -516,8 +516,8 @@ async def test_anthropic_prompt_caching_async_legacy( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1165 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 224 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 224 # verify metrics metrics_data = reader.get_metrics_data() @@ -598,8 +598,8 @@ async def test_anthropic_prompt_caching_async_with_events_with_content( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1165 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 207 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 207 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -607,8 +607,8 @@ async def test_anthropic_prompt_caching_async_with_events_with_content( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1165 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 224 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 224 # verify metrics metrics_data = reader.get_metrics_data() @@ -792,8 +792,8 @@ async def test_anthropic_prompt_caching_async_with_events_with_no_content( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1165 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 207 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 207 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -801,8 +801,8 @@ async def test_anthropic_prompt_caching_async_with_events_with_no_content( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1165 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 224 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 224 # verify metrics metrics_data = reader.get_metrics_data() @@ -925,8 +925,8 @@ def test_anthropic_prompt_caching_stream_legacy( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1165 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 202 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 202 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -934,8 +934,8 @@ def test_anthropic_prompt_caching_stream_legacy( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1165 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 222 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 222 # verify metrics metrics_data = reader.get_metrics_data() @@ -1019,8 +1019,8 @@ def test_anthropic_prompt_caching_stream_with_events_with_content( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1165 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 202 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 202 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -1028,8 +1028,8 @@ def test_anthropic_prompt_caching_stream_with_events_with_content( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1165 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 222 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 222 # verify metrics metrics_data = reader.get_metrics_data() @@ -1218,8 +1218,8 @@ def test_anthropic_prompt_caching_stream_with_events_with_no_content( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1165 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 202 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 202 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -1227,8 +1227,8 @@ def test_anthropic_prompt_caching_stream_with_events_with_no_content( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1165 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1169 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 222 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1169 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 222 # verify metrics metrics_data = reader.get_metrics_data() @@ -1352,8 +1352,8 @@ async def test_anthropic_prompt_caching_async_stream_legacy( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1167 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1171 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 290 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1171 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 290 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -1361,8 +1361,8 @@ async def test_anthropic_prompt_caching_async_stream_legacy( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1167 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1171 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 257 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1171 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 257 # verify metrics metrics_data = reader.get_metrics_data() @@ -1447,8 +1447,8 @@ async def test_anthropic_prompt_caching_async_stream_with_events_with_content( cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1167 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1171 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 290 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1171 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 290 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -1456,8 +1456,8 @@ async def test_anthropic_prompt_caching_async_stream_with_events_with_content( # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1167 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1171 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 257 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1171 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 257 # verify metrics metrics_data = reader.get_metrics_data() @@ -1657,8 +1657,8 @@ async def test_anthropic_prompt_caching_async_stream_with_events_with_no_content cache_creation_span.attributes["gen_ai.usage.cache_creation_input_tokens"] == 1167 ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1171 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 290 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1171 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 290 # first check that cache_read_span only read from cache, but not wrote to it, assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] != 0 @@ -1666,8 +1666,8 @@ async def test_anthropic_prompt_caching_async_stream_with_events_with_no_content # then check for exact figures for the fixture/cassete assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1167 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1171 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 257 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1171 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 257 # verify metrics metrics_data = reader.get_metrics_data() diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_prompt_caching.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_prompt_caching.py index 375b37ae95..f88daa051f 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_prompt_caching.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_prompt_caching.py @@ -67,12 +67,12 @@ def test_openai_prompt_caching(instrument_legacy, span_exporter, log_exporter): assert cache_creation_span.attributes["gen_ai.completion.0.role"] == "assistant" assert cache_read_span.attributes["gen_ai.completion.0.role"] == "assistant" - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1149 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 315 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1149 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 315 assert cache_creation_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 0 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1149 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 353 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1149 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 353 assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1024 logs = log_exporter.get_finished_logs() @@ -129,12 +129,12 @@ def test_openai_prompt_caching_with_events_with_content( == "chatcmpl-BNi420iFNtIOHzy8Gq2fVS5utTus7" ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1149 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 315 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1149 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 315 assert cache_creation_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 0 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1149 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 353 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1149 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 353 assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1024 logs = log_exporter.get_finished_logs() @@ -222,12 +222,12 @@ def test_openai_prompt_caching_with_events_with_no_content( == "chatcmpl-BNi420iFNtIOHzy8Gq2fVS5utTus7" ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1149 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 315 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1149 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 315 assert cache_creation_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 0 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1149 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 353 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1149 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 353 assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1024 logs = log_exporter.get_finished_logs() @@ -319,12 +319,12 @@ async def test_openai_prompt_caching_async( assert cache_creation_span.attributes["gen_ai.completion.0.role"] == "assistant" assert cache_read_span.attributes["gen_ai.completion.0.role"] == "assistant" - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1150 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 293 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1150 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 293 assert cache_creation_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 0 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1150 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 307 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1150 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 307 assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1024 logs = log_exporter.get_finished_logs() @@ -382,12 +382,12 @@ async def test_openai_prompt_caching_async_with_events_with_content( == "chatcmpl-BNhrEFvKSNY08Uphau5iA4InZH6jn" ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1150 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 293 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1150 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 293 assert cache_creation_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 0 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1150 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 307 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1150 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 307 assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1024 logs = log_exporter.get_finished_logs() @@ -476,12 +476,12 @@ async def test_openai_prompt_caching_async_with_events_with_no_content( == "chatcmpl-BNhrEFvKSNY08Uphau5iA4InZH6jn" ) - assert cache_creation_span.attributes["gen_ai.usage.prompt_tokens"] == 1150 - assert cache_creation_span.attributes["gen_ai.usage.completion_tokens"] == 293 + assert cache_creation_span.attributes["gen_ai.usage.input_tokens"] == 1150 + assert cache_creation_span.attributes["gen_ai.usage.output_tokens"] == 293 assert cache_creation_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 0 - assert cache_read_span.attributes["gen_ai.usage.prompt_tokens"] == 1150 - assert cache_read_span.attributes["gen_ai.usage.completion_tokens"] == 307 + assert cache_read_span.attributes["gen_ai.usage.input_tokens"] == 1150 + assert cache_read_span.attributes["gen_ai.usage.output_tokens"] == 307 assert cache_read_span.attributes["gen_ai.usage.cache_read_input_tokens"] == 1024 logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-together/tests/test_chat.py b/packages/opentelemetry-instrumentation-together/tests/test_chat.py index f64ac5217d..df7c710b12 100644 --- a/packages/opentelemetry-instrumentation-together/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-together/tests/test_chat.py @@ -34,12 +34,12 @@ def test_together_chat_legacy( together_span.attributes.get("gen_ai.completion.0.content") == response.choices[0].message.content ) - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 18 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 18 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") assert together_span.attributes.get("gen_ai.response.id") == "88fa668fac30bb19-MXP" logs = log_exporter.get_finished_logs() @@ -66,12 +66,12 @@ def test_together_chat_with_events_with_content( together_span.attributes.get("gen_ai.request.model") == "mistralai/Mixtral-8x7B-Instruct-v0.1" ) - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 18 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 18 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") assert together_span.attributes.get("gen_ai.response.id") == "88fa668fac30bb19-MXP" logs = log_exporter.get_finished_logs() @@ -112,12 +112,12 @@ def test_together_chat_with_events_with_no_content( together_span.attributes.get("gen_ai.request.model") == "mistralai/Mixtral-8x7B-Instruct-v0.1" ) - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 18 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 18 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") assert together_span.attributes.get("gen_ai.response.id") == "88fa668fac30bb19-MXP" logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-together/tests/test_completion.py b/packages/opentelemetry-instrumentation-together/tests/test_completion.py index ca6cafe924..362e1a1386 100644 --- a/packages/opentelemetry-instrumentation-together/tests/test_completion.py +++ b/packages/opentelemetry-instrumentation-together/tests/test_completion.py @@ -34,12 +34,12 @@ def test_together_completion_legacy( together_span.attributes.get("gen_ai.completion.0.content") == response.choices[0].text ) - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 10 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 10 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") assert together_span.attributes.get("gen_ai.response.id") == "88fa66988e400e83-MXP" logs = log_exporter.get_finished_logs() @@ -66,12 +66,12 @@ def test_together_completion_with_events_with_content( together_span.attributes.get("gen_ai.request.model") == "mistralai/Mixtral-8x7B-Instruct-v0.1" ) - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 10 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 10 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") assert together_span.attributes.get("gen_ai.response.id") == "88fa66988e400e83-MXP" logs = log_exporter.get_finished_logs() @@ -112,12 +112,12 @@ def test_together_completion_with_events_with_no_content( together_span.attributes.get("gen_ai.request.model") == "mistralai/Mixtral-8x7B-Instruct-v0.1" ) - assert together_span.attributes.get("gen_ai.usage.prompt_tokens") == 10 + assert together_span.attributes.get("gen_ai.usage.input_tokens") == 10 assert together_span.attributes.get( "llm.usage.total_tokens" ) == together_span.attributes.get( - "gen_ai.usage.completion_tokens" - ) + together_span.attributes.get("gen_ai.usage.prompt_tokens") + "gen_ai.usage.output_tokens" + ) + together_span.attributes.get("gen_ai.usage.input_tokens") assert together_span.attributes.get("gen_ai.response.id") == "88fa66988e400e83-MXP" logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py index ffb2bb7e15..96474a841a 100644 --- a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py +++ b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py @@ -47,8 +47,8 @@ class SpanAttributes: LLM_PROMPTS = "gen_ai.prompt" LLM_COMPLETIONS = "gen_ai.completion" LLM_RESPONSE_MODEL = "gen_ai.response.model" - LLM_USAGE_COMPLETION_TOKENS = "gen_ai.usage.completion_tokens" - LLM_USAGE_PROMPT_TOKENS = "gen_ai.usage.prompt_tokens" + LLM_USAGE_COMPLETION_TOKENS = "gen_ai.usage.output_tokens" + LLM_USAGE_PROMPT_TOKENS = "gen_ai.usage.input_tokens" LLM_USAGE_CACHE_CREATION_INPUT_TOKENS = "gen_ai.usage.cache_creation_input_tokens" LLM_USAGE_CACHE_READ_INPUT_TOKENS = "gen_ai.usage.cache_read_input_tokens" LLM_TOKEN_TYPE = "gen_ai.token.type" From e1cec0a4e68213993a2edc6c9ca8c5fd508081d0 Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Sat, 19 Jul 2025 16:23:27 +0000 Subject: [PATCH 2/8] added opentelemetry gen_ai attributes --- .../instrumentation/alephalpha/__init__.py | 4 +- .../instrumentation/alephalpha/span_utils.py | 8 +- .../instrumentation/anthropic/__init__.py | 12 +- .../instrumentation/anthropic/span_utils.py | 26 +-- .../instrumentation/anthropic/streaming.py | 6 +- .../instrumentation/anthropic/utils.py | 2 +- .../tests/test_completion.py | 4 +- .../tests/test_messages.py | 80 +++---- .../tests/utils.py | 8 +- .../instrumentation/bedrock/guardrail.py | 12 +- .../instrumentation/bedrock/span_utils.py | 136 ++++++------ .../test_bedrock_guardrails_metrics.py | 6 +- .../tests/metrics/test_bedrock_metrics.py | 4 +- .../tests/traces/test_anthropic.py | 32 +-- .../tests/traces/test_cohere.py | 34 +-- .../tests/traces/test_imported_model.py | 32 +-- .../tests/traces/test_meta.py | 28 +-- .../tests/traces/test_nova.py | 200 +++++++++--------- .../tests/traces/test_titan.py | 106 +++++----- .../instrumentation/cohere/__init__.py | 2 +- .../instrumentation/cohere/span_utils.py | 30 +-- .../tests/test_chat.py | 16 +- .../tests/test_completion.py | 14 +- .../tests/test_rerank.py | 24 +-- .../instrumentation/crewai/instrumentation.py | 22 +- .../google_generativeai/__init__.py | 4 +- .../google_generativeai/span_utils.py | 38 ++-- .../tests/test_generate_content.py | 20 +- .../instrumentation/groq/__init__.py | 4 +- .../instrumentation/groq/span_utils.py | 28 +-- .../instrumentation/groq/utils.py | 2 +- .../tests/traces/test_chat_tracing.py | 12 +- .../instrumentation/haystack/wrap_openai.py | 14 +- .../langchain/callback_handler.py | 22 +- .../instrumentation/langchain/span_utils.py | 24 +-- .../tests/metrics/test_langchain_metrics.py | 12 +- .../tests/test_chains.py | 14 +- .../tests/test_llms.py | 88 ++++---- .../tests/test_structured_output.py | 4 +- .../tests/test_tool_calls.py | 102 ++++----- .../llamaindex/custom_llm_instrumentor.py | 14 +- .../instrumentation/llamaindex/span_utils.py | 22 +- .../tests/test_agents.py | 76 +++---- .../tests/test_chroma_vector_store.py | 8 +- .../tests/test_query_pipeline.py | 16 +- .../instrumentation/mistralai/__init__.py | 24 +-- .../tests/test_chat.py | 58 ++--- .../tests/test_embeddings.py | 28 +-- .../instrumentation/ollama/__init__.py | 24 +-- .../instrumentation/ollama/span_utils.py | 36 ++-- .../tests/test_chat.py | 94 ++++---- .../tests/test_embeddings.py | 14 +- .../tests/test_generation.py | 64 +++--- .../tests/test_ollama_metrics.py | 6 +- .../instrumentation/openai_agents/__init__.py | 36 ++-- .../tests/test_openai_agents.py | 32 +-- .../instrumentation/openai/shared/__init__.py | 20 +- .../openai/shared/chat_wrappers.py | 14 +- .../openai/shared/completion_wrappers.py | 4 +- .../openai/shared/embeddings_wrappers.py | 6 +- .../openai/v1/assistant_wrappers.py | 34 +-- .../openai/v1/event_handler_wrapper.py | 4 +- .../tests/metrics/test_openai_metrics.py | 10 +- .../tests/traces/test_assistant.py | 134 ++++++------ .../tests/traces/test_azure.py | 36 ++-- .../tests/traces/test_chat.py | 84 ++++---- .../tests/traces/test_chat_parse.py | 36 ++-- .../tests/traces/test_completions.py | 24 +-- .../tests/traces/test_embeddings.py | 24 +-- .../tests/traces/test_functions.py | 46 ++-- .../tests/traces/test_vision.py | 8 +- .../instrumentation/replicate/__init__.py | 2 +- .../instrumentation/replicate/span_utils.py | 16 +- .../instrumentation/sagemaker/span_utils.py | 2 +- .../tests/test_invocation.py | 6 +- .../instrumentation/together/__init__.py | 2 +- .../instrumentation/together/span_utils.py | 20 +- .../transformers/span_utils.py | 14 +- .../instrumentation/vertexai/__init__.py | 4 +- .../instrumentation/vertexai/span_utils.py | 18 +- .../tests/disabled_test_bison.py | 60 +++--- .../tests/disabled_test_gemini.py | 10 +- .../instrumentation/watsonx/__init__.py | 34 +-- .../tests/metrics/test_watsonx_metrics.py | 8 +- .../tests/traces/test_generate.py | 20 +- .../opentelemetry/semconv_ai/__init__.py | 56 +++-- .../poetry.lock | 109 +++++++++- .../pyproject.toml | 1 + packages/traceloop-sdk/tests/test_manual.py | 10 +- .../tests/test_privacy_no_prompts.py | 4 +- .../tests/test_prompt_management.py | 4 +- .../traceloop-sdk/tests/test_workflows.py | 8 +- .../traceloop/sdk/tracing/manual.py | 14 +- 93 files changed, 1410 insertions(+), 1284 deletions(-) diff --git a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py index e1131b24f8..2f4eb239e5 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py +++ b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py @@ -69,7 +69,7 @@ def _handle_message_event( event: PromptEvent, span: Span, event_logger: Optional[EventLogger], kwargs ): if span.is_recording(): - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) if should_emit_events(): return emit_event(event, event_logger) @@ -157,7 +157,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "AlephAlpha", + SpanAttributes.GEN_AI_SYSTEM: "AlephAlpha", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) diff --git a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py index c604a5f6f9..52ab191646 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py +++ b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py @@ -16,10 +16,10 @@ def set_prompt_attributes(event: PromptEvent, span: Span): return if should_send_prompts(): - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.content", + f"{SpanAttributes.GEN_AI_PROMPT}.0.content", event.content[0].get("data"), ) @@ -36,9 +36,9 @@ def set_completion_attributes(event: CompletionEvent, span: Span): if should_send_prompts(): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", event.message["content"], ) _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py index ebb1234883..86668e3556 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py @@ -127,7 +127,7 @@ async def _aset_token_usage( input_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) @@ -154,7 +154,7 @@ async def _aset_token_usage( completion_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) @@ -220,7 +220,7 @@ def _set_token_usage( input_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) @@ -245,7 +245,7 @@ def _set_token_usage( completion_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) @@ -397,7 +397,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Anthropic", + SpanAttributes.GEN_AI_SYSTEM: "Anthropic", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -494,7 +494,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Anthropic", + SpanAttributes.GEN_AI_SYSTEM: "Anthropic", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py index da7baa2063..a3fbc3f032 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py @@ -73,14 +73,14 @@ async def _dump_content(message_index, content, span): async def aset_input_attributes(span, kwargs): from opentelemetry.instrumentation.anthropic import set_span_attribute - set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("model")) + set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") ) set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, kwargs.get("top_p")) + set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -92,7 +92,7 @@ async def aset_input_attributes(span, kwargs): if should_send_prompts(): if kwargs.get("prompt") is not None: set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.user", kwargs.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) elif kwargs.get("messages") is not None: @@ -101,28 +101,28 @@ async def aset_input_attributes(span, kwargs): has_system_message = True set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.content", + f"{SpanAttributes.GEN_AI_PROMPT}.0.content", await _dump_content( message_index=0, span=span, content=kwargs.get("system") ), ) set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.role", + f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "system", ) for i, message in enumerate(kwargs.get("messages")): prompt_index = i + (1 if has_system_message else 0) set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", await _dump_content( message_index=i, span=span, content=message.get("content") ), ) set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", message.get("role"), ) @@ -146,7 +146,7 @@ def _set_span_completions(span, response): from opentelemetry.instrumentation.anthropic import set_span_attribute index = 0 - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" set_span_attribute(span, f"{prefix}.finish_reason", response.get("stop_reason")) if response.get("role"): set_span_attribute(span, f"{prefix}.role", response.get("role")) @@ -177,7 +177,7 @@ def _set_span_completions(span, response): ) # increment the index for subsequent content blocks index += 1 - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" # set the role to the original role on the next completions set_span_attribute( span, @@ -213,7 +213,7 @@ def set_response_attributes(span, response): if not isinstance(response, dict): response = response.__dict__ - set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response.get("model")) + set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) set_span_attribute(span, GEN_AI_RESPONSE_ID, response.get("id")) if response.get("usage"): @@ -245,7 +245,7 @@ def set_streaming_response_attributes(span, complete_response_events): try: for event in complete_response_events: index = event.get("index") - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" set_span_attribute( span, f"{prefix}.finish_reason", event.get("finish_reason") ) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py index bf8f33963f..bc8e9ae5c9 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py @@ -91,7 +91,7 @@ def _set_token_usage( set_span_attribute(span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens) set_span_attribute( - span, SpanAttributes.LLM_RESPONSE_MODEL, complete_response.get("model") + span, SpanAttributes.GEN_AI_RESPONSE_MODEL, complete_response.get("model") ) set_span_attribute( span, SpanAttributes.LLM_USAGE_CACHE_READ_INPUT_TOKENS, cache_read_tokens @@ -107,7 +107,7 @@ def _set_token_usage( input_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) @@ -116,7 +116,7 @@ def _set_token_usage( completion_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py index c269e9b70d..00ccf266ee 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py @@ -71,7 +71,7 @@ def shared_metrics_attributes(response): return { **common_attributes, GEN_AI_SYSTEM: GEN_AI_SYSTEM_ANTHROPIC, - SpanAttributes.LLM_RESPONSE_MODEL: response.get("model"), + SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), } diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py index e43494d8fe..2a73372c46 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py @@ -34,10 +34,10 @@ def test_anthropic_completion_legacy( anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == f"{HUMAN_PROMPT}\nHello world\n{AI_PROMPT}" ) - assert anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( anthropic_span.attributes.get("gen_ai.response.id") == "compl_01EjfrPvPEsRDRUKD6VoBxtK" diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py index 10cd7858b7..758565c63b 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py @@ -56,16 +56,16 @@ def test_anthropic_message_create_legacy( anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 @@ -235,20 +235,20 @@ def test_anthropic_multi_modal_legacy( ] anthropic_span = spans[0] assert anthropic_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps( [ {"type": "text", "text": "What do you see?"}, {"type": "image_url", "image_url": {"url": "/some/url"}}, ] ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1381 @@ -430,53 +430,53 @@ def test_anthropic_image_with_history( spans = span_exporter.get_finished_spans() assert all(span.name == "anthropic.chat" for span in spans) assert ( - spans[0].attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == system_message + spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_message ) - assert spans[0].attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - spans[0].attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == "Are you capable of describing an image?" ) - assert spans[0].attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "user" + assert spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert ( - spans[0].attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + spans[0].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response1.content[0].text ) assert ( - spans[0].attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] == "assistant" + spans[0].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) assert ( spans[0].attributes.get("gen_ai.response.id") == "msg_01Ctc62hUPvikvYASXZqTo9q" ) assert ( - spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == system_message + spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_message ) - assert spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == "Are you capable of describing an image?" ) - assert spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "user" + assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert ( - spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"] + spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] == response1.content[0].text ) - assert spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "assistant" + assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "assistant" assert json.loads( - spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.3.content"] + spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.content"] ) == [ {"type": "text", "text": "What do you see?"}, {"type": "image_url", "image_url": {"url": "/some/url"}}, ] - assert spans[1].attributes[f"{SpanAttributes.LLM_PROMPTS}.3.role"] == "user" + assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.role"] == "user" assert ( - spans[1].attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + spans[1].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response2.content[0].text ) assert ( - spans[1].attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] == "assistant" + spans[1].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) assert ( spans[1].attributes.get("gen_ai.response.id") == "msg_01EtAvxHCWn5jjdUCnG4wEAd" @@ -516,20 +516,20 @@ async def test_anthropic_async_multi_modal_legacy( ] anthropic_span = spans[0] assert anthropic_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps( [ {"type": "text", "text": "What do you see?"}, {"type": "image_url", "image_url": {"url": "/some/url"}}, ] ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1311 @@ -705,16 +705,16 @@ def test_anthropic_message_streaming_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 @@ -892,16 +892,16 @@ async def test_async_anthropic_message_create_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 @@ -1070,16 +1070,16 @@ async def test_async_anthropic_message_streaming_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/utils.py b/packages/opentelemetry-instrumentation-anthropic/tests/utils.py index e5ebea7b2c..e37b1a6143 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/utils.py @@ -16,12 +16,12 @@ def verify_metrics( if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert ( - data_point.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + data_point.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == model_name ) if not ignore_zero_input_tokens: @@ -32,7 +32,7 @@ def verify_metrics( for data_point in metric.data.data_points: assert data_point.value >= 1 assert ( - data_point.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + data_point.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == model_name ) @@ -45,7 +45,7 @@ def verify_metrics( data_point.sum > 0 for data_point in metric.data.data_points ) assert all( - data_point.attributes.get(SpanAttributes.LLM_RESPONSE_MODEL) + data_point.attributes.get(SpanAttributes.GEN_AI_RESPONSE_MODEL) == model_name or data_point.attributes.get("error.type") == "TypeError" for data_point in metric.data.data_points diff --git a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py index d5e484ef40..f3ebf27e45 100644 --- a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py +++ b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py @@ -36,7 +36,7 @@ def handle_invoke_metrics(t: Type, guardrail, attrs, metric_params): input_latency, attributes={ **attrs, - SpanAttributes.LLM_TOKEN_TYPE: t.value, + SpanAttributes.GEN_AI_TOKEN_TYPE: t.value, }, ) if "guardrailCoverage" in guardrail["invocationMetrics"]: @@ -46,7 +46,7 @@ def handle_invoke_metrics(t: Type, guardrail, attrs, metric_params): char_guarded, attributes={ **attrs, - SpanAttributes.LLM_TOKEN_TYPE: t.value, + SpanAttributes.GEN_AI_TOKEN_TYPE: t.value, }, ) @@ -133,8 +133,8 @@ def handle_words(t: Type, guardrail, attrs, metric_params): def guardrail_converse(response, vendor, model, metric_params): attrs = { "gen_ai.vendor": vendor, - SpanAttributes.LLM_RESPONSE_MODEL: model, - SpanAttributes.LLM_SYSTEM: "bedrock", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model, + SpanAttributes.GEN_AI_SYSTEM: "bedrock", } if "trace" in response and "guardrail" in response["trace"]: guardrail = response["trace"]["guardrail"] @@ -157,8 +157,8 @@ def guardrail_handling(response_body, vendor, model, metric_params): if "amazon-bedrock-guardrailAction" in response_body: attrs = { "gen_ai.vendor": vendor, - SpanAttributes.LLM_RESPONSE_MODEL: model, - SpanAttributes.LLM_SYSTEM: "bedrock", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model, + SpanAttributes.GEN_AI_SYSTEM: "bedrock", } if "amazon-bedrock-trace" in response_body: bedrock_trace = response_body["amazon-bedrock-trace"] diff --git a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py index 13ddb05d60..1e8d7ab2e8 100644 --- a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py +++ b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py @@ -34,12 +34,12 @@ def set_model_message_span_attributes(model_vendor, span, request_body): for idx, message in enumerate(request_body.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{idx}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", message.get("role"), ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.content", + f"{SpanAttributes.GEN_AI_PROMPT}.0.content", json.dumps(message.get("content")), ) elif model_vendor == "ai21": @@ -82,9 +82,9 @@ def set_model_span_attributes( response_model = response_body.get("model") response_id = response_body.get("id") - _set_span_attribute(span, SpanAttributes.LLM_SYSTEM, provider) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, model) - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response_model) + _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, provider) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response_model) _set_span_attribute(span, GEN_AI_RESPONSE_ID, response_id) if model_vendor == "cohere": @@ -114,7 +114,7 @@ def set_model_span_attributes( def _set_prompt_span_attributes(span, request_body): _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.user", request_body.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", request_body.get("prompt") ) @@ -122,12 +122,12 @@ def _set_cohere_span_attributes(span, request_body, response_body, metric_params _set_span_attribute( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, request_body.get("p")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("p")) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, request_body.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, request_body.get("max_tokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens") ) # based on contract at @@ -154,7 +154,7 @@ def _set_generations_span_attributes(span, response_body): for i, generation in enumerate(response_body.get("generations")): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", generation.get("text"), ) @@ -166,14 +166,14 @@ def _set_anthropic_completion_span_attributes( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, request_body.get("top_p") + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, request_body.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( span, - SpanAttributes.LLM_REQUEST_MAX_TOKENS, + SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens_to_sample"), ) @@ -208,16 +208,16 @@ def _set_anthropic_response_span_attributes(span, response_body): if response_body.get("completion") is not None: _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("completion"), ) elif response_body.get("content") is not None: _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.content", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", "assistant" ) _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", json.dumps(response_body.get("content")), ) @@ -229,14 +229,14 @@ def _set_anthropic_messages_span_attributes( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.CHAT.value ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, request_body.get("top_p") + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, request_body.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( span, - SpanAttributes.LLM_REQUEST_MAX_TOKENS, + SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens"), ) @@ -284,13 +284,13 @@ def _set_ai21_span_attributes(span, request_body, response_body, metric_params): span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, request_body.get("topP") + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("topP") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, request_body.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, request_body.get("maxTokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("maxTokens") ) _record_usage_to_span( @@ -305,7 +305,7 @@ def _set_span_completions_attributes(span, response_body): for i, completion in enumerate(response_body.get("completions")): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", completion.get("data").get("text"), ) @@ -315,13 +315,13 @@ def _set_llama_span_attributes(span, request_body, response_body, metric_params) span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, request_body.get("top_p") + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, request_body.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, request_body.get("max_gen_len") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_gen_len") ) _record_usage_to_span( @@ -334,28 +334,28 @@ def _set_llama_span_attributes(span, request_body, response_body, metric_params) def _set_llama_prompt_span_attributes(span, request_body): _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", request_body.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", request_body.get("prompt") ) - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") def _set_llama_response_span_attributes(span, response_body): if response_body.get("generation"): _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("generation"), ) else: for i, generation in enumerate(response_body.get("generations")): _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.role", "assistant" ) _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", generation + span, f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", generation ) @@ -368,21 +368,21 @@ def _set_amazon_span_attributes( if "textGenerationConfig" in request_body: config = request_body.get("textGenerationConfig", {}) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, config.get("topP")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, config.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, config.get("maxTokenCount") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokenCount") ) elif "inferenceConfig" in request_body: config = request_body.get("inferenceConfig", {}) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, config.get("topP")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, config.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, config.get("maxTokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokens") ) total_completion_tokens = 0 @@ -419,7 +419,7 @@ def _set_amazon_input_span_attributes(span, request_body): if "inputText" in request_body: _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.user", + f"{SpanAttributes.GEN_AI_PROMPT}.0.user", request_body.get("inputText"), ) else: @@ -428,24 +428,24 @@ def _set_amazon_input_span_attributes(span, request_body): for idx, prompt in enumerate(request_body["system"]): prompt_idx = idx + 1 _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{idx}.role", "system" + span, f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", "system" ) # TODO: add support for "image" _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{idx}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", prompt.get("text"), ) for idx, prompt in enumerate(request_body["messages"]): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_idx + idx}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx + idx}.role", prompt.get("role"), ) # TODO: here we stringify the object, consider moving these to events or prompt.{i}.content.{j} _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_idx + idx}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx + idx}.content", json.dumps(prompt.get("content", ""), default=str), ) @@ -455,13 +455,13 @@ def _set_amazon_response_span_attributes(span, response_body): for i, result in enumerate(response_body.get("results")): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", result.get("outputText"), ) elif "outputText" in response_body: _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("outputText"), ) elif "output" in response_body: @@ -469,7 +469,7 @@ def _set_amazon_response_span_attributes(span, response_body): for idx, msg in enumerate(msgs): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content", msg.get("text"), ) @@ -481,13 +481,13 @@ def _set_imported_model_span_attributes( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, request_body.get("topP") + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("topP") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, request_body.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, request_body.get("max_tokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens") ) prompt_tokens = ( response_body.get("usage", {}).get("prompt_tokens") @@ -509,14 +509,14 @@ def _set_imported_model_span_attributes( def _set_imported_model_response_span_attributes(span, response_body): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("generation"), ) def _set_imported_model_prompt_span_attributes(span, request_body): _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", request_body.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", request_body.get("prompt") ) @@ -557,7 +557,7 @@ def _record_usage_to_span(span, prompt_tokens, completion_tokens, metric_params) prompt_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) if ( @@ -569,7 +569,7 @@ def _record_usage_to_span(span, prompt_tokens, completion_tokens, metric_params) completion_tokens, attributes={ **metric_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) @@ -579,15 +579,15 @@ def _metric_shared_attributes( ): return { "vendor": response_vendor, - SpanAttributes.LLM_RESPONSE_MODEL: response_model, - SpanAttributes.LLM_SYSTEM: "bedrock", + SpanAttributes.GEN_AI_RESPONSE_MODEL: response_model, + SpanAttributes.GEN_AI_SYSTEM: "bedrock", "stream": is_streaming, } def set_converse_model_span_attributes(span, provider, model, kwargs): - _set_span_attribute(span, SpanAttributes.LLM_SYSTEM, provider) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, model) + _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, provider) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) _set_span_attribute( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.CHAT.value ) @@ -596,12 +596,12 @@ def set_converse_model_span_attributes(span, provider, model, kwargs): if "inferenceConfig" in kwargs: config = kwargs.get("inferenceConfig") - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, config.get("topP")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, config.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, config.get("maxTokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokens") ) @@ -613,25 +613,25 @@ def set_converse_input_prompt_span_attributes(kwargs, span): for idx, prompt in enumerate(kwargs["system"]): prompt_idx = idx + 1 _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{idx}.role", "system" + span, f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", "system" ) # TODO: add support for "image" _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{idx}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", prompt.get("text"), ) if "messages" in kwargs: for idx, prompt in enumerate(kwargs["messages"]): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_idx+idx}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx+idx}.role", prompt.get("role"), ) # TODO: here we stringify the object, consider moving these to events or prompt.{i}.content.{j} _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_idx+idx}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx+idx}.content", json.dumps(prompt.get("content", ""), default=str), ) @@ -642,12 +642,12 @@ def set_converse_response_span_attributes(response, span): if "output" in response: message = response["output"]["message"] _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", message.get("role") + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", message.get("role") ) for idx, content in enumerate(message["content"]): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content", content.get("text"), ) @@ -655,9 +655,9 @@ def set_converse_response_span_attributes(response, span): def set_converse_streaming_response_span_attributes(response, role, span): if not should_send_prompts(): return - _set_span_attribute(span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", role) + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", role) _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.content", "".join(response) + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", "".join(response) ) diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py index f039ee2375..8ac0e5f615 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py @@ -101,7 +101,7 @@ def assert_guardrails(reader): if metric.name == GuardrailMeters.LLM_BEDROCK_GUARDRAIL_LATENCY: found_latency = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -115,14 +115,14 @@ def assert_guardrails(reader): if metric.name == GuardrailMeters.LLM_BEDROCK_GUARDRAIL_COVERAGE: found_coverage = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert data_point.value > 0 assert ( - metric.data.data_points[0].attributes[SpanAttributes.LLM_SYSTEM] + metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] == "bedrock" ) diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py index eaf693e8b2..51c0a0fb57 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py @@ -44,7 +44,7 @@ def test_invoke_model_metrics(test_context, brt): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -60,7 +60,7 @@ def test_invoke_model_metrics(test_context, brt): ) assert ( - metric.data.data_points[0].attributes[SpanAttributes.LLM_SYSTEM] + metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] == "bedrock" ) diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py index 4e5cc7e5f6..4f2fb541d8 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py @@ -37,11 +37,11 @@ def test_anthropic_2_completion(instrument_legacy, brt, span_exporter, log_expor anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Human: Tell me a joke about opentelemetry Assistant:" ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == completion ) @@ -203,14 +203,14 @@ def test_anthropic_3_completion_complex_content( anthropic_span = spans[0] assert json.loads( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "Tell me a joke about opentelemetry"}, ] assert ( json.loads( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") ) == completion ) @@ -404,13 +404,13 @@ def test_anthropic_3_completion_streaming( anthropic_span = spans[0] assert json.loads( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "Tell me a joke about opentelemetry"}, ] assert json.loads( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") ) == [ { "type": "text", @@ -606,13 +606,13 @@ def test_anthropic_3_completion_string_content( anthropic_span = spans[0] assert ( - json.loads(anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"]) + json.loads(anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) == "Tell me a joke about opentelemetry" ) assert ( json.loads( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") ) == completion ) @@ -784,16 +784,16 @@ def test_anthropic_cross_region(instrument_legacy, brt, span_exporter, log_expor # Assert on model name and vendor assert ( - anthropic_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-3-7-sonnet-20250219-v1" ) - assert anthropic_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert anthropic_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" assert anthropic_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(messages[0]["content"]) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == completion ) @@ -840,10 +840,10 @@ def test_anthropic_cross_region_with_events_with_content( # Assert on model name and vendor assert ( - anthropic_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-3-7-sonnet-20250219-v1" ) - assert anthropic_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert anthropic_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 20 assert anthropic_span.attributes.get( @@ -906,10 +906,10 @@ def test_anthropic_cross_region_with_events_with_no_content( # Assert on model name and vendor assert ( - anthropic_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-3-7-sonnet-20250219-v1" ) - assert anthropic_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert anthropic_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 20 assert anthropic_span.attributes.get( diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py index b911c0ebaa..d3faf54024 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py @@ -41,22 +41,22 @@ def test_cohere_completion(instrument_legacy, brt, span_exporter, log_exporter): # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "command-text-v14" + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] == prompt + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == prompt # Assert on response generated_text = response_body["generations"][0]["text"] assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == generated_text ) assert ( @@ -65,9 +65,9 @@ def test_cohere_completion(instrument_legacy, brt, span_exporter, log_exporter): ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 logs = log_exporter.get_finished_logs() assert ( @@ -103,11 +103,11 @@ def test_cohere_completion_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "command-text-v14" + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -119,9 +119,9 @@ def test_cohere_completion_with_events_with_no_content( ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -171,11 +171,11 @@ def test_cohere_completion_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "command-text-v14" + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -188,9 +188,9 @@ def test_cohere_completion_with_events_with_content( ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py index 40f8f9e237..8fcc0ba202 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py @@ -27,20 +27,20 @@ def test_imported_model_completion(instrument_legacy, brt, span_exporter, log_ex imported_model_span = spans[0] assert ( - imported_model_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "arn:aws:sagemaker:us-east-1:767398002385:endpoint/endpoint-quick-start-idr7y" ) assert ( imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" ) - assert imported_model_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert imported_model_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" assert imported_model_span.attributes.get("gen_ai.response.id") is None - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 100 - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 2 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 2 assert ( - imported_model_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + imported_model_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == prompt ) assert data is not None @@ -69,17 +69,17 @@ def test_imported_model_completion_with_events_with_content( imported_model_span = spans[0] assert ( - imported_model_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "arn:aws:sagemaker:us-east-1:767398002385:endpoint/endpoint-quick-start-idr7y" ) assert ( imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" ) - assert imported_model_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert imported_model_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" assert imported_model_span.attributes.get("gen_ai.response.id") is None - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 100 - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 2 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 2 assert data is not None @@ -117,17 +117,17 @@ def test_imported_model_completion_with_events_with_no_content( imported_model_span = spans[0] assert ( - imported_model_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "arn:aws:sagemaker:us-east-1:767398002385:endpoint/endpoint-quick-start-idr7y" ) assert ( imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" ) - assert imported_model_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert imported_model_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" assert imported_model_span.attributes.get("gen_ai.response.id") is None - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 100 - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 2 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 2 assert data is not None diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py index eaa71f8b4b..43b0d0d876 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py @@ -201,9 +201,9 @@ def test_meta_llama3_completion(instrument_legacy, brt, span_exporter, log_expor meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == response_body["generation_token_count"] + response_body["prompt_token_count"] ) - assert meta_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == prompt + assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == prompt assert ( - meta_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response_body["generation"] ) assert meta_span.attributes.get("gen_ai.response.id") is None @@ -350,21 +350,21 @@ def test_meta_converse(instrument_legacy, brt, span_exporter, log_exporter): meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == response["usage"]["totalTokens"] ) - assert meta_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - meta_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == system_prompt + meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_prompt ) - assert meta_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "user" + assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert meta_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.1.content" + f"{SpanAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0]["content"]) for i in range(0, len(generated_text)): assert ( - meta_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role"] + meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.role"] == "assistant" ) assert ( - meta_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content"] + meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) assert meta_span.attributes.get("gen_ai.response.id") is None @@ -558,21 +558,21 @@ def test_meta_converse_stream(instrument_legacy, brt, span_exporter, log_exporte meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == inputTokens + outputTokens ) - assert meta_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - meta_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == system_prompt + meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_prompt ) - assert meta_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "user" + assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert meta_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.1.content" + f"{SpanAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0]["content"]) assert ( - meta_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] + meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == response_role ) assert ( - meta_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] == content + meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == content ) assert meta_span.attributes.get("gen_ai.response.id") is None diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py index 54fcb3fbae..2241f43822 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py @@ -43,39 +43,39 @@ def test_nova_completion(instrument_legacy, brt, span_exporter, log_exporter): bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == system_list[0].get("text") # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "user" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.1.content" + f"{SpanAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(message_list[0].get("content"), default=str) # Assert on response generated_text = response_body["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -120,10 +120,10 @@ def test_nova_completion_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -132,9 +132,9 @@ def test_nova_completion_with_events_with_content( generated_text = response_body["output"]["message"]["content"] # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -199,18 +199,18 @@ def test_nova_completion_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -278,42 +278,42 @@ def test_nova_invoke_stream(instrument_legacy, brt, span_exporter, log_exporter) bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == system_list[0].get("text") # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "user" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.1.content" + f"{SpanAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(message_list[0].get("content"), default=str) # Assert on response completion_msg = "".join(generated_text) assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == completion_msg ) # Assert on other request parameters assert bedrock_span.attributes[ - SpanAttributes.LLM_REQUEST_MAX_TOKENS + SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS ] == inf_params.get("maxTokens") assert bedrock_span.attributes[ - SpanAttributes.LLM_REQUEST_TEMPERATURE + SpanAttributes.GEN_AI_REQUEST_TEMPERATURE ] == inf_params.get("temperature") - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == inf_params.get( + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( "topP" ) # There is no response id for Amazon Titan models in the response body, @@ -371,10 +371,10 @@ def test_nova_invoke_stream_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -384,12 +384,12 @@ def test_nova_invoke_stream_with_events_with_content( # Assert on other request parameters assert bedrock_span.attributes[ - SpanAttributes.LLM_REQUEST_MAX_TOKENS + SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS ] == inf_params.get("maxTokens") assert bedrock_span.attributes[ - SpanAttributes.LLM_REQUEST_TEMPERATURE + SpanAttributes.GEN_AI_REQUEST_TEMPERATURE ] == inf_params.get("temperature") - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == inf_params.get( + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( "topP" ) # There is no response id for Amazon Titan models in the response body, @@ -469,22 +469,22 @@ def test_nova_invoke_stream_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters assert bedrock_span.attributes[ - SpanAttributes.LLM_REQUEST_MAX_TOKENS + SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS ] == inf_params.get("maxTokens") assert bedrock_span.attributes[ - SpanAttributes.LLM_REQUEST_TEMPERATURE + SpanAttributes.GEN_AI_REQUEST_TEMPERATURE ] == inf_params.get("temperature") - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == inf_params.get( + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( "topP" ) # There is no response id for Amazon Titan models in the response body, @@ -565,37 +565,37 @@ def test_nova_converse(instrument_legacy, brt, span_exporter, log_exporter): bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == system[ + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system[ 0 ].get("text") # Assert on prompt assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.1.content" + f"{SpanAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response generated_text = response["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 logs = log_exporter.get_finished_logs() assert ( @@ -659,18 +659,18 @@ def test_nova_converse_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 logs = log_exporter.get_finished_logs() assert len(logs) == 3 @@ -755,18 +755,18 @@ def test_nova_converse_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 logs = log_exporter.get_finished_logs() assert len(logs) == 3 @@ -863,39 +863,39 @@ def test_nova_converse_stream(instrument_legacy, brt, span_exporter, log_exporte bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == system[ + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system[ 0 ].get("text") # Assert on prompt assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.1.content" + f"{SpanAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == content ) assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == response_role ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 # Assert on usage data assert ( @@ -989,18 +989,18 @@ def test_nova_converse_stream_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 # Assert on usage data assert ( @@ -1114,18 +1114,18 @@ def test_nova_converse_stream_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 # Assert on usage data assert ( @@ -1191,34 +1191,34 @@ def test_nova_cross_region_invoke(instrument_legacy, brt, span_exporter, log_exp bedrock_span = spans[0] # Assert on model name and vendor - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(message_list[0].get("content"), default=str) # Assert on response generated_text = response_body["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -1262,19 +1262,19 @@ def test_nova_cross_region_invoke_with_events_with_content( bedrock_span = spans[0] # Assert on model name and vendor - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -1329,19 +1329,19 @@ def test_nova_cross_region_invoke_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name and vendor - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "nova-lite-v1:0" - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py index 68dd1d3b0a..088e8fa790 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py @@ -43,12 +43,12 @@ def test_titan_completion(instrument_legacy, brt, span_exporter, log_exporter): # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -59,21 +59,21 @@ def test_titan_completion(instrument_legacy, brt, span_exporter, log_exporter): "scale generative AI applications with base models (FMs)'." ) assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == expected_prompt ) # Assert on response generated_text = response_body["results"][0]["outputText"] assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == generated_text ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -118,20 +118,20 @@ def test_titan_completion_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -190,20 +190,20 @@ def test_titan_completion_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -266,12 +266,12 @@ def test_titan_invoke_stream(instrument_legacy, brt, span_exporter, log_exporter # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -282,21 +282,21 @@ def test_titan_invoke_stream(instrument_legacy, brt, span_exporter, log_exporter "scale generative AI applications with base models (FMs)'." ) assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == expected_prompt ) # Assert on response completion_text = "".join(generated_text) assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == completion_text ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -351,20 +351,20 @@ def test_titan_invoke_stream_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -436,20 +436,20 @@ def test_titan_invoke_stream_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -516,27 +516,27 @@ def test_titan_converse(instrument_legacy, brt, span_exporter, log_exporter): # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response generated_text = response["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) @@ -594,12 +594,12 @@ def test_titan_converse_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" @@ -671,12 +671,12 @@ def test_titan_converse_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" @@ -766,29 +766,29 @@ def test_titan_converse_stream(instrument_legacy, brt, span_exporter, log_export # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.content" + f"{SpanAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == content ) assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == response_role ) @@ -878,12 +878,12 @@ def test_titan_converse_stream_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" @@ -986,12 +986,12 @@ def test_titan_converse_stream_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" diff --git a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py index 5e43e1e43e..8bede4d48f 100644 --- a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py +++ b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py @@ -114,7 +114,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Cohere", + SpanAttributes.GEN_AI_SYSTEM: "Cohere", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) as span: diff --git a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py index a1a2d2aa03..4861115446 100644 --- a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py +++ b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py @@ -26,32 +26,32 @@ def set_input_attributes(span, llm_request_type, kwargs): if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.COMPLETION: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", kwargs.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("prompt") ) elif llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", kwargs.get("message") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("message") ) elif llm_request_type == LLMRequestTypeValues.RERANK: for index, document in enumerate(kwargs.get("documents")): _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{index}.role", "system" + span, f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", "system" ) _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{index}.content", document + span, f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", document ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{len(kwargs.get('documents'))}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{len(kwargs.get('documents'))}.role", "user", ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{len(kwargs.get('documents'))}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{len(kwargs.get('documents'))}.content", kwargs.get("query"), ) @@ -75,14 +75,14 @@ def set_span_request_attributes(span, kwargs): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) _set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -93,7 +93,7 @@ def set_span_request_attributes(span, kwargs): def _set_span_chat_response(span, response): index = 0 - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", response.text) _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.response_id) @@ -145,7 +145,7 @@ def _set_span_generations_response(span, response): generations = response # Cohere v4 for index, generation in enumerate(generations): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", generation.text) _set_span_attribute(span, f"gen_ai.response.{index}.id", generation.id) @@ -153,7 +153,7 @@ def _set_span_generations_response(span, response): def _set_span_rerank_response(span, response): _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.id) for idx, doc in enumerate(response.results): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{idx}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}" _set_span_attribute(span, f"{prefix}.role", "assistant") content = f"Doc {doc.index}, Score: {doc.relevance_score}" if doc.document: diff --git a/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py b/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py index fd97cf45ce..c6a8ea9fd5 100644 --- a/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py @@ -18,15 +18,15 @@ def test_cohere_chat_legacy( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.chat" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "chat" - assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" assert ( - cohere_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke, pirate style" ) assert ( - cohere_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == res.text ) assert cohere_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 58 @@ -56,9 +56,9 @@ def test_cohere_chat_with_events_with_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.chat" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "chat" - assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -85,9 +85,9 @@ def test_cohere_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.chat" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "chat" - assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py b/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py index 622ec31b23..d8731593e1 100644 --- a/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py +++ b/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py @@ -18,11 +18,11 @@ def test_cohere_completion_legacy( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.completion" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "completion" - assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" assert ( - cohere_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == res.generations[0].text ) assert ( @@ -50,9 +50,9 @@ def test_cohere_completion_with_events_with_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.completion" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "completion" - assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -78,9 +78,9 @@ def test_cohere_completion_with_events_with_no_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.completion" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "completion" - assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py b/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py index 3da05d7417..61f3a7b0f4 100644 --- a/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py +++ b/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py @@ -38,43 +38,43 @@ def test_cohere_rerank_legacy( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.rerank" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "rerank" assert ( - cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) + cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "rerank-multilingual-v2.0" ) assert ( cohere_span.attributes.get( - f"{SpanAttributes.LLM_PROMPTS}.{len(documents)}.role" + f"{SpanAttributes.GEN_AI_PROMPT}.{len(documents)}.role" ) == "user" ) assert ( cohere_span.attributes.get( - f"{SpanAttributes.LLM_PROMPTS}.{len(documents)}.content" + f"{SpanAttributes.GEN_AI_PROMPT}.{len(documents)}.content" ) == query ) for i, doc in enumerate(documents): assert ( - cohere_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.{i}.role") + cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role") == "system" ) assert ( - cohere_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.{i}.content") + cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content") == doc ) for idx, result in enumerate(response.results): assert ( - cohere_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.role") + cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role") == "assistant" ) assert ( cohere_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content" ) == f"Doc {result.index}, Score: {result.relevance_score}" ) @@ -118,10 +118,10 @@ def test_cohere_rerank_with_events_with_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.rerank" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "rerank" assert ( - cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) + cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "rerank-multilingual-v2.0" ) @@ -182,10 +182,10 @@ def test_cohere_rerank_with_events_with_no_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.rerank" - assert cohere_span.attributes.get(SpanAttributes.LLM_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "rerank" assert ( - cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_MODEL) + cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "rerank-multilingual-v2.0" ) diff --git a/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py b/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py index b5404144ce..b483b03e40 100644 --- a/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py +++ b/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py @@ -71,7 +71,7 @@ def wrap_kickoff(tracer: Tracer, duration_histogram: Histogram, token_histogram: "crewai.workflow", kind=SpanKind.INTERNAL, attributes={ - SpanAttributes.LLM_SYSTEM: "crewai", + SpanAttributes.GEN_AI_SYSTEM: "crewai", } ) as span: try: @@ -108,22 +108,22 @@ def wrap_agent_execute_task(tracer, duration_histogram, token_histogram, wrapped token_histogram.record( instance._token_process.get_summary().prompt_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "crewai", - SpanAttributes.LLM_TOKEN_TYPE: "input", - SpanAttributes.LLM_RESPONSE_MODEL: str(instance.llm.model), + SpanAttributes.GEN_AI_SYSTEM: "crewai", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_RESPONSE_MODEL: str(instance.llm.model), } ) token_histogram.record( instance._token_process.get_summary().completion_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "crewai", - SpanAttributes.LLM_TOKEN_TYPE: "output", - SpanAttributes.LLM_RESPONSE_MODEL: str(instance.llm.model), + SpanAttributes.GEN_AI_SYSTEM: "crewai", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_RESPONSE_MODEL: str(instance.llm.model), }, ) - set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, str(instance.llm.model)) - set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, str(instance.llm.model)) + set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, str(instance.llm.model)) + set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, str(instance.llm.model)) span.set_status(Status(StatusCode.OK)) return result except Exception as ex: @@ -172,8 +172,8 @@ def wrap_llm_call(tracer, duration_histogram, token_histogram, wrapped, instance duration_histogram.record( duration, attributes={ - SpanAttributes.LLM_SYSTEM: "crewai", - SpanAttributes.LLM_RESPONSE_MODEL: str(instance.model) + SpanAttributes.GEN_AI_SYSTEM: "crewai", + SpanAttributes.GEN_AI_RESPONSE_MODEL: str(instance.model) }, ) diff --git a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py index c2424d10c1..c2b03fa5d6 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py @@ -194,7 +194,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Google", + SpanAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -252,7 +252,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Google", + SpanAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py index 9879ed5136..2ae944fa9e 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py @@ -28,12 +28,12 @@ def set_input_attributes(span, args, kwargs, llm_model): if isinstance(contents, str): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.content", + f"{SpanAttributes.GEN_AI_PROMPT}.0.content", contents, ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.role", + f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user", ) elif isinstance(contents, list): @@ -43,12 +43,12 @@ def set_input_attributes(span, args, kwargs, llm_model): if hasattr(part, "text"): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", part.text, ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", getattr(content, "role", "user"), ) elif args and len(args) > 0: @@ -62,32 +62,32 @@ def set_input_attributes(span, args, kwargs, llm_model): if prompt: _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.content", + f"{SpanAttributes.GEN_AI_PROMPT}.0.content", prompt, ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.role", + f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user", ) elif "prompt" in kwargs: _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", kwargs["prompt"] + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs["prompt"] ) - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") def set_model_request_attributes(span, kwargs, llm_model): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, llm_model) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, llm_model) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") ) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) _set_span_attribute(span, SpanAttributes.LLM_TOP_K, kwargs.get("top_k")) _set_span_attribute( span, SpanAttributes.LLM_PRESENCE_PENALTY, kwargs.get("presence_penalty") @@ -104,28 +104,28 @@ def set_response_attributes(span, response, llm_model): if hasattr(response, "usage_metadata"): if isinstance(response.text, list): for index, item in enumerate(response): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", item.text) _set_span_attribute(span, f"{prefix}.role", "assistant") elif isinstance(response.text, str): _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.content", response.text + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response.text ) _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) else: if isinstance(response, list): for index, item in enumerate(response): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", item) _set_span_attribute(span, f"{prefix}.role", "assistant") elif isinstance(response, str): _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.content", response + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response ) _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) @@ -133,7 +133,7 @@ def set_model_response_attributes(span, response, llm_model): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, llm_model) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, llm_model) if hasattr(response, "usage_metadata"): _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py b/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py index 11a9787e60..153c5e86c6 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py @@ -24,16 +24,16 @@ def test_gemini_generate_content_legacy( # gemini_span = spans[0] # assert ( - # gemini_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + # gemini_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] # == "The opposite of hot is\n" # ) - # assert gemini_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + # assert gemini_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" # assert ( - # gemini_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + # gemini_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") # == "cold\n" # ) # assert ( - # gemini_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + # gemini_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") # == "assistant" # ) @@ -45,11 +45,11 @@ def test_gemini_generate_content_legacy( # ) # assert ( - # gemini_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + # gemini_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] # == "models/gemini-1.5-flash" # ) # assert ( - # gemini_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + # gemini_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] # == "models/gemini-1.5-flash" # ) @@ -83,11 +83,11 @@ def test_gemini_generate_content_with_events_with_content( # ) # assert ( - # gemini_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + # gemini_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] # == "models/gemini-1.5-flash" # ) # assert ( - # gemini_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + # gemini_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] # == "models/gemini-1.5-flash" # ) @@ -131,11 +131,11 @@ def test_gemini_generate_content_with_events_with_no_content( # ) # assert ( - # gemini_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + # gemini_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] # == "models/gemini-1.5-flash" # ) # assert ( - # gemini_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + # gemini_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] # == "models/gemini-1.5-flash" # ) diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py index 810e9ebd27..ab43a1d9b9 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py @@ -242,7 +242,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Groq", + SpanAttributes.GEN_AI_SYSTEM: "Groq", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -324,7 +324,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Groq", + SpanAttributes.GEN_AI_SYSTEM: "Groq", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py index 8af6035d3b..b37df8d38e 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py @@ -24,18 +24,18 @@ def set_input_attributes(span, kwargs): if should_send_prompts(): if kwargs.get("prompt") is not None: set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.user", kwargs.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) elif kwargs.get("messages") is not None: for i, message in enumerate(kwargs.get("messages")): set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", _dump_content(message.get("content")), ) set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{i}.role", message.get("role") + span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", message.get("role") ) @@ -44,14 +44,14 @@ def set_model_input_attributes(span, kwargs): if not span.is_recording(): return - set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("model")) + set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") ) set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, kwargs.get("top_p")) + set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -70,7 +70,7 @@ def set_streaming_response_attributes( if not span.is_recording() or not should_send_prompts(): return - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.0" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.0" set_span_attribute(span, f"{prefix}.role", "assistant") set_span_attribute(span, f"{prefix}.content", accumulated_content) if finish_reason: @@ -98,7 +98,7 @@ def set_model_response_attributes(span, response, token_histogram): if not span.is_recording(): return response = model_as_dict(response) - set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response.get("model")) + set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) set_span_attribute(span, GEN_AI_RESPONSE_ID, response.get("id")) usage = response.get("usage") or {} @@ -121,8 +121,8 @@ def set_model_response_attributes(span, response, token_histogram): token_histogram.record( prompt_tokens, attributes={ - SpanAttributes.LLM_TOKEN_TYPE: "input", - SpanAttributes.LLM_RESPONSE_MODEL: response.get("model"), + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -134,8 +134,8 @@ def set_model_response_attributes(span, response, token_histogram): token_histogram.record( completion_tokens, attributes={ - SpanAttributes.LLM_TOKEN_TYPE: "output", - SpanAttributes.LLM_RESPONSE_MODEL: response.get("model"), + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -154,7 +154,7 @@ def _set_completions(span, choices): for choice in choices: index = choice.get("index") - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" set_span_attribute(span, f"{prefix}.finish_reason", choice.get("finish_reason")) if choice.get("content_filter_results"): diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py index 21e65329e2..89b767f29a 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py @@ -60,7 +60,7 @@ def shared_metrics_attributes(response): return { **common_attributes, GEN_AI_SYSTEM: GEN_AI_SYSTEM_GROQ, - SpanAttributes.LLM_RESPONSE_MODEL: response_dict.get("model"), + SpanAttributes.GEN_AI_RESPONSE_MODEL: response_dict.get("model"), } diff --git a/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py b/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py index e1df364142..4414d4beb3 100644 --- a/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py +++ b/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py @@ -23,10 +23,10 @@ def test_chat_legacy(instrument_legacy, groq_client, span_exporter, log_exporter ] groq_span = spans[0] assert ( - groq_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + groq_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert groq_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 @@ -146,10 +146,10 @@ async def test_async_chat_legacy( ] groq_span = spans[0] assert ( - groq_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + groq_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert groq_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 @@ -277,11 +277,11 @@ def test_chat_streaming_legacy( ] groq_span = spans[0] assert ( - groq_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + groq_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - groq_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == content ) assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True diff --git a/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py b/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py index 7c5b93708f..6c4ef17bad 100644 --- a/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py +++ b/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py @@ -20,12 +20,12 @@ def _set_input_attributes(span, llm_request_type, kwargs): if llm_request_type == LLMRequestTypeValues.COMPLETION: set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.user", kwargs.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) elif llm_request_type == LLMRequestTypeValues.CHAT: set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.user", + f"{SpanAttributes.GEN_AI_PROMPT}.0.user", [message.content for message in kwargs.get("messages")], ) @@ -33,17 +33,17 @@ def _set_input_attributes(span, llm_request_type, kwargs): generation_kwargs = kwargs["generation_kwargs"] if "model" in generation_kwargs: set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MODEL, generation_kwargs["model"] + span, SpanAttributes.GEN_AI_REQUEST_MODEL, generation_kwargs["model"] ) if "temperature" in generation_kwargs: set_span_attribute( span, - SpanAttributes.LLM_REQUEST_TEMPERATURE, + SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, generation_kwargs["temperature"], ) if "top_p" in generation_kwargs: set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, generation_kwargs["top_p"] + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, generation_kwargs["top_p"] ) if "frequency_penalty" in generation_kwargs: set_span_attribute( @@ -66,7 +66,7 @@ def _set_span_completions(span, llm_request_type, choices): return for index, message in enumerate(choices): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" if llm_request_type == LLMRequestTypeValues.CHAT: if message is not None: @@ -104,7 +104,7 @@ def wrap(tracer, to_wrap, wrapped, instance, args, kwargs): ), kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "OpenAI", + SpanAttributes.GEN_AI_SYSTEM: "OpenAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) as span: diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py index 03c4475d88..8eeb5e0e6f 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py @@ -270,7 +270,7 @@ def _create_llm_span( entity_path=entity_path, metadata=metadata, ) - _set_span_attribute(span, SpanAttributes.LLM_SYSTEM, "Langchain") + _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, "Langchain") _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TYPE, request_type.value) return span @@ -437,11 +437,11 @@ def on_llm_end( "model_name" ) or response.llm_output.get("model_id") if model_name is not None: - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, model_name) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, model_name) if self.spans[run_id].request_model is None: _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MODEL, model_name + span, SpanAttributes.GEN_AI_REQUEST_MODEL, model_name ) id = response.llm_output.get("id") if id is not None and id != "": @@ -480,9 +480,9 @@ def on_llm_end( self.token_histogram.record( prompt_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "Langchain", - SpanAttributes.LLM_TOKEN_TYPE: "input", - SpanAttributes.LLM_RESPONSE_MODEL: model_name or "unknown", + SpanAttributes.GEN_AI_SYSTEM: "Langchain", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", }, ) @@ -490,9 +490,9 @@ def on_llm_end( self.token_histogram.record( completion_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "Langchain", - SpanAttributes.LLM_TOKEN_TYPE: "output", - SpanAttributes.LLM_RESPONSE_MODEL: model_name or "unknown", + SpanAttributes.GEN_AI_SYSTEM: "Langchain", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", }, ) set_chat_response_usage(span, response) @@ -507,8 +507,8 @@ def on_llm_end( self.duration_histogram.record( duration, attributes={ - SpanAttributes.LLM_SYSTEM: "Langchain", - SpanAttributes.LLM_RESPONSE_MODEL: model_name or "unknown", + SpanAttributes.GEN_AI_SYSTEM: "Langchain", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", }, ) diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py index 6c4725074c..b747a23ae7 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py @@ -69,9 +69,9 @@ def set_request_params(span, kwargs, span_holder: SpanHolder): else: model = "unknown" - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, model) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) # response is not available for LLM requests (as opposed to chat) - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, model) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, model) if "invocation_params" in kwargs: params = ( @@ -82,13 +82,13 @@ def set_request_params(span, kwargs, span_holder: SpanHolder): _set_span_attribute( span, - SpanAttributes.LLM_REQUEST_MAX_TOKENS, + SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, params.get("max_tokens") or params.get("max_new_tokens"), ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, params.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, params.get("temperature") ) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, params.get("top_p")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, params.get("top_p")) tools = kwargs.get("invocation_params", {}).get("tools", []) for i, tool in enumerate(tools): @@ -123,12 +123,12 @@ def set_llm_request( for i, msg in enumerate(prompts): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", "user", ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", msg, ) @@ -161,7 +161,7 @@ def set_chat_request( for msg in message: _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", _message_type_to_role(msg.type), ) tool_calls = ( @@ -172,7 +172,7 @@ def set_chat_request( if tool_calls: _set_chat_tool_calls( - span, f"{SpanAttributes.LLM_PROMPTS}.{i}", tool_calls + span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}", tool_calls ) else: @@ -183,14 +183,14 @@ def set_chat_request( ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", content, ) if msg.type == "tool" and hasattr(msg, "tool_call_id"): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.tool_call_id", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.tool_call_id", msg.tool_call_id, ) @@ -204,7 +204,7 @@ def set_chat_response(span: Span, response: LLMResult) -> None: i = 0 for generations in response.generations: for generation in generations: - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{i}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{i}" if hasattr(generation, "text") and generation.text != "": _set_span_attribute( span, diff --git a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py index 6c7583b645..f2c9c5828c 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py @@ -36,13 +36,13 @@ def test_llm_chain_metrics(instrument_legacy, reader, chain): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert data_point.sum > 0 assert ( - data_point.attributes[SpanAttributes.LLM_SYSTEM] + data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Langchain" ) @@ -56,7 +56,7 @@ def test_llm_chain_metrics(instrument_legacy, reader, chain): ) for data_point in metric.data.data_points: assert ( - data_point.attributes[SpanAttributes.LLM_SYSTEM] + data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Langchain" ) @@ -88,13 +88,13 @@ def test_llm_chain_streaming_metrics(instrument_legacy, reader, llm): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert data_point.sum > 0 assert ( - data_point.attributes[SpanAttributes.LLM_SYSTEM] + data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Langchain" ) @@ -108,7 +108,7 @@ def test_llm_chain_streaming_metrics(instrument_legacy, reader, llm): ) for data_point in metric.data.data_points: assert ( - data_point.attributes[SpanAttributes.LLM_SYSTEM] + data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Langchain" ) diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py b/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py index 36c5e2a46e..f896d0467d 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py @@ -123,14 +123,14 @@ def test_sequential_chain(instrument_legacy, span_exporter, log_exporter): openai_span = next(span for span in spans if span.name == "OpenAI.completion") assert ( - openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-instruct" ) assert ( - (openai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL]) + (openai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL]) == "gpt-3.5-turbo-instruct" ) - assert openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + assert openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] logs = log_exporter.get_finished_logs() assert ( @@ -213,11 +213,11 @@ def test_sequential_chain_with_events_with_content( openai_span = next(span for span in spans if span.name == "OpenAI.completion") assert ( - openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-instruct" ) assert ( - (openai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL]) + (openai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL]) == "gpt-3.5-turbo-instruct" ) @@ -334,11 +334,11 @@ def test_sequential_chain_with_events_with_no_content( openai_span = next(span for span in spans if span.name == "OpenAI.completion") assert ( - openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-instruct" ) assert ( - (openai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL]) + (openai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL]) == "gpt-3.5-turbo-instruct" ) diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py index b54255d0f8..ed9c1053cd 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py @@ -142,13 +142,13 @@ def test_custom_llm(instrument_legacy, span_exporter, log_exporter): ) assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" - assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "unknown" + assert hugging_face_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "unknown" assert ( - hugging_face_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + hugging_face_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "System: You are a helpful assistant\nHuman: tell me a short joke" ) assert ( - hugging_face_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + hugging_face_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -185,7 +185,7 @@ def test_custom_llm_with_events_with_content( ) assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" - assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "unknown" + assert hugging_face_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "unknown" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -235,7 +235,7 @@ def test_custom_llm_with_events_with_no_content( ) assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" - assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "unknown" + assert hugging_face_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "unknown" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -275,20 +275,20 @@ def test_openai(instrument_legacy, span_exporter, log_exporter): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-4o-mini" + assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" assert ( - (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"]) + (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" ) - assert (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "system" - assert (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"]) == prompt - assert (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"]) == "user" + assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" + assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) == prompt + assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( - openai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + openai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response.content ) assert ( - (openai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"]) + (openai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"]) == "assistant" ) @@ -330,7 +330,7 @@ def test_openai_with_events_with_content( openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-4o-mini" + assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1497 assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 1037 @@ -384,7 +384,7 @@ def test_openai_with_events_with_no_content( openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-4o-mini" + assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1497 assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 1037 @@ -444,17 +444,17 @@ class Joke(BaseModel): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"]) + (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) == "You are helpful assistant" ) - assert (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "system" + assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" assert ( - (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"]) + (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) == "tell me a short joke" ) - assert (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"]) == "user" + assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( openai_span.attributes[f"{SpanAttributes.LLM_REQUEST_FUNCTIONS}.0.name"] == "Joke" @@ -481,13 +481,13 @@ class Joke(BaseModel): "required": ["setup", "punchline"], } assert ( - openai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + openai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "Joke" ) assert ( json.loads( openai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == response @@ -537,7 +537,7 @@ class Joke(BaseModel): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 76 assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 35 @@ -610,7 +610,7 @@ class Joke(BaseModel): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 76 assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 35 @@ -659,26 +659,26 @@ def test_anthropic(instrument_legacy, span_exporter, log_exporter): ) assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "claude-2.1" - assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 + assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" + assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 assert ( - (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"]) + (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" ) assert ( - (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "system" + (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" ) assert ( - (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"]) + (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) == "tell me a short joke" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"]) == "user" + assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + anthropic_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response.content ) assert ( - (anthropic_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"]) + (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"]) == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 19 @@ -748,8 +748,8 @@ def test_anthropic_with_events_with_content( anthropic_span = next(span for span in spans if span.name == "ChatAnthropic.chat") assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "claude-2.1" - assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 + assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" + assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 19 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 22 @@ -804,8 +804,8 @@ def test_anthropic_with_events_with_no_content( anthropic_span = next(span for span in spans if span.name == "ChatAnthropic.chat") assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "claude-2.1" - assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.5 + assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" + assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 19 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 22 @@ -867,25 +867,25 @@ def test_bedrock(instrument_legacy, span_exporter, log_exporter): assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-haiku-20240307-v1:0" ) assert ( - (bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"]) + (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" ) - assert (bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "system" + assert (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" assert ( - (bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"]) + (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) == "tell me a short joke" ) - assert (bedrock_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"]) == "user" + assert (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( - bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response.content ) assert ( - (bedrock_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"]) + (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"]) == "assistant" ) assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 16 @@ -956,7 +956,7 @@ def test_bedrock_with_events_with_content( assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-haiku-20240307-v1:0" ) @@ -1019,7 +1019,7 @@ def test_bedrock_with_events_with_no_content( assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - bedrock_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-haiku-20240307-v1:0" ) assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 16 diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py b/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py index f9da2bcd00..255f756b21 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py @@ -36,9 +36,9 @@ def test_structured_output(instrument_legacy, span_exporter, log_exporter): chat_span = next(span for span in spans if span.name == "ChatOpenAI.chat") - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == query_text + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == query_text assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == result.model_dump_json() ) diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py index e26277a6df..3a0fb74295 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py @@ -56,14 +56,14 @@ def test_tool_calls(instrument_legacy, span_exporter, log_exporter): "type": "object", } - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == query_text + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == query_text assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "food_analysis" ) arguments = chat_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] assert json.loads(arguments) == json.loads( result.model_dump() @@ -211,55 +211,55 @@ def get_weather(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == messages[1].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "user" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.tool_calls.0.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_calls.0.name"] == messages[2].tool_calls[0]["name"] ) assert ( json.loads( chat_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.2.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_calls.0.arguments" ] ) == messages[2].tool_calls[0]["args"] ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.tool_calls.0.id"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_calls.0.id"] == messages[2].tool_calls[0]["id"] ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "assistant" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "assistant" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.3.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.content"] == messages[3].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.3.role"] == "tool" - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.3.tool_call_id"] == messages[3].tool_call_id + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.role"] == "tool" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.tool_call_id"] == messages[3].tool_call_id assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.4.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.4.content"] == messages[4].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.4.role"] == "user" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.4.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_weather" ) arguments = chat_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] result_arguments = result.model_dump()["additional_kwargs"]["tool_calls"][0][ "function" @@ -494,30 +494,30 @@ def get_news(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] == "assistant" + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) # Test that we write both the content and the tool calls assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == result.content[0]["text"] ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.id"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] == "toolu_016q9vtSd8CY2vnZSpEp1j4o" ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_weather" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == {"location": "San Francisco"} @@ -705,55 +705,55 @@ def get_news(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "assistant" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.tool_calls.0.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_calls.0.name"] == messages[1].tool_calls[0]["name"] ) assert ( json.loads( chat_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.1.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_calls.0.arguments" ] ) == messages[1].tool_calls[0]["args"] ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.tool_calls.0.id"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_calls.0.id"] == messages[1].tool_calls[0]["id"] ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "tool" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "tool" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] == messages[2].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.tool_call_id"] == messages[2].tool_call_id + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_call_id"] == messages[2].tool_call_id assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] == "assistant" + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) # Test that we write both the content and the tool calls assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == result.content[0]["text"] ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.id"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] == "toolu_012guEZNJ5yH5jxHKWAkzCzh" ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_news" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == {"location": "San Francisco"} @@ -900,9 +900,9 @@ def sample_tool(query: str) -> str: assert chat_span.name == "ChatOpenAI.chat" # Verify that the tool_call_id is properly set for the ToolMessage - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "tool" - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"] == "Tool executed successfully" - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.tool_call_id"] == "call_12345" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "tool" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] == "Tool executed successfully" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_call_id"] == "call_12345" logs = log_exporter.get_finished_logs() assert len(logs) == 0, ( @@ -1045,39 +1045,39 @@ def get_news(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] == "assistant" + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.id"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] == "call_EgULHWKqGjuB36aUeiOSpALZ" ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_weather" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == {"location": "San Francisco"} assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.id"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"] == "call_Xer9QGOTDMG2Bxn9AKGiVM14" ) assert ( - chat_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.name"] + chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name"] == "get_news" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" ] ) == {"location": "San Francisco"} diff --git a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py index 3b2472930a..a79f49958d 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py +++ b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py @@ -142,16 +142,16 @@ async def acomplete_wrapper(tracer, wrapped, instance: CustomLLM, args, kwargs): @dont_throw def _handle_request(span, llm_request_type, args, kwargs, instance: CustomLLM): - _set_span_attribute(span, SpanAttributes.LLM_SYSTEM, instance.__class__.__name__) + _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, instance.__class__.__name__) _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TYPE, llm_request_type.value) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MODEL, instance.metadata.model_name + span, SpanAttributes.GEN_AI_REQUEST_MODEL, instance.metadata.model_name ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, instance.metadata.context_window + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, instance.metadata.context_window ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, instance.metadata.num_output + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, instance.metadata.num_output ) if should_send_prompts(): @@ -161,7 +161,7 @@ def _handle_request(span, llm_request_type, args, kwargs, instance: CustomLLM): prompt = args[0] _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.user", + f"{SpanAttributes.GEN_AI_PROMPT}.0.user", prompt[0] if isinstance(prompt, list) else prompt, ) @@ -171,13 +171,13 @@ def _handle_request(span, llm_request_type, args, kwargs, instance: CustomLLM): @dont_throw def _handle_response(span, llm_request_type, instance, response): _set_span_attribute( - span, SpanAttributes.LLM_RESPONSE_MODEL, instance.metadata.model_name + span, SpanAttributes.GEN_AI_RESPONSE_MODEL, instance.metadata.model_name ) if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.COMPLETION: _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.content", response.text + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response.text ) return diff --git a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py index 6ac00eeb8f..5072548541 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py +++ b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py @@ -17,10 +17,10 @@ def set_llm_chat_request(event, span) -> None: if should_send_prompts(): for idx, message in enumerate(event.messages): span.set_attribute( - f"{SpanAttributes.LLM_PROMPTS}.{idx}.role", message.role.value + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", message.role.value ) span.set_attribute( - f"{SpanAttributes.LLM_PROMPTS}.{idx}.content", message.content + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", message.content ) @@ -31,9 +31,9 @@ def set_llm_chat_request_model_attributes(event, span): model_dict = event.model_dict span.set_attribute(SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.CHAT.value) - span.set_attribute(SpanAttributes.LLM_REQUEST_MODEL, model_dict.get("model")) + span.set_attribute(SpanAttributes.GEN_AI_REQUEST_MODEL, model_dict.get("model")) span.set_attribute( - SpanAttributes.LLM_REQUEST_TEMPERATURE, model_dict.get("temperature") + SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, model_dict.get("temperature") ) @@ -46,17 +46,17 @@ def set_llm_chat_response(event, span) -> None: if should_send_prompts(): for idx, message in enumerate(event.messages): span.set_attribute( - f"{SpanAttributes.LLM_PROMPTS}.{idx}.role", message.role.value + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", message.role.value ) span.set_attribute( - f"{SpanAttributes.LLM_PROMPTS}.{idx}.content", message.content + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", message.content ) span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.0.role", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", response.message.role.value, ) span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response.message.content, ) @@ -72,7 +72,7 @@ def set_llm_chat_response_model_attributes(event, span): return span.set_attribute( - SpanAttributes.LLM_RESPONSE_MODEL, + SpanAttributes.GEN_AI_RESPONSE_MODEL, ( raw.get("model") if "model" in raw else raw.model ), # raw can be Any, not just ChatCompletion @@ -93,11 +93,11 @@ def set_llm_chat_response_model_attributes(event, span): def set_llm_predict_response(event, span) -> None: if should_send_prompts(): span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.role", + f"{SpanAttributes.GEN_AI_COMPLETION}.role", MessageRole.ASSISTANT.value, ) span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.content", event.output, ) diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py index dc15b72c86..e11ff11413 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py @@ -81,19 +81,19 @@ def multiply(a: int, b: int) -> int: assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_1.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_1.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_1.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"].startswith( + assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are designed to help with a variety of tasks," ) - assert llm_span_1.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] == ( + assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == ( "What is 2 times 3?" ) assert llm_span_1.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ].startswith( "Thought: The current language of the user is English. I need to use a tool" ) @@ -103,24 +103,24 @@ def multiply(a: int, b: int) -> int: assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_2.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_2.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"].startswith( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are designed to help with a variety of tasks," ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] == ( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == ( "What is 2 times 3?" ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"].startswith( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"].startswith( "Thought: The current language of the user is English. I need to use a tool" ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_PROMPTS}.3.content"] == ( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.content"] == ( "Observation: 6" ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] == ( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( "Thought: I can answer without using any more tools. I'll use the user's " "language to answer.\nAnswer: 2 times 3 is 6." ) @@ -174,19 +174,19 @@ def multiply(a: int, b: int) -> int: assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_1.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_1.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_1.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"].startswith( + assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are designed to help with a variety of tasks," ) - assert llm_span_1.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] == ( + assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == ( "What is 2 times 3?" ) assert llm_span_1.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ].startswith( "Thought: The current language of the user is English. I need to use a tool" ) @@ -196,10 +196,10 @@ def multiply(a: int, b: int) -> int: assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_2.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_2.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 32 @@ -352,10 +352,10 @@ def multiply(a: int, b: int) -> int: assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_1.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_1.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 43 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 479 @@ -363,10 +363,10 @@ def multiply(a: int, b: int) -> int: assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_2.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_2.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 32 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 535 @@ -444,25 +444,25 @@ def test_agent_with_query_tool(instrument_legacy, span_exporter, log_exporter): assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"].startswith( + assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "Given an input question, first create a syntactically correct sqlite" ) assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 68 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 - assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"].startswith( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "Given an input question, synthesize a response from the query results." ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] == ( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( "The city with the highest population in the city_stats table is Tokyo, " "with a population of 13,960,000." ) @@ -529,17 +529,17 @@ def test_agent_with_query_tool_with_events_with_content( assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 68 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 - assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 25 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 63 @@ -654,17 +654,17 @@ def test_agent_with_query_tool_with_events_with_no_content( assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 68 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 - assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 25 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 63 diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py index 7c3a370b0a..0e68fe2efc 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py @@ -58,14 +58,14 @@ def test_rag_with_chroma(instrument_legacy, span_exporter): assert synthesize_span.parent is not None assert llm_span.parent is not None - assert llm_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"].startswith( + assert llm_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are an expert Q&A system that is trusted around the world." ) - assert llm_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] == ( + assert llm_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( "The author worked on writing and programming before college." ) assert llm_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 10 diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py index d0366bbae7..8daf85cd21 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py @@ -75,27 +75,27 @@ def test_query_pipeline(instrument_legacy, span_exporter): assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == ( + assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == ( "Please generate a question about Paul Graham's life regarding the following topic YCombinator" ) - assert llm_span_1.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] == ( + assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( "What role did Paul Graham play in the founding and development of YCombinator, and " "how has his involvement shaped the trajectory of the company?" ) - assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.LLM_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"].startswith( + assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are an expert Q&A system that is trusted around the world." ) assert llm_span_2.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ].startswith( "Paul Graham played a pivotal role in the founding and development of Y Combinator." ) diff --git a/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py b/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py index a6b3e1885e..ef36097fc1 100644 --- a/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py +++ b/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py @@ -79,16 +79,16 @@ def _set_input_attributes(span, llm_request_type, to_wrap, kwargs): return if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") for index, message in enumerate(kwargs.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", message.content, ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", message.role, ) else: @@ -96,21 +96,21 @@ def _set_input_attributes(span, llm_request_type, to_wrap, kwargs): if isinstance(input, str): _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user" + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user" ) _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", input + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", input ) else: for index, prompt in enumerate(input): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", "user", ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", prompt, ) @@ -119,7 +119,7 @@ def _set_input_attributes(span, llm_request_type, to_wrap, kwargs): def _set_model_input_attributes(span, to_wrap, kwargs): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) _set_span_attribute( span, SpanAttributes.LLM_IS_STREAMING, @@ -134,7 +134,7 @@ def _set_response_attributes(span, llm_request_type, response): if should_send_prompts(): for index, choice in enumerate(response.choices): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.finish_reason", @@ -166,7 +166,7 @@ def _set_model_response_attributes(span, llm_request_type, response): if llm_request_type == LLMRequestTypeValues.EMBEDDING: return - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response.model) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.model) if not response.usage: return @@ -398,7 +398,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "MistralAI", + SpanAttributes.GEN_AI_SYSTEM: "MistralAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) @@ -444,7 +444,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "MistralAI", + SpanAttributes.GEN_AI_SYSTEM: "MistralAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) diff --git a/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py b/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py index 59b0896104..819015252f 100644 --- a/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py @@ -24,19 +24,19 @@ def test_mistralai_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response.choices[0].message.content ) assert mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 11 @@ -70,11 +70,11 @@ def test_mistralai_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 11 @@ -123,11 +123,11 @@ def test_mistralai_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 11 @@ -176,19 +176,19 @@ def test_mistralai_streaming_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response ) assert mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 11 @@ -226,11 +226,11 @@ def test_mistralai_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 11 @@ -283,11 +283,11 @@ def test_mistralai_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 11 @@ -333,19 +333,19 @@ async def test_mistralai_async_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response.choices[0].message.content ) # For some reason, async ollama chat doesn't report prompt token usage back @@ -381,11 +381,11 @@ async def test_mistralai_async_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) # For some reason, async ollama chat doesn't report prompt token usage back @@ -435,11 +435,11 @@ async def test_mistralai_async_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) # For some reason, async ollama chat doesn't report prompt token usage back @@ -490,16 +490,16 @@ async def test_mistralai_async_streaming_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert mistral_span.attributes.get("gen_ai.request.model") == "mistral-tiny" assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response ) assert mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 11 @@ -538,7 +538,7 @@ async def test_mistralai_async_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert mistral_span.attributes.get("gen_ai.request.model") == "mistral-tiny" @@ -594,7 +594,7 @@ async def test_mistralai_async_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert mistral_span.attributes.get("gen_ai.request.model") == "mistral-tiny" diff --git a/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py b/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py index 258e3ac862..bb19141f1e 100644 --- a/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py +++ b/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py @@ -21,17 +21,17 @@ def test_mistral_embeddings_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( @@ -57,13 +57,13 @@ def test_mistral_embeddings_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( @@ -100,13 +100,13 @@ def test_mistral_embeddings_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( @@ -144,17 +144,17 @@ async def test_mistral_async_embeddings_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( @@ -181,13 +181,13 @@ async def test_mistral_async_embeddings_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( @@ -238,13 +238,13 @@ async def test_mistral_async_embeddings_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") + mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( diff --git a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py index 4690b38e21..01ec34486b 100644 --- a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py +++ b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py @@ -107,7 +107,7 @@ def _accumulate_streaming_response( first_token_time = time.perf_counter() streaming_time_to_first_token.record( first_token_time - start_time, - attributes={SpanAttributes.LLM_SYSTEM: "Ollama"}, + attributes={SpanAttributes.GEN_AI_SYSTEM: "Ollama"}, ) first_token = False yield res @@ -125,8 +125,8 @@ def _accumulate_streaming_response( streaming_time_to_generate.record( time.perf_counter() - first_token_time, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", - SpanAttributes.LLM_RESPONSE_MODEL: model_name, + SpanAttributes.GEN_AI_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, }, ) @@ -171,7 +171,7 @@ async def _aaccumulate_streaming_response( first_token_time = time.perf_counter() streaming_time_to_first_token.record( first_token_time - start_time, - attributes={SpanAttributes.LLM_SYSTEM: "Ollama"}, + attributes={SpanAttributes.GEN_AI_SYSTEM: "Ollama"}, ) first_token = False yield res @@ -189,8 +189,8 @@ async def _aaccumulate_streaming_response( streaming_time_to_generate.record( time.perf_counter() - first_token_time, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", - SpanAttributes.LLM_RESPONSE_MODEL: model_name, + SpanAttributes.GEN_AI_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, }, ) @@ -297,7 +297,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_SYSTEM: "Ollama", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) @@ -310,10 +310,10 @@ def _wrap( if response: if duration_histogram: duration = end_time - start_time - attrs = {SpanAttributes.LLM_SYSTEM: "Ollama"} + attrs = {SpanAttributes.GEN_AI_SYSTEM: "Ollama"} model = kwargs.get("model") if model is not None: - attrs[SpanAttributes.LLM_RESPONSE_MODEL] = model + attrs[SpanAttributes.GEN_AI_RESPONSE_MODEL] = model duration_histogram.record(duration, attributes=attrs) if kwargs.get("stream"): @@ -364,7 +364,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_SYSTEM: "Ollama", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) @@ -377,10 +377,10 @@ async def _awrap( if response: if duration_histogram: duration = end_time - start_time - attrs = {SpanAttributes.LLM_SYSTEM: "Ollama"} + attrs = {SpanAttributes.GEN_AI_SYSTEM: "Ollama"} model = kwargs.get("model") if model is not None: - attrs[SpanAttributes.LLM_RESPONSE_MODEL] = model + attrs[SpanAttributes.GEN_AI_RESPONSE_MODEL] = model duration_histogram.record(duration, attributes=attrs) if kwargs.get("stream"): diff --git a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py index c7b89f9d15..1d8f76f468 100644 --- a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py +++ b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py @@ -22,25 +22,25 @@ def set_input_attributes(span, llm_request_type, kwargs): json_data = kwargs.get("json", {}) if llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") for index, message in enumerate(json_data.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", message.get("content"), ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", message.get("role"), ) _set_prompts(span, json_data.get("messages")) if json_data.get("tools"): set_tools_attributes(span, json_data.get("tools")) else: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", json_data.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", json_data.get("prompt") ) @@ -49,7 +49,7 @@ def set_model_input_attributes(span, kwargs): if not span.is_recording(): return json_data = kwargs.get("json", {}) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, json_data.get("model")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, json_data.get("model")) _set_span_attribute( span, SpanAttributes.LLM_IS_STREAMING, kwargs.get("stream") or False ) @@ -64,15 +64,15 @@ def set_response_attributes(span, token_histogram, llm_request_type, response): if llm_request_type == LLMRequestTypeValues.COMPLETION: _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response.get("response"), ) _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) elif llm_request_type == LLMRequestTypeValues.CHAT: index = 0 - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.content", response.get("message").get("content") ) @@ -86,7 +86,7 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo if llm_request_type == LLMRequestTypeValues.EMBEDDING or not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response.get("model")) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) input_tokens = response.get("prompt_eval_count") or 0 output_tokens = response.get("eval_count") or 0 @@ -106,7 +106,7 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo SpanAttributes.LLM_USAGE_PROMPT_TOKENS, input_tokens, ) - _set_span_attribute(span, SpanAttributes.LLM_SYSTEM, "Ollama") + _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, "Ollama") if ( token_histogram is not None @@ -116,9 +116,9 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo token_histogram.record( input_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", - SpanAttributes.LLM_TOKEN_TYPE: "input", - SpanAttributes.LLM_RESPONSE_MODEL: response.get("model"), + SpanAttributes.GEN_AI_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -130,9 +130,9 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo token_histogram.record( output_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", - SpanAttributes.LLM_TOKEN_TYPE: "output", - SpanAttributes.LLM_RESPONSE_MODEL: response.get("model"), + SpanAttributes.GEN_AI_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -160,7 +160,7 @@ def _set_prompts(span, messages): if not should_send_prompts(): return for i, msg in enumerate(messages): - prefix = f"{SpanAttributes.LLM_PROMPTS}.{i}" + prefix = f"{SpanAttributes.GEN_AI_PROMPT}.{i}" _set_span_attribute(span, f"{prefix}.role", msg.get("role")) if msg.get("content"): diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py b/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py index e996414e7e..ef123adce7 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py @@ -31,16 +31,16 @@ def test_ollama_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response["message"]["content"] ) assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 @@ -73,10 +73,10 @@ def test_ollama_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -121,10 +121,10 @@ def test_ollama_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -177,27 +177,27 @@ def test_ollama_chat_tool_calls_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3.1" + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" ) assert ( f"{SpanAttributes.LLM_REQUEST_FUNCTIONS}.0.content" not in ollama_span.attributes ) assert ( - ollama_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.name"] + ollama_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( - ollama_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.arguments"] + ollama_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments"] == '{"location": "San Francisco"}' ) assert ( - ollama_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + ollama_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == "The weather in San Francisco is 70 degrees and sunny." ) @@ -237,11 +237,11 @@ def test_ollama_chat_tool_calls_with_events_with_content( ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3.1" + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" ) logs = log_exporter.get_finished_logs() @@ -312,11 +312,11 @@ def test_ollama_chat_tool_calls_with_events_with_no_content( ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3.1" + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" ) logs = log_exporter.get_finished_logs() @@ -372,16 +372,16 @@ def test_ollama_streaming_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response ) assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 @@ -419,10 +419,10 @@ def test_ollama_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -472,10 +472,10 @@ def test_ollama_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -517,16 +517,16 @@ async def test_ollama_async_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response["message"]["content"] ) # For some reason, async ollama chat doesn't report prompt token usage back @@ -561,10 +561,10 @@ async def test_ollama_async_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back # assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( @@ -611,10 +611,10 @@ async def test_ollama_async_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back # assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( @@ -662,16 +662,16 @@ async def test_ollama_async_streaming_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response ) assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 @@ -710,10 +710,10 @@ async def test_ollama_async_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -764,10 +764,10 @@ async def test_ollama_async_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -805,17 +805,17 @@ def test_token_histogram_recording(): token_histogram.record.assert_any_call( 7, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", - SpanAttributes.LLM_TOKEN_TYPE: "input", - SpanAttributes.LLM_RESPONSE_MODEL: "llama3", + SpanAttributes.GEN_AI_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_RESPONSE_MODEL: "llama3", }, ) token_histogram.record.assert_any_call( 10, attributes={ - SpanAttributes.LLM_SYSTEM: "Ollama", - SpanAttributes.LLM_TOKEN_TYPE: "output", - SpanAttributes.LLM_RESPONSE_MODEL: "llama3", + SpanAttributes.GEN_AI_SYSTEM: "Ollama", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_RESPONSE_MODEL: "llama3", }, ) diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py b/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py index 4a907aaa35..5a6065b93d 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py @@ -20,14 +20,14 @@ def test_ollama_embeddings_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.embeddings" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) @@ -48,12 +48,12 @@ def test_ollama_embeddings_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.embeddings" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -86,12 +86,12 @@ def test_ollama_embeddings_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.embeddings" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py index 8e8ccf7f8f..3620db4956 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py @@ -20,18 +20,18 @@ def test_ollama_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response["response"] ) assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 @@ -58,12 +58,12 @@ def test_ollama_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -100,12 +100,12 @@ def test_ollama_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -144,18 +144,18 @@ def test_ollama_streaming_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response ) assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 @@ -186,12 +186,12 @@ def test_ollama_streaming_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -234,12 +234,12 @@ def test_ollama_streaming_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -275,18 +275,18 @@ async def test_ollama_async_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response["response"] ) # For some reason, async ollama chat doesn't report prompt token usage back @@ -315,12 +315,12 @@ async def test_ollama_async_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back # assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( @@ -361,12 +361,12 @@ async def test_ollama_async_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back # assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( @@ -407,18 +407,18 @@ async def test_ollama_async_streaming_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == response ) # For some reason, async ollama chat doesn't report prompt token usage back @@ -451,12 +451,12 @@ async def test_ollama_async_streaming_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back # assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( @@ -501,12 +501,12 @@ async def test_ollama_async_streaming_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back # assert ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 17 assert ollama_span.attributes.get( diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py b/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py index 0864a25916..c7398e9544 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py @@ -40,7 +40,7 @@ def test_ollama_streaming_metrics(instrument_legacy, reader): for name, dp in points: if name == GenAIMetrics.GEN_AI_SERVER_TIME_TO_FIRST_TOKEN: assert dp.sum > 0, "Time to first token should be greater than 0" - assert dp.attributes.get(SpanAttributes.LLM_SYSTEM) == "Ollama" + assert dp.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Ollama" break @@ -63,6 +63,6 @@ def test_ollama_streaming_time_to_generate_metrics(instrument_legacy, reader): for name, dp in points: if name == Meters.LLM_STREAMING_TIME_TO_GENERATE: assert dp.sum > 0, "Streaming time to generate should be greater than 0" - assert dp.attributes.get(SpanAttributes.LLM_SYSTEM) == "Ollama" - assert dp.attributes.get(SpanAttributes.LLM_RESPONSE_MODEL) is not None + assert dp.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Ollama" + assert dp.attributes.get(SpanAttributes.GEN_AI_RESPONSE_MODEL) is not None break diff --git a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py index 2628368d73..b00b04da56 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py +++ b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py @@ -103,8 +103,8 @@ async def _wrap_agent_run( f"{agent_name}.agent", kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "openai", - SpanAttributes.LLM_REQUEST_MODEL: model_name, + SpanAttributes.GEN_AI_SYSTEM: "openai", + SpanAttributes.GEN_AI_REQUEST_MODEL: model_name, SpanAttributes.TRACELOOP_SPAN_KIND: ( TraceloopSpanKindValues.AGENT.value ) @@ -128,8 +128,8 @@ async def _wrap_agent_run( duration_histogram.record( time.time() - start_time, attributes={ - SpanAttributes.LLM_SYSTEM: "openai", - SpanAttributes.LLM_RESPONSE_MODEL: model_name, + SpanAttributes.GEN_AI_SYSTEM: "openai", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, }, ) @@ -213,9 +213,9 @@ def set_model_settings_span_attributes(agent, span): settings_dict = vars(model_settings) key_to_span_attr = { - "max_tokens": SpanAttributes.LLM_REQUEST_MAX_TOKENS, - "temperature": SpanAttributes.LLM_REQUEST_TEMPERATURE, - "top_p": SpanAttributes.LLM_REQUEST_TOP_P, + "max_tokens": SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, + "temperature": SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, + "top_p": SpanAttributes.GEN_AI_REQUEST_TOP_P, } for key, value in settings_dict.items(): @@ -333,12 +333,12 @@ def set_prompt_attributes(span, message_history): content = msg.get("content", None) set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", role, ) set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", content, ) @@ -367,18 +367,18 @@ def set_response_content_span_attribute(response, span): if roles: set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.roles", + f"{SpanAttributes.GEN_AI_COMPLETION}.roles", roles, ) if types: set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.types", + f"{SpanAttributes.GEN_AI_COMPLETION}.types", types, ) if contents: set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.contents", contents + span, f"{SpanAttributes.GEN_AI_COMPLETION}.contents", contents ) @@ -418,18 +418,18 @@ def set_token_usage_span_attributes( token_histogram.record( input_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "openai", - SpanAttributes.LLM_TOKEN_TYPE: "input", - SpanAttributes.LLM_RESPONSE_MODEL: model_name, + SpanAttributes.GEN_AI_SYSTEM: "openai", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, "gen_ai.agent.name": agent_name, }, ) token_histogram.record( output_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: "openai", - SpanAttributes.LLM_TOKEN_TYPE: "output", - SpanAttributes.LLM_RESPONSE_MODEL: model_name, + SpanAttributes.GEN_AI_SYSTEM: "openai", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, "gen_ai.agent.name": agent_name, }, ) diff --git a/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py b/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py index 08fcab2bb0..89a8700958 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py +++ b/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py @@ -37,15 +37,15 @@ def test_agent_spans(exporter, test_agent): assert span.name == "testAgent.agent" assert span.kind == span.kind.CLIENT - assert span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" - assert span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-4.1" + assert span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4.1" assert ( span.attributes[SpanAttributes.TRACELOOP_SPAN_KIND] == TraceloopSpanKindValues.AGENT.value ) - assert span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.3 - assert span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 1024 - assert span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.2 + assert span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.2 assert span.attributes["openai.agent.model.frequency_penalty"] == 1.3 assert span.attributes["gen_ai.agent.name"] == "testAgent" assert ( @@ -53,9 +53,9 @@ def test_agent_spans(exporter, test_agent): == "You are a helpful assistant that answers all questions" ) - assert span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + assert span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert ( - span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "What is AI?") assert span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] is not None @@ -65,25 +65,25 @@ def test_agent_spans(exporter, test_agent): assert span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] is not None assert ( - span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.contents"] + span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.contents"] is not None ) assert ( - len(span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.contents"]) > 0 + len(span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.contents"]) > 0 ) assert ( - span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.roles"] + span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.roles"] is not None ) assert ( - len(span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.roles"]) > 0 + len(span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.roles"]) > 0 ) assert ( - span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.types"] + span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.types"] is not None ) assert ( - len(span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.types"]) > 0 + len(span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.types"]) > 0 ) assert span.status.status_code == StatusCode.OK @@ -234,7 +234,7 @@ def test_generate_metrics(metrics_test_context, test_agent): assert ( ( data_point.attributes[ - SpanAttributes.LLM_TOKEN_TYPE + SpanAttributes.GEN_AI_TOKEN_TYPE ] in [ "output", @@ -257,13 +257,13 @@ def test_generate_metrics(metrics_test_context, test_agent): ) assert ( metric.data.data_points[0].attributes[ - SpanAttributes.LLM_SYSTEM + SpanAttributes.GEN_AI_SYSTEM ] == "openai" ) assert ( metric.data.data_points[0].attributes[ - SpanAttributes.LLM_RESPONSE_MODEL + SpanAttributes.GEN_AI_RESPONSE_MODEL ] == "gpt-4.1" ) diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py index 68860e8aa4..1583e45bdf 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py @@ -112,7 +112,7 @@ def _set_request_attributes(span, kwargs, instance=None): base_url = _get_openai_base_url(instance) if instance else "" vendor = _get_vendor_from_url(base_url) - _set_span_attribute(span, SpanAttributes.LLM_SYSTEM, vendor) + _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, vendor) model = kwargs.get("model") if vendor == "AWS" and model and "." in model: @@ -120,14 +120,14 @@ def _set_request_attributes(span, kwargs, instance=None): elif vendor == "OpenRouter": model = _extract_model_name_from_provider_format(model) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, model) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, kwargs.get("max_tokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) _set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -197,7 +197,7 @@ def _set_response_attributes(span, response): if "error" in response: _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_ERROR}", + f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}", json.dumps(response.get("error")), ) return @@ -205,7 +205,7 @@ def _set_response_attributes(span, response): response_model = response.get("model") if response_model: response_model = _extract_model_name_from_provider_format(response_model) - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response_model) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response_model) _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.get("id")) _set_span_attribute( @@ -245,7 +245,7 @@ def _log_prompt_filter(span, response_dict): if response_dict.get("prompt_filter_results"): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_FILTER_KEY}", + f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}", json.dumps(response_dict.get("prompt_filter_results")), ) @@ -396,8 +396,8 @@ def metric_shared_attributes( return { **attributes, - SpanAttributes.LLM_SYSTEM: vendor, - SpanAttributes.LLM_RESPONSE_MODEL: response_model, + SpanAttributes.GEN_AI_SYSTEM: vendor, + SpanAttributes.GEN_AI_RESPONSE_MODEL: response_model, "gen_ai.operation.name": operation, "server.address": server_address, "stream": is_streaming, diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py index 7e3e188183..8c8521a41a 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py @@ -363,7 +363,7 @@ def _set_token_counter_metrics(token_counter, usage, shared_attributes): if name in OPENAI_LLM_USAGE_TOKEN_TYPES: attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: _token_type(name), + SpanAttributes.GEN_AI_TOKEN_TYPE: _token_type(name), } token_counter.record(val, attributes=attributes_with_token_type) @@ -399,7 +399,7 @@ async def _set_prompts(span, messages): return for i, msg in enumerate(messages): - prefix = f"{SpanAttributes.LLM_PROMPTS}.{i}" + prefix = f"{SpanAttributes.GEN_AI_PROMPT}.{i}" msg = msg if isinstance(msg, dict) else model_as_dict(msg) _set_span_attribute(span, f"{prefix}.role", msg.get("role")) @@ -451,7 +451,7 @@ def _set_completions(span, choices): for choice in choices: index = choice.get("index") - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.finish_reason", choice.get("finish_reason") ) @@ -562,14 +562,14 @@ def _set_streaming_token_metrics( if isinstance(prompt_usage, int) and prompt_usage >= 0: attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", } token_counter.record(prompt_usage, attributes=attributes_with_token_type) if isinstance(completion_usage, int) and completion_usage >= 0: attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", } token_counter.record( completion_usage, attributes=attributes_with_token_type @@ -761,7 +761,7 @@ def _build_from_streaming_response( yield item_to_yield shared_attributes = { - SpanAttributes.LLM_RESPONSE_MODEL: complete_response.get("model") or None, + SpanAttributes.GEN_AI_RESPONSE_MODEL: complete_response.get("model") or None, "server.address": _get_openai_base_url(instance), "stream": True, } @@ -831,7 +831,7 @@ async def _abuild_from_streaming_response( yield item_to_yield shared_attributes = { - SpanAttributes.LLM_RESPONSE_MODEL: complete_response.get("model") or None, + SpanAttributes.GEN_AI_RESPONSE_MODEL: complete_response.get("model") or None, "server.address": _get_openai_base_url(instance), "stream": True, } diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py index d821fecb94..4081d861f7 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py @@ -157,7 +157,7 @@ def _set_prompts(span, prompt): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.user", + f"{SpanAttributes.GEN_AI_PROMPT}.0.user", prompt[0] if isinstance(prompt, list) else prompt, ) @@ -169,7 +169,7 @@ def _set_completions(span, choices): for choice in choices: index = choice.get("index") - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.finish_reason", choice.get("finish_reason") ) diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py index d45af3789a..cfa21b330c 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py @@ -248,7 +248,7 @@ def _set_embeddings_metrics( continue attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: _token_type(name), + SpanAttributes.GEN_AI_TOKEN_TYPE: _token_type(name), } token_counter.record(val, attributes=attributes_with_token_type) @@ -270,11 +270,11 @@ def _set_prompts(span, prompt): if isinstance(prompt, list): for i, p in enumerate(prompt): - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.{i}.content", p) + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", p) else: _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.content", + f"{SpanAttributes.GEN_AI_PROMPT}.0.content", prompt, ) diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py index 203147a85b..ffd84aa2c1 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py @@ -145,37 +145,37 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): _set_span_attribute( span, - SpanAttributes.LLM_SYSTEM, + SpanAttributes.GEN_AI_SYSTEM, "openai", ) _set_span_attribute( span, - SpanAttributes.LLM_REQUEST_MODEL, + SpanAttributes.GEN_AI_REQUEST_MODEL, assistant["model"], ) _set_span_attribute( span, - SpanAttributes.LLM_RESPONSE_MODEL, + SpanAttributes.GEN_AI_RESPONSE_MODEL, assistant["model"], ) if should_emit_events(): emit_event(MessageEvent(content=assistant["instructions"], role="system")) else: _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.role", "system" + span, f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "system" ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", assistant["instructions"], ) prompt_index += 1 _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.role", "system" + span, f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "system" ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", run["instructions"], ) emit_event(MessageEvent(content=run["instructions"], role="system")) @@ -183,7 +183,7 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): completion_index = 0 for msg in messages: - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}" content = msg.get("content") message_content = content[0].get("text").get("value") @@ -194,12 +194,12 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): else: _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", message_role, ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", message_content, ) prompt_index += 1 @@ -262,16 +262,16 @@ def runs_create_and_stream_wrapper(tracer, wrapped, instance, args, kwargs): assistant = assistants[assistant_id] _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MODEL, assistants[assistant_id]["model"] + span, SpanAttributes.GEN_AI_REQUEST_MODEL, assistants[assistant_id]["model"] ) _set_span_attribute( span, - SpanAttributes.LLM_SYSTEM, + SpanAttributes.GEN_AI_SYSTEM, "openai", ) _set_span_attribute( span, - SpanAttributes.LLM_RESPONSE_MODEL, + SpanAttributes.GEN_AI_RESPONSE_MODEL, assistants[assistant_id]["model"], ) if should_emit_events(): @@ -282,20 +282,20 @@ def runs_create_and_stream_wrapper(tracer, wrapped, instance, args, kwargs): ) else: _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{i}.role", "system" + span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", "system" ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{i}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", assistants[assistant_id]["instructions"], ) i += 1 if should_emit_events(): emit_event(MessageEvent(content=instructions, role="system")) else: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.{i}.role", "system") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", "system") _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.{i}.content", instructions + span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", instructions ) from opentelemetry.instrumentation.openai.v1.event_handler_wrapper import ( diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py index c2d39bbf53..f36f4998a5 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py @@ -118,12 +118,12 @@ def on_text_done(self, text): if not should_emit_events(): _set_span_attribute( self._span, - f"{SpanAttributes.LLM_COMPLETIONS}.{self._current_text_index}.role", + f"{SpanAttributes.GEN_AI_COMPLETION}.{self._current_text_index}.role", "assistant", ) _set_span_attribute( self._span, - f"{SpanAttributes.LLM_COMPLETIONS}.{self._current_text_index}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.{self._current_text_index}.content", text.value, ) diff --git a/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py b/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py index d02329a4de..023855445b 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py +++ b/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py @@ -41,7 +41,7 @@ def test_chat_completion_metrics(instrument_legacy, reader, openai_client): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -106,7 +106,7 @@ class StructuredAnswer(BaseModel): for sm in rm.scope_metrics: for metric in sm.metrics: for data_point in metric.data.data_points: - model = data_point.attributes.get(SpanAttributes.LLM_RESPONSE_MODEL) + model = data_point.attributes.get(SpanAttributes.GEN_AI_RESPONSE_MODEL) if ( metric.name == Meters.LLM_TOKEN_USAGE and model == "gpt-4o-2024-08-06" @@ -165,7 +165,7 @@ def test_chat_streaming_metrics(instrument_legacy, reader, openai_client): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -205,10 +205,10 @@ def test_chat_streaming_metrics(instrument_legacy, reader, openai_client): for data_point in metric.data.data_points: assert ( - data_point.attributes.get(SpanAttributes.LLM_SYSTEM) == "openai" + data_point.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "openai" ) assert str( - data_point.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + data_point.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] ) in ("gpt-3.5-turbo", "gpt-3.5-turbo-0125", "gpt-4o-2024-08-06") assert data_point.attributes["gen_ai.operation.name"] == "chat" assert data_point.attributes["server.address"] != "" diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py index aba11b65d4..fc76615aa6 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py @@ -61,31 +61,31 @@ def test_new_assistant( open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.1.content") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "system" - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "user" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "user" assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] == user_message ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 145 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 155 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 for message in messages.data: @@ -93,13 +93,13 @@ def test_new_assistant( continue assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.content" ] == message.content[0].text.value ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}.role" + f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.role" ] == message.role ) @@ -158,17 +158,17 @@ def test_new_assistant_with_events_with_content( open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 145 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 155 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -239,16 +239,16 @@ def test_new_assistant_with_events_with_no_content( open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 145 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 155 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -318,7 +318,7 @@ def test_new_assistant_with_polling( assert open_ai_span.attributes["gen_ai.prompt.2.content"] == user_message assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 374 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 86 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 for message in messages.data: @@ -326,13 +326,13 @@ def test_new_assistant_with_polling( continue assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.content" ] == message.content[0].text.value ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}.role" + f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.role" ] == message.role ) @@ -386,7 +386,7 @@ def test_new_assistant_with_polling_with_events_with_content( assert open_ai_span.attributes["gen_ai.response.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 374 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 86 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -460,7 +460,7 @@ def test_new_assistant_with_polling_with_events_with_no_content( assert open_ai_span.attributes["gen_ai.response.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 374 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 86 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -519,28 +519,28 @@ def test_existing_assistant( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.1.content") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" assert open_ai_span.attributes["gen_ai.prompt.2.role"] == "user" assert open_ai_span.attributes["gen_ai.prompt.2.content"] == user_message assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 639 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 170 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 for message in messages.data: @@ -548,13 +548,13 @@ def test_existing_assistant( continue assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.content" ] == message.content[0].text.value ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}.role" + f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.role" ] == message.role ) @@ -609,17 +609,17 @@ def test_existing_assistant_with_events_with_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 639 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 170 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 5 @@ -704,17 +704,17 @@ def test_existing_assistant_with_events_with_no_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 639 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 170 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 5 @@ -777,35 +777,35 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.1.content") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 790 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 225 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" for idx, message in enumerate(assistant_messages): assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content"] == message ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.role"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role"] == "assistant" ) assert open_ai_span.attributes[f"gen_ai.response.{idx}.id"].startswith("msg") @@ -855,17 +855,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 790 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 225 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -958,17 +958,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 790 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 225 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -1027,34 +1027,34 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.1.content") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "system" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 364 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 88 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" for idx, message in enumerate(assistant_messages): assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content"] == message ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.role"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role"] == "assistant" ) assert open_ai_span.attributes[f"gen_ai.response.{idx}.id"].startswith("msg_") @@ -1104,17 +1104,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 364 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 88 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 3 @@ -1192,17 +1192,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 364 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 88 - assert open_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 3 diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py index 1bdc4af02c..faa979dadf 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py @@ -28,10 +28,10 @@ def test_chat(instrument_legacy, span_exporter, log_exporter, azure_openai_clien ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://traceloop-stg.openai.azure.com/openai/" @@ -146,11 +146,11 @@ def test_chat_content_filtering( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") == "FILTERED" ) assert ( @@ -164,7 +164,7 @@ def test_chat_content_filtering( ) content_filter_json = open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.content_filter_results" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content_filter_results" ) assert len(content_filter_json) > 0 @@ -285,11 +285,11 @@ def test_prompt_content_filtering( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_ERROR}"], str + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str ) error = json.loads( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_ERROR}"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] ) assert "innererror" in error @@ -329,11 +329,11 @@ def test_prompt_content_filtering_with_events_with_content( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_ERROR}"], str + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str ) error = json.loads( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_ERROR}"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] ) assert "innererror" in error @@ -378,11 +378,11 @@ def test_prompt_content_filtering_with_events_with_no_content( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_ERROR}"], str + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str ) error = json.loads( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_ERROR}"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] ) assert "innererror" in error @@ -427,10 +427,10 @@ def test_chat_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://traceloop-stg.openai.azure.com/openai/" @@ -442,7 +442,7 @@ def test_chat_streaming( # prompt filter results prompt_filter_results = json.loads( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_FILTER_KEY}") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") ) assert prompt_filter_results[0]["prompt_index"] == 0 assert ( @@ -495,7 +495,7 @@ def test_chat_streaming_with_events_with_content( # prompt filter results prompt_filter_results = json.loads( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_FILTER_KEY}") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") ) assert prompt_filter_results[0]["prompt_index"] == 0 assert ( @@ -565,7 +565,7 @@ def test_chat_streaming_with_events_with_no_content( # prompt filter results prompt_filter_results = json.loads( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.{PROMPT_FILTER_KEY}") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") ) assert prompt_filter_results[0]["prompt_index"] == 0 assert ( @@ -614,10 +614,10 @@ async def test_chat_async_streaming( open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://traceloop-stg.openai.azure.com/openai/" diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py index abd546db77..232ac6821b 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py @@ -34,10 +34,10 @@ def test_chat(instrument_legacy, span_exporter, log_exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -189,24 +189,24 @@ def test_chat_tool_calls(instrument_legacy, span_exporter, log_exporter, openai_ "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments" ] == '{"location": "San Francisco"}' ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == "The weather in San Francisco is 70 degrees and sunny." ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.tool_call_id"] == "1" + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_call_id"] == "1" ) assert ( open_ai_span.attributes.get("gen_ai.response.id") @@ -254,7 +254,7 @@ def test_chat_tool_calls_with_events_with_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") @@ -332,7 +332,7 @@ def test_chat_tool_calls_with_events_with_no_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-9gKNZbUWSC4s2Uh2QfVV7PYiqWIuH" @@ -397,24 +397,24 @@ def test_chat_pydantic_based_tool_calls( ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments" ] == '{"location": "San Francisco"}' ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == "The weather in San Francisco is 70 degrees and sunny." ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.tool_call_id"] == "1" + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_call_id"] == "1" ) assert ( open_ai_span.attributes.get("gen_ai.response.id") @@ -462,7 +462,7 @@ def test_chat_pydantic_based_tool_calls_with_events_with_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-9lvGJKrBUPeJjHi3KKSEbGfcfomOP" @@ -539,7 +539,7 @@ def test_chat_pydantic_based_tool_calls_with_events_with_no_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-9lvGJKrBUPeJjHi3KKSEbGfcfomOP" @@ -588,10 +588,10 @@ def test_chat_streaming(instrument_legacy, span_exporter, log_exporter, openai_c ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -763,10 +763,10 @@ async def test_chat_async_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -1335,41 +1335,41 @@ def test_chat_history_message_dict(span_exporter, openai_client): first_span = spans[0] assert first_span.name == "openai.chat" assert ( - first_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - first_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] + first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == first_user_message["role"] ) assert ( - first_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == first_response.choices[0].message.content ) assert ( - first_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] == "assistant" + first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) second_span = spans[1] assert second_span.name == "openai.chat" assert ( - second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - second_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == second_response.choices[0].message.content ) assert ( - second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == first_response.choices[0].message.content ) - assert second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "assistant" + assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" assert ( - second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] == second_user_message["content"] ) - assert second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "user" + assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "user" @pytest.mark.vcr @@ -1402,41 +1402,41 @@ def test_chat_history_message_pydantic(span_exporter, openai_client): first_span = spans[0] assert first_span.name == "openai.chat" assert ( - first_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - first_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] + first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == first_user_message["role"] ) assert ( - first_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == first_response.choices[0].message.content ) assert ( - first_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] == "assistant" + first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) second_span = spans[1] assert second_span.name == "openai.chat" assert ( - second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - second_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == second_response.choices[0].message.content ) assert ( - second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == first_response.choices[0].message.content ) - assert second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "assistant" + assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" assert ( - second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"] + second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] == second_user_message["content"] ) - assert second_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "user" + assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "user" def test_chat_exception(instrument_legacy, span_exporter, openai_client): @@ -1454,7 +1454,7 @@ def test_chat_exception(instrument_legacy, span_exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( @@ -1492,7 +1492,7 @@ async def test_chat_async_exception(instrument_legacy, span_exporter, async_open ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py index 8960b63e49..97b8d308d9 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py @@ -33,14 +33,14 @@ def test_parsed_completion( "openai.chat", ] open_ai_span = spans[0] - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" ) assert open_ai_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( @@ -164,10 +164,10 @@ def test_parsed_refused_completion( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.content" not in open_ai_span.attributes - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.refusal" in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal" in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.refusal"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal"] == "I'm very sorry, but I can't assist with that request." ) assert ( @@ -200,7 +200,7 @@ def test_parsed_refused_completion_with_events_with_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGky8KFDbg6f5fF4qLtsBredIjZZh" @@ -243,7 +243,7 @@ def test_parsed_refused_completion_with_events_with_no_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGky8KFDbg6f5fF4qLtsBredIjZZh" @@ -281,14 +281,14 @@ async def test_async_parsed_completion( "openai.chat", ] open_ai_span = spans[0] - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" ) assert open_ai_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( @@ -414,10 +414,10 @@ async def test_async_parsed_refused_completion( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.content" not in open_ai_span.attributes - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.refusal" in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal" in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.refusal"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal"] == "I'm very sorry, but I can't assist with that request." ) assert ( @@ -451,7 +451,7 @@ async def test_async_parsed_refused_completion_with_events_with_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGkyFJGzZPUGAAEDJJuOS3idKvD3G" @@ -495,7 +495,7 @@ async def test_async_parsed_refused_completion_with_events_with_no_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.LLM_COMPLETIONS}.0.content" not in open_ai_span.attributes + assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGkyFJGzZPUGAAEDJJuOS3idKvD3G" @@ -548,8 +548,8 @@ def test_parsed_completion_exception( assert span.name == "openai.chat" assert span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" assert span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") == "Tell me a joke about opentelemetry" - assert span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.role") == "user" + assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about opentelemetry" + assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.role") == "user" assert span.status.status_code == StatusCode.ERROR assert span.status.description.startswith("Error code: 401") @@ -583,8 +583,8 @@ async def test_async_parsed_completion_exception( assert span.name == "openai.chat" assert span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" assert span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") == "Tell me a joke about opentelemetry" - assert span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.role") == "user" + assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about opentelemetry" + assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.role") == "user" assert span.status.status_code == StatusCode.ERROR assert span.status.description.startswith("Error code: 401") diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py index 02f76d6b4c..8a3e775bea 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py @@ -29,10 +29,10 @@ def test_completion(instrument_legacy, span_exporter, log_exporter, openai_clien ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -145,10 +145,10 @@ async def test_async_completion( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get("gen_ai.response.id") == "cmpl-8wq43c8U5ZZCQBX5lrSpsANwcd3OF" @@ -253,10 +253,10 @@ def test_completion_langchain_style( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get("gen_ai.response.id") == "cmpl-8wq43QD6R2WqfxXLpYsRvSAIn9LB9" @@ -368,11 +368,11 @@ def test_completion_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) assert open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ) assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) @@ -564,10 +564,10 @@ async def test_async_completion_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -935,7 +935,7 @@ def test_completion_exception(instrument_legacy, span_exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) assert open_ai_span.status.status_code == StatusCode.ERROR @@ -967,7 +967,7 @@ async def test_async_completion_exception(instrument_legacy, span_exporter, asyn ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) assert open_ai_span.status.status_code == StatusCode.ERROR diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py index 1040427b8a..1f4c6305d3 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py @@ -29,11 +29,11 @@ def test_embeddings(instrument_legacy, span_exporter, log_exporter, openai_clien ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 @@ -63,7 +63,7 @@ def test_embeddings_with_events_with_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 @@ -107,7 +107,7 @@ def test_embeddings_with_events_with_no_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 @@ -142,12 +142,12 @@ def test_embeddings_with_raw_response( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 @@ -180,7 +180,7 @@ def test_embeddings_with_raw_response_with_events_with_content( open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 @@ -227,7 +227,7 @@ def test_embeddings_with_raw_response_with_events_with_no_content( open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 @@ -274,10 +274,10 @@ def test_azure_openai_embeddings(instrument_legacy, span_exporter, log_exporter) ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "embedding" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "embedding" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] @@ -318,7 +318,7 @@ def test_azure_openai_embeddings_with_events_with_content( "openai.embeddings", ] open_ai_span = spans[0] - assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "embedding" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "embedding" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] @@ -373,7 +373,7 @@ def test_azure_openai_embeddings_with_events_with_no_content( "openai.embeddings", ] open_ai_span = spans[0] - assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "embedding" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "embedding" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py index 74ec1e2c57..12df5ffe36 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py @@ -65,7 +65,7 @@ def test_open_ai_function_calls( spans = span_exporter.get_finished_spans() open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "What's the weather like in Boston?" ) assert ( @@ -77,7 +77,7 @@ def test_open_ai_function_calls( == "Get the current weather in a given location" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( @@ -244,7 +244,7 @@ def test_open_ai_function_calls_tools( spans = span_exporter.get_finished_spans() open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "What's the weather like in Boston?" ) assert ( @@ -256,11 +256,11 @@ def test_open_ai_function_calls_tools( == "Get the current weather" ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( @@ -396,7 +396,7 @@ async def test_open_ai_function_calls_tools_streaming( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( @@ -404,18 +404,18 @@ async def test_open_ai_function_calls_tools_streaming( == "get_current_weather" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.finish_reason") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.finish_reason") == "tool_calls" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ) == '{"location":"San Francisco, CA"}' ) @@ -567,40 +567,40 @@ def test_open_ai_function_calls_tools_parallel( == "get_current_weather" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.finish_reason") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.finish_reason") == "tool_calls" ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ) == '{"location": "San Francisco"}' ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.id"], + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.name" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" ) == '{"location": "Boston"}' ) @@ -761,40 +761,40 @@ async def test_open_ai_function_calls_tools_streaming_parallel( == "get_current_weather" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.finish_reason") + open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.finish_reason") == "tool_calls" ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ) == '{"location": "San Francisco"}' ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.id"], + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.name" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.1.arguments" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" ) == '{"location": "Boston"}' ) diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py index cb74cd6a0e..6825b1c50f 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py @@ -42,7 +42,7 @@ def test_vision(instrument_legacy, span_exporter, log_exporter, openai_client): ] open_ai_span = spans[0] assert json.loads( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "What is in this image?"}, { @@ -51,7 +51,7 @@ def test_vision(instrument_legacy, span_exporter, log_exporter, openai_client): }, ] - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -228,7 +228,7 @@ def test_vision_base64(instrument_legacy, span_exporter, log_exporter, openai_cl ] open_ai_span = spans[0] assert json.loads( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "What is in this image?"}, { @@ -237,7 +237,7 @@ def test_vision_base64(instrument_legacy, span_exporter, log_exporter, openai_cl }, ] - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" diff --git a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py index f27f28590a..16a68ae52c 100644 --- a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py +++ b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py @@ -123,7 +123,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Replicate", + SpanAttributes.GEN_AI_SYSTEM: "Replicate", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py index 574fbdb069..7bd9a5a18d 100644 --- a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py +++ b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py @@ -20,7 +20,7 @@ def set_input_attributes(span, args, kwargs): input_attribute = kwargs.get("input") if should_send_prompts(): _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.user", input_attribute.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", input_attribute.get("prompt") ) @@ -30,21 +30,21 @@ def set_model_input_attributes(span, args, kwargs): return if args is not None and len(args) > 0: - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, args[0]) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, args[0]) elif kwargs.get("version"): _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("version").id + span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("version").id ) else: - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, "unknown") + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, "unknown") input_attribute = kwargs.get("input") _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, input_attribute.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, input_attribute.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, input_attribute.get("top_p") + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, input_attribute.get("top_p") ) @@ -53,9 +53,9 @@ def set_response_attributes(span, response): if should_send_prompts(): if isinstance(response, list): for index, item in enumerate(response): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", item) elif isinstance(response, str): _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.content", response + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response ) diff --git a/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py b/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py index dbb750cfe5..f18454ec3e 100644 --- a/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py +++ b/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py @@ -39,7 +39,7 @@ def set_call_span_attributes(span, kwargs, response): return endpoint_name = kwargs.get("EndpointName") - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, endpoint_name) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, endpoint_name) def set_call_request_attributes(span, kwargs): diff --git a/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py b/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py index cb0225e7cd..87bc66a802 100644 --- a/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py +++ b/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py @@ -43,7 +43,7 @@ def test_sagemaker_completion_string_content_legacy( spans = span_exporter.get_finished_spans() meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == endpoint_name + assert meta_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name assert meta_span.attributes[SpanAttributes.TRACELOOP_ENTITY_INPUT] == body logs = log_exporter.get_finished_logs() @@ -84,7 +84,7 @@ def test_sagemaker_completion_string_content_with_events_with_content( spans = span_exporter.get_finished_spans() meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == endpoint_name + assert meta_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -136,7 +136,7 @@ def test_sagemaker_completion_string_content_with_events_with_no_content( spans = span_exporter.get_finished_spans() meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == endpoint_name + assert meta_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py index 8173d6e9d5..5d3345b025 100644 --- a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py +++ b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py @@ -113,7 +113,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "TogetherAI", + SpanAttributes.GEN_AI_SYSTEM: "TogetherAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) diff --git a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py index c6f0e50366..a462bd312e 100644 --- a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py +++ b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py @@ -22,22 +22,22 @@ def set_prompt_attributes(span, llm_request_type, kwargs): if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") for index, message in enumerate(kwargs.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.content", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", message.get("content"), ) _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.role", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", message.get("role"), ) elif llm_request_type == LLMRequestTypeValues.COMPLETION: - _set_span_attribute(span, f"{SpanAttributes.LLM_PROMPTS}.0.role", "user") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.content", kwargs.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("prompt") ) @@ -46,7 +46,7 @@ def set_model_prompt_attributes(span, kwargs): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) _set_span_attribute( span, SpanAttributes.LLM_IS_STREAMING, @@ -63,15 +63,15 @@ def set_completion_attributes(span, llm_request_type, response): if llm_request_type == LLMRequestTypeValues.COMPLETION: _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response.choices[0].text, ) _set_span_attribute( - span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", "assistant" + span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) elif llm_request_type == LLMRequestTypeValues.CHAT: index = 0 - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.content", response.choices[0].message.content ) @@ -85,7 +85,7 @@ def set_model_completion_attributes(span, response): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response.model) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.model) _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.id) usage_data = response.usage diff --git a/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py b/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py index 009b1de601..16e4dc2763 100644 --- a/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py +++ b/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py @@ -35,20 +35,20 @@ def set_model_input_attributes(span, instance): forward_params = instance._forward_params _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MODEL, instance.model.config.name_or_path + span, SpanAttributes.GEN_AI_REQUEST_MODEL, instance.model.config.name_or_path ) _set_span_attribute( - span, SpanAttributes.LLM_SYSTEM, instance.model.config.model_type + span, SpanAttributes.GEN_AI_SYSTEM, instance.model.config.model_type ) _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TYPE, "completion") _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, forward_params.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, forward_params.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, forward_params.get("top_p") + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, forward_params.get("top_p") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, forward_params.get("max_length") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, forward_params.get("max_length") ) _set_span_attribute( span, @@ -69,7 +69,7 @@ def _set_span_completions(span, completions): return for i, completion in enumerate(completions): - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{i}" + prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{i}" _set_span_attribute(span, f"{prefix}.content", completion.get("generated_text")) @@ -81,5 +81,5 @@ def _set_span_prompts(span, messages): messages = [messages] for i, msg in enumerate(messages): - prefix = f"{SpanAttributes.LLM_PROMPTS}.{i}" + prefix = f"{SpanAttributes.GEN_AI_PROMPT}.{i}" _set_span_attribute(span, f"{prefix}.content", msg) diff --git a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py index 67068e3f65..8a69d444cd 100644 --- a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py +++ b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py @@ -229,7 +229,7 @@ async def _awrap(tracer, event_logger, to_wrap, wrapped, instance, args, kwargs) name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Google", + SpanAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -273,7 +273,7 @@ def _wrap(tracer, event_logger, to_wrap, wrapped, instance, args, kwargs): name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Google", + SpanAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py index f12873887f..53b0bf8925 100644 --- a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py +++ b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py @@ -24,7 +24,7 @@ def set_input_attributes(span, args): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.user", + f"{SpanAttributes.GEN_AI_PROMPT}.0.user", prompt, ) @@ -33,17 +33,17 @@ def set_input_attributes(span, args): def set_model_input_attributes(span, kwargs, llm_model): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, llm_model) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, llm_model) _set_span_attribute( - span, f"{SpanAttributes.LLM_PROMPTS}.0.user", kwargs.get("prompt") + span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") + span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") ) - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) _set_span_attribute(span, SpanAttributes.LLM_TOP_K, kwargs.get("top_k")) _set_span_attribute( span, SpanAttributes.LLM_PRESENCE_PENALTY, kwargs.get("presence_penalty") @@ -57,10 +57,10 @@ def set_model_input_attributes(span, kwargs, llm_model): def set_response_attributes(span, llm_model, generation_text): if not span.is_recording() or not should_send_prompts(): return - _set_span_attribute(span, f"{SpanAttributes.LLM_COMPLETIONS}.0.role", "assistant") + _set_span_attribute(span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant") _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", generation_text, ) @@ -69,7 +69,7 @@ def set_response_attributes(span, llm_model, generation_text): def set_model_response_attributes(span, llm_model, token_usage): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, llm_model) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, llm_model) if token_usage: _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py index ca6e6413f5..16ceec2b44 100644 --- a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py +++ b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py @@ -38,17 +38,17 @@ def test_vertexai_predict(instrument_legacy, span_exporter, log_exporter): vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "text-bison@001" + vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison@001" ) assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 assert ( - vertexai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -81,17 +81,17 @@ async def async_predict_text() -> str: vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "text-bison@001" + vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison@001" ) assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 assert ( - vertexai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -118,16 +118,16 @@ def test_vertexai_stream(instrument_legacy, span_exporter, log_exporter): ] vertexai_span = spans[0] - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "text-bison" + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison" assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 assert vertexai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) @@ -158,16 +158,16 @@ async def async_streaming_prediction() -> list: ] vertexai_span = spans[0] - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "text-bison" + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison" assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 assert vertexai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) @@ -204,17 +204,17 @@ def test_vertexai_chat(instrument_legacy, span_exporter, log_exporter): vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "chat-bison@001" + vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "chat-bison@001" ) assert ( "How many planets are there in the solar system?" - in vertexai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.95 - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 assert ( - vertexai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -254,14 +254,14 @@ def test_vertexai_chat_stream(instrument_legacy, span_exporter, log_exporter): vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "chat-bison@001" + vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "chat-bison@001" ) - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_TOP_P] == 0.95 - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_TEMPERATURE] == 0.8 - assert vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.8 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 assert vertexai_span.attributes[ - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) diff --git a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py index 78ad2d4c57..cb37e71042 100644 --- a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py +++ b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py @@ -32,10 +32,10 @@ def test_vertexai_generate_content(instrument_legacy, span_exporter, log_exporte vertexai_span = spans[0] assert ( "what is shown in this image?" - in vertexai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] ) assert ( - vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gemini-2.0-flash-lite" ) assert ( @@ -51,7 +51,7 @@ def test_vertexai_generate_content(instrument_legacy, span_exporter, log_exporte == response._raw_response.usage_metadata.candidates_token_count ) assert ( - vertexai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response.text ) @@ -84,7 +84,7 @@ def test_vertexai_generate_content_with_events_with_content( vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gemini-2.0-flash-lite" ) assert ( @@ -144,7 +144,7 @@ def test_vertexai_generate_content_with_events_with_no_content( vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] + vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gemini-2.0-flash-lite" ) assert ( diff --git a/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py b/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py index c77dda67e6..d8284c412e 100644 --- a/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py +++ b/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py @@ -132,13 +132,13 @@ def _set_input_attributes(span, instance, kwargs): for index, input in enumerate(prompt): _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{index}.user", + f"{SpanAttributes.GEN_AI_PROMPT}.{index}.user", input, ) else: _set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.0.user", + f"{SpanAttributes.GEN_AI_PROMPT}.0.user", prompt, ) @@ -147,7 +147,7 @@ def set_model_input_attributes(span, instance): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, instance.model_id) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, instance.model_id) # Set other attributes modelParameters = instance.params if modelParameters is not None: @@ -181,11 +181,11 @@ def set_model_input_attributes(span, instance): ) _set_span_attribute( span, - SpanAttributes.LLM_REQUEST_TEMPERATURE, + SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, modelParameters.get("temperature", None), ) _set_span_attribute( - span, SpanAttributes.LLM_REQUEST_TOP_P, modelParameters.get("top_p", None) + span, SpanAttributes.GEN_AI_REQUEST_TOP_P, modelParameters.get("top_p", None) ) @@ -194,7 +194,7 @@ def _set_stream_response_attributes(span, stream_response): return _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.0.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", stream_response.get("generated_text"), ) @@ -203,7 +203,7 @@ def _set_model_stream_response_attributes(span, stream_response): if not span.is_recording(): return _set_span_attribute( - span, SpanAttributes.LLM_RESPONSE_MODEL, stream_response.get("model_id") + span, SpanAttributes.GEN_AI_RESPONSE_MODEL, stream_response.get("model_id") ) _set_span_attribute( span, @@ -235,14 +235,14 @@ def _set_completion_content_attributes( if should_send_prompts(): _set_span_attribute( span, - f"{SpanAttributes.LLM_COMPLETIONS}.{index}.content", + f"{SpanAttributes.GEN_AI_COMPLETION}.{index}.content", results[0]["generated_text"], ) model_id = response.get("model_id") if response_counter: attributes_with_reason = { - SpanAttributes.LLM_RESPONSE_MODEL: model_id, + SpanAttributes.GEN_AI_RESPONSE_MODEL: model_id, SpanAttributes.LLM_RESPONSE_STOP_REASON: results[0]["stop_reason"], } response_counter.add(1, attributes=attributes_with_reason) @@ -289,7 +289,7 @@ def _set_response_attributes( if model_id is None: return - _set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, model_id) + _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, model_id) shared_attributes = _metric_shared_attributes(response_model=model_id) @@ -298,12 +298,12 @@ def _set_response_attributes( if token_histogram: attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", } token_histogram.record(completion_token, attributes=attributes_with_token_type) attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", } token_histogram.record(prompt_token, attributes=attributes_with_token_type) @@ -409,14 +409,14 @@ def _build_and_set_stream_response( if token_histogram: attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "output", + SpanAttributes.GEN_AI_TOKEN_TYPE: "output", } token_histogram.record( stream_generated_token_count, attributes=attributes_with_token_type ) attributes_with_token_type = { **shared_attributes, - SpanAttributes.LLM_TOKEN_TYPE: "input", + SpanAttributes.GEN_AI_TOKEN_TYPE: "input", } token_histogram.record( stream_input_token_count, attributes=attributes_with_token_type @@ -436,8 +436,8 @@ def _build_and_set_stream_response( def _metric_shared_attributes(response_model: str, is_streaming: bool = False): return { - SpanAttributes.LLM_RESPONSE_MODEL: response_model, - SpanAttributes.LLM_SYSTEM: "watsonx", + SpanAttributes.GEN_AI_RESPONSE_MODEL: response_model, + SpanAttributes.GEN_AI_SYSTEM: "watsonx", "stream": is_streaming, } @@ -561,7 +561,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.LLM_SYSTEM: "Watsonx", + SpanAttributes.GEN_AI_SYSTEM: "Watsonx", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py b/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py index 99393576c7..a06c5f764c 100644 --- a/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py +++ b/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py @@ -31,7 +31,7 @@ def test_generate_metrics(metrics_test_context_legacy, watson_ai_model, log_expo if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -52,7 +52,7 @@ def test_generate_metrics(metrics_test_context_legacy, watson_ai_model, log_expo ) assert ( - metric.data.data_points[0].attributes[SpanAttributes.LLM_SYSTEM] + metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] == "watsonx" ) @@ -100,7 +100,7 @@ def test_generate_stream_metrics( if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -121,7 +121,7 @@ def test_generate_stream_metrics( ) assert ( - metric.data.data_points[0].attributes[SpanAttributes.LLM_SYSTEM] + metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] == "watsonx" ) diff --git a/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py b/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py index 8b125d60ca..656c9c1146 100644 --- a/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py +++ b/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py @@ -23,11 +23,11 @@ def test_generate(exporter_legacy, watson_ai_model, log_exporter): spans = exporter_legacy.get_finished_spans() watsonx_ai_span = spans[1] assert ( - watsonx_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + watsonx_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "What is 1 + 1?" ) - assert watsonx_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "Watsonx" - assert watsonx_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -49,7 +49,7 @@ def test_generate_with_events_with_content( response = watson_ai_model.generate(prompt="What is 1 + 1?") spans = exporter_with_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -85,7 +85,7 @@ def test_generate_with_with_events_no_content( response = watson_ai_model.generate(prompt="What is 1 + 1?") spans = exporter_with_no_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -120,12 +120,12 @@ def test_generate_text_stream(exporter_legacy, watson_ai_model, log_exporter): spans = exporter_legacy.get_finished_spans() watsonx_ai_span = spans[1] assert ( - watsonx_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.user"] + watsonx_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == "Write an epigram about the sun" ) - assert watsonx_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" assert ( - watsonx_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + watsonx_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == generated_text ) assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -154,7 +154,7 @@ def test_generate_text_stream_with_events_with_content( generated_text += chunk spans = exporter_with_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -195,7 +195,7 @@ def test_generate_text_stream_with_events_with_no_content( generated_text += chunk spans = exporter_with_no_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.LLM_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py index 96474a841a..f9dbee646c 100644 --- a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py +++ b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py @@ -1,4 +1,5 @@ from enum import Enum +import opentelemetry.semconv._incubating.attributes.gen_ai_attributes as otel_gen_ai_attributes SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY = "suppress_language_model_instrumentation" @@ -34,25 +35,44 @@ class Meters: class SpanAttributes: - # Semantic Conventions for LLM requests, this needs to be removed after - # OpenTelemetry Semantic Conventions support Gen AI. - # Issue at https://github.com/open-telemetry/opentelemetry-python/issues/3868 + # OpenTelemetry Semantic Conventions for Gen AI - # Refer to https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-spans.md - # for more detail for LLM spans from OpenTelemetry Community. - LLM_SYSTEM = "gen_ai.system" - LLM_REQUEST_MODEL = "gen_ai.request.model" - LLM_REQUEST_MAX_TOKENS = "gen_ai.request.max_tokens" - LLM_REQUEST_TEMPERATURE = "gen_ai.request.temperature" - LLM_REQUEST_TOP_P = "gen_ai.request.top_p" - LLM_PROMPTS = "gen_ai.prompt" - LLM_COMPLETIONS = "gen_ai.completion" - LLM_RESPONSE_MODEL = "gen_ai.response.model" - LLM_USAGE_COMPLETION_TOKENS = "gen_ai.usage.output_tokens" - LLM_USAGE_PROMPT_TOKENS = "gen_ai.usage.input_tokens" - LLM_USAGE_CACHE_CREATION_INPUT_TOKENS = "gen_ai.usage.cache_creation_input_tokens" - LLM_USAGE_CACHE_READ_INPUT_TOKENS = "gen_ai.usage.cache_read_input_tokens" - LLM_TOKEN_TYPE = "gen_ai.token.type" - LLM_REQUEST_STRUCTURED_OUTPUT_SCHEMA = "gen_ai.request.structured_output_schema" + GEN_AI_AGENT_DESCRIPTION=otel_gen_ai_attributes.GEN_AI_AGENT_DESCRIPTION + GEN_AI_AGENT_ID= otel_gen_ai_attributes.GEN_AI_AGENT_ID + GEN_AI_AGENT_NAME= otel_gen_ai_attributes.GEN_AI_AGENT_NAME + GEN_AI_COMPLETION=otel_gen_ai_attributes.GEN_AI_COMPLETION + GEN_AI_CONVERSATION_ID=otel_gen_ai_attributes.GEN_AI_CONVERSATION_ID + GEN_AI_DATA_SOURCE_ID=otel_gen_ai_attributes.GEN_AI_DATA_SOURCE_ID + GEN_AI_OPENAI_REQUEST_SERVICE_TIER=otel_gen_ai_attributes.GEN_AI_OPENAI_REQUEST_SERVICE_TIER + GEN_AI_OPENAI_RESPONSE_SERVICE_TIER=otel_gen_ai_attributes.GEN_AI_OPENAI_RESPONSE_SERVICE_TIER + GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT=otel_gen_ai_attributes.GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT + GEN_AI_OUTPUT_TYPE=otel_gen_ai_attributes.GEN_AI_OUTPUT_TYPE + GEN_AI_PROMPT=otel_gen_ai_attributes.GEN_AI_PROMPT + GEN_AI_REQUEST_CHOICE_COUNT=otel_gen_ai_attributes.GEN_AI_REQUEST_CHOICE_COUNT + GEN_AI_REQUEST_ENCODING_FORMATS= otel_gen_ai_attributes.GEN_AI_REQUEST_ENCODING_FORMATS + GEN_AI_REQUEST_FREQUENCY_PENALTY= otel_gen_ai_attributes.GEN_AI_REQUEST_FREQUENCY_PENALTY + GEN_AI_REQUEST_MAX_TOKENS=otel_gen_ai_attributes.GEN_AI_REQUEST_MAX_TOKENS + GEN_AI_REQUEST_MODEL=otel_gen_ai_attributes.GEN_AI_REQUEST_MODEL + GEN_AI_REQUEST_PRESENCE_PENALTY=otel_gen_ai_attributes.GEN_AI_REQUEST_PRESENCE_PENALTY + GEN_AI_REQUEST_SEED=otel_gen_ai_attributes.GEN_AI_REQUEST_SEED + GEN_AI_REQUEST_STOP_SEQUENCES=otel_gen_ai_attributes.GEN_AI_REQUEST_STOP_SEQUENCES + GEN_AI_REQUEST_TEMPERATURE=otel_gen_ai_attributes.GEN_AI_REQUEST_TEMPERATURE + GEN_AI_REQUEST_TOP_K=otel_gen_ai_attributes.GEN_AI_REQUEST_TOP_K + GEN_AI_REQUEST_TOP_P=otel_gen_ai_attributes.GEN_AI_REQUEST_TOP_P + GEN_AI_REQUEST_STRUCTURED_OUTPUT_SCHEMA = "gen_ai.request.structured_output_schema" + GEN_AI_RESPONSE_FINISH_REASONS=otel_gen_ai_attributes.GEN_AI_RESPONSE_FINISH_REASONS + GEN_AI_RESPONSE_ID=otel_gen_ai_attributes.GEN_AI_RESPONSE_ID + GEN_AI_RESPONSE_MODEL=otel_gen_ai_attributes.GEN_AI_RESPONSE_MODEL + GEN_AI_SYSTEM=otel_gen_ai_attributes.GEN_AI_SYSTEM + GEN_AI_TOKEN_TYPE=otel_gen_ai_attributes.GEN_AI_TOKEN_TYPE + GEN_AI_TOOL_CALL_ID=otel_gen_ai_attributes.GEN_AI_TOOL_CALL_ID + GEN_AI_TOOL_DESCRIPTION=otel_gen_ai_attributes.GEN_AI_TOOL_DESCRIPTION + GEN_AI_TOOL_NAME=otel_gen_ai_attributes.GEN_AI_TOOL_NAME + GEN_AI_TOOL_TYPE=otel_gen_ai_attributes.GEN_AI_TOOL_TYPE + GEN_AI_USAGE_INPUT_TOKENS=otel_gen_ai_attributes.GEN_AI_USAGE_INPUT_TOKENS + GEN_AI_USAGE_OUTPUT_TOKENS=otel_gen_ai_attributes.GEN_AI_USAGE_OUTPUT_TOKENS + GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS = "gen_ai.usage.cache_creation_input_tokens" + GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = "gen_ai.usage.cache_read_input_tokens" # LLM LLM_REQUEST_TYPE = "llm.request.type" diff --git a/packages/opentelemetry-semantic-conventions-ai/poetry.lock b/packages/opentelemetry-semantic-conventions-ai/poetry.lock index 2e13e6ce0c..dec2a76d43 100644 --- a/packages/opentelemetry-semantic-conventions-ai/poetry.lock +++ b/packages/opentelemetry-semantic-conventions-ai/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "autopep8" @@ -62,6 +62,30 @@ mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.11.0,<2.12.0" pyflakes = ">=3.2.0,<3.3.0" +[[package]] +name = "importlib-metadata" +version = "8.7.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"}, + {file = "importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000"}, +] + +[package.dependencies] +zipp = ">=3.20" + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +perf = ["ipython"] +test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["pytest-mypy"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -86,6 +110,55 @@ files = [ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] +[[package]] +name = "opentelemetry-api" +version = "1.35.0" +description = "OpenTelemetry Python API" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_api-1.35.0-py3-none-any.whl", hash = "sha256:c4ea7e258a244858daf18474625e9cc0149b8ee354f37843415771a40c25ee06"}, + {file = "opentelemetry_api-1.35.0.tar.gz", hash = "sha256:a111b959bcfa5b4d7dffc2fbd6a241aa72dd78dd8e79b5b1662bda896c5d2ffe"}, +] + +[package.dependencies] +importlib-metadata = ">=6.0,<8.8.0" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-sdk" +version = "1.35.0" +description = "OpenTelemetry Python SDK" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_sdk-1.35.0-py3-none-any.whl", hash = "sha256:223d9e5f5678518f4842311bb73966e0b6db5d1e0b74e35074c052cd2487f800"}, + {file = "opentelemetry_sdk-1.35.0.tar.gz", hash = "sha256:2a400b415ab68aaa6f04e8a6a9f6552908fb3090ae2ff78d6ae0c597ac581954"}, +] + +[package.dependencies] +opentelemetry-api = "1.35.0" +opentelemetry-semantic-conventions = "0.56b0" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.56b0" +description = "OpenTelemetry Semantic Conventions" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_semantic_conventions-0.56b0-py3-none-any.whl", hash = "sha256:df44492868fd6b482511cc43a942e7194be64e94945f572db24df2e279a001a2"}, + {file = "opentelemetry_semantic_conventions-0.56b0.tar.gz", hash = "sha256:c114c2eacc8ff6d3908cb328c811eaf64e6d68623840be9224dc829c4fd6c2ea"}, +] + +[package.dependencies] +opentelemetry-api = "1.35.0" +typing-extensions = ">=4.5.0" + [[package]] name = "packaging" version = "24.1" @@ -209,7 +282,39 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "typing-extensions" +version = "4.14.1" +description = "Backported and Experimental Type Hints for Python 3.9+" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"}, + {file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"}, +] + +[[package]] +name = "zipp" +version = "3.23.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, + {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] + [metadata] lock-version = "2.1" python-versions = ">=3.9,<4" -content-hash = "4aa103228aa2f0c253690ff1a73203803c137319a5b3fe49c68773c87a401907" +content-hash = "6f5d29ff2d916317f0ca2c830518ae1ce166b83c5ec808c9ef563855ebced3a4" diff --git a/packages/opentelemetry-semantic-conventions-ai/pyproject.toml b/packages/opentelemetry-semantic-conventions-ai/pyproject.toml index a5e9382ae9..3c81ed22ac 100644 --- a/packages/opentelemetry-semantic-conventions-ai/pyproject.toml +++ b/packages/opentelemetry-semantic-conventions-ai/pyproject.toml @@ -23,6 +23,7 @@ include = "opentelemetry/semconv_ai" [tool.poetry.dependencies] python = ">=3.9,<4" +opentelemetry-sdk = "^1.35.0" [tool.poetry.group.dev.dependencies] autopep8 = "^2.2.0" diff --git a/packages/traceloop-sdk/tests/test_manual.py b/packages/traceloop-sdk/tests/test_manual.py index 182fc000a2..d3afd6f282 100644 --- a/packages/traceloop-sdk/tests/test_manual.py +++ b/packages/traceloop-sdk/tests/test_manual.py @@ -36,18 +36,18 @@ def test_manual_report(exporter, openai_client): spans = exporter.get_finished_spans() open_ai_span = spans[0] - assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-3.5-turbo" - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" + assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes[SpanAttributes.LLM_RESPONSE_MODEL] + open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == "Why did the opentelemetry developer break up with their partner? Because they were tired" + " of constantly tracing their every move!" ) diff --git a/packages/traceloop-sdk/tests/test_privacy_no_prompts.py b/packages/traceloop-sdk/tests/test_privacy_no_prompts.py index 931d2008ef..9b870e18c6 100644 --- a/packages/traceloop-sdk/tests/test_privacy_no_prompts.py +++ b/packages/traceloop-sdk/tests/test_privacy_no_prompts.py @@ -44,7 +44,7 @@ def joke_workflow(): ] open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 15 - assert not open_ai_span.attributes.get(f"{SpanAttributes.LLM_PROMPTS}.0.content") + assert not open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") assert not open_ai_span.attributes.get( - f"{SpanAttributes.LLM_PROMPTS}.0.completions" + f"{SpanAttributes.GEN_AI_PROMPT}.0.completions" ) diff --git a/packages/traceloop-sdk/tests/test_prompt_management.py b/packages/traceloop-sdk/tests/test_prompt_management.py index 40737655a3..098309d401 100644 --- a/packages/traceloop-sdk/tests/test_prompt_management.py +++ b/packages/traceloop-sdk/tests/test_prompt_management.py @@ -82,8 +82,8 @@ def test_prompt_management(exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry, pirate style" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert open_ai_span.attributes.get("traceloop.prompt.key") == "joke_generator" diff --git a/packages/traceloop-sdk/tests/test_workflows.py b/packages/traceloop-sdk/tests/test_workflows.py index c8d45967ba..3c167b9c4c 100644 --- a/packages/traceloop-sdk/tests/test_workflows.py +++ b/packages/traceloop-sdk/tests/test_workflows.py @@ -44,8 +44,8 @@ def joke_workflow(): "pirate_joke_generator.workflow", ] open_ai_span = next(span for span in spans if span.name == "openai.chat") - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == "Tell me a joke about OpenTelemetry" - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert open_ai_span.attributes.get("traceloop.prompt.template") == "Tell me a {what} about {subject}" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.what") == "joke" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.subject") == "OpenTelemetry" @@ -90,8 +90,8 @@ async def joke_workflow(): "pirate_joke_generator.workflow", ] open_ai_span = next(span for span in spans if span.name == "openai.chat") - assert open_ai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] == "Tell me a joke about OpenTelemetry" - assert open_ai_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" + assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert open_ai_span.attributes.get("traceloop.prompt.template") == "Tell me a {what} about {subject}" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.what") == "joke" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.subject") == "OpenTelemetry" diff --git a/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py b/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py index e289c2d409..c877117175 100644 --- a/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py +++ b/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py @@ -26,23 +26,23 @@ def __init__(self, span: Span): pass def report_request(self, model: str, messages: list[LLMMessage]): - self._span.set_attribute(SpanAttributes.LLM_REQUEST_MODEL, model) + self._span.set_attribute(SpanAttributes.GEN_AI_REQUEST_MODEL, model) for idx, message in enumerate(messages): self._span.set_attribute( - f"{SpanAttributes.LLM_PROMPTS}.{idx}.role", message.role + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", message.role ) self._span.set_attribute( - f"{SpanAttributes.LLM_PROMPTS}.{idx}.content", message.content + f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", message.content ) def report_response(self, model: str, completions: list[str]): - self._span.set_attribute(SpanAttributes.LLM_RESPONSE_MODEL, model) + self._span.set_attribute(SpanAttributes.GEN_AI_RESPONSE_MODEL, model) for idx, completion in enumerate(completions): self._span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.role", "assistant" + f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role", "assistant" ) self._span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.content", completion + f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content", completion ) def report_usage(self, usage: LLMUsage): @@ -69,7 +69,7 @@ def report_usage(self, usage: LLMUsage): def track_llm_call(vendor: str, type: str): with get_tracer() as tracer: with tracer.start_as_current_span(name=f"{vendor}.{type}") as span: - span.set_attribute(SpanAttributes.LLM_SYSTEM, vendor) + span.set_attribute(SpanAttributes.GEN_AI_SYSTEM, vendor) span.set_attribute(SpanAttributes.LLM_REQUEST_TYPE, type) llm_span = LLMSpan(span) try: From 64ade2bfa71fa565fdb7fdac1961da88bf1497c6 Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Sat, 19 Jul 2025 16:39:30 +0000 Subject: [PATCH 3/8] fixed remaining opentelemetry gen_ai attributes --- .../instrumentation/alephalpha/__init__.py | 2 +- .../instrumentation/anthropic/__init__.py | 4 +-- .../instrumentation/anthropic/span_utils.py | 2 +- .../instrumentation/anthropic/streaming.py | 2 +- .../tests/test_messages.py | 36 +++++++++---------- .../instrumentation/bedrock/span_utils.py | 2 +- .../tests/traces/test_ai21.py | 12 +++---- .../tests/traces/test_anthropic.py | 30 ++++++++-------- .../tests/traces/test_meta.py | 24 ++++++------- .../tests/traces/test_nova.py | 6 ++-- .../tests/traces/test_titan.py | 6 ++-- .../instrumentation/cohere/span_utils.py | 4 +-- .../tests/test_chat.py | 2 +- .../google_generativeai/span_utils.py | 4 +-- .../tests/test_generate_content.py | 6 ++-- .../instrumentation/groq/span_utils.py | 4 +-- .../tests/traces/test_chat_tracing.py | 18 +++++----- .../langchain/callback_handler.py | 2 +- .../instrumentation/langchain/span_utils.py | 2 +- .../tests/test_llms.py | 24 ++++++------- .../instrumentation/llamaindex/span_utils.py | 2 +- .../tests/test_agents.py | 24 ++++++------- .../tests/test_chroma_vector_store.py | 2 +- .../instrumentation/mistralai/__init__.py | 2 +- .../tests/test_chat.py | 24 ++++++------- .../instrumentation/ollama/span_utils.py | 2 +- .../tests/test_chat.py | 24 ++++++------- .../tests/test_generation.py | 24 ++++++------- .../instrumentation/openai_agents/__init__.py | 2 +- .../tests/test_openai_agents.py | 2 +- .../instrumentation/openai/shared/__init__.py | 4 +-- .../openai/v1/assistant_wrappers.py | 2 +- .../openai/v1/event_handler_wrapper.py | 2 +- .../tests/traces/test_assistant.py | 30 ++++++++-------- .../tests/traces/test_azure.py | 6 ++-- .../tests/traces/test_chat.py | 12 +++---- .../tests/traces/test_completions.py | 6 ++-- .../instrumentation/together/span_utils.py | 2 +- .../instrumentation/vertexai/span_utils.py | 4 +-- .../tests/disabled_test_bison.py | 12 +++---- .../tests/disabled_test_gemini.py | 6 ++-- .../instrumentation/watsonx/__init__.py | 6 ++-- packages/traceloop-sdk/tests/test_manual.py | 2 +- .../traceloop/sdk/tracing/manual.py | 2 +- 44 files changed, 198 insertions(+), 198 deletions(-) diff --git a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py index 2f4eb239e5..9744b84aa4 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py +++ b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py @@ -86,7 +86,7 @@ def _handle_completion_event(event: CompletionEvent, span, event_logger, respons span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, input_tokens + output_tokens ) _set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, output_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens ) _set_span_attribute(span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, input_tokens) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py index 86668e3556..f74894de7a 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py @@ -177,7 +177,7 @@ async def _aset_token_usage( set_span_attribute(span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, input_tokens) set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute(span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens) @@ -268,7 +268,7 @@ def _set_token_usage( set_span_attribute(span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, input_tokens) set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute(span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py index a3fbc3f032..8970120c80 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py @@ -221,7 +221,7 @@ def set_response_attributes(span, response): completion_tokens = response.get("usage").output_tokens set_span_attribute(span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, prompt_tokens) set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute( span, diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py index bc8e9ae5c9..4ad476ec44 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py @@ -86,7 +86,7 @@ def _set_token_usage( set_span_attribute(span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, input_tokens) set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute(span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens) diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py index 758565c63b..820d38b2fb 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py @@ -70,7 +70,7 @@ def test_anthropic_message_create_legacy( ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -117,7 +117,7 @@ def test_anthropic_message_create_with_events_with_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -182,7 +182,7 @@ def test_anthropic_message_create_with_events_with_no_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -253,7 +253,7 @@ def test_anthropic_multi_modal_legacy( ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1381 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -307,7 +307,7 @@ def test_anthropic_multi_modal_with_events_with_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1381 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -368,7 +368,7 @@ def test_anthropic_multi_modal_with_events_with_no_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1381 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -534,7 +534,7 @@ async def test_anthropic_async_multi_modal_legacy( ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1311 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -589,7 +589,7 @@ async def test_anthropic_async_multi_modal_with_events_with_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1311 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -651,7 +651,7 @@ async def test_anthropic_async_multi_modal_with_events_with_no_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1311 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -719,7 +719,7 @@ def test_anthropic_message_streaming_legacy( ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -773,7 +773,7 @@ def test_anthropic_message_streaming_with_events_with_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -838,7 +838,7 @@ def test_anthropic_message_streaming_with_events_with_no_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -906,7 +906,7 @@ async def test_async_anthropic_message_create_legacy( ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -953,7 +953,7 @@ async def test_async_anthropic_message_create_with_events_with_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -1011,7 +1011,7 @@ async def test_async_anthropic_message_create_with_events_with_no_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -1084,7 +1084,7 @@ async def test_async_anthropic_message_streaming_legacy( ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -1138,7 +1138,7 @@ async def test_async_anthropic_message_streaming_with_events_with_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -1202,7 +1202,7 @@ async def test_async_anthropic_message_streaming_with_events_with_no_content( anthropic_span = spans[0] assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) diff --git a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py index 1e8d7ab2e8..ec0f3ba0ad 100644 --- a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py +++ b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py @@ -528,7 +528,7 @@ def _record_usage_to_span(span, prompt_tokens, completion_tokens, metric_params) ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py index 231ca3bd39..764399a6f0 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py @@ -46,13 +46,13 @@ def test_ai21_j2_completion_string_content( assert meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == len( response_body.get("prompt").get("tokens") ) - assert meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == len( + assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( response_body.get("completions")[0].get("data").get("tokens") ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] - + meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] ) # It is apparently always 1234, but for the sake of consistency, # we should not assert on it. @@ -99,13 +99,13 @@ def test_ai21_j2_completion_string_content_with_events_with_content( assert meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == len( response_body.get("prompt").get("tokens") ) - assert meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == len( + assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( response_body.get("completions")[0].get("data").get("tokens") ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] - + meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] ) # It is apparently always 1234, but for the sake of consistency, # we should not assert on it. @@ -158,13 +158,13 @@ def test_ai21_j2_completion_string_content_with_events_with_no_content( assert meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == len( response_body.get("prompt").get("tokens") ) - assert meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == len( + assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( response_body.get("completions")[0].get("data").get("tokens") ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] - + meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] ) # It is apparently always 1234, but for the sake of consistency, # we should not assert on it. diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py index 4f2fb541d8..51c696e67e 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py @@ -47,7 +47,7 @@ def test_anthropic_2_completion(instrument_legacy, brt, span_exporter, log_expor assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 13 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -89,7 +89,7 @@ def test_anthropic_2_completion_with_events_with_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 13 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -145,7 +145,7 @@ def test_anthropic_2_completion_with_events_with_no_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 13 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -217,7 +217,7 @@ def test_anthropic_3_completion_complex_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -269,7 +269,7 @@ def test_anthropic_3_completion_complex_content_with_events_with_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -339,7 +339,7 @@ def test_anthropic_3_completion_complex_content_with_events_with_no_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -420,7 +420,7 @@ def test_anthropic_3_completion_streaming( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -477,7 +477,7 @@ def test_anthropic_3_completion_streaming_with_events_with_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -548,7 +548,7 @@ def test_anthropic_3_completion_streaming_with_events_with_no_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -619,7 +619,7 @@ def test_anthropic_3_completion_string_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -669,7 +669,7 @@ def test_anthropic_3_completion_string_content_with_events_with_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -732,7 +732,7 @@ def test_anthropic_3_completion_string_content_with_events_with_no_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -799,7 +799,7 @@ def test_anthropic_cross_region(instrument_legacy, brt, span_exporter, log_expor assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 20 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -847,7 +847,7 @@ def test_anthropic_cross_region_with_events_with_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 20 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -913,7 +913,7 @@ def test_anthropic_cross_region_with_events_with_no_content( assert anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 20 assert anthropic_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py index 43b0d0d876..aa87e11fe7 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py @@ -43,7 +43,7 @@ def test_meta_llama2_completion_string_content( == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -90,7 +90,7 @@ def test_meta_llama2_completion_string_content_with_events_with_content( == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -147,7 +147,7 @@ def test_meta_llama2_completion_string_content_with_events_with_no_content( == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -194,7 +194,7 @@ def test_meta_llama3_completion(instrument_legacy, brt, span_exporter, log_expor == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -238,7 +238,7 @@ def test_meta_llama3_completion_with_events_with_content( == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -287,7 +287,7 @@ def test_meta_llama3_completion_with_events_with_no_content( == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -343,7 +343,7 @@ def test_meta_converse(instrument_legacy, brt, span_exporter, log_exporter): == response["usage"]["inputTokens"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response["usage"]["outputTokens"] ) assert ( @@ -408,7 +408,7 @@ def test_meta_converse_with_events_with_content( == response["usage"]["inputTokens"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response["usage"]["outputTokens"] ) assert ( @@ -475,7 +475,7 @@ def test_meta_converse_with_events_with_no_content( == response["usage"]["inputTokens"] ) assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response["usage"]["outputTokens"] ) assert ( @@ -552,7 +552,7 @@ def test_meta_converse_stream(instrument_legacy, brt, span_exporter, log_exporte meta_span = spans[0] assert meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == outputTokens + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] @@ -628,7 +628,7 @@ def test_meta_converse_stream_with_events_with_content( meta_span = spans[0] assert meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == outputTokens + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] @@ -708,7 +708,7 @@ def test_meta_converse_stream_with_events_with_no_content( meta_span = spans[0] assert meta_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens assert ( - meta_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == outputTokens + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py index 2241f43822..ab4025296f 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py @@ -902,7 +902,7 @@ def test_nova_converse_stream(instrument_legacy, brt, span_exporter, log_exporte bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -1007,7 +1007,7 @@ def test_nova_converse_stream_with_events_with_content( bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -1132,7 +1132,7 @@ def test_nova_converse_stream_with_events_with_no_content( bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py index 088e8fa790..d2d65a8cdd 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py @@ -797,7 +797,7 @@ def test_titan_converse_stream(instrument_legacy, brt, span_exporter, log_export bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -893,7 +893,7 @@ def test_titan_converse_stream_with_events_with_content( bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -1001,7 +1001,7 @@ def test_titan_converse_stream_with_events_with_no_content( bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( diff --git a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py index 4861115446..3169d462f3 100644 --- a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py +++ b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py @@ -106,7 +106,7 @@ def _set_span_chat_response(span, response): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, response.token_count.get("response_tokens"), ) _set_span_attribute( @@ -127,7 +127,7 @@ def _set_span_chat_response(span, response): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py b/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py index c6a8ea9fd5..e532453f2b 100644 --- a/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py @@ -33,7 +33,7 @@ def test_cohere_chat_legacy( assert cohere_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == cohere_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + cohere_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( cohere_span.attributes.get("gen_ai.response.id") diff --git a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py index 2ae944fa9e..cdf5d34937 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py @@ -88,7 +88,7 @@ def set_model_request_attributes(span, kwargs, llm_model): span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") ) _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) - _set_span_attribute(span, SpanAttributes.LLM_TOP_K, kwargs.get("top_k")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_K, kwargs.get("top_k")) _set_span_attribute( span, SpanAttributes.LLM_PRESENCE_PENALTY, kwargs.get("presence_penalty") ) @@ -143,7 +143,7 @@ def set_model_response_attributes(span, response, llm_model): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, response.usage_metadata.candidates_token_count, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py b/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py index 153c5e86c6..61652b21c7 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py @@ -39,7 +39,7 @@ def test_gemini_generate_content_legacy( # assert gemini_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 5 # assert ( - # gemini_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + # gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] # + gemini_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] # == gemini_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] # ) @@ -77,7 +77,7 @@ def test_gemini_generate_content_with_events_with_content( # assert gemini_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 5 # assert ( - # gemini_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + # gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] # + gemini_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] # == gemini_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] # ) @@ -125,7 +125,7 @@ def test_gemini_generate_content_with_events_with_no_content( # assert gemini_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 5 # assert ( - # gemini_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + # gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] # + gemini_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] # == gemini_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] # ) diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py index b37df8d38e..67413fca55 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py @@ -83,7 +83,7 @@ def set_model_streaming_response_attributes(span, usage): if usage: set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, usage.completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens ) set_span_attribute( span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, usage.prompt_tokens @@ -109,7 +109,7 @@ def set_model_response_attributes(span, response, token_histogram): span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.get("total_tokens") ) set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute(span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, prompt_tokens) diff --git a/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py b/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py index 4414d4beb3..fe8aade992 100644 --- a/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py +++ b/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py @@ -29,7 +29,7 @@ def test_chat_legacy(instrument_legacy, groq_client, span_exporter, log_exporter assert groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -59,7 +59,7 @@ def test_chat_with_events_with_content( groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -106,7 +106,7 @@ def test_chat_with_events_with_no_content( groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -152,7 +152,7 @@ async def test_async_chat_legacy( assert groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -183,7 +183,7 @@ async def test_async_chat_with_events_with_content( groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -232,7 +232,7 @@ async def test_async_chat_with_events_with_no_content( groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -286,7 +286,7 @@ def test_chat_streaming_legacy( ) assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 18 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) == 73 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 91 logs = log_exporter.get_finished_logs() @@ -318,7 +318,7 @@ def test_chat_streaming_with_events_with_content( groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 18 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) == 73 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 91 logs = log_exporter.get_finished_logs() @@ -368,7 +368,7 @@ def test_chat_streaming_with_events_with_no_content( groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 18 - assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) == 73 + assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 91 logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py index 8eeb5e0e6f..921c3199f3 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py @@ -469,7 +469,7 @@ def on_llm_end( span, SpanAttributes.LLM_USAGE_PROMPT_TOKENS, prompt_tokens ) _set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) _set_span_attribute( span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py index b747a23ae7..0a84779975 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py @@ -317,7 +317,7 @@ def set_chat_response_usage(span: Span, response: LLMResult): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py index ed9c1053cd..678964da1c 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py @@ -293,7 +293,7 @@ def test_openai(instrument_legacy, span_exporter, log_exporter): ) assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1497 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 1037 + assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2534 assert ( openai_span.attributes[SpanAttributes.LLM_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 @@ -333,7 +333,7 @@ def test_openai_with_events_with_content( assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1497 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 1037 + assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2534 assert ( openai_span.attributes[SpanAttributes.LLM_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 @@ -387,7 +387,7 @@ def test_openai_with_events_with_no_content( assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 1497 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 1037 + assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2534 assert ( openai_span.attributes[SpanAttributes.LLM_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 @@ -493,7 +493,7 @@ class Joke(BaseModel): == response ) assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 76 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 35 + assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 111 logs = log_exporter.get_finished_logs() @@ -540,7 +540,7 @@ class Joke(BaseModel): assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 76 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 35 + assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 111 logs = log_exporter.get_finished_logs() @@ -613,7 +613,7 @@ class Joke(BaseModel): assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 76 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 35 + assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 111 logs = log_exporter.get_finished_logs() @@ -682,7 +682,7 @@ def test_anthropic(instrument_legacy, span_exporter, log_exporter): == "assistant" ) assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 19 - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 22 + assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 41 assert ( anthropic_span.attributes["gen_ai.response.id"] @@ -752,7 +752,7 @@ def test_anthropic_with_events_with_content( assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 19 - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 22 + assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 41 assert ( anthropic_span.attributes["gen_ai.response.id"] @@ -808,7 +808,7 @@ def test_anthropic_with_events_with_no_content( assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 19 - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 22 + assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 41 assert ( anthropic_span.attributes["gen_ai.response.id"] @@ -889,7 +889,7 @@ def test_bedrock(instrument_legacy, span_exporter, log_exporter): == "assistant" ) assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 16 - assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 27 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 43 output = json.loads( workflow_span.attributes[SpanAttributes.TRACELOOP_ENTITY_OUTPUT] @@ -961,7 +961,7 @@ def test_bedrock_with_events_with_content( ) assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 16 - assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 27 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 43 logs = log_exporter.get_finished_logs() @@ -1023,7 +1023,7 @@ def test_bedrock_with_events_with_no_content( == "anthropic.claude-3-haiku-20240307-v1:0" ) assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 16 - assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 27 + assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 43 logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py index 5072548541..18564675db 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py +++ b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py @@ -79,7 +79,7 @@ def set_llm_chat_response_model_attributes(event, span): ) if usage := raw.get("usage") if "usage" in raw else raw.usage: span.set_attribute( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, usage.completion_tokens + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens ) span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, usage.prompt_tokens) span.set_attribute(SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens) diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py index e11ff11413..d8bbcad3ce 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py @@ -97,7 +97,7 @@ def multiply(a: int, b: int) -> int: ].startswith( "Thought: The current language of the user is English. I need to use a tool" ) - assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 43 + assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 479 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 522 @@ -124,7 +124,7 @@ def multiply(a: int, b: int) -> int: "Thought: I can answer without using any more tools. I'll use the user's " "language to answer.\nAnswer: 2 times 3 is 6." ) - assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 32 + assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 535 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 567 @@ -190,7 +190,7 @@ def multiply(a: int, b: int) -> int: ].startswith( "Thought: The current language of the user is English. I need to use a tool" ) - assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 43 + assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 479 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 522 @@ -202,7 +202,7 @@ def multiply(a: int, b: int) -> int: llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 32 + assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 535 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 567 @@ -357,7 +357,7 @@ def multiply(a: int, b: int) -> int: assert ( llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 43 + assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 479 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 522 @@ -368,7 +368,7 @@ def multiply(a: int, b: int) -> int: assert ( llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 32 + assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 535 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 567 @@ -451,7 +451,7 @@ def test_agent_with_query_tool(instrument_legacy, span_exporter, log_exporter): assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( "Given an input question, first create a syntactically correct sqlite" ) - assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 68 + assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 @@ -466,7 +466,7 @@ def test_agent_with_query_tool(instrument_legacy, span_exporter, log_exporter): "The city with the highest population in the city_stats table is Tokyo, " "with a population of 13,960,000." ) - assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 25 + assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 63 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 88 @@ -533,7 +533,7 @@ def test_agent_with_query_tool_with_events_with_content( assert ( llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 68 + assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 @@ -541,7 +541,7 @@ def test_agent_with_query_tool_with_events_with_content( assert ( llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 25 + assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 63 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 88 @@ -658,7 +658,7 @@ def test_agent_with_query_tool_with_events_with_no_content( assert ( llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 68 + assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 @@ -666,7 +666,7 @@ def test_agent_with_query_tool_with_events_with_no_content( assert ( llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 25 + assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 63 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 88 diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py index 0e68fe2efc..b6f1d6a59c 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py @@ -68,6 +68,6 @@ def test_rag_with_chroma(instrument_legacy, span_exporter): assert llm_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( "The author worked on writing and programming before college." ) - assert llm_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 10 + assert llm_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 10 assert llm_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 2070 assert llm_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2080 diff --git a/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py b/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py index ef36097fc1..28c4f31fa3 100644 --- a/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py +++ b/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py @@ -182,7 +182,7 @@ def _set_model_response_attributes(span, llm_request_type, response): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py b/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py index 819015252f..e64ed24336 100644 --- a/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py @@ -43,7 +43,7 @@ def test_mistralai_chat_legacy( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -81,7 +81,7 @@ def test_mistralai_chat_with_events_with_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -134,7 +134,7 @@ def test_mistralai_chat_with_events_with_no_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -195,7 +195,7 @@ def test_mistralai_streaming_chat_legacy( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -237,7 +237,7 @@ def test_mistralai_streaming_chat_with_events_with_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -294,7 +294,7 @@ def test_mistralai_streaming_chat_with_events_with_no_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -353,7 +353,7 @@ async def test_mistralai_async_chat_legacy( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -393,7 +393,7 @@ async def test_mistralai_async_chat_with_events_with_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -447,7 +447,7 @@ async def test_mistralai_async_chat_with_events_with_no_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -506,7 +506,7 @@ async def test_mistralai_async_streaming_chat_legacy( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -546,7 +546,7 @@ async def test_mistralai_async_streaming_chat_with_events_with_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") @@ -602,7 +602,7 @@ async def test_mistralai_async_streaming_chat_with_events_with_no_content( assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + mistral_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") diff --git a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py index 1d8f76f468..1b668d5306 100644 --- a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py +++ b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py @@ -98,7 +98,7 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py b/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py index ef123adce7..a12e3669e9 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py @@ -47,7 +47,7 @@ def test_ollama_chat_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -81,7 +81,7 @@ def test_ollama_chat_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -129,7 +129,7 @@ def test_ollama_chat_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -388,7 +388,7 @@ def test_ollama_streaming_chat_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -427,7 +427,7 @@ def test_ollama_streaming_chat_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -480,7 +480,7 @@ def test_ollama_streaming_chat_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -534,7 +534,7 @@ async def test_ollama_async_chat_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -570,7 +570,7 @@ async def test_ollama_async_chat_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -620,7 +620,7 @@ async def test_ollama_async_chat_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -678,7 +678,7 @@ async def test_ollama_async_streaming_chat_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -718,7 +718,7 @@ async def test_ollama_async_streaming_chat_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -772,7 +772,7 @@ async def test_ollama_async_streaming_chat_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py index 3620db4956..a980cf608a 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py @@ -38,7 +38,7 @@ def test_ollama_generation_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -68,7 +68,7 @@ def test_ollama_generation_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -110,7 +110,7 @@ def test_ollama_generation_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -162,7 +162,7 @@ def test_ollama_streaming_generation_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -196,7 +196,7 @@ def test_ollama_streaming_generation_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -244,7 +244,7 @@ def test_ollama_streaming_generation_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -294,7 +294,7 @@ async def test_ollama_async_generation_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -326,7 +326,7 @@ async def test_ollama_async_generation_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -372,7 +372,7 @@ async def test_ollama_async_generation_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -426,7 +426,7 @@ async def test_ollama_async_streaming_generation_legacy( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -462,7 +462,7 @@ async def test_ollama_async_streaming_generation_with_events_with_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() @@ -512,7 +512,7 @@ async def test_ollama_async_streaming_generation_with_events_with_no_content( assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + ollama_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py index b00b04da56..8bb2e82d16 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py +++ b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py @@ -405,7 +405,7 @@ def set_token_usage_span_attributes( if output_tokens is not None: set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) if total_tokens is not None: diff --git a/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py b/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py index 89a8700958..ddb11250d5 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py +++ b/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py @@ -60,7 +60,7 @@ def test_agent_spans(exporter, test_agent): assert span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] is not None assert ( - span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] is not None) assert span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] is not None diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py index 1583e45bdf..417f071e19 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py @@ -226,7 +226,7 @@ def _set_response_attributes(span, response): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.get("completion_tokens"), ) _set_span_attribute( @@ -257,7 +257,7 @@ def _set_span_stream_usage(span, prompt_tokens, completion_tokens): if isinstance(completion_tokens, int) and completion_tokens >= 0: _set_span_attribute( - span, SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens + span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) if isinstance(prompt_tokens, int) and prompt_tokens >= 0: diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py index ffd84aa2c1..5990b2efa8 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py @@ -223,7 +223,7 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): usage_dict = model_as_dict(run.get("usage")) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage_dict.get("completion_tokens"), ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py index f36f4998a5..3d01949f9a 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py @@ -29,7 +29,7 @@ def on_end(self): ) _set_span_attribute( self._span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, self._completion_tokens, ) self._original_handler.on_end() diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py index fc76615aa6..1ca1af43e2 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py @@ -84,7 +84,7 @@ def test_new_assistant( == user_message ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 145 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 155 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 @@ -167,7 +167,7 @@ def test_new_assistant_with_events_with_content( ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 145 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 155 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -247,7 +247,7 @@ def test_new_assistant_with_events_with_no_content( == "gpt-4-turbo-preview" ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 145 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 155 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -317,7 +317,7 @@ def test_new_assistant_with_polling( assert open_ai_span.attributes["gen_ai.prompt.2.role"] == "user" assert open_ai_span.attributes["gen_ai.prompt.2.content"] == user_message assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 374 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 86 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 @@ -385,7 +385,7 @@ def test_new_assistant_with_polling_with_events_with_content( assert open_ai_span.attributes["gen_ai.request.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes["gen_ai.response.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 374 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 86 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -459,7 +459,7 @@ def test_new_assistant_with_polling_with_events_with_no_content( assert open_ai_span.attributes["gen_ai.request.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes["gen_ai.response.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 374 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 86 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -539,7 +539,7 @@ def test_existing_assistant( assert open_ai_span.attributes["gen_ai.prompt.2.role"] == "user" assert open_ai_span.attributes["gen_ai.prompt.2.content"] == user_message assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 639 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 170 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 @@ -618,7 +618,7 @@ def test_existing_assistant_with_events_with_content( ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 639 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 170 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -713,7 +713,7 @@ def test_existing_assistant_with_events_with_no_content( ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 639 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 170 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -796,7 +796,7 @@ def on_text_delta(self, delta, snapshot): assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 790 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 225 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" for idx, message in enumerate(assistant_messages): @@ -864,7 +864,7 @@ def on_text_delta(self, delta, snapshot): ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 790 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 225 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -967,7 +967,7 @@ def on_text_delta(self, delta, snapshot): ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 790 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 225 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -1045,7 +1045,7 @@ def on_text_delta(self, delta, snapshot): ) assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 364 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 88 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" for idx, message in enumerate(assistant_messages): @@ -1113,7 +1113,7 @@ def on_text_delta(self, delta, snapshot): ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 364 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 88 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() @@ -1201,7 +1201,7 @@ def on_text_delta(self, delta, snapshot): ) assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 364 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 88 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py index faa979dadf..b69e2bdb38 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py @@ -626,7 +626,7 @@ async def test_chat_async_streaming( assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 36 assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 8 - assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) == 28 + assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 events = open_ai_span.events assert len(events) == chunk_count @@ -671,7 +671,7 @@ async def test_chat_async_streaming_with_events_with_content( assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 36 assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 8 - assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) == 28 + assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 events = open_ai_span.events assert len(events) == chunk_count @@ -734,7 +734,7 @@ async def test_chat_async_streaming_with_events_with_no_content( assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 36 assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) == 8 - assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) == 28 + assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 events = open_ai_span.events assert len(events) == chunk_count diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py index 232ac6821b..e76feddc30 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py @@ -603,7 +603,7 @@ def test_chat_streaming(instrument_legacy, span_exporter, log_exporter, openai_c # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -651,7 +651,7 @@ def test_chat_streaming_with_events_with_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -718,7 +718,7 @@ def test_chat_streaming_with_events_with_no_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -778,7 +778,7 @@ async def test_chat_async_streaming( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -827,7 +827,7 @@ async def test_chat_async_streaming_with_events_with_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -893,7 +893,7 @@ async def test_chat_async_streaming_with_events_with_no_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py index 8a3e775bea..6f45958e8f 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py @@ -381,7 +381,7 @@ def test_completion_streaming( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS @@ -438,7 +438,7 @@ def test_completion_streaming_with_events_with_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS @@ -511,7 +511,7 @@ def test_completion_streaming_with_events_with_no_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get( SpanAttributes.LLM_USAGE_PROMPT_TOKENS diff --git a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py index a462bd312e..0fe93507bd 100644 --- a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py +++ b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py @@ -99,7 +99,7 @@ def set_model_completion_attributes(span, response): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py index 53b0bf8925..49d86fd4b2 100644 --- a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py +++ b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py @@ -44,7 +44,7 @@ def set_model_input_attributes(span, kwargs, llm_model): span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") ) _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) - _set_span_attribute(span, SpanAttributes.LLM_TOP_K, kwargs.get("top_k")) + _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_K, kwargs.get("top_k")) _set_span_attribute( span, SpanAttributes.LLM_PRESENCE_PENALTY, kwargs.get("presence_penalty") ) @@ -79,7 +79,7 @@ def set_model_response_attributes(span, llm_model, token_usage): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, token_usage.candidates_token_count, ) _set_span_attribute( diff --git a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py index 16ceec2b44..23c24e9e17 100644 --- a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py +++ b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py @@ -46,7 +46,7 @@ def test_vertexai_predict(instrument_legacy, span_exporter, log_exporter): ) assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert ( vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response @@ -89,7 +89,7 @@ async def async_predict_text() -> str: ) assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert ( vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response @@ -125,7 +125,7 @@ def test_vertexai_stream(instrument_legacy, span_exporter, log_exporter): ) assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert vertexai_span.attributes[ f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) @@ -165,7 +165,7 @@ async def async_streaming_prediction() -> list: ) assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert vertexai_span.attributes[ f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) @@ -212,7 +212,7 @@ def test_vertexai_chat(instrument_legacy, span_exporter, log_exporter): ) assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert ( vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == response @@ -259,7 +259,7 @@ def test_vertexai_chat_stream(instrument_legacy, span_exporter, log_exporter): assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.8 assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.LLM_TOP_K] == 40 + assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert vertexai_span.attributes[ f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) diff --git a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py index cb37e71042..3b7cce0657 100644 --- a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py +++ b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py @@ -47,7 +47,7 @@ def test_vertexai_generate_content(instrument_legacy, span_exporter, log_exporte == response._raw_response.usage_metadata.prompt_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response._raw_response.usage_metadata.candidates_token_count ) assert ( @@ -96,7 +96,7 @@ def test_vertexai_generate_content_with_events_with_content( == response._raw_response.usage_metadata.prompt_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response._raw_response.usage_metadata.candidates_token_count ) @@ -156,7 +156,7 @@ def test_vertexai_generate_content_with_events_with_no_content( == response._raw_response.usage_metadata.prompt_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] + vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response._raw_response.usage_metadata.candidates_token_count ) diff --git a/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py b/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py index d8284c412e..e764b4329f 100644 --- a/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py +++ b/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py @@ -172,7 +172,7 @@ def set_model_input_attributes(span, instance): modelParameters.get("min_new_tokens", None), ) _set_span_attribute( - span, SpanAttributes.LLM_TOP_K, modelParameters.get("top_k", None) + span, SpanAttributes.GEN_AI_REQUEST_TOP_K, modelParameters.get("top_k", None) ) _set_span_attribute( span, @@ -212,7 +212,7 @@ def _set_model_stream_response_attributes(span, stream_response): ) _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, stream_response.get("generated_token_count"), ) total_token = stream_response.get("input_token_count") + stream_response.get( @@ -321,7 +321,7 @@ def set_model_response_attributes( if (prompt_token + completion_token) != 0: _set_span_attribute( span, - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_token, ) _set_span_attribute( diff --git a/packages/traceloop-sdk/tests/test_manual.py b/packages/traceloop-sdk/tests/test_manual.py index d3afd6f282..2f300be157 100644 --- a/packages/traceloop-sdk/tests/test_manual.py +++ b/packages/traceloop-sdk/tests/test_manual.py @@ -53,7 +53,7 @@ def test_manual_report(exporter, openai_client): ) assert open_ai_span.end_time > open_ai_span.start_time assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 15 - assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 24 + assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 24 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 39 assert ( open_ai_span.attributes[SpanAttributes.LLM_USAGE_CACHE_CREATION_INPUT_TOKENS] diff --git a/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py b/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py index c877117175..0fad8ed508 100644 --- a/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py +++ b/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py @@ -50,7 +50,7 @@ def report_usage(self, usage: LLMUsage): SpanAttributes.LLM_USAGE_PROMPT_TOKENS, usage.prompt_tokens ) self._span.set_attribute( - SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, usage.completion_tokens + SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens ) self._span.set_attribute( SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens From c44af4ca122cc15b04ae2556144c7ac375878f9f Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Tue, 19 Aug 2025 11:40:50 +0000 Subject: [PATCH 4/8] deprecating gen_ai attributes from our semconv AI --- .../instrumentation/alephalpha/__init__.py | 11 +- .../instrumentation/alephalpha/span_utils.py | 11 +- .../poetry.lock | 18 +- .../pyproject.toml | 1 - .../instrumentation/anthropic/__init__.py | 28 +-- .../instrumentation/anthropic/span_utils.py | 36 +-- .../instrumentation/anthropic/streaming.py | 18 +- .../instrumentation/anthropic/utils.py | 6 +- .../tests/test_completion.py | 4 +- .../tests/test_messages.py | 188 ++++++++-------- .../tests/utils.py | 8 +- .../instrumentation/bedrock/guardrail.py | 16 +- .../instrumentation/bedrock/span_utils.py | 146 ++++++------ .../test_bedrock_guardrails_metrics.py | 10 +- .../tests/metrics/test_bedrock_metrics.py | 9 +- .../tests/traces/test_ai21.py | 24 +- .../tests/traces/test_anthropic.py | 122 +++++----- .../tests/traces/test_cohere.py | 34 +-- .../tests/traces/test_imported_model.py | 32 +-- .../tests/traces/test_meta.py | 76 +++---- .../tests/traces/test_nova.py | 212 +++++++++--------- .../tests/traces/test_titan.py | 118 +++++----- .../instrumentation/cohere/__init__.py | 5 +- .../instrumentation/cohere/span_utils.py | 48 ++-- .../tests/test_chat.py | 22 +- .../tests/test_completion.py | 14 +- .../tests/test_rerank.py | 24 +- .../instrumentation/crewai/instrumentation.py | 25 ++- .../google_generativeai/__init__.py | 7 +- .../google_generativeai/span_utils.py | 47 ++-- .../tests/test_generate_content.py | 38 ++-- .../instrumentation/groq/__init__.py | 7 +- .../instrumentation/groq/span_utils.py | 39 ++-- .../instrumentation/groq/utils.py | 6 +- .../tests/traces/test_chat_tracing.py | 48 ++-- .../instrumentation/haystack/wrap_openai.py | 17 +- .../langchain/callback_handler.py | 32 +-- .../instrumentation/langchain/span_utils.py | 33 +-- .../tests/metrics/test_langchain_metrics.py | 15 +- .../tests/test_chains.py | 14 +- .../tests/test_llms.py | 144 ++++++------ .../tests/test_structured_output.py | 4 +- .../tests/test_tool_calls.py | 102 ++++----- .../llamaindex/custom_llm_instrumentor.py | 17 +- .../instrumentation/llamaindex/span_utils.py | 29 +-- .../tests/test_agents.py | 124 +++++----- .../tests/test_chroma_vector_store.py | 15 +- .../tests/test_query_pipeline.py | 20 +- .../instrumentation/mistralai/__init__.py | 34 +-- .../tests/test_chat.py | 130 +++++------ .../tests/test_embeddings.py | 28 +-- .../instrumentation/ollama/__init__.py | 31 +-- .../instrumentation/ollama/span_utils.py | 43 ++-- .../tests/test_chat.py | 166 +++++++------- .../tests/test_embeddings.py | 14 +- .../tests/test_generation.py | 136 +++++------ .../tests/test_ollama_metrics.py | 15 +- .../instrumentation/openai_agents/__init__.py | 62 ++--- .../tests/test_openai_agents.py | 54 ++--- .../instrumentation/openai/shared/__init__.py | 40 ++-- .../openai/shared/chat_wrappers.py | 17 +- .../openai/shared/completion_wrappers.py | 7 +- .../openai/shared/embeddings_wrappers.py | 9 +- .../openai/v1/assistant_wrappers.py | 41 ++-- .../openai/v1/event_handler_wrapper.py | 12 +- .../openai/v1/responses_wrappers.py | 73 +++--- .../tests/metrics/test_openai_metrics.py | 19 +- .../tests/traces/test_assistant.py | 194 ++++++++-------- .../tests/traces/test_azure.py | 48 ++-- .../tests/traces/test_chat.py | 108 ++++----- .../tests/traces/test_chat_parse.py | 38 ++-- .../tests/traces/test_completions.py | 36 +-- .../tests/traces/test_embeddings.py | 42 ++-- .../tests/traces/test_functions.py | 46 ++-- .../tests/traces/test_vision.py | 8 +- .../instrumentation/replicate/__init__.py | 5 +- .../instrumentation/replicate/span_utils.py | 20 +- .../instrumentation/sagemaker/span_utils.py | 5 +- .../tests/test_invocation.py | 6 +- .../instrumentation/together/__init__.py | 5 +- .../instrumentation/together/span_utils.py | 30 +-- .../transformers/span_utils.py | 17 +- .../instrumentation/vertexai/__init__.py | 7 +- .../instrumentation/vertexai/span_utils.py | 27 ++- .../tests/disabled_test_bison.py | 73 +++--- .../tests/disabled_test_gemini.py | 22 +- .../instrumentation/watsonx/__init__.py | 47 ++-- .../tests/metrics/test_watsonx_metrics.py | 13 +- .../tests/traces/test_generate.py | 20 +- .../opentelemetry/semconv_ai/__init__.py | 70 +++--- .../poetry.lock | 28 +-- .../pyproject.toml | 1 + packages/traceloop-sdk/tests/test_manual.py | 23 +- .../tests/test_privacy_no_prompts.py | 10 +- .../tests/test_prompt_management.py | 7 +- .../traceloop-sdk/tests/test_workflows.py | 11 +- .../traceloop/sdk/tracing/manual.py | 25 ++- 97 files changed, 2028 insertions(+), 1919 deletions(-) diff --git a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py index 059f1a66d3..37fd0a0159 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py +++ b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/__init__.py @@ -23,6 +23,9 @@ _SUPPRESS_INSTRUMENTATION_KEY, unwrap, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -69,7 +72,7 @@ def _handle_message_event( event: PromptEvent, span: Span, event_logger: Optional[EventLogger], kwargs ): if span.is_recording(): - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) if should_emit_events(): return emit_event(event, event_logger) @@ -86,9 +89,9 @@ def _handle_completion_event(event: CompletionEvent, span, event_logger, respons span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, input_tokens + output_tokens ) _set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens ) - _set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) + _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) if should_emit_events(): emit_event(event, event_logger) @@ -157,7 +160,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "AlephAlpha", + GenAIAttributes.GEN_AI_SYSTEM: "AlephAlpha", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) diff --git a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py index 52ab191646..858c374976 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py +++ b/packages/opentelemetry-instrumentation-alephalpha/opentelemetry/instrumentation/alephalpha/span_utils.py @@ -3,6 +3,9 @@ PromptEvent, ) from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.trace.span import Span @@ -16,10 +19,10 @@ def set_prompt_attributes(event: PromptEvent, span: Span): return if should_send_prompts(): - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", event.content[0].get("data"), ) @@ -36,9 +39,9 @@ def set_completion_attributes(event: CompletionEvent, span: Span): if should_send_prompts(): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", event.message["content"], ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) diff --git a/packages/opentelemetry-instrumentation-alephalpha/poetry.lock b/packages/opentelemetry-instrumentation-alephalpha/poetry.lock index 6743eaef96..fed1ce1eae 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/poetry.lock +++ b/packages/opentelemetry-instrumentation-alephalpha/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. [[package]] name = "aiodns" @@ -912,18 +912,6 @@ files = [ deprecated = ">=1.2.6" opentelemetry-api = "1.29.0" -[[package]] -name = "opentelemetry-semantic-conventions-ai" -version = "0.4.11" -description = "OpenTelemetry Semantic Conventions Extension for Large Language Models" -optional = false -python-versions = "<4,>=3.9" -groups = ["main"] -files = [ - {file = "opentelemetry_semantic_conventions_ai-0.4.11-py3-none-any.whl", hash = "sha256:9b07da1e66bed1746b61bb5d49d8fba9ae693625ec4ea94ddab390760505bf4b"}, - {file = "opentelemetry_semantic_conventions_ai-0.4.11.tar.gz", hash = "sha256:bc84b71c66a01a5836a28104e691c5524f4f677fc90b40a4e6fbc2ec3e250610"}, -] - [[package]] name = "packaging" version = "24.1" @@ -1659,7 +1647,7 @@ description = "HTTP library with thread-safe connection pooling, file post, and optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" groups = ["test"] -markers = "platform_python_implementation == \"PyPy\" or python_version < \"3.10\"" +markers = "platform_python_implementation == \"PyPy\" or python_version == \"3.9\"" files = [ {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, @@ -1909,4 +1897,4 @@ instruments = [] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4" -content-hash = "b65243f1ab28c5c8138c4c9ab1c9f072a424cd7542efcef4ab8e5d40bf98bd40" +content-hash = "7ffc9e3c9f7c96d9aadbf3375b5f21acda5867d6de4c78f44224fde3cfb700ba" diff --git a/packages/opentelemetry-instrumentation-alephalpha/pyproject.toml b/packages/opentelemetry-instrumentation-alephalpha/pyproject.toml index dd6f23405c..c657fa8d67 100644 --- a/packages/opentelemetry-instrumentation-alephalpha/pyproject.toml +++ b/packages/opentelemetry-instrumentation-alephalpha/pyproject.toml @@ -27,7 +27,6 @@ python = ">=3.9,<4" opentelemetry-api = "^1.28.0" opentelemetry-instrumentation = ">=0.50b0" opentelemetry-semantic-conventions = ">=0.50b0" -opentelemetry-semantic-conventions-ai = "0.4.11" [tool.poetry.group.dev.dependencies] autopep8 = "^2.2.0" diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py index 52415878fa..483f572cc3 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py @@ -127,7 +127,7 @@ async def _aset_token_usage( input_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) @@ -154,7 +154,7 @@ async def _aset_token_usage( completion_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) @@ -175,18 +175,18 @@ async def _aset_token_usage( }, ) - set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) + set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute(span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, cache_read_tokens + span, GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, cache_read_tokens ) set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, cache_creation_tokens, ) @@ -220,7 +220,7 @@ def _set_token_usage( input_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) @@ -245,7 +245,7 @@ def _set_token_usage( completion_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) @@ -266,18 +266,18 @@ def _set_token_usage( }, ) - set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) + set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute(span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, cache_read_tokens + span, GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, cache_read_tokens ) set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, cache_creation_tokens, ) @@ -397,7 +397,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Anthropic", + GenAIAttributes.GEN_AI_SYSTEM: "Anthropic", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -494,7 +494,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Anthropic", + GenAIAttributes.GEN_AI_SYSTEM: "Anthropic", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py index 68eb3e2197..1276824c4c 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py @@ -9,8 +9,8 @@ model_as_dict, should_send_prompts, ) -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import SpanAttributes @@ -73,14 +73,14 @@ async def _dump_content(message_index, content, span): async def aset_input_attributes(span, kwargs): from opentelemetry.instrumentation.anthropic import set_span_attribute - set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) + set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") ) set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) + set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -92,7 +92,7 @@ async def aset_input_attributes(span, kwargs): if should_send_prompts(): if kwargs.get("prompt") is not None: set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) elif kwargs.get("messages") is not None: @@ -101,28 +101,28 @@ async def aset_input_attributes(span, kwargs): has_system_message = True set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", await _dump_content( message_index=0, span=span, content=kwargs.get("system") ), ) set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "system", ) for i, message in enumerate(kwargs.get("messages")): prompt_index = i + (1 if has_system_message else 0) set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", await _dump_content( message_index=i, span=span, content=message.get("content") ), ) set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", message.get("role"), ) @@ -146,7 +146,7 @@ def _set_span_completions(span, response): from opentelemetry.instrumentation.anthropic import set_span_attribute index = 0 - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" set_span_attribute(span, f"{prefix}.finish_reason", response.get("stop_reason")) if response.get("role"): set_span_attribute(span, f"{prefix}.role", response.get("role")) @@ -177,7 +177,7 @@ def _set_span_completions(span, response): ) # increment the index for subsequent content blocks index += 1 - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" # set the role to the original role on the next completions set_span_attribute( span, @@ -213,15 +213,15 @@ def set_response_attributes(span, response): if not isinstance(response, dict): response = response.__dict__ - set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) - set_span_attribute(span, GEN_AI_RESPONSE_ID, response.get("id")) + set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) + set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response.get("id")) if response.get("usage"): prompt_tokens = response.get("usage").input_tokens completion_tokens = response.get("usage").output_tokens - set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) + set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute( span, @@ -245,7 +245,7 @@ def set_streaming_response_attributes(span, complete_response_events): try: for event in complete_response_events: index = event.get("index") - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" set_span_attribute( span, f"{prefix}.finish_reason", event.get("finish_reason") ) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py index fa1bdd2e9c..d8becdffb6 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py @@ -19,8 +19,8 @@ should_emit_events, ) from opentelemetry.metrics import Counter, Histogram -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import SpanAttributes from opentelemetry.trace.status import Status, StatusCode @@ -84,14 +84,14 @@ def _set_token_usage( input_tokens = prompt_tokens + cache_read_tokens + cache_creation_tokens total_tokens = input_tokens + completion_tokens - set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) + set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute(span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens) set_span_attribute( - span, SpanAttributes.GEN_AI_RESPONSE_MODEL, complete_response.get("model") + span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, complete_response.get("model") ) set_span_attribute( span, SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, cache_read_tokens @@ -107,7 +107,7 @@ def _set_token_usage( input_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) @@ -116,7 +116,7 @@ def _set_token_usage( completion_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) @@ -167,7 +167,7 @@ def build_from_streaming_response( _process_response_item(item, complete_response) metric_attributes = shared_metrics_attributes(complete_response) - set_span_attribute(span, GEN_AI_RESPONSE_ID, complete_response.get("id")) + set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, complete_response.get("id")) if duration_histogram: duration = time.time() - start_time duration_histogram.record( @@ -242,7 +242,7 @@ async def abuild_from_streaming_response( raise e _process_response_item(item, complete_response) - set_span_attribute(span, GEN_AI_RESPONSE_ID, complete_response.get("id")) + set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, complete_response.get("id")) metric_attributes = shared_metrics_attributes(complete_response) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py index 00ccf266ee..d7f119a256 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/utils.py @@ -8,7 +8,9 @@ from opentelemetry import context as context_api from opentelemetry.instrumentation.anthropic.config import Config -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) GEN_AI_SYSTEM = "gen_ai.system" GEN_AI_SYSTEM_ANTHROPIC = "anthropic" @@ -71,7 +73,7 @@ def shared_metrics_attributes(response): return { **common_attributes, GEN_AI_SYSTEM: GEN_AI_SYSTEM_ANTHROPIC, - SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), } diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py index 2a73372c46..e84836cd60 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py @@ -34,10 +34,10 @@ def test_anthropic_completion_legacy( anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == f"{HUMAN_PROMPT}\nHello world\n{AI_PROMPT}" ) - assert anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( anthropic_span.attributes.get("gen_ai.response.id") == "compl_01EjfrPvPEsRDRUKD6VoBxtK" diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py index 0b2ebf8a84..228f0e64f8 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py @@ -56,22 +56,22 @@ def test_anthropic_message_create_legacy( anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -115,10 +115,10 @@ def test_anthropic_message_create_with_events_with_content( assert all(span.name == "anthropic.chat" for span in spans) anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -180,10 +180,10 @@ def test_anthropic_message_create_with_events_with_no_content( assert all(span.name == "anthropic.chat" for span in spans) anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -235,26 +235,26 @@ def test_anthropic_multi_modal_legacy( ] anthropic_span = spans[0] assert anthropic_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps( [ {"type": "text", "text": "What do you see?"}, {"type": "image_url", "image_url": {"url": "/some/url"}}, ] ) - assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1381 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1381 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -305,10 +305,10 @@ def test_anthropic_multi_modal_with_events_with_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1381 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1381 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -366,10 +366,10 @@ def test_anthropic_multi_modal_with_events_with_no_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1381 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1381 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -430,53 +430,53 @@ def test_anthropic_image_with_history( spans = span_exporter.get_finished_spans() assert all(span.name == "anthropic.chat" for span in spans) assert ( - spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_message + spans[0].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == system_message ) - assert spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert spans[0].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + spans[0].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == "Are you capable of describing an image?" ) - assert spans[0].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" + assert spans[0].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert ( - spans[0].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + spans[0].attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response1.content[0].text ) assert ( - spans[0].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" + spans[0].attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) assert ( spans[0].attributes.get("gen_ai.response.id") == "msg_01Ctc62hUPvikvYASXZqTo9q" ) assert ( - spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_message + spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == system_message ) - assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == "Are you capable of describing an image?" ) - assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" + assert spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert ( - spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] + spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"] == response1.content[0].text ) - assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "assistant" + assert spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "assistant" assert json.loads( - spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.content"] + spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.content"] ) == [ {"type": "text", "text": "What do you see?"}, {"type": "image_url", "image_url": {"url": "/some/url"}}, ] - assert spans[1].attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.role"] == "user" + assert spans[1].attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.role"] == "user" assert ( - spans[1].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + spans[1].attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response2.content[0].text ) assert ( - spans[1].attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" + spans[1].attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) assert ( spans[1].attributes.get("gen_ai.response.id") == "msg_01EtAvxHCWn5jjdUCnG4wEAd" @@ -516,26 +516,26 @@ async def test_anthropic_async_multi_modal_legacy( ] anthropic_span = spans[0] assert anthropic_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps( [ {"type": "text", "text": "What do you see?"}, {"type": "image_url", "image_url": {"url": "/some/url"}}, ] ) - assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1311 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1311 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -587,10 +587,10 @@ async def test_anthropic_async_multi_modal_with_events_with_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1311 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1311 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -649,10 +649,10 @@ async def test_anthropic_async_multi_modal_with_events_with_no_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1311 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1311 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -705,22 +705,22 @@ def test_anthropic_message_streaming_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -771,10 +771,10 @@ def test_anthropic_message_streaming_with_events_with_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -836,10 +836,10 @@ def test_anthropic_message_streaming_with_events_with_no_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -892,22 +892,22 @@ async def test_async_anthropic_message_create_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -951,10 +951,10 @@ async def test_async_anthropic_message_create_with_events_with_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -1009,10 +1009,10 @@ async def test_async_anthropic_message_create_with_events_with_no_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -1070,22 +1070,22 @@ async def test_async_anthropic_message_streaming_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -1136,10 +1136,10 @@ async def test_async_anthropic_message_streaming_with_events_with_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -1200,10 +1200,10 @@ async def test_async_anthropic_message_streaming_with_events_with_no_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - + anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/utils.py b/packages/opentelemetry-instrumentation-anthropic/tests/utils.py index e37b1a6143..c3bab973c8 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/utils.py @@ -16,12 +16,12 @@ def verify_metrics( if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert ( - data_point.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + data_point.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == model_name ) if not ignore_zero_input_tokens: @@ -32,7 +32,7 @@ def verify_metrics( for data_point in metric.data.data_points: assert data_point.value >= 1 assert ( - data_point.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + data_point.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == model_name ) @@ -45,7 +45,7 @@ def verify_metrics( data_point.sum > 0 for data_point in metric.data.data_points ) assert all( - data_point.attributes.get(SpanAttributes.GEN_AI_RESPONSE_MODEL) + data_point.attributes.get(GenAIAttributes.GEN_AI_RESPONSE_MODEL) == model_name or data_point.attributes.get("error.type") == "TypeError" for data_point in metric.data.data_points diff --git a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py index f3ebf27e45..42ea697e22 100644 --- a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py +++ b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/guardrail.py @@ -1,5 +1,7 @@ -from opentelemetry.semconv_ai import SpanAttributes from enum import Enum +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) class Type(Enum): @@ -36,7 +38,7 @@ def handle_invoke_metrics(t: Type, guardrail, attrs, metric_params): input_latency, attributes={ **attrs, - SpanAttributes.GEN_AI_TOKEN_TYPE: t.value, + GenAIAttributes.GEN_AI_TOKEN_TYPE: t.value, }, ) if "guardrailCoverage" in guardrail["invocationMetrics"]: @@ -46,7 +48,7 @@ def handle_invoke_metrics(t: Type, guardrail, attrs, metric_params): char_guarded, attributes={ **attrs, - SpanAttributes.GEN_AI_TOKEN_TYPE: t.value, + GenAIAttributes.GEN_AI_TOKEN_TYPE: t.value, }, ) @@ -133,8 +135,8 @@ def handle_words(t: Type, guardrail, attrs, metric_params): def guardrail_converse(response, vendor, model, metric_params): attrs = { "gen_ai.vendor": vendor, - SpanAttributes.GEN_AI_RESPONSE_MODEL: model, - SpanAttributes.GEN_AI_SYSTEM: "bedrock", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model, + GenAIAttributes.GEN_AI_SYSTEM: "bedrock", } if "trace" in response and "guardrail" in response["trace"]: guardrail = response["trace"]["guardrail"] @@ -157,8 +159,8 @@ def guardrail_handling(response_body, vendor, model, metric_params): if "amazon-bedrock-guardrailAction" in response_body: attrs = { "gen_ai.vendor": vendor, - SpanAttributes.GEN_AI_RESPONSE_MODEL: model, - SpanAttributes.GEN_AI_SYSTEM: "bedrock", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model, + GenAIAttributes.GEN_AI_SYSTEM: "bedrock", } if "amazon-bedrock-trace" in response_body: bedrock_trace = response_body["amazon-bedrock-trace"] diff --git a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py index 0ce282a861..864d917455 100644 --- a/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py +++ b/packages/opentelemetry-instrumentation-bedrock/opentelemetry/instrumentation/bedrock/span_utils.py @@ -4,8 +4,8 @@ import anthropic from opentelemetry.instrumentation.bedrock.config import Config from opentelemetry.instrumentation.bedrock.utils import should_send_prompts -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import ( LLMRequestTypeValues, @@ -34,12 +34,12 @@ def set_model_message_span_attributes(model_vendor, span, request_body): for idx, message in enumerate(request_body.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.role", message.get("role"), ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", json.dumps(message.get("content")), ) elif model_vendor == "ai21": @@ -82,10 +82,10 @@ def set_model_span_attributes( response_model = response_body.get("model") response_id = response_body.get("id") - _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, provider) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response_model) - _set_span_attribute(span, GEN_AI_RESPONSE_ID, response_id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_SYSTEM, provider) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, response_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response_id) if model_vendor == "cohere": _set_cohere_span_attributes(span, request_body, response_body, metric_params) @@ -114,7 +114,7 @@ def set_model_span_attributes( def _set_prompt_span_attributes(span, request_body): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", request_body.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", request_body.get("prompt") ) @@ -122,12 +122,12 @@ def _set_cohere_span_attributes(span, request_body, response_body, metric_params _set_span_attribute( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("p")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("p")) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens") ) # based on contract at @@ -154,7 +154,7 @@ def _set_generations_span_attributes(span, response_body): for i, generation in enumerate(response_body.get("generations")): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", generation.get("text"), ) @@ -166,14 +166,14 @@ def _set_anthropic_completion_span_attributes( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( span, - SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, + GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens_to_sample"), ) @@ -208,16 +208,16 @@ def _set_anthropic_response_span_attributes(span, response_body): if response_body.get("completion") is not None: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("completion"), ) elif response_body.get("content") is not None: _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", "assistant" ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", json.dumps(response_body.get("content")), ) @@ -229,14 +229,14 @@ def _set_anthropic_messages_span_attributes( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.CHAT.value ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( span, - SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, + GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens"), ) @@ -284,13 +284,13 @@ def _set_ai21_span_attributes(span, request_body, response_body, metric_params): span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("topP") + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("topP") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("maxTokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("maxTokens") ) _record_usage_to_span( @@ -305,7 +305,7 @@ def _set_span_completions_attributes(span, response_body): for i, completion in enumerate(response_body.get("completions")): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", completion.get("data").get("text"), ) @@ -315,13 +315,13 @@ def _set_llama_span_attributes(span, request_body, response_body, metric_params) span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("top_p") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_gen_len") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_gen_len") ) _record_usage_to_span( @@ -334,28 +334,28 @@ def _set_llama_span_attributes(span, request_body, response_body, metric_params) def _set_llama_prompt_span_attributes(span, request_body): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", request_body.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", request_body.get("prompt") ) - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") def _set_llama_response_span_attributes(span, response_body): if response_body.get("generation"): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("generation"), ) else: for i, generation in enumerate(response_body.get("generations")): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role", "assistant" ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", generation + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", generation ) @@ -368,21 +368,21 @@ def _set_amazon_span_attributes( if "textGenerationConfig" in request_body: config = request_body.get("textGenerationConfig", {}) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokenCount") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokenCount") ) elif "inferenceConfig" in request_body: config = request_body.get("inferenceConfig", {}) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokens") ) total_completion_tokens = 0 @@ -419,7 +419,7 @@ def _set_amazon_input_span_attributes(span, request_body): if "inputText" in request_body: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.user", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", request_body.get("inputText"), ) else: @@ -428,24 +428,24 @@ def _set_amazon_input_span_attributes(span, request_body): for idx, prompt in enumerate(request_body["system"]): prompt_idx = idx + 1 _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", "system" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.role", "system" ) # TODO: add support for "image" _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.content", prompt.get("text"), ) for idx, prompt in enumerate(request_body["messages"]): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx + idx}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_idx + idx}.role", prompt.get("role"), ) # TODO: here we stringify the object, consider moving these to events or prompt.{i}.content.{j} _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx + idx}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_idx + idx}.content", json.dumps(prompt.get("content", ""), default=str), ) @@ -455,13 +455,13 @@ def _set_amazon_response_span_attributes(span, response_body): for i, result in enumerate(response_body.get("results")): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", result.get("outputText"), ) elif "outputText" in response_body: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("outputText"), ) elif "output" in response_body: @@ -469,7 +469,7 @@ def _set_amazon_response_span_attributes(span, response_body): for idx, msg in enumerate(msgs): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.content", msg.get("text"), ) @@ -481,13 +481,13 @@ def _set_imported_model_span_attributes( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.COMPLETION.value ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("topP") + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, request_body.get("topP") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, request_body.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, request_body.get("max_tokens") ) prompt_tokens = ( response_body.get("usage", {}).get("prompt_tokens") @@ -509,26 +509,26 @@ def _set_imported_model_span_attributes( def _set_imported_model_response_span_attributes(span, response_body): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response_body.get("generation"), ) def _set_imported_model_prompt_span_attributes(span, request_body): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", request_body.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", request_body.get("prompt") ) def _record_usage_to_span(span, prompt_tokens, completion_tokens, metric_params): _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens, ) _set_span_attribute( @@ -557,7 +557,7 @@ def _record_usage_to_span(span, prompt_tokens, completion_tokens, metric_params) prompt_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", }, ) if ( @@ -569,7 +569,7 @@ def _record_usage_to_span(span, prompt_tokens, completion_tokens, metric_params) completion_tokens, attributes={ **metric_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", }, ) @@ -579,15 +579,15 @@ def _metric_shared_attributes( ): return { "vendor": response_vendor, - SpanAttributes.GEN_AI_RESPONSE_MODEL: response_model, - SpanAttributes.GEN_AI_SYSTEM: "bedrock", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response_model, + GenAIAttributes.GEN_AI_SYSTEM: "bedrock", "stream": is_streaming, } def set_converse_model_span_attributes(span, provider, model, kwargs): - _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, provider) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_SYSTEM, provider) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, model) _set_span_attribute( span, SpanAttributes.LLM_REQUEST_TYPE, LLMRequestTypeValues.CHAT.value ) @@ -596,12 +596,12 @@ def set_converse_model_span_attributes(span, provider, model, kwargs): if "inferenceConfig" in kwargs: config = kwargs.get("inferenceConfig") - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, config.get("topP")) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, config.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, config.get("maxTokens") ) @@ -613,25 +613,25 @@ def set_converse_input_prompt_span_attributes(kwargs, span): for idx, prompt in enumerate(kwargs["system"]): prompt_idx = idx + 1 _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", "system" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.role", "system" ) # TODO: add support for "image" _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.content", prompt.get("text"), ) if "messages" in kwargs: for idx, prompt in enumerate(kwargs["messages"]): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx+idx}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_idx+idx}.role", prompt.get("role"), ) # TODO: here we stringify the object, consider moving these to events or prompt.{i}.content.{j} _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_idx+idx}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_idx+idx}.content", json.dumps(prompt.get("content", ""), default=str), ) @@ -642,12 +642,12 @@ def set_converse_response_span_attributes(response, span): if "output" in response: message = response["output"]["message"] _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", message.get("role") + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", message.get("role") ) for idx, content in enumerate(message["content"]): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.content", content.get("text"), ) @@ -655,9 +655,9 @@ def set_converse_response_span_attributes(response, span): def set_converse_streaming_response_span_attributes(response, role, span): if not should_send_prompts(): return - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", role) + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", role) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", "".join(response) + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", "".join(response) ) diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py index 8ac0e5f615..c4797b9fe5 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_guardrails_metrics.py @@ -1,7 +1,9 @@ import json import pytest -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.instrumentation.bedrock import GuardrailMeters @@ -101,7 +103,7 @@ def assert_guardrails(reader): if metric.name == GuardrailMeters.LLM_BEDROCK_GUARDRAIL_LATENCY: found_latency = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -115,14 +117,14 @@ def assert_guardrails(reader): if metric.name == GuardrailMeters.LLM_BEDROCK_GUARDRAIL_COVERAGE: found_coverage = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert data_point.value > 0 assert ( - metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] + metric.data.data_points[0].attributes[GenAIAttributes.GEN_AI_SYSTEM] == "bedrock" ) diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py index 51c0a0fb57..c8686938f7 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/metrics/test_bedrock_metrics.py @@ -1,7 +1,10 @@ import json import pytest -from opentelemetry.semconv_ai import Meters, SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv_ai import Meters @pytest.mark.vcr @@ -44,7 +47,7 @@ def test_invoke_model_metrics(test_context, brt): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -60,7 +63,7 @@ def test_invoke_model_metrics(test_context, brt): ) assert ( - metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] + metric.data.data_points[0].attributes[GenAIAttributes.GEN_AI_SYSTEM] == "bedrock" ) diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py index e6769e8be2..5d9d1c2ed9 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_ai21.py @@ -43,16 +43,16 @@ def test_ai21_j2_completion_string_content( assert all(span.name == "bedrock.completion" for span in spans) meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == len( + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == len( response_body.get("prompt").get("tokens") ) - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( response_body.get("completions")[0].get("data").get("tokens") ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] - == meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] - + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + == meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] + + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] ) # It is apparently always 1234, but for the sake of consistency, # we should not assert on it. @@ -96,16 +96,16 @@ def test_ai21_j2_completion_string_content_with_events_with_content( assert all(span.name == "bedrock.completion" for span in spans) meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == len( + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == len( response_body.get("prompt").get("tokens") ) - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( response_body.get("completions")[0].get("data").get("tokens") ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] - == meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] - + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + == meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] + + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] ) # It is apparently always 1234, but for the sake of consistency, # we should not assert on it. @@ -155,16 +155,16 @@ def test_ai21_j2_completion_string_content_with_events_with_no_content( assert all(span.name == "bedrock.completion" for span in spans) meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == len( + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == len( response_body.get("prompt").get("tokens") ) - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == len( response_body.get("completions")[0].get("data").get("tokens") ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] - == meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] - + meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + == meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] + + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] ) # It is apparently always 1234, but for the sake of consistency, # we should not assert on it. diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py index 91d6e02944..f35c181ff2 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_anthropic.py @@ -37,19 +37,19 @@ def test_anthropic_2_completion(instrument_legacy, brt, span_exporter, log_expor anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Human: Tell me a joke about opentelemetry Assistant:" ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == completion ) - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 13 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 13 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) # Bedrock does not return the response id for claude-v2:1 assert anthropic_span.attributes.get("gen_ai.response.id") is None @@ -87,11 +87,11 @@ def test_anthropic_2_completion_with_events_with_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 13 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 13 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) # Bedrock does not return the response id for claude-v2:1 assert anthropic_span.attributes.get("gen_ai.response.id") is None @@ -143,11 +143,11 @@ def test_anthropic_2_completion_with_events_with_no_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 13 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 13 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) # Bedrock does not return the response id for claude-v2:1 assert anthropic_span.attributes.get("gen_ai.response.id") is None @@ -203,23 +203,23 @@ def test_anthropic_3_completion_complex_content( anthropic_span = spans[0] assert json.loads( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "Tell me a joke about opentelemetry"}, ] assert ( json.loads( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") ) == completion ) - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -267,11 +267,11 @@ def test_anthropic_3_completion_complex_content_with_events_with_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -337,11 +337,11 @@ def test_anthropic_3_completion_complex_content_with_events_with_no_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -404,13 +404,13 @@ def test_anthropic_3_completion_streaming( anthropic_span = spans[0] assert json.loads( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "Tell me a joke about opentelemetry"}, ] assert json.loads( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") ) == [ { "type": "text", @@ -418,11 +418,11 @@ def test_anthropic_3_completion_streaming( } ] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -475,11 +475,11 @@ def test_anthropic_3_completion_streaming_with_events_with_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -546,11 +546,11 @@ def test_anthropic_3_completion_streaming_with_events_with_no_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -606,22 +606,22 @@ def test_anthropic_3_completion_string_content( anthropic_span = spans[0] assert ( - json.loads(anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) + json.loads(anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"]) == "Tell me a joke about opentelemetry" ) assert ( json.loads( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") ) == completion ) - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -667,11 +667,11 @@ def test_anthropic_3_completion_string_content_with_events_with_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -730,11 +730,11 @@ def test_anthropic_3_completion_string_content_with_events_with_no_content( anthropic_span = spans[0] - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 16 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert ( anthropic_span.attributes.get("gen_ai.response.id") @@ -784,24 +784,24 @@ def test_anthropic_cross_region(instrument_legacy, brt, span_exporter, log_expor # Assert on model name and vendor assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "claude-3-7-sonnet-20250219-v1" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" assert anthropic_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(messages[0]["content"]) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == completion ) - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 20 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 20 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) # Bedrock does not return the response id for claude-v2:1 assert anthropic_span.attributes.get("gen_ai.response.id") is None @@ -840,16 +840,16 @@ def test_anthropic_cross_region_with_events_with_content( # Assert on model name and vendor assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "claude-3-7-sonnet-20250219-v1" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 20 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 20 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) # Bedrock does not return the response id for claude-v2:1 assert anthropic_span.attributes.get("gen_ai.response.id") is None @@ -906,16 +906,16 @@ def test_anthropic_cross_region_with_events_with_no_content( # Assert on model name and vendor assert ( - anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "claude-3-7-sonnet-20250219-v1" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" - assert anthropic_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 20 + assert anthropic_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 20 assert anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) + anthropic_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) == anthropic_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) # Bedrock does not return the response id for claude-v2:1 assert anthropic_span.attributes.get("gen_ai.response.id") is None diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py index d3faf54024..23edef4877 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_cohere.py @@ -41,22 +41,22 @@ def test_cohere_completion(instrument_legacy, brt, span_exporter, log_exporter): # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] == prompt + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == prompt # Assert on response generated_text = response_body["generations"][0]["text"] assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == generated_text ) assert ( @@ -65,9 +65,9 @@ def test_cohere_completion(instrument_legacy, brt, span_exporter, log_exporter): ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 logs = log_exporter.get_finished_logs() assert ( @@ -103,11 +103,11 @@ def test_cohere_completion_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -119,9 +119,9 @@ def test_cohere_completion_with_events_with_no_content( ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -171,11 +171,11 @@ def test_cohere_completion_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "command-text-v14" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -188,9 +188,9 @@ def test_cohere_completion_with_events_with_content( ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py index 8fcc0ba202..cdee0db77f 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_imported_model.py @@ -27,20 +27,20 @@ def test_imported_model_completion(instrument_legacy, brt, span_exporter, log_ex imported_model_span = spans[0] assert ( - imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "arn:aws:sagemaker:us-east-1:767398002385:endpoint/endpoint-quick-start-idr7y" ) assert ( imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" ) - assert imported_model_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" assert imported_model_span.attributes.get("gen_ai.response.id") is None - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 2 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 2 assert ( - imported_model_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + imported_model_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == prompt ) assert data is not None @@ -69,17 +69,17 @@ def test_imported_model_completion_with_events_with_content( imported_model_span = spans[0] assert ( - imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "arn:aws:sagemaker:us-east-1:767398002385:endpoint/endpoint-quick-start-idr7y" ) assert ( imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" ) - assert imported_model_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" assert imported_model_span.attributes.get("gen_ai.response.id") is None - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 2 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 2 assert data is not None @@ -117,17 +117,17 @@ def test_imported_model_completion_with_events_with_no_content( imported_model_span = spans[0] assert ( - imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "arn:aws:sagemaker:us-east-1:767398002385:endpoint/endpoint-quick-start-idr7y" ) assert ( imported_model_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" ) - assert imported_model_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" assert imported_model_span.attributes.get("gen_ai.response.id") is None - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert imported_model_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 2 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 100 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert imported_model_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 2 assert data is not None diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py index e8965b5c62..3ec99059b1 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_meta.py @@ -39,11 +39,11 @@ def test_meta_llama2_completion_string_content( meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -86,11 +86,11 @@ def test_meta_llama2_completion_string_content_with_events_with_content( meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -143,11 +143,11 @@ def test_meta_llama2_completion_string_content_with_events_with_no_content( meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -190,20 +190,20 @@ def test_meta_llama3_completion(instrument_legacy, brt, span_exporter, log_expor meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == response_body["generation_token_count"] + response_body["prompt_token_count"] ) - assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == prompt + assert meta_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == prompt assert ( - meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + meta_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response_body["generation"] ) assert meta_span.attributes.get("gen_ai.response.id") is None @@ -234,11 +234,11 @@ def test_meta_llama3_completion_with_events_with_content( meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -283,11 +283,11 @@ def test_meta_llama3_completion_with_events_with_no_content( meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response_body["prompt_token_count"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response_body["generation_token_count"] ) assert ( @@ -339,32 +339,32 @@ def test_meta_converse(instrument_legacy, brt, span_exporter, log_exporter): meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response["usage"]["inputTokens"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response["usage"]["outputTokens"] ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == response["usage"]["totalTokens"] ) - assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert meta_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_prompt + meta_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == system_prompt ) - assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" + assert meta_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert meta_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.1.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0]["content"]) for i in range(0, len(generated_text)): assert ( - meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.role"] + meta_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role"] == "assistant" ) assert ( - meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] + meta_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) assert meta_span.attributes.get("gen_ai.response.id") is None @@ -404,11 +404,11 @@ def test_meta_converse_with_events_with_content( meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response["usage"]["inputTokens"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response["usage"]["outputTokens"] ) assert ( @@ -471,11 +471,11 @@ def test_meta_converse_with_events_with_no_content( meta_span = spans[0] assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response["usage"]["inputTokens"] ) assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response["usage"]["outputTokens"] ) assert ( @@ -550,29 +550,29 @@ def test_meta_converse_stream(instrument_legacy, brt, span_exporter, log_exporte assert all(span.name == "bedrock.converse" for span in spans) meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == inputTokens + outputTokens ) - assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert meta_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system_prompt + meta_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == system_prompt ) - assert meta_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" + assert meta_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert meta_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.1.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0]["content"]) assert ( - meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] + meta_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == response_role ) assert ( - meta_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == content + meta_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == content ) assert meta_span.attributes.get("gen_ai.response.id") is None @@ -626,9 +626,9 @@ def test_meta_converse_stream_with_events_with_content( assert all(span.name == "bedrock.converse" for span in spans) meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] @@ -706,9 +706,9 @@ def test_meta_converse_stream_with_events_with_no_content( assert all(span.name == "bedrock.converse" for span in spans) meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + assert meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens assert ( - meta_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens + meta_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( meta_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py index 66340ffdc0..5a6dcbdc4e 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_nova.py @@ -43,39 +43,39 @@ def test_nova_completion(instrument_legacy, brt, span_exporter, log_exporter): bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == system_list[0].get("text") # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.1.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(message_list[0].get("content"), default=str) # Assert on response generated_text = response_body["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -120,10 +120,10 @@ def test_nova_completion_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -132,9 +132,9 @@ def test_nova_completion_with_events_with_content( generated_text = response_body["output"]["message"]["content"] # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -199,18 +199,18 @@ def test_nova_completion_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -278,42 +278,42 @@ def test_nova_invoke_stream(instrument_legacy, brt, span_exporter, log_exporter) bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == system_list[0].get("text") # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.1.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(message_list[0].get("content"), default=str) # Assert on response completion_msg = "".join(generated_text) assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == completion_msg ) # Assert on other request parameters assert bedrock_span.attributes[ - SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS + GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS ] == inf_params.get("maxTokens") assert bedrock_span.attributes[ - SpanAttributes.GEN_AI_REQUEST_TEMPERATURE + GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE ] == inf_params.get("temperature") - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( "topP" ) # There is no response id for Amazon Titan models in the response body, @@ -371,10 +371,10 @@ def test_nova_invoke_stream_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -384,12 +384,12 @@ def test_nova_invoke_stream_with_events_with_content( # Assert on other request parameters assert bedrock_span.attributes[ - SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS + GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS ] == inf_params.get("maxTokens") assert bedrock_span.attributes[ - SpanAttributes.GEN_AI_REQUEST_TEMPERATURE + GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE ] == inf_params.get("temperature") - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( "topP" ) # There is no response id for Amazon Titan models in the response body, @@ -469,22 +469,22 @@ def test_nova_invoke_stream_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters assert bedrock_span.attributes[ - SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS + GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS ] == inf_params.get("maxTokens") assert bedrock_span.attributes[ - SpanAttributes.GEN_AI_REQUEST_TEMPERATURE + GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE ] == inf_params.get("temperature") - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == inf_params.get( "topP" ) # There is no response id for Amazon Titan models in the response body, @@ -565,37 +565,37 @@ def test_nova_converse(instrument_legacy, brt, span_exporter, log_exporter): bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system[ + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == system[ 0 ].get("text") # Assert on prompt assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.1.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response generated_text = response["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 logs = log_exporter.get_finished_logs() assert ( @@ -659,18 +659,18 @@ def test_nova_converse_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 logs = log_exporter.get_finished_logs() assert len(logs) == 3 @@ -755,18 +755,18 @@ def test_nova_converse_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 logs = log_exporter.get_finished_logs() assert len(logs) == 3 @@ -863,46 +863,46 @@ def test_nova_converse_stream(instrument_legacy, brt, span_exporter, log_exporte bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on system prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == system[ + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == system[ 0 ].get("text") # Assert on prompt assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.1.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.1.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == content ) assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == response_role ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 # Assert on usage data assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -989,25 +989,25 @@ def test_nova_converse_stream_with_events_with_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 # Assert on usage data assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -1114,25 +1114,25 @@ def test_nova_converse_stream_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 300 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.1 # Assert on usage data assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -1191,34 +1191,34 @@ def test_nova_cross_region_invoke(instrument_legacy, brt, span_exporter, log_exp bedrock_span = spans[0] # Assert on model name and vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(message_list[0].get("content"), default=str) # Assert on response generated_text = response_body["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -1262,19 +1262,19 @@ def test_nova_cross_region_invoke_with_events_with_content( bedrock_span = spans[0] # Assert on model name and vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -1329,19 +1329,19 @@ def test_nova_cross_region_invoke_with_events_with_no_content( bedrock_span = spans[0] # Assert on model name and vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "nova-lite-v1:0" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 500 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.7 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.9 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None diff --git a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py index f1c7e08d14..a8f4e0a316 100644 --- a/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py +++ b/packages/opentelemetry-instrumentation-bedrock/tests/traces/test_titan.py @@ -43,12 +43,12 @@ def test_titan_completion(instrument_legacy, brt, span_exporter, log_exporter): # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -59,21 +59,21 @@ def test_titan_completion(instrument_legacy, brt, span_exporter, log_exporter): "scale generative AI applications with base models (FMs)'." ) assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == expected_prompt ) # Assert on response generated_text = response_body["results"][0]["outputText"] assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == generated_text ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -118,20 +118,20 @@ def test_titan_completion_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -190,20 +190,20 @@ def test_titan_completion_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -266,12 +266,12 @@ def test_titan_invoke_stream(instrument_legacy, brt, span_exporter, log_exporter # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" @@ -282,21 +282,21 @@ def test_titan_invoke_stream(instrument_legacy, brt, span_exporter, log_exporter "scale generative AI applications with base models (FMs)'." ) assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == expected_prompt ) # Assert on response completion_text = "".join(generated_text) assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == completion_text ) # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -351,20 +351,20 @@ def test_titan_invoke_stream_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -436,20 +436,20 @@ def test_titan_invoke_stream_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" # Assert on other request parameters - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 200 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.5 # There is no response id for Amazon Titan models in the response body, # only request id in the response. assert bedrock_span.attributes.get("gen_ai.response.id") is None @@ -516,27 +516,27 @@ def test_titan_converse(instrument_legacy, brt, span_exporter, log_exporter): # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response generated_text = response["output"]["message"]["content"] for i in range(0, len(generated_text)): assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{i}.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content"] == generated_text[i]["text"] ) @@ -594,12 +594,12 @@ def test_titan_converse_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" @@ -671,12 +671,12 @@ def test_titan_converse_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" @@ -766,38 +766,38 @@ def test_titan_converse_stream(instrument_legacy, brt, span_exporter, log_export # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on prompt - assert bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert bedrock_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" ] == json.dumps(messages[0].get("content"), default=str) # Assert on response assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == content ) assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == response_role ) # Assert on usage data assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -878,22 +878,22 @@ def test_titan_converse_stream_with_events_with_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on usage data assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( @@ -986,22 +986,22 @@ def test_titan_converse_stream_with_events_with_no_content( # Assert on model name assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "titan-text-express-v1" ) # Assert on vendor - assert bedrock_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" # Assert on request type assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" # Assert on usage data assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == inputTokens ) assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == outputTokens ) assert ( diff --git a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py index 8bede4d48f..c218ee3adc 100644 --- a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py +++ b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/__init__.py @@ -22,6 +22,9 @@ _SUPPRESS_INSTRUMENTATION_KEY, unwrap, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -114,7 +117,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Cohere", + GenAIAttributes.GEN_AI_SYSTEM: "Cohere", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) as span: diff --git a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py index 3f2541c2e2..36670ccc7d 100644 --- a/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py +++ b/packages/opentelemetry-instrumentation-cohere/opentelemetry/instrumentation/cohere/span_utils.py @@ -2,8 +2,8 @@ dont_throw, should_send_prompts, ) -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import ( LLMRequestTypeValues, @@ -26,32 +26,32 @@ def set_input_attributes(span, llm_request_type, kwargs): if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.COMPLETION: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("prompt") ) elif llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("message") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("message") ) elif llm_request_type == LLMRequestTypeValues.RERANK: for index, document in enumerate(kwargs.get("documents")): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", "system" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.role", "system" ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", document + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.content", document ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{len(kwargs.get('documents'))}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{len(kwargs.get('documents'))}.role", "user", ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{len(kwargs.get('documents'))}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{len(kwargs.get('documents'))}.content", kwargs.get("query"), ) @@ -75,14 +75,14 @@ def set_span_request_attributes(span, kwargs): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) _set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -93,9 +93,9 @@ def set_span_request_attributes(span, kwargs): def _set_span_chat_response(span, response): index = 0 - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", response.text) - _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.response_id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response.response_id) # Cohere v4 if hasattr(response, "token_count"): @@ -106,12 +106,12 @@ def _set_span_chat_response(span, response): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, response.token_count.get("response_tokens"), ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, response.token_count.get("prompt_tokens"), ) @@ -127,33 +127,33 @@ def _set_span_chat_response(span, response): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens, ) def _set_span_generations_response(span, response): - _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response.id) if hasattr(response, "generations"): generations = response.generations # Cohere v5 else: generations = response # Cohere v4 for index, generation in enumerate(generations): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", generation.text) _set_span_attribute(span, f"gen_ai.response.{index}.id", generation.id) def _set_span_rerank_response(span, response): - _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response.id) for idx, doc in enumerate(response.results): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}" _set_span_attribute(span, f"{prefix}.role", "assistant") content = f"Doc {doc.index}, Score: {doc.relevance_score}" if doc.document: diff --git a/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py b/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py index 0592b03205..4c5280c6e3 100644 --- a/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-cohere/tests/test_chat.py @@ -18,23 +18,23 @@ def test_cohere_chat_legacy( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.chat" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "chat" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "command" assert ( - cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + cohere_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke, pirate style" ) assert ( - cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + cohere_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == res.text ) - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 58 + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 58 assert cohere_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == cohere_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + cohere_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + cohere_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( cohere_span.attributes.get("gen_ai.response.id") == "440f51f4-3e47-44b6-a5d7-5ba33edcfc58" @@ -56,9 +56,9 @@ def test_cohere_chat_with_events_with_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.chat" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "chat" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -85,9 +85,9 @@ def test_cohere_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.chat" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "chat" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py b/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py index d8731593e1..ca6115a837 100644 --- a/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py +++ b/packages/opentelemetry-instrumentation-cohere/tests/test_completion.py @@ -18,11 +18,11 @@ def test_cohere_completion_legacy( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.completion" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "completion" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "command" assert ( - cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + cohere_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == res.generations[0].text ) assert ( @@ -50,9 +50,9 @@ def test_cohere_completion_with_events_with_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.completion" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "completion" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -78,9 +78,9 @@ def test_cohere_completion_with_events_with_no_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.completion" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "completion" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) == "command" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "command" logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py b/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py index 61f3a7b0f4..88ff42b39a 100644 --- a/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py +++ b/packages/opentelemetry-instrumentation-cohere/tests/test_rerank.py @@ -38,43 +38,43 @@ def test_cohere_rerank_legacy( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.rerank" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "rerank" assert ( - cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) + cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "rerank-multilingual-v2.0" ) assert ( cohere_span.attributes.get( - f"{SpanAttributes.GEN_AI_PROMPT}.{len(documents)}.role" + f"{GenAIAttributes.GEN_AI_PROMPT}.{len(documents)}.role" ) == "user" ) assert ( cohere_span.attributes.get( - f"{SpanAttributes.GEN_AI_PROMPT}.{len(documents)}.content" + f"{GenAIAttributes.GEN_AI_PROMPT}.{len(documents)}.content" ) == query ) for i, doc in enumerate(documents): assert ( - cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role") + cohere_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role") == "system" ) assert ( - cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content") + cohere_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content") == doc ) for idx, result in enumerate(response.results): assert ( - cohere_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role") + cohere_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.role") == "assistant" ) assert ( cohere_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.content" ) == f"Doc {result.index}, Score: {result.relevance_score}" ) @@ -118,10 +118,10 @@ def test_cohere_rerank_with_events_with_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.rerank" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "rerank" assert ( - cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) + cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "rerank-multilingual-v2.0" ) @@ -182,10 +182,10 @@ def test_cohere_rerank_with_events_with_no_content( spans = span_exporter.get_finished_spans() cohere_span = spans[0] assert cohere_span.name == "cohere.rerank" - assert cohere_span.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Cohere" + assert cohere_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Cohere" assert cohere_span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) == "rerank" assert ( - cohere_span.attributes.get(SpanAttributes.GEN_AI_REQUEST_MODEL) + cohere_span.attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL) == "rerank-multilingual-v2.0" ) diff --git a/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py b/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py index b483b03e40..8027a79a55 100644 --- a/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py +++ b/packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py @@ -9,6 +9,9 @@ from opentelemetry.instrumentation.utils import unwrap from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.crewai.version import __version__ +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues, Meters from .crewai_span_attributes import CrewAISpanAttributes, set_span_attribute @@ -71,7 +74,7 @@ def wrap_kickoff(tracer: Tracer, duration_histogram: Histogram, token_histogram: "crewai.workflow", kind=SpanKind.INTERNAL, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "crewai", + GenAIAttributes.GEN_AI_SYSTEM: "crewai", } ) as span: try: @@ -108,22 +111,22 @@ def wrap_agent_execute_task(tracer, duration_histogram, token_histogram, wrapped token_histogram.record( instance._token_process.get_summary().prompt_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "crewai", - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", - SpanAttributes.GEN_AI_RESPONSE_MODEL: str(instance.llm.model), + GenAIAttributes.GEN_AI_SYSTEM: "crewai", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: str(instance.llm.model), } ) token_histogram.record( instance._token_process.get_summary().completion_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "crewai", - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", - SpanAttributes.GEN_AI_RESPONSE_MODEL: str(instance.llm.model), + GenAIAttributes.GEN_AI_SYSTEM: "crewai", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: str(instance.llm.model), }, ) - set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, str(instance.llm.model)) - set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, str(instance.llm.model)) + set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, str(instance.llm.model)) + set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, str(instance.llm.model)) span.set_status(Status(StatusCode.OK)) return result except Exception as ex: @@ -172,8 +175,8 @@ def wrap_llm_call(tracer, duration_histogram, token_histogram, wrapped, instance duration_histogram.record( duration, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "crewai", - SpanAttributes.GEN_AI_RESPONSE_MODEL: str(instance.model) + GenAIAttributes.GEN_AI_SYSTEM: "crewai", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: str(instance.model) }, ) diff --git a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py index c2b03fa5d6..31e043f5e0 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/__init__.py @@ -26,6 +26,9 @@ from opentelemetry.instrumentation.google_generativeai.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY, unwrap +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -194,7 +197,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Google", + GenAIAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -252,7 +255,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Google", + GenAIAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py index 4873c39285..10ef54924d 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/opentelemetry/instrumentation/google_generativeai/span_utils.py @@ -2,6 +2,9 @@ dont_throw, should_send_prompts, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SpanAttributes, ) @@ -28,12 +31,12 @@ def set_input_attributes(span, args, kwargs, llm_model): if isinstance(contents, str): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", contents, ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user", ) elif isinstance(contents, list): @@ -43,12 +46,12 @@ def set_input_attributes(span, args, kwargs, llm_model): if hasattr(part, "text"): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", part.text, ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", getattr(content, "role", "user"), ) elif args and len(args) > 0: @@ -62,33 +65,33 @@ def set_input_attributes(span, args, kwargs, llm_model): if prompt: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", prompt, ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user", ) elif "prompt" in kwargs: _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs["prompt"] + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", kwargs["prompt"] ) - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") def set_model_request_attributes(span, kwargs, llm_model): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, llm_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, llm_model) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") ) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_K, kwargs.get("top_k")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_K, kwargs.get("top_k")) _set_span_attribute( span, SpanAttributes.LLM_PRESENCE_PENALTY, kwargs.get("presence_penalty") ) @@ -104,28 +107,28 @@ def set_response_attributes(span, response, llm_model): if hasattr(response, "usage_metadata"): if isinstance(response.text, list): for index, item in enumerate(response): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", item.text) _set_span_attribute(span, f"{prefix}.role", "assistant") elif isinstance(response.text, str): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response.text + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response.text ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) else: if isinstance(response, list): for index, item in enumerate(response): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", item) _set_span_attribute(span, f"{prefix}.role", "assistant") elif isinstance(response, str): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) @@ -133,7 +136,7 @@ def set_model_response_attributes(span, response, llm_model): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, llm_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, llm_model) if hasattr(response, "usage_metadata"): _set_span_attribute( @@ -143,12 +146,12 @@ def set_model_response_attributes(span, response, llm_model): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, response.usage_metadata.candidates_token_count, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, response.usage_metadata.prompt_token_count, ) diff --git a/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py b/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py index fd68ba9da5..0247229cd4 100644 --- a/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py +++ b/packages/opentelemetry-instrumentation-google-generativeai/tests/test_generate_content.py @@ -24,32 +24,32 @@ def test_gemini_generate_content_legacy( # gemini_span = spans[0] # assert ( - # gemini_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + # gemini_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] # == "The opposite of hot is\n" # ) - # assert gemini_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + # assert gemini_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" # assert ( - # gemini_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + # gemini_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") # == "cold\n" # ) # assert ( - # gemini_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.role") + # gemini_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") # == "assistant" # ) - # assert gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 5 + # assert gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 5 # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - # + gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + # gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + # + gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] # == gemini_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] # ) # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + # gemini_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] # == "models/gemini-1.5-flash" # ) # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + # gemini_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] # == "models/gemini-1.5-flash" # ) @@ -75,19 +75,19 @@ def test_gemini_generate_content_with_events_with_content( # gemini_span = spans[0] - # assert gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 5 + # assert gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 5 # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - # + gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + # gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + # + gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] # == gemini_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] # ) # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + # gemini_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] # == "models/gemini-1.5-flash" # ) # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + # gemini_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] # == "models/gemini-1.5-flash" # ) @@ -123,19 +123,19 @@ def test_gemini_generate_content_with_events_with_no_content( # gemini_span = spans[0] - # assert gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 5 + # assert gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 5 # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] - # + gemini_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + # gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + # + gemini_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] # == gemini_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] # ) # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + # gemini_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] # == "models/gemini-1.5-flash" # ) # assert ( - # gemini_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + # gemini_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] # == "models/gemini-1.5-flash" # ) diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py index ab43a1d9b9..20e1be2017 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py @@ -30,6 +30,9 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY, unwrap from opentelemetry.metrics import Counter, Histogram, Meter, get_meter +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -242,7 +245,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Groq", + GenAIAttributes.GEN_AI_SYSTEM: "Groq", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -324,7 +327,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Groq", + GenAIAttributes.GEN_AI_SYSTEM: "Groq", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py index 98efba3289..25b7d6961f 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/span_utils.py @@ -9,6 +9,9 @@ from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( GEN_AI_RESPONSE_ID, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SpanAttributes, ) @@ -24,18 +27,18 @@ def set_input_attributes(span, kwargs): if should_send_prompts(): if kwargs.get("prompt") is not None: set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) elif kwargs.get("messages") is not None: for i, message in enumerate(kwargs.get("messages")): set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", _dump_content(message.get("content")), ) set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", message.get("role") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", message.get("role") ) @@ -44,14 +47,14 @@ def set_model_input_attributes(span, kwargs): if not span.is_recording(): return - set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) + set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens_to_sample") ) set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) + set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -70,7 +73,7 @@ def set_streaming_response_attributes( if not span.is_recording() or not should_send_prompts(): return - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.0" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.0" set_span_attribute(span, f"{prefix}.role", "assistant") set_span_attribute(span, f"{prefix}.content", accumulated_content) if finish_reason: @@ -83,10 +86,10 @@ def set_model_streaming_response_attributes(span, usage): if usage: set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens ) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens + span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens ) set_span_attribute( span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens @@ -98,7 +101,7 @@ def set_model_response_attributes(span, response, token_histogram): if not span.is_recording(): return response = model_as_dict(response) - set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) + set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) set_span_attribute(span, GEN_AI_RESPONSE_ID, response.get("id")) usage = response.get("usage") or {} @@ -109,9 +112,9 @@ def set_model_response_attributes(span, response, token_histogram): span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.get("total_tokens") ) set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) - set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) + set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) if ( isinstance(prompt_tokens, int) @@ -121,8 +124,8 @@ def set_model_response_attributes(span, response, token_histogram): token_histogram.record( prompt_tokens, attributes={ - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", - SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -134,8 +137,8 @@ def set_model_response_attributes(span, response, token_histogram): token_histogram.record( completion_tokens, attributes={ - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", - SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -154,7 +157,7 @@ def _set_completions(span, choices): for choice in choices: index = choice.get("index") - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" set_span_attribute(span, f"{prefix}.finish_reason", choice.get("finish_reason")) if choice.get("content_filter_results"): diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py index 89b767f29a..f7bf7003f4 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/utils.py @@ -5,7 +5,9 @@ from opentelemetry import context as context_api from opentelemetry.instrumentation.groq.config import Config -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) GEN_AI_SYSTEM = "gen_ai.system" GEN_AI_SYSTEM_GROQ = "groq" @@ -60,7 +62,7 @@ def shared_metrics_attributes(response): return { **common_attributes, GEN_AI_SYSTEM: GEN_AI_SYSTEM_GROQ, - SpanAttributes.GEN_AI_RESPONSE_MODEL: response_dict.get("model"), + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response_dict.get("model"), } diff --git a/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py b/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py index 340cb77210..f7e7dcc232 100644 --- a/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py +++ b/packages/opentelemetry-instrumentation-groq/tests/traces/test_chat_tracing.py @@ -23,13 +23,13 @@ def test_chat_legacy(instrument_legacy, groq_client, span_exporter, log_exporter ] groq_span = spans[0] assert ( - groq_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + groq_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert groq_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -58,8 +58,8 @@ def test_chat_with_events_with_content( ] groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -105,8 +105,8 @@ def test_chat_with_events_with_no_content( ] groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -146,13 +146,13 @@ async def test_async_chat_legacy( ] groq_span = spans[0] assert ( - groq_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + groq_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert groq_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -182,8 +182,8 @@ async def test_async_chat_with_events_with_content( ] groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -231,8 +231,8 @@ async def test_async_chat_with_events_with_no_content( ] groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 assert ( groq_span.attributes.get("gen_ai.response.id") @@ -277,16 +277,16 @@ def test_chat_streaming_legacy( ] groq_span = spans[0] assert ( - groq_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + groq_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - groq_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + groq_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == content ) assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 18 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 18 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 91 logs = log_exporter.get_finished_logs() @@ -317,8 +317,8 @@ def test_chat_streaming_with_events_with_content( ] groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 18 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 18 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 91 logs = log_exporter.get_finished_logs() @@ -367,8 +367,8 @@ def test_chat_streaming_with_events_with_no_content( ] groq_span = spans[0] assert groq_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 18 - assert groq_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 18 + assert groq_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 73 assert groq_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 91 logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py b/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py index 6c4ef17bad..151781ea54 100644 --- a/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py +++ b/packages/opentelemetry-instrumentation-haystack/opentelemetry/instrumentation/haystack/wrap_openai.py @@ -5,6 +5,9 @@ from opentelemetry.trace.status import Status, StatusCode from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes, LLMRequestTypeValues from opentelemetry.instrumentation.haystack.utils import ( dont_throw, @@ -20,12 +23,12 @@ def _set_input_attributes(span, llm_request_type, kwargs): if llm_request_type == LLMRequestTypeValues.COMPLETION: set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) elif llm_request_type == LLMRequestTypeValues.CHAT: set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.user", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", [message.content for message in kwargs.get("messages")], ) @@ -33,17 +36,17 @@ def _set_input_attributes(span, llm_request_type, kwargs): generation_kwargs = kwargs["generation_kwargs"] if "model" in generation_kwargs: set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MODEL, generation_kwargs["model"] + span, GenAIAttributes.GEN_AI_REQUEST_MODEL, generation_kwargs["model"] ) if "temperature" in generation_kwargs: set_span_attribute( span, - SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, + GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, generation_kwargs["temperature"], ) if "top_p" in generation_kwargs: set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, generation_kwargs["top_p"] + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, generation_kwargs["top_p"] ) if "frequency_penalty" in generation_kwargs: set_span_attribute( @@ -66,7 +69,7 @@ def _set_span_completions(span, llm_request_type, choices): return for index, message in enumerate(choices): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" if llm_request_type == LLMRequestTypeValues.CHAT: if message is not None: @@ -104,7 +107,7 @@ def wrap(tracer, to_wrap, wrapped, instance, args, kwargs): ), kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "OpenAI", + GenAIAttributes.GEN_AI_SYSTEM: "OpenAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) as span: diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py index 09228ef24b..791fec65a2 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py @@ -52,8 +52,8 @@ ) from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.metrics import Histogram -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, @@ -297,7 +297,7 @@ def _create_llm_span( vendor = detect_vendor_from_class(_extract_class_name_from_serialized(serialized)) - _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, vendor) + _set_span_attribute(span, GenAIAttributes.GEN_AI_SYSTEM, vendor) _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TYPE, request_type.value) return span @@ -464,15 +464,15 @@ def on_llm_end( "model_name" ) or response.llm_output.get("model_id") if model_name is not None: - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, model_name) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, model_name) if self.spans[run_id].request_model is None: _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MODEL, model_name + span, GenAIAttributes.GEN_AI_REQUEST_MODEL, model_name ) id = response.llm_output.get("id") if id is not None and id != "": - _set_span_attribute(span, GEN_AI_RESPONSE_ID, id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, id) if model_name is None: model_name = extract_model_name_from_response_metadata(response) token_usage = (response.llm_output or {}).get("token_usage") or ( @@ -494,10 +494,10 @@ def on_llm_end( ) _set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens + span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens ) _set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) _set_span_attribute( span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, total_tokens @@ -509,9 +509,9 @@ def on_llm_end( self.token_histogram.record( prompt_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: vendor, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", + GenAIAttributes.GEN_AI_SYSTEM: vendor, + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", }, ) @@ -519,9 +519,9 @@ def on_llm_end( self.token_histogram.record( completion_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: vendor, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", + GenAIAttributes.GEN_AI_SYSTEM: vendor, + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", }, ) set_chat_response_usage(span, response, self.token_histogram, token_usage is None, model_name) @@ -537,8 +537,8 @@ def on_llm_end( self.duration_histogram.record( duration, attributes={ - SpanAttributes.GEN_AI_SYSTEM: vendor, - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", + GenAIAttributes.GEN_AI_SYSTEM: vendor, + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_name or "unknown", }, ) diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py index 005c190d23..df8bcbc18e 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py @@ -15,6 +15,9 @@ CallbackFilteredJSONEncoder, should_send_prompts, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.metrics import Histogram from opentelemetry.semconv_ai import ( SpanAttributes, @@ -70,9 +73,9 @@ def set_request_params(span, kwargs, span_holder: SpanHolder): else: model = "unknown" - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, model) # response is not available for LLM requests (as opposed to chat) - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, model) if "invocation_params" in kwargs: params = ( @@ -83,13 +86,13 @@ def set_request_params(span, kwargs, span_holder: SpanHolder): _set_span_attribute( span, - SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, + GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, params.get("max_tokens") or params.get("max_new_tokens"), ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, params.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, params.get("temperature") ) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, params.get("top_p")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, params.get("top_p")) tools = kwargs.get("invocation_params", {}).get("tools", []) for i, tool in enumerate(tools): @@ -124,12 +127,12 @@ def set_llm_request( for i, msg in enumerate(prompts): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", "user", ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", msg, ) @@ -162,7 +165,7 @@ def set_chat_request( for msg in message: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", _message_type_to_role(msg.type), ) tool_calls = ( @@ -173,7 +176,7 @@ def set_chat_request( if tool_calls: _set_chat_tool_calls( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}", tool_calls + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{i}", tool_calls ) else: @@ -184,14 +187,14 @@ def set_chat_request( ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", content, ) if msg.type == "tool" and hasattr(msg, "tool_call_id"): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.tool_call_id", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.tool_call_id", msg.tool_call_id, ) @@ -205,7 +208,7 @@ def set_chat_response(span: Span, response: LLMResult) -> None: i = 0 for generations in response.generations: for generation in generations: - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{i}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}" if hasattr(generation, "text") and generation.text != "": _set_span_attribute( span, @@ -317,12 +320,12 @@ def set_chat_response_usage( ): _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( @@ -332,7 +335,7 @@ def set_chat_response_usage( ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, cache_read_tokens, ) if record_token_usage: diff --git a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py index cf0813c5c1..8ba2f9aeea 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py @@ -3,6 +3,9 @@ from langchain.chains import LLMChain from langchain.prompts import PromptTemplate from langchain_openai import ChatOpenAI +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import Meters, SpanAttributes @@ -37,13 +40,13 @@ def test_llm_chain_metrics(instrument_legacy, reader, chain): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert data_point.sum > 0 assert ( - data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] + data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" ) @@ -57,7 +60,7 @@ def test_llm_chain_metrics(instrument_legacy, reader, chain): ) for data_point in metric.data.data_points: assert ( - data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] + data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" ) @@ -89,13 +92,13 @@ def test_llm_chain_streaming_metrics(instrument_legacy, reader, llm): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] assert data_point.sum > 0 assert ( - data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] + data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" ) @@ -109,7 +112,7 @@ def test_llm_chain_streaming_metrics(instrument_legacy, reader, llm): ) for data_point in metric.data.data_points: assert ( - data_point.attributes[SpanAttributes.GEN_AI_SYSTEM] + data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" ) diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py b/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py index f896d0467d..a68ce635fe 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_chains.py @@ -123,14 +123,14 @@ def test_sequential_chain(instrument_legacy, span_exporter, log_exporter): openai_span = next(span for span in spans if span.name == "OpenAI.completion") assert ( - openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-instruct" ) assert ( - (openai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL]) + (openai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL]) == "gpt-3.5-turbo-instruct" ) - assert openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + assert openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] logs = log_exporter.get_finished_logs() assert ( @@ -213,11 +213,11 @@ def test_sequential_chain_with_events_with_content( openai_span = next(span for span in spans if span.name == "OpenAI.completion") assert ( - openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-instruct" ) assert ( - (openai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL]) + (openai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL]) == "gpt-3.5-turbo-instruct" ) @@ -334,11 +334,11 @@ def test_sequential_chain_with_events_with_no_content( openai_span = next(span for span in spans if span.name == "OpenAI.completion") assert ( - openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-instruct" ) assert ( - (openai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL]) + (openai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL]) == "gpt-3.5-turbo-instruct" ) diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py index 514d1dcff4..ae579d399c 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py @@ -142,14 +142,14 @@ def test_custom_llm(instrument_legacy, span_exporter, log_exporter): ) assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" - assert hugging_face_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "unknown" + assert hugging_face_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "unknown" assert hugging_face_span.attributes[SpanAttributes.LLM_SYSTEM] == "HuggingFace" assert ( - hugging_face_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + hugging_face_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "System: You are a helpful assistant\nHuman: tell me a short joke" ) assert ( - hugging_face_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + hugging_face_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -186,7 +186,7 @@ def test_custom_llm_with_events_with_content( ) assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" - assert hugging_face_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "unknown" + assert hugging_face_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "unknown" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -236,7 +236,7 @@ def test_custom_llm_with_events_with_no_content( ) assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" - assert hugging_face_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "unknown" + assert hugging_face_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "unknown" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -276,29 +276,29 @@ def test_openai(instrument_legacy, span_exporter, log_exporter): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" + assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" assert openai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" assert ( - (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) + (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" ) - assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" - assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) == prompt - assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" + assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "system" + assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"]) == prompt + assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( - openai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + openai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response.content ) assert ( - (openai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"]) + (openai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"]) == "assistant" ) - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1497 - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1497 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2534 assert ( - openai_span.attributes[SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 + openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 ) logs = log_exporter.get_finished_logs() @@ -332,13 +332,13 @@ def test_openai_with_events_with_content( openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" + assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1497 - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1497 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2534 assert ( - openai_span.attributes[SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 + openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 ) logs = log_exporter.get_finished_logs() @@ -386,13 +386,13 @@ def test_openai_with_events_with_no_content( openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" + assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1497 - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 1497 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 1037 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2534 assert ( - openai_span.attributes[SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 + openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 1408 ) logs = log_exporter.get_finished_logs() @@ -446,17 +446,17 @@ class Joke(BaseModel): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) + (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"]) == "You are helpful assistant" ) - assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" + assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "system" assert ( - (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) + (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"]) == "tell me a short joke" ) - assert (openai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" + assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( openai_span.attributes[f"{SpanAttributes.LLM_REQUEST_FUNCTIONS}.0.name"] == "Joke" @@ -483,19 +483,19 @@ class Joke(BaseModel): "required": ["setup", "punchline"], } assert ( - openai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + openai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "Joke" ) assert ( json.loads( openai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == response ) - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 76 - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 76 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 111 logs = log_exporter.get_finished_logs() @@ -539,10 +539,10 @@ class Joke(BaseModel): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 76 - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 76 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 111 logs = log_exporter.get_finished_logs() @@ -612,10 +612,10 @@ class Joke(BaseModel): openai_span = next(span for span in spans if span.name == "ChatOpenAI.chat") assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 76 - assert openai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 76 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 35 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 111 logs = log_exporter.get_finished_logs() @@ -661,31 +661,31 @@ def test_anthropic(instrument_legacy, span_exporter, log_exporter): ) assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" - assert anthropic_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Anthropic" - assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "Anthropic" + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 assert ( - (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) + (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" ) assert ( - (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" + (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "system" ) assert ( - (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) + (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"]) == "tell me a short joke" ) - assert (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( - anthropic_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response.content ) assert ( - (anthropic_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"]) + (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"]) == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 19 - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 19 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 41 assert ( anthropic_span.attributes["gen_ai.response.id"] @@ -751,11 +751,11 @@ def test_anthropic_with_events_with_content( anthropic_span = next(span for span in spans if span.name == "ChatAnthropic.chat") assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" - assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 19 - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 19 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 41 assert ( anthropic_span.attributes["gen_ai.response.id"] @@ -807,11 +807,11 @@ def test_anthropic_with_events_with_no_content( anthropic_span = next(span for span in spans if span.name == "ChatAnthropic.chat") assert anthropic_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" - assert anthropic_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "claude-2.1" + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5 - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 19 - assert anthropic_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 19 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 22 assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 41 assert ( anthropic_span.attributes["gen_ai.response.id"] @@ -870,30 +870,30 @@ def test_bedrock(instrument_legacy, span_exporter, log_exporter): assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-haiku-20240307-v1:0" ) assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" assert ( - (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"]) + (bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" ) - assert (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"]) == "system" + assert (bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "system" assert ( - (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"]) + (bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"]) == "tell me a short joke" ) - assert (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"]) == "user" + assert (bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( - bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response.content ) assert ( - (bedrock_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"]) + (bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"]) == "assistant" ) - assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 16 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 16 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 43 output = json.loads( workflow_span.attributes[SpanAttributes.TRACELOOP_ENTITY_OUTPUT] @@ -960,12 +960,12 @@ def test_bedrock_with_events_with_content( assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-haiku-20240307-v1:0" ) - assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 16 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 16 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 43 logs = log_exporter.get_finished_logs() @@ -1023,11 +1023,11 @@ def test_bedrock_with_events_with_no_content( assert bedrock_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - bedrock_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-haiku-20240307-v1:0" ) - assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 16 - assert bedrock_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 16 + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 27 assert bedrock_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 43 logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py b/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py index 255f756b21..c5ffe8521a 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_structured_output.py @@ -36,9 +36,9 @@ def test_structured_output(instrument_legacy, span_exporter, log_exporter): chat_span = next(span for span in spans if span.name == "ChatOpenAI.chat") - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == query_text + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == query_text assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == result.model_dump_json() ) diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py index 3a0fb74295..c6a069f94c 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py @@ -56,14 +56,14 @@ def test_tool_calls(instrument_legacy, span_exporter, log_exporter): "type": "object", } - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == query_text + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == query_text assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "food_analysis" ) arguments = chat_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] assert json.loads(arguments) == json.loads( result.model_dump() @@ -211,55 +211,55 @@ def get_weather(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == messages[1].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "user" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_calls.0.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.tool_calls.0.name"] == messages[2].tool_calls[0]["name"] ) assert ( json.loads( chat_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_PROMPT}.2.tool_calls.0.arguments" ] ) == messages[2].tool_calls[0]["args"] ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_calls.0.id"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.tool_calls.0.id"] == messages[2].tool_calls[0]["id"] ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "assistant" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "assistant" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.content"] == messages[3].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.role"] == "tool" - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.tool_call_id"] == messages[3].tool_call_id + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.role"] == "tool" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.tool_call_id"] == messages[3].tool_call_id assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.4.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.4.content"] == messages[4].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.4.role"] == "user" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.4.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_weather" ) arguments = chat_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] result_arguments = result.model_dump()["additional_kwargs"]["tool_calls"][0][ "function" @@ -494,30 +494,30 @@ def get_news(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) # Test that we write both the content and the tool calls assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == result.content[0]["text"] ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] == "toolu_016q9vtSd8CY2vnZSpEp1j4o" ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_weather" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == {"location": "San Francisco"} @@ -705,55 +705,55 @@ def get_news(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_calls.0.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_calls.0.name"] == messages[1].tool_calls[0]["name"] ) assert ( json.loads( chat_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_calls.0.arguments" ] ) == messages[1].tool_calls[0]["args"] ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_calls.0.id"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_calls.0.id"] == messages[1].tool_calls[0]["id"] ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "tool" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "tool" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"] == messages[2].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_call_id"] == messages[2].tool_call_id + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.tool_call_id"] == messages[2].tool_call_id assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) # Test that we write both the content and the tool calls assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == result.content[0]["text"] ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] == "toolu_012guEZNJ5yH5jxHKWAkzCzh" ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_news" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == {"location": "San Francisco"} @@ -900,9 +900,9 @@ def sample_tool(query: str) -> str: assert chat_span.name == "ChatOpenAI.chat" # Verify that the tool_call_id is properly set for the ToolMessage - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "tool" - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] == "Tool executed successfully" - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.tool_call_id"] == "call_12345" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "tool" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"] == "Tool executed successfully" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.tool_call_id"] == "call_12345" logs = log_exporter.get_finished_logs() assert len(logs) == 0, ( @@ -1045,39 +1045,39 @@ def get_news(location: str) -> str: } assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == messages[0].content ) - assert chat_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert chat_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"] == "call_EgULHWKqGjuB36aUeiOSpALZ" ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_weather" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ] ) == {"location": "San Francisco"} assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"] == "call_Xer9QGOTDMG2Bxn9AKGiVM14" ) assert ( - chat_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name"] + chat_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name"] == "get_news" ) assert json.loads( chat_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" ] ) == {"location": "San Francisco"} diff --git a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py index a79f49958d..00a68a2e44 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py +++ b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py @@ -7,6 +7,9 @@ from opentelemetry import context as context_api from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes, LLMRequestTypeValues from opentelemetry.instrumentation.llamaindex.utils import ( _with_tracer_wrapper, @@ -142,16 +145,16 @@ async def acomplete_wrapper(tracer, wrapped, instance: CustomLLM, args, kwargs): @dont_throw def _handle_request(span, llm_request_type, args, kwargs, instance: CustomLLM): - _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, instance.__class__.__name__) + _set_span_attribute(span, GenAIAttributes.GEN_AI_SYSTEM, instance.__class__.__name__) _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TYPE, llm_request_type.value) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MODEL, instance.metadata.model_name + span, GenAIAttributes.GEN_AI_REQUEST_MODEL, instance.metadata.model_name ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, instance.metadata.context_window + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, instance.metadata.context_window ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, instance.metadata.num_output + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, instance.metadata.num_output ) if should_send_prompts(): @@ -161,7 +164,7 @@ def _handle_request(span, llm_request_type, args, kwargs, instance: CustomLLM): prompt = args[0] _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.user", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", prompt[0] if isinstance(prompt, list) else prompt, ) @@ -171,13 +174,13 @@ def _handle_request(span, llm_request_type, args, kwargs, instance: CustomLLM): @dont_throw def _handle_response(span, llm_request_type, instance, response): _set_span_attribute( - span, SpanAttributes.GEN_AI_RESPONSE_MODEL, instance.metadata.model_name + span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, instance.metadata.model_name ) if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.COMPLETION: _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response.text + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response.text ) return diff --git a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py index 1b7f07709a..c4ff0f7ec6 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py +++ b/packages/opentelemetry-instrumentation-llamaindex/opentelemetry/instrumentation/llamaindex/span_utils.py @@ -3,6 +3,9 @@ dont_throw, should_send_prompts, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( LLMRequestTypeValues, SpanAttributes, @@ -17,10 +20,10 @@ def set_llm_chat_request(event, span) -> None: if should_send_prompts(): for idx, message in enumerate(event.messages): span.set_attribute( - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", message.role.value + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.role", message.role.value ) span.set_attribute( - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", message.content + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.content", message.content ) @@ -36,9 +39,9 @@ def set_llm_chat_request_model_attributes(event, span): if "llm" in model_dict: model_dict = model_dict.get("llm", {}) - span.set_attribute(SpanAttributes.GEN_AI_REQUEST_MODEL, model_dict.get("model")) + span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_MODEL, model_dict.get("model")) span.set_attribute( - SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, model_dict.get("temperature") + GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, model_dict.get("temperature") ) @@ -51,17 +54,17 @@ def set_llm_chat_response(event, span) -> None: if should_send_prompts(): for idx, message in enumerate(event.messages): span.set_attribute( - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", message.role.value + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.role", message.role.value ) span.set_attribute( - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", message.content + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.content", message.content ) span.set_attribute( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", response.message.role.value, ) span.set_attribute( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response.message.content, ) @@ -77,16 +80,16 @@ def set_llm_chat_response_model_attributes(event, span): return span.set_attribute( - SpanAttributes.GEN_AI_RESPONSE_MODEL, + GenAIAttributes.GEN_AI_RESPONSE_MODEL, ( raw.get("model") if "model" in raw else raw.model ), # raw can be Any, not just ChatCompletion ) if usage := raw.get("usage") if "usage" in raw else raw.usage: span.set_attribute( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens ) - span.set_attribute(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens) + span.set_attribute(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens) span.set_attribute(SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens) if choices := raw.choices: span.set_attribute( @@ -98,11 +101,11 @@ def set_llm_chat_response_model_attributes(event, span): def set_llm_predict_response(event, span) -> None: if should_send_prompts(): span.set_attribute( - f"{SpanAttributes.GEN_AI_COMPLETION}.role", + f"{GenAIAttributes.GEN_AI_COMPLETION}.role", MessageRole.ASSISTANT.value, ) span.set_attribute( - f"{SpanAttributes.GEN_AI_COMPLETION}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.content", event.output, ) diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py index 330f29a9bd..87555477ef 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_agents.py @@ -81,51 +81,51 @@ def multiply(a: int, b: int) -> int: assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( + assert llm_span_1.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are designed to help with a variety of tasks," ) - assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == ( + assert llm_span_1.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == ( "What is 2 times 3?" ) assert llm_span_1.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ].startswith( "Thought: The current language of the user is English. I need to use a tool" ) - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 479 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 479 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 522 assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are designed to help with a variety of tasks," ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == ( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == ( "What is 2 times 3?" ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"].startswith( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"].startswith( "Thought: The current language of the user is English. I need to use a tool" ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.3.content"] == ( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.content"] == ( "Observation: 6" ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == ( "Thought: I can answer without using any more tools. I'll use the user's " "language to answer.\nAnswer: 2 times 3 is 6." ) - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 535 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 535 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 567 logs = log_exporter.get_finished_logs() @@ -174,36 +174,36 @@ def multiply(a: int, b: int) -> int: assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( + assert llm_span_1.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are designed to help with a variety of tasks," ) - assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] == ( + assert llm_span_1.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == ( "What is 2 times 3?" ) assert llm_span_1.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ].startswith( "Thought: The current language of the user is English. I need to use a tool" ) - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 479 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 479 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 522 assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 535 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 535 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 567 logs = log_exporter.get_finished_logs() @@ -352,24 +352,24 @@ def multiply(a: int, b: int) -> int: assert llm_span_1.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_1.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 479 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 43 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 479 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 522 assert llm_span_2.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo-0613" ) assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" + llm_span_2.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0613" ) - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 535 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 32 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 535 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 567 logs = log_exporter.get_finished_logs() @@ -444,30 +444,30 @@ def test_agent_with_query_tool(instrument_legacy, span_exporter, log_exporter): assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( + assert llm_span_1.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"].startswith( "Given an input question, first create a syntactically correct sqlite" ) - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 224 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"].startswith( "Given an input question, synthesize a response from the query results." ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == ( "The city with the highest population in the city_stats table is Tokyo, " "with a population of 13,960,000." ) - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 63 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 63 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 88 logs = log_exporter.get_finished_logs() @@ -529,20 +529,20 @@ def test_agent_with_query_tool_with_events_with_content( assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 224 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 63 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 63 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 88 logs = log_exporter.get_finished_logs() @@ -654,20 +654,20 @@ def test_agent_with_query_tool_with_events_with_no_content( assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 - assert llm_span_1.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 224 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 68 + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 224 assert llm_span_1.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 292 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 - assert llm_span_2.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 63 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 25 + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 63 assert llm_span_2.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 88 logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py index 03ce3b4425..989e0cbc35 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_chroma_vector_store.py @@ -9,6 +9,9 @@ ) from llama_index.embeddings.openai import OpenAIEmbedding from llama_index.vector_stores.chroma import ChromaVectorStore +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes @@ -58,16 +61,16 @@ def test_rag_with_chroma(instrument_legacy, span_exporter): assert synthesize_span.parent is not None assert llm_span.parent is not None - assert llm_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( + assert llm_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are an expert Q&A system that is trusted around the world." ) - assert llm_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( + assert llm_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == ( "The author worked on writing and programming before college." ) - assert llm_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 10 - assert llm_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 2070 + assert llm_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 10 + assert llm_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 2070 assert llm_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 2080 diff --git a/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py b/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py index 8daf85cd21..53fff9fe71 100644 --- a/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py +++ b/packages/opentelemetry-instrumentation-llamaindex/tests/test_query_pipeline.py @@ -10,7 +10,9 @@ from llama_index.core.response_synthesizers import TreeSummarize from llama_index.llms.openai import OpenAI from llama_index.postprocessor.cohere_rerank import CohereRerank -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) @pytest.mark.vcr @@ -75,27 +77,27 @@ def test_query_pipeline(instrument_legacy, span_exporter): assert llm_span_1.parent is not None assert llm_span_2.parent is not None - assert llm_span_1.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_1.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_1.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_1.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == ( + assert llm_span_1.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == ( "Please generate a question about Paul Graham's life regarding the following topic YCombinator" ) - assert llm_span_1.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] == ( + assert llm_span_1.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == ( "What role did Paul Graham play in the founding and development of YCombinator, and " "how has his involvement shaped the trajectory of the company?" ) - assert llm_span_2.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert llm_span_2.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" assert ( - llm_span_2.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" + llm_span_2.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) - assert llm_span_2.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"].startswith( + assert llm_span_2.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"].startswith( "You are an expert Q&A system that is trusted around the world." ) assert llm_span_2.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ].startswith( "Paul Graham played a pivotal role in the founding and development of Y Combinator." ) diff --git a/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py b/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py index 669429c3b7..b1628861cf 100644 --- a/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py +++ b/packages/opentelemetry-instrumentation-mistralai/opentelemetry/instrumentation/mistralai/__init__.py @@ -23,8 +23,8 @@ _SUPPRESS_INSTRUMENTATION_KEY, unwrap, ) -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, @@ -79,16 +79,16 @@ def _set_input_attributes(span, llm_request_type, to_wrap, kwargs): return if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") for index, message in enumerate(kwargs.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.content", message.content, ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.role", message.role, ) else: @@ -96,21 +96,21 @@ def _set_input_attributes(span, llm_request_type, to_wrap, kwargs): if isinstance(input, str): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user" ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", input + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", input ) else: for index, prompt in enumerate(input): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.role", "user", ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.content", prompt, ) @@ -119,7 +119,7 @@ def _set_input_attributes(span, llm_request_type, to_wrap, kwargs): def _set_model_input_attributes(span, to_wrap, kwargs): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) _set_span_attribute( span, SpanAttributes.LLM_IS_STREAMING, @@ -134,7 +134,7 @@ def _set_response_attributes(span, llm_request_type, response): if should_send_prompts(): for index, choice in enumerate(response.choices): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.finish_reason", @@ -161,12 +161,12 @@ def _set_model_response_attributes(span, llm_request_type, response): if not span.is_recording(): return - _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response.id) if llm_request_type == LLMRequestTypeValues.EMBEDDING: return - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, response.model) if not response.usage: return @@ -182,12 +182,12 @@ def _set_model_response_attributes(span, llm_request_type, response): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens, ) @@ -398,7 +398,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "MistralAI", + GenAIAttributes.GEN_AI_SYSTEM: "MistralAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) @@ -444,7 +444,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "MistralAI", + GenAIAttributes.GEN_AI_SYSTEM: "MistralAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) diff --git a/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py b/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py index 115ce0685a..7a767ec4c0 100644 --- a/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-mistralai/tests/test_chat.py @@ -24,27 +24,27 @@ def test_mistralai_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response.choices[0].message.content ) - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "d5f25c4c1e29441db526ce7db3400010" @@ -70,19 +70,19 @@ def test_mistralai_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "d5f25c4c1e29441db526ce7db3400010" @@ -123,19 +123,19 @@ def test_mistralai_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "d5f25c4c1e29441db526ce7db3400010" @@ -176,27 +176,27 @@ def test_mistralai_streaming_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response ) - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "937738cd542a461da86a967ad7c2c8db" @@ -226,19 +226,19 @@ def test_mistralai_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "937738cd542a461da86a967ad7c2c8db" @@ -283,19 +283,19 @@ def test_mistralai_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "937738cd542a461da86a967ad7c2c8db" @@ -333,28 +333,28 @@ async def test_mistralai_async_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response.choices[0].message.content ) # For some reason, async ollama chat doesn't report prompt token usage back - # assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + # assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "84e3f907fd2045eba99a91a50a6c5a53" @@ -381,20 +381,20 @@ async def test_mistralai_async_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) # For some reason, async ollama chat doesn't report prompt token usage back - # assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + # assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "84e3f907fd2045eba99a91a50a6c5a53" @@ -435,20 +435,20 @@ async def test_mistralai_async_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-tiny" ) # For some reason, async ollama chat doesn't report prompt token usage back - # assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + # assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "84e3f907fd2045eba99a91a50a6c5a53" @@ -490,24 +490,24 @@ async def test_mistralai_async_streaming_chat_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert mistral_span.attributes.get("gen_ai.request.model") == "mistral-tiny" assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response ) - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "8b811019d651417b913b5c16b32732e2" @@ -538,16 +538,16 @@ async def test_mistralai_async_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert mistral_span.attributes.get("gen_ai.request.model") == "mistral-tiny" - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "8b811019d651417b913b5c16b32732e2" @@ -594,16 +594,16 @@ async def test_mistralai_async_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.chat" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert mistral_span.attributes.get("gen_ai.request.model") == "mistral-tiny" - assert mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 + assert mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 11 assert mistral_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == mistral_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + mistral_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + mistral_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) assert ( mistral_span.attributes.get("gen_ai.response.id") == "8b811019d651417b913b5c16b32732e2" diff --git a/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py b/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py index bb19141f1e..3dc6a45f7b 100644 --- a/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py +++ b/packages/opentelemetry-instrumentation-mistralai/tests/test_embeddings.py @@ -21,17 +21,17 @@ def test_mistral_embeddings_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( @@ -57,13 +57,13 @@ def test_mistral_embeddings_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( @@ -100,13 +100,13 @@ def test_mistral_embeddings_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( @@ -144,17 +144,17 @@ async def test_mistral_async_embeddings_legacy( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( @@ -181,13 +181,13 @@ async def test_mistral_async_embeddings_with_events_with_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( @@ -238,13 +238,13 @@ async def test_mistral_async_embeddings_with_events_with_no_content( spans = span_exporter.get_finished_spans() mistral_span = spans[0] assert mistral_span.name == "mistralai.embeddings" - assert mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "MistralAI" + assert mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "MistralAI" assert ( mistral_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not mistral_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - mistral_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") + mistral_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "mistral-embed" ) assert ( diff --git a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py index 01ec34486b..40dc6ce101 100644 --- a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py +++ b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/__init__.py @@ -27,7 +27,12 @@ unwrap, ) from opentelemetry.metrics import Histogram, Meter, get_meter -from opentelemetry.semconv._incubating.metrics import gen_ai_metrics as GenAIMetrics +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv._incubating.metrics import ( + gen_ai_metrics as GenAIMetrics, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -107,7 +112,7 @@ def _accumulate_streaming_response( first_token_time = time.perf_counter() streaming_time_to_first_token.record( first_token_time - start_time, - attributes={SpanAttributes.GEN_AI_SYSTEM: "Ollama"}, + attributes={GenAIAttributes.GEN_AI_SYSTEM: "Ollama"}, ) first_token = False yield res @@ -125,8 +130,8 @@ def _accumulate_streaming_response( streaming_time_to_generate.record( time.perf_counter() - first_token_time, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_name, }, ) @@ -171,7 +176,7 @@ async def _aaccumulate_streaming_response( first_token_time = time.perf_counter() streaming_time_to_first_token.record( first_token_time - start_time, - attributes={SpanAttributes.GEN_AI_SYSTEM: "Ollama"}, + attributes={GenAIAttributes.GEN_AI_SYSTEM: "Ollama"}, ) first_token = False yield res @@ -189,8 +194,8 @@ async def _aaccumulate_streaming_response( streaming_time_to_generate.record( time.perf_counter() - first_token_time, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_name, }, ) @@ -297,7 +302,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) @@ -310,10 +315,10 @@ def _wrap( if response: if duration_histogram: duration = end_time - start_time - attrs = {SpanAttributes.GEN_AI_SYSTEM: "Ollama"} + attrs = {GenAIAttributes.GEN_AI_SYSTEM: "Ollama"} model = kwargs.get("model") if model is not None: - attrs[SpanAttributes.GEN_AI_RESPONSE_MODEL] = model + attrs[GenAIAttributes.GEN_AI_RESPONSE_MODEL] = model duration_histogram.record(duration, attributes=attrs) if kwargs.get("stream"): @@ -364,7 +369,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) @@ -377,10 +382,10 @@ async def _awrap( if response: if duration_histogram: duration = end_time - start_time - attrs = {SpanAttributes.GEN_AI_SYSTEM: "Ollama"} + attrs = {GenAIAttributes.GEN_AI_SYSTEM: "Ollama"} model = kwargs.get("model") if model is not None: - attrs[SpanAttributes.GEN_AI_RESPONSE_MODEL] = model + attrs[GenAIAttributes.GEN_AI_RESPONSE_MODEL] = model duration_histogram.record(duration, attributes=attrs) if kwargs.get("stream"): diff --git a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py index db6b721615..e108f04c21 100644 --- a/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py +++ b/packages/opentelemetry-instrumentation-ollama/opentelemetry/instrumentation/ollama/span_utils.py @@ -1,6 +1,9 @@ import json from opentelemetry.instrumentation.ollama.utils import dont_throw, should_send_prompts +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( LLMRequestTypeValues, SpanAttributes, @@ -22,25 +25,25 @@ def set_input_attributes(span, llm_request_type, kwargs): json_data = kwargs.get("json", {}) if llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") for index, message in enumerate(json_data.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.content", message.get("content"), ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.role", message.get("role"), ) _set_prompts(span, json_data.get("messages")) if json_data.get("tools"): set_tools_attributes(span, json_data.get("tools")) else: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", json_data.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", json_data.get("prompt") ) @@ -49,7 +52,7 @@ def set_model_input_attributes(span, kwargs): if not span.is_recording(): return json_data = kwargs.get("json", {}) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, json_data.get("model")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, json_data.get("model")) _set_span_attribute( span, SpanAttributes.LLM_IS_STREAMING, kwargs.get("stream") or False ) @@ -64,15 +67,15 @@ def set_response_attributes(span, token_histogram, llm_request_type, response): if llm_request_type == LLMRequestTypeValues.COMPLETION: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response.get("response"), ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) elif llm_request_type == LLMRequestTypeValues.CHAT: index = 0 - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.content", response.get("message").get("content") ) @@ -86,7 +89,7 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo if llm_request_type == LLMRequestTypeValues.EMBEDDING or not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, response.get("model")) input_tokens = response.get("prompt_eval_count") or 0 output_tokens = response.get("eval_count") or 0 @@ -98,15 +101,15 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens, ) - _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, "Ollama") + _set_span_attribute(span, GenAIAttributes.GEN_AI_SYSTEM, "Ollama") if ( token_histogram is not None @@ -116,9 +119,9 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo token_histogram.record( input_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", - SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -130,9 +133,9 @@ def set_model_response_attributes(span, token_histogram, llm_request_type, respo token_histogram.record( output_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", - SpanAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response.get("model"), }, ) @@ -160,7 +163,7 @@ def _set_prompts(span, messages): if not should_send_prompts(): return for i, msg in enumerate(messages): - prefix = f"{SpanAttributes.GEN_AI_PROMPT}.{i}" + prefix = f"{GenAIAttributes.GEN_AI_PROMPT}.{i}" _set_span_attribute(span, f"{prefix}.role", msg.get("role")) if msg.get("content"): diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py b/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py index 8e5ca8a813..2a548d35a9 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_chat.py @@ -31,24 +31,24 @@ def test_ollama_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response["message"]["content"] ) - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -73,16 +73,16 @@ def test_ollama_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -121,16 +121,16 @@ def test_ollama_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -177,27 +177,27 @@ def test_ollama_chat_tool_calls_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" ) assert ( f"{SpanAttributes.LLM_REQUEST_FUNCTIONS}.0.content" not in ollama_span.attributes ) assert ( - ollama_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] + ollama_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( - ollama_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments"] + ollama_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments"] == '{"location": "San Francisco"}' ) assert ( - ollama_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + ollama_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == "The weather in San Francisco is 70 degrees and sunny." ) @@ -237,11 +237,11 @@ def test_ollama_chat_tool_calls_with_events_with_content( ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" ) logs = log_exporter.get_finished_logs() @@ -312,11 +312,11 @@ def test_ollama_chat_tool_calls_with_events_with_no_content( ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3.1" ) logs = log_exporter.get_finished_logs() @@ -372,24 +372,24 @@ def test_ollama_streaming_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response ) - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -419,16 +419,16 @@ def test_ollama_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -472,16 +472,16 @@ def test_ollama_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -517,25 +517,25 @@ async def test_ollama_async_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response["message"]["content"] ) # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -561,17 +561,17 @@ async def test_ollama_async_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -611,17 +611,17 @@ async def test_ollama_async_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -662,24 +662,24 @@ async def test_ollama_async_streaming_chat_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response ) - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -710,16 +710,16 @@ async def test_ollama_async_streaming_chat_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -764,16 +764,16 @@ async def test_ollama_async_streaming_chat_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.chat" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "chat" assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -805,17 +805,17 @@ def test_token_histogram_recording(): token_histogram.record.assert_any_call( 7, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", - SpanAttributes.GEN_AI_RESPONSE_MODEL: "llama3", + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: "llama3", }, ) token_histogram.record.assert_any_call( 10, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Ollama", - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", - SpanAttributes.GEN_AI_RESPONSE_MODEL: "llama3", + GenAIAttributes.GEN_AI_SYSTEM: "Ollama", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: "llama3", }, ) diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py b/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py index 5a6065b93d..606d4aa355 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_embeddings.py @@ -20,14 +20,14 @@ def test_ollama_embeddings_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.embeddings" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) @@ -48,12 +48,12 @@ def test_ollama_embeddings_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.embeddings" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -86,12 +86,12 @@ def test_ollama_embeddings_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.embeddings" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "embedding" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py index b3309d08f8..9f47d164d9 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py @@ -20,26 +20,26 @@ def test_ollama_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response["response"] ) - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -58,18 +58,18 @@ def test_ollama_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -100,18 +100,18 @@ def test_ollama_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -144,26 +144,26 @@ def test_ollama_streaming_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response ) - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -186,18 +186,18 @@ def test_ollama_streaming_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -234,18 +234,18 @@ def test_ollama_streaming_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" - assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -275,27 +275,27 @@ async def test_ollama_async_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response["response"] ) # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -315,19 +315,19 @@ async def test_ollama_async_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -361,19 +361,19 @@ async def test_ollama_async_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert not ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -407,27 +407,27 @@ async def test_ollama_async_streaming_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about OpenTelemetry" ) assert ( - ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response ) # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert ( @@ -451,19 +451,19 @@ async def test_ollama_async_streaming_generation_with_events_with_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -501,19 +501,19 @@ async def test_ollama_async_streaming_generation_with_events_with_no_content( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) assert ollama_span.attributes.get(f"{SpanAttributes.LLM_IS_STREAMING}") - assert ollama_span.attributes.get(f"{SpanAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" + assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_REQUEST_MODEL}") == "llama3" # For some reason, async ollama chat doesn't report prompt token usage back - # assert ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 + # assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 17 assert ollama_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS ) == ollama_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - ) + ollama_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + ) + ollama_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py b/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py index c7398e9544..574962adbb 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_ollama_metrics.py @@ -1,7 +1,12 @@ import ollama import pytest -from opentelemetry.semconv._incubating.metrics import gen_ai_metrics as GenAIMetrics -from opentelemetry.semconv_ai import Meters, SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv._incubating.metrics import ( + gen_ai_metrics as GenAIMetrics, +) +from opentelemetry.semconv_ai import Meters def _collect_metrics(reader): @@ -40,7 +45,7 @@ def test_ollama_streaming_metrics(instrument_legacy, reader): for name, dp in points: if name == GenAIMetrics.GEN_AI_SERVER_TIME_TO_FIRST_TOKEN: assert dp.sum > 0, "Time to first token should be greater than 0" - assert dp.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Ollama" + assert dp.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Ollama" break @@ -63,6 +68,6 @@ def test_ollama_streaming_time_to_generate_metrics(instrument_legacy, reader): for name, dp in points: if name == Meters.LLM_STREAMING_TIME_TO_GENERATE: assert dp.sum > 0, "Streaming time to generate should be greater than 0" - assert dp.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "Ollama" - assert dp.attributes.get(SpanAttributes.GEN_AI_RESPONSE_MODEL) is not None + assert dp.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Ollama" + assert dp.attributes.get(GenAIAttributes.GEN_AI_RESPONSE_MODEL) is not None break diff --git a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py index e72db09a07..ebae0770c0 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py +++ b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/__init__.py @@ -18,8 +18,8 @@ TraceloopSpanKindValues, Meters, ) -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_COMPLETION, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from .utils import set_span_attribute, JSONEncoder from agents import FunctionTool, WebSearchTool, FileSearchTool, ComputerTool @@ -360,9 +360,9 @@ def set_model_settings_span_attributes(agent, span): settings_dict = vars(model_settings) key_to_span_attr = { - "max_tokens": SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, - "temperature": SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, - "top_p": SpanAttributes.GEN_AI_REQUEST_TOP_P, + "max_tokens": GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, + "temperature": GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, + "top_p": GenAIAttributes.GEN_AI_REQUEST_TOP_P, } for key, value in settings_dict.items(): @@ -424,17 +424,17 @@ async def wrapped_on_invoke_tool(tool_context, args_json): ) as span: try: span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.name", tool_name + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.name", tool_name ) span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.type", "FunctionTool" + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type", "FunctionTool" ) span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.description", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.description", original_tool.description, ) span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.strict_json_schema", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.strict_json_schema", original_tool.strict_json_schema, ) span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_INPUT, args_json) @@ -469,35 +469,35 @@ async def wrapped_on_invoke_tool(tool_context, args_json): ) if isinstance(tool, WebSearchTool): - span.set_attribute(f"{GEN_AI_COMPLETION}.tool.type", "WebSearchTool") + span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type", "WebSearchTool") span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.search_context_size", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.search_context_size", tool.search_context_size, ) if tool.user_location: span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.user_location", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.user_location", str(tool.user_location), ) elif isinstance(tool, FileSearchTool): - span.set_attribute(f"{GEN_AI_COMPLETION}.tool.type", "FileSearchTool") + span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type", "FileSearchTool") span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.vector_store_ids", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.vector_store_ids", str(tool.vector_store_ids), ) if tool.max_num_results: span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.max_num_results", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.max_num_results", tool.max_num_results, ) span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.include_search_results", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.include_search_results", tool.include_search_results, ) elif isinstance(tool, ComputerTool): - span.set_attribute(f"{GEN_AI_COMPLETION}.tool.type", "ComputerTool") + span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type", "ComputerTool") span.set_attribute( - f"{GEN_AI_COMPLETION}.tool.computer", str(tool.computer) + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.computer", str(tool.computer) ) span.set_status(Status(StatusCode.OK)) @@ -514,12 +514,12 @@ def set_prompt_attributes(span, message_history): content = msg.get("content", None) set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", role, ) set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", content, ) @@ -549,18 +549,18 @@ def set_response_content_span_attribute(response, span): if roles: set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.roles", + f"{GenAIAttributes.GEN_AI_COMPLETION}.roles", roles, ) if types: set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.types", + f"{GenAIAttributes.GEN_AI_COMPLETION}.types", types, ) if contents: set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.contents", contents + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.contents", contents ) @@ -581,13 +581,13 @@ def set_token_usage_span_attributes( if input_tokens is not None: set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens, ) if output_tokens is not None: set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) if total_tokens is not None: @@ -600,18 +600,18 @@ def set_token_usage_span_attributes( token_histogram.record( input_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "openai", - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, + GenAIAttributes.GEN_AI_SYSTEM: "openai", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_name, "gen_ai.agent.name": agent_name, }, ) token_histogram.record( output_tokens, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "openai", - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_name, + GenAIAttributes.GEN_AI_SYSTEM: "openai", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_name, "gen_ai.agent.name": agent_name, }, ) diff --git a/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py b/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py index 152693802a..1331a00b20 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py +++ b/packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py @@ -11,8 +11,8 @@ TraceloopSpanKindValues, Meters, ) -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_COMPLETION, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) @@ -41,9 +41,9 @@ def test_agent_spans(exporter, test_agent): span.attributes[SpanAttributes.TRACELOOP_SPAN_KIND] == TraceloopSpanKindValues.AGENT.value ) - assert span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 - assert span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 1024 - assert span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.2 + assert span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.3 + assert span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 1024 + assert span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.2 assert span.attributes["openai.agent.model.frequency_penalty"] == 1.3 assert span.attributes["gen_ai.agent.name"] == "testAgent" assert ( @@ -51,21 +51,21 @@ def test_agent_spans(exporter, test_agent): == "You are a helpful assistant that answers all questions" ) - assert span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" - assert span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "What is AI?" + assert span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "What is AI?" - assert span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] is not None + assert span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] is not None assert ( - span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] is not None) assert span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] is not None - assert span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.contents"] is not None - assert len(span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.contents"]) > 0 - assert span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.roles"] is not None - assert len(span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.roles"]) > 0 - assert span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.types"] is not None - assert len(span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.types"]) > 0 + assert span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.contents"] is not None + assert len(span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.contents"]) > 0 + assert span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.roles"] is not None + assert len(span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.roles"]) > 0 + assert span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.types"] is not None + assert len(span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.types"]) > 0 assert span.status.status_code == StatusCode.OK @@ -94,14 +94,14 @@ def test_agent_with_function_tool_spans(exporter, function_tool_agent): ) assert tool_span.kind == tool_span.kind.INTERNAL - assert tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.name"] == "get_weather" - assert tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.type"] == "FunctionTool" + assert tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.name"] == "get_weather" + assert tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type"] == "FunctionTool" assert ( - tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.description"] + tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.description"] == "Gets the current weather for a specified city." ) - assert tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.strict_json_schema"] is True + assert tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.strict_json_schema"] is True assert agent_span.status.status_code == StatusCode.OK assert tool_span.status.status_code == StatusCode.OK @@ -131,12 +131,12 @@ def test_agent_with_web_search_tool_spans(exporter, web_search_tool_agent): ) assert tool_span.kind == tool_span.kind.INTERNAL - assert tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.type"] == "WebSearchTool" + assert tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type"] == "WebSearchTool" assert ( - tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.search_context_size"] + tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.search_context_size"] is not None ) - assert f"{GEN_AI_COMPLETION}.tool.user_location" not in tool_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.user_location" not in tool_span.attributes assert agent_span.status.status_code == StatusCode.OK assert tool_span.status.status_code == StatusCode.OK @@ -193,7 +193,7 @@ def test_generate_metrics(metrics_test_context, test_agent): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -314,11 +314,11 @@ async def test_recipe_workflow_agent_handoffs_with_function_tools( == TraceloopSpanKindValues.TOOL.value ) assert ( - search_tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.name"] + search_tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.name"] == "search_recipes" ) assert ( - search_tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.type"] == "FunctionTool" + search_tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type"] == "FunctionTool" ) assert "traceloop.entity.input" in search_tool_span.attributes @@ -329,11 +329,11 @@ async def test_recipe_workflow_agent_handoffs_with_function_tools( == TraceloopSpanKindValues.TOOL.value ) assert ( - modify_tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.name"] + modify_tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.name"] == "plan_and_apply_recipe_modifications" ) assert ( - modify_tool_span.attributes[f"{GEN_AI_COMPLETION}.tool.type"] == "FunctionTool" + modify_tool_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type"] == "FunctionTool" ) assert "traceloop.entity.input" in modify_tool_span.attributes diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py index c63401d74c..648cecd80d 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/__init__.py @@ -1,6 +1,8 @@ import json import logging import types +import openai +import pydantic from importlib.metadata import version from opentelemetry.instrumentation.openai.shared.config import Config @@ -9,14 +11,12 @@ is_openai_v1, should_record_stream_token_usage, ) -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import SpanAttributes from opentelemetry.trace.propagation import set_span_in_context from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator -import openai -import pydantic OPENAI_LLM_USAGE_TOKEN_TYPES = ["prompt_tokens", "completion_tokens"] PROMPT_FILTER_KEY = "prompt_filter_results" @@ -112,7 +112,7 @@ def _set_request_attributes(span, kwargs, instance=None): base_url = _get_openai_base_url(instance) if instance else "" vendor = _get_vendor_from_url(base_url) - _set_span_attribute(span, SpanAttributes.GEN_AI_SYSTEM, vendor) + _set_span_attribute(span, GenAIAttributes.GEN_AI_SYSTEM, vendor) model = kwargs.get("model") if vendor == "AWS" and model and "." in model: @@ -120,14 +120,14 @@ def _set_request_attributes(span, kwargs, instance=None): elif vendor == "OpenRouter": model = _extract_model_name_from_provider_format(model) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, model) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_tokens") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) _set_span_attribute( span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty") ) @@ -197,7 +197,7 @@ def _set_response_attributes(span, response): if "error" in response: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}", + f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}", json.dumps(response.get("error")), ) return @@ -205,8 +205,8 @@ def _set_response_attributes(span, response): response_model = response.get("model") if response_model: response_model = _extract_model_name_from_provider_format(response_model) - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response_model) - _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.get("id")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, response_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response.get("id")) _set_span_attribute( span, @@ -226,16 +226,16 @@ def _set_response_attributes(span, response): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.get("completion_tokens"), ) _set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.get("prompt_tokens") + span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.get("prompt_tokens") ) prompt_tokens_details = dict(usage.get("prompt_tokens_details", {})) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, prompt_tokens_details.get("cached_tokens", 0), ) return @@ -245,7 +245,7 @@ def _log_prompt_filter(span, response_dict): if response_dict.get("prompt_filter_results"): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}", + f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}", json.dumps(response_dict.get("prompt_filter_results")), ) @@ -257,11 +257,11 @@ def _set_span_stream_usage(span, prompt_tokens, completion_tokens): if isinstance(completion_tokens, int) and completion_tokens >= 0: _set_span_attribute( - span, SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) if isinstance(prompt_tokens, int) and prompt_tokens >= 0: - _set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) + _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) if ( isinstance(prompt_tokens, int) @@ -402,8 +402,8 @@ def metric_shared_attributes( return { **attributes, - SpanAttributes.GEN_AI_SYSTEM: vendor, - SpanAttributes.GEN_AI_RESPONSE_MODEL: response_model, + GenAIAttributes.GEN_AI_SYSTEM: vendor, + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response_model, "gen_ai.operation.name": operation, "server.address": server_address, "stream": is_streaming, diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py index 75d7dbc814..bfaddfa3b9 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/chat_wrappers.py @@ -42,6 +42,9 @@ from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.metrics import Counter, Histogram from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -363,7 +366,7 @@ def _set_token_counter_metrics(token_counter, usage, shared_attributes): if name in OPENAI_LLM_USAGE_TOKEN_TYPES: attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: _token_type(name), + GenAIAttributes.GEN_AI_TOKEN_TYPE: _token_type(name), } token_counter.record(val, attributes=attributes_with_token_type) @@ -399,7 +402,7 @@ async def _set_prompts(span, messages): return for i, msg in enumerate(messages): - prefix = f"{SpanAttributes.GEN_AI_PROMPT}.{i}" + prefix = f"{GenAIAttributes.GEN_AI_PROMPT}.{i}" msg = msg if isinstance(msg, dict) else model_as_dict(msg) _set_span_attribute(span, f"{prefix}.role", msg.get("role")) @@ -451,7 +454,7 @@ def _set_completions(span, choices): for choice in choices: index = choice.get("index") - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.finish_reason", choice.get("finish_reason") ) @@ -564,14 +567,14 @@ def _set_streaming_token_metrics( if isinstance(prompt_usage, int) and prompt_usage >= 0: attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", } token_counter.record(prompt_usage, attributes=attributes_with_token_type) if isinstance(completion_usage, int) and completion_usage >= 0: attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", } token_counter.record( completion_usage, attributes=attributes_with_token_type @@ -763,7 +766,7 @@ def _build_from_streaming_response( yield item_to_yield shared_attributes = { - SpanAttributes.GEN_AI_RESPONSE_MODEL: complete_response.get("model") or None, + GenAIAttributes.GEN_AI_RESPONSE_MODEL: complete_response.get("model") or None, "server.address": _get_openai_base_url(instance), "stream": True, } @@ -833,7 +836,7 @@ async def _abuild_from_streaming_response( yield item_to_yield shared_attributes = { - SpanAttributes.GEN_AI_RESPONSE_MODEL: complete_response.get("model") or None, + GenAIAttributes.GEN_AI_RESPONSE_MODEL: complete_response.get("model") or None, "server.address": _get_openai_base_url(instance), "stream": True, } diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py index 4081d861f7..3afb50b0fa 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/completion_wrappers.py @@ -29,6 +29,9 @@ should_send_prompts, ) from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -157,7 +160,7 @@ def _set_prompts(span, prompt): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.user", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", prompt[0] if isinstance(prompt, list) else prompt, ) @@ -169,7 +172,7 @@ def _set_completions(span, choices): for choice in choices: index = choice.get("index") - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.finish_reason", choice.get("finish_reason") ) diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py index cfa21b330c..855e883a68 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py @@ -32,6 +32,9 @@ from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.metrics import Counter, Histogram from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -248,7 +251,7 @@ def _set_embeddings_metrics( continue attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: _token_type(name), + GenAIAttributes.GEN_AI_TOKEN_TYPE: _token_type(name), } token_counter.record(val, attributes=attributes_with_token_type) @@ -270,11 +273,11 @@ def _set_prompts(span, prompt): if isinstance(prompt, list): for i, p in enumerate(prompt): - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", p) + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", p) else: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", prompt, ) diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py index 80fa9e426c..d8607533f4 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py @@ -19,6 +19,9 @@ ) from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import LLMRequestTypeValues, SpanAttributes from opentelemetry.trace import SpanKind, Status, StatusCode @@ -145,37 +148,37 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): _set_span_attribute( span, - SpanAttributes.GEN_AI_SYSTEM, + GenAIAttributes.GEN_AI_SYSTEM, "openai", ) _set_span_attribute( span, - SpanAttributes.GEN_AI_REQUEST_MODEL, + GenAIAttributes.GEN_AI_REQUEST_MODEL, assistant["model"], ) _set_span_attribute( span, - SpanAttributes.GEN_AI_RESPONSE_MODEL, + GenAIAttributes.GEN_AI_RESPONSE_MODEL, assistant["model"], ) if should_emit_events(): emit_event(MessageEvent(content=assistant["instructions"], role="system")) else: _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "system" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "system" ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", assistant["instructions"], ) prompt_index += 1 _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "system" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "system" ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", run["instructions"], ) emit_event(MessageEvent(content=run["instructions"], role="system")) @@ -183,7 +186,7 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): completion_index = 0 for msg in messages: - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}" content = msg.get("content") message_content = content[0].get("text").get("value") @@ -194,12 +197,12 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): else: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", message_role, ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", message_content, ) prompt_index += 1 @@ -223,12 +226,12 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): usage_dict = model_as_dict(run.get("usage")) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage_dict.get("completion_tokens"), ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage_dict.get("prompt_tokens"), ) @@ -262,16 +265,16 @@ def runs_create_and_stream_wrapper(tracer, wrapped, instance, args, kwargs): assistant = assistants[assistant_id] _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MODEL, assistants[assistant_id]["model"] + span, GenAIAttributes.GEN_AI_REQUEST_MODEL, assistants[assistant_id]["model"] ) _set_span_attribute( span, - SpanAttributes.GEN_AI_SYSTEM, + GenAIAttributes.GEN_AI_SYSTEM, "openai", ) _set_span_attribute( span, - SpanAttributes.GEN_AI_RESPONSE_MODEL, + GenAIAttributes.GEN_AI_RESPONSE_MODEL, assistants[assistant_id]["model"], ) if should_emit_events(): @@ -282,20 +285,20 @@ def runs_create_and_stream_wrapper(tracer, wrapped, instance, args, kwargs): ) else: _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", "system" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", "system" ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", assistants[assistant_id]["instructions"], ) i += 1 if should_emit_events(): emit_event(MessageEvent(content=instructions, role="system")) else: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.role", "system") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", "system") _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.{i}.content", instructions + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", instructions ) from opentelemetry.instrumentation.openai.v1.event_handler_wrapper import ( diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py index 9c07e5a98e..7b58b21a8e 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py @@ -3,7 +3,9 @@ from opentelemetry.instrumentation.openai.shared.event_models import ChoiceEvent from opentelemetry.instrumentation.openai.utils import should_emit_events from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.trace import Status, StatusCode from typing_extensions import override @@ -24,12 +26,12 @@ def __init__(self, original_handler, span): def on_end(self): _set_span_attribute( self._span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, self._prompt_tokens, ) _set_span_attribute( self._span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, self._completion_tokens, ) self._original_handler.on_end() @@ -118,12 +120,12 @@ def on_text_done(self, text): if not should_emit_events(): _set_span_attribute( self._span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{self._current_text_index}.role", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{self._current_text_index}.role", "assistant", ) _set_span_attribute( self._span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{self._current_text_index}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{self._current_text_index}.content", text.value, ) diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py index f3a5c1e248..569e11a1f2 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py @@ -38,18 +38,11 @@ from openai._legacy_response import LegacyAPIResponse from opentelemetry import context as context_api from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_COMPLETION, - GEN_AI_PROMPT, - GEN_AI_USAGE_INPUT_TOKENS, - GEN_AI_USAGE_OUTPUT_TOKENS, - GEN_AI_RESPONSE_ID, - GEN_AI_REQUEST_MODEL, - GEN_AI_RESPONSE_MODEL, - GEN_AI_SYSTEM, -) from opentelemetry.trace import SpanKind, Span, StatusCode, Tracer from typing import Any, Optional, Union from typing_extensions import NotRequired @@ -181,20 +174,20 @@ def process_content_block( @dont_throw def set_data_attributes(traced_response: TracedData, span: Span): - _set_span_attribute(span, GEN_AI_SYSTEM, "openai") - _set_span_attribute(span, GEN_AI_REQUEST_MODEL, traced_response.request_model) - _set_span_attribute(span, GEN_AI_RESPONSE_ID, traced_response.response_id) - _set_span_attribute(span, GEN_AI_RESPONSE_MODEL, traced_response.response_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_SYSTEM, "openai") + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, traced_response.request_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, traced_response.response_id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, traced_response.response_model) if usage := traced_response.usage: - _set_span_attribute(span, GEN_AI_USAGE_INPUT_TOKENS, usage.input_tokens) - _set_span_attribute(span, GEN_AI_USAGE_OUTPUT_TOKENS, usage.output_tokens) + _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.input_tokens) + _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.output_tokens) _set_span_attribute( span, SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens ) if usage.input_tokens_details: _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, + GenAIAttributes.GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, usage.input_tokens_details.cached_tokens, ) # TODO: add reasoning tokens in output token details @@ -227,17 +220,17 @@ def set_data_attributes(traced_response: TracedData, span: Span): if traced_response.instructions: _set_span_attribute( span, - f"{GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", traced_response.instructions, ) - _set_span_attribute(span, f"{GEN_AI_PROMPT}.{prompt_index}.role", "system") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "system") prompt_index += 1 if isinstance(traced_response.input, str): _set_span_attribute( - span, f"{GEN_AI_PROMPT}.{prompt_index}.content", traced_response.input + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", traced_response.input ) - _set_span_attribute(span, f"{GEN_AI_PROMPT}.{prompt_index}.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "user") prompt_index += 1 else: for block in traced_response.input: @@ -257,24 +250,24 @@ def set_data_attributes(traced_response: TracedData, span: Span): ) _set_span_attribute( span, - f"{GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", stringified_content, ) _set_span_attribute( span, - f"{GEN_AI_PROMPT}.{prompt_index}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", block_dict.get("role"), ) prompt_index += 1 elif block_dict.get("type") == "computer_call_output": _set_span_attribute( - span, f"{GEN_AI_PROMPT}.{prompt_index}.role", "computer-call" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "computer-call" ) output_image_url = block_dict.get("output", {}).get("image_url") if output_image_url: _set_span_attribute( span, - f"{GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", json.dumps( [ { @@ -287,7 +280,7 @@ def set_data_attributes(traced_response: TracedData, span: Span): prompt_index += 1 elif block_dict.get("type") == "computer_call": _set_span_attribute( - span, f"{GEN_AI_PROMPT}.{prompt_index}.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.role", "assistant" ) call_content = {} if block_dict.get("id"): @@ -298,16 +291,16 @@ def set_data_attributes(traced_response: TracedData, span: Span): call_content["action"] = block_dict.get("action") _set_span_attribute( span, - f"{GEN_AI_PROMPT}.{prompt_index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.content", json.dumps(call_content), ) prompt_index += 1 # TODO: handle other block types - _set_span_attribute(span, f"{GEN_AI_COMPLETION}.0.role", "assistant") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant") if traced_response.output_text: _set_span_attribute( - span, f"{GEN_AI_COMPLETION}.0.content", traced_response.output_text + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", traced_response.output_text ) tool_call_index = 0 for block in traced_response.output_blocks.values(): @@ -318,64 +311,64 @@ def set_data_attributes(traced_response: TracedData, span: Span): if block_dict.get("type") == "function_call": _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", block_dict.get("id"), ) _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", block_dict.get("name"), ) _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.arguments", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.arguments", block_dict.get("arguments"), ) tool_call_index += 1 elif block_dict.get("type") == "file_search_call": _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", block_dict.get("id"), ) _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", "file_search_call", ) tool_call_index += 1 elif block_dict.get("type") == "web_search_call": _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", block_dict.get("id"), ) _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", "web_search_call", ) tool_call_index += 1 elif block_dict.get("type") == "computer_call": _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.id", block_dict.get("call_id"), ) _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.name", "computer_call", ) _set_span_attribute( span, - f"{GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.arguments", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.{tool_call_index}.arguments", json.dumps(block_dict.get("action")), ) tool_call_index += 1 elif block_dict.get("type") == "reasoning": _set_span_attribute( - span, f"{GEN_AI_COMPLETION}.0.reasoning", block_dict.get("summary") + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.reasoning", block_dict.get("summary") ) # TODO: handle other block types, in particular other calls diff --git a/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py b/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py index 023855445b..e21cc6ec7b 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py +++ b/packages/opentelemetry-instrumentation-openai/tests/metrics/test_openai_metrics.py @@ -1,7 +1,12 @@ import pytest from openai import OpenAI -from opentelemetry.semconv._incubating.metrics import gen_ai_metrics as GenAIMetrics -from opentelemetry.semconv_ai import Meters, SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv._incubating.metrics import ( + gen_ai_metrics as GenAIMetrics, +) +from opentelemetry.semconv_ai import Meters from pydantic import BaseModel @@ -41,7 +46,7 @@ def test_chat_completion_metrics(instrument_legacy, reader, openai_client): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -106,7 +111,7 @@ class StructuredAnswer(BaseModel): for sm in rm.scope_metrics: for metric in sm.metrics: for data_point in metric.data.data_points: - model = data_point.attributes.get(SpanAttributes.GEN_AI_RESPONSE_MODEL) + model = data_point.attributes.get(GenAIAttributes.GEN_AI_RESPONSE_MODEL) if ( metric.name == Meters.LLM_TOKEN_USAGE and model == "gpt-4o-2024-08-06" @@ -165,7 +170,7 @@ def test_chat_streaming_metrics(instrument_legacy, reader, openai_client): if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -205,10 +210,10 @@ def test_chat_streaming_metrics(instrument_legacy, reader, openai_client): for data_point in metric.data.data_points: assert ( - data_point.attributes.get(SpanAttributes.GEN_AI_SYSTEM) == "openai" + data_point.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "openai" ) assert str( - data_point.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + data_point.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] ) in ("gpt-3.5-turbo", "gpt-3.5-turbo-0125", "gpt-4o-2024-08-06") assert data_point.attributes["gen_ai.operation.name"] == "chat" assert data_point.attributes["server.address"] != "" diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py index 9d3f797126..01c6f06b12 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_assistant.py @@ -61,31 +61,31 @@ def test_new_assistant( open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "user" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "system" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "user" assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"] == user_message ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 145 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 145 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 for message in messages.data: @@ -93,13 +93,13 @@ def test_new_assistant( continue assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}.content" ] == message.content[0].text.value ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.role" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}.role" ] == message.role ) @@ -158,17 +158,17 @@ def test_new_assistant_with_events_with_content( open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 145 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 145 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -239,16 +239,16 @@ def test_new_assistant_with_events_with_no_content( open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 145 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 145 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 155 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -316,9 +316,9 @@ def test_new_assistant_with_polling( assert open_ai_span.attributes["gen_ai.prompt.1.role"] == "system" assert open_ai_span.attributes["gen_ai.prompt.2.role"] == "user" assert open_ai_span.attributes["gen_ai.prompt.2.content"] == user_message - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 374 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 374 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 for message in messages.data: @@ -326,13 +326,13 @@ def test_new_assistant_with_polling( continue assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}.content" ] == message.content[0].text.value ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.role" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}.role" ] == message.role ) @@ -384,9 +384,9 @@ def test_new_assistant_with_polling_with_events_with_content( assert open_ai_span.attributes["llm.request.type"] == "chat" assert open_ai_span.attributes["gen_ai.request.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes["gen_ai.response.model"] == "gpt-4-turbo-preview" - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 374 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 374 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -458,9 +458,9 @@ def test_new_assistant_with_polling_with_events_with_no_content( assert open_ai_span.attributes["llm.request.type"] == "chat" assert open_ai_span.attributes["gen_ai.request.model"] == "gpt-4-turbo-preview" assert open_ai_span.attributes["gen_ai.response.model"] == "gpt-4-turbo-preview" - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 374 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 374 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 86 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -519,28 +519,28 @@ def test_existing_assistant( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "system" assert open_ai_span.attributes["gen_ai.prompt.2.role"] == "user" assert open_ai_span.attributes["gen_ai.prompt.2.content"] == user_message - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 639 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 639 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" completion_index = 0 for message in messages.data: @@ -548,13 +548,13 @@ def test_existing_assistant( continue assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}.content" ] == message.content[0].text.value ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.{completion_index}.role" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}.role" ] == message.role ) @@ -609,17 +609,17 @@ def test_existing_assistant_with_events_with_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 639 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 639 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 5 @@ -704,17 +704,17 @@ def test_existing_assistant_with_events_with_no_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 639 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 639 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 170 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 5 @@ -777,35 +777,35 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "system" - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 790 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 790 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" for idx, message in enumerate(assistant_messages): assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.content"] == message ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.role"] == "assistant" ) assert open_ai_span.attributes[f"gen_ai.response.{idx}.id"].startswith("msg") @@ -855,17 +855,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 790 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 790 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -958,17 +958,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 790 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 790 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 225 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 4 @@ -1027,34 +1027,34 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "You are a personal math tutor. Write and run code to answer math questions." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "system" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "system" assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.1.content") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.1.content") == "Please address the user as Jane Doe. The user has a premium account." ) - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "system" - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 364 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "system" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 364 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" for idx, message in enumerate(assistant_messages): assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.content"] == message ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.role"] == "assistant" ) assert open_ai_span.attributes[f"gen_ai.response.{idx}.id"].startswith("msg_") @@ -1104,17 +1104,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 364 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 364 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 3 @@ -1192,17 +1192,17 @@ def on_text_delta(self, delta, snapshot): open_ai_span = spans[0] assert open_ai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4-turbo-preview" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-4-turbo-preview" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 364 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "openai" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 364 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 88 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" logs = log_exporter.get_finished_logs() assert len(logs) == 3 diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py index 99bf395766..a957350f6b 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_azure.py @@ -28,10 +28,10 @@ def test_chat(instrument_legacy, span_exporter, log_exporter, azure_openai_clien ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://traceloop-stg.openai.azure.com/openai/" @@ -146,11 +146,11 @@ def test_chat_content_filtering( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == "FILTERED" ) assert ( @@ -164,7 +164,7 @@ def test_chat_content_filtering( ) content_filter_json = open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content_filter_results" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content_filter_results" ) assert len(content_filter_json) > 0 @@ -285,11 +285,11 @@ def test_prompt_content_filtering( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str ) error = json.loads( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] ) assert "innererror" in error @@ -329,11 +329,11 @@ def test_prompt_content_filtering_with_events_with_content( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str ) error = json.loads( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] ) assert "innererror" in error @@ -378,11 +378,11 @@ def test_prompt_content_filtering_with_events_with_no_content( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"], str ) error = json.loads( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_ERROR}"] ) assert "innererror" in error @@ -427,10 +427,10 @@ def test_chat_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://traceloop-stg.openai.azure.com/openai/" @@ -442,7 +442,7 @@ def test_chat_streaming( # prompt filter results prompt_filter_results = json.loads( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") ) assert prompt_filter_results[0]["prompt_index"] == 0 assert ( @@ -495,7 +495,7 @@ def test_chat_streaming_with_events_with_content( # prompt filter results prompt_filter_results = json.loads( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") ) assert prompt_filter_results[0]["prompt_index"] == 0 assert ( @@ -565,7 +565,7 @@ def test_chat_streaming_with_events_with_no_content( # prompt filter results prompt_filter_results = json.loads( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.{PROMPT_FILTER_KEY}") ) assert prompt_filter_results[0]["prompt_index"] == 0 assert ( @@ -614,10 +614,10 @@ async def test_chat_async_streaming( open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://traceloop-stg.openai.azure.com/openai/" @@ -625,8 +625,8 @@ async def test_chat_async_streaming( assert open_ai_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 36 - assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 8 - assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 + assert open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 8 + assert open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 events = open_ai_span.events assert len(events) == chunk_count @@ -670,8 +670,8 @@ async def test_chat_async_streaming_with_events_with_content( assert open_ai_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 36 - assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 8 - assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 + assert open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 8 + assert open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 events = open_ai_span.events assert len(events) == chunk_count @@ -733,8 +733,8 @@ async def test_chat_async_streaming_with_events_with_no_content( assert open_ai_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is True assert open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) == 36 - assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 8 - assert open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 + assert open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) == 8 + assert open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) == 28 events = open_ai_span.events assert len(events) == chunk_count diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py index c446ffefa8..d5ce59feda 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat.py @@ -34,10 +34,10 @@ def test_chat(instrument_legacy, span_exporter, log_exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -189,24 +189,24 @@ def test_chat_tool_calls(instrument_legacy, span_exporter, log_exporter, openai_ "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments" ] == '{"location": "San Francisco"}' ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == "The weather in San Francisco is 70 degrees and sunny." ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_call_id"] == "1" + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_call_id"] == "1" ) assert ( open_ai_span.attributes.get("gen_ai.response.id") @@ -254,7 +254,7 @@ def test_chat_tool_calls_with_events_with_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") @@ -332,7 +332,7 @@ def test_chat_tool_calls_with_events_with_no_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-9gKNZbUWSC4s2Uh2QfVV7PYiqWIuH" @@ -397,24 +397,24 @@ def test_chat_pydantic_based_tool_calls( ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( open_ai_span.attributes[ - f"{SpanAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.arguments" ] == '{"location": "San Francisco"}' ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == "The weather in San Francisco is 70 degrees and sunny." ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.tool_call_id"] == "1" + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_call_id"] == "1" ) assert ( open_ai_span.attributes.get("gen_ai.response.id") @@ -462,7 +462,7 @@ def test_chat_pydantic_based_tool_calls_with_events_with_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-9lvGJKrBUPeJjHi3KKSEbGfcfomOP" @@ -539,7 +539,7 @@ def test_chat_pydantic_based_tool_calls_with_events_with_no_content( ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-9lvGJKrBUPeJjHi3KKSEbGfcfomOP" @@ -588,10 +588,10 @@ def test_chat_streaming(instrument_legacy, span_exporter, log_exporter, openai_c ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -603,9 +603,9 @@ def test_chat_streaming(instrument_legacy, span_exporter, log_exporter, openai_c # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) - prompt_tokens = open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + prompt_tokens = open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert completion_tokens and prompt_tokens and total_tokens assert completion_tokens + prompt_tokens == total_tokens @@ -651,9 +651,9 @@ def test_chat_streaming_with_events_with_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) - prompt_tokens = open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + prompt_tokens = open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert completion_tokens and prompt_tokens and total_tokens assert completion_tokens + prompt_tokens == total_tokens @@ -718,9 +718,9 @@ def test_chat_streaming_with_events_with_no_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) - prompt_tokens = open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + prompt_tokens = open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert completion_tokens and prompt_tokens and total_tokens assert completion_tokens + prompt_tokens == total_tokens @@ -763,10 +763,10 @@ async def test_chat_async_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -778,9 +778,9 @@ async def test_chat_async_streaming( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) - prompt_tokens = open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + prompt_tokens = open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert completion_tokens and prompt_tokens and total_tokens assert completion_tokens + prompt_tokens == total_tokens @@ -827,9 +827,9 @@ async def test_chat_async_streaming_with_events_with_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) - prompt_tokens = open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + prompt_tokens = open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert completion_tokens and prompt_tokens and total_tokens assert completion_tokens + prompt_tokens == total_tokens @@ -893,9 +893,9 @@ async def test_chat_async_streaming_with_events_with_no_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) - prompt_tokens = open_ai_span.attributes.get(SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS) + prompt_tokens = open_ai_span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) total_tokens = open_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) assert completion_tokens and prompt_tokens and total_tokens assert completion_tokens + prompt_tokens == total_tokens @@ -1335,41 +1335,41 @@ def test_chat_history_message_dict(span_exporter, openai_client): first_span = spans[0] assert first_span.name == "openai.chat" assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + first_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] + first_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == first_user_message["role"] ) assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + first_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == first_response.choices[0].message.content ) assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" + first_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) second_span = spans[1] assert second_span.name == "openai.chat" assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == second_response.choices[0].message.content ) assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == first_response.choices[0].message.content ) - assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" + assert second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"] == second_user_message["content"] ) - assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "user" + assert second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "user" @pytest.mark.vcr @@ -1402,41 +1402,41 @@ def test_chat_history_message_pydantic(span_exporter, openai_client): first_span = spans[0] assert first_span.name == "openai.chat" assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + first_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] + first_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == first_user_message["role"] ) assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + first_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == first_response.choices[0].message.content ) assert ( - first_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" + first_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] == "assistant" ) second_span = spans[1] assert second_span.name == "openai.chat" assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == first_user_message["content"] ) assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == second_response.choices[0].message.content ) assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == first_response.choices[0].message.content ) - assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" + assert second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" assert ( - second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.content"] + second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"] == second_user_message["content"] ) - assert second_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.2.role"] == "user" + assert second_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "user" def test_chat_exception(instrument_legacy, span_exporter, openai_client): @@ -1454,7 +1454,7 @@ def test_chat_exception(instrument_legacy, span_exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( @@ -1492,7 +1492,7 @@ async def test_chat_async_exception(instrument_legacy, span_exporter, async_open ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py index 97b8d308d9..8e27c4182e 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_chat_parse.py @@ -1,5 +1,6 @@ import json import pytest +from pydantic import BaseModel from opentelemetry.sdk._logs import LogData from opentelemetry.semconv._incubating.attributes import ( event_attributes as EventAttributes, @@ -10,7 +11,6 @@ from opentelemetry.semconv_ai import SpanAttributes from opentelemetry.sdk.trace import Span from opentelemetry.trace import StatusCode -from pydantic import BaseModel class StructuredAnswer(BaseModel): @@ -33,14 +33,14 @@ def test_parsed_completion( "openai.chat", ] open_ai_span = spans[0] - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" ) assert open_ai_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( @@ -164,10 +164,10 @@ def test_parsed_refused_completion( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal" in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.refusal" in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.refusal"] == "I'm very sorry, but I can't assist with that request." ) assert ( @@ -200,7 +200,7 @@ def test_parsed_refused_completion_with_events_with_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGky8KFDbg6f5fF4qLtsBredIjZZh" @@ -243,7 +243,7 @@ def test_parsed_refused_completion_with_events_with_no_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGky8KFDbg6f5fF4qLtsBredIjZZh" @@ -281,14 +281,14 @@ async def test_async_parsed_completion( "openai.chat", ] open_ai_span = spans[0] - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" ) assert open_ai_span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( @@ -414,10 +414,10 @@ async def test_async_parsed_refused_completion( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal" in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.refusal" in open_ai_span.attributes assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.refusal"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.refusal"] == "I'm very sorry, but I can't assist with that request." ) assert ( @@ -451,7 +451,7 @@ async def test_async_parsed_refused_completion_with_events_with_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGkyFJGzZPUGAAEDJJuOS3idKvD3G" @@ -495,7 +495,7 @@ async def test_async_parsed_refused_completion_with_events_with_no_content( "openai.chat", ] open_ai_span = spans[0] - assert f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes + assert f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" not in open_ai_span.attributes assert ( open_ai_span.attributes.get("gen_ai.response.id") == "chatcmpl-AGkyFJGzZPUGAAEDJJuOS3idKvD3G" @@ -548,8 +548,8 @@ def test_parsed_completion_exception( assert span.name == "openai.chat" assert span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" assert span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about opentelemetry" - assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.role") == "user" + assert span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about opentelemetry" + assert span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.role") == "user" assert span.status.status_code == StatusCode.ERROR assert span.status.description.startswith("Error code: 401") @@ -583,8 +583,8 @@ async def test_async_parsed_completion_exception( assert span.name == "openai.chat" assert span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" assert span.attributes.get(SpanAttributes.LLM_IS_STREAMING) is False - assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about opentelemetry" - assert span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.role") == "user" + assert span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") == "Tell me a joke about opentelemetry" + assert span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.role") == "user" assert span.status.status_code == StatusCode.ERROR assert span.status.description.startswith("Error code: 401") diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py index 8f2eba9194..4691bfbab2 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py @@ -29,10 +29,10 @@ def test_completion(instrument_legacy, span_exporter, log_exporter, openai_clien ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -145,10 +145,10 @@ async def test_async_completion( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get("gen_ai.response.id") == "cmpl-8wq43c8U5ZZCQBX5lrSpsANwcd3OF" @@ -253,10 +253,10 @@ def test_completion_langchain_style( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get("gen_ai.response.id") == "cmpl-8wq43QD6R2WqfxXLpYsRvSAIn9LB9" @@ -368,11 +368,11 @@ def test_completion_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) assert open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ) assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) @@ -381,10 +381,10 @@ def test_completion_streaming( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) total_tokens = open_ai_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -438,10 +438,10 @@ def test_completion_streaming_with_events_with_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) total_tokens = open_ai_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -511,10 +511,10 @@ def test_completion_streaming_with_events_with_no_content( # check token usage attributes for stream completion_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS ) prompt_tokens = open_ai_span.attributes.get( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS ) total_tokens = open_ai_span.attributes.get( SpanAttributes.LLM_USAGE_TOTAL_TOKENS @@ -564,10 +564,10 @@ async def test_async_completion_streaming( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) == "https://api.openai.com/v1/" @@ -935,7 +935,7 @@ def test_completion_exception(instrument_legacy, span_exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) assert open_ai_span.status.status_code == StatusCode.ERROR @@ -967,7 +967,7 @@ async def test_async_completion_exception(instrument_legacy, span_exporter, asyn ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Tell me a joke about opentelemetry" ) assert open_ai_span.status.status_code == StatusCode.ERROR diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py index 5723a091c6..7db0155a85 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_embeddings.py @@ -29,14 +29,14 @@ def test_embeddings(instrument_legacy, span_exporter, log_exporter, openai_clien ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -63,10 +63,10 @@ def test_embeddings_with_events_with_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -107,10 +107,10 @@ def test_embeddings_with_events_with_no_content( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -142,15 +142,15 @@ def test_embeddings_with_raw_response( ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -180,10 +180,10 @@ def test_embeddings_with_raw_response_with_events_with_content( open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -227,10 +227,10 @@ def test_embeddings_with_raw_response_with_events_with_no_content( open_ai_span = spans[0] assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-embedding-ada-002" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -274,11 +274,11 @@ def test_azure_openai_embeddings(instrument_legacy, span_exporter, log_exporter) ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) - assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "embedding" - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "embedding" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == f"https://{azure_resource}.openai.azure.com/openai/deployments/{azure_deployment}/" @@ -318,8 +318,8 @@ def test_azure_openai_embeddings_with_events_with_content( "openai.embeddings", ] open_ai_span = spans[0] - assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "embedding" - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "embedding" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == f"https://{azure_resource}.openai.azure.com/openai/deployments/{azure_deployment}/" @@ -373,8 +373,8 @@ def test_azure_openai_embeddings_with_events_with_no_content( "openai.embeddings", ] open_ai_span = spans[0] - assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "embedding" - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "embedding" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 8 assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == f"https://{azure_resource}.openai.azure.com/openai/deployments/{azure_deployment}/" diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py index 12df5ffe36..693930b156 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_functions.py @@ -65,7 +65,7 @@ def test_open_ai_function_calls( spans = span_exporter.get_finished_spans() open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "What's the weather like in Boston?" ) assert ( @@ -77,7 +77,7 @@ def test_open_ai_function_calls( == "Get the current weather in a given location" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( @@ -244,7 +244,7 @@ def test_open_ai_function_calls_tools( spans = span_exporter.get_finished_spans() open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "What's the weather like in Boston?" ) assert ( @@ -256,11 +256,11 @@ def test_open_ai_function_calls_tools( == "Get the current weather" ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name"] == "get_current_weather" ) assert ( @@ -396,7 +396,7 @@ async def test_open_ai_function_calls_tools_streaming( open_ai_span = spans[0] assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( @@ -404,18 +404,18 @@ async def test_open_ai_function_calls_tools_streaming( == "get_current_weather" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.finish_reason") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.finish_reason") == "tool_calls" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ) == '{"location":"San Francisco, CA"}' ) @@ -567,40 +567,40 @@ def test_open_ai_function_calls_tools_parallel( == "get_current_weather" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.finish_reason") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.finish_reason") == "tool_calls" ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ) == '{"location": "San Francisco"}' ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"], + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" ) == '{"location": "Boston"}' ) @@ -761,40 +761,40 @@ async def test_open_ai_function_calls_tools_streaming_parallel( == "get_current_weather" ) assert ( - open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.finish_reason") + open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.finish_reason") == "tool_calls" ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.arguments" ) == '{"location": "San Francisco"}' ) assert isinstance( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"], + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.id"], str, ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.name" ) == "get_current_weather" ) assert ( open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.1.arguments" ) == '{"location": "Boston"}' ) diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py index 6825b1c50f..157862f3cd 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_vision.py @@ -42,7 +42,7 @@ def test_vision(instrument_legacy, span_exporter, log_exporter, openai_client): ] open_ai_span = spans[0] assert json.loads( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "What is in this image?"}, { @@ -51,7 +51,7 @@ def test_vision(instrument_legacy, span_exporter, log_exporter, openai_client): }, ] - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" @@ -228,7 +228,7 @@ def test_vision_base64(instrument_legacy, span_exporter, log_exporter, openai_cl ] open_ai_span = spans[0] assert json.loads( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] ) == [ {"type": "text", "text": "What is in this image?"}, { @@ -237,7 +237,7 @@ def test_vision_base64(instrument_legacy, span_exporter, log_exporter, openai_cl }, ] - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert ( open_ai_span.attributes[SpanAttributes.LLM_OPENAI_API_BASE] == "https://api.openai.com/v1/" diff --git a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py index 16a68ae52c..20898987e4 100644 --- a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py +++ b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/__init__.py @@ -24,6 +24,9 @@ _SUPPRESS_INSTRUMENTATION_KEY, unwrap, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import LLMRequestTypeValues, SpanAttributes from opentelemetry.trace import SpanKind, get_tracer from opentelemetry.trace.status import Status, StatusCode @@ -123,7 +126,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Replicate", + GenAIAttributes.GEN_AI_SYSTEM: "Replicate", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py index 7bd9a5a18d..a9eba62fea 100644 --- a/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py +++ b/packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/span_utils.py @@ -2,7 +2,9 @@ dont_throw, should_send_prompts, ) -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) def _set_span_attribute(span, name, value): @@ -20,7 +22,7 @@ def set_input_attributes(span, args, kwargs): input_attribute = kwargs.get("input") if should_send_prompts(): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", input_attribute.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", input_attribute.get("prompt") ) @@ -30,21 +32,21 @@ def set_model_input_attributes(span, args, kwargs): return if args is not None and len(args) > 0: - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, args[0]) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, args[0]) elif kwargs.get("version"): _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("version").id + span, GenAIAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("version").id ) else: - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, "unknown") + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, "unknown") input_attribute = kwargs.get("input") _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, input_attribute.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, input_attribute.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, input_attribute.get("top_p") + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, input_attribute.get("top_p") ) @@ -53,9 +55,9 @@ def set_response_attributes(span, response): if should_send_prompts(): if isinstance(response, list): for index, item in enumerate(response): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute(span, f"{prefix}.content", item) elif isinstance(response, str): _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", response + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response ) diff --git a/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py b/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py index f18454ec3e..00d9ec4b29 100644 --- a/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py +++ b/packages/opentelemetry-instrumentation-sagemaker/opentelemetry/instrumentation/sagemaker/span_utils.py @@ -1,6 +1,9 @@ import json from opentelemetry.instrumentation.sagemaker.utils import should_send_prompts +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SpanAttributes, ) @@ -39,7 +42,7 @@ def set_call_span_attributes(span, kwargs, response): return endpoint_name = kwargs.get("EndpointName") - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, endpoint_name) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, endpoint_name) def set_call_request_attributes(span, kwargs): diff --git a/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py b/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py index 87bc66a802..3ec6546104 100644 --- a/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py +++ b/packages/opentelemetry-instrumentation-sagemaker/tests/test_invocation.py @@ -43,7 +43,7 @@ def test_sagemaker_completion_string_content_legacy( spans = span_exporter.get_finished_spans() meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name + assert meta_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name assert meta_span.attributes[SpanAttributes.TRACELOOP_ENTITY_INPUT] == body logs = log_exporter.get_finished_logs() @@ -84,7 +84,7 @@ def test_sagemaker_completion_string_content_with_events_with_content( spans = span_exporter.get_finished_spans() meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name + assert meta_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name logs = log_exporter.get_finished_logs() assert len(logs) == 2 @@ -136,7 +136,7 @@ def test_sagemaker_completion_string_content_with_events_with_no_content( spans = span_exporter.get_finished_spans() meta_span = spans[0] - assert meta_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name + assert meta_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == endpoint_name logs = log_exporter.get_finished_logs() assert len(logs) == 2 diff --git a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py index 5d3345b025..d4acd50efb 100644 --- a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py +++ b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/__init__.py @@ -23,6 +23,9 @@ _SUPPRESS_INSTRUMENTATION_KEY, unwrap, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -113,7 +116,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "TogetherAI", + GenAIAttributes.GEN_AI_SYSTEM: "TogetherAI", SpanAttributes.LLM_REQUEST_TYPE: llm_request_type.value, }, ) diff --git a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py index 03daae380e..7b41e33712 100644 --- a/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py +++ b/packages/opentelemetry-instrumentation-together/opentelemetry/instrumentation/together/span_utils.py @@ -1,6 +1,6 @@ from opentelemetry.instrumentation.together.utils import dont_throw, should_send_prompts -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( - GEN_AI_RESPONSE_ID, +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, ) from opentelemetry.semconv_ai import ( LLMRequestTypeValues, @@ -22,22 +22,22 @@ def set_prompt_attributes(span, llm_request_type, kwargs): if should_send_prompts(): if llm_request_type == LLMRequestTypeValues.CHAT: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") for index, message in enumerate(kwargs.get("messages")): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.content", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.content", message.get("content"), ) _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.role", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.role", message.get("role"), ) elif llm_request_type == LLMRequestTypeValues.COMPLETION: - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_PROMPT}.0.role", "user") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.role", "user") _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.content", kwargs.get("prompt") ) @@ -46,7 +46,7 @@ def set_model_prompt_attributes(span, kwargs): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, kwargs.get("model")) _set_span_attribute( span, SpanAttributes.LLM_IS_STREAMING, @@ -63,15 +63,15 @@ def set_completion_attributes(span, llm_request_type, response): if llm_request_type == LLMRequestTypeValues.COMPLETION: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", response.choices[0].text, ) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant" + span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant" ) elif llm_request_type == LLMRequestTypeValues.CHAT: index = 0 - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" _set_span_attribute( span, f"{prefix}.content", response.choices[0].message.content ) @@ -85,8 +85,8 @@ def set_model_completion_attributes(span, response): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, response.model) - _set_span_attribute(span, GEN_AI_RESPONSE_ID, response.id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, response.model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, response.id) usage_data = response.usage input_tokens = getattr(usage_data, "prompt_tokens", 0) @@ -99,11 +99,11 @@ def set_model_completion_attributes(span, response): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, input_tokens, ) diff --git a/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py b/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py index 16e4dc2763..6a1cbbc660 100644 --- a/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py +++ b/packages/opentelemetry-instrumentation-transformers/opentelemetry/instrumentation/transformers/span_utils.py @@ -2,6 +2,9 @@ dont_throw, should_send_prompts, ) +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SpanAttributes, ) @@ -35,20 +38,20 @@ def set_model_input_attributes(span, instance): forward_params = instance._forward_params _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MODEL, instance.model.config.name_or_path + span, GenAIAttributes.GEN_AI_REQUEST_MODEL, instance.model.config.name_or_path ) _set_span_attribute( - span, SpanAttributes.GEN_AI_SYSTEM, instance.model.config.model_type + span, GenAIAttributes.GEN_AI_SYSTEM, instance.model.config.model_type ) _set_span_attribute(span, SpanAttributes.LLM_REQUEST_TYPE, "completion") _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, forward_params.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, forward_params.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, forward_params.get("top_p") + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, forward_params.get("top_p") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, forward_params.get("max_length") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, forward_params.get("max_length") ) _set_span_attribute( span, @@ -69,7 +72,7 @@ def _set_span_completions(span, completions): return for i, completion in enumerate(completions): - prefix = f"{SpanAttributes.GEN_AI_COMPLETION}.{i}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}" _set_span_attribute(span, f"{prefix}.content", completion.get("generated_text")) @@ -81,5 +84,5 @@ def _set_span_prompts(span, messages): messages = [messages] for i, msg in enumerate(messages): - prefix = f"{SpanAttributes.GEN_AI_PROMPT}.{i}" + prefix = f"{GenAIAttributes.GEN_AI_PROMPT}.{i}" _set_span_attribute(span, f"{prefix}.content", msg) diff --git a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py index 8a69d444cd..a7f8e986ee 100644 --- a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py +++ b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/__init__.py @@ -21,6 +21,9 @@ ) from opentelemetry.instrumentation.vertexai.utils import dont_throw, should_emit_events from opentelemetry.instrumentation.vertexai.version import __version__ +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -229,7 +232,7 @@ async def _awrap(tracer, event_logger, to_wrap, wrapped, instance, args, kwargs) name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Google", + GenAIAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -273,7 +276,7 @@ def _wrap(tracer, event_logger, to_wrap, wrapped, instance, args, kwargs): name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Google", + GenAIAttributes.GEN_AI_SYSTEM: "Google", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py index cb7ce2782f..a608aaea1a 100644 --- a/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py +++ b/packages/opentelemetry-instrumentation-vertexai/opentelemetry/instrumentation/vertexai/span_utils.py @@ -1,4 +1,7 @@ from opentelemetry.instrumentation.vertexai.utils import dont_throw, should_send_prompts +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes @@ -24,7 +27,7 @@ def set_input_attributes(span, args): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.user", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", prompt, ) @@ -33,18 +36,18 @@ def set_input_attributes(span, args): def set_model_input_attributes(span, kwargs, llm_model): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, llm_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, llm_model) _set_span_attribute( - span, f"{SpanAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") + span, f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", kwargs.get("prompt") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") + span, GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, kwargs.get("temperature") ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") + span, GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get("max_output_tokens") ) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_TOP_K, kwargs.get("top_k")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, kwargs.get("top_p")) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_TOP_K, kwargs.get("top_k")) _set_span_attribute( span, SpanAttributes.LLM_PRESENCE_PENALTY, kwargs.get("presence_penalty") ) @@ -57,10 +60,10 @@ def set_model_input_attributes(span, kwargs, llm_model): def set_response_attributes(span, llm_model, generation_text): if not span.is_recording() or not should_send_prompts(): return - _set_span_attribute(span, f"{SpanAttributes.GEN_AI_COMPLETION}.0.role", "assistant") + _set_span_attribute(span, f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role", "assistant") _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", generation_text, ) @@ -69,7 +72,7 @@ def set_response_attributes(span, llm_model, generation_text): def set_model_response_attributes(span, llm_model, token_usage): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, llm_model) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, llm_model) if token_usage: _set_span_attribute( @@ -79,11 +82,11 @@ def set_model_response_attributes(span, llm_model, token_usage): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, token_usage.candidates_token_count, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, token_usage.prompt_token_count, ) diff --git a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py index 23c24e9e17..d8252939f5 100644 --- a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py +++ b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_bison.py @@ -9,7 +9,6 @@ from opentelemetry.semconv._incubating.attributes import ( gen_ai_attributes as GenAIAttributes, ) -from opentelemetry.semconv_ai import SpanAttributes from vertexai.language_models import ChatModel, InputOutputTextPair, TextGenerationModel vertexai.init() @@ -38,17 +37,17 @@ def test_vertexai_predict(instrument_legacy, span_exporter, log_exporter): vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison@001" + vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-bison@001" ) assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + in vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert ( - vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -81,17 +80,17 @@ async def async_predict_text() -> str: vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison@001" + vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-bison@001" ) assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + in vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert ( - vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -118,16 +117,16 @@ def test_vertexai_stream(instrument_legacy, span_exporter, log_exporter): ] vertexai_span = spans[0] - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison" + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-bison" assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + in vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert vertexai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) @@ -158,16 +157,16 @@ async def async_streaming_prediction() -> list: ] vertexai_span = spans[0] - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "text-bison" + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "text-bison" assert ( "Give me ten interview questions for the role of program manager." - in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + in vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.8 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert vertexai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) @@ -204,17 +203,17 @@ def test_vertexai_chat(instrument_legacy, span_exporter, log_exporter): vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "chat-bison@001" + vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "chat-bison@001" ) assert ( "How many planets are there in the solar system?" - in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + in vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] ) - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert ( - vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response ) @@ -254,14 +253,14 @@ def test_vertexai_chat_stream(instrument_legacy, span_exporter, log_exporter): vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "chat-bison@001" + vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "chat-bison@001" ) - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.8 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 - assert vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_TOP_K] == 40 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_P] == 0.95 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.8 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 256 + assert vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_TOP_K] == 40 assert vertexai_span.attributes[ - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ] == "".join(response) diff --git a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py index f52e532a45..0ae04b595c 100644 --- a/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py +++ b/packages/opentelemetry-instrumentation-vertexai/tests/disabled_test_gemini.py @@ -32,10 +32,10 @@ def test_vertexai_generate_content(instrument_legacy, span_exporter, log_exporte vertexai_span = spans[0] assert ( "what is shown in this image?" - in vertexai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + in vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] ) assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gemini-2.0-flash-lite" ) assert ( @@ -43,15 +43,15 @@ def test_vertexai_generate_content(instrument_legacy, span_exporter, log_exporte == response._raw_response.usage_metadata.total_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + vertexai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response._raw_response.usage_metadata.prompt_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + vertexai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response._raw_response.usage_metadata.candidates_token_count ) assert ( - vertexai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + vertexai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response.text ) @@ -84,7 +84,7 @@ def test_vertexai_generate_content_with_events_with_content( vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gemini-2.0-flash-lite" ) assert ( @@ -92,11 +92,11 @@ def test_vertexai_generate_content_with_events_with_content( == response._raw_response.usage_metadata.total_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + vertexai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response._raw_response.usage_metadata.prompt_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + vertexai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response._raw_response.usage_metadata.candidates_token_count ) @@ -144,7 +144,7 @@ def test_vertexai_generate_content_with_events_with_no_content( vertexai_span = spans[0] assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] + vertexai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gemini-2.0-flash-lite" ) assert ( @@ -152,11 +152,11 @@ def test_vertexai_generate_content_with_events_with_no_content( == response._raw_response.usage_metadata.total_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] + vertexai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == response._raw_response.usage_metadata.prompt_token_count ) assert ( - vertexai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + vertexai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == response._raw_response.usage_metadata.candidates_token_count ) diff --git a/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py b/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py index 337b8e90c5..68764d9312 100644 --- a/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py +++ b/packages/opentelemetry-instrumentation-watsonx/opentelemetry/instrumentation/watsonx/__init__.py @@ -25,6 +25,9 @@ ) from opentelemetry.instrumentation.watsonx.version import __version__ from opentelemetry.metrics import Counter, Histogram, get_meter +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, @@ -132,13 +135,13 @@ def _set_input_attributes(span, instance, kwargs): for index, input in enumerate(prompt): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.{index}.user", + f"{GenAIAttributes.GEN_AI_PROMPT}.{index}.user", input, ) else: _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_PROMPT}.0.user", + f"{GenAIAttributes.GEN_AI_PROMPT}.0.user", prompt, ) @@ -147,7 +150,7 @@ def set_model_input_attributes(span, instance): if not span.is_recording(): return - _set_span_attribute(span, SpanAttributes.GEN_AI_REQUEST_MODEL, instance.model_id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_REQUEST_MODEL, instance.model_id) # Set other attributes modelParameters = instance.params if modelParameters is not None: @@ -172,7 +175,7 @@ def set_model_input_attributes(span, instance): modelParameters.get("min_new_tokens", None), ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_K, modelParameters.get("top_k", None) + span, GenAIAttributes.GEN_AI_REQUEST_TOP_K, modelParameters.get("top_k", None) ) _set_span_attribute( span, @@ -181,11 +184,11 @@ def set_model_input_attributes(span, instance): ) _set_span_attribute( span, - SpanAttributes.GEN_AI_REQUEST_TEMPERATURE, + GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, modelParameters.get("temperature", None), ) _set_span_attribute( - span, SpanAttributes.GEN_AI_REQUEST_TOP_P, modelParameters.get("top_p", None) + span, GenAIAttributes.GEN_AI_REQUEST_TOP_P, modelParameters.get("top_p", None) ) @@ -194,7 +197,7 @@ def _set_stream_response_attributes(span, stream_response): return _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.0.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content", stream_response.get("generated_text"), ) @@ -203,16 +206,16 @@ def _set_model_stream_response_attributes(span, stream_response): if not span.is_recording(): return _set_span_attribute( - span, SpanAttributes.GEN_AI_RESPONSE_MODEL, stream_response.get("model_id") + span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, stream_response.get("model_id") ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, stream_response.get("input_token_count"), ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, stream_response.get("generated_token_count"), ) total_token = stream_response.get("input_token_count") + stream_response.get( @@ -235,14 +238,14 @@ def _set_completion_content_attributes( if should_send_prompts(): _set_span_attribute( span, - f"{SpanAttributes.GEN_AI_COMPLETION}.{index}.content", + f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}.content", results[0]["generated_text"], ) model_id = response.get("model_id") if response_counter: attributes_with_reason = { - SpanAttributes.GEN_AI_RESPONSE_MODEL: model_id, + GenAIAttributes.GEN_AI_RESPONSE_MODEL: model_id, SpanAttributes.LLM_RESPONSE_STOP_REASON: results[0]["stop_reason"], } response_counter.add(1, attributes=attributes_with_reason) @@ -289,7 +292,7 @@ def _set_response_attributes( if model_id is None: return - _set_span_attribute(span, SpanAttributes.GEN_AI_RESPONSE_MODEL, model_id) + _set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, model_id) shared_attributes = _metric_shared_attributes(response_model=model_id) @@ -298,12 +301,12 @@ def _set_response_attributes( if token_histogram: attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", } token_histogram.record(completion_token, attributes=attributes_with_token_type) attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", } token_histogram.record(prompt_token, attributes=attributes_with_token_type) @@ -321,12 +324,12 @@ def set_model_response_attributes( if (prompt_token + completion_token) != 0: _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_token, ) _set_span_attribute( span, - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_token, ) _set_span_attribute( @@ -409,14 +412,14 @@ def _build_and_set_stream_response( if token_histogram: attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "output", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "output", } token_histogram.record( stream_generated_token_count, attributes=attributes_with_token_type ) attributes_with_token_type = { **shared_attributes, - SpanAttributes.GEN_AI_TOKEN_TYPE: "input", + GenAIAttributes.GEN_AI_TOKEN_TYPE: "input", } token_histogram.record( stream_input_token_count, attributes=attributes_with_token_type @@ -436,8 +439,8 @@ def _build_and_set_stream_response( def _metric_shared_attributes(response_model: str, is_streaming: bool = False): return { - SpanAttributes.GEN_AI_RESPONSE_MODEL: response_model, - SpanAttributes.GEN_AI_SYSTEM: "watsonx", + GenAIAttributes.GEN_AI_RESPONSE_MODEL: response_model, + GenAIAttributes.GEN_AI_SYSTEM: "watsonx", "stream": is_streaming, } @@ -561,7 +564,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - SpanAttributes.GEN_AI_SYSTEM: "Watsonx", + GenAIAttributes.GEN_AI_SYSTEM: "Watsonx", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py b/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py index a06c5f764c..7bf8a4429b 100644 --- a/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py +++ b/packages/opentelemetry-instrumentation-watsonx/tests/metrics/test_watsonx_metrics.py @@ -1,7 +1,10 @@ import sys import pytest -from opentelemetry.semconv_ai import Meters, SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv_ai import Meters @pytest.mark.skipif( @@ -31,7 +34,7 @@ def test_generate_metrics(metrics_test_context_legacy, watson_ai_model, log_expo if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -52,7 +55,7 @@ def test_generate_metrics(metrics_test_context_legacy, watson_ai_model, log_expo ) assert ( - metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] + metric.data.data_points[0].attributes[GenAIAttributes.GEN_AI_SYSTEM] == "watsonx" ) @@ -100,7 +103,7 @@ def test_generate_stream_metrics( if metric.name == Meters.LLM_TOKEN_USAGE: found_token_metric = True for data_point in metric.data.data_points: - assert data_point.attributes[SpanAttributes.GEN_AI_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -121,7 +124,7 @@ def test_generate_stream_metrics( ) assert ( - metric.data.data_points[0].attributes[SpanAttributes.GEN_AI_SYSTEM] + metric.data.data_points[0].attributes[GenAIAttributes.GEN_AI_SYSTEM] == "watsonx" ) diff --git a/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py b/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py index 656c9c1146..14ba2affcd 100644 --- a/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py +++ b/packages/opentelemetry-instrumentation-watsonx/tests/traces/test_generate.py @@ -23,11 +23,11 @@ def test_generate(exporter_legacy, watson_ai_model, log_exporter): spans = exporter_legacy.get_finished_spans() watsonx_ai_span = spans[1] assert ( - watsonx_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + watsonx_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "What is 1 + 1?" ) - assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" - assert watsonx_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert watsonx_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -49,7 +49,7 @@ def test_generate_with_events_with_content( response = watson_ai_model.generate(prompt="What is 1 + 1?") spans = exporter_with_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -85,7 +85,7 @@ def test_generate_with_with_events_no_content( response = watson_ai_model.generate(prompt="What is 1 + 1?") spans = exporter_with_no_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -120,12 +120,12 @@ def test_generate_text_stream(exporter_legacy, watson_ai_model, log_exporter): spans = exporter_legacy.get_finished_spans() watsonx_ai_span = spans[1] assert ( - watsonx_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.user"] + watsonx_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.user"] == "Write an epigram about the sun" ) - assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "Watsonx" assert ( - watsonx_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + watsonx_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == generated_text ) assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) @@ -154,7 +154,7 @@ def test_generate_text_stream_with_events_with_content( generated_text += chunk spans = exporter_with_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() @@ -195,7 +195,7 @@ def test_generate_text_stream_with_events_with_no_content( generated_text += chunk spans = exporter_with_no_content.get_finished_spans() watsonx_ai_span = spans[1] - assert watsonx_ai_span.attributes[SpanAttributes.GEN_AI_SYSTEM] == "Watsonx" + assert watsonx_ai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "Watsonx" assert watsonx_ai_span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) logs = log_exporter.get_finished_logs() diff --git a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py index f9dbee646c..88b8aa9fca 100644 --- a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py +++ b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py @@ -1,5 +1,7 @@ from enum import Enum -import opentelemetry.semconv._incubating.attributes.gen_ai_attributes as otel_gen_ai_attributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY = "suppress_language_model_instrumentation" @@ -37,40 +39,40 @@ class Meters: class SpanAttributes: # OpenTelemetry Semantic Conventions for Gen AI - # Refer to https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-spans.md - GEN_AI_AGENT_DESCRIPTION=otel_gen_ai_attributes.GEN_AI_AGENT_DESCRIPTION - GEN_AI_AGENT_ID= otel_gen_ai_attributes.GEN_AI_AGENT_ID - GEN_AI_AGENT_NAME= otel_gen_ai_attributes.GEN_AI_AGENT_NAME - GEN_AI_COMPLETION=otel_gen_ai_attributes.GEN_AI_COMPLETION - GEN_AI_CONVERSATION_ID=otel_gen_ai_attributes.GEN_AI_CONVERSATION_ID - GEN_AI_DATA_SOURCE_ID=otel_gen_ai_attributes.GEN_AI_DATA_SOURCE_ID - GEN_AI_OPENAI_REQUEST_SERVICE_TIER=otel_gen_ai_attributes.GEN_AI_OPENAI_REQUEST_SERVICE_TIER - GEN_AI_OPENAI_RESPONSE_SERVICE_TIER=otel_gen_ai_attributes.GEN_AI_OPENAI_RESPONSE_SERVICE_TIER - GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT=otel_gen_ai_attributes.GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT - GEN_AI_OUTPUT_TYPE=otel_gen_ai_attributes.GEN_AI_OUTPUT_TYPE - GEN_AI_PROMPT=otel_gen_ai_attributes.GEN_AI_PROMPT - GEN_AI_REQUEST_CHOICE_COUNT=otel_gen_ai_attributes.GEN_AI_REQUEST_CHOICE_COUNT - GEN_AI_REQUEST_ENCODING_FORMATS= otel_gen_ai_attributes.GEN_AI_REQUEST_ENCODING_FORMATS - GEN_AI_REQUEST_FREQUENCY_PENALTY= otel_gen_ai_attributes.GEN_AI_REQUEST_FREQUENCY_PENALTY - GEN_AI_REQUEST_MAX_TOKENS=otel_gen_ai_attributes.GEN_AI_REQUEST_MAX_TOKENS - GEN_AI_REQUEST_MODEL=otel_gen_ai_attributes.GEN_AI_REQUEST_MODEL - GEN_AI_REQUEST_PRESENCE_PENALTY=otel_gen_ai_attributes.GEN_AI_REQUEST_PRESENCE_PENALTY - GEN_AI_REQUEST_SEED=otel_gen_ai_attributes.GEN_AI_REQUEST_SEED - GEN_AI_REQUEST_STOP_SEQUENCES=otel_gen_ai_attributes.GEN_AI_REQUEST_STOP_SEQUENCES - GEN_AI_REQUEST_TEMPERATURE=otel_gen_ai_attributes.GEN_AI_REQUEST_TEMPERATURE - GEN_AI_REQUEST_TOP_K=otel_gen_ai_attributes.GEN_AI_REQUEST_TOP_K - GEN_AI_REQUEST_TOP_P=otel_gen_ai_attributes.GEN_AI_REQUEST_TOP_P + GEN_AI_AGENT_DESCRIPTION=GenAIAttributes.GEN_AI_AGENT_DESCRIPTION + GEN_AI_AGENT_ID= GenAIAttributes.GEN_AI_AGENT_ID + GEN_AI_AGENT_NAME= GenAIAttributes.GEN_AI_AGENT_NAME + GEN_AI_COMPLETION=GenAIAttributes.GEN_AI_COMPLETION + GEN_AI_CONVERSATION_ID=GenAIAttributes.GEN_AI_CONVERSATION_ID + GEN_AI_DATA_SOURCE_ID=GenAIAttributes.GEN_AI_DATA_SOURCE_ID + GEN_AI_OPENAI_REQUEST_SERVICE_TIER=GenAIAttributes.GEN_AI_OPENAI_REQUEST_SERVICE_TIER + GEN_AI_OPENAI_RESPONSE_SERVICE_TIER=GenAIAttributes.GEN_AI_OPENAI_RESPONSE_SERVICE_TIER + GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT=GenAIAttributes.GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT + GEN_AI_OUTPUT_TYPE=GenAIAttributes.GEN_AI_OUTPUT_TYPE + GEN_AI_PROMPT=GenAIAttributes.GEN_AI_PROMPT + GEN_AI_REQUEST_CHOICE_COUNT=GenAIAttributes.GEN_AI_REQUEST_CHOICE_COUNT + GEN_AI_REQUEST_ENCODING_FORMATS= GenAIAttributes.GEN_AI_REQUEST_ENCODING_FORMATS + GEN_AI_REQUEST_FREQUENCY_PENALTY= GenAIAttributes.GEN_AI_REQUEST_FREQUENCY_PENALTY + GEN_AI_REQUEST_MAX_TOKENS=GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS + GEN_AI_REQUEST_MODEL=GenAIAttributes.GEN_AI_REQUEST_MODEL + GEN_AI_REQUEST_PRESENCE_PENALTY=GenAIAttributes.GEN_AI_REQUEST_PRESENCE_PENALTY + GEN_AI_REQUEST_SEED=GenAIAttributes.GEN_AI_REQUEST_SEED + GEN_AI_REQUEST_STOP_SEQUENCES=GenAIAttributes.GEN_AI_REQUEST_STOP_SEQUENCES + GEN_AI_REQUEST_TEMPERATURE=GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE + GEN_AI_REQUEST_TOP_K=GenAIAttributes.GEN_AI_REQUEST_TOP_K + GEN_AI_REQUEST_TOP_P=GenAIAttributes.GEN_AI_REQUEST_TOP_P GEN_AI_REQUEST_STRUCTURED_OUTPUT_SCHEMA = "gen_ai.request.structured_output_schema" - GEN_AI_RESPONSE_FINISH_REASONS=otel_gen_ai_attributes.GEN_AI_RESPONSE_FINISH_REASONS - GEN_AI_RESPONSE_ID=otel_gen_ai_attributes.GEN_AI_RESPONSE_ID - GEN_AI_RESPONSE_MODEL=otel_gen_ai_attributes.GEN_AI_RESPONSE_MODEL - GEN_AI_SYSTEM=otel_gen_ai_attributes.GEN_AI_SYSTEM - GEN_AI_TOKEN_TYPE=otel_gen_ai_attributes.GEN_AI_TOKEN_TYPE - GEN_AI_TOOL_CALL_ID=otel_gen_ai_attributes.GEN_AI_TOOL_CALL_ID - GEN_AI_TOOL_DESCRIPTION=otel_gen_ai_attributes.GEN_AI_TOOL_DESCRIPTION - GEN_AI_TOOL_NAME=otel_gen_ai_attributes.GEN_AI_TOOL_NAME - GEN_AI_TOOL_TYPE=otel_gen_ai_attributes.GEN_AI_TOOL_TYPE - GEN_AI_USAGE_INPUT_TOKENS=otel_gen_ai_attributes.GEN_AI_USAGE_INPUT_TOKENS - GEN_AI_USAGE_OUTPUT_TOKENS=otel_gen_ai_attributes.GEN_AI_USAGE_OUTPUT_TOKENS + GEN_AI_RESPONSE_FINISH_REASONS=GenAIAttributes.GEN_AI_RESPONSE_FINISH_REASONS + GEN_AI_RESPONSE_ID=GenAIAttributes.GEN_AI_RESPONSE_ID + GEN_AI_RESPONSE_MODEL=GenAIAttributes.GEN_AI_RESPONSE_MODEL + GEN_AI_SYSTEM=GenAIAttributes.GEN_AI_SYSTEM + GEN_AI_TOKEN_TYPE=GenAIAttributes.GEN_AI_TOKEN_TYPE + GEN_AI_TOOL_CALL_ID=GenAIAttributes.GEN_AI_TOOL_CALL_ID + GEN_AI_TOOL_DESCRIPTION=GenAIAttributes.GEN_AI_TOOL_DESCRIPTION + GEN_AI_TOOL_NAME=GenAIAttributes.GEN_AI_TOOL_NAME + GEN_AI_TOOL_TYPE=GenAIAttributes.GEN_AI_TOOL_TYPE + GEN_AI_USAGE_INPUT_TOKENS=GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS + GEN_AI_USAGE_OUTPUT_TOKENS=GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS = "gen_ai.usage.cache_creation_input_tokens" GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = "gen_ai.usage.cache_read_input_tokens" diff --git a/packages/opentelemetry-semantic-conventions-ai/poetry.lock b/packages/opentelemetry-semantic-conventions-ai/poetry.lock index dec2a76d43..d3c695e0d7 100644 --- a/packages/opentelemetry-semantic-conventions-ai/poetry.lock +++ b/packages/opentelemetry-semantic-conventions-ai/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. [[package]] name = "autopep8" @@ -112,14 +112,14 @@ files = [ [[package]] name = "opentelemetry-api" -version = "1.35.0" +version = "1.36.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "opentelemetry_api-1.35.0-py3-none-any.whl", hash = "sha256:c4ea7e258a244858daf18474625e9cc0149b8ee354f37843415771a40c25ee06"}, - {file = "opentelemetry_api-1.35.0.tar.gz", hash = "sha256:a111b959bcfa5b4d7dffc2fbd6a241aa72dd78dd8e79b5b1662bda896c5d2ffe"}, + {file = "opentelemetry_api-1.36.0-py3-none-any.whl", hash = "sha256:02f20bcacf666e1333b6b1f04e647dc1d5111f86b8e510238fcc56d7762cda8c"}, + {file = "opentelemetry_api-1.36.0.tar.gz", hash = "sha256:9a72572b9c416d004d492cbc6e61962c0501eaf945ece9b5a0f56597d8348aa0"}, ] [package.dependencies] @@ -128,35 +128,35 @@ typing-extensions = ">=4.5.0" [[package]] name = "opentelemetry-sdk" -version = "1.35.0" +version = "1.36.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "opentelemetry_sdk-1.35.0-py3-none-any.whl", hash = "sha256:223d9e5f5678518f4842311bb73966e0b6db5d1e0b74e35074c052cd2487f800"}, - {file = "opentelemetry_sdk-1.35.0.tar.gz", hash = "sha256:2a400b415ab68aaa6f04e8a6a9f6552908fb3090ae2ff78d6ae0c597ac581954"}, + {file = "opentelemetry_sdk-1.36.0-py3-none-any.whl", hash = "sha256:19fe048b42e98c5c1ffe85b569b7073576ad4ce0bcb6e9b4c6a39e890a6c45fb"}, + {file = "opentelemetry_sdk-1.36.0.tar.gz", hash = "sha256:19c8c81599f51b71670661ff7495c905d8fdf6976e41622d5245b791b06fa581"}, ] [package.dependencies] -opentelemetry-api = "1.35.0" -opentelemetry-semantic-conventions = "0.56b0" +opentelemetry-api = "1.36.0" +opentelemetry-semantic-conventions = "0.57b0" typing-extensions = ">=4.5.0" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.56b0" +version = "0.57b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "opentelemetry_semantic_conventions-0.56b0-py3-none-any.whl", hash = "sha256:df44492868fd6b482511cc43a942e7194be64e94945f572db24df2e279a001a2"}, - {file = "opentelemetry_semantic_conventions-0.56b0.tar.gz", hash = "sha256:c114c2eacc8ff6d3908cb328c811eaf64e6d68623840be9224dc829c4fd6c2ea"}, + {file = "opentelemetry_semantic_conventions-0.57b0-py3-none-any.whl", hash = "sha256:757f7e76293294f124c827e514c2a3144f191ef175b069ce8d1211e1e38e9e78"}, + {file = "opentelemetry_semantic_conventions-0.57b0.tar.gz", hash = "sha256:609a4a79c7891b4620d64c7aac6898f872d790d75f22019913a660756f27ff32"}, ] [package.dependencies] -opentelemetry-api = "1.35.0" +opentelemetry-api = "1.36.0" typing-extensions = ">=4.5.0" [[package]] @@ -317,4 +317,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4" -content-hash = "6f5d29ff2d916317f0ca2c830518ae1ce166b83c5ec808c9ef563855ebced3a4" +content-hash = "97baf46a238bef870f8a9ab9c33aa0be8ab4488acdbffc114c19d84651e95568" diff --git a/packages/opentelemetry-semantic-conventions-ai/pyproject.toml b/packages/opentelemetry-semantic-conventions-ai/pyproject.toml index 3c81ed22ac..e257c36d1c 100644 --- a/packages/opentelemetry-semantic-conventions-ai/pyproject.toml +++ b/packages/opentelemetry-semantic-conventions-ai/pyproject.toml @@ -24,6 +24,7 @@ include = "opentelemetry/semconv_ai" [tool.poetry.dependencies] python = ">=3.9,<4" opentelemetry-sdk = "^1.35.0" +opentelemetry-semantic-conventions = "^0.57b0" [tool.poetry.group.dev.dependencies] autopep8 = "^2.2.0" diff --git a/packages/traceloop-sdk/tests/test_manual.py b/packages/traceloop-sdk/tests/test_manual.py index ce245d684b..c249abf210 100644 --- a/packages/traceloop-sdk/tests/test_manual.py +++ b/packages/traceloop-sdk/tests/test_manual.py @@ -1,6 +1,9 @@ -from opentelemetry.semconv_ai import SpanAttributes import pytest from openai import OpenAI +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv_ai import SpanAttributes from traceloop.sdk.tracing.manual import LLMMessage, LLMUsage, track_llm_call @@ -36,29 +39,29 @@ def test_manual_report(exporter, openai_client): spans = exporter.get_finished_spans() open_ai_span = spans[0] - assert open_ai_span.attributes[SpanAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-3.5-turbo" + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about opentelemetry" ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_RESPONSE_MODEL] + open_ai_span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL] == "gpt-3.5-turbo-0125" ) assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_COMPLETION}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == "Why did the opentelemetry developer break up with their partner? Because they were tired" + " of constantly tracing their every move!" ) assert open_ai_span.end_time > open_ai_span.start_time - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 15 - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 24 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 15 + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 24 assert open_ai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 39 assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS] + open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS] == 15 ) assert ( - open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 18 + open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] == 18 ) diff --git a/packages/traceloop-sdk/tests/test_privacy_no_prompts.py b/packages/traceloop-sdk/tests/test_privacy_no_prompts.py index dc64576e59..c25275137b 100644 --- a/packages/traceloop-sdk/tests/test_privacy_no_prompts.py +++ b/packages/traceloop-sdk/tests/test_privacy_no_prompts.py @@ -2,7 +2,9 @@ import pytest from openai import OpenAI -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from traceloop.sdk.decorators import workflow, task @@ -43,8 +45,8 @@ def joke_workflow(): "pirate_joke_generator.workflow", ] open_ai_span = spans[0] - assert open_ai_span.attributes[SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 15 - assert not open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_PROMPT}.0.content") + assert open_ai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 15 + assert not open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_PROMPT}.0.content") assert not open_ai_span.attributes.get( - f"{SpanAttributes.GEN_AI_PROMPT}.0.completions" + f"{GenAIAttributes.GEN_AI_PROMPT}.0.completions" ) diff --git a/packages/traceloop-sdk/tests/test_prompt_management.py b/packages/traceloop-sdk/tests/test_prompt_management.py index da4b735c8a..3819c54a2b 100644 --- a/packages/traceloop-sdk/tests/test_prompt_management.py +++ b/packages/traceloop-sdk/tests/test_prompt_management.py @@ -2,6 +2,9 @@ import pytest from openai import OpenAI +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes from traceloop.sdk.prompts import get_prompt from traceloop.sdk.prompts.client import PromptRegistryClient @@ -233,10 +236,10 @@ def test_prompt_management(exporter, openai_client): ] open_ai_span = spans[0] assert ( - open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] + open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry, pirate style" ) - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert open_ai_span.attributes.get("traceloop.prompt.key") == "joke_generator" diff --git a/packages/traceloop-sdk/tests/test_workflows.py b/packages/traceloop-sdk/tests/test_workflows.py index 3c167b9c4c..e9861fdb80 100644 --- a/packages/traceloop-sdk/tests/test_workflows.py +++ b/packages/traceloop-sdk/tests/test_workflows.py @@ -4,6 +4,9 @@ import pytest from openai import OpenAI, AsyncOpenAI +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes from opentelemetry.trace.status import StatusCode from traceloop.sdk import Traceloop @@ -44,8 +47,8 @@ def joke_workflow(): "pirate_joke_generator.workflow", ] open_ai_span = next(span for span in spans if span.name == "openai.chat") - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert open_ai_span.attributes.get("traceloop.prompt.template") == "Tell me a {what} about {subject}" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.what") == "joke" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.subject") == "OpenTelemetry" @@ -90,8 +93,8 @@ async def joke_workflow(): "pirate_joke_generator.workflow", ] open_ai_span = next(span for span in spans if span.name == "openai.chat") - assert open_ai_span.attributes[f"{SpanAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" - assert open_ai_span.attributes.get(f"{SpanAttributes.GEN_AI_COMPLETION}.0.content") + assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" + assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") assert open_ai_span.attributes.get("traceloop.prompt.template") == "Tell me a {what} about {subject}" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.what") == "joke" assert open_ai_span.attributes.get("traceloop.prompt.template_variables.subject") == "OpenTelemetry" diff --git a/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py b/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py index c601e62a63..7880f8a751 100644 --- a/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py +++ b/packages/traceloop-sdk/traceloop/sdk/tracing/manual.py @@ -1,4 +1,7 @@ from contextlib import contextmanager +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes from opentelemetry.trace import Span from pydantic import BaseModel @@ -26,41 +29,41 @@ def __init__(self, span: Span): pass def report_request(self, model: str, messages: list[LLMMessage]): - self._span.set_attribute(SpanAttributes.GEN_AI_REQUEST_MODEL, model) + self._span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_MODEL, model) for idx, message in enumerate(messages): self._span.set_attribute( - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.role", message.role + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.role", message.role ) self._span.set_attribute( - f"{SpanAttributes.GEN_AI_PROMPT}.{idx}.content", message.content + f"{GenAIAttributes.GEN_AI_PROMPT}.{idx}.content", message.content ) def report_response(self, model: str, completions: list[str]): - self._span.set_attribute(SpanAttributes.GEN_AI_RESPONSE_MODEL, model) + self._span.set_attribute(GenAIAttributes.GEN_AI_RESPONSE_MODEL, model) for idx, completion in enumerate(completions): self._span.set_attribute( - f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.role", "assistant" + f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.role", "assistant" ) self._span.set_attribute( - f"{SpanAttributes.GEN_AI_COMPLETION}.{idx}.content", completion + f"{GenAIAttributes.GEN_AI_COMPLETION}.{idx}.content", completion ) def report_usage(self, usage: LLMUsage): self._span.set_attribute( - SpanAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens ) self._span.set_attribute( - SpanAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens ) self._span.set_attribute( SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens ) self._span.set_attribute( - SpanAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, usage.cache_creation_input_tokens, ) self._span.set_attribute( - SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, usage.cache_read_input_tokens, ) @@ -69,7 +72,7 @@ def report_usage(self, usage: LLMUsage): def track_llm_call(vendor: str, type: str): with get_tracer() as tracer: with tracer.start_as_current_span(name=f"{vendor}.{type}") as span: - span.set_attribute(SpanAttributes.GEN_AI_SYSTEM, vendor) + span.set_attribute(GenAIAttributes.GEN_AI_SYSTEM, vendor) span.set_attribute(SpanAttributes.LLM_REQUEST_TYPE, type) llm_span = LLMSpan(span) try: From 0129a0a5c032046281cf9673db8cfc1021bdb5a1 Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Tue, 19 Aug 2025 12:33:56 +0000 Subject: [PATCH 5/8] deprecating gen_ai attributes from our semconv AI --- .../instrumentation/anthropic/__init__.py | 3 ++ .../tests/utils.py | 5 ++- .../langchain/callback_handler.py | 4 +- .../instrumentation/langchain/span_utils.py | 6 +-- .../tests/metrics/test_langchain_metrics.py | 4 +- .../tests/test_llms.py | 8 ++-- .../tests/test_generation.py | 2 +- .../openai/v1/responses_wrappers.py | 2 +- .../opentelemetry/semconv_ai/__init__.py | 39 ------------------- 9 files changed, 20 insertions(+), 53 deletions(-) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py index 483f572cc3..c2ae4f0d6c 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py @@ -34,6 +34,9 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY, unwrap from opentelemetry.metrics import Counter, Histogram, Meter, get_meter +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import ( SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY, LLMRequestTypeValues, diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/utils.py b/packages/opentelemetry-instrumentation-anthropic/tests/utils.py index c3bab973c8..fd3ad80c5a 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/utils.py @@ -1,4 +1,7 @@ -from opentelemetry.semconv_ai import Meters, SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv_ai import Meters def verify_metrics( diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py index 791fec65a2..3a8e9ad36c 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py @@ -504,7 +504,7 @@ def on_llm_end( ) # Record token usage metrics - vendor = span.attributes.get(SpanAttributes.LLM_SYSTEM, "Langchain") + vendor = span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM, "Langchain") if prompt_tokens > 0: self.token_histogram.record( prompt_tokens, @@ -533,7 +533,7 @@ def on_llm_end( # Record duration duration = time.time() - self.spans[run_id].start_time - vendor = span.attributes.get(SpanAttributes.LLM_SYSTEM, "Langchain") + vendor = span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM, "Langchain") self.duration_histogram.record( duration, attributes={ diff --git a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py index df8bcbc18e..8f3a386edd 100644 --- a/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py +++ b/packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.py @@ -339,13 +339,13 @@ def set_chat_response_usage( cache_read_tokens, ) if record_token_usage: - vendor = span.attributes.get(SpanAttributes.LLM_SYSTEM, "Langchain") + vendor = span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM, "Langchain") if input_tokens > 0: token_histogram.record( input_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: vendor, + GenAIAttributes.GEN_AI_SYSTEM: vendor, SpanAttributes.LLM_TOKEN_TYPE: "input", SpanAttributes.LLM_RESPONSE_MODEL: model_name, }, @@ -355,7 +355,7 @@ def set_chat_response_usage( token_histogram.record( output_tokens, attributes={ - SpanAttributes.LLM_SYSTEM: vendor, + GenAIAttributes.GEN_AI_SYSTEM: vendor, SpanAttributes.LLM_TOKEN_TYPE: "output", SpanAttributes.LLM_RESPONSE_MODEL: model_name, }, diff --git a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py index 8ba2f9aeea..22550e68d9 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py @@ -127,14 +127,14 @@ def verify_token_metrics(data_points): "input", ] assert data_point.sum > 0 - assert data_point.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" def verify_duration_metrics(data_points): assert any(data_point.count > 0 for data_point in data_points) assert any(data_point.sum > 0 for data_point in data_points) for data_point in data_points: - assert data_point.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" def verify_langchain_metrics(reader): diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py index ae579d399c..e60fb40dde 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_llms.py @@ -143,7 +143,7 @@ def test_custom_llm(instrument_legacy, span_exporter, log_exporter): assert hugging_face_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "completion" assert hugging_face_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "unknown" - assert hugging_face_span.attributes[SpanAttributes.LLM_SYSTEM] == "HuggingFace" + assert hugging_face_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "HuggingFace" assert ( hugging_face_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "System: You are a helpful assistant\nHuman: tell me a short joke" @@ -277,7 +277,7 @@ def test_openai(instrument_legacy, span_exporter, log_exporter): assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o-mini" - assert openai_span.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert openai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" assert ( (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" @@ -873,7 +873,7 @@ def test_bedrock(instrument_legacy, span_exporter, log_exporter): bedrock_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "anthropic.claude-3-haiku-20240307-v1:0" ) - assert bedrock_span.attributes[SpanAttributes.LLM_SYSTEM] == "AWS" + assert bedrock_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "AWS" assert ( (bedrock_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"]) == "You are a helpful assistant" @@ -1094,7 +1094,7 @@ def test_trace_propagation(instrument_legacy, span_exporter, log_exporter, LLM): VLLMOpenAI: "openai", ChatOpenAI: "openai" } - assert openai_span.attributes[SpanAttributes.LLM_SYSTEM] == expected_vendors[LLM] + assert openai_span.attributes[GenAIAttributes.GEN_AI_SYSTEM] == expected_vendors[LLM] args, kwargs = send_spy.mock.call_args request = args[0] diff --git a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py index 9f47d164d9..07a03b355b 100644 --- a/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py +++ b/packages/opentelemetry-instrumentation-ollama/tests/test_generation.py @@ -20,7 +20,7 @@ def test_ollama_generation_legacy( spans = span_exporter.get_finished_spans() ollama_span = spans[0] assert ollama_span.name == "ollama.completion" - assert ollama_span.attributes.get(f"{GenAIAttributes.GEN_AI_SYSTEM}") == "Ollama" + assert ollama_span.attributes.get(GenAIAttributes.GEN_AI_SYSTEM) == "Ollama" assert ( ollama_span.attributes.get(f"{SpanAttributes.LLM_REQUEST_TYPE}") == "completion" ) diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py index 569e11a1f2..fecc7e33db 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/responses_wrappers.py @@ -187,7 +187,7 @@ def set_data_attributes(traced_response: TracedData, span: Span): if usage.input_tokens_details: _set_span_attribute( span, - GenAIAttributes.GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, usage.input_tokens_details.cached_tokens, ) # TODO: add reasoning tokens in output token details diff --git a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py index 88b8aa9fca..65a7749a95 100644 --- a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py +++ b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py @@ -37,45 +37,6 @@ class Meters: class SpanAttributes: - # OpenTelemetry Semantic Conventions for Gen AI - - # Refer to https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-spans.md - GEN_AI_AGENT_DESCRIPTION=GenAIAttributes.GEN_AI_AGENT_DESCRIPTION - GEN_AI_AGENT_ID= GenAIAttributes.GEN_AI_AGENT_ID - GEN_AI_AGENT_NAME= GenAIAttributes.GEN_AI_AGENT_NAME - GEN_AI_COMPLETION=GenAIAttributes.GEN_AI_COMPLETION - GEN_AI_CONVERSATION_ID=GenAIAttributes.GEN_AI_CONVERSATION_ID - GEN_AI_DATA_SOURCE_ID=GenAIAttributes.GEN_AI_DATA_SOURCE_ID - GEN_AI_OPENAI_REQUEST_SERVICE_TIER=GenAIAttributes.GEN_AI_OPENAI_REQUEST_SERVICE_TIER - GEN_AI_OPENAI_RESPONSE_SERVICE_TIER=GenAIAttributes.GEN_AI_OPENAI_RESPONSE_SERVICE_TIER - GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT=GenAIAttributes.GEN_AI_OPENAI_RESPONSE_SYSTEM_FINGERPRINT - GEN_AI_OUTPUT_TYPE=GenAIAttributes.GEN_AI_OUTPUT_TYPE - GEN_AI_PROMPT=GenAIAttributes.GEN_AI_PROMPT - GEN_AI_REQUEST_CHOICE_COUNT=GenAIAttributes.GEN_AI_REQUEST_CHOICE_COUNT - GEN_AI_REQUEST_ENCODING_FORMATS= GenAIAttributes.GEN_AI_REQUEST_ENCODING_FORMATS - GEN_AI_REQUEST_FREQUENCY_PENALTY= GenAIAttributes.GEN_AI_REQUEST_FREQUENCY_PENALTY - GEN_AI_REQUEST_MAX_TOKENS=GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS - GEN_AI_REQUEST_MODEL=GenAIAttributes.GEN_AI_REQUEST_MODEL - GEN_AI_REQUEST_PRESENCE_PENALTY=GenAIAttributes.GEN_AI_REQUEST_PRESENCE_PENALTY - GEN_AI_REQUEST_SEED=GenAIAttributes.GEN_AI_REQUEST_SEED - GEN_AI_REQUEST_STOP_SEQUENCES=GenAIAttributes.GEN_AI_REQUEST_STOP_SEQUENCES - GEN_AI_REQUEST_TEMPERATURE=GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE - GEN_AI_REQUEST_TOP_K=GenAIAttributes.GEN_AI_REQUEST_TOP_K - GEN_AI_REQUEST_TOP_P=GenAIAttributes.GEN_AI_REQUEST_TOP_P - GEN_AI_REQUEST_STRUCTURED_OUTPUT_SCHEMA = "gen_ai.request.structured_output_schema" - GEN_AI_RESPONSE_FINISH_REASONS=GenAIAttributes.GEN_AI_RESPONSE_FINISH_REASONS - GEN_AI_RESPONSE_ID=GenAIAttributes.GEN_AI_RESPONSE_ID - GEN_AI_RESPONSE_MODEL=GenAIAttributes.GEN_AI_RESPONSE_MODEL - GEN_AI_SYSTEM=GenAIAttributes.GEN_AI_SYSTEM - GEN_AI_TOKEN_TYPE=GenAIAttributes.GEN_AI_TOKEN_TYPE - GEN_AI_TOOL_CALL_ID=GenAIAttributes.GEN_AI_TOOL_CALL_ID - GEN_AI_TOOL_DESCRIPTION=GenAIAttributes.GEN_AI_TOOL_DESCRIPTION - GEN_AI_TOOL_NAME=GenAIAttributes.GEN_AI_TOOL_NAME - GEN_AI_TOOL_TYPE=GenAIAttributes.GEN_AI_TOOL_TYPE - GEN_AI_USAGE_INPUT_TOKENS=GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS - GEN_AI_USAGE_OUTPUT_TOKENS=GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS - GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS = "gen_ai.usage.cache_creation_input_tokens" - GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = "gen_ai.usage.cache_read_input_tokens" - # LLM LLM_REQUEST_TYPE = "llm.request.type" LLM_USAGE_TOTAL_TOKENS = "llm.usage.total_tokens" From 0959a96221cb136b0c059b6c42075ed088653e31 Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Tue, 19 Aug 2025 13:13:24 +0000 Subject: [PATCH 6/8] deprecating gen_ai attributes from our semconv AI --- .../instrumentation/anthropic/span_utils.py | 6 +- .../tests/test_bedrock_with_raw_response.py | 12 ++-- .../tests/test_messages.py | 8 +-- .../tests/metrics/test_langchain_metrics.py | 4 +- .../tests/test_langgraph.py | 8 +-- .../tests/test_tool_call_content.py | 66 +++++++++---------- .../instrumentation/openai_agents/_hooks.py | 8 +-- .../traces/test_streaming_with_api_usage.py | 2 +- 8 files changed, 57 insertions(+), 57 deletions(-) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py index 49bfd630ab..d2898bf01b 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py @@ -140,17 +140,17 @@ async def aset_input_attributes(span, kwargs): for tool_num, tool_use_block in enumerate(tool_use_blocks): set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.tool_calls.{tool_num}.id", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.tool_calls.{tool_num}.id", tool_use_block.get("id"), ) set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.tool_calls.{tool_num}.name", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.tool_calls.{tool_num}.name", tool_use_block.get("name"), ) set_span_attribute( span, - f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.tool_calls.{tool_num}.arguments", + f"{GenAIAttributes.GEN_AI_PROMPT}.{prompt_index}.tool_calls.{tool_num}.arguments", json.dumps(tool_use_block.get("input")), ) diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py index fab8fe84d7..72b10b0536 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py @@ -53,10 +53,10 @@ async def test_async_anthropic_bedrock_with_raw_response( anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" # For raw response, content is accessed differently response_content = ( response.parse().content[0].text @@ -108,10 +108,10 @@ async def test_async_anthropic_bedrock_regular_create( anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") == response.content[0].text @@ -159,10 +159,10 @@ async def test_async_anthropic_bedrock_beta_with_raw_response( anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" # For raw response, content is accessed differently response_content = ( response.parse().content[0].text diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py index 45d8a1aa45..b24e69afa5 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py @@ -2497,10 +2497,10 @@ def test_anthropic_message_stream_manager_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") == response_content @@ -2687,10 +2687,10 @@ async def test_async_anthropic_message_stream_manager_legacy( ] anthropic_span = spans[0] assert ( - anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" ) - assert (anthropic_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "user" + assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") == response_content diff --git a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py index 0e979e8dac..131b9a5989 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py @@ -130,7 +130,7 @@ def test_llm_chain_streaming_metrics(instrument_legacy, reader, llm): def verify_token_metrics(data_points): for data_point in data_points: - assert data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in [ + assert data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in [ "output", "input", ] @@ -236,7 +236,7 @@ def calculate(state: State): assert token_usage_data_point.sum > 0 assert ( token_usage_data_point.attributes[SpanAttributes.LLM_SYSTEM] == "openai" - and token_usage_data_point.attributes[SpanAttributes.LLM_TOKEN_TYPE] in ["input", "output"] + and token_usage_data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in ["input", "output"] ) duration_metric = next( diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py b/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py index 891b9d09cb..fe394f2e30 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py @@ -46,13 +46,13 @@ def calculate(state: State): assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-4o" assert ( - openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] ) == "You are a mathematician." - assert (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"]) == "system" + assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "system" assert ( - openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] ) == user_request - assert (openai_span.attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"]) == "user" + assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( openai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] == response diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py index b94017dcb0..287b85b47a 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py @@ -49,46 +49,46 @@ def test_assistant_message_with_tool_calls_includes_content(): call_args = [call[0] for call in mock_span.set_attribute.call_args_list] attributes = {args[0]: args[1] for args in call_args} - assert f"{SpanAttributes.LLM_PROMPTS}.0.role" in attributes - assert attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "user" - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.role" in attributes + assert attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "user" + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "what is the current time? First greet me." ) - assert f"{SpanAttributes.LLM_PROMPTS}.1.role" in attributes - assert attributes[f"{SpanAttributes.LLM_PROMPTS}.1.role"] == "assistant" - assert f"{SpanAttributes.LLM_PROMPTS}.1.content" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.1.role" in attributes + assert attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"] == "assistant" + assert f"{GenAIAttributes.GEN_AI_PROMPT}.1.content" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.1.content"] + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.content"] == "Hello! Let me check the current time for you." ) - assert f"{SpanAttributes.LLM_PROMPTS}.1.tool_calls.0.id" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_calls.0.id" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.1.tool_calls.0.id"] + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_calls.0.id"] == "call_qU7pH3EdQvzwkPyKPOdpgaKA" ) - assert f"{SpanAttributes.LLM_PROMPTS}.1.tool_calls.0.name" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_calls.0.name" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.1.tool_calls.0.name"] + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.tool_calls.0.name"] == "get_current_time" ) - assert f"{SpanAttributes.LLM_PROMPTS}.2.role" in attributes - assert attributes[f"{SpanAttributes.LLM_PROMPTS}.2.role"] == "tool" - assert f"{SpanAttributes.LLM_PROMPTS}.2.content" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.2.role" in attributes + assert attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.role"] == "tool" + assert f"{GenAIAttributes.GEN_AI_PROMPT}.2.content" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.2.content"] == "2025-08-15 08:15:21" + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.content"] == "2025-08-15 08:15:21" ) - assert f"{SpanAttributes.LLM_PROMPTS}.2.tool_call_id" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.2.tool_call_id" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.2.tool_call_id"] + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.2.tool_call_id"] == "call_qU7pH3EdQvzwkPyKPOdpgaKA" ) - assert f"{SpanAttributes.LLM_PROMPTS}.3.role" in attributes - assert attributes[f"{SpanAttributes.LLM_PROMPTS}.3.role"] == "assistant" - assert f"{SpanAttributes.LLM_PROMPTS}.3.content" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.3.role" in attributes + assert attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.role"] == "assistant" + assert f"{GenAIAttributes.GEN_AI_PROMPT}.3.content" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.3.content"] + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.3.content"] == "The current time is 2025-08-15 08:15:21" ) @@ -119,14 +119,14 @@ def test_assistant_message_with_only_tool_calls_no_content(): call_args = [call[0] for call in mock_span.set_attribute.call_args_list] attributes = {args[0]: args[1] for args in call_args} - assert f"{SpanAttributes.LLM_PROMPTS}.0.role" in attributes - assert attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "assistant" - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" not in attributes - assert f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.id" in attributes - assert attributes[f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.id"] == "call_123" - assert f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.name" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.role" in attributes + assert attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "assistant" + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" not in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.id" in attributes + assert attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.id"] == "call_123" + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.0.tool_calls.0.name"] == "some_tool" + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.tool_calls.0.name"] == "some_tool" ) @@ -148,11 +148,11 @@ def test_assistant_message_with_only_content_no_tool_calls(): attributes = {args[0]: args[1] for args in call_args} - assert f"{SpanAttributes.LLM_PROMPTS}.0.role" in attributes - assert attributes[f"{SpanAttributes.LLM_PROMPTS}.0.role"] == "assistant" - assert f"{SpanAttributes.LLM_PROMPTS}.0.content" in attributes + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.role" in attributes + assert attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"] == "assistant" + assert f"{GenAIAttributes.GEN_AI_PROMPT}.0.content" in attributes assert ( - attributes[f"{SpanAttributes.LLM_PROMPTS}.0.content"] + attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Just a regular response with no tool calls" ) diff --git a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py index 117dcaf240..2c320a93be 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py +++ b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py @@ -235,12 +235,12 @@ def on_span_end(self, span): if input_data: for i, message in enumerate(input_data): if hasattr(message, 'role') and hasattr(message, 'content'): - otel_span.set_attribute(f"{SpanAttributes.LLM_PROMPTS}.{i}.role", message.role) - otel_span.set_attribute(f"{SpanAttributes.LLM_PROMPTS}.{i}.content", message.content) + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", message.role) + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", message.content) elif isinstance(message, dict): if 'role' in message and 'content' in message: - otel_span.set_attribute(f"{SpanAttributes.LLM_PROMPTS}.{i}.role", message['role']) - otel_span.set_attribute(f"{SpanAttributes.LLM_PROMPTS}.{i}.content", message['content']) + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.role", message['role']) + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_PROMPT}.{i}.content", message['content']) # Add function/tool specifications to the request using OpenAI semantic conventions response = getattr(span_data, 'response', None) diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py index 9aef31547c..b1c6ef6bb1 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py @@ -41,7 +41,7 @@ def test_streaming_with_api_usage_capture( # Verify that the response content is meaningful assert len(response_content) > 0 - assert span.attributes.get(SpanAttributes.LLM_RESPONSE_MODEL) == "deepseek-chat" + assert span.attributes.get(GenAIAttributes.GEN_AI_RESPONSE_MODEL) == "deepseek-chat" @pytest.mark.vcr From 9d4ad8828c1433fe12b21d32acccc7bb79816dfc Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Tue, 19 Aug 2025 14:25:26 +0000 Subject: [PATCH 7/8] deprecating gen_ai attributes from our semconv AI --- .../instrumentation/anthropic/span_utils.py | 2 +- .../tests/test_bedrock_with_raw_response.py | 39 +++++---- .../tests/test_completion.py | 1 - .../tests/test_messages.py | 44 +++++----- .../instrumentation/groq/__init__.py | 4 +- .../tests/metrics/test_langchain_metrics.py | 8 +- .../tests/test_langgraph.py | 14 +-- .../tests/test_tool_call_content.py | 4 +- .../instrumentation/openai_agents/_hooks.py | 86 ++++++++++--------- .../openai/v1/assistant_wrappers.py | 2 +- .../tests/traces/test_completions.py | 2 +- .../traces/test_streaming_with_api_usage.py | 12 ++- .../tests/test_prompt_management.py | 4 +- 13 files changed, 117 insertions(+), 105 deletions(-) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py index d2898bf01b..a4cad8bfde 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py @@ -244,7 +244,7 @@ def _set_span_completions(span, response): response = _extract_response_data(response) index = 0 - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{index}" set_span_attribute(span, f"{prefix}.finish_reason", response.get("stop_reason")) if response.get("role"): set_span_attribute(span, f"{prefix}.role", response.get("role")) diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py index 72b10b0536..6d87f51093 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_bedrock_with_raw_response.py @@ -1,5 +1,8 @@ import os import pytest +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes try: @@ -64,18 +67,18 @@ async def test_async_anthropic_bedrock_with_raw_response( else response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] > 0 - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] > 0 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] > 0 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] > 0 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -113,18 +116,18 @@ async def test_async_anthropic_bedrock_regular_create( ) assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] > 0 - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] > 0 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] > 0 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] > 0 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -170,17 +173,17 @@ async def test_async_anthropic_bedrock_beta_with_raw_response( else response.content[0].text ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] > 0 - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] > 0 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] > 0 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] > 0 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py index e84836cd60..aec3ddd00f 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_completion.py @@ -7,7 +7,6 @@ from opentelemetry.semconv._incubating.attributes import ( gen_ai_attributes as GenAIAttributes, ) -from opentelemetry.semconv_ai import SpanAttributes from .utils import verify_metrics diff --git a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py index b24e69afa5..8d9e651f4f 100644 --- a/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py +++ b/packages/opentelemetry-instrumentation-anthropic/tests/test_messages.py @@ -2502,17 +2502,17 @@ def test_anthropic_message_stream_manager_legacy( ) assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -2562,10 +2562,10 @@ def test_anthropic_message_stream_manager_with_events_with_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -2626,10 +2626,10 @@ def test_anthropic_message_stream_manager_with_events_with_no_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -2692,17 +2692,17 @@ async def test_async_anthropic_message_stream_manager_legacy( ) assert (anthropic_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.role"]) == "user" assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.content") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") == response_content ) assert ( - anthropic_span.attributes.get(f"{SpanAttributes.LLM_COMPLETIONS}.0.role") + anthropic_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role") == "assistant" ) - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) assert ( @@ -2752,10 +2752,10 @@ async def test_async_anthropic_message_stream_manager_with_events_with_content( "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) @@ -2815,10 +2815,10 @@ async def test_async_anthropic_message_stream_manager_with_events_with_no_conten "anthropic.chat", ] anthropic_span = spans[0] - assert anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 17 + assert anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 17 assert ( - anthropic_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] - + anthropic_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] + + anthropic_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == anthropic_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] ) diff --git a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py index 56ac49848b..2803939f97 100644 --- a/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py +++ b/packages/opentelemetry-instrumentation-groq/opentelemetry/instrumentation/groq/__init__.py @@ -245,7 +245,7 @@ def _wrap( name, kind=SpanKind.CLIENT, attributes={ - GenAIAttributes.GEN_AI_SYSTEM: "Groq", + GenAIAttributes.GEN_AI_SYSTEM: "groq", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) @@ -327,7 +327,7 @@ async def _awrap( name, kind=SpanKind.CLIENT, attributes={ - GenAIAttributes.GEN_AI_SYSTEM: "Groq", + GenAIAttributes.GEN_AI_SYSTEM: "groq", SpanAttributes.LLM_REQUEST_TYPE: LLMRequestTypeValues.COMPLETION.value, }, ) diff --git a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py index 131b9a5989..49b6b836ee 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py @@ -7,7 +7,7 @@ from opentelemetry.semconv._incubating.attributes import ( gen_ai_attributes as GenAIAttributes, ) -from opentelemetry.semconv_ai import Meters, SpanAttributes +from opentelemetry.semconv_ai import Meters from langgraph.graph import StateGraph from openai import OpenAI @@ -235,7 +235,7 @@ def calculate(state: State): token_usage_data_point = token_usage_metric.data.data_points[0] assert token_usage_data_point.sum > 0 assert ( - token_usage_data_point.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + token_usage_data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" and token_usage_data_point.attributes[GenAIAttributes.GEN_AI_TOKEN_TYPE] in ["input", "output"] ) @@ -250,7 +250,7 @@ def calculate(state: State): assert duration_metric is not None duration_data_point = duration_metric.data.data_points[0] assert duration_data_point.sum > 0 - assert duration_data_point.attributes[SpanAttributes.LLM_SYSTEM] == "openai" + assert duration_data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" generation_choices_metric = next( ( @@ -264,7 +264,7 @@ def calculate(state: State): generation_choices_data_points = generation_choices_metric.data.data_points for data_point in generation_choices_data_points: assert ( - data_point.attributes[SpanAttributes.LLM_SYSTEM] + data_point.attributes[GenAIAttributes.GEN_AI_SYSTEM] == "openai" ) assert data_point.value > 0 diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py b/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py index fe394f2e30..a17d8f94e2 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_langgraph.py @@ -3,6 +3,9 @@ from typing import TypedDict from langgraph.graph import StateGraph from opentelemetry import trace +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) from opentelemetry.semconv_ai import SpanAttributes from opentelemetry.trace import INVALID_SPAN @@ -44,7 +47,7 @@ def calculate(state: State): assert openai_span.parent.span_id == calculate_task_span.context.span_id assert openai_span.attributes[SpanAttributes.LLM_REQUEST_TYPE] == "chat" - assert openai_span.attributes[SpanAttributes.LLM_REQUEST_MODEL] == "gpt-4o" + assert openai_span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == "gpt-4o" assert ( openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] ) == "You are a mathematician." @@ -54,17 +57,16 @@ def calculate(state: State): ) == user_request assert (openai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.1.role"]) == "user" assert ( - openai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.content"] + openai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content"] == response ) assert ( - openai_span.attributes[f"{SpanAttributes.LLM_COMPLETIONS}.0.role"] + openai_span.attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.0.role"] ) == "assistant" - assert openai_span.attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 24 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 11 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS] == 24 + assert openai_span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS] == 11 assert openai_span.attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 35 - assert openai_span.attributes[SpanAttributes.LLM_USAGE_CACHE_READ_INPUT_TOKENS] == 0 @pytest.mark.vcr diff --git a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py index 287b85b47a..9f999613d8 100644 --- a/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py +++ b/packages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.py @@ -9,7 +9,9 @@ from unittest.mock import Mock from langchain_core.messages import AIMessage, HumanMessage, ToolMessage from opentelemetry.instrumentation.langchain.span_utils import set_chat_request -from opentelemetry.semconv_ai import SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) def test_assistant_message_with_tool_calls_includes_content(): diff --git a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py index 2c320a93be..e88312e90e 100644 --- a/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py +++ b/packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py @@ -7,7 +7,9 @@ from opentelemetry.trace import Tracer, Status, StatusCode, SpanKind, get_current_span, set_span_in_context from opentelemetry import context from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues -from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import GEN_AI_COMPLETION +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes +) from agents.tracing.processors import TracingProcessor from .utils import dont_throw @@ -153,16 +155,16 @@ def on_span_start(self, span): SpanAttributes.TRACELOOP_SPAN_KIND: TraceloopSpanKindValues.TOOL.value, "gen_ai.tool.name": tool_name, "gen_ai.system": "openai_agents", - f"{GEN_AI_COMPLETION}.tool.name": tool_name, - f"{GEN_AI_COMPLETION}.tool.type": "FunctionTool", - f"{GEN_AI_COMPLETION}.tool.strict_json_schema": True + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.name": tool_name, + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.type": "FunctionTool", + f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.strict_json_schema": True } if hasattr(span_data, 'description') and span_data.description: # Only use description if it's not a generic class description desc = span_data.description if desc and not desc.startswith("Represents a Function Span"): - tool_attributes[f"{GEN_AI_COMPLETION}.tool.description"] = desc + tool_attributes[f"{GenAIAttributes.GEN_AI_COMPLETION}.tool.description"] = desc otel_span = self.tracer.start_span( f"{tool_name}.tool", @@ -276,15 +278,15 @@ def on_span_end(self, span): if hasattr(response, 'temperature') and response.temperature is not None: model_settings['temperature'] = response.temperature - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_TEMPERATURE, response.temperature) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, response.temperature) if hasattr(response, 'max_output_tokens') and response.max_output_tokens is not None: model_settings['max_tokens'] = response.max_output_tokens - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_MAX_TOKENS, response.max_output_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, response.max_output_tokens) if hasattr(response, 'top_p') and response.top_p is not None: model_settings['top_p'] = response.top_p - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_TOP_P, response.top_p) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_TOP_P, response.top_p) if hasattr(response, 'model') and response.model: model_settings['model'] = response.model @@ -303,9 +305,9 @@ def on_span_end(self, span): if content_text: otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", content_text) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", content_text) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role", getattr( + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role", getattr( output, 'role', 'assistant')) elif hasattr(output, 'name'): @@ -315,41 +317,41 @@ def on_span_end(self, span): tool_call_id = getattr(output, 'call_id', f"call_{i}") # Set completion with tool call following OpenAI format - otel_span.set_attribute(f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role", "assistant") + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role", "assistant") otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.finish_reason", "tool_calls") + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.finish_reason", "tool_calls") otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.tool_calls.0.name", tool_name) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.name", tool_name) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.tool_calls.0.arguments", arguments) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.arguments", arguments) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.tool_calls.0.id", tool_call_id) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.id", tool_call_id) elif hasattr(output, 'text'): # Direct text content - otel_span.set_attribute(f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", output.text) + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", output.text) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role", getattr( + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role", getattr( output, 'role', 'assistant')) # Add finish reason if available (for non-tool-call cases) if hasattr(response, 'finish_reason') and not hasattr(output, 'name'): otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.finish_reason", response.finish_reason) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.finish_reason", response.finish_reason) # Extract usage data and add directly to response span if hasattr(response, 'usage') and response.usage: usage = response.usage # Try both naming conventions: input_tokens/output_tokens and prompt_tokens/completion_tokens if hasattr(usage, 'input_tokens') and usage.input_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, usage.input_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.input_tokens) elif hasattr(usage, 'prompt_tokens') and usage.prompt_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, usage.prompt_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens) if hasattr(usage, 'output_tokens') and usage.output_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, usage.output_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.output_tokens) elif hasattr(usage, 'completion_tokens') and usage.completion_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, usage.completion_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens) if hasattr(usage, 'total_tokens') and usage.total_tokens is not None: otel_span.set_attribute(SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens) @@ -379,15 +381,15 @@ def on_span_end(self, span): if hasattr(response, 'temperature') and response.temperature is not None: model_settings['temperature'] = response.temperature - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_TEMPERATURE, response.temperature) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, response.temperature) if hasattr(response, 'max_output_tokens') and response.max_output_tokens is not None: model_settings['max_tokens'] = response.max_output_tokens - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_MAX_TOKENS, response.max_output_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, response.max_output_tokens) if hasattr(response, 'top_p') and response.top_p is not None: model_settings['top_p'] = response.top_p - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_TOP_P, response.top_p) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_TOP_P, response.top_p) if hasattr(response, 'model') and response.model: model_settings['model'] = response.model @@ -406,9 +408,9 @@ def on_span_end(self, span): if content_text: otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", content_text) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", content_text) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role", getattr( + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role", getattr( output, 'role', 'assistant')) elif hasattr(output, 'name'): @@ -418,41 +420,41 @@ def on_span_end(self, span): tool_call_id = getattr(output, 'call_id', f"call_{i}") # Set completion with tool call following OpenAI format - otel_span.set_attribute(f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role", "assistant") + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role", "assistant") otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.finish_reason", "tool_calls") + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.finish_reason", "tool_calls") otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.tool_calls.0.name", tool_name) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.name", tool_name) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.tool_calls.0.arguments", arguments) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.arguments", arguments) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.tool_calls.0.id", tool_call_id) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.id", tool_call_id) elif hasattr(output, 'text'): # Direct text content - otel_span.set_attribute(f"{SpanAttributes.LLM_COMPLETIONS}.{i}.content", output.text) + otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", output.text) otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.role", getattr( + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.role", getattr( output, 'role', 'assistant')) # Add finish reason if available (for non-tool-call cases) if hasattr(response, 'finish_reason') and not hasattr(output, 'name'): otel_span.set_attribute( - f"{SpanAttributes.LLM_COMPLETIONS}.{i}.finish_reason", response.finish_reason) + f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.finish_reason", response.finish_reason) # Extract usage data and add directly to response span if hasattr(response, 'usage') and response.usage: usage = response.usage # Try both naming conventions: input_tokens/output_tokens and prompt_tokens/completion_tokens if hasattr(usage, 'input_tokens') and usage.input_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, usage.input_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.input_tokens) elif hasattr(usage, 'prompt_tokens') and usage.prompt_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, usage.prompt_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage.prompt_tokens) if hasattr(usage, 'output_tokens') and usage.output_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, usage.output_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.output_tokens) elif hasattr(usage, 'completion_tokens') and usage.completion_tokens is not None: - otel_span.set_attribute(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, usage.completion_tokens) + otel_span.set_attribute(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage.completion_tokens) if hasattr(usage, 'total_tokens') and usage.total_tokens is not None: otel_span.set_attribute(SpanAttributes.LLM_USAGE_TOTAL_TOKENS, usage.total_tokens) @@ -469,11 +471,11 @@ def on_span_end(self, span): if hasattr(self, '_last_model_settings') and self._last_model_settings: for key, value in self._last_model_settings.items(): if key == 'temperature': - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_TEMPERATURE, value) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE, value) elif key == 'max_tokens': - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_MAX_TOKENS, value) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS, value) elif key == 'top_p': - otel_span.set_attribute(SpanAttributes.LLM_REQUEST_TOP_P, value) + otel_span.set_attribute(GenAIAttributes.GEN_AI_REQUEST_TOP_P, value) elif key == 'model': otel_span.set_attribute("gen_ai.request.model", value) elif key == 'frequency_penalty': diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py index 9a6af18c59..f4ab2596df 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py @@ -192,7 +192,7 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): completion_index = 0 for msg in messages: - prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{completion_index}" + prefix = f"{GenAIAttributes.GEN_AI_COMPLETION}.{completion_index}" content = msg.get("content") message_content = content[0].get("text").get("value") diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py index c5c31590df..0a1bfc6b97 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_completions.py @@ -366,7 +366,7 @@ def test_completion_streaming( == "Tell me a joke about opentelemetry" ) assert open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ) assert ( open_ai_span.attributes.get(SpanAttributes.LLM_OPENAI_API_BASE) diff --git a/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py b/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py index b1c6ef6bb1..1faca441ee 100644 --- a/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py +++ b/packages/opentelemetry-instrumentation-openai/tests/traces/test_streaming_with_api_usage.py @@ -1,5 +1,9 @@ import pytest from openai import OpenAI +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) + from opentelemetry.semconv_ai import SpanAttributes @@ -35,8 +39,8 @@ def test_streaming_with_api_usage_capture( assert span.name == "openai.chat" # Check that token usage is captured from API response - assert span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 assert span.attributes.get(SpanAttributes.LLM_USAGE_TOTAL_TOKENS) > 0 # Verify that the response content is meaningful @@ -64,8 +68,8 @@ def test_streaming_with_api_usage_and_events( span = spans[0] # Check that usage metrics are captured from API response - assert span.attributes.get(SpanAttributes.LLM_USAGE_PROMPT_TOKENS) > 0 - assert span.attributes.get(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS) > 0 + assert span.attributes.get(GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS) > 0 + assert span.attributes.get(GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS) > 0 # Check event logs logs = log_exporter.get_finished_logs() diff --git a/packages/traceloop-sdk/tests/test_prompt_management.py b/packages/traceloop-sdk/tests/test_prompt_management.py index 3819c54a2b..ff208ea4d1 100644 --- a/packages/traceloop-sdk/tests/test_prompt_management.py +++ b/packages/traceloop-sdk/tests/test_prompt_management.py @@ -254,7 +254,7 @@ def test_prompt_management_with_tools(exporter, openai_client): spans = exporter.get_finished_spans() open_ai_span = spans[0] completion = open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.tool_calls.0.name" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.tool_calls.0.name" ) assert completion == "get_joke" @@ -270,7 +270,7 @@ def test_prompt_management_with_response_format(exporter, openai_client): spans = exporter.get_finished_spans() open_ai_span = spans[0] completion = open_ai_span.attributes.get( - f"{SpanAttributes.LLM_COMPLETIONS}.0.content" + f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content" ) try: json.loads(completion) From 6538cad844ab6f24977e85ff3af90043aeb539a0 Mon Sep 17 00:00:00 2001 From: Martim Santos Date: Tue, 19 Aug 2025 14:45:55 +0000 Subject: [PATCH 8/8] small fixes --- .../opentelemetry/instrumentation/anthropic/span_utils.py | 2 +- .../instrumentation/openai/v1/assistant_wrappers.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py index a4cad8bfde..4f0251665c 100644 --- a/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py +++ b/packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py @@ -319,7 +319,7 @@ async def aset_response_attributes(span, response): completion_tokens = response.get("usage").output_tokens set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) set_span_attribute( - span, GenAIAttributes.GEN_AI_USAGE_COMPLETION_TOKENS, completion_tokens + span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens ) set_span_attribute( span, diff --git a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py index f4ab2596df..550f05632d 100644 --- a/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +++ b/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py @@ -232,12 +232,12 @@ def messages_list_wrapper(tracer, wrapped, instance, args, kwargs): usage_dict = model_as_dict(run.get("usage")) _set_span_attribute( span, - GenAIAttributes.GEN_AI_USAGE_PROMPT_TOKENS, + GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, usage_dict.get("completion_tokens"), ) _set_span_attribute( span, - GenAIAttributes.GEN_AI_USAGE_COMPLETION_TOKENS, + GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, usage_dict.get("prompt_tokens"), )