diff --git a/sentry_sdk/integrations/opentelemetry/potel_span_processor.py b/sentry_sdk/integrations/opentelemetry/potel_span_processor.py index cddaf24ab2..ebb5bbc17a 100644 --- a/sentry_sdk/integrations/opentelemetry/potel_span_processor.py +++ b/sentry_sdk/integrations/opentelemetry/potel_span_processor.py @@ -7,7 +7,7 @@ from sentry_sdk import capture_event from sentry_sdk.integrations.opentelemetry.utils import ( is_sentry_span, - convert_otel_timestamp, + convert_from_otel_timestamp, extract_span_data, ) from sentry_sdk.integrations.opentelemetry.consts import ( @@ -141,8 +141,8 @@ def _root_span_to_transaction_event(self, span): # TODO-neel-potel tx source based on integration "transaction_info": {"source": "custom"}, "contexts": contexts, - "start_timestamp": convert_otel_timestamp(span.start_time), - "timestamp": convert_otel_timestamp(span.end_time), + "start_timestamp": convert_from_otel_timestamp(span.start_time), + "timestamp": convert_from_otel_timestamp(span.end_time), } # type: Event return event @@ -168,8 +168,8 @@ def _span_to_json(self, span): "op": op, "description": description, "status": status, - "start_timestamp": convert_otel_timestamp(span.start_time), - "timestamp": convert_otel_timestamp(span.end_time), + "start_timestamp": convert_from_otel_timestamp(span.start_time), + "timestamp": convert_from_otel_timestamp(span.end_time), "origin": origin or SPAN_ORIGIN, } # type: dict[str, Any] diff --git a/sentry_sdk/integrations/opentelemetry/utils.py b/sentry_sdk/integrations/opentelemetry/utils.py index ecb1852404..2444131002 100644 --- a/sentry_sdk/integrations/opentelemetry/utils.py +++ b/sentry_sdk/integrations/opentelemetry/utils.py @@ -14,7 +14,7 @@ from sentry_sdk._types import TYPE_CHECKING if TYPE_CHECKING: - from typing import Optional, Mapping, Sequence + from typing import Optional, Mapping, Sequence, Union GRPC_ERROR_MAP = { @@ -72,11 +72,20 @@ def is_sentry_span(span): return False -def convert_otel_timestamp(time): +def convert_from_otel_timestamp(time): # type: (int) -> datetime + """Convert an OTel nanosecond-level timestamp to a datetime.""" return datetime.fromtimestamp(time / 1e9, timezone.utc) +def convert_to_otel_timestamp(time): + # type: (Union[datetime.datetime, float]) -> int + """Convert a datetime to an OTel timestamp (with nanosecond precision).""" + if isinstance(time, datetime): + return int(time.timestamp() * 1e9) + return int(time * 1e9) + + def extract_span_data(span): # type: (ReadableSpan) -> tuple[str, str, Optional[str], Optional[int], Optional[str]] op = span.name