Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add origin to transactions/spans created by integrations #3135

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e4a88cc
Added origin to aiohttp integration
antonpirker Jun 5, 2024
550f4e2
Added origin to anthropic integration
antonpirker Jun 5, 2024
fc8ffe6
Added origin to arq integration
antonpirker Jun 5, 2024
6d1ac51
format
antonpirker Jun 5, 2024
90a6f9b
Merge branch 'antonpirker/trace-origin' into antonpirker/trace-origin…
antonpirker Jun 5, 2024
21f02a5
Added origin to asyncio integration
antonpirker Jun 5, 2024
85c9d44
Added origin to asyncpg integration
antonpirker Jun 5, 2024
63a90b6
Added origin to boto3 integration
antonpirker Jun 5, 2024
323e19d
Added origin to clickhouse_driver integration
antonpirker Jun 5, 2024
70b3ad8
Only one type of origin for boto3 because the OP is different anyhow
antonpirker Jun 5, 2024
ade975a
Added origin to cohere integration
antonpirker Jun 5, 2024
b25904c
Added origin to httpx integration
antonpirker Jun 5, 2024
448aa8a
Added origin to huey integration
antonpirker Jun 5, 2024
a43b848
Added origin to huggingface_hub integration
antonpirker Jun 5, 2024
682fe5c
Added origin to langchain integration
antonpirker Jun 5, 2024
0f72a86
Added origin to openai integration
antonpirker Jun 5, 2024
d919633
Added origin to pymongo integration
antonpirker Jun 5, 2024
d2821a9
Added origin to rq integration
antonpirker Jun 5, 2024
5b7eaf0
fix
antonpirker Jun 5, 2024
1799b19
Added origin to sanic integration
antonpirker Jun 5, 2024
2d05fd9
Added origin to starlette integration
antonpirker Jun 5, 2024
f3d9666
Added origin to starlite integration
antonpirker Jun 5, 2024
a64873e
Added origin to strawberry integration
antonpirker Jun 5, 2024
d50998b
Added origin to tornado integration
antonpirker Jun 5, 2024
c2f40eb
Disable test for Sanic versions not supporting performance
antonpirker Jun 6, 2024
19fcf79
oops
antonpirker Jun 6, 2024
f1e8839
Merge branch 'antonpirker/trace-origin' into antonpirker/trace-origin…
antonpirker Jun 6, 2024
b6ec7a8
Added origin to bottle integration
antonpirker Jun 7, 2024
9516c3e
Added origin to falcon integration
antonpirker Jun 7, 2024
e6d4c05
Added origin to flask integration
antonpirker Jun 7, 2024
7c28481
Added origin to pyramid integration
antonpirker Jun 7, 2024
0a9468d
Added origin to trytond integration
antonpirker Jun 7, 2024
16eb21d
Added origin to django integration
antonpirker Jun 7, 2024
cf4082f
Added origin tests to wsgi integration
antonpirker Jun 7, 2024
da44c76
Added origin to Django asgi integration
antonpirker Jun 7, 2024
3da3795
Since Django 3 the channels handler is deprecated
antonpirker Jun 7, 2024
b70db4c
small fix
antonpirker Jun 7, 2024
f980fd2
Added origin to quart integration
antonpirker Jun 7, 2024
605f6d6
Added origin to starlite integration
antonpirker Jun 7, 2024
588c256
Added origin to starlette integration
antonpirker Jun 7, 2024
3271163
Added origin to aws_lambda integration
antonpirker Jun 7, 2024
cf953a1
Added origin to gcp integration
antonpirker Jun 7, 2024
94f5acd
trytond fix
antonpirker Jun 7, 2024
d31814e
aws_lambda fix
antonpirker Jun 7, 2024
512cfa8
strawberry fix
antonpirker Jun 7, 2024
40eaf92
formatting
antonpirker Jun 7, 2024
0de08ea
needs django >1.11
antonpirker Jun 7, 2024
51e0163
Merge branch 'antonpirker/trace-origin' into antonpirker/trace-origin…
antonpirker Jun 12, 2024
d9706a1
fixed merge problem
antonpirker Jun 12, 2024
341e1a4
Merge branch 'antonpirker/trace-origin' into antonpirker/trace-origin…
antonpirker Jun 19, 2024
fea2dc6
Added more origin to django integration
antonpirker Jun 19, 2024
87b3463
trigger ci
antonpirker Jun 19, 2024
31a1ba0
Added tests for all kinds of spans emmited by django
antonpirker Jun 21, 2024
bfafadb
Fixed tests
antonpirker Jun 21, 2024
89d3f0d
Fixed tests again
antonpirker Jun 21, 2024
963aa67
Merge branch 'antonpirker/trace-origin' into antonpirker/trace-origin…
antonpirker Jun 21, 2024
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
3 changes: 3 additions & 0 deletions sentry_sdk/integrations/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

