@@ -290,9 +290,19 @@ class AsyncResponseHandler : public http_client::EventHandler
290290# endif
291291
292292ElasticsearchLogRecordExporter::ElasticsearchLogRecordExporter ()
293- : options_{ElasticsearchExporterOptions ()},
294- http_client_{ext::http::client::HttpClientFactory::Create ()}
295- {}
293+ : options_{ElasticsearchExporterOptions ()}, http_client_
294+ {
295+ ext::http::client::HttpClientFactory::Create ()
296+ }
297+ # ifdef ENABLE_ASYNC_EXPORT
298+ , synchronization_data_(new SynchronizationData())
299+ # endif
300+ {
301+ # ifdef ENABLE_ASYNC_EXPORT
302+ synchronization_data_->finished_session_counter_ .store (0 );
303+ synchronization_data_->session_counter_ .store (0 );
304+ # endif
305+ }
296306
297307ElasticsearchLogRecordExporter::ElasticsearchLogRecordExporter (
298308 const ElasticsearchExporterOptions &options)
@@ -343,10 +353,12 @@ sdk::common::ExportResult ElasticsearchLogRecordExporter::Export(
343353
344354# ifdef ENABLE_ASYNC_EXPORT
345355 // Send the request
346- std::size_t span_count = records.size ();
347- auto handler = std::make_shared<AsyncResponseHandler>(
356+ synchronization_data_->session_counter_ .fetch_add (1 , std::memory_order_release);
357+ std::size_t span_count = records.size ();
358+ auto synchronization_data = synchronization_data_;
359+ auto handler = std::make_shared<AsyncResponseHandler>(
348360 session,
349- [span_count](opentelemetry::sdk::common::ExportResult result) {
361+ [span_count, synchronization_data ](opentelemetry::sdk::common::ExportResult result) {
350362 if (result != opentelemetry::sdk::common::ExportResult::kSuccess )
351363 {
352364 OTEL_INTERNAL_LOG_ERROR (" [ES Log Exporter] ERROR: Export "
@@ -358,6 +370,9 @@ sdk::common::ExportResult ElasticsearchLogRecordExporter::Export(
358370 OTEL_INTERNAL_LOG_DEBUG (" [ES Log Exporter] Export " << span_count
359371 << " trace span(s) success" );
360372 }
373+
374+ synchronization_data->finished_session_counter_ .fetch_add (1 , std::memory_order_release);
375+ synchronization_data->force_flush_cv .notify_all ();
361376 return true ;
362377 },
363378 options_.console_debug_ );
@@ -401,6 +416,49 @@ sdk::common::ExportResult ElasticsearchLogRecordExporter::Export(
401416# endif
402417}
403418
419+ bool ElasticsearchLogRecordExporter::ForceFlush (std::chrono::microseconds timeout) noexcept
420+ {
421+ # ifdef ENABLE_ASYNC_EXPORT
422+ std::lock_guard<std::recursive_mutex> lock_guard{synchronization_data_->force_flush_m };
423+ std::size_t running_counter =
424+ synchronization_data_->session_counter_ .load (std::memory_order_acquire);
425+ // ASAN will report chrono: runtime error: signed integer overflow: A + B cannot be represented
426+ // in type 'long int' here. So we reset timeout to meet signed long int limit here.
427+ timeout = opentelemetry::common::DurationUtil::AdjustWaitForTimeout (
428+ timeout, std::chrono::microseconds::zero ());
429+
430+ std::chrono::steady_clock::duration timeout_steady =
431+ std::chrono::duration_cast<std::chrono::steady_clock::duration>(timeout);
432+ if (timeout_steady <= std::chrono::steady_clock::duration::zero ())
433+ {
434+ timeout_steady = std::chrono::steady_clock::duration::max ();
435+ }
436+
437+ std::unique_lock<std::mutex> lk_cv (synchronization_data_->force_flush_cv_m );
438+ // Wait for all the sessions to finish
439+ while (timeout_steady > std::chrono::steady_clock::duration::zero ())
440+ {
441+ if (synchronization_data_->finished_session_counter_ .load (std::memory_order_acquire) >=
442+ running_counter)
443+ {
444+ break ;
445+ }
446+
447+ std::chrono::steady_clock::time_point start_timepoint = std::chrono::steady_clock::now ();
448+ if (std::cv_status::no_timeout != synchronization_data_->force_flush_cv .wait_for (
449+ lk_cv, std::chrono::seconds{options_.response_timeout_ }))
450+ {
451+ break ;
452+ }
453+ timeout_steady -= std::chrono::steady_clock::now () - start_timepoint;
454+ }
455+
456+ return timeout_steady > std::chrono::steady_clock::duration::zero ();
457+ # else
458+ return true ;
459+ # endif
460+ }
461+
404462bool ElasticsearchLogRecordExporter::Shutdown (std::chrono::microseconds /* timeout */ ) noexcept
405463{
406464 const std::lock_guard<opentelemetry::common::SpinLockMutex> locked (lock_);
0 commit comments