Skip to content

Commit e8b26b9

Browse files
refactor(profiling): split upload function
1 parent 29b010a commit e8b26b9

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

libdd-profiling-ffi/src/exporter.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,38 @@ unsafe fn parse_json(
222222
}
223223
}
224224

225+
/// Initializes the tokio runtime for the exporter.
226+
///
227+
/// This function creates the tokio runtime used by `ddog_prof_Exporter_send_blocking`.
228+
/// It can be called ahead of time to ensure the runtime is ready before sending.
229+
///
230+
/// # Thread Affinity
231+
///
232+
/// **Important**: The runtime has thread affinity. This function should be called from
233+
/// the same thread that will later call `ddog_prof_Exporter_send_blocking`.
234+
///
235+
/// # Arguments
236+
/// * `exporter` - Borrows the exporter.
237+
///
238+
/// # Safety
239+
/// The `exporter` must point to a valid ProfileExporter that has not been dropped.
240+
#[no_mangle]
241+
#[must_use]
242+
#[named]
243+
pub unsafe extern "C" fn ddog_prof_Exporter_init_runtime(
244+
mut exporter: *mut Handle<ProfileExporter>,
245+
) -> VoidResult {
246+
wrap_with_void_ffi_result!({
247+
let exporter = exporter.to_inner_mut()?;
248+
exporter.init_runtime()?
249+
})
250+
}
251+
225252
/// Builds a request and sends it, returning the HttpStatus.
226253
///
254+
/// Note: If the runtime has not been initialized via `ddog_prof_Exporter_init_runtime`,
255+
/// it will be lazily initialized on first call.
256+
///
227257
/// # Arguments
228258
/// * `exporter` - Borrows the exporter.
229259
/// * `profile` - Takes ownership of the profile.

libdd-profiling/src/exporter/profile_exporter.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,26 @@ impl ProfileExporter {
152152
/// - Using the async [`send`] method directly from within a tokio runtime
153153
///
154154
/// [`send`]: ProfileExporter::send
155+
/// Initializes the tokio runtime for blocking operations.
156+
///
157+
/// This method lazily creates a single-threaded tokio runtime. It can be called
158+
/// before `send_blocking` to ensure the runtime is ready ahead of time.
159+
///
160+
/// # Thread Affinity
161+
///
162+
/// **Important**: The runtime uses `new_current_thread()`, which has thread affinity.
163+
/// This method should be called from the same thread that will later call `send_blocking`.
164+
pub fn init_runtime(&mut self) -> anyhow::Result<()> {
165+
if self.runtime.is_none() {
166+
self.runtime = Some(
167+
tokio::runtime::Builder::new_current_thread()
168+
.enable_all()
169+
.build()?,
170+
);
171+
}
172+
Ok(())
173+
}
174+
155175
#[allow(clippy::too_many_arguments)]
156176
pub fn send_blocking(
157177
&mut self,
@@ -163,13 +183,7 @@ impl ProfileExporter {
163183
process_tags: Option<&str>,
164184
cancel: Option<&CancellationToken>,
165185
) -> anyhow::Result<reqwest::StatusCode> {
166-
if self.runtime.is_none() {
167-
self.runtime = Some(
168-
tokio::runtime::Builder::new_current_thread()
169-
.enable_all()
170-
.build()?,
171-
);
172-
}
186+
self.init_runtime()?;
173187

174188
Ok(self
175189
.runtime

0 commit comments

Comments
 (0)