Skip to content

Commit ec42339

Browse files
committed
initial commit
1 parent 032d6c6 commit ec42339

File tree

6 files changed

+189
-4
lines changed

6 files changed

+189
-4
lines changed

opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,10 @@
162162
OTEL_SEMCONV_STABILITY_OPT_IN = "OTEL_SEMCONV_STABILITY_OPT_IN"
163163

164164

165-
class _OpenTelemetryStabilitySignalType:
165+
class _OpenTelemetryStabilitySignalType(Enum):
166166
HTTP = "http"
167167
DATABASE = "database"
168+
GEN_AI = "gen_ai"
168169

169170

170171
class _StabilityMode(Enum):
@@ -173,6 +174,7 @@ class _StabilityMode(Enum):
173174
HTTP_DUP = "http/dup"
174175
DATABASE = "database"
175176
DATABASE_DUP = "database/dup"
177+
GEN_AI_LATEST = "gen_ai_latest_experimental"
176178

177179

178180
def _report_new(mode: _StabilityMode):
@@ -195,24 +197,27 @@ def _initialize(cls):
195197
return
196198

197199
# Users can pass in comma delimited string for opt-in options
198-
# Only values for http and database stability are supported for now
200+
# Only values for http, gen ai, and database stability are supported for now
199201
opt_in = os.environ.get(OTEL_SEMCONV_STABILITY_OPT_IN)
200202

201203
if not opt_in:
202204
# early return in case of default
203205
cls._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING = {
204206
_OpenTelemetryStabilitySignalType.HTTP: _StabilityMode.DEFAULT,
205207
_OpenTelemetryStabilitySignalType.DATABASE: _StabilityMode.DEFAULT,
208+
_OpenTelemetryStabilitySignalType.GEN_AI: _StabilityMode.DEFAULT,
206209
}
207210
cls._initialized = True
208211
return
209212

210213
opt_in_list = [s.strip() for s in opt_in.split(",")]
211214

212215
cls._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[
213-
_OpenTelemetryStabilitySignalType.HTTP
216+
_OpenTelemetryStabilitySignalType.GEN_AI
214217
] = cls._filter_mode(
215-
opt_in_list, _StabilityMode.HTTP, _StabilityMode.HTTP_DUP
218+
opt_in_list,
219+
_StabilityMode.DEFAULT,
220+
_StabilityMode.GEN_AI_LATEST,
216221
)
217222

218223
cls._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[

opentelemetry-instrumentation/tests/test_semconv.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ def test_default_mode(self):
5454
),
5555
_StabilityMode.DEFAULT,
5656
)
57+
self.assertEqual(
58+
_OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
59+
_OpenTelemetryStabilitySignalType.GEN_AI
60+
),
61+
_StabilityMode.DEFAULT,
62+
)
5763

5864
@stability_mode("http")
5965
def test_http_stable_mode(self):
@@ -91,6 +97,15 @@ def test_database_dup_mode(self):
9197
_StabilityMode.DATABASE_DUP,
9298
)
9399

100+
@stability_mode("gen_ai_latest_experimental")
101+
def test_genai_latest_experimental(self):
102+
self.assertEqual(
103+
_OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
104+
_OpenTelemetryStabilitySignalType.GEN_AI
105+
),
106+
_StabilityMode.GEN_AI_LATEST,
107+
)
108+
94109
@stability_mode("database,http")
95110
def test_multiple_stability_database_http_modes(self):
96111
self.assertEqual(
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = (
16+
"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
17+
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 enum import Enum
16+
17+
18+
class ContentCapturingMode(Enum):
19+
# Do not capture content (default).
20+
NO_CONTENT = 0
21+
# Only capture content in spans.
22+
SPAN_ONLY = 1
23+
# Only capture content in events.
24+
EVENT_ONLY = 2
25+
# Capture content in both spans and events.
26+
SPAN_AND_EVENT = 3
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
import os
16+
17+
from opentelemetry.instrumentation._semconv import (
18+
_OpenTelemetrySemanticConventionStability,
19+
_OpenTelemetryStabilitySignalType,
20+
_StabilityMode,
21+
)
22+
from opentelemetry.util.genai.environment_variables import (
23+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT,
24+
)
25+
from opentelemetry.util.genai.types import ContentCapturingMode
26+
27+
28+
def get_content_capturing_mode() -> ContentCapturingMode:
29+
envvar = os.environ.get(OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT)
30+
if (
31+
_OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
32+
_OpenTelemetryStabilitySignalType.GEN_AI,
33+
)
34+
== _StabilityMode.DEFAULT
35+
):
36+
raise RuntimeError(
37+
"This function should never be called when StabilityMode is default.."
38+
)
39+
if not envvar:
40+
return ContentCapturingMode.NO_CONTENT
41+
try:
42+
return ContentCapturingMode[envvar.upper()]
43+
except KeyError:
44+
raise RuntimeError(
45+
"{} is not a valid option for `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` environment variable. Must be one of {}".format(
46+
envvar, ", ".join([e.name for e in ContentCapturingMode])
47+
)
48+
)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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+
import os
16+
import unittest
17+
from unittest.mock import patch
18+
19+
from opentelemetry.instrumentation._semconv import (
20+
OTEL_SEMCONV_STABILITY_OPT_IN,
21+
_OpenTelemetrySemanticConventionStability,
22+
)
23+
from opentelemetry.util.genai.environment_variables import (
24+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT,
25+
)
26+
from opentelemetry.util.genai.types import ContentCapturingMode
27+
from opentelemetry.util.genai.utils import get_content_capturing_mode
28+
29+
30+
def patch_env_vars(stability_mode, content_capturing):
31+
def decorator(test_case):
32+
@patch.dict(
33+
os.environ,
34+
{
35+
OTEL_SEMCONV_STABILITY_OPT_IN: stability_mode,
36+
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT: content_capturing,
37+
},
38+
)
39+
def wrapper(*args, **kwargs):
40+
# Reset state.
41+
_OpenTelemetrySemanticConventionStability._initialized = False
42+
_OpenTelemetrySemanticConventionStability._initialize()
43+
return test_case(*args, **kwargs)
44+
45+
return wrapper
46+
47+
return decorator
48+
49+
50+
class TestVersion(unittest.TestCase):
51+
@patch_env_vars("gen_ai_latest_experimental", "SPAN_ONLY")
52+
def test_get_content_caputring_mode_parses_valid_envvar(self): # pylint: disable=no-self-use
53+
_OpenTelemetrySemanticConventionStability._initialized = False
54+
assert get_content_capturing_mode() == ContentCapturingMode.SPAN_ONLY
55+
56+
@patch_env_vars("gen_ai_latest_experimental", "")
57+
def test_empty_content_capturing_envvar(self): # pylint: disable=no-self-use
58+
_OpenTelemetrySemanticConventionStability._initialized = False
59+
assert get_content_capturing_mode() == ContentCapturingMode.NO_CONTENT
60+
61+
@patch_env_vars("default", "True")
62+
def test_get_content_caputring_mode_raises_exception_when_semconv_stability_default(
63+
self,
64+
): # pylint: disable=no-self-use
65+
_OpenTelemetrySemanticConventionStability._initialized = False
66+
with self.assertRaises(RuntimeError):
67+
get_content_capturing_mode()
68+
69+
@patch_env_vars("gen_ai_latest_experimental", "INVALID_VALUE")
70+
def test_get_content_caputring_mode_raises_exception_on_invalid_envvar(
71+
self,
72+
): # pylint: disable=no-self-use
73+
with self.assertRaises(RuntimeError):
74+
get_content_capturing_mode()

0 commit comments

Comments
 (0)