Repository navigation
Description
Describe your environment
main at d64b2512, macOS 26.6.2, Apple clang, CMake Debug build with WITH_ELASTICSEARCH=ON, libcurl 8.7.1. The curl client is the only HTTP client in tree.
Steps to reproduce
Point the Elasticsearch log exporter at a socket that accepts the connection and never answers, with a 1 second response timeout.
ElasticsearchExporterOptions options("127.0.0.1", port, "logs", /*response_timeout=*/1);
ElasticsearchLogRecordExporter exporter(options);
auto record = exporter.MakeRecordable();
record->SetBody("probe");
exporter.Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1));s = socket.socket(); s.bind(("127.0.0.1", port)); s.listen(8)
while True: c, _ = s.accept() # accept, read nothing, answer nothingWhat is the expected behavior?
SetTimeoutMs() expires, the session reports SessionState::TimedOut, and the exporter logs [ES Log Exporter] Request timed out from the handler at es_log_record_exporter.cc:178. The doc comment at :114 states this directly: the longest wait is "the timeout of the request, set by SetTimeoutMs(), which arrives here as a TimedOut session event".
What is the actual behavior?
SendFailed, every time. Two runs:
log + 0.4ms [ES Log Exporter] Sending request
log + 1006.4ms [ES Log Exporter] Failed to send request
export 0 result=FAILURE elapsed=1006.4ms
log + 1002.9ms [ES Log Exporter] Failed to send request
export 1 result=FAILURE elapsed=1003.0ms
The timeout is honoured, so this is a classification problem rather than a hang.
Additional context
SessionState::TimedOut is declared at ext/include/opentelemetry/ext/http/client/http_client.h:93 and is never dispatched anywhere under ext/. HttpOperation::PerformCurlMessage (http_operation_curl.cc:1564-1594) maps every non-CURLE_OK code to ConnectFailed when the state is Connecting and to SendFailed when it is Connected or Sending, so CURLE_OPERATION_TIMEDOUT is indistinguishable from a refused connection or a dropped socket.
Four handler branches wait for an event that cannot arrive: es_log_record_exporter.cc:178 and :320, otlp_http_client.cc:200 and :303. A caller cannot currently tell a timeout from a transport failure, which matters because the two usually deserve different retry behaviour.
Two ways out, and I do not want to guess which you prefer. Dispatch TimedOut for CURLE_OPERATION_TIMEDOUT in PerformCurlMessage, which makes the four branches live and could change behaviour for anyone switching on SendFailed today. Or drop the enum value with its four branches and correct the comment at :114. Happy to send a PR either way.
Activity
om7057 commentedon Sep 28, 2026
I went ahead. Opened #4647 taking the drop-the-enum direction, since it doesn't change behavior for anyone already handling a timeout via
SendFailed. Open to rework it to thedispatch-TimedOutdirection instead if you'd rather have that, or if you'd already started on this let me know!mateenali66 commentedon Sep 28, 2026
I hadn't started, so no clash.
[HTTP CLIENT] Remove dead SessionState::TimedOut
Scope down to just the doc comment fix per review feedback