Skip to content
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

Extract origin from span attributes #3432

Merged
merged 1 commit into from
Aug 13, 2024
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
8 changes: 4 additions & 4 deletions sentry_sdk/integrations/opentelemetry/potel_span_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ def _root_span_to_transaction_event(self, span):
span_id = format_span_id(span.context.span_id)
parent_span_id = format_span_id(span.parent.span_id) if span.parent else None

(op, description, status, _) = extract_span_data(span)
(op, description, status, _, origin) = extract_span_data(span)

trace_context = {
"trace_id": trace_id,
"span_id": span_id,
"origin": SPAN_ORIGIN,
"origin": origin,
"op": op,
"status": status,
} # type: dict[str, Any]
Expand Down Expand Up @@ -160,17 +160,17 @@ def _span_to_json(self, span):
span_id = format_span_id(span.context.span_id)
parent_span_id = format_span_id(span.parent.span_id) if span.parent else None

(op, description, status, _) = extract_span_data(span)
(op, description, status, _, origin) = extract_span_data(span)

span_json = {
"trace_id": trace_id,
"span_id": span_id,
"origin": SPAN_ORIGIN,
"op": op,
"description": description,
"status": status,
"start_timestamp": convert_otel_timestamp(span.start_time),
"timestamp": convert_otel_timestamp(span.end_time),
"origin": origin or SPAN_ORIGIN,
} # type: dict[str, Any]

if parent_span_id:
Expand Down
4 changes: 2 additions & 2 deletions sentry_sdk/integrations/opentelemetry/span_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def _update_span_with_otel_data(self, sentry_span, otel_span):
for key, val in otel_span.attributes.items():
sentry_span.set_data(key, val)

(op, description, status, http_status) = extract_span_data(otel_span)
(op, description, status, http_status, _) = extract_span_data(otel_span)
sentry_span.op = op
sentry_span.description = description

Expand All @@ -270,7 +270,7 @@ def _update_span_with_otel_data(self, sentry_span, otel_span):

def _update_transaction_with_otel_data(self, sentry_span, otel_span):
# type: (SentrySpan, OTelSpan) -> None
(op, _, status, http_status) = extract_span_data(otel_span)
(op, _, status, http_status, _) = extract_span_data(otel_span)
sentry_span.op = op

if http_status:
Expand Down
33 changes: 18 additions & 15 deletions sentry_sdk/integrations/opentelemetry/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from opentelemetry.sdk.trace import ReadableSpan
from sentry_sdk.consts import SPANSTATUS
from sentry_sdk.tracing import get_span_status_from_http_code
from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute
from urllib3.util import parse_url as urlparse

from sentry_sdk.utils import Dsn
Expand Down Expand Up @@ -77,13 +78,17 @@ def convert_otel_timestamp(time):


def extract_span_data(span):
# type: (ReadableSpan) -> tuple[str, str, Optional[str], Optional[int]]
# type: (ReadableSpan) -> tuple[str, str, Optional[str], Optional[int], Optional[str]]
op = span.name
description = span.name
status, http_status = extract_span_status(span)
origin = None

if span.attributes is None:
return (op, description, status, http_status)
return (op, description, status, http_status, origin)

origin = span.attributes.get(SentrySpanAttribute.ORIGIN)
description = span.attributes.get(SentrySpanAttribute.DESCRIPTION) or description

http_method = span.attributes.get(SpanAttributes.HTTP_METHOD)
http_method = cast("Optional[str]", http_method)
Expand All @@ -96,26 +101,21 @@ def extract_span_data(span):

rpc_service = span.attributes.get(SpanAttributes.RPC_SERVICE)
if rpc_service:
return ("rpc", description, status, http_status)
return ("rpc", description, status, http_status, origin)

messaging_system = span.attributes.get(SpanAttributes.MESSAGING_SYSTEM)
if messaging_system:
return ("message", description, status, http_status)
return ("message", description, status, http_status, origin)

faas_trigger = span.attributes.get(SpanAttributes.FAAS_TRIGGER)
if faas_trigger:
return (
str(faas_trigger),
description,
status,
http_status,
)
return (str(faas_trigger), description, status, http_status, origin)

return (op, description, status, http_status)
return (op, description, status, http_status, origin)


def span_data_for_http_method(span):
# type: (ReadableSpan) -> tuple[str, str, Optional[str], Optional[int]]
# type: (ReadableSpan) -> tuple[str, str, Optional[str], Optional[int], Optional[str]]
span_attributes = span.attributes or {}

op = "http"
Expand Down Expand Up @@ -151,11 +151,13 @@ def span_data_for_http_method(span):

status, http_status = extract_span_status(span)

return (op, description, status, http_status)
origin = span_attributes.get(SentrySpanAttribute.ORIGIN)

return (op, description, status, http_status, origin)


def span_data_for_db_query(span):
# type: (ReadableSpan) -> tuple[str, str, Optional[str], Optional[int]]
# type: (ReadableSpan) -> tuple[str, str, Optional[str], Optional[int], Optional[str]]
span_attributes = span.attributes or {}

