Skip to content

Commit b31b80e

Browse files
Update semconv utilities to support opt into >=1.33.0 db_attributes (#4108)
* Add _semconv set_db fns * lint * Changelog
1 parent be56431 commit b31b80e

File tree

3 files changed

+228
-0
lines changed

3 files changed

+228
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3737
([#4051](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4051))
3838
- `opentelemetry-instrumentation-aiohttp-server` Implement new semantic convention opt-in migration
3939
([#3980](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3980))
40+
- `opentelemetry-instrumentation`: add database stability attribute setters in `_semconv` utilities
41+
([#4108](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4108))
4042

4143
### Fixed
4244

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

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
from typing import Container, Mapping, MutableMapping
2121

2222
from opentelemetry.instrumentation.utils import http_status_to_status_code
23+
from opentelemetry.semconv._incubating.attributes.db_attributes import (
24+
DB_NAME,
25+
DB_STATEMENT,
26+
DB_SYSTEM,
27+
DB_USER,
28+
)
2329
from opentelemetry.semconv._incubating.attributes.http_attributes import (
2430
HTTP_FLAVOR,
2531
HTTP_HOST,
@@ -42,6 +48,11 @@
4248
CLIENT_ADDRESS,
4349
CLIENT_PORT,
4450
)
51+
from opentelemetry.semconv.attributes.db_attributes import (
52+
DB_NAMESPACE,
53+
DB_QUERY_TEXT,
54+
DB_SYSTEM_NAME,
55+
)
4556
from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
4657
from opentelemetry.semconv.attributes.http_attributes import (
4758
HTTP_REQUEST_METHOD,
@@ -533,6 +544,55 @@ def _set_http_net_peer_name_server(
533544
set_string_attribute(result, CLIENT_ADDRESS, name)
534545

535546

547+
# Database
548+
549+
550+
def _set_db_system(
551+
result: MutableMapping[str, AttributeValue],
552+
system: str,
553+
sem_conv_opt_in_mode: _StabilityMode,
554+
) -> None:
555+
if _report_old(sem_conv_opt_in_mode):
556+
set_string_attribute(result, DB_SYSTEM, system)
557+
if _report_new(sem_conv_opt_in_mode):
558+
set_string_attribute(result, DB_SYSTEM_NAME, system)
559+
560+
561+
def _set_db_name(
562+
result: MutableMapping[str, AttributeValue],
563+
name: str,
564+
sem_conv_opt_in_mode: _StabilityMode,
565+
) -> None:
566+
if _report_old(sem_conv_opt_in_mode):
567+
set_string_attribute(result, DB_NAME, name)
568+
if _report_new(sem_conv_opt_in_mode):
569+
set_string_attribute(result, DB_NAMESPACE, name)
570+
571+
572+
def _set_db_statement(
573+
result: MutableMapping[str, AttributeValue],
574+
statement: str,
575+
sem_conv_opt_in_mode: _StabilityMode,
576+
) -> None:
577+
if _report_old(sem_conv_opt_in_mode):
578+
set_string_attribute(result, DB_STATEMENT, statement)
579+
if _report_new(sem_conv_opt_in_mode):
580+
set_string_attribute(result, DB_QUERY_TEXT, statement)
581+
582+
583+
def _set_db_user(
584+
result: MutableMapping[str, AttributeValue],
585+
user: str,
586+
sem_conv_opt_in_mode: _StabilityMode,
587+
) -> None:
588+
if _report_old(sem_conv_opt_in_mode):
589+
set_string_attribute(result, DB_USER, user)
590+
# No new attribute - db.user was removed with no replacement
591+
592+
593+
# General
594+
595+
536596
def _set_status(
537597
span: Span,
538598
metrics_attributes: MutableMapping[str, AttributeValue],

opentelemetry-instrumentation/tests/test_semconv.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,24 @@
2020
OTEL_SEMCONV_STABILITY_OPT_IN,
2121
_OpenTelemetrySemanticConventionStability,
2222
_OpenTelemetryStabilitySignalType,
23+
_set_db_name,
24+
_set_db_statement,
25+
_set_db_system,
26+
_set_db_user,
2327
_set_status,
2428
_StabilityMode,
2529
)
30+
from opentelemetry.semconv._incubating.attributes.db_attributes import (
31+
DB_NAME,
32+
DB_STATEMENT,
33+
DB_SYSTEM,
34+
DB_USER,
35+
)
36+
from opentelemetry.semconv.attributes.db_attributes import (
37+
DB_NAMESPACE,
38+
DB_QUERY_TEXT,
39+
DB_SYSTEM_NAME,
40+
)
2641
from opentelemetry.trace.status import StatusCode
2742

2843

@@ -277,3 +292,154 @@ def test_non_recording_span(self):
277292
# Verify status code set for metrics independent of tracing decision
278293
self.assertIn("http.status_code", metrics_attributes)
279294
self.assertIn("http.response.status_code", metrics_attributes)
295+
296+
297+
class TestOpenTelemetrySemConvStabilityDatabase(TestCase):
298+
def test_db_system_default(self):
299+
result = {}
300+
_set_db_system(
301+
result, "postgresql", sem_conv_opt_in_mode=_StabilityMode.DEFAULT
302+
)
303+
self.assertIn(DB_SYSTEM, result)
304+
self.assertEqual(result[DB_SYSTEM], "postgresql")
305+
self.assertNotIn(DB_SYSTEM_NAME, result)
306+
307+
def test_db_system_database_stable(self):
308+
result = {}
309+
_set_db_system(
310+
result, "postgresql", sem_conv_opt_in_mode=_StabilityMode.DATABASE
311+
)
312+
self.assertNotIn(DB_SYSTEM, result)
313+
self.assertIn(DB_SYSTEM_NAME, result)
314+
self.assertEqual(result[DB_SYSTEM_NAME], "postgresql")
315+
316+
def test_db_system_database_dup(self):
317+
result = {}
318+
_set_db_system(
319+
result,
320+
"postgresql",
321+
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
322+
)
323+
self.assertIn(DB_SYSTEM, result)
324+
self.assertEqual(result[DB_SYSTEM], "postgresql")
325+
self.assertIn(DB_SYSTEM_NAME, result)
326+
self.assertEqual(result[DB_SYSTEM_NAME], "postgresql")
327+
328+
def test_db_system_none_value(self):
329+
result = {}
330+
_set_db_system(
331+
result, None, sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP
332+
)
333+
self.assertNotIn(DB_SYSTEM, result)
334+
self.assertNotIn(DB_SYSTEM_NAME, result)
335+
336+
def test_db_name_default(self):
337+
result = {}
338+
_set_db_name(
339+
result, "my_database", sem_conv_opt_in_mode=_StabilityMode.DEFAULT
340+
)
341+
self.assertIn(DB_NAME, result)
342+
self.assertEqual(result[DB_NAME], "my_database")
343+
self.assertNotIn(DB_NAMESPACE, result)
344+
345+
def test_db_name_database_stable(self):
346+
result = {}
347+
_set_db_name(
348+
result, "my_database", sem_conv_opt_in_mode=_StabilityMode.DATABASE
349+
)
350+
self.assertNotIn(DB_NAME, result)
351+
self.assertIn(DB_NAMESPACE, result)
352+
self.assertEqual(result[DB_NAMESPACE], "my_database")
353+
354+
def test_db_name_database_dup(self):
355+
result = {}
356+
_set_db_name(
357+
result,
358+
"my_database",
359+
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
360+
)
361+
self.assertIn(DB_NAME, result)
362+
self.assertEqual(result[DB_NAME], "my_database")
363+
self.assertIn(DB_NAMESPACE, result)
364+
self.assertEqual(result[DB_NAMESPACE], "my_database")
365+
366+
def test_db_name_none_value(self):
367+
result = {}
368+
_set_db_name(
369+
result, None, sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP
370+
)
371+
self.assertNotIn(DB_NAME, result)
372+
self.assertNotIn(DB_NAMESPACE, result)
373+
374+
def test_db_statement_default(self):
375+
result = {}
376+
_set_db_statement(
377+
result,
378+
"SELECT * FROM users",
379+
sem_conv_opt_in_mode=_StabilityMode.DEFAULT,
380+
)
381+
self.assertIn(DB_STATEMENT, result)
382+
self.assertEqual(result[DB_STATEMENT], "SELECT * FROM users")
383+
self.assertNotIn(DB_QUERY_TEXT, result)
384+
385+
def test_db_statement_database_stable(self):
386+
result = {}
387+
_set_db_statement(
388+
result,
389+
"SELECT * FROM users",
390+
sem_conv_opt_in_mode=_StabilityMode.DATABASE,
391+
)
392+
self.assertNotIn(DB_STATEMENT, result)
393+
self.assertIn(DB_QUERY_TEXT, result)
394+
self.assertEqual(result[DB_QUERY_TEXT], "SELECT * FROM users")
395+
396+
def test_db_statement_database_dup(self):
397+
result = {}
398+
_set_db_statement(
399+
result,
400+
"SELECT * FROM users",
401+
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
402+
)
403+
self.assertIn(DB_STATEMENT, result)
404+
self.assertEqual(result[DB_STATEMENT], "SELECT * FROM users")
405+
self.assertIn(DB_QUERY_TEXT, result)
406+
self.assertEqual(result[DB_QUERY_TEXT], "SELECT * FROM users")
407+
408+
def test_db_statement_none_value(self):
409+
result = {}
410+
_set_db_statement(
411+
result, None, sem_conv_opt_in_mode=_StabilityMode.DEFAULT
412+
)
413+
self.assertNotIn(DB_STATEMENT, result)
414+
self.assertNotIn(DB_QUERY_TEXT, result)
415+
416+
def test_db_user_default(self):
417+
result = {}
418+
_set_db_user(
419+
result, "admin", sem_conv_opt_in_mode=_StabilityMode.DEFAULT
420+
)
421+
self.assertIn(DB_USER, result)
422+
self.assertEqual(result[DB_USER], "admin")
423+
424+
def test_db_user_database_stable(self):
425+
result = {}
426+
_set_db_user(
427+
result, "admin", sem_conv_opt_in_mode=_StabilityMode.DATABASE
428+
)
429+
# No new attribute - db.user was removed with no replacement
430+
self.assertNotIn(DB_USER, result)
431+
432+
def test_db_user_database_dup(self):
433+
result = {}
434+
_set_db_user(
435+
result,
436+
"admin",
437+
sem_conv_opt_in_mode=_StabilityMode.DATABASE_DUP,
438+
)
439+
self.assertIn(DB_USER, result)
440+
self.assertEqual(result[DB_USER], "admin")
441+
442+
def test_db_user_none_value(self):
443+
result = {}
444+
_set_db_user(result, None, sem_conv_opt_in_mode=_StabilityMode.DEFAULT)
445+
self.assertNotIn(DB_USER, result)

0 commit comments

Comments
 (0)