Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
- Adds environment variables for log exporter
([#3037](https://github.com/open-telemetry/opentelemetry-python/pull/3037))

## Version 1.15.0/0.36b0 (2022-12-09)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [
"grpcio >= 1.0.0, < 2.0.0",
"opentelemetry-api ~= 1.12",
"opentelemetry-proto == 1.16.0.dev",
"opentelemetry-sdk ~= 1.12",
"opentelemetry-sdk ~= 1.16.0.dev",
]

[project.optional-dependencies]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from os import environ
from typing import Optional, Sequence
from grpc import ChannelCredentials, Compression
from opentelemetry.exporter.otlp.proto.grpc.exporter import (
OTLPExporterMixin,
get_resource_data,
_get_credentials,
_translate_value,
environ_to_compression,
)
from opentelemetry.proto.collector.logs.v1.logs_service_pb2 import (
ExportLogsServiceRequest,
Expand All @@ -34,6 +37,15 @@
from opentelemetry.sdk._logs import LogData
from opentelemetry.sdk._logs.export import LogExporter, LogExportResult

from opentelemetry.sdk.environment_variables import (
OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE,
OTEL_EXPORTER_OTLP_LOGS_COMPRESSION,
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
OTEL_EXPORTER_OTLP_LOGS_HEADERS,
OTEL_EXPORTER_OTLP_LOGS_INSECURE,
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
)


class OTLPLogExporter(
LogExporter,
Expand All @@ -52,13 +64,40 @@ def __init__(
timeout: Optional[int] = None,
compression: Optional[Compression] = None,
):
if insecure is None:
insecure = environ.get(OTEL_EXPORTER_OTLP_LOGS_INSECURE)
if insecure is not None:
insecure = insecure.lower() == "true"

if (
not insecure
and environ.get(OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE) is not None
):
credentials = _get_credentials(
credentials, OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE
)

environ_timeout = environ.get(OTEL_EXPORTER_OTLP_LOGS_TIMEOUT)
environ_timeout = (
int(environ_timeout) if environ_timeout is not None else None
)

compression = (
environ_to_compression(OTEL_EXPORTER_OTLP_LOGS_COMPRESSION)
if compression is None
else compression
)
endpoint = endpoint or environ.get(OTEL_EXPORTER_OTLP_LOGS_ENDPOINT)

headers = headers or environ.get(OTEL_EXPORTER_OTLP_LOGS_HEADERS)

super().__init__(
**{
"endpoint": endpoint,
"insecure": insecure,
"credentials": credentials,
"headers": headers,
"timeout": timeout,
"timeout": timeout or environ_timeout,
"compression": compression,
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@

import time
from concurrent.futures import ThreadPoolExecutor
from os.path import dirname
from unittest import TestCase
from unittest.mock import patch

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

from opentelemetry._logs import SeverityNumber
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
Expand Down Expand Up @@ -47,10 +48,19 @@
)
from opentelemetry.sdk._logs import LogData, LogRecord
from opentelemetry.sdk._logs.export import LogExportResult
from opentelemetry.sdk.environment_variables import (
OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE,
OTEL_EXPORTER_OTLP_LOGS_COMPRESSION,
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
OTEL_EXPORTER_OTLP_LOGS_HEADERS,
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
)
from opentelemetry.sdk.resources import Resource as SDKResource
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
from opentelemetry.trace import TraceFlags

THIS_DIR = dirname(__file__)


class LogsServiceServicerUNAVAILABLEDelay(LogsServiceServicer):
# pylint: disable=invalid-name,unused-argument,no-self-use
Expand Down Expand Up @@ -100,7 +110,6 @@ def Export(self, request, context):

class TestOTLPLogExporter(TestCase):
def setUp(self):

self.exporter = OTLPLogExporter()

self.server = server(ThreadPoolExecutor(max_workers=10))
Expand Down Expand Up @@ -164,6 +173,32 @@ def test_exporting(self):
# pylint: disable=protected-access
self.assertEqual(self.exporter._exporting, "logs")

@patch.dict(
"os.environ",
{
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: "logs:4317",
OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE: THIS_DIR
+ "/../fixtures/test.cert",
OTEL_EXPORTER_OTLP_LOGS_HEADERS: " key1=value1,KEY2 = VALUE=2",
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT: "10",
OTEL_EXPORTER_OTLP_LOGS_COMPRESSION: "gzip",
},
)
@patch(
"opentelemetry.exporter.otlp.proto.grpc.exporter.OTLPExporterMixin.__init__"
)
def test_env_variables(self, mock_exporter_mixin):
OTLPLogExporter()

self.assertTrue(len(mock_exporter_mixin.call_args_list) == 1)
_, kwargs = mock_exporter_mixin.call_args_list[0]
self.assertEqual(kwargs["endpoint"], "logs:4317")
self.assertEqual(kwargs["headers"], " key1=value1,KEY2 = VALUE=2")
self.assertEqual(kwargs["timeout"], 10)
self.assertEqual(kwargs["compression"], Compression.Gzip)
self.assertIsNotNone(kwargs["credentials"])
self.assertIsInstance(kwargs["credentials"], ChannelCredentials)

@patch(
"opentelemetry.exporter.otlp.proto.grpc.exporter.ssl_channel_credentials"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies = [
"googleapis-common-protos ~= 1.52",
"opentelemetry-api ~= 1.12",
"opentelemetry-proto == 1.16.0.dev",
"opentelemetry-sdk ~= 1.12",
"opentelemetry-sdk ~= 1.16.0.dev",
"requests ~= 2.7",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
OTEL_EXPORTER_OTLP_ENDPOINT,
OTEL_EXPORTER_OTLP_HEADERS,
OTEL_EXPORTER_OTLP_TIMEOUT,
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE,
OTEL_EXPORTER_OTLP_LOGS_HEADERS,
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
OTEL_EXPORTER_OTLP_LOGS_COMPRESSION,
)
from opentelemetry.sdk._logs import LogData
from opentelemetry.sdk._logs.export import (
Expand Down Expand Up @@ -79,16 +84,26 @@ def __init__(
compression: Optional[Compression] = None,
session: Optional[requests.Session] = None,
):
self._endpoint = endpoint or _append_logs_path(
environ.get(OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_ENDPOINT)
self._endpoint = endpoint or environ.get(
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
_append_logs_path(
environ.get(OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_ENDPOINT)
),
)
self._certificate_file = certificate_file or environ.get(
OTEL_EXPORTER_OTLP_CERTIFICATE, True
OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE,
environ.get(OTEL_EXPORTER_OTLP_CERTIFICATE, True),
)
headers_string = environ.get(
OTEL_EXPORTER_OTLP_LOGS_HEADERS,
environ.get(OTEL_EXPORTER_OTLP_HEADERS, ""),
)
headers_string = environ.get(OTEL_EXPORTER_OTLP_HEADERS, "")
self._headers = headers or parse_env_headers(headers_string)
self._timeout = timeout or int(
environ.get(OTEL_EXPORTER_OTLP_TIMEOUT, DEFAULT_TIMEOUT)
environ.get(
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
environ.get(OTEL_EXPORTER_OTLP_TIMEOUT, DEFAULT_TIMEOUT),
)
)
self._compression = compression or _compression_from_env()
self._session = session or requests.Session()
Expand Down Expand Up @@ -170,7 +185,12 @@ def shutdown(self):

def _compression_from_env() -> Compression:
compression = (
environ.get(OTEL_EXPORTER_OTLP_COMPRESSION, "none").lower().strip()
environ.get(
OTEL_EXPORTER_OTLP_LOGS_COMPRESSION,
environ.get(OTEL_EXPORTER_OTLP_COMPRESSION, "none"),
)
.lower()
.strip()
)
return Compression(compression)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
OTEL_EXPORTER_OTLP_COMPRESSION,
OTEL_EXPORTER_OTLP_ENDPOINT,
OTEL_EXPORTER_OTLP_HEADERS,
OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE,
OTEL_EXPORTER_OTLP_LOGS_COMPRESSION,
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
OTEL_EXPORTER_OTLP_LOGS_HEADERS,
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
OTEL_EXPORTER_OTLP_TIMEOUT,
)
from opentelemetry.sdk.resources import Resource as SDKResource
Expand Down Expand Up @@ -92,6 +97,38 @@ def test_constructor_default(self):
"application/x-protobuf",
)

@patch.dict(
"os.environ",
{
OTEL_EXPORTER_OTLP_CERTIFICATE: ENV_CERTIFICATE,
OTEL_EXPORTER_OTLP_COMPRESSION: Compression.Gzip.value,
OTEL_EXPORTER_OTLP_ENDPOINT: ENV_ENDPOINT,
OTEL_EXPORTER_OTLP_HEADERS: ENV_HEADERS,
OTEL_EXPORTER_OTLP_TIMEOUT: ENV_TIMEOUT,
OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE: "logs/certificate.env",
OTEL_EXPORTER_OTLP_LOGS_COMPRESSION: Compression.Deflate.value,
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: "https://logs.endpoint.env",
OTEL_EXPORTER_OTLP_LOGS_HEADERS: "logsEnv1=val1,logsEnv2=val2,logsEnv3===val3==",
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT: "40",
},
)
def test_exporter_metrics_env_take_priority(self):
exporter = OTLPLogExporter()

self.assertEqual(exporter._endpoint, "https://logs.endpoint.env")
self.assertEqual(exporter._certificate_file, "logs/certificate.env")
self.assertEqual(exporter._timeout, 40)
self.assertIs(exporter._compression, Compression.Deflate)
self.assertEqual(
exporter._headers,
{
"logsenv1": "val1",
"logsenv2": "val2",
"logsenv3": "==val3==",
},
)
self.assertIsInstance(exporter._session, requests.Session)

@patch.dict(
"os.environ",
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,15 @@
A scheme of https indicates a secure connection and takes precedence over this configuration setting.
"""

OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"
"""
.. envvar:: OTEL_EXPORTER_OTLP_LOGS_ENDPOINT

The :envvar:`OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` target to which the log exporter is going to send logs.
The endpoint MUST be a valid URL host, and MAY contain a scheme (http or https), port and path.
A scheme of https indicates a secure connection and takes precedence over this configuration setting.
"""

OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = "OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE"
"""
.. envvar:: OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE
Expand Down Expand Up @@ -378,6 +387,14 @@
associated with gRPC or HTTP requests.
"""

OTEL_EXPORTER_OTLP_LOGS_HEADERS = "OTEL_EXPORTER_OTLP_LOGS_HEADERS"
"""
.. envvar:: OTEL_EXPORTER_OTLP_LOGS_HEADERS

The :envvar:`OTEL_EXPORTER_OTLP_LOGS_HEADERS` contains the key-value pairs to be used as headers for logs
associated with gRPC or HTTP requests.
"""

OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION"
"""
.. envvar:: OTEL_EXPORTER_OTLP_TRACES_COMPRESSION
Expand All @@ -396,6 +413,14 @@
exporter. If both are present, this takes higher precedence.
"""

OTEL_EXPORTER_OTLP_LOGS_COMPRESSION = "OTEL_EXPORTER_OTLP_LOGS_COMPRESSION"
"""
.. envvar:: OTEL_EXPORTER_OTLP_LOGS_COMPRESSION

Same as :envvar:`OTEL_EXPORTER_OTLP_COMPRESSION` but only for the log
exporter. If both are present, this takes higher precedence.
"""

OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT"
"""
.. envvar:: OTEL_EXPORTER_OTLP_TRACES_TIMEOUT
Expand All @@ -421,6 +446,15 @@
Default: False
"""

OTEL_EXPORTER_OTLP_LOGS_INSECURE = "OTEL_EXPORTER_OTLP_LOGS_INSECURE"
"""
.. envvar:: OTEL_EXPORTER_OTLP_LOGS_INSECURE

The :envvar:`OTEL_EXPORTER_OTLP_LOGS_INSECURE` represents whether to enable client transport security
for gRPC requests for metrics. A scheme of https takes precedence over the this configuration setting.
Default: False
"""

OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"
"""
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
Expand All @@ -440,6 +474,14 @@
TLS credentials of gRPC client for traces. Should only be used for a secure connection for tracing.
"""

OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE = "OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE"
"""
.. envvar:: OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE

The :envvar:`OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE` stores the path to the certificate file for
TLS credentials of gRPC client for traces. Should only be used for a secure connection for tracing.
"""

OTEL_EXPORTER_OTLP_METRICS_HEADERS = "OTEL_EXPORTER_OTLP_METRICS_HEADERS"
"""
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_HEADERS
Expand All @@ -456,6 +498,14 @@
wait for each batch export for metrics.
"""

OTEL_EXPORTER_OTLP_LOGS_TIMEOUT = "OTEL_EXPORTER_OTLP_LOGS_TIMEOUT"
"""
.. envvar:: OTEL_EXPORTER_OTLP_LOGS_TIMEOUT

The :envvar:`OTEL_EXPORTER_OTLP_LOGS_TIMEOUT` is the maximum time the OTLP exporter will
wait for each batch export for logs.
"""

OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = (
"OTEL_EXPORTER_OTLP_METRICS_COMPRESSION"
)
Expand Down