Skip to content
Draft
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
1 change: 1 addition & 0 deletions eachdist.ini
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ packages=
opentelemetry-opentracing-shim
opentelemetry-opencensus-shim
opentelemetry-exporter-opencensus
opentelemetry-exporter-otlp-proto-http-light
opentelemetry-exporter-prometheus
opentelemetry-distro
opentelemetry-proto-json
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
OpenTelemetry OTLP Protobuf HTTP Exporter (Light)
=================================================

This package provides OTLP/HTTP exporters for traces, metrics, and logs using
only Python stdlib for HTTP transport (``http.client``), with no dependency on
``requests``.

It is a drop-in alternative to ``opentelemetry-exporter-otlp-proto-http`` for
environments where minimizing the dependency footprint or import-time memory
overhead is a priority.

Differences from the standard package
--------------------------------------

- **No ``requests`` dependency.** HTTP is handled by stdlib ``http.client``
with persistent keep-alive connections managed internally.

- **No custom session support.** The standard package accepts a
``requests.Session`` parameter and supports the
``OTEL_PYTHON_EXPORTER_OTLP_HTTP_*_CREDENTIAL_PROVIDER`` environment
variables, which load a credential-provider plugin that returns a
pre-configured ``requests.Session`` (e.g. for GCP auth). Neither the session
parameter nor the credential-provider env vars are supported by this package.
Use the standard package if you need pluggable session-level authentication.

- **Import path differs.** Use ``opentelemetry.exporter.otlp.proto.http_light``
instead of ``opentelemetry.exporter.otlp.proto.http``.

- **Entry-point keys differ.** Auto-configuration uses ``otlp_proto_http_light``
instead of ``otlp_proto_http``.

Installation
------------

.. code-block:: sh

pip install opentelemetry-exporter-otlp-proto-http-light

Usage
-----

.. code-block:: python

from opentelemetry.exporter.otlp.proto.http_light.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.http_light._log_exporter import OTLPLogExporter
from opentelemetry.exporter.otlp.proto.http_light.metric_exporter import OTLPMetricExporter
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest-benchmark==4.0.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# 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.

# pylint: disable=invalid-name

from unittest.mock import patch

from opentelemetry.exporter.otlp.proto.http_light._common import (
_OTLPHTTPResponse,
)
from opentelemetry.exporter.otlp.proto.http_light.trace_exporter import (
OTLPSpanExporter,
)
from opentelemetry.sdk.trace import TracerProvider, sampling
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
SimpleSpanProcessor,
)

_MOCK_RESPONSE = _OTLPHTTPResponse(200, "OK")


def get_tracer_with_processor(span_processor_class):
span_processor = span_processor_class(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer = TracerProvider(
active_span_processor=span_processor,
sampler=sampling.DEFAULT_ON,
).get_tracer("pipeline_benchmark_tracer")
return tracer


@patch(
"opentelemetry.exporter.otlp.proto.http_light._common._OTLPHTTPClient.post",
return_value=_MOCK_RESPONSE,
)
def test_simple_span_processor(mock_post, benchmark):
tracer = get_tracer_with_processor(SimpleSpanProcessor)

def create_spans_to_be_exported():
span = tracer.start_span("benchmarkedSpan")
for i in range(10):
span.set_attribute(
f"benchmarkAttribute_{i}",
f"benchmarkAttrValue_{i}",
)
span.end()

benchmark(create_spans_to_be_exported)


@patch(
"opentelemetry.exporter.otlp.proto.http_light._common._OTLPHTTPClient.post",
return_value=_MOCK_RESPONSE,
)
def test_batch_span_processor(mock_post, benchmark):
"""Runs benchmark tests using BatchSpanProcessor.

One particular call by pytest-benchmark will be much more expensive since
the batch export thread will activate and consume a lot of CPU to process
all the spans. For this reason, focus on the average measurement. Do not
focus on the min/max measurements which will be misleading.
"""
tracer = get_tracer_with_processor(BatchSpanProcessor)

def create_spans_to_be_exported():
span = tracer.start_span("benchmarkedSpan")
for i in range(10):
span.set_attribute(
f"benchmarkAttribute_{i}",
f"benchmarkAttrValue_{i}",
)
span.end()

benchmark(create_spans_to_be_exported)
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "opentelemetry-exporter-otlp-proto-http-light"
dynamic = ["version"]
description = "OpenTelemetry Collector Protobuf over HTTP Exporter (stdlib-only, no requests dependency)"
readme = "README.rst"
license = "Apache-2.0"
requires-python = ">=3.10"
authors = [
{ name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" },
]
classifiers = [
"Development Status :: 4 - Beta",
"Framework :: OpenTelemetry",
"Framework :: OpenTelemetry :: Exporters",
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
dependencies = [
"googleapis-common-protos ~= 1.52",
"opentelemetry-api ~= 1.15",
"opentelemetry-proto == 1.42.0.dev",
"opentelemetry-sdk ~= 1.42.0.dev",
"opentelemetry-exporter-otlp-proto-common == 1.42.0.dev",
"typing-extensions >= 4.5.0",
]

[project.entry-points.opentelemetry_traces_exporter]
otlp_proto_http_light = "opentelemetry.exporter.otlp.proto.http_light.trace_exporter:OTLPSpanExporter"

[project.entry-points.opentelemetry_metrics_exporter]
otlp_proto_http_light = "opentelemetry.exporter.otlp.proto.http_light.metric_exporter:OTLPMetricExporter"

[project.entry-points.opentelemetry_logs_exporter]
otlp_proto_http_light = "opentelemetry.exporter.otlp.proto.http_light._log_exporter:OTLPLogExporter"

[project.urls]
Homepage = "https://github.com/open-telemetry/opentelemetry-python/tree/main/exporter/opentelemetry-exporter-otlp-proto-http-light"
Repository = "https://github.com/open-telemetry/opentelemetry-python"

[tool.hatch.version]
path = "src/opentelemetry/exporter/otlp/proto/http_light/version/__init__.py"

[tool.hatch.build.targets.sdist]
include = [
"/src",
"/tests",
]

[tool.hatch.build.targets.wheel]
packages = ["src/opentelemetry"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# 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 enum
from os import environ

from opentelemetry.sdk.environment_variables import (
OTEL_EXPORTER_OTLP_COMPRESSION,
)

from .version import __version__

_OTLP_HTTP_HEADERS = {
"Content-Type": "application/x-protobuf",
"User-Agent": "OTel-OTLP-Light-Exporter-Python/" + __version__,
}


class Compression(enum.Enum):
NoCompression = "none"
Deflate = "deflate"
Gzip = "gzip"


DEFAULT_COMPRESSION = Compression.NoCompression


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