Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
02adc40
Duplicate: add _semconv schem_url helper
tammy-baylis-swi Mar 27, 2026
6cc6600
Redis Http,Database semconv opt in
tammy-baylis-swi Mar 27, 2026
269949b
Changelog
tammy-baylis-swi Mar 27, 2026
aadf1d2
semconv status generated
tammy-baylis-swi Mar 27, 2026
1d4d6d5
lint
tammy-baylis-swi Mar 27, 2026
1c7e3cc
Add dep for py39 redis test
tammy-baylis-swi Mar 30, 2026
1a033fb
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi Apr 2, 2026
fafc229
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi Apr 6, 2026
ef149b3
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi Apr 7, 2026
e2f5f0f
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi Apr 20, 2026
f2c0940
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi Apr 30, 2026
ea83a81
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi May 4, 2026
1d9f2a0
Add _set_db_redis_database_index
tammy-baylis-swi May 4, 2026
54881b8
Add _set_net_transport
tammy-baylis-swi May 4, 2026
b1fde84
Add _get_semconv_opt_in_modes
tammy-baylis-swi May 4, 2026
732d1e7
TestBase and async coverage
tammy-baylis-swi May 5, 2026
34de467
Add more attr asserts
tammy-baylis-swi May 5, 2026
23280ae
Add test_pipeline attr asserts
tammy-baylis-swi May 5, 2026
961bab7
Rm dep not needed since no py39
tammy-baylis-swi May 5, 2026
19ebb5b
pylint
tammy-baylis-swi May 5, 2026
cf2d4dd
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi May 5, 2026
93a9f89
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi May 6, 2026
f66e625
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi May 8, 2026
8739bca
oops
tammy-baylis-swi May 8, 2026
8a427f8
lint
tammy-baylis-swi May 8, 2026
516232f
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi May 8, 2026
8fa5888
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi May 12, 2026
69e874d
test async redis stability_mode
tammy-baylis-swi May 12, 2026
10cb39d
Mv _get_semconv_modes to util
tammy-baylis-swi May 12, 2026
ce89049
Merge branch 'main' into redis-semconv-opt-in
tammy-baylis-swi May 12, 2026
0ac6c02
Merge branch 'main' into redis-semconv-opt-in
lzchen May 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#4212](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4212))
- `opentelemetry-instrumentation-botocore`: Add support for instrumenting `aiobotocore`
([#4049](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4049))
- `opentelemetry-instrumentation-redis`: implement new semantic convention opt-in migration
([#4370](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4370))

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion instrumentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
| [opentelemetry-instrumentation-pymssql](./opentelemetry-instrumentation-pymssql) | pymssql >= 2.1.5, < 3 | No | development
| [opentelemetry-instrumentation-pymysql](./opentelemetry-instrumentation-pymysql) | PyMySQL < 2 | No | development
| [opentelemetry-instrumentation-pyramid](./opentelemetry-instrumentation-pyramid) | pyramid >= 1.7 | Yes | migration
| [opentelemetry-instrumentation-redis](./opentelemetry-instrumentation-redis) | redis >= 2.6 | No | development
| [opentelemetry-instrumentation-redis](./opentelemetry-instrumentation-redis) | redis >= 2.6 | No | migration
| [opentelemetry-instrumentation-remoulade](./opentelemetry-instrumentation-remoulade) | remoulade >= 0.50 | No | development
| [opentelemetry-instrumentation-requests](./opentelemetry-instrumentation-requests) | requests ~= 2.0 | Yes | migration
| [opentelemetry-instrumentation-sqlalchemy](./opentelemetry-instrumentation-sqlalchemy) | sqlalchemy >= 1.0.0, < 2.1.0 | Yes | development
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ def response_hook(span, instance, response):
from wrapt import wrap_function_wrapper

from opentelemetry import trace
from opentelemetry.instrumentation._semconv import (
_get_schema_url_for_signal_types,
_OpenTelemetrySemanticConventionStability,
_OpenTelemetryStabilitySignalType,
_set_db_statement,
)
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.redis.package import _instruments
from opentelemetry.instrumentation.redis.util import (
Expand All @@ -167,9 +173,6 @@ def response_hook(span, instance, response):
is_instrumentation_enabled,
unwrap,
)
from opentelemetry.semconv._incubating.attributes.db_attributes import (
DB_STATEMENT,
)
from opentelemetry.trace import (
StatusCode,
Tracer,
Expand Down Expand Up @@ -222,6 +225,15 @@ def _traced_execute_factory(
request_hook: RequestHook | None = None,
response_hook: ResponseHook | None = None,
):
# Get semconv opt-in modes for database and HTTP signal types
_OpenTelemetrySemanticConventionStability._initialize()
Comment thread
tammy-baylis-swi marked this conversation as resolved.
Outdated
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.DATABASE
)
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.HTTP
)

def _traced_execute_command(
func: Callable[..., R],
instance: RedisInstance,
Expand All @@ -237,9 +249,20 @@ def _traced_execute_command(
name, kind=trace.SpanKind.CLIENT
) as span:
if span.is_recording():
span.set_attribute(DB_STATEMENT, query)
_set_connection_attributes(span, instance)
span.set_attribute("db.redis.args_length", len(args))
span_attrs = {}
_set_db_statement(span_attrs, query, db_sem_conv_opt_in_mode)
span_attrs["db.redis.args_length"] = len(args)

# Set all DB attributes
for key, value in span_attrs.items():
span.set_attribute(key, value)

_set_connection_attributes(
span,
instance,
db_sem_conv_opt_in_mode,
http_sem_conv_opt_in_mode,
)
if span.name == "redis.create_index":
_add_create_attributes(span, args)
if callable(request_hook):
Expand All @@ -260,6 +283,15 @@ def _traced_execute_pipeline_factory(
request_hook: RequestHook | None = None,
response_hook: ResponseHook | None = None,
):
# Get semconv opt-in modes for database and HTTP signal types
_OpenTelemetrySemanticConventionStability._initialize()
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.DATABASE
)
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.HTTP
)

def _traced_execute_pipeline(
func: Callable[..., R],
instance: PipelineInstance,
Expand All @@ -279,10 +311,21 @@ def _traced_execute_pipeline(
span_name, kind=trace.SpanKind.CLIENT
) as span:
if span.is_recording():
span.set_attribute(DB_STATEMENT, resource)
_set_connection_attributes(span, instance)
span.set_attribute(
"db.redis.pipeline_length", len(command_stack)
span_attrs = {}
_set_db_statement(
span_attrs, resource, db_sem_conv_opt_in_mode
)
span_attrs["db.redis.pipeline_length"] = len(command_stack)

# Set all DB attributes
for key, value in span_attrs.items():
span.set_attribute(key, value)

_set_connection_attributes(
span,
instance,
db_sem_conv_opt_in_mode,
http_sem_conv_opt_in_mode,
)

response = None
Expand All @@ -308,6 +351,15 @@ def _async_traced_execute_factory(
request_hook: RequestHook | None = None,
response_hook: ResponseHook | None = None,
):
# Get semconv opt-in modes for database and HTTP signal types
_OpenTelemetrySemanticConventionStability._initialize()
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.DATABASE
)
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.HTTP
)

async def _async_traced_execute_command(
func: Callable[..., Awaitable[R]],
instance: AsyncRedisInstance,
Expand All @@ -324,9 +376,20 @@ async def _async_traced_execute_command(
name, kind=trace.SpanKind.CLIENT
) as span:
if span.is_recording():
span.set_attribute(DB_STATEMENT, query)
_set_connection_attributes(span, instance)
span.set_attribute("db.redis.args_length", len(args))
span_attrs = {}
_set_db_statement(span_attrs, query, db_sem_conv_opt_in_mode)
span_attrs["db.redis.args_length"] = len(args)

# Set all DB attributes
for key, value in span_attrs.items():
span.set_attribute(key, value)

_set_connection_attributes(
span,
instance,
db_sem_conv_opt_in_mode,
http_sem_conv_opt_in_mode,
)
if callable(request_hook):
request_hook(span, instance, args, kwargs)
response = await func(*args, **kwargs)
Expand All @@ -342,6 +405,15 @@ def _async_traced_execute_pipeline_factory(
request_hook: RequestHook | None = None,
response_hook: ResponseHook | None = None,
):
# Get semconv opt-in modes for database and HTTP signal types
_OpenTelemetrySemanticConventionStability._initialize()
db_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.DATABASE
)
http_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.HTTP
)

async def _async_traced_execute_pipeline(
func: Callable[..., Awaitable[R]],
instance: AsyncPipelineInstance,
Expand All @@ -363,10 +435,21 @@ async def _async_traced_execute_pipeline(
span_name, kind=trace.SpanKind.CLIENT
) as span:
if span.is_recording():
span.set_attribute(DB_STATEMENT, resource)
_set_connection_attributes(span, instance)
span.set_attribute(
"db.redis.pipeline_length", len(command_stack)
span_attrs = {}
_set_db_statement(
span_attrs, resource, db_sem_conv_opt_in_mode
)
span_attrs["db.redis.pipeline_length"] = len(command_stack)

# Set all DB attributes
for key, value in span_attrs.items():
span.set_attribute(key, value)

_set_connection_attributes(
span,
instance,
db_sem_conv_opt_in_mode,
http_sem_conv_opt_in_mode,
)

response = None
Expand Down Expand Up @@ -540,12 +623,20 @@ def _pipeline_wrapper(func, instance, args, kwargs):
class RedisInstrumentor(BaseInstrumentor):
@staticmethod
def _get_tracer(**kwargs):
# Initialize semantic conventions opt-in if needed
_OpenTelemetrySemanticConventionStability._initialize()
# Redis instrumentation supports both DATABASE and HTTP signal types
signal_types = [
_OpenTelemetryStabilitySignalType.DATABASE,
_OpenTelemetryStabilitySignalType.HTTP,
]

tracer_provider = kwargs.get("tracer_provider")
return get_tracer(
__name__,
__version__,
tracer_provider=tracer_provider,
schema_url="https://opentelemetry.io/schemas/1.11.0",
schema_url=_get_schema_url_for_signal_types(signal_types),
)

def instrument(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@


_instruments = ("redis >= 2.6",)

_semconv_status = "migration"
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@

from typing import TYPE_CHECKING, Any

from opentelemetry.instrumentation._semconv import (
_set_db_system,
_set_http_net_peer_name_client,
_set_http_peer_port_client,
)
from opentelemetry.semconv._incubating.attributes.db_attributes import (
DB_REDIS_DATABASE_INDEX,
DB_SYSTEM,
)
from opentelemetry.semconv._incubating.attributes.net_attributes import (
NET_PEER_NAME,
NET_PEER_PORT,
NET_TRANSPORT,
)
from opentelemetry.semconv.trace import (
Expand All @@ -46,19 +48,33 @@
_FIELD_TYPES = ["NUMERIC", "TEXT", "GEO", "TAG", "VECTOR"]


def _extract_conn_attributes(conn_kwargs):
def _extract_conn_attributes(
conn_kwargs, db_sem_conv_opt_in_mode, http_sem_conv_opt_in_mode
):
"""Transform redis conn info into dict"""
attributes = {
DB_SYSTEM: DbSystemValues.REDIS.value,
}
attributes = {}
_set_db_system(
attributes, DbSystemValues.REDIS.value, db_sem_conv_opt_in_mode
)

db = conn_kwargs.get("db", 0)
attributes[DB_REDIS_DATABASE_INDEX] = db
Comment thread
tammy-baylis-swi marked this conversation as resolved.
Outdated
if "path" in conn_kwargs:
attributes[NET_PEER_NAME] = conn_kwargs.get("path", "")
_set_http_net_peer_name_client(
attributes, conn_kwargs.get("path", ""), http_sem_conv_opt_in_mode
)
attributes[NET_TRANSPORT] = NetTransportValues.OTHER.value
Comment thread
tammy-baylis-swi marked this conversation as resolved.
Outdated
else:
attributes[NET_PEER_NAME] = conn_kwargs.get("host", "localhost")
attributes[NET_PEER_PORT] = conn_kwargs.get("port", 6379)
_set_http_net_peer_name_client(
attributes,
conn_kwargs.get("host", "localhost"),
http_sem_conv_opt_in_mode,
)
_set_http_peer_port_client(
attributes,
conn_kwargs.get("port", 6379),
http_sem_conv_opt_in_mode,
)
attributes[NET_TRANSPORT] = NetTransportValues.IP_TCP.value
Comment thread
tammy-baylis-swi marked this conversation as resolved.
Outdated

return attributes
Expand Down Expand Up @@ -99,12 +115,17 @@ def _value_or_none(values, n):


def _set_connection_attributes(
span: Span, conn: RedisInstance | AsyncRedisInstance
span: Span,
conn: RedisInstance | AsyncRedisInstance,
db_sem_conv_opt_in_mode,
http_sem_conv_opt_in_mode,
) -> None:
if not span.is_recording() or not hasattr(conn, "connection_pool"):
return
for key, value in _extract_conn_attributes(
conn.connection_pool.connection_kwargs
conn.connection_pool.connection_kwargs,
db_sem_conv_opt_in_mode,
http_sem_conv_opt_in_mode,
).items():
span.set_attribute(key, value)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ packaging==24.0
pluggy==1.6.0
py-cpuinfo==9.0.0
pytest==7.4.4
pytest-asyncio==0.23.5
Comment thread
tammy-baylis-swi marked this conversation as resolved.
Outdated
redis==5.0.1
tomli==2.0.1
typing_extensions==4.12.2
Expand Down
Loading
Loading