Skip to content

Commit a48fafd

Browse files
authored
Include framework in SDK name (getsentry#1662)
* Made SDK name dynamic depending on modules loaded
1 parent c0ef3d0 commit a48fafd

4 files changed

Lines changed: 119 additions & 6 deletions

File tree

sentry_sdk/client.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@
1010
current_stacktrace,
1111
disable_capture_event,
1212
format_timestamp,
13+
get_sdk_name,
1314
get_type_name,
1415
get_default_release,
1516
handle_in_app,
1617
logger,
1718
)
1819
from sentry_sdk.serializer import serialize
1920
from sentry_sdk.transport import make_transport
20-
from sentry_sdk.consts import DEFAULT_OPTIONS, SDK_INFO, ClientConstructor
21+
from sentry_sdk.consts import (
22+
DEFAULT_OPTIONS,
23+
VERSION,
24+
ClientConstructor,
25+
)
2126
from sentry_sdk.integrations import setup_integrations
2227
from sentry_sdk.utils import ContextVar
2328
from sentry_sdk.sessions import SessionFlusher
@@ -41,6 +46,13 @@
4146
_client_init_debug = ContextVar("client_init_debug")
4247

4348

49+
SDK_INFO = {
50+
"name": "sentry.python", # SDK name will be overridden after integrations have been loaded with sentry_sdk.integrations.setup_integrations()
51+
"version": VERSION,
52+
"packages": [{"name": "pypi:sentry-sdk", "version": VERSION}],
53+
}
54+
55+
4456
def _get_options(*args, **kwargs):
4557
# type: (*Optional[str], **Any) -> Dict[str, Any]
4658
if args and (isinstance(args[0], (text_type, bytes, str)) or args[0] is None):
@@ -128,6 +140,11 @@ def _capture_envelope(envelope):
128140
"auto_enabling_integrations"
129141
],
130142
)
143+
144+
sdk_name = get_sdk_name(list(self.integrations.keys()))
145+
SDK_INFO["name"] = sdk_name
146+
logger.debug("Setting SDK name to '%s'", sdk_name)
147+
131148
finally:
132149
_client_init_debug.set(old_debug)
133150

sentry_sdk/consts.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ def _get_default_options():
105105

106106

107107
VERSION = "1.9.10"
108-
SDK_INFO = {
109-
"name": "sentry.python",
110-
"version": VERSION,
111-
"packages": [{"name": "pypi:sentry-sdk", "version": VERSION}],
112-
}
113108

114109

115110
class OP:

sentry_sdk/utils.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,40 @@ def get_default_release():
9595
return None
9696

9797

98+
def get_sdk_name(installed_integrations):
99+
# type: (List[str]) -> str
100+
"""Return the SDK name including the name of the used web framework."""
101+
102+
# Note: I can not use for example sentry_sdk.integrations.django.DjangoIntegration.identifier
103+
# here because if django is not installed the integration is not accessible.
104+
framework_integrations = [
105+
"django",
106+
"flask",
107+
"fastapi",
108+
"bottle",
109+
"falcon",
110+
"quart",
111+
"sanic",
112+
"starlette",
113+
"chalice",
114+
"serverless",
115+
"pyramid",
116+
"tornado",
117+
"aiohttp",
118+
"aws_lambda",
119+
"gcp",
120+
"beam",
121+
"asgi",
122+
"wsgi",
123+
]
124+
125+
for integration in framework_integrations:
126+
if integration in installed_integrations:
127+
return "sentry.python.{}".format(integration)
128+
129+
return "sentry.python"
130+
131+
98132
class CaptureInternalException(object):
99133
__slots__ = ()
100134

tests/test_basics.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
add_global_event_processor,
2525
global_event_processors,
2626
)
27+
from sentry_sdk.utils import get_sdk_name
2728

2829

2930
def test_processors(sentry_init, capture_events):
@@ -437,3 +438,69 @@ def foo(event, hint):
437438
assert reports == [("event_processor", "error"), ("event_processor", "transaction")]
438439

