@@ -110,8 +110,8 @@ class ResponseHandler : public http_client::EventHandler
110110
111111 /* *
112112 * A method the user calls to block their thread until the request has either produced a
113- * response or failed. The longest duration is the timeout of the request, set by
114- * SetTimeoutMs(), which arrives here as a TimedOut session event .
113+ * response or failed. It has no deadline of its own and relies on the HTTP client reporting
114+ * one of the terminal session states .
115115 */
116116 bool waitForResponse ()
117117 {
@@ -135,12 +135,18 @@ class ResponseHandler : public http_client::EventHandler
135135 // Callback method when an http event occurs
136136 void OnEvent (http_client::SessionState state, nostd::string_view /* reason */ ) noexcept override
137137 {
138- // If any failure event occurs, release the condition variable to unblock main thread
138+ // If any failure event occurs, release the condition variable to unblock main thread.
139+ //
140+ // A failure is reported only by the event that decided the outcome. Recording is first writer
141+ // wins, so any of these can arrive after a response has already succeeded, and an error line
142+ // there would describe a failure the caller was never told about.
139143 switch (state)
140144 {
141145 case http_client::SessionState::CreateFailed:
142- OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed to create session" );
143- recordCompletion (CompletionState::Failure);
146+ if (recordCompletion (CompletionState::Failure))
147+ {
148+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed to create session" );
149+ }
144150 break ;
145151 case http_client::SessionState::Created:
146152 OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Session created" );
@@ -155,8 +161,10 @@ class ResponseHandler : public http_client::EventHandler
155161 OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Connecting to peer" );
156162 break ;
157163 case http_client::SessionState::ConnectFailed:
158- OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed to connect to peer" );
159- recordCompletion (CompletionState::Failure);
164+ if (recordCompletion (CompletionState::Failure))
165+ {
166+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed to connect to peer" );
167+ }
160168 break ;
161169 case http_client::SessionState::Connected:
162170 OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Connected to peer" );
@@ -165,33 +173,49 @@ class ResponseHandler : public http_client::EventHandler
165173 OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Sending request" );
166174 break ;
167175 case http_client::SessionState::SendFailed:
168- OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed to send request" );
169- recordCompletion (CompletionState::Failure);
176+ if (recordCompletion (CompletionState::Failure))
177+ {
178+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed to send request" );
179+ }
170180 break ;
171181 case http_client::SessionState::Response:
172182 OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Received response" );
173183 break ;
174184 case http_client::SessionState::SSLHandshakeFailed:
175- OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed SSL Handshake" );
176- recordCompletion (CompletionState::Failure);
185+ if (recordCompletion (CompletionState::Failure))
186+ {
187+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Failed SSL Handshake" );
188+ }
177189 break ;
178190 case http_client::SessionState::TimedOut:
179- OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Request timed out" );
180- recordCompletion (CompletionState::Failure);
191+ if (recordCompletion (CompletionState::Failure))
192+ {
193+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Request timed out" );
194+ }
181195 break ;
182196 case http_client::SessionState::NetworkError:
183- OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Network error" );
184- recordCompletion (CompletionState::Failure);
197+ if (recordCompletion (CompletionState::Failure))
198+ {
199+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Network error" );
200+ }
185201 break ;
186202 case http_client::SessionState::ReadError:
187- OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Read error" );
203+ if (recordCompletion (CompletionState::Failure))
204+ {
205+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Read error" );
206+ }
188207 break ;
189208 case http_client::SessionState::WriteError:
190- OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Write error" );
209+ if (recordCompletion (CompletionState::Failure))
210+ {
211+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] Write error" );
212+ }
191213 break ;
192214 case http_client::SessionState::Cancelled:
193- OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] (manually) cancelled" );
194- recordCompletion (CompletionState::Failure);
215+ if (recordCompletion (CompletionState::Failure))
216+ {
217+ OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] (manually) cancelled" );
218+ }
195219 break ;
196220 }
197221 }
@@ -208,22 +232,27 @@ class ResponseHandler : public http_client::EventHandler
208232 * Record the outcome of the request, first writer wins, then release any waiter. Keeping the
209233 * first outcome means a session destroyed after a successful response does not overwrite it.
210234 */
211- void recordCompletion (CompletionState state)
235+ // / Returns whether this call is the one that decided the outcome.
236+ bool recordCompletion (CompletionState state)
212237 {
238+ bool recorded = false ;
213239 {
214240 std::unique_lock<std::mutex> lk (mutex_);
215- recordCompletionLocked (state);
241+ recorded = recordCompletionLocked (state);
216242 }
217243 cv_.notify_all ();
244+ return recorded;
218245 }
219246
220247 // / As recordCompletion(), for callers that already hold mutex_ and notify themselves.
221- void recordCompletionLocked (CompletionState state)
248+ bool recordCompletionLocked (CompletionState state)
222249 {
223- if (completion_ = = CompletionState::Pending)
250+ if (completion_ ! = CompletionState::Pending)
224251 {
225- completion_ = state ;
252+ return false ;
226253 }
254+ completion_ = state;
255+ return true ;
227256 }
228257
229258 // Define a condition variable and mutex
0 commit comments