Skip to content

Commit 4fcfa51

Browse files
committed
some fixes
1 parent 23e777f commit 4fcfa51

8 files changed

Lines changed: 38 additions & 37 deletions

File tree

pyproject.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,6 @@ ignore = [
178178

179179
[tool.ruff.lint.per-file-ignores]
180180
"docs/**/*.*" = ["A001"]
181-
# Deferred imports to break circular dependency: utils -> types -> inference_invocation -> utils
182-
"util/opentelemetry-util-genai/src/opentelemetry/util/genai/utils.py" = ["PLC0415"]
183-
# Bottom-of-file import of LLMInvocation for backward-compatibility re-export; cannot move to top
184-
"util/opentelemetry-util-genai/src/opentelemetry/util/genai/types.py" = ["E402"]
185181

186182
[tool.ruff.lint.isort]
187183
detect-same-package = false # to not consider instrumentation packages as first-party

util/opentelemetry-util-genai/pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,9 @@ include = ["/src", "/tests"]
5050

5151
[tool.hatch.build.targets.wheel]
5252
packages = ["src/opentelemetry"]
53+
54+
[tool.pytest.ini_options]
55+
# TODO: remove once all usages of LLMInvocation are migrated to InferenceInvocation
56+
filterwarnings = [
57+
"ignore:LLMInvocation is deprecated:DeprecationWarning",
58+
]

util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ def _start(self, invocation: _T) -> _T:
147147

148148
return invocation
149149

150-
def _finish(self, invocation: _T, error: Error | None = None) -> _T:
150+
def _finish( # pylint: disable=no-self-use
151+
self, invocation: _T, error: Error | None = None
152+
) -> _T:
151153
"""Finalize a GenAI invocation and end its span."""
152154
if invocation._context_token is None:
153155
# TODO: Provide feedback that this invocation was not started

util/opentelemetry-util-genai/src/opentelemetry/util/genai/inference_invocation.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@
2828
from opentelemetry.trace import INVALID_SPAN, SpanKind
2929
from opentelemetry.trace.propagation import set_span_in_context
3030
from opentelemetry.util.genai.types import (
31-
ContentCapturingMode,
3231
Error,
3332
GenAIInvocation,
3433
InputMessage,
3534
MessagePart,
3635
OutputMessage,
3736
)
3837
from opentelemetry.util.genai.utils import (
38+
ContentCapturingMode,
3939
gen_ai_json_dumps,
4040
get_content_capturing_mode,
4141
is_experimental_mode,
@@ -57,7 +57,7 @@ class InferenceInvocation(GenAIInvocation):
5757
def operation_name(self) -> str:
5858
return GenAI.GenAiOperationNameValues.CHAT.value
5959

60-
def __init__(
60+
def __init__( # pylint: disable=too-many-locals
6161
self,
6262
handler: TelemetryHandler,
6363
provider: str,
@@ -236,7 +236,7 @@ def _emit_event(self) -> None:
236236

237237
@deprecated("LLMInvocation is deprecated. Use InferenceInvocation instead.")
238238
class LLMInvocation(InferenceInvocation):
239-
def __init__(
239+
def __init__( # pylint: disable=too-many-locals
240240
self,
241241
handler: "TelemetryHandler | None" = None,
242242
provider: str = "",

util/opentelemetry-util-genai/src/opentelemetry/util/genai/metrics.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
)
1212
from opentelemetry.semconv.attributes import server_attributes
1313
from opentelemetry.trace import set_span_in_context
14-
from opentelemetry.util.genai.inference_invocation import InferenceInvocation
1514
from opentelemetry.util.genai.instruments import (
1615
create_duration_histogram,
1716
create_token_histogram,
1817
)
1918
from opentelemetry.util.types import AttributeValue
2019

20+
from .inference_invocation import InferenceInvocation
21+
2122

2223
class InvocationMetricsRecorder:
2324
"""Records duration and token usage histograms for GenAI invocations."""

util/opentelemetry-util-genai/src/opentelemetry/util/genai/types.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,17 @@
2222
from typing_extensions import TypeAlias
2323

2424
from opentelemetry.context import Context
25+
from opentelemetry.semconv.attributes import error_attributes
2526
from opentelemetry.trace import INVALID_SPAN as _INVALID_SPAN
2627
from opentelemetry.trace import Span, SpanKind
28+
from opentelemetry.trace.status import Status, StatusCode
2729

2830
if TYPE_CHECKING:
2931
from opentelemetry.util.genai.handler import TelemetryHandler
30-
from opentelemetry.semconv.attributes import error_attributes
31-
from opentelemetry.trace.status import Status, StatusCode
3232

3333
ContextToken: TypeAlias = Token[Context]
3434

3535

36-
@dataclass()
37-
class GenericPart:
38-
"""Used for provider-specific message part types that don't match
39-
the standard MessagePart types defined in semantic conventions. Wrap custom
40-
types with GenericPart(value=...) to explicitly opt-in to non-standard types.
41-
This will be removed in a future version when all instrumentations use core types."""
42-
43-
value: Any
44-
type: Literal["generic"] = "generic"
45-
46-
4736
class ContentCapturingMode(Enum):
4837
# Do not capture content (default).
4938
NO_CONTENT = 0
@@ -55,6 +44,17 @@ class ContentCapturingMode(Enum):
5544
SPAN_AND_EVENT = 3
5645

5746

47+
@dataclass()
48+
class GenericPart:
49+
"""Used for provider-specific message part types that don't match
50+
the standard MessagePart types defined in semantic conventions. Wrap custom
51+
types with GenericPart(value=...) to explicitly opt-in to non-standard types.
52+
This will be removed in a future version when all instrumentations use core types."""
53+
54+
value: Any
55+
type: Literal["generic"] = "generic"
56+
57+
5858
@dataclass()
5959
class ToolCallRequest:
6060
"""Represents a tool call requested by the model (message part only).
@@ -293,7 +293,6 @@ def _apply_error_attributes(self, error: Error) -> None:
293293
def _apply_finish(self, _error: Error | None = None) -> None:
294294
"""Apply finish telemetry (attributes, metrics, events)."""
295295
# nothing to do at the base class level
296-
pass
297296

298297
def stop(self) -> None:
299298
"""Finalize the invocation successfully and end its span."""
@@ -306,6 +305,11 @@ def fail(self, error: Error | BaseException) -> None:
306305
self._handler._finish(self, error)
307306

308307

309-
from opentelemetry.util.genai.inference_invocation import (
310-
LLMInvocation, # noqa: F401
311-
)
308+
def __getattr__(name: str) -> object:
309+
if name == "LLMInvocation":
310+
from opentelemetry.util.genai.inference_invocation import ( # noqa: PLC0415 # pylint: disable=import-outside-toplevel
311+
LLMInvocation,
312+
)
313+
314+
return LLMInvocation
315+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

util/opentelemetry-util-genai/src/opentelemetry/util/genai/utils.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import os
2020
from base64 import b64encode
2121
from functools import partial
22-
from typing import TYPE_CHECKING, Any
22+
from typing import Any
2323

2424
from opentelemetry.instrumentation._semconv import (
2525
_OpenTelemetrySemanticConventionStability,
@@ -30,9 +30,7 @@
3030
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT,
3131
OTEL_INSTRUMENTATION_GENAI_EMIT_EVENT,
3232
)
33-
34-
if TYPE_CHECKING:
35-
from opentelemetry.util.genai.types import ContentCapturingMode
33+
from opentelemetry.util.genai.types import ContentCapturingMode
3634

3735
logger = logging.getLogger(__name__)
3836

@@ -50,8 +48,6 @@ def get_content_capturing_mode() -> ContentCapturingMode:
5048
"""This function should not be called when GEN_AI stability mode is set to DEFAULT.
5149
5250
When the GEN_AI stability mode is DEFAULT this function will raise a ValueError -- see the code below."""
53-
from opentelemetry.util.genai.types import ContentCapturingMode
54-
5551
envvar = os.environ.get(OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT)
5652
if not is_experimental_mode():
5753
raise ValueError(
@@ -99,8 +95,6 @@ def should_emit_event() -> bool:
9995

10096
# If not explicitly set (or invalid), determine default based on content capturing mode
10197
try:
102-
from opentelemetry.util.genai.types import ContentCapturingMode
103-
10498
if not is_experimental_mode():
10599
# Not in experimental mode, default to False
106100
return False
@@ -121,8 +115,6 @@ def should_emit_event() -> bool:
121115

122116
def should_capture_content_on_spans_in_experimental_mode() -> bool:
123117
"""Return True when content conversion should be performed."""
124-
from opentelemetry.util.genai.types import ContentCapturingMode
125-
126118
if not is_experimental_mode():
127119
return False
128120
mode = get_content_capturing_mode()

util/opentelemetry-util-genai/src/opentelemetry/util/genai/workflow_invocation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
)
2323
from opentelemetry.trace import SpanKind
2424
from opentelemetry.util.genai.types import (
25-
ContentCapturingMode,
2625
Error,
2726
GenAIInvocation,
2827
InputMessage,
2928
OutputMessage,
3029
)
3130
from opentelemetry.util.genai.utils import (
31+
ContentCapturingMode,
3232
gen_ai_json_dumps,
3333
get_content_capturing_mode,
3434
is_experimental_mode,

0 commit comments

Comments
 (0)