Skip to content

Commit

Permalink
Merge branch 'main' into issue_1968
Browse files Browse the repository at this point in the history
  • Loading branch information
ocelotl authored Sep 24, 2021
2 parents 2afd1ba + 3cee4ef commit 94e4f8e
Show file tree
Hide file tree
Showing 21 changed files with 176 additions and 72 deletions.
18 changes: 0 additions & 18 deletions .github/workflows/close-stale-issues.yml

This file was deleted.

6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#2096](https://github.com/open-telemetry/opentelemetry-python/pull/2096))
- Fix propagation bug caused by counting skipped entries
([#2071](https://github.com/open-telemetry/opentelemetry-python/pull/2071))
- Add entry point for exporters with default protocol
([#2093](https://github.com/open-telemetry/opentelemetry-python/pull/2093))
- Do not skip sequence attribute on decode error
([#2097](https://github.com/open-telemetry/opentelemetry-python/pull/2097))
- `opentelemetry-test`: Add `HttpTestBase` to allow tests with actual TCP sockets
([#2101](https://github.com/open-telemetry/opentelemetry-python/pull/2101))
- Fix incorrect headers parsing via environment variables
([#2103](https://github.com/open-telemetry/opentelemetry-python/pull/2103))
- `opentelemetry-exporter-otlp`: Add `opentelemetry-otlp-proto-http` as dependency
- ([#2147](https://github.com/open-telemetry/opentelemetry-python/pull/2147))

## [1.5.0-0.24b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.5.0-0.24b0) - 2021-08-26

Expand Down
2 changes: 1 addition & 1 deletion docs/examples/auto-instrumentation/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -233,5 +233,5 @@ Additional resources
~~~~~~~~~~~~~~~~~~~~

In order to send telemetry to an OpenTelemetry Collector without doing any
additional configuration, read about the `OpenTelemetry Distro <../distro/README.html>`_
additional configuration, read about the `OpenTelemetry Distro <../distro>`_
package.
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ where = src
test =

[options.entry_points]
opentelemetry_exporter =
opentelemetry_traces_exporter =
jaeger_proto = opentelemetry.exporter.jaeger.proto.grpc:JaegerExporter
4 changes: 2 additions & 2 deletions exporter/opentelemetry-exporter-jaeger-thrift/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ where = src
test =

[options.entry_points]
opentelemetry_exporter =
jaeger_thrift = opentelemetry.exporter.jaeger.thrift:JaegerExporter
opentelemetry_traces_exporter =
jaeger_thrift = opentelemetry.exporter.jaeger.thrift:JaegerExporter
4 changes: 4 additions & 0 deletions exporter/opentelemetry-exporter-jaeger/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ install_requires =

[options.extras_require]
test =

[options.entry_points]
opentelemetry_traces_exporter =
jaeger = opentelemetry.exporter.jaeger.proto.grpc:JaegerExporter
4 changes: 2 additions & 2 deletions exporter/opentelemetry-exporter-opencensus/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ where = src
test =

[options.entry_points]
opentelemetry_exporter =
opencensus = opentelemetry.exporter.opencensus.trace_exporter:OpenCensusSpanExporter
opentelemetry_traces_exporter =
opencensus = opentelemetry.exporter.opencensus.trace_exporter:OpenCensusSpanExporter
4 changes: 2 additions & 2 deletions exporter/opentelemetry-exporter-otlp-proto-grpc/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,5 @@ test =
where = src

[options.entry_points]
opentelemetry_exporter =
otlp_proto_grpc_span = opentelemetry.exporter.otlp.proto.grpc.trace_exporter:OTLPSpanExporter
opentelemetry_traces_exporter =
otlp_proto_grpc = opentelemetry.exporter.otlp.proto.grpc.trace_exporter:OTLPSpanExporter
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
OTEL_EXPORTER_OTLP_TIMEOUT,
)
from opentelemetry.sdk.resources import Resource as SDKResource
from opentelemetry.util.re import parse_headers

logger = logging.getLogger(__name__)
SDKDataT = TypeVar("SDKDataT")
Expand Down Expand Up @@ -228,19 +229,8 @@ def __init__(

self._headers = headers or environ.get(OTEL_EXPORTER_OTLP_HEADERS)
if isinstance(self._headers, str):
temp_headers = []
for header_pair in self._headers.split(","):
key, value = header_pair.split("=", maxsplit=1)
key = key.strip().lower()
value = value.strip()
temp_headers.append(
(
key,
value,
)
)

self._headers = tuple(temp_headers)
temp_headers = parse_headers(self._headers)
self._headers = tuple(temp_headers.items())

self._timeout = timeout or int(
environ.get(OTEL_EXPORTER_OTLP_TIMEOUT, 10)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
OTEL_EXPORTER_OTLP_TRACES_HEADERS,
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT,
)
from opentelemetry.sdk.trace import Span as ReadableSpan
from opentelemetry.sdk.trace import ReadableSpan
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
from opentelemetry.trace import StatusCode

Expand Down
4 changes: 2 additions & 2 deletions exporter/opentelemetry-exporter-otlp-proto-http/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ test =
where = src

[options.entry_points]
opentelemetry_exporter =
otlp_proto_http_span = opentelemetry.exporter.otlp.proto.http.trace_exporter:OTLPSpanExporter
opentelemetry_traces_exporter =
otlp_proto_http = opentelemetry.exporter.otlp.proto.http.trace_exporter:OTLPSpanExporter
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from opentelemetry.exporter.otlp.proto.http.trace_exporter.encoder import (
_ProtobufEncoder,
)
from opentelemetry.util.re import parse_headers


_logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -70,7 +71,11 @@ def __init__(
OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE,
environ.get(OTEL_EXPORTER_OTLP_CERTIFICATE, True),
)
self._headers = headers or _headers_from_env()
headers_string = environ.get(
OTEL_EXPORTER_OTLP_TRACES_HEADERS,
environ.get(OTEL_EXPORTER_OTLP_HEADERS, ""),
)
self._headers = headers or parse_headers(headers_string)
self._timeout = timeout or int(
environ.get(
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT,
Expand Down Expand Up @@ -155,24 +160,6 @@ def shutdown(self):
self._shutdown = True


def _headers_from_env() -> Optional[Dict[str, str]]:
headers_str = environ.get(
OTEL_EXPORTER_OTLP_TRACES_HEADERS,
environ.get(OTEL_EXPORTER_OTLP_HEADERS),
)
headers = {}
if headers_str:
for header in headers_str.split(","):
try:
header_name, header_value = header.split("=")
headers[header_name.strip()] = header_value.strip()
except ValueError:
_logger.warning(
"Skipped invalid OTLP exporter header: %r", header
)
return headers


def _compression_from_env() -> Compression:
compression = (
environ.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_constructor_default(self):
OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE: "traces/certificate.env",
OTEL_EXPORTER_OTLP_TRACES_COMPRESSION: Compression.Deflate.value,
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "https://traces.endpoint.env",
OTEL_EXPORTER_OTLP_TRACES_HEADERS: "tracesEnv1=val1,tracesEnv2=val2",
OTEL_EXPORTER_OTLP_TRACES_HEADERS: "tracesEnv1=val1,tracesEnv2=val2,traceEnv3===val3==",
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT: "40",
},
)
Expand All @@ -77,7 +77,11 @@ def test_exporter_traces_env_take_priority(self):
self.assertIs(exporter._compression, Compression.Deflate)
self.assertEqual(
exporter._headers,
{"tracesEnv1": "val1", "tracesEnv2": "val2"},
{
"tracesenv1": "val1",
"tracesenv2": "val2",
"traceenv3": "==val3==",
},
)

@patch.dict(
Expand Down Expand Up @@ -127,7 +131,7 @@ def test_exporter_env(self):
self.assertEqual(exporter._timeout, int(OS_ENV_TIMEOUT))
self.assertIs(exporter._compression, Compression.Gzip)
self.assertEqual(
exporter._headers, {"envHeader1": "val1", "envHeader2": "val2"}
exporter._headers, {"envheader1": "val1", "envheader2": "val2"}
)

@patch.dict(
Expand All @@ -143,5 +147,5 @@ def test_headers_parse_from_env(self):

self.assertEqual(
cm.records[0].message,
"Skipped invalid OTLP exporter header: 'missingValue'",
"Header doesn't match the format: missingValue.",
)
5 changes: 5 additions & 0 deletions exporter/opentelemetry-exporter-otlp/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,8 @@ python_requires = >=3.6
packages=find_namespace:
install_requires =
opentelemetry-exporter-otlp-proto-grpc == 1.5.0
opentelemetry-exporter-otlp-proto-http == 1.5.0

[options.entry_points]
opentelemetry_traces_exporter =
otlp = opentelemetry.exporter.otlp.proto.grpc.trace_exporter:OTLPSpanExporter
4 changes: 2 additions & 2 deletions exporter/opentelemetry-exporter-zipkin-json/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ where = src
test =

[options.entry_points]
opentelemetry_exporter =
zipkin_json = opentelemetry.exporter.zipkin.json:ZipkinExporter
opentelemetry_traces_exporter =
zipkin_json = opentelemetry.exporter.zipkin.json:ZipkinExporter
4 changes: 2 additions & 2 deletions exporter/opentelemetry-exporter-zipkin-proto-http/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,5 @@ where = src
test =

[options.entry_points]
opentelemetry_exporter =
zipkin_proto = opentelemetry.exporter.zipkin.proto.http:ZipkinExporter
opentelemetry_traces_exporter =
zipkin_proto = opentelemetry.exporter.zipkin.proto.http:ZipkinExporter
4 changes: 4 additions & 0 deletions exporter/opentelemetry-exporter-zipkin/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ install_requires =

[options.extras_require]
test =

[options.entry_points]
opentelemetry_traces_exporter =
zipkin = opentelemetry.exporter.zipkin.proto.http:ZipkinExporter
56 changes: 56 additions & 0 deletions opentelemetry-api/src/opentelemetry/util/re.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
from re import compile, split
from typing import Mapping

_logger = logging.getLogger(__name__)


# https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specifying-headers-via-environment-variables
_OWS = r"[ \t]*"
# A key contains one or more US-ASCII character except CTLs or separators.
_KEY_FORMAT = (
r"[\x21\x23-\x27\x2a\x2b\x2d\x2e\x30-\x39\x41-\x5a\x5e-\x7a\x7c\x7e]+"
)
# A value contains a URL encoded UTF-8 string.
_VALUE_FORMAT = r"[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*"
_HEADER_FORMAT = _KEY_FORMAT + _OWS + r"=" + _OWS + _VALUE_FORMAT
_HEADER_PATTERN = compile(_HEADER_FORMAT)
_DELIMITER_PATTERN = compile(r"[ \t]*,[ \t]*")


# pylint: disable=invalid-name
def parse_headers(s: str) -> Mapping[str, str]:
"""
Parse ``s`` (a ``str`` instance containing HTTP headers). Uses W3C Baggage
HTTP header format https://www.w3.org/TR/baggage/#baggage-http-header-format, except that
additional semi-colon delimited metadata is not supported.
"""
headers = {}
for header in split(_DELIMITER_PATTERN, s):
if not header: # empty string
continue
match = _HEADER_PATTERN.fullmatch(header.strip())
if not match:
_logger.warning("Header doesn't match the format: %s.", header)
continue
# value may contain any number of `=`
name, value = match.string.split("=", 1)
name = name.strip().lower()
value = value.strip()
headers[name] = value

return headers
66 changes: 66 additions & 0 deletions opentelemetry-api/tests/util/test_re.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# type: ignore

import unittest

from opentelemetry.util.re import parse_headers


class TestParseHeaders(unittest.TestCase):
def test_parse_headers(self):
inp = [
# invalid header name
("=value", [], True),
("}key=value", [], True),
("@key()=value", [], True),
("/key=value", [], True),
# invalid header value
("name=\\", [], True),
('name=value"', [], True),
("name=;value", [], True),
# different header values
("name=", [("name", "")], False),
("name===value=", [("name", "==value=")], False),
# mix of valid and invalid headers
(
"name1=value1,invalidName, name2 = value2 , name3=value3==",
[
(
"name1",
"value1",
),
("name2", "value2"),
("name3", "value3=="),
],
True,
),
(
"=name=valu3; key1; key2, content = application, red=\tvelvet; cake",
[("content", "application")],
True,
),
]
for case in inp:
s, expected, warn = case
if warn:
with self.assertLogs(level="WARNING") as cm:
self.assertEqual(parse_headers(s), dict(expected))
self.assertTrue(
"Header doesn't match the format:"
in cm.records[0].message,
)
else:
self.assertEqual(parse_headers(s), dict(expected))
4 changes: 2 additions & 2 deletions opentelemetry-sdk/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ where = src
[options.entry_points]
opentelemetry_tracer_provider =
sdk_tracer_provider = opentelemetry.sdk.trace:TracerProvider
opentelemetry_exporter =
console_span = opentelemetry.sdk.trace.export:ConsoleSpanExporter
opentelemetry_traces_exporter =
console = opentelemetry.sdk.trace.export:ConsoleSpanExporter
opentelemetry_id_generator =
random = opentelemetry.sdk.trace.id_generator:RandomIdGenerator
opentelemetry_environment_variables =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def _import_exporters(
exporter_name,
exporter_impl,
) in _import_tracer_provider_config_components(
exporter_names, "opentelemetry_exporter"
exporter_names, "opentelemetry_traces_exporter"
):
if issubclass(exporter_impl, SpanExporter):
trace_exporters[exporter_name] = exporter_impl
Expand Down

0 comments on commit 94e4f8e

Please sign in to comment.