Skip to content

Commit f0189ca

Browse files
committed
Move common gen AI utils into opentelemetry-instrumentation
1 parent 5219242 commit f0189ca

File tree

5 files changed

+63
-34
lines changed

5 files changed

+63
-34
lines changed

instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from opentelemetry._events import get_event_logger
4848
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
4949
from opentelemetry.instrumentation.openai_v2.package import _instruments
50-
from opentelemetry.instrumentation.openai_v2.utils import is_content_enabled
50+
from opentelemetry.instrumentation.genai_utils import is_content_enabled
5151
from opentelemetry.instrumentation.utils import unwrap
5252
from opentelemetry.semconv.schemas import Schemas
5353
from opentelemetry.trace import get_tracer

instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818
from openai import Stream
1919

2020
from opentelemetry._events import Event, EventLogger
21+
from opentelemetry.instrumentation.genai_utils import (
22+
get_span_name,
23+
handle_span_exception,
24+
)
2125
from opentelemetry.semconv._incubating.attributes import (
2226
gen_ai_attributes as GenAIAttributes,
2327
)
2428
from opentelemetry.trace import Span, SpanKind, Tracer
2529

2630
from .utils import (
2731
choice_to_event,
28-
get_llm_request_attributes,
29-
handle_span_exception,
32+
get_genai_request_attributes,
3033
is_streaming,
3134
message_to_event,
3235
set_span_attribute,
@@ -39,9 +42,9 @@ def chat_completions_create(
3942
"""Wrap the `create` method of the `ChatCompletion` class to trace it."""
4043

4144
def traced_method(wrapped, instance, args, kwargs):
42-
span_attributes = {**get_llm_request_attributes(kwargs, instance)}
45+
span_attributes = {**get_genai_request_attributes(kwargs, instance)}
4346

44-
span_name = f"{span_attributes[GenAIAttributes.GEN_AI_OPERATION_NAME]} {span_attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]}"
47+
span_name = get_span_name(span_attributes)
4548
with tracer.start_as_current_span(
4649
name=span_name,
4750
kind=SpanKind.CLIENT,
@@ -81,7 +84,7 @@ def async_chat_completions_create(
8184
"""Wrap the `create` method of the `AsyncChatCompletion` class to trace it."""
8285

8386
async def traced_method(wrapped, instance, args, kwargs):
84-
span_attributes = {**get_llm_request_attributes(kwargs, instance)}
87+
span_attributes = {**get_genai_request_attributes(kwargs, instance)}
8588

8689
span_name = f"{span_attributes[GenAIAttributes.GEN_AI_OPERATION_NAME]} {span_attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]}"
8790
with tracer.start_as_current_span(

instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,6 @@
2626
from opentelemetry.semconv._incubating.attributes import (
2727
server_attributes as ServerAttributes,
2828
)
29-
from opentelemetry.semconv.attributes import (
30-
error_attributes as ErrorAttributes,
31-
)
32-
from opentelemetry.trace.status import Status, StatusCode
33-
34-
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = (
35-
"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
36-
)
37-
38-
39-
def is_content_enabled() -> bool:
40-
capture_content = environ.get(
41-
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, "false"
42-
)
43-
44-
return capture_content.lower() == "true"
4529

4630

4731
def extract_tool_calls(item, capture_content):
@@ -183,7 +167,7 @@ def non_numerical_value_is_set(value: Optional[Union[bool, str]]):
183167
return bool(value) and value != NOT_GIVEN
184168

185169

186-
def get_llm_request_attributes(
170+
def get_genai_request_attributes(
187171
kwargs,
188172
client_instance,
189173
operation_name=GenAIAttributes.GenAiOperationNameValues.CHAT.value,
@@ -227,12 +211,3 @@ def get_llm_request_attributes(
227211

228212
# filter out None values
229213
return {k: v for k, v in attributes.items() if v is not None}
230-
231-
232-
def handle_span_exception(span, error):
233-
span.set_status(Status(StatusCode.ERROR, str(error)))
234-
if span.is_recording():
235-
span.set_attribute(
236-
ErrorAttributes.ERROR_TYPE, type(error).__qualname__
237-
)
238-
span.end()

instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
import yaml
88
from openai import AsyncOpenAI, OpenAI
99

10-
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
11-
from opentelemetry.instrumentation.openai_v2.utils import (
10+
from opentelemetry.instrumentation.genai_utils import (
1211
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT,
1312
)
13+
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
1414
from opentelemetry.sdk._events import EventLoggerProvider
1515
from opentelemetry.sdk._logs import LoggerProvider
1616
from opentelemetry.sdk._logs.export import (
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from os import environ
16+
17+
from opentelemetry.semconv._incubating.attributes import (
18+
gen_ai_attributes as GenAIAttributes,
19+
)
20+
from opentelemetry.semconv.attributes import (
21+
error_attributes as ErrorAttributes,
22+
)
23+
from opentelemetry.trace.status import Status, StatusCode
24+
25+
26+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = (
27+
"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
28+
)
29+
30+
31+
def is_content_enabled() -> bool:
32+
capture_content = environ.get(
33+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, "false"
34+
)
35+
36+
return capture_content.lower() == "true"
37+
38+
39+
def get_span_name(span_attributes):
40+
name = span_attributes.get(GenAIAttributes.GEN_AI_OPERATION_NAME, "")
41+
model = span_attributes.get(GenAIAttributes.GEN_AI_REQUEST_MODEL, "")
42+
return f"{name} {model}"
43+
44+
45+
def handle_span_exception(span, error):
46+
span.set_status(Status(StatusCode.ERROR, str(error)))
47+
if span.is_recording():
48+
span.set_attribute(
49+
ErrorAttributes.ERROR_TYPE, type(error).__qualname__
50+
)
51+
span.end()

0 commit comments

Comments
 (0)