Skip to content

Commit

Permalink
Cleanup OTLP exporter compression options, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aabmass committed Mar 5, 2021
1 parent 1af9f87 commit 691fe0b
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 47 deletions.
30 changes: 16 additions & 14 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Add `max_attr_value_length` support to Jaeger exporter
([#1633])(https://github.com/open-telemetry/opentelemetry-python/pull/1633)
([#1633](https://github.com/open-telemetry/opentelemetry-python/pull/1633))

### Changed
- Rename `IdsGenerator` to `IdGenerator`
([#1651])(https://github.com/open-telemetry/opentelemetry-python/pull/1651)
([#1651](https://github.com/open-telemetry/opentelemetry-python/pull/1651))
- Make TracerProvider's resource attribute private
([#1652])(https://github.com/open-telemetry/opentelemetry-python/pull/1652)
([#1652](https://github.com/open-telemetry/opentelemetry-python/pull/1652))
- Rename Resource's `create_empty` to `get_empty`
([#1653])(https://github.com/open-telemetry/opentelemetry-python/pull/1653)
([#1653](https://github.com/open-telemetry/opentelemetry-python/pull/1653))
- Renamed `BatchExportSpanProcessor` to `BatchSpanProcessor` and `SimpleExportSpanProcessor` to
`SimpleSpanProcessor`
([#1656])(https://github.com/open-telemetry/opentelemetry-python/pull/1656)
([#1656](https://github.com/open-telemetry/opentelemetry-python/pull/1656))
- Rename `DefaultSpan` to `NonRecordingSpan`
([#1661])(https://github.com/open-telemetry/opentelemetry-python/pull/1661)
([#1661](https://github.com/open-telemetry/opentelemetry-python/pull/1661))
- Moving `Getter`, `Setter` and `TextMapPropagator` out of `opentelemetry.trace.propagation` and
into `opentelemetry.propagators`
([#1662])(https://github.com/open-telemetry/opentelemetry-python/pull/1662)
([#1662](https://github.com/open-telemetry/opentelemetry-python/pull/1662))
- Rename `BaggagePropagator` to `W3CBaggagePropagator`
([#1663])(https://github.com/open-telemetry/opentelemetry-python/pull/1663)
([#1663](https://github.com/open-telemetry/opentelemetry-python/pull/1663))
- Rename `JaegerSpanExporter` to `JaegerExporter` and rename `ZipkinSpanExporter` to `ZipkinExporter`
([#1664])(https://github.com/open-telemetry/opentelemetry-python/pull/1664)
([#1664](https://github.com/open-telemetry/opentelemetry-python/pull/1664))
- Cleanup OTLP exporter compression options, add tests
([#1671](https://github.com/open-telemetry/opentelemetry-python/pull/1671))

## [0.18b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v0.18b0) - 2021-02-16

### Added
- Add urllib to opentelemetry-bootstrap target list
([#1584])(https://github.com/open-telemetry/opentelemetry-python/pull/1584)
([#1584](https://github.com/open-telemetry/opentelemetry-python/pull/1584))

## [1.0.0rc1](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.0.0rc1) - 2021-02-12

### Changed
- Tracer provider environment variables are now consistent with the rest
([#1571](https://github.com/open-telemetry/opentelemetry-python/pull/1571)])
([#1571](https://github.com/open-telemetry/opentelemetry-python/pull/1571))
- Rename `TRACE_` to `TRACES_` for environment variables
([#1595](https://github.com/open-telemetry/opentelemetry-python/pull/1595)])
([#1595](https://github.com/open-telemetry/opentelemetry-python/pull/1595))
- Limits for Span attributes, events and links have been updated to 128
([1597](https://github.com/open-telemetry/opentelemetry-python/pull/1597)])
([1597](https://github.com/open-telemetry/opentelemetry-python/pull/1597))
- Read-only Span attributes have been moved to ReadableSpan class
([#1560](https://github.com/open-telemetry/opentelemetry-python/pull/1560))
- `BatchExportSpanProcessor` flushes export queue when it reaches `max_export_batch_size`
([#1521])(https://github.com/open-telemetry/opentelemetry-python/pull/1521)

### Added
- Added `end_on_exit` argument to `start_as_current_span`
([#1519](https://github.com/open-telemetry/opentelemetry-python/pull/1519)])
([#1519](https://github.com/open-telemetry/opentelemetry-python/pull/1519))
- Add `Span.set_attributes` method to set multiple values with one call
([#1520](https://github.com/open-telemetry/opentelemetry-python/pull/1520))
- Make sure Resources follow semantic conventions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

"""OTLP Exporter"""

import enum
import logging
from abc import ABC, abstractmethod
from collections.abc import Mapping, Sequence
Expand All @@ -40,6 +39,7 @@
from opentelemetry.proto.resource.v1.resource_pb2 import Resource
from opentelemetry.sdk.environment_variables import (
OTEL_EXPORTER_OTLP_CERTIFICATE,
OTEL_EXPORTER_OTLP_COMPRESSION,
OTEL_EXPORTER_OTLP_ENDPOINT,
OTEL_EXPORTER_OTLP_HEADERS,
OTEL_EXPORTER_OTLP_INSECURE,
Expand All @@ -54,9 +54,22 @@
ExportServiceRequestT = TypeVar("ExportServiceRequestT")
ExportResultT = TypeVar("ExportResultT")

_ENVIRON_TO_COMPRESSION = {
None: None,
"gzip": Compression.Gzip,
"deflate": Compression.Deflate,
}

class OTLPCompression(enum.Enum):
gzip = "gzip"

def environ_to_compression(environ_key: str) -> Optional[Compression]:
environ_value = environ.get(environ_key)
if environ_value not in _ENVIRON_TO_COMPRESSION:
raise Exception(
'Invalid value "{}" for compression envvar {}'.format(
environ_value, environ_key
)
)
return _ENVIRON_TO_COMPRESSION[environ_value]


def _translate_key_values(key: Text, value: Any) -> KeyValue:
Expand Down Expand Up @@ -87,7 +100,7 @@ def _translate_key_values(key: Text, value: Any) -> KeyValue:
return KeyValue(key=key, value=any_value)


def _get_resource_data(
def get_resource_data(
sdk_resource_instrumentation_library_data: Dict[
SDKResource, ResourceDataT
],
Expand Down Expand Up @@ -160,7 +173,7 @@ def __init__(
credentials: Optional[ChannelCredentials] = None,
headers: Optional[Sequence] = None,
timeout: Optional[int] = None,
compression: str = None,
compression: Optional[Compression] = None,
):
super().__init__()

Expand All @@ -187,30 +200,15 @@ def __init__(
)
self._collector_span_kwargs = None

if compression is None:
compression_algorithm = Compression.NoCompression
elif (
compression in OTLPCompression._value2member_map_
and OTLPCompression(compression) is OTLPCompression.gzip
):
compression_algorithm = Compression.Gzip
else:
compression_str = environ.get(OTEL_EXPORTER_OTLP_INSECURE)
if compression_str is None:
compression_algorithm = Compression.NoCompression
elif (
compression_str in OTLPCompression._value2member_map_
and OTLPCompression(compression_str) is OTLPCompression.gzip
):
compression_algorithm = Compression.Gzip
else:
raise ValueError(
"OTEL_EXPORTER_OTLP_COMPRESSION environment variable does not match gzip."
)
compression = (
environ_to_compression(OTEL_EXPORTER_OTLP_COMPRESSION)
if compression is None
else compression
) or Compression.NoCompression

if insecure:
self._client = self._stub(
insecure_channel(endpoint, compression=compression_algorithm)
insecure_channel(endpoint, compression=compression)
)
return

Expand All @@ -226,9 +224,7 @@ def __init__(
environ.get(OTEL_EXPORTER_OTLP_CERTIFICATE)
)
self._client = self._stub(
secure_channel(
endpoint, credentials, compression=compression_algorithm
)
secure_channel(endpoint, credentials, compression=compression)
)

@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
from os import environ
from typing import Optional, Sequence

from grpc import ChannelCredentials
from grpc import ChannelCredentials, Compression

from opentelemetry.exporter.otlp.exporter import (
OTLPExporterMixin,
_get_resource_data,
_load_credential_from_file,
_translate_key_values,
environ_to_compression,
get_resource_data,
)
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
ExportTraceServiceRequest,
Expand All @@ -40,6 +41,7 @@
from opentelemetry.proto.trace.v1.trace_pb2 import Status
from opentelemetry.sdk.environment_variables import (
OTEL_EXPORTER_OTLP_SPAN_CERTIFICATE,
OTEL_EXPORTER_OTLP_SPAN_COMPRESSION,
OTEL_EXPORTER_OTLP_SPAN_ENDPOINT,
OTEL_EXPORTER_OTLP_SPAN_HEADERS,
OTEL_EXPORTER_OTLP_SPAN_INSECURE,
Expand Down Expand Up @@ -80,6 +82,7 @@ def __init__(
credentials: Optional[ChannelCredentials] = None,
headers: Optional[Sequence] = None,
timeout: Optional[int] = None,
compression: Optional[Compression] = None,
):
if insecure is None:
insecure = environ.get(OTEL_EXPORTER_OTLP_SPAN_INSECURE)
Expand All @@ -97,6 +100,12 @@ def __init__(
int(environ_timeout) if environ_timeout is not None else None
)

compression = (
environ_to_compression(OTEL_EXPORTER_OTLP_SPAN_COMPRESSION)
if compression is None
else compression
)

super().__init__(
**{
"endpoint": endpoint
Expand All @@ -106,6 +115,7 @@ def __init__(
"headers": headers
or environ.get(OTEL_EXPORTER_OTLP_SPAN_HEADERS),
"timeout": timeout or environ_timeout,
"compression": compression,
}
)

Expand Down Expand Up @@ -274,7 +284,7 @@ def _translate_data(
].spans.append(CollectorSpan(**self._collector_span_kwargs))

return ExportTraceServiceRequest(
resource_spans=_get_resource_data(
resource_spans=get_resource_data(
sdk_resource_instrumentation_library_spans,
ResourceSpans,
"spans",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from unittest import TestCase
from unittest.mock import patch

from grpc import Compression

from opentelemetry.exporter.otlp.exporter import environ_to_compression


class TestOTLPExporterMixin(TestCase):
def test_environ_to_compression(self):
with patch.dict(
"os.environ",
{
"test_gzip": "gzip",
"test_deflate": "deflate",
"test_invalid": "some invalid compression",
},
):
self.assertEqual(
environ_to_compression("test_gzip"), Compression.Gzip
)
self.assertEqual(
environ_to_compression("test_deflate"), Compression.Deflate
)
self.assertIsNone(environ_to_compression("missing_key"),)
with self.assertRaises(Exception):
environ_to_compression("test_invalid")
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from google.protobuf.duration_pb2 import Duration
from google.rpc.error_details_pb2 import RetryInfo
from grpc import ChannelCredentials, StatusCode, server
from grpc import ChannelCredentials, Compression, StatusCode, server

from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
Expand All @@ -46,7 +46,9 @@
from opentelemetry.proto.trace.v1.trace_pb2 import Span as OTLPSpan
from opentelemetry.proto.trace.v1.trace_pb2 import Status
from opentelemetry.sdk.environment_variables import (
OTEL_EXPORTER_OTLP_COMPRESSION,
OTEL_EXPORTER_OTLP_SPAN_CERTIFICATE,
OTEL_EXPORTER_OTLP_SPAN_COMPRESSION,
OTEL_EXPORTER_OTLP_SPAN_ENDPOINT,
OTEL_EXPORTER_OTLP_SPAN_HEADERS,
OTEL_EXPORTER_OTLP_SPAN_TIMEOUT,
Expand Down Expand Up @@ -174,6 +176,7 @@ def tearDown(self):
+ "/fixtures/test.cert",
OTEL_EXPORTER_OTLP_SPAN_HEADERS: "key1=value1,key2=value2",
OTEL_EXPORTER_OTLP_SPAN_TIMEOUT: "10",
OTEL_EXPORTER_OTLP_SPAN_COMPRESSION: "gzip",
},
)
@patch("opentelemetry.exporter.otlp.exporter.OTLPExporterMixin.__init__")
Expand All @@ -186,6 +189,7 @@ def test_env_variables(self, mock_exporter_mixin):
self.assertEqual(kwargs["endpoint"], "collector:4317")
self.assertEqual(kwargs["headers"], "key1=value1,key2=value2")
self.assertEqual(kwargs["timeout"], 10)
self.assertEqual(kwargs["compression"], Compression.Gzip)
self.assertIsNotNone(kwargs["credentials"])
self.assertIsInstance(kwargs["credentials"], ChannelCredentials)

Expand Down Expand Up @@ -220,6 +224,57 @@ def test_otlp_headers_from_env(self, mock_ssl_channel, mock_secure):
exporter._headers, (("key3", "value3"), ("key4", "value4"))
)

# pylint: disable=no-self-use
def test_otlp_compression_from_env(self):
# Specifying kwarg should take precedence over env
with patch(
"opentelemetry.exporter.otlp.exporter.insecure_channel"
) as mock_insecure_channel, patch.dict(
"os.environ", {OTEL_EXPORTER_OTLP_COMPRESSION: "gzip"}
):
OTLPSpanExporter(
insecure=True, compression=Compression.NoCompression
)
mock_insecure_channel.assert_called_once_with(
"localhost:4317", compression=Compression.NoCompression
)

# No env or kwarg should be NoCompression
with patch(
"opentelemetry.exporter.otlp.exporter.insecure_channel"
) as mock_insecure_channel, patch.dict("os.environ", {}):
OTLPSpanExporter(insecure=True)
mock_insecure_channel.assert_called_once_with(
"localhost:4317", compression=Compression.NoCompression
)

# Just OTEL_EXPORTER_OTLP_COMPRESSION should work
with patch(
"opentelemetry.exporter.otlp.exporter.insecure_channel"
) as mock_insecure_channel, patch.dict(
"os.environ", {OTEL_EXPORTER_OTLP_COMPRESSION: "deflate"}
):
OTLPSpanExporter(insecure=True)
mock_insecure_channel.assert_called_once_with(
"localhost:4317", compression=Compression.Deflate
)

# OTEL_EXPORTER_OTLP_SPAN_COMPRESSION as higher priority than
# OTEL_EXPORTER_OTLP_COMPRESSION
with patch(
"opentelemetry.exporter.otlp.exporter.insecure_channel"
) as mock_insecure_channel, patch.dict(
"os.environ",
{
OTEL_EXPORTER_OTLP_COMPRESSION: "deflate",
OTEL_EXPORTER_OTLP_SPAN_COMPRESSION: "gzip",
},
):
OTLPSpanExporter(insecure=True)
mock_insecure_channel.assert_called_once_with(
"localhost:4317", compression=Compression.Gzip
)

@patch("opentelemetry.exporter.otlp.exporter.ssl_channel_credentials")
@patch("opentelemetry.exporter.otlp.exporter.secure_channel")
# pylint: disable=unused-argument
Expand Down

0 comments on commit 691fe0b

Please sign in to comment.