class AioHttpIntegration(Integration):
identifier = "aiohttp"
origin = f"auto.http.{identifier}"

def __init__(self, transaction_style="handler_name"):
# type: (str) -> None
Expand Down Expand Up @@ -120,6 +121,7 @@ async def sentry_app_handle(self, request, *args, **kwargs):
# URL resolver did not find a route or died trying.
name="generic AIOHTTP request",
source=TRANSACTION_SOURCE_ROUTE,
origin=AioHttpIntegration.origin,
)
with sentry_sdk.start_transaction(
transaction,
Expand Down Expand Up @@ -206,6 +208,7 @@ async def on_request_start(session, trace_config_ctx, params):
op=OP.HTTP_CLIENT,
description="%s %s"
% (method, parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE),
origin=AioHttpIntegration.origin,
)
span.set_data(SPANDATA.HTTP_METHOD, method)
if parsed_url is not None:
Expand Down
5 changes: 4 additions & 1 deletion sentry_sdk/integrations/anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

class AnthropicIntegration(Integration):
identifier = "anthropic"
origin = f"auto.ai.{identifier}"

def __init__(self, include_prompts=True):
# type: (AnthropicIntegration, bool) -> None
Expand Down Expand Up @@ -92,7 +93,9 @@ def _sentry_patched_create(*args, **kwargs):
model = kwargs.get("model")

span = sentry_sdk.start_span(
op=OP.ANTHROPIC_MESSAGES_CREATE, description="Anthropic messages create"
op=OP.ANTHROPIC_MESSAGES_CREATE,
description="Anthropic messages create",
origin=AnthropicIntegration.origin,
)
span.__enter__()

Expand Down
6 changes: 5 additions & 1 deletion sentry_sdk/integrations/arq.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

class ArqIntegration(Integration):
identifier = "arq"
origin = f"auto.queue.{identifier}"

@staticmethod
def setup_once():
Expand Down Expand Up @@ -76,7 +77,9 @@ async def _sentry_enqueue_job(self, function, *args, **kwargs):
if integration is None:
return await old_enqueue_job(self, function, *args, **kwargs)

with sentry_sdk.start_span(op=OP.QUEUE_SUBMIT_ARQ, description=function):
with sentry_sdk.start_span(
op=OP.QUEUE_SUBMIT_ARQ, description=function, origin=ArqIntegration.origin
):
return await old_enqueue_job(self, function, *args, **kwargs)

ArqRedis.enqueue_job = _sentry_enqueue_job
Expand All @@ -101,6 +104,7 @@ async def _sentry_run_job(self, job_id, score):
status="ok",
op=OP.QUEUE_TASK_ARQ,
source=TRANSACTION_SOURCE_TASK,
origin=ArqIntegration.origin,
)

with sentry_sdk.start_transaction(transaction):
Expand Down
17 changes: 14 additions & 3 deletions sentry_sdk/integrations/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,23 @@ def _looks_like_asgi3(app):


class SentryAsgiMiddleware:
__slots__ = ("app", "__call__", "transaction_style", "mechanism_type")
__slots__ = (
"app",
"__call__",
"transaction_style",
"mechanism_type",
"span_origin",
)

