-
Notifications
You must be signed in to change notification settings - Fork 579
feat(span-streaming): Add more span properties #5421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dd89e68
014e2cc
ba0478e
4768e99
bae1f67
4de063c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,15 +6,61 @@ | |
| """ | ||
|
|
||
| import uuid | ||
| from enum import Enum | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| from sentry_sdk.consts import SPANDATA | ||
| from sentry_sdk.utils import format_attribute | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing import Optional | ||
| from typing import Optional, Union | ||
| from sentry_sdk._types import Attributes, AttributeValue | ||
|
|
||
|
|
||
| FLAGS_CAPACITY = 10 | ||
|
|
||
|
|
||
| class SpanStatus(str, Enum): | ||
| OK = "ok" | ||
| ERROR = "error" | ||
|
|
||
| def __str__(self) -> str: | ||
| return self.value | ||
|
|
||
|
|
||
| # Segment source, see | ||
| # https://getsentry.github.io/sentry-conventions/generated/attributes/sentry.html#sentryspansource | ||
| class SegmentSource(str, Enum): | ||
| COMPONENT = "component" | ||
| CUSTOM = "custom" | ||
| ROUTE = "route" | ||
| TASK = "task" | ||
| URL = "url" | ||
| VIEW = "view" | ||
|
|
||
| def __str__(self) -> str: | ||
| return self.value | ||
|
|
||
|
|
||
| # These are typically high cardinality and the server hates them | ||
| LOW_QUALITY_SEGMENT_SOURCES = [ | ||
| SegmentSource.URL, | ||
| ] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused constant
|
||
|
|
||
|
|
||
| SOURCE_FOR_STYLE = { | ||
| "endpoint": SegmentSource.COMPONENT, | ||
| "function_name": SegmentSource.COMPONENT, | ||
| "handler_name": SegmentSource.COMPONENT, | ||
| "method_and_path_pattern": SegmentSource.ROUTE, | ||
| "path": SegmentSource.URL, | ||
| "route_name": SegmentSource.COMPONENT, | ||
| "route_pattern": SegmentSource.ROUTE, | ||
| "uri_template": SegmentSource.ROUTE, | ||
| "url": SegmentSource.ROUTE, | ||
| } | ||
|
|
||
|
|
||
| class StreamedSpan: | ||
| """ | ||
| A span holds timing information of a block of code. | ||
|
|
@@ -26,9 +72,12 @@ class StreamedSpan: | |
| """ | ||
|
|
||
| __slots__ = ( | ||
| "name", | ||
| "_name", | ||
| "_attributes", | ||
| "_span_id", | ||
| "_trace_id", | ||
| "_status", | ||
| "_flags", | ||
| ) | ||
|
|
||
| def __init__( | ||
|
|
@@ -38,13 +87,19 @@ def __init__( | |
| attributes: "Optional[Attributes]" = None, | ||
| trace_id: "Optional[str]" = None, | ||
| ): | ||
| self.name: str = name | ||
| self._name: str = name | ||
| self._attributes: "Attributes" = {} | ||
| if attributes: | ||
| for attribute, value in attributes.items(): | ||
| self.set_attribute(attribute, value) | ||
|
|
||
| self._trace_id = trace_id | ||
| self._span_id: "Optional[str]" = None | ||
| self._trace_id: "Optional[str]" = trace_id | ||
|
|
||
| self.set_status(SpanStatus.OK) | ||
| self.set_source(SegmentSource.CUSTOM) | ||
|
|
||
| self._flags: dict[str, bool] = {} | ||
|
|
||
| def get_attributes(self) -> "Attributes": | ||
| return self._attributes | ||
|
|
@@ -62,6 +117,55 @@ def remove_attribute(self, key: str) -> None: | |
| except KeyError: | ||
| pass | ||
|
|
||
| def get_status(self) -> "Union[SpanStatus, str]": | ||
| if self._status in {s.value for s in SpanStatus}: | ||
| return SpanStatus(self._status) | ||
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return self._status | ||
|
|
||
| def set_status(self, status: "Union[SpanStatus, str]") -> None: | ||
| if isinstance(status, Enum): | ||
| status = status.value | ||
|
|
||
| self._status = status | ||
|
|
||
| def set_http_status(self, http_status: int) -> None: | ||
| self.set_attribute(SPANDATA.HTTP_STATUS_CODE, http_status) | ||
|
|
||
| if http_status >= 400: | ||
| self.set_status(SpanStatus.ERROR) | ||
| else: | ||
| self.set_status(SpanStatus.OK) | ||
|
|
||
| def get_name(self) -> str: | ||
| return self._name | ||
|
|
||
| def set_name(self, name: str) -> None: | ||
| self._name = name | ||
|
|
||
| def set_flag(self, flag: str, result: bool) -> None: | ||
| if len(self._flags) < FLAGS_CAPACITY: | ||
| self._flags[flag] = result | ||
|
|
||
| def set_op(self, op: str) -> None: | ||
| self.set_attribute("sentry.op", op) | ||
|
|
||
| def set_origin(self, origin: str) -> None: | ||
| self.set_attribute("sentry.origin", origin) | ||
|
|
||
| def set_source(self, source: "Union[str, SegmentSource]") -> None: | ||
| if isinstance(source, Enum): | ||
| source = source.value | ||
|
|
||
| self.set_attribute("sentry.span.source", source) | ||
|
|
||
| @property | ||
| def span_id(self) -> str: | ||
| if not self._span_id: | ||
| self._span_id = uuid.uuid4().hex[16:] | ||
|
|
||
| return self._span_id | ||
|
|
||
| @property | ||
| def trace_id(self) -> str: | ||
| if not self._trace_id: | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This source related stuff is all just copied from the old
TransactionSourceand will be used by integrations and DSC later.