Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .sampo/changesets/async-exception-span-ids.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
pypi/posthog: minor
---

`AsyncPosthog.capture_exception` now adds the active OpenTelemetry span's `$trace_id` and `$span_id`, like `Client.capture_exception`, even when `capture_trace_context` is off.
1 change: 1 addition & 0 deletions docs/migration-7.x-to-8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ The headers only fill a missing distinct ID or session ID, and any client can se
- `capture_exception` takes a `level=` argument on `Client`, `AsyncPosthog` and the module. It sets `$exception_level`, for example `"warning"` or `"fatal"`. The default is `"error"`, and an unknown value counts as unset.
- `capture_exception` ignores reserved exception properties in `properties`, such as `$exception_list`, `$exception_level` and `$exception_source`. In 7.x they overrode the SDK's values, with a `DeprecationWarning`. Use `level=` instead of `$exception_level`.
- `AsyncPosthog.capture_exception` now sends `$exception_level`.
- `AsyncPosthog.capture_exception` now adds `$trace_id` and `$span_id` from the active OpenTelemetry span, like `Client.capture_exception`. In 7.x it added them only with `capture_trace_context=True`.

## Event options

Expand Down
6 changes: 6 additions & 0 deletions posthog/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ def _build_capture_event(
trace_properties=(
_get_current_otel_span_properties()
if self.capture_trace_context
or kwargs.get("_capture_trace_context")
else None
),
),
Expand Down Expand Up @@ -922,6 +923,10 @@ def capture_exception(
``level`` sets ``$exception_level`` and defaults to ``"error"``. An unknown
value counts as unset. Reserved exception properties in ``properties``,
such as ``$exception_list`` and ``$exception_level``, are ignored.

When OpenTelemetry is installed and a valid span is active, its trace and
span IDs are added as ``$trace_id`` and ``$span_id`` event properties,
unless the event, a context tag or ``super_properties`` sets either one.
"""
try:
if exception is not None and exception_is_already_captured(exception):
Expand Down Expand Up @@ -998,6 +1003,7 @@ def capture_exception(
flags=kwargs.get("flags"),
disable_geoip=kwargs.get("disable_geoip"),
options=kwargs.get("options"),
_capture_trace_context=True,
)
if exception is not None and result is not None:
mark_exception_as_captured(exception, result)
Expand Down
15 changes: 9 additions & 6 deletions posthog/test/test_event_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,8 @@ def _span_ids(properties):
return {k: properties[k] for k in SPAN_IDS if k in properties}


def _sync_trace_context(method):
# Sync capture_exception adds the span ids even with capture_trace_context off.
def _trace_context_setting(method):
# capture_exception adds the span ids even with capture_trace_context off.
return method != "capture_exception"


Expand All @@ -541,7 +541,7 @@ def _sync_trace_context(method):
def test_sync_span_ids_fill_as_a_pair_below_caller_layers(method, source, expected):
events = _sync_wire_events(
_capture_in_span(method, source),
**_trace_config(source, _sync_trace_context(method)),
**_trace_config(source, _trace_context_setting(method)),
)
assert _span_ids(events[0]["properties"]) == expected

Expand All @@ -553,7 +553,8 @@ async def test_async_span_ids_fill_as_a_pair_below_caller_layers(
method, source, expected
):
events = await _async_wire_events(
_capture_in_span(method, source), **_trace_config(source)
_capture_in_span(method, source),
**_trace_config(source, _trace_context_setting(method)),
)
assert _span_ids(events[0]["properties"]) == expected

Expand All @@ -572,7 +573,7 @@ def test_sync_before_send_sees_and_changes_span_ids(method):
events = _sync_wire_events(
_capture_in_span(method),
before_send=_span_id_hook(seen),
**_trace_config(None, _sync_trace_context(method)),
**_trace_config(None, _trace_context_setting(method)),
)
assert seen == [SPAN_IDS]
assert _span_ids(events[0]["properties"]) == {**SPAN_IDS, "$span_id": "hook"}
Expand All @@ -583,7 +584,9 @@ def test_sync_before_send_sees_and_changes_span_ids(method):
async def test_async_before_send_sees_and_changes_span_ids(method):
seen: list = []
events = await _async_wire_events(
_capture_in_span(method), before_send=_span_id_hook(seen), **_trace_config(None)
_capture_in_span(method),
before_send=_span_id_hook(seen),
**_trace_config(None, _trace_context_setting(method)),
)
assert seen == [SPAN_IDS]
assert _span_ids(events[0]["properties"]) == {**SPAN_IDS, "$span_id": "hook"}
Expand Down
Loading