Skip to content

Commit 49d50fa

Browse files
committed
feat: upload compression config
1 parent 3634bc9 commit 49d50fa

File tree

7 files changed

+139
-37
lines changed

7 files changed

+139
-37
lines changed

datadog-profiling-ffi/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ mod exporter;
1414
mod profiles;
1515
mod string_storage;
1616

17+
pub use profiles::*;
18+
1719
// re-export crashtracker ffi
1820
#[cfg(feature = "crashtracker-ffi")]
1921
pub use datadog_crashtracker_ffi::*;

datadog-profiling-ffi/src/profiles/datatypes.rs

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ impl From<anyhow::Result<()>> for ProfileResult {
7070
}
7171
}
7272

73+
impl From<ProfileResult> for Result<(), Error> {
74+
fn from(result: ProfileResult) -> Self {
75+
match result {
76+
ProfileResult::Ok(_) => Ok(()),
77+
ProfileResult::Err(err) => Err(err),
78+
}
79+
}
80+
}
81+
7382
/// Returned by [ddog_prof_Profile_new].
7483
#[allow(dead_code)]
7584
#[repr(C)]
@@ -79,6 +88,15 @@ pub enum ProfileNewResult {
7988
Err(Error),
8089
}
8190

91+
impl From<ProfileNewResult> for Result<Profile, Error> {
92+
fn from(value: ProfileNewResult) -> Self {
93+
match value {
94+
ProfileNewResult::Ok(v) => Ok(v),
95+
ProfileNewResult::Err(e) => Err(e),
96+
}
97+
}
98+
}
99+
82100
#[allow(dead_code)]
83101
#[repr(C)]
84102
pub enum SerializeResult {
@@ -390,7 +408,7 @@ impl<'a> From<Sample<'a>> for api::StringIdSample<'a> {
390408
/// time.
391409
///
392410
/// # Safety
393-
/// All slices must be have pointers that are suitably aligned for their type
411+
/// All slices must have pointers that are suitably aligned for their type
394412
/// and must have the correct number of elements for the slice.
395413
#[no_mangle]
396414
#[must_use]
@@ -401,7 +419,11 @@ pub unsafe extern "C" fn ddog_prof_Profile_new(
401419
profile_new(sample_types, period, None)
402420
}
403421

404-
/// Same as `ddog_profile_new` but also configures a `string_storage` for the profile.
422+
/// Same as [ddog_prof_Profile_new] but also configures a `string_storage` for
423+
/// the profile.
424+
///
425+
/// # Safety
426+
/// Has all same safety conditions as [ddog_prof_Profile_new].
405427
#[no_mangle]
406428
#[must_use]
407429
/// TODO: @ivoanjo Should this take a `*mut ManagedStringStorage` like Profile APIs do?
@@ -447,26 +469,6 @@ pub unsafe extern "C" fn ddog_prof_Profile_drop(profile: *mut Profile) {
447469
}
448470
}
449471

450-
#[cfg(test)]
451-
impl From<ProfileResult> for Result<(), Error> {
452-
fn from(result: ProfileResult) -> Self {
453-
match result {
454-
ProfileResult::Ok(_) => Ok(()),
455-
ProfileResult::Err(err) => Err(err),
456-
}
457-
}
458-
}
459-
460-
#[cfg(test)]
461-
impl From<ProfileNewResult> for Result<Profile, Error> {
462-
fn from(result: ProfileNewResult) -> Self {
463-
match result {
464-
ProfileNewResult::Ok(p) => Ok(p),
465-
ProfileNewResult::Err(err) => Err(err),
466-
}
467-
}
468-
}
469-
470472
/// # Safety
471473
/// The `profile` ptr must point to a valid Profile object created by this
472474
/// module. All pointers inside the `sample` need to be valid for the duration
@@ -547,6 +549,58 @@ pub unsafe extern "C" fn ddog_prof_Profile_set_endpoint(
547549
.into()
548550
}
549551

