Skip to content

Commit 1eeafde

Browse files
committed
enable OTLP JSON exporter support
1 parent 2caf95e commit 1eeafde

17 files changed

Lines changed: 779 additions & 27 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
### Added
44

5+
- **✨ OTLP: HTTP/JSON export format support**
6+
- Added `OTLPJSONExporter` class for exporting spans in JSON format over HTTP
7+
- Added `otlp_protocol` configuration option to `OTLPConfig` (supports `"http/protobuf"` or `"http/json"`)
8+
- `HoneyHiveOTLPExporter` now supports protocol selection via `protocol` parameter
9+
- Protocol can be set via environment variable `HH_OTLP_PROTOCOL` or `OTEL_EXPORTER_OTLP_PROTOCOL`
10+
- JSON exporter sends spans with `Content-Type: application/json` header
11+
- All attribute values are serialized as strings to allow backend type conversion testing
12+
- Files: `src/honeyhive/tracer/processing/otlp_exporter.py`, `src/honeyhive/config/models/otlp.py`, `src/honeyhive/tracer/instrumentation/initialization.py`
13+
514
- **✨ Experiments: Instrumentors support for evaluate()**
615
- `honeyhive.experiments.evaluate()` and `run_experiment()` now accept an `instrumentors` parameter
716
- Pass factory functions (e.g., `[lambda: GoogleADKInstrumentor()]`) to automatically instrument third-party libraries

‎docs/how-to/integrations/non-instrumentor-frameworks.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ Environment Variables
109109
# Optional
110110
export HH_SOURCE="my-application"
111111
export HH_OTLP_ENABLED="true" # Enable OTLP export (default: true)
112+
export HH_OTLP_PROTOCOL="http/json" # Use JSON format (default: http/protobuf)
112113
113114
Code Configuration
114115
~~~~~~~~~~~~~~~~~~

‎docs/reference/api/config-models.rst‎

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,99 @@ ExperimentConfig
539539
experiment_metadata={"model": "gpt-4", "temperature": 0.7}
540540
)
541541
542+
OTLPConfig
543+
----------
544+
545+
.. autoclass:: OTLPConfig
546+
:members:
547+
:undoc-members:
548+
:show-inheritance:
549+
550+
**OTLP (OpenTelemetry Protocol) export configuration parameters.**
551+
552+
**OTLP Fields:**
553+
554+
.. py:attribute:: otlp_enabled
555+
:type: bool
556+
:value: True
557+
558+
Enable OTLP export.
559+
560+
**Environment Variable**: ``HH_OTLP_ENABLED``
561+
562+
.. py:attribute:: otlp_endpoint
563+
:type: Optional[str]
564+
:value: None
565+
566+
Custom OTLP endpoint URL.
567+
568+
**Environment Variable**: ``HH_OTLP_ENDPOINT``
569+
570+
.. py:attribute:: otlp_headers
571+
:type: Optional[Dict[str, Any]]
572+
:value: None
573+
574+
OTLP headers in JSON format.
575+
576+
**Environment Variable**: ``HH_OTLP_HEADERS`` (JSON string)
577+
578+
.. py:attribute:: otlp_protocol
579+
:type: str
580+
:value: "http/protobuf"
581+
582+
OTLP protocol format: ``"http/protobuf"`` (default) or ``"http/json"``.
583+
584+
**Environment Variables**: ``HH_OTLP_PROTOCOL`` or ``OTEL_EXPORTER_OTLP_PROTOCOL``
585+
586+
.. py:attribute:: batch_size
587+
:type: int
588+
:value: 100
589+
590+
OTLP batch size for performance optimization.
591+
592+
**Environment Variable**: ``HH_BATCH_SIZE``
593+
594+
.. py:attribute:: flush_interval
595+
:type: float
596+
:value: 5.0
597+
598+
OTLP flush interval in seconds.
599+
600+
**Environment Variable**: ``HH_FLUSH_INTERVAL``
601+
602+
.. py:attribute:: max_export_batch_size
603+
:type: int
604+
:value: 512
605+
606+
Maximum export batch size.
607+
608+
**Environment Variable**: ``HH_MAX_EXPORT_BATCH_SIZE``
609+
610+
.. py:attribute:: export_timeout
611+
:type: float
612+
:value: 30.0
613+
614+
Export timeout in seconds.
615+
616+
**Environment Variable**: ``HH_EXPORT_TIMEOUT``
617+
618+
**Example Usage:**
619+
620+
.. code-block:: python
621+
622+
from honeyhive.config.models import OTLPConfig
623+
624+
# Use JSON format for OTLP export
625+
otlp_config = OTLPConfig(
626+
otlp_protocol="http/json",
627+
batch_size=200,
628+
flush_interval=1.0
629+
)
630+
631+
# Or via environment variable
632+
# export HH_OTLP_PROTOCOL=http/json
633+
otlp_config = OTLPConfig() # Loads from HH_OTLP_PROTOCOL
634+
542635
Environment Variable Integration
543636
================================
544637

