Skip to content

Commit 31cd819

Browse files
committed
[profiling] Refactor: use the new FFI macros and types
1 parent d111f32 commit 31cd819

File tree

10 files changed

+459
-559
lines changed

10 files changed

+459
-559
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ddcommon-ffi/src/handle.rs

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ pub struct Handle<T> {
1212
}
1313

1414
pub trait ToInner<T> {
15+
/// # Safety
16+
/// The Handle must hold a valid `inner` which has been allocated and not freed.
17+
unsafe fn to_inner(&self) -> anyhow::Result<&T>;
1518
/// # Safety
1619
/// The Handle must hold a valid `inner` which has been allocated and not freed.
1720
unsafe fn to_inner_mut(&mut self) -> anyhow::Result<&mut T>;
@@ -21,6 +24,10 @@ pub trait ToInner<T> {
2124
}
2225

2326
impl<T> ToInner<T> for *mut Handle<T> {
27+
unsafe fn to_inner(&self) -> anyhow::Result<&T> {
28+
self.as_ref().context("Null pointer")?.to_inner()
29+
}
30+
2431
unsafe fn to_inner_mut(&mut self) -> anyhow::Result<&mut T> {
2532
self.as_mut().context("Null pointer")?.to_inner_mut()
2633
}
@@ -31,6 +38,12 @@ impl<T> ToInner<T> for *mut Handle<T> {
3138
}
3239

3340
impl<T> ToInner<T> for Handle<T> {
41+
unsafe fn to_inner(&self) -> anyhow::Result<&T> {
42+
self.inner
43+
.as_ref()
44+
.context("inner pointer was null, indicates use after free")
45+
}
46+
3447
unsafe fn to_inner_mut(&mut self) -> anyhow::Result<&mut T> {
3548
self.inner
3649
.as_mut()

ddcommon-ffi/src/result.rs

+18
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ impl From<anyhow::Result<()>> for VoidResult {
2424
}
2525
}
2626

27+
impl From<VoidResult> for anyhow::Result<()> {
28+
fn from(value: VoidResult) -> Self {
29+
match value {
30+
VoidResult::Ok(_) => Self::Ok(()),
31+
VoidResult::Err(err) => Self::Err(err.into()),
32+
}
33+
}
34+
}
35+
2736
/// A generic result type for when an operation may fail,
2837
/// or may return <T> in case of success.
2938
#[repr(C)]
@@ -49,3 +58,12 @@ impl<T> From<anyhow::Result<T>> for Result<T> {
4958
}
5059
}
5160
}
61+
62+
impl<T> From<Result<T>> for anyhow::Result<T> {
63+
fn from(value: Result<T>) -> Self {
64+
match value {
65+
Result::Ok(v) => Self::Ok(v),
66+
Result::Err(err) => Self::Err(err.into()),
67+
}
68+
}
69+
}

examples/ffi/exporter.cpp

+55-38
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,50 @@
88
#include <thread>
99

1010
static ddog_CharSlice to_slice_c_char(const char *s) { return {.ptr = s, .len = strlen(s)}; }
11-
12-
struct Deleter {
13-
void operator()(ddog_prof_Profile *object) { ddog_prof_Profile_drop(object); }
14-
};
11+
static ddog_CharSlice to_slice_c_char(const char *s, std::size_t size) {
12+
return {.ptr = s, .len = size};
13+
}
14+
static ddog_CharSlice to_slice_string(std::string const &s) {
15+
return {.ptr = s.data(), .len = s.length()};
16+
}
1517

1618
void print_error(const char *s, const ddog_Error &err) {
1719
auto charslice = ddog_Error_message(&err);
1820
printf("%s (%.*s)\n", s, static_cast<int>(charslice.len), charslice.ptr);
1921
}
2022

23+
#define CHECK_RESULT(typ, ok_tag) \
24+
void check_result(typ result, const char *msg) { \
25+
if (result.tag != ok_tag) { \
26+
print_error(msg, result.err); \
27+
ddog_Error_drop(&result.err); \
28+
exit(EXIT_FAILURE); \
29+
} \
30+
}
31+
32+
CHECK_RESULT(ddog_VoidResult, DDOG_VOID_RESULT_OK)
33+
34+
#define EXTRACT_RESULT(typ, ok_tag) \
35+
struct typ##Deleter { \
36+
void operator()(ddog_prof_Handle_##typ *object) { \
37+
ddog_prof_##typ##_drop(object); \
38+
delete object; \
39+
} \
40+
}; \
41+
std::unique_ptr<ddog_prof_Handle_##typ, typ##Deleter> extract_result( \
42+
ddog_prof_Result_Handle##typ result, const char *msg) { \
43+
if (result.tag != ok_tag) { \
44+
print_error(msg, result.err); \
45+
ddog_Error_drop(&result.err); \
46+
exit(EXIT_FAILURE); \
47+
} \
48+
std::unique_ptr<ddog_prof_Handle_##typ, typ##Deleter> rval{ \
49+
new ddog_prof_Handle_##typ{result.ok}}; \
50+
return rval; \
51+
}
52+
53+
EXTRACT_RESULT(Profile, DDOG_PROF_RESULT_HANDLE_PROFILE_OK_HANDLE_PROFILE)
54+
2155
int main(int argc, char *argv[]) {
2256
if (argc != 2) {
2357
printf("Usage: exporter SERVICE_NAME\n");
@@ -38,14 +72,8 @@ int main(int argc, char *argv[]) {
3872

3973
const ddog_prof_Slice_ValueType sample_types = {&wall_time, 1};
4074
const ddog_prof_Period period = {wall_time, 60};
41-
ddog_prof_Profile_NewResult profile_new_result =
42-
ddog_prof_Profile_new(sample_types, &period, nullptr);
43-
if (profile_new_result.tag != DDOG_PROF_PROFILE_NEW_RESULT_OK) {
44-
print_error("Failed to make new profile: ", profile_new_result.err);
45-
ddog_Error_drop(&profile_new_result.err);
46-
exit(EXIT_FAILURE);
47-
}
48-
std::unique_ptr<ddog_prof_Profile, Deleter> profile{&profile_new_result.ok};
75+
auto profile =
76+
extract_result(ddog_prof_Profile_new(sample_types, &period, nullptr), "Can't get profile");
4977

5078
ddog_prof_Location root_location = {
5179
// yes, a zero-initialized mapping is valid
@@ -67,30 +95,18 @@ int main(int argc, char *argv[]) {
6795
.values = {&value, 1},
6896
.labels = {&label, 1},
6997
};
70-
auto add_result = ddog_prof_Profile_add(profile.get(), sample, 0);
71-
if (add_result.tag != DDOG_PROF_PROFILE_RESULT_OK) {
72-
print_error("Failed to add sample to profile: ", add_result.err);
73-
ddog_Error_drop(&add_result.err);
74-
return 1;
75-
}
98+
check_result(ddog_prof_Profile_add(profile.get(), sample, 0), "failed to add");
7699

77100
uintptr_t offset[1] = {0};
78101
ddog_prof_Slice_Usize offsets_slice = {.ptr = offset, .len = 1};
79102
ddog_CharSlice empty_charslice = DDOG_CHARSLICE_C_BARE("");
80103

81-
auto upscaling_addresult = ddog_prof_Profile_add_upscaling_rule_proportional(
82-
profile.get(), offsets_slice, empty_charslice, empty_charslice, 1, 1);
104+
check_result(ddog_prof_Profile_add_upscaling_rule_proportional(
105+
profile.get(), offsets_slice, empty_charslice, empty_charslice, 1, 1),
106+
"failed to add upscaling rule");
83107

84-
if (upscaling_addresult.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
85-
print_error("Failed to add an upscaling rule: ", upscaling_addresult.err);
86-
ddog_Error_drop(&upscaling_addresult.err);
87-
// in this specific case, we want to fail the execution. But in general, we should not
88-
return 1;
89-
}
90-
91-
ddog_prof_Profile_SerializeResult serialize_result =
92-
ddog_prof_Profile_serialize(profile.get(), nullptr, nullptr, nullptr);
93-
if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
108+
auto serialize_result = ddog_prof_Profile_serialize(profile.get(), nullptr, nullptr, nullptr);
109+
if (serialize_result.tag != DDOG_PROF_RESULT_ENCODED_PROFILE_OK_ENCODED_PROFILE) {
94110
print_error("Failed to serialize profile: ", serialize_result.err);
95111
ddog_Error_drop(&serialize_result.err);
96112
return 1;
@@ -110,9 +126,9 @@ int main(int argc, char *argv[]) {
110126
return 1;
111127
}
112128

113-
ddog_prof_Exporter_NewResult exporter_new_result =
114-
ddog_prof_Exporter_new(DDOG_CHARSLICE_C_BARE("exporter-example"), DDOG_CHARSLICE_C_BARE("1.2.3"),
115-
DDOG_CHARSLICE_C_BARE("native"), &tags, endpoint);
129+
ddog_prof_Exporter_NewResult exporter_new_result = ddog_prof_Exporter_new(
130+
DDOG_CHARSLICE_C_BARE("exporter-example"), DDOG_CHARSLICE_C_BARE("1.2.3"),
131+
DDOG_CHARSLICE_C_BARE("native"), &tags, endpoint);
116132
ddog_Vec_Tag_drop(tags);
117133

118134
if (exporter_new_result.tag == DDOG_PROF_EXPORTER_NEW_RESULT_ERR) {
@@ -137,14 +153,15 @@ int main(int argc, char *argv[]) {
137153
ddog_CharSlice internal_metadata_example = DDOG_CHARSLICE_C_BARE(
138154
"{\"no_signals_workaround_enabled\": \"true\", \"execution_trace_enabled\": \"false\"}");
139155

140-
ddog_CharSlice info_example = DDOG_CHARSLICE_C_BARE(
141-
"{\"application\": {\"start_time\": \"2024-01-24T11:17:22+0000\"}, \"platform\": {\"kernel\": \"Darwin Kernel 22.5.0\"}}");
156+
ddog_CharSlice info_example =
157+
DDOG_CHARSLICE_C_BARE("{\"application\": {\"start_time\": \"2024-01-24T11:17:22+0000\"}, "
158+
"\"platform\": {\"kernel\": \"Darwin Kernel 22.5.0\"}}");
142159

143160
auto res = ddog_prof_Exporter_set_timeout(exporter, 30000);
144161
if (res.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
145-
print_error("Failed to set the timeout", res.some);
146-
ddog_Error_drop(&res.some);
147-
return 1;
162+
print_error("Failed to set the timeout", res.some);
163+
ddog_Error_drop(&res.some);
164+
return 1;
148165
}
149166

150167
ddog_prof_Exporter_Request_BuildResult build_result = ddog_prof_Exporter_Request_build(

examples/ffi/profiles.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ int main(void) {
1414
const ddog_prof_Slice_ValueType sample_types = {&wall_time, 1};
1515
const ddog_prof_Period period = {wall_time, 60};
1616

17-
ddog_prof_Profile_NewResult new_result = ddog_prof_Profile_new(sample_types, &period, NULL);
18-
if (new_result.tag != DDOG_PROF_PROFILE_NEW_RESULT_OK) {
17+
ddog_prof_Result_HandleProfile new_result = ddog_prof_Profile_new(sample_types, &period, NULL);
18+
if (new_result.tag != DDOG_PROF_RESULT_HANDLE_PROFILE_OK_HANDLE_PROFILE) {
1919
ddog_CharSlice message = ddog_Error_message(&new_result.err);
2020
fprintf(stderr, "%.*s", (int)message.len, message.ptr);
2121
ddog_Error_drop(&new_result.err);
@@ -47,8 +47,8 @@ int main(void) {
4747
for (int i = 0; i < 10000000; i++) {
4848
label.num = i;
4949

50-
ddog_prof_Profile_Result add_result = ddog_prof_Profile_add(profile, sample, 0);
51-
if (add_result.tag != DDOG_PROF_PROFILE_RESULT_OK) {
50+
ddog_VoidResult add_result = ddog_prof_Profile_add(profile, sample, 0);
51+
if (add_result.tag == DDOG_VOID_RESULT_ERR) {
5252
ddog_CharSlice message = ddog_Error_message(&add_result.err);
5353
fprintf(stderr, "%.*s", (int)message.len, message.ptr);
5454
ddog_Error_drop(&add_result.err);
@@ -58,8 +58,8 @@ int main(void) {
5858
// printf("Press any key to reset and drop...");
5959
// getchar();
6060

61-
ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(profile, NULL);
62-
if (reset_result.tag != DDOG_PROF_PROFILE_RESULT_OK) {
61+
ddog_VoidResult reset_result = ddog_prof_Profile_reset(profile, NULL);
62+
if (reset_result.tag == DDOG_VOID_RESULT_ERR) {
6363
ddog_CharSlice message = ddog_Error_message(&reset_result.err);
6464
fprintf(stderr, "%.*s", (int)message.len, message.ptr);
6565
ddog_Error_drop(&reset_result.err);

profiling-ffi/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@ symbolizer-ffi = { path = "../symbolizer-ffi", optional = true, default-features
4646
symbolic-demangle = { version = "12.8.0", default-features = false, features = ["rust", "cpp", "msvc"] }
4747
symbolic-common = "12.8.0"
4848
data-pipeline-ffi = { path = "../data-pipeline-ffi", default-features = false, optional = true }
49+
function_name = "0.3.0"

profiling-ffi/cbindgen.toml

+2-4
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,15 @@ renaming_overrides_prefixing = true
3333
"Timespec" = "ddog_Timespec"
3434
"Vec_Tag" = "ddog_Vec_Tag"
3535
"Vec_U8" = "ddog_Vec_U8"
36+
"VoidResult" = "ddog_VoidResult"
3637

37-
"ProfilingEndpoint" = "ddog_prof_Endpoint"
3838
"ExporterNewResult" = "ddog_prof_Exporter_NewResult"
3939
"File" = "ddog_prof_Exporter_File"
4040
"ProfileExporter" = "ddog_prof_Exporter"
41-
"ProfileNewResult" = "ddog_prof_Profile_NewResult"
42-
"ProfileResult" = "ddog_prof_Profile_Result"
41+
"ProfilingEndpoint" = "ddog_prof_Endpoint"
4342
"Request" = "ddog_prof_Exporter_Request"
4443
"RequestBuildResult" = "ddog_prof_Exporter_Request_BuildResult"
4544
"SendResult" = "ddog_prof_Exporter_SendResult"
46-
"SerializeResult" = "ddog_prof_Profile_SerializeResult"
4745
"Slice_File" = "ddog_prof_Exporter_Slice_File"
4846

4947
[export.mangle]

0 commit comments

Comments
 (0)