Skip to content

Commit

Permalink
Merge branch 'master' into txiao/feat/add-client-reports-for-profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
Zylphrex authored Jun 28, 2023
2 parents 11bdd9c + 0245011 commit c229e8d
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-python@v4
with:
python-version: 3.9
python-version: 3.11

- run: |
pip install virtualenv
Expand Down
2 changes: 1 addition & 1 deletion docs-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
shibuya
sphinx==7.0.1
sphinx-rtd-theme
sphinx-autodoc-typehints[type_comments]>=1.8.0
typing-extensions
16 changes: 9 additions & 7 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

import os
import sys

import typing
from datetime import datetime

# prevent circular imports
import sphinx.builders.html
import sphinx.builders.latex
import sphinx.builders.texinfo
import sphinx.builders.text
import sphinx.ext.autodoc
import urllib3.exceptions
import sphinx.ext.autodoc # noqa: F401
import urllib3.exceptions # noqa: F401

typing.TYPE_CHECKING = True

Expand All @@ -27,7 +27,7 @@
# -- Project information -----------------------------------------------------

project = "sentry-python"
copyright = "2019, Sentry Team and Contributors"
copyright = "2019-{}, Sentry Team and Contributors".format(datetime.now().year)
author = "Sentry Team and Contributors"

release = "1.26.0"
Expand Down Expand Up @@ -87,13 +87,15 @@

on_rtd = os.environ.get("READTHEDOCS", None) == "True"

html_theme = "alabaster"
html_theme = "shibuya"

# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
html_theme_options = {
"github_url": "https://github.com/getsentry/sentry-python",
}

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
Expand Down Expand Up @@ -167,7 +169,7 @@
"sentry-python Documentation",
author,
"sentry-python",
"One line description of project.",
"The official Sentry SDK for Python.",
"Miscellaneous",
)
]
Expand Down
37 changes: 3 additions & 34 deletions sentry_sdk/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
from sentry_sdk.hub import Hub
from sentry_sdk.scope import Scope
from sentry_sdk.tracing import NoOpSpan, Transaction
from sentry_sdk.tracing_utils import (
has_tracing_enabled,
normalize_incoming_data,
)

if TYPE_CHECKING:
from typing import Any
Expand Down Expand Up @@ -254,47 +250,20 @@ def get_traceparent():
"""
Returns the traceparent either from the active span or from the scope.
"""
hub = Hub.current
if hub.client is not None:
if has_tracing_enabled(hub.client.options) and hub.scope.span is not None:
return hub.scope.span.to_traceparent()

return hub.scope.get_traceparent()
return Hub.current.get_traceparent()


def get_baggage():
# type: () -> Optional[str]
"""
Returns Baggage either from the active span or from the scope.
"""
hub = Hub.current
if (
hub.client is not None
and has_tracing_enabled(hub.client.options)
and hub.scope.span is not None
):
baggage = hub.scope.span.to_baggage()
else:
baggage = hub.scope.get_baggage()

if baggage is not None:
return baggage.serialize()

return None
return Hub.current.get_baggage()


def continue_trace(environ_or_headers, op=None, name=None, source=None):
# type: (Dict[str, Any], Optional[str], Optional[str], Optional[str]) -> Transaction
"""
Sets the propagation context from environment or headers and returns a transaction.
"""
with Hub.current.configure_scope() as scope:
scope.generate_propagation_context(environ_or_headers)

transaction = Transaction.continue_from_headers(
normalize_incoming_data(environ_or_headers),
op=op,
name=name,
source=source,
)
return transaction
return Hub.current.continue_trace(environ_or_headers, op, name, source)
81 changes: 75 additions & 6 deletions sentry_sdk/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@
from sentry_sdk.scope import Scope
from sentry_sdk.client import Client
from sentry_sdk.profiler import Profile
from sentry_sdk.tracing import NoOpSpan, Span, Transaction
from sentry_sdk.tracing import (
NoOpSpan,
Span,
Transaction,
BAGGAGE_HEADER_NAME,
SENTRY_TRACE_HEADER_NAME,
)
from sentry_sdk.session import Session
from sentry_sdk.tracing_utils import has_tracing_enabled
from sentry_sdk.tracing_utils import (
has_tracing_enabled,
normalize_incoming_data,
)

