Skip to content

Commit

Permalink
Populate service_name from exporting span in JaegerExporters (#1703)
Browse files Browse the repository at this point in the history
  • Loading branch information
lzchen authored Mar 17, 2021
1 parent 77ff070 commit 724c792
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
install it as a dependency. This will allow for the next package/protocol to also be in
its own package.
([#1695](https://github.com/open-telemetry/opentelemetry-python/pull/1695))
- Change Jaeger exporters to obtain service.name from span
([#1703](https://github.com/open-telemetry/opentelemetry-python/pull/1703))

### Removed
- Removed unused `get_hexadecimal_trace_id` and `get_hexadecimal_span_id` methods.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ def _collector_grpc_client(self) -> Optional[CollectorServiceStub]:
return self._grpc_client

def export(self, spans) -> SpanExportResult:
# Populate service_name from first span
# We restrict any SpanProcessor to be only associated with a single
# TracerProvider, so it is safe to assume that all Spans in a single
# batch all originate from one TracerProvider (and in turn have all
# the same service.name)
if spans:
service_name = spans[0].resource.attributes.get(SERVICE_NAME)
if service_name:
self.service_name = service_name
translator = Translate(spans)
pb_translator = ProtobufTranslator(
self.service_name, self._max_tag_value_length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import os
import unittest
from collections import OrderedDict
from unittest.mock import patch
from unittest import mock

# pylint:disable=no-name-in-module
# pylint:disable=import-error
Expand All @@ -34,7 +34,9 @@
OTEL_EXPORTER_JAEGER_ENDPOINT,
OTEL_RESOURCE_ATTRIBUTES,
)
from opentelemetry.sdk.trace import Resource, TracerProvider
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SpanExportResult
from opentelemetry.sdk.util.instrumentation import InstrumentationInfo
from opentelemetry.trace.status import Status, StatusCode

Expand All @@ -43,13 +45,13 @@
class TestJaegerExporter(unittest.TestCase):
def setUp(self):
# create and save span to be used in tests
context = trace_api.SpanContext(
self.context = trace_api.SpanContext(
trace_id=0x000000000000000000000000DEADBEEF,
span_id=0x00000000DEADBEF0,
is_remote=False,
)

self._test_span = trace._Span("test_span", context=context)
self._test_span = trace._Span("test_span", context=self.context)
self._test_span.start()
self._test_span.end()

Expand All @@ -62,7 +64,7 @@ def test_constructor_by_environment_variables(self):

collector_endpoint = "localhost:14250"

env_patch = patch.dict(
env_patch = mock.patch.dict(
"os.environ",
{
OTEL_EXPORTER_JAEGER_ENDPOINT: collector_endpoint,
Expand Down Expand Up @@ -438,3 +440,30 @@ def test_max_tag_value_length(self):
self.assertEqual("hello", tags_by_keys["key_string"])
self.assertEqual("('tup", tags_by_keys["key_tuple"])
self.assertEqual("some_", tags_by_keys["key_resource"])

def test_export(self):
client_mock = mock.Mock()
spans = []
exporter = JaegerExporter()
exporter._grpc_client = client_mock
status = exporter.export(spans)
self.assertEqual(SpanExportResult.SUCCESS, status)

def test_export_span_service_name(self):
resource = Resource.create({SERVICE_NAME: "test"})
span = trace._Span(
"test_span", context=self.context, resource=resource
)
span.start()
span.end()
client_mock = mock.Mock()
exporter = JaegerExporter()
exporter._grpc_client = client_mock
exporter.export([span])
self.assertEqual(exporter.service_name, "test")


class MockResponse:
def __init__(self, status_code):
self.status_code = status_code
self.text = status_code
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,15 @@ def _collector_http_client(self) -> Optional[Collector]:
return self._collector

def export(self, spans) -> SpanExportResult:

# Populate service_name from first span
# We restrict any SpanProcessor to be only associated with a single
# TracerProvider, so it is safe to assume that all Spans in a single
# batch all originate from one TracerProvider (and in turn have all
# the same service.name)
if spans:
service_name = spans[0].resource.attributes.get(SERVICE_NAME)
if service_name:
self.service_name = service_name
translator = Translate(spans)
thrift_translator = ThriftTranslator(self._max_tag_value_length)
jaeger_spans = translator._translate(thrift_translator)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@
class TestJaegerExporter(unittest.TestCase):
def setUp(self):
# create and save span to be used in tests
context = trace_api.SpanContext(
self.context = trace_api.SpanContext(
trace_id=0x000000000000000000000000DEADBEEF,
span_id=0x00000000DEADBEF0,
is_remote=False,
)

self._test_span = trace._Span("test_span", context=context)
self._test_span = trace._Span("test_span", context=self.context)
self._test_span.start()
self._test_span.end()
# pylint: disable=protected-access
Expand Down Expand Up @@ -491,6 +491,27 @@ def test_export(self):
self.assertEqual(collector_mock.submit.call_count, 1)
# trace_api._TRACER_PROVIDER = None

@patch("opentelemetry.exporter.jaeger.thrift.trace._TRACER_PROVIDER", None)
def test_export_span_service_name(self):
trace_api.set_tracer_provider(
TracerProvider(
resource=Resource.create({SERVICE_NAME: "text_export"})
)
)
exporter = jaeger_exporter.JaegerExporter(
agent_host_name="localhost", agent_port=6318
)
agent_client_mock = mock.Mock(spec=jaeger_exporter.AgentClientUDP)
exporter._agent_client = agent_client_mock
resource = Resource.create({SERVICE_NAME: "test"})
span = trace._Span(
"test_span", context=self.context, resource=resource
)
span.start()
span.end()
exporter.export([span])
self.assertEqual(exporter.service_name, "test")

def test_agent_client(self):
agent_client = jaeger_exporter.AgentClientUDP(
host_name="localhost", port=6354
Expand Down
19 changes: 6 additions & 13 deletions exporter/opentelemetry-exporter-jaeger/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ OpenTelemetry Jaeger Exporter
.. |pypi| image:: https://badge.fury.io/py/opentelemetry-exporter-jaeger.svg
:target: https://pypi.org/project/opentelemetry-exporter-jaeger/

This library allows to export tracing data to `Jaeger <https://www.jaegertracing.io/>`_.
This library is provided as a convenience to install all supported Jaeger Exporters. Currently it installs:
* opentelemetry-exporter-jaeger-proto
* opentelemetry-exporter-jaeger-thrift

To avoid unnecessary dependencies, users should install the specific package once they've determined their
preferred serialization method.

Installation
------------
Expand All @@ -16,18 +21,6 @@ Installation
pip install opentelemetry-exporter-jaeger


.. _Jaeger: https://www.jaegertracing.io/
.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/

Configuration
-------------

OpenTelemetry Jaeger Exporter can be configured by setting `JaegerExporter parameters
<https://github.com/open-telemetry/opentelemetry-python/blob/main/exporter/opentelemetry-exporter-jaeger
/src/opentelemetry/exporter/jaeger/__init__.py#L88>`_ or by setting
`environment variables <https://github.com/open-telemetry/opentelemetry-specification/blob/main/
specification/sdk-environment-variables.md#jaeger-exporter>`_

References
----------

Expand Down

0 comments on commit 724c792

Please sign in to comment.