Skip to content

Commit c07829c

Browse files
temp(profiling): split upload function
1 parent 9aa79d2 commit c07829c

2 files changed

Lines changed: 55 additions & 8 deletions

File tree

libdd-profiling-ffi/src/exporter.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
use function_name::named;
88
use libdd_common::tag::Tag;
99
use libdd_common_ffi::slice::{AsBytes, ByteSlice, CharSlice, Slice};
10-
use libdd_common_ffi::{wrap_with_ffi_result, Handle, Result, ToInner};
10+
use libdd_common_ffi::{
11+
wrap_with_ffi_result, wrap_with_void_ffi_result, Handle, Result, ToInner, VoidResult,
12+
};
1113
use libdd_profiling::exporter;
1214
use libdd_profiling::exporter::ProfileExporter;
1315
use libdd_profiling::internal::EncodedProfile;
@@ -210,11 +212,41 @@ unsafe fn parse_json(
210212
}
211213
}
212214

215+
/// Initializes the tokio runtime for the exporter.
216+
///
217+
/// This function creates the tokio runtime used by `ddog_prof_Exporter_send_blocking`.
218+
/// It can be called ahead of time to ensure the runtime is ready before sending.
219+
///
220+
/// # Thread Affinity
221+
///
222+
/// **Important**: The runtime has thread affinity. This function should be called from
223+
/// the same thread that will later call `ddog_prof_Exporter_send_blocking`.
224+
///
225+
/// # Arguments
226+
/// * `exporter` - Borrows the exporter.
227+
///
228+
/// # Safety
229+
/// The `exporter` must point to a valid ProfileExporter that has not been dropped.
230+
#[no_mangle]
231+
#[must_use]
232+
#[named]
233+
pub unsafe extern "C" fn ddog_prof_Exporter_init_runtime(
234+
mut exporter: *mut Handle<ProfileExporter>,
235+
) -> VoidResult {
236+
wrap_with_void_ffi_result!({
237+
let exporter = exporter.to_inner_mut()?;
238+
exporter.init_runtime()?
239+
})
240+
}
241+
213242
/// Builds a request and sends it, returning the HttpStatus.
214243
/// This is a more efficient version of calling `ddog_prof_Exporter_Request_build`
215244
/// followed by `ddog_prof_Exporter_send`, as it avoids exposing the intermediate
216245
/// `Request` object.
217246
///
247+
/// Note: If the runtime has not been initialized via `ddog_prof_Exporter_init_runtime`,
248+
/// it will be lazily initialized on first call.
249+
///
218250
/// # Arguments
219251
/// * `exporter` - Borrows the exporter.
220252
/// * `profile` - Takes ownership of the profile.

libdd-profiling/src/exporter/profile_exporter.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,27 @@ impl ProfileExporter {
217217
/// - Using the async [`send`] method directly from within a tokio runtime
218218
///
219219
/// [`send`]: ProfileExporter::send
220+
221+
/// Initializes the tokio runtime for blocking operations.
222+
///
223+
/// This method lazily creates a single-threaded tokio runtime. It can be called
224+
/// before `send_blocking` to ensure the runtime is ready ahead of time.
225+
///
226+
/// # Thread Affinity
227+
///
228+
/// **Important**: The runtime uses `new_current_thread()`, which has thread affinity.
229+
/// This method should be called from the same thread that will later call `send_blocking`.
230+
pub fn init_runtime(&mut self) -> anyhow::Result<()> {
231+
if self.runtime.is_none() {
232+
self.runtime = Some(
233+
tokio::runtime::Builder::new_current_thread()
234+
.enable_all()
235+
.build()?,
236+
);
237+
}
238+
Ok(())
239+
}
240+
220241
#[allow(clippy::too_many_arguments)]
221242
pub fn send_blocking(
222243
&mut self,
@@ -228,13 +249,7 @@ impl ProfileExporter {
228249
process_tags: Option<&str>,
229250
cancel: Option<&CancellationToken>,
230251
) -> anyhow::Result<reqwest::StatusCode> {
231-
if self.runtime.is_none() {
232-
self.runtime = Some(
233-
tokio::runtime::Builder::new_current_thread()
234-
.enable_all()
235-
.build()?,
236-
);
237-
}
252+
self.init_runtime()?;
238253

239254
self.runtime
240255
.as_ref()

0 commit comments

Comments
 (0)