op = "db"
Expand All @@ -164,8 +166,9 @@ def span_data_for_db_query(span):
statement = cast("Optional[str]", statement)

description = statement or span.name
origin = span_attributes.get(SentrySpanAttribute.ORIGIN)

return (op, description, None, None)
return (op, description, None, None, origin)


def extract_span_status(span):
Expand Down
8 changes: 4 additions & 4 deletions tests/integrations/opentelemetry/test_potel.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def test_root_span_transaction_payload_started_with_otel_only(capture_envelopes)
trace_context = contexts["trace"]
assert "trace_id" in trace_context
assert "span_id" in trace_context
assert trace_context["origin"] == "auto.otel"
assert trace_context["origin"] == "manual"
assert trace_context["op"] == "request"
assert trace_context["status"] == "ok"

Expand All @@ -62,7 +62,7 @@ def test_child_span_payload_started_with_otel_only(capture_envelopes):

assert span["op"] == "db"
assert span["description"] == "db"
assert span["origin"] == "auto.otel"
assert span["origin"] == "manual"
assert span["status"] == "ok"
assert span["span_id"] is not None
assert span["trace_id"] == payload["contexts"]["trace"]["trace_id"]
Expand Down Expand Up @@ -124,7 +124,7 @@ def test_root_span_transaction_payload_started_with_sentry_only(capture_envelope
trace_context = contexts["trace"]
assert "trace_id" in trace_context
assert "span_id" in trace_context
assert trace_context["origin"] == "auto.otel"
assert trace_context["origin"] == "manual"
assert trace_context["op"] == "request"
assert trace_context["status"] == "ok"

Expand All @@ -145,7 +145,7 @@ def test_child_span_payload_started_with_sentry_only(capture_envelopes):

assert span["op"] == "db"
assert span["description"] == "db"
assert span["origin"] == "auto.otel"
assert span["origin"] == "manual"
assert span["status"] == "ok"
assert span["span_id"] is not None
assert span["trace_id"] == payload["contexts"]["trace"]["trace_id"]
Expand Down
23 changes: 19 additions & 4 deletions tests/integrations/opentelemetry/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"description": "OTel Span Blank",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
(
Expand All @@ -36,6 +37,7 @@
"description": "OTel Span RPC",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
(
Expand All @@ -49,6 +51,7 @@
"description": "OTel Span Messaging",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
(
Expand All @@ -62,6 +65,7 @@
"description": "OTel Span FaaS",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
],
Expand All @@ -72,12 +76,13 @@ def test_extract_span_data(name, status, attributes, expected):
otel_span.status = Status(StatusCode.UNSET)
otel_span.attributes = attributes

op, description, status, http_status_code = extract_span_data(otel_span)
op, description, status, http_status_code, origin = extract_span_data(otel_span)
result = {
"op": op,
"description": description,
"status": status,
"http_status_code": http_status_code,
"origin": origin,
}
assert result == expected

Expand All @@ -99,6 +104,7 @@ def test_extract_span_data(name, status, attributes, expected):
"description": "GET",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
(
Expand All @@ -113,6 +119,7 @@ def test_extract_span_data(name, status, attributes, expected):
"description": "GET /target",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
(
Expand All @@ -127,6 +134,7 @@ def test_extract_span_data(name, status, attributes, expected):
"description": "GET example.com",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
(
Expand All @@ -142,6 +150,7 @@ def test_extract_span_data(name, status, attributes, expected):
"description": "GET /target",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
(
Expand All @@ -156,6 +165,7 @@ def test_extract_span_data(name, status, attributes, expected):
"description": "GET https://example.com/bla/",
"status": "ok",
"http_status_code": None,
"origin": None,
},
),
],
Expand All @@ -166,12 +176,15 @@ def test_span_data_for_http_method(kind, status, attributes, expected):
otel_span.status = status
otel_span.attributes = attributes

op, description, status, http_status_code = span_data_for_http_method(otel_span)
op, description, status, http_status_code, origin = span_data_for_http_method(
otel_span
)
result = {
"op": op,
"description": description,
"status": status,
"http_status_code": http_status_code,
"origin": origin,
}
assert result == expected

Expand All @@ -181,19 +194,21 @@ def test_span_data_for_db_query():
otel_span.name = "OTel Span"
otel_span.attributes = {}

op, description, status, http_status = span_data_for_db_query(otel_span)
op, description, status, http_status, origin = span_data_for_db_query(otel_span)
assert op == "db"
assert description == "OTel Span"
assert status is None
assert http_status is None
assert origin is None

otel_span.attributes = {"db.statement": "SELECT * FROM table;"}

op, description, status, http_status = span_data_for_db_query(otel_span)
op, description, status, http_status, origin = span_data_for_db_query(otel_span)
assert op == "db"
assert description == "SELECT * FROM table;"
assert status is None
assert http_status is None
assert origin is None


@pytest.mark.parametrize(
Expand Down
Loading