Skip to content

Commit 021e4e8

Browse files
committed
feat: upload compression config
1 parent 68be8ec commit 021e4e8

File tree

6 files changed

+125
-30
lines changed

6 files changed

+125
-30
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: 71 additions & 21 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]
@@ -447,26 +465,6 @@ pub unsafe extern "C" fn ddog_prof_Profile_drop(profile: *mut Profile) {
447465
}
448466
}
449467

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-
470468
/// # Safety
471469
/// The `profile` ptr must point to a valid Profile object created by this
472470
/// module. All pointers inside the `sample` need to be valid for the duration
@@ -547,6 +545,58 @@ pub unsafe extern "C" fn ddog_prof_Profile_set_endpoint(
547545
.into()
548546
}
549547

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

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, Value, Varint};
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
@@ -730,6 +750,7 @@ impl Profile {
730750
string_storage_cached_profile_id: None, /* Never reuse an id! See comments on
731751
* CachedProfileId for why. */
732752
timestamp_key: Default::default(),
753+
upload_compression: Default::default(),
733754
upscaling_rules: Default::default(),
734755
};
735756

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)