@@ -551,6 +644,7 @@ All configuration models support **automatic environment variable loading** usin
551644
- **Performance**: ``HH_TIMEOUT``, ``HH_MAX_CONNECTIONS``, ``HH_RATE_LIMIT_*``
552645
- **Caching**: ``HH_CACHE_ENABLED``, ``HH_CACHE_MAX_SIZE``, ``HH_CACHE_TTL``
553646
- **Experiments**: ``HH_EXPERIMENT_ID``, ``HH_EXPERIMENT_NAME``
647+
- **OTLP**: ``HH_OTLP_ENABLED``, ``HH_OTLP_ENDPOINT``, ``HH_OTLP_PROTOCOL``, ``HH_OTLP_HEADERS``, ``HH_BATCH_SIZE``, ``HH_FLUSH_INTERVAL``
554648

555649
**Priority Order:**
556650

‎docs/reference/api/tracer-architecture.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Processing Module (``tracer/processing/``)
174174
* - ``context.py``
175175
- Context injection and extraction
176176
* - ``otlp_exporter.py``
177-
- OTLP exporter configuration
177+
- OTLP exporter configuration (supports Protobuf and JSON formats)
178178
* - ``otlp_profiles.py``
179179
- OTLP export profiles
180180
* - ``otlp_session.py``

‎docs/reference/api/tracer-internals.rst‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@ Environment Profile
4141
:undoc-members:
4242
:show-inheritance:
4343

44+
OTLP Exporters
45+
~~~~~~~~~~~~~~~
46+
47+
.. autoclass:: honeyhive.tracer.processing.otlp_exporter.HoneyHiveOTLPExporter
48+
:members:
49+
:undoc-members:
50+
:show-inheritance:
51+
52+
.. autoclass:: honeyhive.tracer.processing.otlp_exporter.OTLPJSONExporter
53+
:members:
54+
:undoc-members:
55+
:show-inheritance:
56+
4457
Infrastructure
4558
--------------
4659

‎docs/reference/configuration/config-options.rst‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,57 @@ HTTP Configuration
405405

406406
**Range**: 1 - 100
407407

408+
OTLP Configuration
409+
~~~~~~~~~~~~~~~~~~
410+
411+
.. py:data:: otlp_enabled
412+
:type: bool
413+
:value: True
414+
415+
**Description**: Enable OTLP export to HoneyHive backend
416+
417+
**Environment Variable**: ``HH_OTLP_ENABLED``
418+
419+
**Default**: ``True``
420+
421+
**Usage**: Set to ``False`` to disable OTLP export (useful for testing)
422+
423+
.. py:data:: otlp_endpoint
424+
:type: Optional[str]
425+
:value: None
426+
427+
**Description**: Custom OTLP endpoint URL
428+
429+
**Environment Variable**: ``HH_OTLP_ENDPOINT``
430+
431+
**Default**: Auto-configured based on ``server_url``
432+
433+
**Example**: ``"https://custom.honeyhive.ai/opentelemetry/v1/traces"``
434+
435+
.. py:data:: otlp_protocol
436+
:type: str
437+
:value: "http/protobuf"
438+
439+
**Description**: OTLP protocol format for span export
440+
441+
**Environment Variables**: ``HH_OTLP_PROTOCOL`` or ``OTEL_EXPORTER_OTLP_PROTOCOL``
442+
443+
**Valid Values**:
444+
- ``"http/protobuf"`` (default) - Binary Protobuf format
445+
- ``"http/json"`` - JSON format for debugging and backend type conversion testing
446+
447+
**Example**: Set ``HH_OTLP_PROTOCOL=http/json`` to use JSON format
448+
449+
.. py:data:: otlp_headers
450+
:type: Optional[Dict[str, Any]]
451+
:value: None
452+
453+
**Description**: Additional HTTP headers for OTLP export requests
454+
455+
**Environment Variable**: ``HH_OTLP_HEADERS`` (JSON string)
456+
457+
**Example**: ``{"X-Custom-Header": "value"}``
458+
408459
Tracing Configuration
409460
~~~~~~~~~~~~~~~~~~~~~
410461

‎docs/reference/data-models/spans.rst‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,10 @@ Span Export Format
597597

598598
**OTLP Format** (OpenTelemetry Protocol):
599599

