Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
8 changes: 2 additions & 6 deletions sentry_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,8 @@ def _capture_envelope(envelope):
try:
_client_init_debug.set(self.options["debug"])
self.transport = make_transport(self.options)
session_mode = self.options["_experiments"].get(
"session_mode", "application"
)
self.session_flusher = SessionFlusher(
capture_func=_capture_envelope, session_mode=session_mode
)

self.session_flusher = SessionFlusher(capture_func=_capture_envelope)

request_bodies = ("always", "never", "small", "medium")
if self.options["request_bodies"] not in request_bodies:
Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
{
"max_spans": Optional[int],
"record_sql_params": Optional[bool],
"auto_session_tracking": Optional[bool],
"smart_transaction_trimming": Optional[bool],
},
total=False,
Expand Down Expand Up @@ -75,6 +74,7 @@ def __init__(
traces_sample_rate=None, # type: Optional[float]
traces_sampler=None, # type: Optional[TracesSampler]
auto_enabling_integrations=True, # type: bool
auto_session_tracking=True, # type: bool
_experiments={}, # type: Experiments # noqa: B006
):
# type: (...) -> None
Expand Down
5 changes: 4 additions & 1 deletion sentry_sdk/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,9 @@ def inner():

return inner()

def start_session(self):
def start_session(
self, session_mode="application" # type: str
):
# type: (...) -> None
"""Starts a new session."""
self.end_session()
Expand All @@ -632,6 +634,7 @@ def start_session(self):
release=client.options["release"] if client else None,
environment=client.options["environment"] if client else None,
user=scope._user,
session_mode=session_mode,
)

def end_session(self):
Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def __call__(self, environ, start_response):
_wsgi_middleware_applied.set(True)
try:
hub = Hub(Hub.current)
with auto_session_tracking(hub):
with auto_session_tracking(hub, session_mode="request"):
with hub:
with capture_internal_exceptions():
with hub.configure_scope() as scope:
Expand Down
2 changes: 2 additions & 0 deletions sentry_sdk/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(
ip_address=None, # type: Optional[str]
errors=None, # type: Optional[int]
user=None, # type: Optional[Any]
session_mode="application", # type: str
):
# type: (...) -> None
if sid is None:
Expand All @@ -58,6 +59,7 @@ def __init__(
self.duration = None # type: Optional[float]
self.user_agent = None # type: Optional[str]
self.ip_address = None # type: Optional[str]
self.session_mode = session_mode # type: str
self.errors = 0

self.update(
Expand Down
14 changes: 6 additions & 8 deletions sentry_sdk/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@ def is_auto_session_tracking_enabled(hub=None):
hub = sentry_sdk.Hub.current
should_track = hub.scope._force_auto_session_tracking
if should_track is None:
exp = hub.client.options["_experiments"] if hub.client else {}
should_track = exp.get("auto_session_tracking")
client_options = hub.client.options if hub.client else {}
should_track = client_options["auto_session_tracking"]
return should_track


@contextmanager
def auto_session_tracking(hub=None):
# type: (Optional[sentry_sdk.Hub]) -> Generator[None, None, None]
def auto_session_tracking(hub=None, session_mode="application"):
# type: (Optional[sentry_sdk.Hub], str) -> Generator[None, None, None]
"""Starts and stops a session automatically around a block."""
if hub is None:
hub = sentry_sdk.Hub.current
should_track = is_auto_session_tracking_enabled(hub)
if should_track:
hub.start_session()
hub.start_session(session_mode=session_mode)
try:
yield
finally:
Expand All @@ -59,12 +59,10 @@ class SessionFlusher(object):
def __init__(
self,
capture_func, # type: Callable[[Envelope], None]
session_mode, # type: str
flush_interval=60, # type: int
):
# type: (...) -> None
self.capture_func = capture_func
self.session_mode = session_mode
self.flush_interval = flush_interval
self.pending_sessions = [] # type: List[Any]
self.pending_aggregates = {} # type: Dict[Any, Any]
Expand Down Expand Up @@ -158,7 +156,7 @@ def add_session(
self, session # type: Session
):
# type: (...) -> None
if self.session_mode == "request":
if session.session_mode == "request":
self.add_aggregate_session(session)
else:
self.pending_sessions.append(session.to_json())
Expand Down
14 changes: 5 additions & 9 deletions tests/integrations/flask/test_flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,6 @@ def test_flask_session_tracking(sentry_init, capture_envelopes, app):
sentry_init(
integrations=[flask_sentry.FlaskIntegration()],
release="demo-release",
_experiments=dict(
auto_session_tracking=True,
),
)

@app.route("/")
Expand All @@ -276,16 +273,15 @@ def index():
first_event = first_event.get_event()
error_event = error_event.get_event()
session = session.items[0].payload.json
aggregates = session["aggregates"]

assert first_event["exception"]["values"][0]["type"] == "ValueError"
assert error_event["exception"]["values"][0]["type"] == "ZeroDivisionError"
assert session["status"] == "crashed"
assert session["did"] == "42"
assert session["errors"] == 2
assert session["init"]

assert len(aggregates) == 1
assert aggregates[0]["crashed"] == 1
assert aggregates[0]["started"]
assert session["attrs"]["release"] == "demo-release"
assert session["attrs"]["ip_address"] == "1.2.3.4"
assert session["attrs"]["user_agent"] == "blafasel/1.0"


@pytest.mark.parametrize("data", [{}, []], ids=["empty-dict", "empty-list"])
Expand Down
35 changes: 35 additions & 0 deletions tests/integrations/wsgi/test_wsgi.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from werkzeug.test import Client
import pytest

import sentry_sdk
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware

try:
Expand Down Expand Up @@ -201,3 +202,37 @@ def app(environ, start_response):
}
)
)


