Update semconv utilities to support opt into >=1.33.0 db_attributes (#4108)

* Add _semconv set_db fns

* lint

* Changelog
This commit is contained in:
Tammy Baylis
2026-01-21 03:36:48 -08:00
committed by GitHub
parent be56431caa
commit b31b80eb50
3 changed files with 228 additions and 0 deletions

View File

@@ -37,6 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#4051](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4051))
- `opentelemetry-instrumentation-aiohttp-server` Implement new semantic convention opt-in migration
([#3980](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3980))
- `opentelemetry-instrumentation`: add database stability attribute setters in `_semconv` utilities
([#4108](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4108))
### Fixed

View File

@@ -20,6 +20,12 @@ from enum import Enum
from typing import Container, Mapping, MutableMapping
from opentelemetry.instrumentation.utils import http_status_to_status_code
from opentelemetry.semconv._incubating.attributes.db_attributes import (
DB_NAME,
DB_STATEMENT,
DB_SYSTEM,
DB_USER,
)
from opentelemetry.semconv._incubating.attributes.http_attributes import (
HTTP_FLAVOR,
HTTP_HOST,
@@ -42,6 +48,11 @@ from opentelemetry.semconv.attributes.client_attributes import (
CLIENT_ADDRESS,
CLIENT_PORT,
)
from opentelemetry.semconv.attributes.db_attributes import (
DB_NAMESPACE,
DB_QUERY_TEXT,
DB_SYSTEM_NAME,
)
from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
from opentelemetry.semconv.attributes.http_attributes import (
HTTP_REQUEST_METHOD,
@@ -533,6 +544,55 @@ def _set_http_net_peer_name_server(
set_string_attribute(result, CLIENT_ADDRESS, name)
# Database
def _set_db_system(
result: MutableMapping[str, AttributeValue],
system: str,
sem_conv_opt_in_mode: _StabilityMode,
) -> None:
if _report_old(sem_conv_opt_in_mode):
set_string_attribute(result, DB_SYSTEM, system)
if _report_new(sem_conv_opt_in_mode):
set_string_attribute(result, DB_SYSTEM_NAME, system)
def _set_db_name(
result: MutableMapping[str, AttributeValue],
name: str,
sem_conv_opt_in_mode: _StabilityMode,
) -> None:
if _report_old(sem_conv_opt_in_mode):
set_string_attribute(result, DB_NAME, name)
if _report_new(sem_conv_opt_in_mode):
set_string_attribute(result, DB_NAMESPACE, name)
def _set_db_statement(
result: MutableMapping[str, AttributeValue],
statement: str,
sem_conv_opt_in_mode: _StabilityMode,
) -> None:
if _report_old(sem_conv_opt_in_mode):
set_string_attribute(result, DB_STATEMENT, statement)
if _report_new(sem_conv_opt_in_mode):
set_string_attribute(result, DB_QUERY_TEXT, statement)
def _set_db_user(
result: MutableMapping[str, AttributeValue],
user: str,
sem_conv_opt_in_mode: _StabilityMode,
) -> None:
if _report_old(sem_conv_opt_in_mode):
set_string_attribute(result, DB_USER, user)
# No new attribute - db.user was removed with no replacement
# General
def _set_status(
span: Span,
metrics_attributes: MutableMapping[str, AttributeValue],

View File

@@ -20,9 +20,24 @@ from opentelemetry.instrumentation._semconv import (
OTEL_SEMCONV_STABILITY_OPT_IN,
_OpenTelemetrySemanticConventionStability,
_OpenTelemetryStabilitySignalType,
_set_db_name,
_set_db_statement,
_set_db_system,
_set_db_user,
_set_status,
_StabilityMode,
)
from opentelemetry.semconv._incubating.attributes.db_attributes import (
DB_NAME,
DB_STATEMENT,
DB_SYSTEM,
DB_USER,
)
from opentelemetry.semconv.attributes.db_attributes import (
DB_NAMESPACE,
DB_QUERY_TEXT,
DB_SYSTEM_NAME,
)
from opentelemetry.trace.status import StatusCode
@@ -277,3 +292,154 @@ class TestOpenTelemetrySemConvStabilityHTTP(TestCase):
# Verify status code set for metrics independent of tracing decision
self.assertIn("http.status_code", metrics_attributes)
self.assertIn("http.response.status_code", metrics_attributes)
class TestOpenTelemetrySemConvStabilityDatabase(TestCase):
def test_db_system_default(self):
result = {}
_set_db_system(
result, "postgresql", sem_conv_opt_in_mode=_StabilityMode.DEFAULT
)
self.assertIn(DB_SYSTEM, result)
self.assertEqual(result[DB_SYSTEM], "postgresql")
self.assertNotIn(DB_SYSTEM_NAME, result)
def test_db_system_database_stable(self):
result = {}
_set_db_system(
result, "postgresql", sem_conv_opt_in_mode=_StabilityMode.DATABASE
)
self.assertNotIn(DB_SYSTEM, result)
self.assertIn(DB_SYSTEM_NAME, result)
self.assertEqual(result[DB_SYSTEM_NAME], "postgresql")
def test_db_system_database_dup(self):
result = {}
_set_db_system(
result,
"postgresql",
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
)
self.assertIn(DB_SYSTEM, result)
self.assertEqual(result[DB_SYSTEM], "postgresql")
self.assertIn(DB_SYSTEM_NAME, result)
self.assertEqual(result[DB_SYSTEM_NAME], "postgresql")
def test_db_system_none_value(self):
result = {}
_set_db_system(
result, None, sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP
)
self.assertNotIn(DB_SYSTEM, result)
self.assertNotIn(DB_SYSTEM_NAME, result)
def test_db_name_default(self):
result = {}
_set_db_name(
result, "my_database", sem_conv_opt_in_mode=_StabilityMode.DEFAULT
)
self.assertIn(DB_NAME, result)
self.assertEqual(result[DB_NAME], "my_database")
self.assertNotIn(DB_NAMESPACE, result)
def test_db_name_database_stable(self):
result = {}
_set_db_name(
result, "my_database", sem_conv_opt_in_mode=_StabilityMode.DATABASE
)
self.assertNotIn(DB_NAME, result)
self.assertIn(DB_NAMESPACE, result)
self.assertEqual(result[DB_NAMESPACE], "my_database")
def test_db_name_database_dup(self):
result = {}
_set_db_name(
result,
"my_database",
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
)
self.assertIn(DB_NAME, result)
self.assertEqual(result[DB_NAME], "my_database")
self.assertIn(DB_NAMESPACE, result)
self.assertEqual(result[DB_NAMESPACE], "my_database")
def test_db_name_none_value(self):
result = {}
_set_db_name(
result, None, sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP
)
self.assertNotIn(DB_NAME, result)
self.assertNotIn(DB_NAMESPACE, result)
def test_db_statement_default(self):
result = {}
_set_db_statement(
result,
"SELECT * FROM users",
sem_conv_opt_in_mode=_StabilityMode.DEFAULT,
)
self.assertIn(DB_STATEMENT, result)
self.assertEqual(result[DB_STATEMENT], "SELECT * FROM users")
self.assertNotIn(DB_QUERY_TEXT, result)
def test_db_statement_database_stable(self):
result = {}
_set_db_statement(
result,
"SELECT * FROM users",
sem_conv_opt_in_mode=_StabilityMode.DATABASE,
)
self.assertNotIn(DB_STATEMENT, result)
self.assertIn(DB_QUERY_TEXT, result)
self.assertEqual(result[DB_QUERY_TEXT], "SELECT * FROM users")
def test_db_statement_database_dup(self):
result = {}
_set_db_statement(
result,
"SELECT * FROM users",
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
)
self.assertIn(DB_STATEMENT, result)
self.assertEqual(result[DB_STATEMENT], "SELECT * FROM users")
self.assertIn(DB_QUERY_TEXT, result)
self.assertEqual(result[DB_QUERY_TEXT], "SELECT * FROM users")
def test_db_statement_none_value(self):
result = {}
_set_db_statement(
result, None, sem_conv_opt_in_mode=_StabilityMode.DEFAULT
)
self.assertNotIn(DB_STATEMENT, result)
self.assertNotIn(DB_QUERY_TEXT, result)
def test_db_user_default(self):
result = {}
_set_db_user(
result, "admin", sem_conv_opt_in_mode=_StabilityMode.DEFAULT
)
self.assertIn(DB_USER, result)
self.assertEqual(result[DB_USER], "admin")
def test_db_user_database_stable(self):
result = {}
_set_db_user(
result, "admin", sem_conv_opt_in_mode=_StabilityMode.DATABASE
)
# No new attribute - db.user was removed with no replacement
self.assertNotIn(DB_USER, result)
def test_db_user_database_dup(self):
result = {}
_set_db_user(
result,
"admin",
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
)
self.assertIn(DB_USER, result)
self.assertEqual(result[DB_USER], "admin")
def test_db_user_none_value(self):
result = {}
_set_db_user(result, None, sem_conv_opt_in_mode=_StabilityMode.DEFAULT)
self.assertNotIn(DB_USER, result)