diff --git a/libdd-profiling-ffi/src/profiles/datatypes.rs b/libdd-profiling-ffi/src/profiles/datatypes.rs index c7ec589d5c..0436db2a1b 100644 --- a/libdd-profiling-ffi/src/profiles/datatypes.rs +++ b/libdd-profiling-ffi/src/profiles/datatypes.rs @@ -101,6 +101,24 @@ impl From> for SerializeResult { /// Re-exported from libdd_profiling::api for FFI use. pub use api::SampleType; +/// Returns the pprof type string for a `SampleType` (e.g. `"cpu-time"`). +/// The returned slice points to a static string; it is always valid and +/// never needs to be freed. +#[no_mangle] +pub extern "C" fn ddog_prof_SampleType_type_str(sample_type: SampleType) -> CharSlice<'static> { + let vt: api::ValueType = sample_type.into(); + CharSlice::from(vt.r#type) +} + +/// Returns the pprof unit string for a `SampleType` (e.g. `"nanoseconds"`). +/// The returned slice points to a static string; it is always valid and +/// never needs to be freed. +#[no_mangle] +pub extern "C" fn ddog_prof_SampleType_unit_str(sample_type: SampleType) -> CharSlice<'static> { + let vt: api::ValueType = sample_type.into(); + CharSlice::from(vt.unit) +} + /// Re-export Period from the API for consistency. /// The FFI Period is identical to the API Period. pub use api::Period; @@ -1094,4 +1112,36 @@ mod tests { ddog_prof_Profile_drop(&mut provide_distinct_locations_ffi()); } } + + #[test] + fn sample_type_str_functions() { + // Verify that the type/unit strings match expected pprof column names. + // These strings are what the backend uses to identify profile types, so + // any change here would be a breaking change for consumers. + let cases: &[(SampleType, &str, &str)] = &[ + (SampleType::CpuTime, "cpu-time", "nanoseconds"), + (SampleType::CpuSamples, "cpu-samples", "count"), + (SampleType::AllocSpace, "alloc-space", "bytes"), + (SampleType::AllocSamples, "alloc-samples", "count"), + (SampleType::InuseSpace, "inuse-space", "bytes"), + (SampleType::InuseObjects, "inuse-objects", "count"), + (SampleType::Tracepoint, "tracepoint", "events"), + (SampleType::WallTime, "wall-time", "nanoseconds"), + (SampleType::WallSamples, "wall-samples", "count"), + ]; + for &(sample_type, expected_type, expected_unit) in cases { + let type_str = ddog_prof_SampleType_type_str(sample_type); + let unit_str = ddog_prof_SampleType_unit_str(sample_type); + assert_eq!( + type_str.try_to_utf8().unwrap(), + expected_type, + "type string mismatch for {sample_type:?}" + ); + assert_eq!( + unit_str.try_to_utf8().unwrap(), + expected_unit, + "unit string mismatch for {sample_type:?}" + ); + } + } } diff --git a/libdd-profiling/src/api/sample_type.rs b/libdd-profiling/src/api/sample_type.rs index 1554fb46ca..4e1156b4bb 100644 --- a/libdd-profiling/src/api/sample_type.rs +++ b/libdd-profiling/src/api/sample_type.rs @@ -58,6 +58,7 @@ pub enum SampleType { ObjectsLegacy, RequestTime, Sample, + Tracepoint, SocketReadSize, SocketReadSizeSamples, SocketReadTime, @@ -137,6 +138,7 @@ impl From for ValueType<'static> { SampleType::ObjectsLegacy => ValueType::new("objects", "count"), SampleType::RequestTime => ValueType::new("request-time", "nanoseconds"), SampleType::Sample => ValueType::new("sample", "count"), + SampleType::Tracepoint => ValueType::new("tracepoint", "events"), SampleType::SocketReadSize => ValueType::new("socket-read-size", "bytes"), SampleType::SocketReadSizeSamples => { ValueType::new("socket-read-size-samples", "count") @@ -210,6 +212,7 @@ impl<'a> TryFrom> for SampleType { ("objects", "count") => SampleType::ObjectsLegacy, ("request-time", "nanoseconds") => SampleType::RequestTime, ("sample", "count") => SampleType::Sample, + ("tracepoint", "events") => SampleType::Tracepoint, ("socket-read-size", "bytes") => SampleType::SocketReadSize, ("socket-read-size-samples", "count") => SampleType::SocketReadSizeSamples, ("socket-read-time", "nanoseconds") => SampleType::SocketReadTime, diff --git a/libdd-profiling/src/cxx.rs b/libdd-profiling/src/cxx.rs index 7895ab4535..312b1c636d 100644 --- a/libdd-profiling/src/cxx.rs +++ b/libdd-profiling/src/cxx.rs @@ -75,6 +75,7 @@ pub mod ffi { ObjectsLegacy, // LEGACY: Use InuseObjects instead RequestTime, Sample, + Tracepoint, SocketReadSize, SocketReadSizeSamples, SocketReadTime, @@ -376,6 +377,7 @@ impl TryFrom for api::SampleType { ffi::SampleType::ObjectsLegacy => api::SampleType::ObjectsLegacy, ffi::SampleType::RequestTime => api::SampleType::RequestTime, ffi::SampleType::Sample => api::SampleType::Sample, + ffi::SampleType::Tracepoint => api::SampleType::Tracepoint, ffi::SampleType::SocketReadSize => api::SampleType::SocketReadSize, ffi::SampleType::SocketReadSizeSamples => api::SampleType::SocketReadSizeSamples, ffi::SampleType::SocketReadTime => api::SampleType::SocketReadTime,