Skip to content

Commit 4c297d4

Browse files
wip
1 parent 24ad01a commit 4c297d4

File tree

14 files changed

+222
-24
lines changed

14 files changed

+222
-24
lines changed

ddtrace/internal/datadog/profiling/dd_wrapper/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ add_library(
5656
src/profile.cpp
5757
src/profile_borrow.cpp
5858
src/profiler_stats.cpp
59+
src/profiler_upload_batch.cpp
5960
src/sample.cpp
6061
src/sample_manager.cpp
6162
src/static_sample_pool.cpp

ddtrace/internal/datadog/profiling/dd_wrapper/include/profile.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ extern "C"
1616
namespace Datadog {
1717

1818
class ProfileBorrow;
19+
class ProfilerUploadBatch;
1920

2021
// Serves to collect individual samples, as well as lengthen the scope of string data
2122
class Profile
2223
{
2324
friend class ProfileBorrow;
25+
friend class ProfilerUploadBatch;
2426

2527
private:
2628
// Serialization for static state
@@ -46,6 +48,7 @@ class Profile
4648
// The profile object is initialized here as a skeleton object, but it
4749
// cannot be used until it's initialized by libdatadog
4850
ddog_prof_Profile cur_profile{};
51+
ddog_prof_Profile last_profile{};
4952

5053
Datadog::ProfilerStats cur_profiler_stats{};
5154

ddtrace/internal/datadog/profiling/dd_wrapper/include/profile_borrow.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class ProfileBorrow
1212
{
1313
private:
1414
Profile* profile_ptr;
15+
ProfilerStats profiler_stats;
1516

1617
public:
1718
explicit ProfileBorrow(Profile& profile);

ddtrace/internal/datadog/profiling/dd_wrapper/include/profiler_stats.hpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <cstddef>
44

55
#include <string>
6-
#include <string_view>
76

87
namespace Datadog {
98

@@ -17,8 +16,6 @@ a mutex to protect access to the data.
1716
class ProfilerStats
1817
{
1918
private:
20-
std::string internal_metadata_json;
21-
2219
// Number of samples collected (one per thread)
2320
size_t sample_count = 0;
2421

@@ -37,9 +34,7 @@ class ProfilerStats
3734

3835
// Returns a JSON string containing relevant Profiler Stats to be included
3936
// in the libdatadog payload.
40-
// The function returned a string_view to a statically allocated string that
41-
// is updated every time the function is called.
42-
std::string_view get_internal_metadata_json();
37+
std::string get_internal_metadata_json();
4338

4439
void reset_state();
4540
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
#include "profile.hpp"
4+
#include "profiler_stats.hpp"
5+
6+
extern "C"
7+
{
8+
#include "datadog/profiling.h"
9+
}
10+
11+
namespace Datadog {
12+
13+
// Forward declaration
14+
class Profile;
15+
16+
// RAII wrapper specifically for uploading profiles with minimal lock time
17+
// This class:
18+
// 1. Locks briefly to swap profiles
19+
// 2. Serializes the profile (which resets it)
20+
// 3. Unlocks before doing the actual upload
21+
class ProfilerUploadBatch
22+
{
23+
private:
24+
ddog_prof_Profile profile_to_upload{};
25+
ProfilerStats stats_to_upload{};
26+
ddog_prof_EncodedProfile encoded_profile{};
27+
bool serialized{ false };
28+
29+
public:
30+
explicit ProfilerUploadBatch(Profile& profile);
31+
~ProfilerUploadBatch();
32+
33+
// Disable copy
34+
ProfilerUploadBatch(const ProfilerUploadBatch&) = delete;
35+
ProfilerUploadBatch& operator=(const ProfilerUploadBatch&) = delete;
36+
37+
// Enable move
38+
ProfilerUploadBatch(ProfilerUploadBatch&& other) noexcept;
39+
ProfilerUploadBatch& operator=(ProfilerUploadBatch&& other) noexcept;
40+
41+
// Serialize the profile (must be called before accessing encoded profile)
42+
bool serialize();
43+
44+
// Accessors (only valid after serialize() returns true)
45+
ddog_prof_EncodedProfile* get_encoded_profile();
46+
ProfilerStats& stats();
47+
48+
// For operations that need access to the profile before serialization
49+
ddog_prof_Profile& profile();
50+
};
51+
52+
} // namespace Datadog

ddtrace/internal/datadog/profiling/dd_wrapper/include/sample.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "libdatadog_helpers.hpp"
44
#include "profile.hpp"
55
#include "profile_borrow.hpp"
6+
#include "profiler_upload_batch.hpp"
67
#include "types.hpp"
78

89
#include <string>
@@ -136,6 +137,7 @@ class Sample
136137
bool flush_sample(bool reverse_locations = false);
137138

138139
static ProfileBorrow profile_borrow();
140+
static ProfilerUploadBatch profile_upload_batch();
139141
static void postfork_child();
140142
Sample(SampleType _type_mask, unsigned int _max_nframes);
141143

ddtrace/internal/datadog/profiling/dd_wrapper/include/uploader.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Uploader
2727

2828
public:
2929
bool upload(ddog_prof_Profile& profile, Datadog::ProfilerStats& profiler_stats);
30+
bool upload(ddog_prof_EncodedProfile* encoded, Datadog::ProfilerStats& profiler_stats);
3031
static void cancel_inflight();
3132
static void lock();
3233
static void unlock();

ddtrace/internal/datadog/profiling/dd_wrapper/src/ddup_interface.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -359,14 +359,18 @@ ddup_upload() // cppcheck-suppress unusedFunction
359359

360360
// Get the reference to the uploader
361361
auto& uploader = std::get<Datadog::Uploader>(uploader_or_err);
362-
// There are a few things going on here.
363-
// * profile_borrow() takes a reference in a way that locks the areas where the profile might
364-
// be modified. It gets released and cleared after uploading.
365-
// * Uploading cancels inflight uploads. There are better ways to do this, but this is what
366-
// we have for now.
367-
auto borrowed = Datadog::Sample::profile_borrow();
368-
bool success = uploader.upload(borrowed.profile(), borrowed.stats());
369-
borrowed.stats().reset_state();
362+
363+
// Create the upload batch - this swaps profiles and unlocks immediately
364+
auto upload_batch = Datadog::Sample::profile_upload_batch();
365+
366+
// Serialize the profile (still outside of any locks)
367+
if (!upload_batch.serialize()) {
368+
return false;
369+
}
370+
371+
// Upload without holding any locks
372+
bool success = uploader.upload(upload_batch.get_encoded_profile(), upload_batch.stats());
373+
upload_batch.stats().reset_state();
370374
return success;
371375
}
372376

ddtrace/internal/datadog/profiling/dd_wrapper/src/profile.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ Datadog::Profile::reset_profile()
5858
return false;
5959
}
6060

61+
res = ddog_prof_Profile_reset(&last_profile);
62+
if (!res.ok) { // NOLINT (cppcoreguidelines-pro-type-union-access)
63+
auto err = res.err; // NOLINT (cppcoreguidelines-pro-type-union-access)
64+
if (!already_warned) {
65+
already_warned = true;
66+
const std::string errmsg = err_to_msg(&err, "Error resetting last_profile");
67+
std::cerr << "Could not drop last_profile:" << errmsg << std::endl;
68+
}
69+
ddog_Error_drop(&err);
70+
return false;
71+
}
72+
6173
cur_profiler_stats.reset_state();
6274
return true;
6375
}
@@ -189,7 +201,15 @@ Datadog::Profile::one_time_init(SampleType type, unsigned int _max_nframes)
189201
if (!make_profile(sample_types, &default_period, cur_profile)) {
190202
if (!already_warned) {
191203
already_warned = true;
192-
std::cerr << "Error initializing profile" << std::endl;
204+
std::cerr << "Error initializing cur_profile" << std::endl;
205+
}
206+
return;
207+
}
208+
209+
if (!make_profile(sample_types, &default_period, last_profile)) {
210+
if (!already_warned) {
211+
already_warned = true;
212+
std::cerr << "Error initializing last_profile" << std::endl;
193213
}
194214
return;
195215
}

ddtrace/internal/datadog/profiling/dd_wrapper/src/profile_borrow.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Datadog::ProfileBorrow::ProfileBorrow(Profile& profile)
66
{
77
// Lock the mutex on construction
88
profile_ptr->profile_borrow_internal();
9+
10+
std::swap(profile_ptr->cur_profile, profile_ptr->last_profile);
11+
std::swap(profile_ptr->cur_profiler_stats, profiler_stats);
912
}
1013

1114
Datadog::ProfileBorrow::~ProfileBorrow()
@@ -17,6 +20,7 @@ Datadog::ProfileBorrow::~ProfileBorrow()
1720

1821
Datadog::ProfileBorrow::ProfileBorrow(ProfileBorrow&& other) noexcept
1922
: profile_ptr(other.profile_ptr)
23+
, profiler_stats(std::move(other.profiler_stats))
2024
{
2125
other.profile_ptr = nullptr;
2226
}
@@ -32,6 +36,7 @@ Datadog::ProfileBorrow::operator=(ProfileBorrow&& other) noexcept
3236

3337
// Take ownership from other
3438
profile_ptr = other.profile_ptr;
39+
profiler_stats = std::move(other.profiler_stats);
3540
other.profile_ptr = nullptr;
3641
}
3742
return *this;
@@ -40,11 +45,11 @@ Datadog::ProfileBorrow::operator=(ProfileBorrow&& other) noexcept
4045
ddog_prof_Profile&
4146
Datadog::ProfileBorrow::profile()
4247
{
43-
return profile_ptr->cur_profile;
48+
return profile_ptr->last_profile;
4449
}
4550

4651
Datadog::ProfilerStats&
4752
Datadog::ProfileBorrow::stats()
4853
{
49-
return profile_ptr->cur_profiler_stats;
54+
return profiler_stats;
5055
}

0 commit comments

Comments
 (0)