552+
/// Sets the profile's upload compression algorithm. Useful only for testing.
553+
///
554+
/// # Errors
555+
///
556+
/// Returns an error if either the pointer or the inner profiler ptr is null.
557+
///
558+
/// # Safety
559+
///
560+
/// The `profile` ptr must point to a valid Profile object.
561+
///
562+
/// # Examples
563+
///
564+
/// ```
565+
/// # use datadog_profiling_ffi::{Error, ddog_prof_Profile_set_upload_compression, ddog_prof_Profile_new, ValueType, Slice, CharSlice};
566+
/// # use std::ptr::addr_of_mut;
567+
/// # fn main() -> Result<(), Error> { unsafe {
568+
/// use datadog_profiling::UploadCompression;
569+
///
570+
/// let mut profile = Result::from(ddog_prof_Profile_new(
571+
/// Slice::from([ValueType {
572+
/// type_: CharSlice::from("sample"),
573+
/// unit: CharSlice::from("count"),
574+
/// }].as_slice()),
575+
/// None,
576+
/// ))?;
577+
///
578+
/// // Set compression off (only for testing).
579+
/// Result::from(ddog_prof_Profile_set_upload_compression(
580+
/// addr_of_mut!(profile),
581+
/// UploadCompression::Off
582+
/// ))?;
583+
/// # } Ok(()) }
584+
/// ```
585+
#[no_mangle]
586+
#[must_use]
587+
#[named]
588+
pub unsafe extern "C" fn ddog_prof_Profile_set_upload_compression(
589+
profile: *mut Profile,
590+
upload_compression: datadog_profiling::UploadCompression,
591+
) -> ProfileResult {
592+
match profile_ptr_to_inner(profile) {
593+
Ok(profile) => {
594+
profile.set_upload_compression(upload_compression);
595+
ProfileResult::Ok(true)
596+
}
597+
Err(err) => {
598+
let e = err.context(concat!(function_name!(), " failed"));
599+
ProfileResult::Err(e.into())
600+
}
601+
}
602+
}
603+
550604
/// Count the number of times an endpoint has been seen.
551605
///
552606
/// # Arguments
@@ -759,6 +813,14 @@ pub unsafe extern "C" fn ddog_prof_Profile_serialize(
759813
.into()
760814
}
761815

