Skip to content

Commit 6cc6600

Browse files
Redis Http,Database semconv opt in
1 parent 02adc40 commit 6cc6600

4 files changed

Lines changed: 525 additions & 31 deletions

File tree

instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py

Lines changed: 109 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ def response_hook(span, instance, response):
152152
from wrapt import wrap_function_wrapper
153153

154154
from opentelemetry import trace
155+
from opentelemetry.instrumentation._semconv import (
156+
_get_schema_url_for_signal_types,
157+
_OpenTelemetrySemanticConventionStability,
158+
_OpenTelemetryStabilitySignalType,
159+
_set_db_statement,
160+
)
155161
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
156162
from opentelemetry.instrumentation.redis.package import _instruments
157163
from opentelemetry.instrumentation.redis.util import (
@@ -167,9 +173,6 @@ def response_hook(span, instance, response):
167173
is_instrumentation_enabled,
168174
unwrap,
169175
)
170-
from opentelemetry.semconv._incubating.attributes.db_attributes import (
171-
DB_STATEMENT,
172-
)
173176
from opentelemetry.trace import (
174177
StatusCode,
175178
Tracer,
@@ -222,6 +225,15 @@ def _traced_execute_factory(
222225
request_hook: RequestHook | None = None,
223226
response_hook: ResponseHook | None = None,
224227
):
228+
# Get semconv opt-in modes for database and HTTP signal types
229+
_OpenTelemetrySemanticConventionStability._initialize()
230+
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
231+
_OpenTelemetryStabilitySignalType.DATABASE
232+
)
233+
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
234+
_OpenTelemetryStabilitySignalType.HTTP
235+
)
236+
225237
def _traced_execute_command(
226238
func: Callable[..., R],
227239
instance: RedisInstance,
@@ -237,9 +249,20 @@ def _traced_execute_command(
237249
name, kind=trace.SpanKind.CLIENT
238250
) as span:
239251
if span.is_recording():
240-
span.set_attribute(DB_STATEMENT, query)
241-
_set_connection_attributes(span, instance)
242-
span.set_attribute("db.redis.args_length", len(args))
252+
span_attrs = {}
253+
_set_db_statement(span_attrs, query, db_sem_conv_opt_in_mode)
254+
span_attrs["db.redis.args_length"] = len(args)
255+
256+
# Set all DB attributes
257+
for key, value in span_attrs.items():
258+
span.set_attribute(key, value)
259+
260+
_set_connection_attributes(
261+
span,
262+
instance,
263+
db_sem_conv_opt_in_mode,
264+
http_sem_conv_opt_in_mode,
265+
)
243266
if span.name == "redis.create_index":
244267
_add_create_attributes(span, args)
245268
if callable(request_hook):
@@ -260,6 +283,15 @@ def _traced_execute_pipeline_factory(
260283
request_hook: RequestHook | None = None,
261284
response_hook: ResponseHook | None = None,
262285
):
286+
# Get semconv opt-in modes for database and HTTP signal types
287+
_OpenTelemetrySemanticConventionStability._initialize()
288+
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
289+
_OpenTelemetryStabilitySignalType.DATABASE
290+
)
291+
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
292+
_OpenTelemetryStabilitySignalType.HTTP
293+
)
294+
263295
def _traced_execute_pipeline(
264296
func: Callable[..., R],
265297
instance: PipelineInstance,
@@ -279,10 +311,21 @@ def _traced_execute_pipeline(
279311
span_name, kind=trace.SpanKind.CLIENT
280312
) as span:
281313
if span.is_recording():
282-
span.set_attribute(DB_STATEMENT, resource)
283-
_set_connection_attributes(span, instance)
284-
span.set_attribute(
285-
"db.redis.pipeline_length", len(command_stack)
314+
span_attrs = {}
315+
_set_db_statement(
316+
span_attrs, resource, db_sem_conv_opt_in_mode
317+
)
318+
span_attrs["db.redis.pipeline_length"] = len(command_stack)
319+
320+
# Set all DB attributes
321+
for key, value in span_attrs.items():
322+
span.set_attribute(key, value)
323+
324+
_set_connection_attributes(
325+
span,
326+
instance,
327+
db_sem_conv_opt_in_mode,
328+
http_sem_conv_opt_in_mode,
286329
)
287330

288331
response = None
@@ -308,6 +351,15 @@ def _async_traced_execute_factory(
308351
request_hook: RequestHook | None = None,
309352
response_hook: ResponseHook | None = None,
310353
):
354+
# Get semconv opt-in modes for database and HTTP signal types
355+
_OpenTelemetrySemanticConventionStability._initialize()
356+
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
357+
_OpenTelemetryStabilitySignalType.DATABASE
358+
)
359+
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
360+
_OpenTelemetryStabilitySignalType.HTTP
361+
)
362+
311363
async def _async_traced_execute_command(
312364
func: Callable[..., Awaitable[R]],
313365
instance: AsyncRedisInstance,
@@ -324,9 +376,20 @@ async def _async_traced_execute_command(
324376
name, kind=trace.SpanKind.CLIENT
325377
) as span:
326378
if span.is_recording():
327-
span.set_attribute(DB_STATEMENT, query)
328-
_set_connection_attributes(span, instance)
329-
span.set_attribute("db.redis.args_length", len(args))
379+
span_attrs = {}
380+
_set_db_statement(span_attrs, query, db_sem_conv_opt_in_mode)
381+
span_attrs["db.redis.args_length"] = len(args)
382+
383+
# Set all DB attributes
384+
for key, value in span_attrs.items():
385+
span.set_attribute(key, value)
386+
387+
_set_connection_attributes(
388+
span,
389+
instance,
390+
db_sem_conv_opt_in_mode,
391+
http_sem_conv_opt_in_mode,
392+
)
330393
if callable(request_hook):
331394
request_hook(span, instance, args, kwargs)
332395
response = await func(*args, **kwargs)
@@ -342,6 +405,15 @@ def _async_traced_execute_pipeline_factory(
342405
request_hook: RequestHook | None = None,
343406
response_hook: ResponseHook | None = None,
344407
):
408+
# Get semconv opt-in modes for database and HTTP signal types
409+
_OpenTelemetrySemanticConventionStability._initialize()
410+
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
411+
_OpenTelemetryStabilitySignalType.DATABASE
412+
)
413+
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
414+
_OpenTelemetryStabilitySignalType.HTTP
415+
)
416+
345417
async def _async_traced_execute_pipeline(
346418
func: Callable[..., Awaitable[R]],
347419
instance: AsyncPipelineInstance,
@@ -363,10 +435,21 @@ async def _async_traced_execute_pipeline(
363435
span_name, kind=trace.SpanKind.CLIENT
364436
) as span:
365437
if span.is_recording():
366-
span.set_attribute(DB_STATEMENT, resource)
367-
_set_connection_attributes(span, instance)
368-
span.set_attribute(
369-
"db.redis.pipeline_length", len(command_stack)
438+
span_attrs = {}
439+
_set_db_statement(
440+
span_attrs, resource, db_sem_conv_opt_in_mode
441+
)
442+
span_attrs["db.redis.pipeline_length"] = len(command_stack)
443+
444+
# Set all DB attributes
445+
for key, value in span_attrs.items():
446+
span.set_attribute(key, value)
447+
448+
_set_connection_attributes(
449+
span,
450+
instance,
451+
db_sem_conv_opt_in_mode,
452+
http_sem_conv_opt_in_mode,
370453
)
371454

372455
response = None
@@ -540,12 +623,20 @@ def _pipeline_wrapper(func, instance, args, kwargs):
540623
class RedisInstrumentor(BaseInstrumentor):
541624
@staticmethod
542625
def _get_tracer(**kwargs):
626+
# Initialize semantic conventions opt-in if needed
627+
_OpenTelemetrySemanticConventionStability._initialize()
628+
# Redis instrumentation supports both DATABASE and HTTP signal types
629+
signal_types = [
630+
_OpenTelemetryStabilitySignalType.DATABASE,
631+
_OpenTelemetryStabilitySignalType.HTTP,
632+
]
633+
543634
tracer_provider = kwargs.get("tracer_provider")
544635
return get_tracer(
545636
__name__,
546637
__version__,
547638
tracer_provider=tracer_provider,
548-
schema_url="https://opentelemetry.io/schemas/1.11.0",
639+
schema_url=_get_schema_url_for_signal_types(signal_types),
549640
)
550641

551642
def instrument(

instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/package.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@
1414

1515

1616
_instruments = ("redis >= 2.6",)
17+
18+
_semconv_status = "migration"

instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020

2121
from typing import TYPE_CHECKING, Any
2222

23+
from opentelemetry.instrumentation._semconv import (
24+
_set_db_system,
25+
_set_http_net_peer_name_client,
26+
_set_http_peer_port_client,
27+
)
2328
from opentelemetry.semconv._incubating.attributes.db_attributes import (
2429
DB_REDIS_DATABASE_INDEX,
25-
DB_SYSTEM,
2630
)
2731
from opentelemetry.semconv._incubating.attributes.net_attributes import (
28-
NET_PEER_NAME,
29-
NET_PEER_PORT,
3032
NET_TRANSPORT,
3133
)
3234
from opentelemetry.semconv.trace import (
@@ -46,19 +48,33 @@
4648
_FIELD_TYPES = ["NUMERIC", "TEXT", "GEO", "TAG", "VECTOR"]
4749

4850

49-
def _extract_conn_attributes(conn_kwargs):
51+
def _extract_conn_attributes(
52+
conn_kwargs, db_sem_conv_opt_in_mode, http_sem_conv_opt_in_mode
53+
):
5054
"""Transform redis conn info into dict"""
51-
attributes = {
52-
DB_SYSTEM: DbSystemValues.REDIS.value,
53-
}
55+
attributes = {}
56+
_set_db_system(
57+
attributes, DbSystemValues.REDIS.value, db_sem_conv_opt_in_mode
58+
)
59+
5460
db = conn_kwargs.get("db", 0)
5561
attributes[DB_REDIS_DATABASE_INDEX] = db
5662
if "path" in conn_kwargs:
57-
attributes[NET_PEER_NAME] = conn_kwargs.get("path", "")
63+
_set_http_net_peer_name_client(
64+
attributes, conn_kwargs.get("path", ""), http_sem_conv_opt_in_mode
65+
)
5866
attributes[NET_TRANSPORT] = NetTransportValues.OTHER.value
5967
else:
60-
attributes[NET_PEER_NAME] = conn_kwargs.get("host", "localhost")
61-
attributes[NET_PEER_PORT] = conn_kwargs.get("port", 6379)
68+
_set_http_net_peer_name_client(
69+
attributes,
70+
conn_kwargs.get("host", "localhost"),
71+
http_sem_conv_opt_in_mode,
72+
)
73+
_set_http_peer_port_client(
74+
attributes,
75+
conn_kwargs.get("port", 6379),
76+
http_sem_conv_opt_in_mode,
77+
)
6278
attributes[NET_TRANSPORT] = NetTransportValues.IP_TCP.value
6379

6480
return attributes
@@ -99,12 +115,17 @@ def _value_or_none(values, n):
99115

100116

101117
def _set_connection_attributes(
102-
span: Span, conn: RedisInstance | AsyncRedisInstance
118+
span: Span,
119+
conn: RedisInstance | AsyncRedisInstance,
120+
db_sem_conv_opt_in_mode,
121+
http_sem_conv_opt_in_mode,
103122
) -> None:
104123
if not span.is_recording() or not hasattr(conn, "connection_pool"):
105124
return
106125
for key, value in _extract_conn_attributes(
107-
conn.connection_pool.connection_kwargs
126+
conn.connection_pool.connection_kwargs,
127+
db_sem_conv_opt_in_mode,
128+
http_sem_conv_opt_in_mode,
108129
).items():
109130
span.set_attribute(key, value)
110131

0 commit comments

Comments
 (0)