from sentry_sdk.utils import (
exc_info_from_error,
event_from_exception,
Expand Down Expand Up @@ -533,6 +543,22 @@ def start_transaction(

return transaction

def continue_trace(self, environ_or_headers, op=None, name=None, source=None):
# type: (Dict[str, Any], Optional[str], Optional[str], Optional[str]) -> Transaction
"""
Sets the propagation context from environment or headers and returns a transaction.
"""
with self.configure_scope() as scope:
scope.generate_propagation_context(environ_or_headers)

transaction = Transaction.continue_from_headers(
normalize_incoming_data(environ_or_headers),
op=op,
name=name,
source=source,
)
return transaction

@overload
def push_scope(
self, callback=None # type: Optional[None]
Expand Down Expand Up @@ -699,6 +725,36 @@ def flush(
if client is not None:
return client.flush(timeout=timeout, callback=callback)

def get_traceparent(self):
# type: () -> Optional[str]
"""
Returns the traceparent either from the active span or from the scope.
"""
if self.client is not None:
if has_tracing_enabled(self.client.options) and self.scope.span is not None:
return self.scope.span.to_traceparent()

return self.scope.get_traceparent()

def get_baggage(self):
# type: () -> Optional[str]
"""
Returns Baggage either from the active span or from the scope.
"""
if (
self.client is not None
and has_tracing_enabled(self.client.options)
and self.scope.span is not None
):
baggage = self.scope.span.to_baggage()
else:
baggage = self.scope.get_baggage()

if baggage is not None:
return baggage.serialize()

return None

def iter_trace_propagation_headers(self, span=None):
# type: (Optional[Span]) -> Generator[Tuple[str, str], None, None]
"""
Expand All @@ -723,13 +779,26 @@ def iter_trace_propagation_headers(self, span=None):
def trace_propagation_meta(self, span=None):
# type: (Optional[Span]) -> str
"""
Return meta tags which should be injected into the HTML template
to allow propagation of trace data.
Return meta tags which should be injected into HTML templates
to allow propagation of trace information.
"""
if span is None:
logger.warning(
"The parameter `span` in trace_propagation_meta() is deprecated and will be removed in the future."
)

meta = ""

for name, content in self.iter_trace_propagation_headers(span):
meta += '<meta name="%s" content="%s">' % (name, content)
sentry_trace = self.get_traceparent()
if sentry_trace is not None:
meta += '<meta name="%s" content="%s">' % (
SENTRY_TRACE_HEADER_NAME,
sentry_trace,
)

baggage = self.get_baggage()
if baggage is not None:
meta += '<meta name="%s" content="%s">' % (BAGGAGE_HEADER_NAME, baggage)

return meta

Expand Down
79 changes: 78 additions & 1 deletion sentry_sdk/integrations/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from sentry_sdk.api import continue_trace
from sentry_sdk._compat import reraise
from sentry_sdk.consts import OP
from sentry_sdk.consts import OP, SPANDATA
from sentry_sdk.hub import Hub
from sentry_sdk.integrations import Integration, DidNotEnable
from sentry_sdk.integrations.logging import ignore_logger
Expand All @@ -13,20 +13,25 @@
request_body_within_bounds,
)
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_ROUTE
from sentry_sdk.tracing_utils import should_propagate_trace
from sentry_sdk.utils import (
capture_internal_exceptions,
event_from_exception,
logger,
parse_url,
parse_version,
transaction_from_function,
HAS_REAL_CONTEXTVARS,
CONTEXTVARS_ERROR_MESSAGE,
SENSITIVE_DATA_SUBSTITUTE,
AnnotatedValue,
)

try:
import asyncio

from aiohttp import __version__ as AIOHTTP_VERSION
from aiohttp import ClientSession, TraceConfig
from aiohttp.web import Application, HTTPException, UrlDispatcher
except ImportError:
raise DidNotEnable("AIOHTTP not installed")
Expand All @@ -36,6 +41,8 @@
if TYPE_CHECKING:
from aiohttp.web_request import Request
from aiohttp.abc import AbstractMatchInfo
from aiohttp import TraceRequestStartParams, TraceRequestEndParams
from types import SimpleNamespace
from typing import Any
from typing import Dict
from typing import Optional
Expand Down Expand Up @@ -164,6 +171,76 @@ async def sentry_urldispatcher_resolve(self, request):

UrlDispatcher.resolve = sentry_urldispatcher_resolve

old_client_session_init = ClientSession.__init__

def init(*args, **kwargs):
# type: (Any, Any) -> ClientSession
hub = Hub.current
if hub.get_integration(AioHttpIntegration) is None:
return old_client_session_init(*args, **kwargs)

client_trace_configs = list(kwargs.get("trace_configs", ()))
trace_config = create_trace_config()
client_trace_configs.append(trace_config)

kwargs["trace_configs"] = client_trace_configs
return old_client_session_init(*args, **kwargs)

ClientSession.__init__ = init


def create_trace_config():
# type: () -> TraceConfig
async def on_request_start(session, trace_config_ctx, params):
# type: (ClientSession, SimpleNamespace, TraceRequestStartParams) -> None
hub = Hub.current
if hub.get_integration(AioHttpIntegration) is None:
return

method = params.method.upper()

parsed_url = None
with capture_internal_exceptions():
parsed_url = parse_url(str(params.url), sanitize=False)

span = hub.start_span(
op=OP.HTTP_CLIENT,
description="%s %s"
% (method, parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE),
)
span.set_data(SPANDATA.HTTP_METHOD, method)
span.set_data("url", parsed_url.url)
span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query)
span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment)

if should_propagate_trace(hub, str(params.url)):
for key, value in hub.iter_trace_propagation_headers(span):
logger.debug(
"[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format(
key=key, value=value, url=params.url
)
)
params.headers[key] = value

trace_config_ctx.span = span

async def on_request_end(session, trace_config_ctx, params):
# type: (ClientSession, SimpleNamespace, TraceRequestEndParams) -> None
if trace_config_ctx.span is None:
return

span = trace_config_ctx.span
span.set_http_status(int(params.response.status))
span.set_data("reason", params.response.reason)
span.finish()

trace_config = TraceConfig()

trace_config.on_request_start.append(on_request_start)
trace_config.on_request_end.append(on_request_end)

return trace_config


def _make_request_processor(weak_request):
# type: (Callable[[], Request]) -> EventProcessor
Expand Down
4 changes: 2 additions & 2 deletions sentry_sdk/integrations/huey.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@

try:
from huey.api import Huey, Result, ResultGroup, Task
from huey.exceptions import CancelExecution, RetryTask
from huey.exceptions import CancelExecution, RetryTask, TaskLockedException
except ImportError:
raise DidNotEnable("Huey is not installed")


HUEY_CONTROL_FLOW_EXCEPTIONS = (CancelExecution, RetryTask)
HUEY_CONTROL_FLOW_EXCEPTIONS = (CancelExecution, RetryTask, TaskLockedException)


class HueyIntegration(Integration):
Expand Down
8 changes: 4 additions & 4 deletions sentry_sdk/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,11 +605,11 @@ def _drop(cause, ty):

contexts = event.setdefault("contexts", {})

if has_tracing_enabled(options):
if self._span is not None:
if contexts.get("trace") is None:
if has_tracing_enabled(options) and self._span is not None:
contexts["trace"] = self._span.get_trace_context()
else:
contexts["trace"] = self.get_trace_context()
else:
contexts["trace"] = self.get_trace_context()

exc_info = hint.get("exc_info")
if exc_info is not None:
Expand Down
Loading

0 comments on commit c229e8d

Please sign in to comment.