Skip to content

Commit 19914cd

Browse files
authored
feat(tracing): Add convenience function update_current_span. (#4673)
Manually setting data on spans for our insights modules can be made easier. This PR introduces a convenience function. Right now users need to do some like this: ```python import sentry_sdk span = sentry_sdk.get_current_span() if span is not None: span.description = f"Some {dynamic} name" span.set_attribute("key1", "value1") span.set_attribute("key2", "value2") ``` With this new convenience function a user can do: ```python import sentry_sdk sentry_sdk.update_current_span( name=f"Some {dynamic} name", attributes={ "key1": "value1", "key2": "value2", }, )
1 parent 63e0c67 commit 19914cd

File tree

4 files changed

+127
-0
lines changed

4 files changed

+127
-0
lines changed

docs/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Performance Monitoring
4141
.. autofunction:: sentry_sdk.api.get_current_span
4242
.. autofunction:: sentry_sdk.api.start_span
4343
.. autofunction:: sentry_sdk.api.start_transaction
44+
.. autofunction:: sentry_sdk.api.update_current_span
4445

4546

4647
Distributed Tracing

sentry_sdk/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"start_session",
5151
"end_session",
5252
"set_transaction_name",
53+
"update_current_span",
5354
]
5455

5556
# Initialize the debug support after everything is loaded

sentry_sdk/api.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def overload(x):
8585
"start_session",
8686
"end_session",
8787
"set_transaction_name",
88+
"update_current_span",
8889
]
8990

9091

@@ -473,3 +474,82 @@ def end_session():
473474
def set_transaction_name(name, source=None):
474475
# type: (str, Optional[str]) -> None
475476
return get_current_scope().set_transaction_name(name, source)
477+
478+
479+
def update_current_span(op=None, name=None, attributes=None, data=None):
480+
# type: (Optional[str], Optional[str], Optional[dict[str, Union[str, int, float, bool]]], Optional[dict[str, Any]]) -> None
481+
"""
482+
Update the current active span with the provided parameters.
483+
484+
This function allows you to modify properties of the currently active span.
485+
If no span is currently active, this function will do nothing.
486+
487+
:param op: The operation name for the span. This is a high-level description
488+
of what the span represents (e.g., "http.client", "db.query").
489+
You can use predefined constants from :py:class:`sentry_sdk.consts.OP`
490+
or provide your own string. If not provided, the span's operation will
491+
remain unchanged.
492+
:type op: str or None
493+
494+
:param name: The human-readable name/description for the span. This provides
495+
more specific details about what the span represents (e.g., "GET /api/users",
496+
"SELECT * FROM users"). If not provided, the span's name will remain unchanged.
497+
:type name: str or None
498+
499+
:param data: A dictionary of key-value pairs to add as data to the span. This
500+
data will be merged with any existing span data. If not provided,
501+
no data will be added.
502+
503+
.. deprecated:: 2.35.0
504+
Use ``attributes`` instead. The ``data`` parameter will be removed
505+
in a future version.
506+
:type data: dict[str, Union[str, int, float, bool]] or None
507+
508+
:param attributes: A dictionary of key-value pairs to add as attributes to the span.
509+
Attribute values must be strings, integers, floats, or booleans. These
510+
attributes will be merged with any existing span data. If not provided,
511+
no attributes will be added.
512+
:type attributes: dict[str, Union[str, int, float, bool]] or None
513+
514+
:returns: None
515+
516+
.. versionadded:: 2.35.0
517+
518+
Example::
519+
520+
import sentry_sdk
521+
from sentry_sdk.consts import OP
522+
523+
sentry_sdk.update_current_span(
524+
op=OP.FUNCTION,
525+
name="process_user_data",
526+
attributes={"user_id": 123, "batch_size": 50}
527+
)
528+
"""
529+
current_span = get_current_span()
530+
531+
if current_span is None:
532+
return
533+
534+
if op is not None:
535+
current_span.op = op
536+
537+
if name is not None:
538+
# internally it is still description
539+
current_span.description = name
540+
541+
if data is not None and attributes is not None:
542+
raise ValueError(
543+
"Cannot provide both `data` and `attributes`. Please use only `attributes`."
544+
)
545+
546+
if data is not None:
547+
warnings.warn(
548+
"The `data` parameter is deprecated. Please use `attributes` instead.",
549+
DeprecationWarning,
550+
stacklevel=2,
551+
)
552+
attributes = data
553+
554+
if attributes is not None:
555+
current_span.update_data(attributes)

tests/tracing/test_misc.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,3 +540,48 @@ def test_span_set_data_update_data(sentry_init, capture_events):
540540
"thread.id": mock.ANY,
541541
"thread.name": mock.ANY,
542542
}
543+
544+
545+
def test_update_current_span(sentry_init, capture_events):
546+
sentry_init(traces_sample_rate=1.0)
547+
548+
events = capture_events()
549+
550+
with sentry_sdk.start_transaction(name="test-transaction"):
551+
with start_span(op="test-span-op", name="test-span-name"):
552+
sentry_sdk.update_current_span(
553+
op="updated-span-op",
554+
name="updated-span-name",
555+
attributes={
556+
"key0": "value0",
557+
"key1": "value1",
558+
},
559+
)
560+
561+
sentry_sdk.update_current_span(
562+
op="updated-span-op-2",
563+
)
564+
565+
sentry_sdk.update_current_span(
566+
name="updated-span-name-3",
567+
)
568+
569+
sentry_sdk.update_current_span(
570+
attributes={
571+
"key1": "updated-value-4",
572+
"key2": "value2",
573+
},
574+
)
575+
576+
(event,) = events
577+
span = event["spans"][0]
578+
579+
assert span["op"] == "updated-span-op-2"
580+
assert span["description"] == "updated-span-name-3"
581+
assert span["data"] == {
582+
"key0": "value0",
583+
"key1": "updated-value-4",
584+
"key2": "value2",
585+
"thread.id": mock.ANY,
586+
"thread.name": mock.ANY,
587+
}

0 commit comments

Comments
 (0)