def __init__(
self,
app,
unsafe_context_data=False,
transaction_style="endpoint",
mechanism_type="asgi",
span_origin="manual",
):
# type: (Any, bool, str, str) -> None
# type: (Any, bool, str, str, str) -> None
"""
Instrument an ASGI application with Sentry. Provides HTTP/websocket
data to sent events and basic handling for exceptions bubbling up
Expand Down Expand Up @@ -124,6 +131,7 @@ def __init__(

self.transaction_style = transaction_style
self.mechanism_type = mechanism_type
self.span_origin = span_origin
self.app = app

if _looks_like_asgi3(app):
Expand Down Expand Up @@ -182,6 +190,7 @@ async def _run_app(self, scope, receive, send, asgi_version):
op="{}.server".format(ty),
name=transaction_name,
source=transaction_source,
origin=self.span_origin,
)
logger.debug(
"[ASGI] Created transaction (continuing trace): %s",
Expand All @@ -192,6 +201,7 @@ async def _run_app(self, scope, receive, send, asgi_version):
op=OP.HTTP_SERVER,
name=transaction_name,
source=transaction_source,
origin=self.span_origin,
)
logger.debug(
"[ASGI] Created transaction (new): %s", transaction
Expand All @@ -205,7 +215,8 @@ async def _run_app(self, scope, receive, send, asgi_version):
)

with sentry_sdk.start_transaction(
transaction, custom_sampling_context={"asgi_scope": scope}
transaction,
custom_sampling_context={"asgi_scope": scope},
):
logger.debug("[ASGI] Started transaction: %s", transaction)
try:
Expand Down
5 changes: 4 additions & 1 deletion sentry_sdk/integrations/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ async def _coro_creating_hub_and_span():

with sentry_sdk.isolation_scope():
with sentry_sdk.start_span(
op=OP.FUNCTION, description=get_name(coro)
op=OP.FUNCTION,
description=get_name(coro),
origin=AsyncioIntegration.origin,
):
try:
result = await coro
Expand Down Expand Up @@ -97,6 +99,7 @@ def _capture_exception():

class AsyncioIntegration(Integration):
identifier = "asyncio"
origin = f"auto.function.{identifier}"

@staticmethod
def setup_once():
Expand Down
5 changes: 4 additions & 1 deletion sentry_sdk/integrations/asyncpg.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

class AsyncPGIntegration(Integration):
identifier = "asyncpg"
origin = f"auto.db.{identifier}"
_record_params = False

def __init__(self, *, record_params: bool = False):
Expand Down Expand Up @@ -154,7 +155,9 @@ async def _inner(*args: Any, **kwargs: Any) -> T:
user = kwargs["params"].user
database = kwargs["params"].database

with sentry_sdk.start_span(op=OP.DB, description="connect") as span:
with sentry_sdk.start_span(
op=OP.DB, description="connect", origin=AsyncPGIntegration.origin
) as span:
span.set_data(SPANDATA.DB_SYSTEM, "postgresql")
addr = kwargs.get("addr")
if addr:
Expand Down
2 changes: 2 additions & 0 deletions sentry_sdk/integrations/aws_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def sentry_handler(aws_event, aws_context, *args, **kwargs):
op=OP.FUNCTION_AWS,
name=aws_context.function_name,
source=TRANSACTION_SOURCE_COMPONENT,
origin=AwsLambdaIntegration.origin,
)
with sentry_sdk.start_transaction(
transaction,
Expand Down Expand Up @@ -178,6 +179,7 @@ def _drain_queue():

class AwsLambdaIntegration(Integration):
identifier = "aws_lambda"
origin = f"auto.function.{identifier}"

def __init__(self, timeout_warning=False):
# type: (bool) -> None
Expand Down
3 changes: 3 additions & 0 deletions sentry_sdk/integrations/boto3.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

class Boto3Integration(Integration):
identifier = "boto3"
origin = f"auto.http.{identifier}"

@staticmethod
def setup_once():
Expand Down Expand Up @@ -69,6 +70,7 @@ def _sentry_request_created(service_id, request, operation_name, **kwargs):
span = sentry_sdk.start_span(
op=OP.HTTP_CLIENT,
description=description,
origin=Boto3Integration.origin,
)

with capture_internal_exceptions():
Expand Down Expand Up @@ -106,6 +108,7 @@ def _sentry_after_call(context, parsed, **kwargs):
streaming_span = span.start_child(
op=OP.HTTP_CLIENT_STREAM,
description=span.description,
origin=Boto3Integration.origin,
)

orig_read = body.read
Expand Down
8 changes: 6 additions & 2 deletions sentry_sdk/integrations/bottle.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

class BottleIntegration(Integration):
identifier = "bottle"
origin = f"auto.http.{identifier}"

transaction_style = ""

Expand Down Expand Up @@ -69,10 +70,13 @@ def setup_once():
@ensure_integration_enabled(BottleIntegration, old_app)
def sentry_patched_wsgi_app(self, environ, start_response):
# type: (Any, Dict[str, str], Callable[..., Any]) -> _ScopedResponse
return SentryWsgiMiddleware(lambda *a, **kw: old_app(self, *a, **kw))(
environ, start_response
middleware = SentryWsgiMiddleware(
lambda *a, **kw: old_app(self, *a, **kw),
span_origin=BottleIntegration.origin,
)

return middleware(environ, start_response)

Bottle.__call__ = sentry_patched_wsgi_app

old_handle = Bottle._handle
Expand Down
7 changes: 6 additions & 1 deletion sentry_sdk/integrations/clickhouse_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def __getitem__(self, _):

class ClickhouseDriverIntegration(Integration):
identifier = "clickhouse_driver"
origin = f"auto.db.{identifier}"

@staticmethod
def setup_once() -> None:
Expand Down Expand Up @@ -81,7 +82,11 @@ def _inner(*args: P.args, **kwargs: P.kwargs) -> T:
query_id = args[2] if len(args) > 2 else kwargs.get("query_id")
params = args[3] if len(args) > 3 else kwargs.get("params")

span = sentry_sdk.start_span(op=OP.DB, description=query)
span = sentry_sdk.start_span(
op=OP.DB,
description=query,
origin=ClickhouseDriverIntegration.origin,
)

connection._sentry_span = span # type: ignore[attr-defined]

Expand Down
3 changes: 3 additions & 0 deletions sentry_sdk/integrations/cohere.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

class CohereIntegration(Integration):
identifier = "cohere"
origin = f"auto.ai.{identifier}"

def __init__(self, include_prompts=True):
# type: (CohereIntegration, bool) -> None
Expand Down Expand Up @@ -141,6 +142,7 @@ def new_chat(*args, **kwargs):
span = sentry_sdk.start_span(
op=consts.OP.COHERE_CHAT_COMPLETIONS_CREATE,
description="cohere.client.Chat",
origin=CohereIntegration.origin,
)
span.__enter__()
try:
Expand Down Expand Up @@ -225,6 +227,7 @@ def new_embed(*args, **kwargs):
with sentry_sdk.start_span(
op=consts.OP.COHERE_EMBEDDINGS_CREATE,
description="Cohere Embedding Creation",
origin=CohereIntegration.origin,
) as span:
integration = sentry_sdk.get_client().get_integration(CohereIntegration)
if "texts" in kwargs and (
Expand Down
36 changes: 29 additions & 7 deletions sentry_sdk/integrations/django/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class DjangoIntegration(Integration):
"""

