Skip to content

[EXPORTER] Add custom HTTP client#4071

Open
ltowarek wants to merge 10 commits into
open-telemetry:mainfrom
ltowarek:fix/issue-24-custom-http-client
Open

[EXPORTER] Add custom HTTP client#4071
ltowarek wants to merge 10 commits into
open-telemetry:mainfrom
ltowarek:fix/issue-24-custom-http-client

Conversation

@ltowarek
Copy link
Copy Markdown

@ltowarek ltowarek commented May 8, 2026

Fixes #2084

Changes

Adds a way to provide a custom HTTP client instead of the default libcurl-based client.

The main motivation are embedded and cross-compiled targets where libcurl is unavailable. A working example for ESP32S3 using ESP-IDF's esp_http_client as the transport backend is at ltowarek/esp-opentelemetry-cpp#30.

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented May 8, 2026

CLA Signed

The committers listed above are authorized under a signed CLA.

@ltowarek ltowarek marked this pull request as ready for review May 8, 2026 21:40
@ltowarek ltowarek requested a review from a team as a code owner May 8, 2026 21:40
@owent
Copy link
Copy Markdown
Member

owent commented May 11, 2026

Could you please add a test to use a simple custom http client?

@lalitb
Copy link
Copy Markdown
Member

lalitb commented May 11, 2026

Thanks @ltowarek. Couple of review comments as of now -

  1. As @owent mentioned, could we also add a minimal example for this option, even if the transport is just a no-op custom HttpClient / HttpClientSync? The important part is showing where the user provides HttpClientFactory::Create() and CreateSync(), and how their target is linked with the OTLP HTTP exporter.

  2. Also, I believe there are still a few CMake paths that bring in curl directly. For example, Zipkin, Elasticsearch, HTTP examples, and the W3C tracecontext HTTP test server still link opentelemetry_http_client_curl / CURL::libcurl, while WITH_CUSTOM_HTTP_CLIENT=ON disables the curl client target globally. Can we either make this option explicitly incompatible with those curl-only paths, or update them to follow the same custom-client path?

@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.01%. Comparing base (e0c6c33) to head (516c51b).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4071      +/-   ##
==========================================
+ Coverage   81.99%   82.01%   +0.02%     
==========================================
  Files         385      385              
  Lines       16023    16023              
==========================================
+ Hits        13137    13139       +2     
+ Misses       2886     2884       -2     

see 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member

@dbarker dbarker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Please see the question below.

Comment thread exporters/otlp/CMakeLists.txt Outdated
@ltowarek
Copy link
Copy Markdown
Author

Thanks for the feedback! I think I've covered everything in the new patch set:

  • Added opentelemetry_http_client interface library to easily inject different implementations.
  • Added tests based on http_client::nosend::HttpClient.
  • Added an example app.
  • Used WITH_HTTP_CLIENT_CURL=OFF instead of WITH_CUSTOM_HTTP_CLIENT.

Copy link
Copy Markdown
Member

@marcalff marcalff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution.

Please consider to use:

  • an abstract class HttpClientFactory, with virtual methods for Create and CreateSync
  • A child class HttpCurlClientFactory, which implement this for CURL
  • a HttpCurlClientFactory::singleton

Everywhere the static method HttpClientFactory::Create() is used today, pass a HttpClientFactory instance instead, taken as input parameter.

The user of an HTTP client can then decide which implementation to use:

  • pass HttpCurlClientFactory::singleton to use CURL
  • pass an instance of MyOwnHttpClientFactory for alternate implementations.

It should be possible to mix CURL and non CURL HTTP clients in the same binary, for example:

  • send traces using HTTP + CURL to endpoint A
  • send metrics using HTTP + alternate to endpoint B

@ltowarek ltowarek force-pushed the fix/issue-24-custom-http-client branch from 5147826 to 516c51b Compare May 13, 2026 21:38
@ltowarek
Copy link
Copy Markdown
Author

Thanks for the contribution.

Please consider to use:

* an abstract class `HttpClientFactory`, with virtual methods for `Create` and `CreateSync`

* A child class `HttpCurlClientFactory`, which implement this for CURL

* a HttpCurlClientFactory::singleton

Everywhere the static method HttpClientFactory::Create() is used today, pass a HttpClientFactory instance instead, taken as input parameter.

The user of an HTTP client can then decide which implementation to use:

* pass HttpCurlClientFactory::singleton to use CURL

* pass an instance of MyOwnHttpClientFactory for alternate implementations.

It should be possible to mix CURL and non CURL HTTP clients in the same binary, for example:

* send traces using HTTP + CURL to endpoint A

* send metrics using HTTP + alternate to endpoint B

@marcalff, it looks like a good idea.

My main goal with the current PR is build-time configuration - to enable opentelemetry-cpp for embedded systems as they simply can't build
libcurl. The binary for such systems will always contain only one HTTP client.

I think runtime changes should be a part of a separate PR which I'm open to working on.

Comment thread exporters/zipkin/CMakeLists.txt Outdated
@ltowarek ltowarek changed the title [EXPORTER] Add WITH_CUSTOM_HTTP_CLIENT option [EXPORTER] Add custom HTTP client May 14, 2026
@ltowarek ltowarek requested review from marcalff and owent May 14, 2026 18:17
@ltowarek
Copy link
Copy Markdown
Author

@marcalff I've added runtime changes to this PR. Please let me know if b8eb45d fits the needs.

@lalitb
Copy link
Copy Markdown
Member

lalitb commented May 15, 2026

Thanks for adding the runtime factory path. I think this is moving in the right direction, but can we make the injection story consistent across all HTTP exporters?

Right now OtlpHttpExporterFactory has overloads that accept a custom HttpClientFactory / HttpClient, but the OTLP HTTP log and metric exporter factories still only expose the default-client path. That means a user can inject a custom client for traces, but not for logs/metrics through the same public factory API.

Also, after making HttpClientFactory::Create*() virtual instance methods, there still seem to be a few static call sites left, for example the HTTP example and test_ext_http_curl.cc. Those should probably go through GetDefaultHttpClientFactory()->Create*() or a concrete curl factory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow adding custom HTTP client

5 participants