600+
The SDK supports both Protobuf (default) and JSON formats for OTLP export.
601+
Set the ``HH_OTLP_PROTOCOL`` environment variable to ``http/json`` to use JSON format,
602+
or ``http/protobuf`` (default) for Protobuf format.
603+
600604
.. code-block:: json
601605
602606
{

‎docs/reference/index.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Core Capabilities
6666
- **Graceful Degradation**: SDK never crashes host application, continues operation on failures
6767
- **Batch Processing**: Configurable span batching for optimal performance
6868
- **OTLP Performance Tuning**: Environment variables for batch size and flush interval optimization
69+
- **OTLP JSON Format**: Support for HTTP/JSON export format via ``HH_OTLP_PROTOCOL=http/json``
6970
- **Production Optimization**: ``HH_BATCH_SIZE`` and ``HH_FLUSH_INTERVAL`` for fine-tuned performance control
7071

7172
**Development & Quality**:
@@ -373,6 +374,7 @@ All configuration supports the ``HH_*`` prefix pattern:
373374
- **Authentication**: ``HH_API_KEY``, ``HH_SOURCE``
374375
- **Operational**: ``HH_TEST_MODE``, ``HH_DEBUG_MODE``, ``HH_DISABLE_TRACING``
375376
- **Performance**: ``HH_TIMEOUT``, ``HH_MAX_CONNECTIONS``, ``HH_RATE_LIMIT_*``, ``HH_BATCH_SIZE``, ``HH_FLUSH_INTERVAL``
377+
- **OTLP**: ``HH_OTLP_ENABLED``, ``HH_OTLP_ENDPOINT``, ``HH_OTLP_PROTOCOL``, ``HH_OTLP_HEADERS``
376378
- **Security**: ``HH_SSL_*``, ``HH_PROXY_*``
377379

378380
**Configuration Hierarchy**:

‎src/honeyhive/api/datapoints.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ def list_datapoints(
162162
163163
Args:
164164
project: Project name to filter by
165-
dataset: (Legacy) Dataset ID or name to filter by - use dataset_id or dataset_name instead
165+
dataset: (Legacy) Dataset ID or name to filter by - use dataset_id or
166+
dataset_name instead
166167
dataset_id: Dataset ID to filter by (takes precedence over dataset_name)
167168
dataset_name: Dataset name to filter by
168169
@@ -206,7 +207,8 @@ async def list_datapoints_async(
206207
207208
Args:
208209
project: Project name to filter by
209-
dataset: (Legacy) Dataset ID or name to filter by - use dataset_id or dataset_name instead
210+
dataset: (Legacy) Dataset ID or name to filter by - use dataset_id or
211+
dataset_name instead
210212
dataset_id: Dataset ID to filter by (takes precedence over dataset_name)
211213
dataset_name: Dataset name to filter by
212214

‎src/honeyhive/api/events.py‎

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ def list_events(
335335
Uses the proper /events/export POST endpoint as specified in OpenAPI spec.
336336
337337
Args:
338-
event_filters: EventFilter or list of EventFilter objects with filtering criteria
338+
event_filters: EventFilter or list of EventFilter objects with
339+
filtering criteria
339340
limit: Maximum number of events to return (default: 100)
340341
project: Project name to filter by (required by API)
341342
page: Page number for pagination (default: 1)
@@ -347,8 +348,18 @@ def list_events(
347348
Filter events by type and status::
348349
349350
filters = [
350-
EventFilter(field="event_type", operator="is", value="model", type="string"),
351-
EventFilter(field="error", operator="is not", value=None, type="string"),
351+
EventFilter(
352+
field="event_type",
353+
operator="is",
354+
value="model",
355+
type="string",
356+
),
357+
EventFilter(
358+
field="error",
359+
operator="is not",
360+
value=None,
361+
type="string",
362+
),
352363
]
353364
events = client.events.list_events(
354365
event_filters=filters,
@@ -471,7 +482,8 @@ async def list_events_async(
471482
Uses the proper /events/export POST endpoint as specified in OpenAPI spec.
472483
473484
Args:
474-
event_filters: EventFilter or list of EventFilter objects with filtering criteria
485+
event_filters: EventFilter or list of EventFilter objects with
486+
filtering criteria
475487
limit: Maximum number of events to return (default: 100)
476488
project: Project name to filter by (required by API)
477489
page: Page number for pagination (default: 1)
@@ -483,8 +495,18 @@ async def list_events_async(
483495
Filter events by type and status::
484496
485497
filters = [
486-
EventFilter(field="event_type", operator="is", value="model", type="string"),
487-
EventFilter(field="error", operator="is not", value=None, type="string"),
498+
EventFilter(
499+
field="event_type",
500+
operator="is",
501+
value="model",
502+
type="string",
503+
),
504+
EventFilter(
505+
field="error",
506+
operator="is not",
507+
value=None,
508+
type="string",
509+
),
488510
]
489511
events = await client.events.list_events_async(
490512
event_filters=filters,

0 commit comments

Comments
 (0)