816+
/// Borrows FFI Vec as an FFI Slice.
817+
///
818+
/// # Safety
819+
/// The input needs to be a valid reference to an FFI Vec, and the slice needs
820+
/// to be used in a way consistent with the lifetime and safety rules. Some
821+
/// things to avoid:
822+
/// - Do not modify the Vec at all while the Slice is alive.
823+
/// - Do not drop the Vec while the Slice is alive.
762824
#[must_use]
763825
#[no_mangle]
764826
pub unsafe extern "C" fn ddog_Vec_U8_as_slice(vec: &ddcommon_ffi::Vec<u8>) -> Slice<u8> {

datadog-profiling-ffi/src/profiles/interning_api.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -407,14 +407,9 @@ pub unsafe extern "C" fn ddog_prof_Profile_get_generation(
407407
}
408408

409409
/// This functions returns whether the given generations are equal.
410-
///
411-
/// # Safety: No safety requirements
412410
#[must_use]
413411
#[no_mangle]
414-
pub unsafe extern "C" fn ddog_prof_Profile_generations_are_equal(
415-
a: Generation,
416-
b: Generation,
417-
) -> bool {
412+
pub extern "C" fn ddog_prof_Profile_generations_are_equal(a: Generation, b: Generation) -> bool {
418413
a == b
419414
}
420415

datadog-profiling-ffi/src/profiles/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33

44
mod datatypes;
55
mod interning_api;
6+
7+
pub use datatypes::*;
8+
pub use interning_api::*;

datadog-profiling/src/internal/profile/mod.rs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,16 @@ mod fuzz_tests;
66

77
pub mod interning_api;
88

9-
use self::api::UpscalingInfo;
109
use super::*;
11-
use crate::api;
12-
use crate::api::ManagedStringId;
10+
use crate::api::{self, ManagedStringId, UpscalingInfo};
1311
use crate::collections::identifiable::*;
1412
use crate::collections::string_storage::{CachedProfileId, ManagedStringStorage};
1513
use crate::collections::string_table::StringTable;
1614
use crate::iter::{IntoLendingIterator, LendingIterator};
15+
use crate::UploadCompression;
1716
use anyhow::Context;
1817
use datadog_profiling_protobuf::{self as protobuf, Field, NO_OPT_ZERO, OPT_ZERO};
1918
use interning_api::Generation;
20-
use lz4_flex::frame::FrameEncoder;
2119
use std::borrow::Cow;
2220
use std::collections::HashMap;
2321
use std::io;
@@ -51,6 +49,7 @@ pub struct Profile {
5149
string_storage: Option<Arc<Mutex<ManagedStringStorage>>>,
5250
string_storage_cached_profile_id: Option<CachedProfileId>,
5351
timestamp_key: StringId,
52+
upload_compression: UploadCompression,
5453
upscaling_rules: UpscalingRules,
5554
}
5655

@@ -313,6 +312,13 @@ impl Profile {
313312
Ok(profile)
314313
}
315314

315+
/// Sets the upload compression algorithm. The default level is
316+
/// [UploadCompression::On]. The exact algorithm that on uses may change
317+
/// over time.
318+
pub fn set_upload_compression(&mut self, compression: UploadCompression) {
319+
self.upload_compression = compression;
320+
}
321+
316322
/// Serialize the aggregated profile, adding the end time and duration.
317323
/// # Arguments
318324
/// * `end_time` - Optional end time of the profile. Passing None will use the current time.
@@ -336,11 +342,25 @@ impl Profile {
336342
// size of 32KiB should definitely outperform starting at zero for
337343
// time consumed, allocator pressure, and allocator fragmentation.
338344
const INITIAL_PPROF_BUFFER_SIZE: usize = 32 * 1024;
339-
let mut compressor = FrameEncoder::new(Vec::with_capacity(INITIAL_PPROF_BUFFER_SIZE));
340-
341-
let mut encoded_profile = self.encode(&mut compressor, end_time, duration)?;
342-
encoded_profile.buffer = compressor.finish()?;
343-
Ok(encoded_profile)
345+
let mut buffer = Vec::with_capacity(INITIAL_PPROF_BUFFER_SIZE);
346+
347+
Ok(match self.upload_compression {
348+
UploadCompression::Off => {
349+
let encoded_profile = self.encode(&mut buffer, end_time, duration)?;
350+
EncodedProfile {
351+
buffer,
352+
..encoded_profile
353+
}
354+
}
355+
UploadCompression::On | UploadCompression::Lz4 => {
356+
let mut compressor = lz4_flex::frame::FrameEncoder::new(buffer);
357+
let encoded_profile = self.encode(&mut compressor, end_time, duration)?;
358+
EncodedProfile {
359+
buffer: compressor.finish()?,
360+
..encoded_profile
361+
}
362+
}
363+
})
344364
}
345365

346366
/// Encodes the profile. Note that the buffer will be empty. The caller
@@ -735,6 +755,7 @@ impl Profile {
735755
string_storage_cached_profile_id: None, /* Never reuse an id! See comments on
736756
* CachedProfileId for why. */
737757
timestamp_key: Default::default(),
758+
upload_compression: Default::default(),
738759
upscaling_rules: Default::default(),
739760
};
740761

datadog-profiling/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,13 @@ pub mod exporter;
1212
pub mod internal;
1313
pub mod iter;
1414
pub mod pprof;
15+
16+
#[repr(C)]
17+
#[derive(Copy, Clone, Debug, Default)]
18+
pub enum UploadCompression {
19+
Off,
20+
/// On is the default. The compression algorithm used can change over time.
21+
#[default]
22+
On,
23+
Lz4,
24+
}

ddcommon-ffi/src/result.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ pub enum Result<T> {
4646
Err(Error),
4747
}
4848

49+
impl From<VoidResult> for std::result::Result<(), Error> {
50+
fn from(result: VoidResult) -> Self {
51+
match result {
52+
VoidResult::Ok(_) => Ok(()),
53+
VoidResult::Err(err) => Err(err),
54+
}
55+
}
56+
}
57+
4958
impl<T> Result<T> {
5059
pub fn unwrap(self) -> T {
5160
match self {

0 commit comments

Comments
 (0)