def test_session_mode_defaults_to_request_mode_in_wsgi_handler(
capture_envelopes, sentry_init
):
"""
Test that ensures that even though the default `session_mode` for
auto_session_tracking is `application`, that flips to `request` when we are
in the WSGI handler
"""

def app(environ, start_response):
start_response("200 OK", [])
return ["Go get the ball! Good dog!"]

traces_sampler = mock.Mock(return_value=True)
sentry_init(send_default_pii=True, traces_sampler=traces_sampler)

app = SentryWsgiMiddleware(app)
envelopes = capture_envelopes()

client = Client(app)

client.get("/dogs/are/great/")

sentry_sdk.flush()

sess = envelopes[1]
assert len(sess.items) == 1
sess_event = sess.items[0].payload.json

aggregates = sess_event["aggregates"]
assert len(aggregates) == 1
assert aggregates[0]["exited"] == 1
42 changes: 38 additions & 4 deletions tests/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,12 @@ def test_aggregates(sentry_init, capture_envelopes):
sentry_init(
release="fun-release",
environment="not-fun-env",
_experiments={"auto_session_tracking": True, "session_mode": "request"},
)
envelopes = capture_envelopes()

hub = Hub.current

with auto_session_tracking():
with auto_session_tracking(session_mode="request"):
with sentry_sdk.push_scope():
try:
with sentry_sdk.configure_scope() as scope:
Expand All @@ -62,10 +61,10 @@ def test_aggregates(sentry_init, capture_envelopes):
except Exception:
sentry_sdk.capture_exception()

with auto_session_tracking():
with auto_session_tracking(session_mode="request"):
pass

hub.start_session()
hub.start_session(session_mode="request")
hub.end_session()

sentry_sdk.flush()
Expand All @@ -85,3 +84,38 @@ def test_aggregates(sentry_init, capture_envelopes):
assert len(aggregates) == 1
assert aggregates[0]["exited"] == 2
assert aggregates[0]["errored"] == 1


def test_aggregates_explicitly_disabled_session_tracking_request_mode(
sentry_init, capture_envelopes
):
sentry_init(
release="fun-release", environment="not-fun-env", auto_session_tracking=False
)
envelopes = capture_envelopes()

hub = Hub.current

with auto_session_tracking(session_mode="request"):
with sentry_sdk.push_scope():
try:
raise Exception("all is wrong")
except Exception:
sentry_sdk.capture_exception()

with auto_session_tracking(session_mode="request"):
pass

hub.start_session(session_mode="request")
hub.end_session()

sentry_sdk.flush()

sess = envelopes[1]
assert len(sess.items) == 1
sess_event = sess.items[0].payload.json

aggregates = sorted_aggregates(sess_event)
assert len(aggregates) == 1
assert aggregates[0]["exited"] == 1
assert "errored" not in aggregates[0]