439440
global_event_processors.pop()
441+
442+
443+
@pytest.mark.parametrize(
444+
"installed_integrations, expected_name",
445+
[
446+
# integrations with own name
447+
(["django"], "sentry.python.django"),
448+
(["flask"], "sentry.python.flask"),
449+
(["fastapi"], "sentry.python.fastapi"),
450+
(["bottle"], "sentry.python.bottle"),
451+
(["falcon"], "sentry.python.falcon"),
452+
(["quart"], "sentry.python.quart"),
453+
(["sanic"], "sentry.python.sanic"),
454+
(["starlette"], "sentry.python.starlette"),
455+
(["chalice"], "sentry.python.chalice"),
456+
(["serverless"], "sentry.python.serverless"),
457+
(["pyramid"], "sentry.python.pyramid"),
458+
(["tornado"], "sentry.python.tornado"),
459+
(["aiohttp"], "sentry.python.aiohttp"),
460+
(["aws_lambda"], "sentry.python.aws_lambda"),
461+
(["gcp"], "sentry.python.gcp"),
462+
(["beam"], "sentry.python.beam"),
463+
(["asgi"], "sentry.python.asgi"),
464+
(["wsgi"], "sentry.python.wsgi"),
465+
# integrations without name
466+
(["argv"], "sentry.python"),
467+
(["atexit"], "sentry.python"),
468+
(["boto3"], "sentry.python"),
469+
(["celery"], "sentry.python"),
470+
(["dedupe"], "sentry.python"),
471+
(["excepthook"], "sentry.python"),
472+
(["executing"], "sentry.python"),
473+
(["modules"], "sentry.python"),
474+
(["pure_eval"], "sentry.python"),
475+
(["redis"], "sentry.python"),
476+
(["rq"], "sentry.python"),
477+
(["sqlalchemy"], "sentry.python"),
478+
(["stdlib"], "sentry.python"),
479+
(["threading"], "sentry.python"),
480+
(["trytond"], "sentry.python"),
481+
(["logging"], "sentry.python"),
482+
(["gnu_backtrace"], "sentry.python"),
483+
(["httpx"], "sentry.python"),
484+
# precedence of frameworks
485+
(["flask", "django", "celery"], "sentry.python.django"),
486+
(["fastapi", "flask", "redis"], "sentry.python.flask"),
487+
(["bottle", "fastapi", "httpx"], "sentry.python.fastapi"),
488+
(["falcon", "bottle", "logging"], "sentry.python.bottle"),
489+
(["quart", "falcon", "gnu_backtrace"], "sentry.python.falcon"),
490+
(["sanic", "quart", "sqlalchemy"], "sentry.python.quart"),
491+
(["starlette", "sanic", "rq"], "sentry.python.sanic"),
492+
(["chalice", "starlette", "modules"], "sentry.python.starlette"),
493+
(["serverless", "chalice", "pure_eval"], "sentry.python.chalice"),
494+
(["pyramid", "serverless", "modules"], "sentry.python.serverless"),
495+
(["tornado", "pyramid", "executing"], "sentry.python.pyramid"),
496+
(["aiohttp", "tornado", "dedupe"], "sentry.python.tornado"),
497+
(["aws_lambda", "aiohttp", "boto3"], "sentry.python.aiohttp"),
498+
(["gcp", "aws_lambda", "atexit"], "sentry.python.aws_lambda"),
499+
(["beam", "gcp", "argv"], "sentry.python.gcp"),
500+
(["asgi", "beam", "stdtlib"], "sentry.python.beam"),
501+
(["wsgi", "asgi", "boto3"], "sentry.python.asgi"),
502+
(["wsgi", "celery", "redis"], "sentry.python.wsgi"),
503+
],
504+
)
505+
def test_get_sdk_name(installed_integrations, expected_name):
506+
assert get_sdk_name(installed_integrations) == expected_name

0 commit comments

Comments
 (0)