Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions libdd-profiling-ffi/src/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,38 @@ unsafe fn parse_json(
}
}

/// Initializes the tokio runtime for the exporter.
///
/// This function creates the tokio runtime used by `ddog_prof_Exporter_send_blocking`.
/// It can be called ahead of time to ensure the runtime is ready before sending.
///
/// # Thread Affinity
///
/// **Important**: The runtime has thread affinity. This function should be called from
/// the same thread that will later call `ddog_prof_Exporter_send_blocking`.
///
/// # Arguments
/// * `exporter` - Borrows the exporter.
///
/// # Safety
/// The `exporter` must point to a valid ProfileExporter that has not been dropped.
#[no_mangle]
#[must_use]
#[named]
pub unsafe extern "C" fn ddog_prof_Exporter_init_runtime(
mut exporter: *mut Handle<ProfileExporter>,
) -> VoidResult {
wrap_with_void_ffi_result!({
let exporter = exporter.to_inner_mut()?;
exporter.init_runtime()?
})
}

/// Builds a request and sends it, returning the HttpStatus.
///
/// Note: If the runtime has not been initialized via `ddog_prof_Exporter_init_runtime`,
/// it will be lazily initialized on first call.
///
/// # Arguments
/// * `exporter` - Borrows the exporter.
/// * `profile` - Takes ownership of the profile.
Expand Down
28 changes: 21 additions & 7 deletions libdd-profiling/src/exporter/profile_exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,26 @@ impl ProfileExporter {
/// - Using the async [`send`] method directly from within a tokio runtime
///
/// [`send`]: ProfileExporter::send
/// Initializes the tokio runtime for blocking operations.
///
/// This method lazily creates a single-threaded tokio runtime. It can be called
/// before `send_blocking` to ensure the runtime is ready ahead of time.
///
/// # Thread Affinity
///
/// **Important**: The runtime uses `new_current_thread()`, which has thread affinity.
/// This method should be called from the same thread that will later call `send_blocking`.
pub fn init_runtime(&mut self) -> anyhow::Result<()> {
if self.runtime.is_none() {
self.runtime = Some(
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?,
);
}
Ok(())
}

#[allow(clippy::too_many_arguments)]
pub fn send_blocking(
&mut self,
Expand All @@ -163,13 +183,7 @@ impl ProfileExporter {
process_tags: Option<&str>,
cancel: Option<&CancellationToken>,
) -> anyhow::Result<reqwest::StatusCode> {
if self.runtime.is_none() {
self.runtime = Some(
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?,
);
}
self.init_runtime()?;

Ok(self
.runtime
Expand Down
Loading