Skip to content

Commit 6236c40

Browse files
committed
Merge branch 'py-2298-migrate-aiohttp-to-span-first' of github.com:getsentry/sentry-python into py-2298-migrate-aiohttp-to-span-first
2 parents 299e300 + 551e1d7 commit 6236c40

39 files changed

Lines changed: 3775 additions & 1382 deletions

.github/workflows/update-tox.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
jobs:
1010
update-tox:
1111
name: Update test matrix
12+
if: github.ref == 'refs/heads/master'
1213
runs-on: ubuntu-latest
1314
timeout-minutes: 10
1415

@@ -55,11 +56,15 @@ jobs:
5556
5657
- name: Create pull request
5758
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
59+
env:
60+
BRANCH_NAME: ${{ steps.create-branch.outputs.branch_name }}
61+
COMMIT_TITLE: ${{ steps.create-branch.outputs.commit_title }}
62+
DATE: ${{ steps.create-branch.outputs.date }}
5863
with:
5964
script: |
60-
const branchName = '${{ steps.create-branch.outputs.branch_name }}';
61-
const commitTitle = '${{ steps.create-branch.outputs.commit_title }}';
62-
const date = '${{ steps.create-branch.outputs.date }}';
65+
const branchName = process.env.BRANCH_NAME;
66+
const commitTitle = process.env.COMMIT_TITLE;
67+
const date = process.env.DATE;
6368
const prBody = `Update our test matrix with new releases of integrated frameworks and libraries.
6469
6570
## How it works
@@ -100,7 +105,7 @@ jobs:
100105
repo: context.repo.repo,
101106
title: commitTitle + ' (' + date + ')',
102107
head: branchName,
103-
base: '${{ github.ref_name }}',
108+
base: 'master',
104109
body: prBody,
105110
});
106111

scripts/populate_tox/package_dependencies.jsonl

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.

scripts/populate_tox/releases.jsonl

Lines changed: 15 additions & 16 deletions
Large diffs are not rendered by default.

sentry_sdk/_batcher.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import threading
44
from datetime import datetime, timezone
55
from typing import TYPE_CHECKING, TypeVar, Generic
6+
import weakref
67

78
from sentry_sdk.utils import format_timestamp
89
from sentry_sdk.envelope import Envelope, Item, PayloadRef
@@ -38,6 +39,26 @@ def __init__(
3839
self._flusher: "Optional[threading.Thread]" = None
3940
self._flusher_pid: "Optional[int]" = None
4041

42+
# See https://github.com/getsentry/sentry-python/blob/051cc01640a29bfd64b1f1e2e3414c02f027dd1b/sentry_sdk/monitor.py#L41-L50
43+
if hasattr(os, "register_at_fork"):
44+
weak_reset = weakref.WeakMethod(self._reset_thread_state)
45+
46+
def _reset_in_child() -> None:
47+
method = weak_reset()
48+
if method is not None:
49+
method()
50+
51+
os.register_at_fork(after_in_child=_reset_in_child)
52+
53+
def _reset_thread_state(self) -> None:
54+
self._buffer = []
55+
self._running = True
56+
self._lock = threading.Lock()
57+
self._active = threading.local()
58+
self._flush_event = threading.Event()
59+
self._flusher = None
60+
self._flusher_pid = None
61+
4162
def _ensure_thread(self) -> bool:
4263
"""For forking processes we might need to restart this thread.
4364
This ensures that our process actually has that thread running.

sentry_sdk/_span_batcher.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import threading
21
from collections import defaultdict
32
from datetime import datetime, timezone
3+
import os
4+
import threading
45
from typing import TYPE_CHECKING
6+
import weakref
57

68
from sentry_sdk._batcher import Batcher
79
from sentry_sdk.envelope import Envelope, Item, PayloadRef
@@ -50,6 +52,30 @@ def __init__(
5052
self._flusher: "Optional[threading.Thread]" = None
5153
self._flusher_pid: "Optional[int]" = None
5254

55+
# See https://github.com/getsentry/sentry-python/blob/051cc01640a29bfd64b1f1e2e3414c02f027dd1b/sentry_sdk/monitor.py#L41-L50
56+
if hasattr(os, "register_at_fork"):
57+
weak_reset = weakref.WeakMethod(self._reset_thread_state)
58+
59+
def _reset_in_child() -> None:
60+
method = weak_reset()
61+
if method is not None:
62+
method()
63+
64+
os.register_at_fork(after_in_child=_reset_in_child)
65+
66+
def _reset_thread_state(self) -> None:
67+
self._span_buffer = defaultdict(list)
68+
self._running_size = defaultdict(lambda: 0)
69+
self._running = True
70+
71+
self._lock = threading.Lock()
72+
self._active = threading.local()
73+
74+
self._flush_event = threading.Event()
75+
76+
self._flusher = None
77+
self._flusher_pid = None
78+
5379
def add(self, span: "StreamedSpan") -> None:
5480
# Bail out if the current thread is already executing batcher code.
5581
# This prevents deadlocks when code running inside the batcher (e.g.

sentry_sdk/api.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from sentry_sdk._init_implementation import init
77
from sentry_sdk.consts import INSTRUMENTER
88
from sentry_sdk.scope import Scope, _ScopeManager, new_scope, isolation_scope
9-
from sentry_sdk.traces import StreamedSpan
9+
from sentry_sdk.traces import StreamedSpan, _get_current_streamed_span
1010
from sentry_sdk.tracing import NoOpSpan, Transaction, trace
1111
from sentry_sdk.crons import monitor
1212

@@ -422,7 +422,7 @@ def set_measurement(name: str, value: float, unit: "MeasurementUnit" = "") -> No
422422

423423
def get_current_span(
424424
scope: "Optional[Scope]" = None,
425-
) -> "Optional[Union[Span, StreamedSpan]]":
425+
) -> "Optional[Span]":
426426
"""
427427
Returns the currently active span if there is one running, otherwise `None`
428428
"""
@@ -533,12 +533,7 @@ def update_current_span(
533533
attributes={"user_id": 123, "batch_size": 50}
534534
)
535535
"""
536-
current_span = get_current_span()
537-
538-
if current_span is None:
539-
return
540-
541-
if isinstance(current_span, StreamedSpan):
536+
if isinstance(_get_current_streamed_span(), StreamedSpan):
542537
warnings.warn(
543538
"The `update_current_span` API isn't available in streaming mode. "
544539
"Retrieve the current span with get_current_span() and use its API "
@@ -548,6 +543,11 @@ def update_current_span(
548543
)
549544
return
550545

546+
current_span = get_current_span()
547+
548+
if current_span is None:
549+
return
550+
551551
if op is not None:
552552
current_span.op = op
553553

sentry_sdk/consts.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,12 @@ class SPANDATA:
881881
Example: "tcp", "udp", "unix"
882882
"""
883883

884+
PROCESS_PID = "process.pid"
885+
"""
886+
The process ID of the running process.
887+
Example: 12345
888+
"""
889+
884890
PROFILER_ID = "profiler_id"
885891
"""
886892
Label identifying the profiler id that the span occurred in. This should be a string.
@@ -924,6 +930,24 @@ class SPANDATA:
924930
Example: "MainThread"
925931
"""
926932

933+
URL_FULL = "url.full"
934+
"""
935+
The URL of the resource that was fetched.
936+
Example: "https://example.com/test?foo=bar#buzz"
937+
"""
938+
939+
URL_FRAGMENT = "url.fragment"
940+
"""
941+
The fragments present in the URI. Note that this does not contain the leading # character, while the `http.fragment` attribute does.
942+
Example: "details"
943+
"""
944+
945+
URL_QUERY = "url.query"
946+
"""
947+
The query string present in the URL. Note that this does not contain the leading ? character, while the `http.query` attribute does.
948+
Example: "foo=bar&bar=baz"
949+
"""
950+
927951
MCP_TOOL_NAME = "mcp.tool.name"
928952
"""
929953
The name of the MCP tool being called.

sentry_sdk/integrations/_wsgi_common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"HTTP_SET_COOKIE",
3232
"HTTP_COOKIE",
3333
"HTTP_AUTHORIZATION",
34+
"HTTP_PROXY_AUTHORIZATION",
3435
"HTTP_X_API_KEY",
3536
"HTTP_X_FORWARDED_FOR",
3637
"HTTP_X_REAL_IP",

sentry_sdk/integrations/celery/__init__.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from sentry_sdk.integrations.celery.utils import _now_seconds_since_epoch
1616
from sentry_sdk.integrations.logging import ignore_logger
1717
from sentry_sdk.scope import should_send_default_pii
18-
from sentry_sdk.traces import StreamedSpan
18+
from sentry_sdk.traces import StreamedSpan, _get_current_streamed_span
1919
from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, Span, TransactionSource
2020
from sentry_sdk.tracing_utils import Baggage, has_span_streaming_enabled
2121
from sentry_sdk.utils import (
@@ -98,13 +98,16 @@ def setup_once() -> None:
9898

9999

100100
def _set_status(status: str) -> None:
101+
client = sentry_sdk.get_client()
102+
span_streaming = has_span_streaming_enabled(client.options)
103+
101104
with capture_internal_exceptions():
102105
scope = sentry_sdk.get_current_scope()
103-
if scope.span is not None:
104-
if isinstance(scope.span, Span):
105-
scope.span.set_status(status)
106-
else:
107-
scope.span.status = "ok" if status == "ok" else "error"
106+
107+
if span_streaming and scope.streamed_span is not None:
108+
scope.streamed_span.status = "ok" if status == "ok" else "error"
109+
elif not span_streaming and scope.span is not None:
110+
scope.span.set_status(status)
108111

109112

110113
def _capture_exception(task: "Any", exc_info: "ExcInfo") -> None:
@@ -289,7 +292,7 @@ def apply_async(*args: "Any", **kwargs: "Any") -> "Any":
289292

290293
span_mgr: "Union[StreamedSpan, Span, NoOpMgr]" = NoOpMgr()
291294
if span_streaming:
292-
if not task_started_from_beat and sentry_sdk.get_current_span() is not None:
295+
if not task_started_from_beat and _get_current_streamed_span() is not None:
293296
span_mgr = sentry_sdk.traces.start_span(
294297
name=task_name,
295298
attributes={
@@ -570,7 +573,7 @@ def sentry_publish(self: "Producer", *args: "Any", **kwargs: "Any") -> "Any":
570573

571574
span: "Union[StreamedSpan, Span, None]" = None
572575
if span_streaming:
573-
if sentry_sdk.get_current_span() is not None:
576+
if _get_current_streamed_span() is not None:
574577
span = sentry_sdk.traces.start_span(
575578
name=task_name,
576579
attributes={

sentry_sdk/integrations/fastapi.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,17 @@ def _sentry_get_request_handler(*args: "Any", **kwargs: "Any") -> "Any":
9090
@wraps(old_call)
9191
def _sentry_call(*args: "Any", **kwargs: "Any") -> "Any":
9292
current_scope = sentry_sdk.get_current_scope()
93-
current_span = current_scope.span
9493

95-
if isinstance(current_span, StreamedSpan) and not isinstance(
96-
current_span, NoOpStreamedSpan
97-
):
98-
segment = current_span._segment
99-
segment._update_active_thread()
94+
client = sentry_sdk.get_client()
95+
if has_span_streaming_enabled(client.options):
96+
current_span = current_scope.streamed_span
97+
98+
if isinstance(current_span, StreamedSpan) and not isinstance(
99+
current_span, NoOpStreamedSpan
100+
):
101+
segment = current_span._segment
102+
segment._update_active_thread()
103+
100104
elif current_scope.transaction is not None:
101105
current_scope.transaction.update_active_thread()
102106

0 commit comments

Comments
 (0)