mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-31 14:11:50 +08:00
exporter/datadog: add support for resource labels and service.name (#1074)
* exporter/datadog: add support for resource labels and service.name
This commit is contained in:
@ -2,6 +2,8 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Add support for span resource labels and service name
|
||||
|
||||
## Version 0.12b0
|
||||
|
||||
Released 2020-08-14
|
||||
|
@ -6,3 +6,4 @@ SAMPLE_RATE_METRIC_KEY = "_sample_rate"
|
||||
SAMPLING_PRIORITY_KEY = "_sampling_priority_v1"
|
||||
ENV_KEY = "env"
|
||||
VERSION_KEY = "version"
|
||||
SERVICE_NAME_TAG = "service.name"
|
||||
|
@ -26,7 +26,13 @@ from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
||||
from opentelemetry.trace.status import StatusCanonicalCode
|
||||
|
||||
# pylint:disable=relative-beyond-top-level
|
||||
from .constants import DD_ORIGIN, ENV_KEY, SAMPLE_RATE_METRIC_KEY, VERSION_KEY
|
||||
from .constants import (
|
||||
DD_ORIGIN,
|
||||
ENV_KEY,
|
||||
SAMPLE_RATE_METRIC_KEY,
|
||||
SERVICE_NAME_TAG,
|
||||
VERSION_KEY,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -107,6 +113,7 @@ class DatadogSpanExporter(SpanExporter):
|
||||
self.agent_writer.stop()
|
||||
self.agent_writer.join(self.agent_writer.exit_timeout)
|
||||
|
||||
# pylint: disable=too-many-locals
|
||||
def _translate_to_datadog(self, spans):
|
||||
datadog_spans = []
|
||||
|
||||
@ -119,10 +126,16 @@ class DatadogSpanExporter(SpanExporter):
|
||||
# duration.
|
||||
tracer = None
|
||||
|
||||
# extract resource attributes to be used as tags as well as potential service name
|
||||
[
|
||||
resource_tags,
|
||||
resource_service_name,
|
||||
] = _extract_tags_from_resource(span.resource)
|
||||
|
||||
datadog_span = DatadogSpan(
|
||||
tracer,
|
||||
_get_span_name(span),
|
||||
service=self.service,
|
||||
service=resource_service_name or self.service,
|
||||
resource=_get_resource(span),
|
||||
span_type=_get_span_type(span),
|
||||
trace_id=trace_id,
|
||||
@ -140,7 +153,12 @@ class DatadogSpanExporter(SpanExporter):
|
||||
datadog_span.set_tag("error.msg", exc_val)
|
||||
datadog_span.set_tag("error.type", exc_type)
|
||||
|
||||
datadog_span.set_tags(span.attributes)
|
||||
# combine resource attributes and span attributes, don't modify existing span attributes
|
||||
combined_span_tags = {}
|
||||
combined_span_tags.update(resource_tags)
|
||||
combined_span_tags.update(span.attributes)
|
||||
|
||||
datadog_span.set_tags(combined_span_tags)
|
||||
|
||||
# add configured env tag
|
||||
if self.env is not None:
|
||||
@ -282,3 +300,19 @@ def _parse_tags_str(tags_str):
|
||||
parsed_tags[key] = value
|
||||
|
||||
return parsed_tags
|
||||
|
||||
|
||||
def _extract_tags_from_resource(resource):
|
||||
"""Parse tags from resource.attributes, except service.name which
|
||||
has special significance within datadog"""
|
||||
tags = {}
|
||||
service_name = None
|
||||
if not (resource and getattr(resource, "attributes", None)):
|
||||
return [tags, service_name]
|
||||
|
||||
for attribute_key, attribute_value in resource.attributes.items():
|
||||
if attribute_key == SERVICE_NAME_TAG:
|
||||
service_name = attribute_value
|
||||
else:
|
||||
tags[attribute_key] = attribute_value
|
||||
return [tags, service_name]
|
||||
|
@ -23,7 +23,7 @@ from ddtrace.internal.writer import AgentWriter
|
||||
from opentelemetry import trace as trace_api
|
||||
from opentelemetry.exporter import datadog
|
||||
from opentelemetry.sdk import trace
|
||||
from opentelemetry.sdk.trace import sampling
|
||||
from opentelemetry.sdk.trace import Resource, sampling
|
||||
from opentelemetry.sdk.util.instrumentation import InstrumentationInfo
|
||||
|
||||
|
||||
@ -144,6 +144,17 @@ class TestDatadogSpanExporter(unittest.TestCase):
|
||||
# pylint: disable=invalid-name
|
||||
self.maxDiff = None
|
||||
|
||||
resource = Resource(
|
||||
attributes={
|
||||
"key_resource": "some_resource",
|
||||
"service.name": "resource_service_name",
|
||||
}
|
||||
)
|
||||
|
||||
resource_without_service = Resource(
|
||||
attributes={"conflicting_key": "conflicting_value"}
|
||||
)
|
||||
|
||||
span_names = ("test1", "test2", "test3")
|
||||
trace_id = 0x6E0C63257DE34C926F9EFCD03927272E
|
||||
trace_id_low = 0x6F9EFCD03927272E
|
||||
@ -183,18 +194,25 @@ class TestDatadogSpanExporter(unittest.TestCase):
|
||||
parent=parent_context,
|
||||
kind=trace_api.SpanKind.CLIENT,
|
||||
instrumentation_info=instrumentation_info,
|
||||
resource=Resource({}),
|
||||
),
|
||||
trace.Span(
|
||||
name=span_names[1],
|
||||
context=parent_context,
|
||||
parent=None,
|
||||
instrumentation_info=instrumentation_info,
|
||||
resource=resource_without_service,
|
||||
),
|
||||
trace.Span(
|
||||
name=span_names[2], context=other_context, parent=None,
|
||||
name=span_names[2],
|
||||
context=other_context,
|
||||
parent=None,
|
||||
resource=resource,
|
||||
),
|
||||
]
|
||||
|
||||
otel_spans[1].set_attribute("conflicting_key", "original_value")
|
||||
|
||||
otel_spans[0].start(start_time=start_times[0])
|
||||
otel_spans[0].end(end_time=end_times[0])
|
||||
|
||||
@ -234,7 +252,12 @@ class TestDatadogSpanExporter(unittest.TestCase):
|
||||
duration=durations[1],
|
||||
error=0,
|
||||
service="test-service",
|
||||
meta={"env": "test", "team": "testers", "version": "0.0.1"},
|
||||
meta={
|
||||
"env": "test",
|
||||
"team": "testers",
|
||||
"version": "0.0.1",
|
||||
"conflicting_key": "original_value",
|
||||
},
|
||||
),
|
||||
dict(
|
||||
trace_id=trace_id_low,
|
||||
@ -245,8 +268,13 @@ class TestDatadogSpanExporter(unittest.TestCase):
|
||||
start=start_times[2],
|
||||
duration=durations[2],
|
||||
error=0,
|
||||
service="test-service",
|
||||
meta={"env": "test", "team": "testers", "version": "0.0.1"},
|
||||
service="resource_service_name",
|
||||
meta={
|
||||
"env": "test",
|
||||
"team": "testers",
|
||||
"version": "0.0.1",
|
||||
"key_resource": "some_resource",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
|
Reference in New Issue
Block a user