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

[exporter/datadog]: fix service name resolution #570

Merged
merged 15 commits into from
Jul 20, 2021
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#581](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/581))
- `opentelemetry-instrumentation-botocore` Suppress botocore downstream instrumentation like urllib3
([#563](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/563))
- `opentelemetry-exporter-datadog` Datadog exporter should not use `unknown_service` as fallback resource service name.
([#570](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/570))

### Added
- `opentelemetry-instrumentation-httpx` Add `httpx` instrumentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,12 @@ def _translate_to_datadog(self, spans):
[
resource_tags,
resource_service_name,
] = _extract_tags_from_resource(span.resource)
] = _extract_tags_from_resource(span.resource, self.service)

datadog_span = DatadogSpan(
tracer,
_get_span_name(span),
service=resource_service_name or self.service,
service=resource_service_name,
resource=_get_resource(span),
span_type=_get_span_type(span),
trace_id=trace_id,
Expand Down Expand Up @@ -312,19 +312,23 @@ def _parse_tags_str(tags_str):
return parsed_tags


def _extract_tags_from_resource(resource):
def _extract_tags_from_resource(resource, fallback_service_name):
"""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]
return [tags, fallback_service_name]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically tags could just be {} here since it's not really use here at this point too! But that's not in scope for your PR I would say :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. As you can tell my code is not particularly pythonic (i'm mostly ruby these days 😅 ). But there's a lot in this little exporter that could get cleaned up. I'll make a note to also try to give this code another pass for #574


service_name = None
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

if service_name is None or service_name == "unknown_service":
service_name = fallback_service_name

return [tags, service_name]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,3 +612,41 @@ def test_sampling_rate(self):
]
expected = [0.5]
self.assertListEqual(actual, expected)

def test_service_name_fallback(self):
context = trace_api.SpanContext(
trace_id=0x000000000000000000000000DEADBEEF,
span_id=0x34BF92DEEFC58C92,
is_remote=False,
trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED),
)
trace_api.get_tracer_provider().sampler = sampling.TraceIdRatioBased(
0.5
)

resource_with_default_name = Resource(
attributes={
"key_resource": "some_resource",
"service.name": "unknown_service",
}
)

span = trace._Span(
name="sampled",
context=context,
parent=None,
resource=resource_with_default_name,
)
span.start()
span.end()

# pylint: disable=protected-access
exporter = datadog.DatadogSpanExporter(service="fallback_service_name")
datadog_spans = [
span.to_dict() for span in exporter._translate_to_datadog([span])
]

self.assertEqual(len(datadog_spans), 1)

span = datadog_spans[0]
self.assertEqual(span["service"], "fallback_service_name")