Skip to content

Commit f106906

Browse files
authored
Add db.system to redis and SQLAlchemy db spans (#2037, #2038, #2039)
* Add `db.system` constant * Add `db.system` data to redis db spans (#2038) * Add `db.system` data to SQLAlchemy db spans (#2039)
1 parent 64c0987 commit f106906

File tree

6 files changed

+46
-3
lines changed

6 files changed

+46
-3
lines changed

sentry_sdk/consts.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ class INSTRUMENTER:
5151
OTEL = "otel"
5252

5353

54+
# See: https://develop.sentry.dev/sdk/performance/span-data-conventions/
55+
class SPANDATA:
56+
DB_SYSTEM = "db.system"
57+
"""
58+
An identifier for the database management system (DBMS) product being used.
59+
See: https://github.com/open-telemetry/opentelemetry-python/blob/e00306206ea25cf8549eca289e39e0b6ba2fa560/opentelemetry-semantic-conventions/src/opentelemetry/semconv/trace/__init__.py#L58
60+
"""
61+
62+
5463
class OP:
5564
DB = "db"
5665
DB_REDIS = "db.redis"

sentry_sdk/integrations/redis.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import absolute_import
22

33
from sentry_sdk import Hub
4-
from sentry_sdk.consts import OP
4+
from sentry_sdk.consts import OP, SPANDATA
55
from sentry_sdk.hub import _should_send_default_pii
66
from sentry_sdk.utils import (
77
SENSITIVE_DATA_SUBSTITUTE,
@@ -63,6 +63,7 @@ def sentry_patched_execute(self, *args, **kwargs):
6363
"redis.commands",
6464
{"count": len(self.command_stack), "first_ten": commands},
6565
)
66+
span.set_data(SPANDATA.DB_SYSTEM, "redis")
6667

6768
return old_execute(self, *args, **kwargs)
6869

sentry_sdk/integrations/sqlalchemy.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import re
44

55
from sentry_sdk._types import TYPE_CHECKING
6+
from sentry_sdk.consts import SPANDATA
67
from sentry_sdk.hub import Hub
78
from sentry_sdk.integrations import Integration, DidNotEnable
89
from sentry_sdk.tracing_utils import record_sql_queries
@@ -67,6 +68,9 @@ def _before_cursor_execute(
6768
span = ctx_mgr.__enter__()
6869

6970
if span is not None:
71+
db_system = _get_db_system(conn.engine.name)
72+
if db_system is not None:
73+
span.set_data(SPANDATA.DB_SYSTEM, db_system)
7074
context._sentry_sql_span = span
7175

7276

@@ -102,3 +106,24 @@ def _handle_error(context, *args):
102106
if ctx_mgr is not None:
103107
execution_context._sentry_sql_span_manager = None
104108
ctx_mgr.__exit__(None, None, None)
109+
110+
111+
# See: https://docs.sqlalchemy.org/en/20/dialects/index.html
112+
def _get_db_system(name):
113+
# type: (str) -> Optional[str]
114+
if "sqlite" in name:
115+
return "sqlite"
116+
117+
if "postgres" in name:
118+
return "postgresql"
119+
120+
if "mariadb" in name:
121+
return "mariadb"
122+
123+
if "mysql" in name:
124+
return "mysql"
125+
126+
if "oracle" in name:
127+
return "oracle"
128+
129+
return None

tests/integrations/redis/test_redis.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import mock
22

33
from sentry_sdk import capture_message, start_transaction
4+
from sentry_sdk.consts import SPANDATA
45
from sentry_sdk.integrations.redis import RedisIntegration
56

67
from fakeredis import FakeStrictRedis
@@ -53,7 +54,8 @@ def test_redis_pipeline(sentry_init, capture_events, is_transaction):
5354
"redis.commands": {
5455
"count": 3,
5556
"first_ten": ["GET 'foo'", "SET 'bar' 1", "SET 'baz' 2"],
56-
}
57+
},
58+
SPANDATA.DB_SYSTEM: "redis",
5759
}
5860
assert span["tags"] == {
5961
"redis.transaction": is_transaction,

tests/integrations/rediscluster/test_rediscluster.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22
from sentry_sdk import capture_message
3+
from sentry_sdk.consts import SPANDATA
34
from sentry_sdk.api import start_transaction
45
from sentry_sdk.integrations.redis import RedisIntegration
56

@@ -71,7 +72,8 @@ def test_rediscluster_pipeline(sentry_init, capture_events):
7172
"redis.commands": {
7273
"count": 3,
7374
"first_ten": ["GET 'foo'", "SET 'bar' 1", "SET 'baz' 2"],
74-
}
75+
},
76+
SPANDATA.DB_SYSTEM: "redis",
7577
}
7678
assert span["tags"] == {
7779
"redis.transaction": False, # For Cluster, this is always False

tests/integrations/sqlalchemy/test_sqlalchemy.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from sqlalchemy.orm import relationship, sessionmaker
88

99
from sentry_sdk import capture_message, start_transaction, configure_scope
10+
from sentry_sdk.consts import SPANDATA
1011
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
1112
from sentry_sdk.serializer import MAX_EVENT_BYTES
1213
from sentry_sdk.utils import json_dumps, MAX_STRING_LENGTH
@@ -119,6 +120,9 @@ class Address(Base):
119120

120121
(event,) = events
121122

123+
for span in event["spans"]:
124+
assert span["data"][SPANDATA.DB_SYSTEM] == "sqlite"
125+
122126
assert (
123127
render_span_tree(event)
124128
== """\

0 commit comments

Comments
 (0)