Skip to content
Merged
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
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Performance Monitoring
.. autofunction:: sentry_sdk.api.get_current_span
.. autofunction:: sentry_sdk.api.start_span
.. autofunction:: sentry_sdk.api.start_transaction
.. autofunction:: sentry_sdk.api.update_current_span


Distributed Tracing
Expand Down
1 change: 1 addition & 0 deletions sentry_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"start_session",
"end_session",
"set_transaction_name",
"update_current_span",
]

# Initialize the debug support after everything is loaded
Expand Down
80 changes: 80 additions & 0 deletions sentry_sdk/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def overload(x):
"start_session",
"end_session",
"set_transaction_name",
"update_current_span",
]


Expand Down Expand Up @@ -473,3 +474,82 @@ def end_session():
def set_transaction_name(name, source=None):
# type: (str, Optional[str]) -> None
return get_current_scope().set_transaction_name(name, source)


def update_current_span(op=None, name=None, attributes=None, data=None):
# type: (Optional[str], Optional[str], Optional[dict[str, Union[str, int, float, bool]]], Optional[dict[str, Any]]) -> None
"""
Update the current active span with the provided parameters.

This function allows you to modify properties of the currently active span.
If no span is currently active, this function will do nothing.

:param op: The operation name for the span. This is a high-level description
of what the span represents (e.g., "http.client", "db.query").
You can use predefined constants from :py:class:`sentry_sdk.consts.OP`
or provide your own string. If not provided, the span's operation will
remain unchanged.
:type op: str or None

:param name: The human-readable name/description for the span. This provides
more specific details about what the span represents (e.g., "GET /api/users",
"SELECT * FROM users"). If not provided, the span's name will remain unchanged.
:type name: str or None

:param data: A dictionary of key-value pairs to add as data to the span. This
data will be merged with any existing span data. If not provided,
no data will be added.

.. deprecated:: 2.35.0
Use ``attributes`` instead. The ``data`` parameter will be removed
in a future version.
:type data: dict[str, Union[str, int, float, bool]] or None

:param attributes: A dictionary of key-value pairs to add as attributes to the span.
Attribute values must be strings, integers, floats, or booleans. These
attributes will be merged with any existing span data. If not provided,
no attributes will be added.
:type attributes: dict[str, Union[str, int, float, bool]] or None

:returns: None

.. versionadded:: 2.35.0

Example::

import sentry_sdk
from sentry_sdk.consts import OP

sentry_sdk.update_current_span(
op=OP.FUNCTION,
name="process_user_data",
attributes={"user_id": 123, "batch_size": 50}
)
"""
current_span = get_current_span()

if current_span is None:
return

if op is not None:
current_span.op = op

if name is not None:
# internally it is still description
current_span.description = name

if data is not None and attributes is not None:
raise ValueError(
"Cannot provide both `data` and `attributes`. Please use only `attributes`."
)

if data is not None:
warnings.warn(
"The `data` parameter is deprecated. Please use `attributes` instead.",
DeprecationWarning,
stacklevel=2,
)
attributes = data

if attributes is not None:
current_span.update_data(attributes)
45 changes: 45 additions & 0 deletions tests/tracing/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,3 +540,48 @@ def test_span_set_data_update_data(sentry_init, capture_events):
"thread.id": mock.ANY,
"thread.name": mock.ANY,
}


def test_update_current_span(sentry_init, capture_events):
sentry_init(traces_sample_rate=1.0)

events = capture_events()

with sentry_sdk.start_transaction(name="test-transaction"):
with start_span(op="test-span-op", name="test-span-name"):
sentry_sdk.update_current_span(
op="updated-span-op",
name="updated-span-name",
attributes={
"key0": "value0",
"key1": "value1",
},
)

sentry_sdk.update_current_span(
op="updated-span-op-2",
)

sentry_sdk.update_current_span(
name="updated-span-name-3",
)

sentry_sdk.update_current_span(
attributes={
"key1": "updated-value-4",
"key2": "value2",
},
)

(event,) = events
span = event["spans"][0]

assert span["op"] == "updated-span-op-2"
assert span["description"] == "updated-span-name-3"
assert span["data"] == {
"key0": "value0",
"key1": "updated-value-4",
"key2": "value2",
"thread.id": mock.ANY,
"thread.name": mock.ANY,
}