identifier = "django"
origin = f"auto.http.{identifier}"

transaction_style = ""
middleware_spans = None
Expand Down Expand Up @@ -171,9 +172,12 @@ def sentry_patched_wsgi_handler(self, environ, start_response):

use_x_forwarded_for = settings.USE_X_FORWARDED_HOST

return SentryWsgiMiddleware(bound_old_app, use_x_forwarded_for)(
environ, start_response
middleware = SentryWsgiMiddleware(
bound_old_app,
use_x_forwarded_for,
span_origin=DjangoIntegration.origin,
)
return middleware(environ, start_response)

WSGIHandler.__call__ = sentry_patched_wsgi_handler

Expand Down Expand Up @@ -321,10 +325,14 @@ def sentry_patched_drf_initial(self, request, *args, **kwargs):
def _patch_channels():
# type: () -> None
try:
# Django < 3.0
from channels.http import AsgiHandler # type: ignore
except ImportError:
return

try:
# DJango 3.0+
from django.core.handlers.asgi import ASGIHandler as AsgiHandler
except ImportError:
return
if not HAS_REAL_CONTEXTVARS:
# We better have contextvars or we're going to leak state between
# requests.
Expand Down Expand Up @@ -621,7 +629,12 @@ def install_sql_hook():
def execute(self, sql, params=None):
# type: (CursorWrapper, Any, Optional[Any]) -> Any
with record_sql_queries(
self.cursor, sql, params, paramstyle="format", executemany=False
cursor=self.cursor,
query=sql,
params_list=params,
paramstyle="format",
executemany=False,
span_origin=DjangoIntegration.origin,
) as span:
_set_db_data(span, self)
options = (
Expand Down Expand Up @@ -649,7 +662,12 @@ def execute(self, sql, params=None):
def executemany(self, sql, param_list):
# type: (CursorWrapper, Any, List[Any]) -> Any
with record_sql_queries(
self.cursor, sql, param_list, paramstyle="format", executemany=True
cursor=self.cursor,
query=sql,
params_list=param_list,
paramstyle="format",
executemany=True,
span_origin=DjangoIntegration.origin,
) as span:
_set_db_data(span, self)

Expand All @@ -666,7 +684,11 @@ def connect(self):
with capture_internal_exceptions():
sentry_sdk.add_breadcrumb(message="connect", category="query")

with sentry_sdk.start_span(op=OP.DB, description="connect") as span:
with sentry_sdk.start_span(
op=OP.DB,
description="connect",
origin=DjangoIntegration.origin,
) as span:
_set_db_data(span, self)
return real_connect(self)

Expand Down
14 changes: 11 additions & 3 deletions sentry_sdk/integrations/django/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ async def sentry_patched_asgi_handler(self, scope, receive, send):
return await old_app(self, scope, receive, send)

middleware = SentryAsgiMiddleware(
old_app.__get__(self, cls), unsafe_context_data=True
old_app.__get__(self, cls),
unsafe_context_data=True,
span_origin=DjangoIntegration.origin,
)._run_asgi3

return await middleware(scope, receive, send)
Expand Down Expand Up @@ -145,7 +147,9 @@ async def sentry_patched_asgi_handler(self, receive, send):
return await old_app(self, receive, send)

middleware = SentryAsgiMiddleware(
lambda _scope: old_app.__get__(self, cls), unsafe_context_data=True
lambda _scope: old_app.__get__(self, cls),
unsafe_context_data=True,
span_origin=DjangoIntegration.origin,
)

return await middleware(self.scope)(receive, send)
Expand All @@ -160,6 +164,8 @@ async def sentry_patched_asgi_handler(self, receive, send):

def wrap_async_view(callback):
# type: (Any) -> Any
from sentry_sdk.integrations.django import DjangoIntegration

@functools.wraps(callback)
async def sentry_wrapped_callback(request, *args, **kwargs):
# type: (Any, *Any, **Any) -> Any
Expand All @@ -168,7 +174,9 @@ async def sentry_wrapped_callback(request, *args, **kwargs):
sentry_scope.profile.update_active_thread_id()

with sentry_sdk.start_span(
op=OP.VIEW_RENDER, description=request.resolver_match.view_name
op=OP.VIEW_RENDER,
description=request.resolver_match.view_name,
origin=DjangoIntegration.origin,
):
return await callback(request, *args, **kwargs)

Expand Down
Loading
Loading