Skip to content

Commit

Permalink
[PROF-10477] Upgrade to libdatadog 12 (#3885)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexJF authored Sep 10, 2024
1 parent ebd0c3e commit cb78dc6
Show file tree
Hide file tree
Showing 486 changed files with 1,381 additions and 1,408 deletions.
2 changes: 1 addition & 1 deletion datadog.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Gem::Specification.new do |spec|

# When updating the version here, please also update the version in `libdatadog_extconf_helpers.rb`
# (and yes we have a test for it)
spec.add_dependency 'libdatadog', '~> 11.0.0.1.0'
spec.add_dependency 'libdatadog', '~> 12.0.0.1.0'

spec.extensions = [
'ext/datadog_profiling_native_extension/extconf.rb',
Expand Down
27 changes: 0 additions & 27 deletions ext/datadog_profiling_native_extension/datadog_ruby_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,6 @@ VALUE datadog_gem_version(void) {
return version_string;
}

__attribute__((warn_unused_result))
ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
ENFORCE_TYPE(exporter_configuration, T_ARRAY);

VALUE exporter_working_mode = rb_ary_entry(exporter_configuration, 0);
ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
ID working_mode = SYM2ID(exporter_working_mode);

ID agentless_id = rb_intern("agentless");
ID agent_id = rb_intern("agent");

if (working_mode != agentless_id && working_mode != agent_id) {
rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
}

if (working_mode == agentless_id) {
VALUE site = rb_ary_entry(exporter_configuration, 1);
VALUE api_key = rb_ary_entry(exporter_configuration, 2);

return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
} else { // agent_id
VALUE base_url = rb_ary_entry(exporter_configuration, 1);

return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
}
}

static VALUE log_failure_to_process_tag(VALUE err_details) {
VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
Expand Down
3 changes: 0 additions & 3 deletions ext/datadog_profiling_native_extension/datadog_ruby_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ static inline ddog_CharSlice char_slice_from_ruby_string(VALUE string) {
return char_slice;
}

__attribute__((warn_unused_result))
ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration);

__attribute__((warn_unused_result))
ddog_Vec_Tag convert_tags(VALUE tags_as_array);

Expand Down
44 changes: 38 additions & 6 deletions ext/datadog_profiling_native_extension/http_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,32 @@ static VALUE _native_validate_exporter(DDTRACE_UNUSED VALUE _self, VALUE exporte
return rb_ary_new_from_args(2, ok_symbol, Qnil);
}

static ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
ENFORCE_TYPE(exporter_configuration, T_ARRAY);

VALUE exporter_working_mode = rb_ary_entry(exporter_configuration, 0);
ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
ID working_mode = SYM2ID(exporter_working_mode);

ID agentless_id = rb_intern("agentless");
ID agent_id = rb_intern("agent");

if (working_mode != agentless_id && working_mode != agent_id) {
rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
}

if (working_mode == agentless_id) {
VALUE site = rb_ary_entry(exporter_configuration, 1);
VALUE api_key = rb_ary_entry(exporter_configuration, 2);

return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
} else { // agent_id
VALUE base_url = rb_ary_entry(exporter_configuration, 1);

return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
}
}

static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration, VALUE tags_as_array) {
ENFORCE_TYPE(exporter_configuration, T_ARRAY);
ENFORCE_TYPE(tags_as_array, T_ARRAY);
Expand Down Expand Up @@ -115,8 +141,7 @@ static VALUE perform_export(
ddog_prof_Exporter_Slice_File files_to_export_unmodified,
ddog_Vec_Tag *additional_tags,
ddog_CharSlice internal_metadata,
ddog_CharSlice info,
uint64_t timeout_milliseconds
ddog_CharSlice info
) {
ddog_prof_ProfiledEndpointsStats *endpoints_stats = NULL; // Not in use yet
ddog_prof_Exporter_Request_BuildResult build_result = ddog_prof_Exporter_Request_build(
Expand All @@ -128,8 +153,7 @@ static VALUE perform_export(
additional_tags,
endpoints_stats,
&internal_metadata,
&info,
timeout_milliseconds
&info
);

if (build_result.tag == DDOG_PROF_EXPORTER_REQUEST_BUILD_RESULT_ERR) {
Expand Down Expand Up @@ -254,6 +278,15 @@ static VALUE _native_do_export(
VALUE failure_tuple = handle_exporter_failure(exporter_result);
if (!NIL_P(failure_tuple)) return failure_tuple;

ddog_prof_MaybeError timeout_result = ddog_prof_Exporter_set_timeout(exporter_result.ok, timeout_milliseconds);
if (timeout_result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
// NOTE: Seems a bit harsh to fail the upload if we can't set a timeout. OTOH, this is only expected to fail
// if the exporter is not well built. Because such a situation should already be caught above I think it's
// preferable to leave this here as a virtually unreachable exception rather than ignoring it.
ddog_prof_Exporter_drop(exporter_result.ok);
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.some));
}

return perform_export(
exporter_result.ok,
start,
Expand All @@ -262,8 +295,7 @@ static VALUE _native_do_export(
files_to_export_unmodified,
null_additional_tags,
internal_metadata,
info,
timeout_milliseconds
info
);
}

Expand Down
37 changes: 19 additions & 18 deletions ext/libdatadog_api/crashtracker.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <ruby.h>
#include <datadog/profiling.h>
#include <datadog/crashtracker.h>

#include "datadog_ruby_common.h"

Expand Down Expand Up @@ -29,7 +29,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
VALUE options;
rb_scan_args(argc, argv, "0:", &options);

VALUE exporter_configuration = rb_hash_fetch(options, ID2SYM(rb_intern("exporter_configuration")));
VALUE agent_base_url = rb_hash_fetch(options, ID2SYM(rb_intern("agent_base_url")));
VALUE path_to_crashtracking_receiver_binary = rb_hash_fetch(options, ID2SYM(rb_intern("path_to_crashtracking_receiver_binary")));
VALUE ld_library_path = rb_hash_fetch(options, ID2SYM(rb_intern("ld_library_path")));
VALUE tags_as_array = rb_hash_fetch(options, ID2SYM(rb_intern("tags_as_array")));
Expand All @@ -39,7 +39,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
VALUE start_action = ID2SYM(rb_intern("start"));
VALUE update_on_fork_action = ID2SYM(rb_intern("update_on_fork"));

ENFORCE_TYPE(exporter_configuration, T_ARRAY);
ENFORCE_TYPE(agent_base_url, T_STRING);
ENFORCE_TYPE(tags_as_array, T_ARRAY);
ENFORCE_TYPE(path_to_crashtracking_receiver_binary, T_STRING);
ENFORCE_TYPE(ld_library_path, T_STRING);
Expand All @@ -49,13 +49,13 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
if (action != start_action && action != update_on_fork_action) rb_raise(rb_eArgError, "Unexpected action: %+"PRIsVALUE, action);

VALUE version = datadog_gem_version();
ddog_prof_Endpoint endpoint = endpoint_from(exporter_configuration);

// Tags are heap-allocated, so after here we can't raise exceptions otherwise we'll leak this memory
// Tags and endpoint are heap-allocated, so after here we can't raise exceptions otherwise we'll leak this memory
// Start of exception-free zone to prevent leaks {{
ddog_Endpoint *endpoint = ddog_endpoint_from_url(char_slice_from_ruby_string(agent_base_url));
ddog_Vec_Tag tags = convert_tags(tags_as_array);

ddog_prof_CrashtrackerConfiguration config = {
ddog_crasht_Config config = {
.additional_files = {},
// The Ruby VM already uses an alt stack to detect stack overflows so the crash handler must not overwrite it.
//
Expand All @@ -67,53 +67,54 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
// "Process.kill('SEGV', Process.pid)" gets run.
.create_alt_stack = false,
.endpoint = endpoint,
.resolve_frames = DDOG_PROF_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER,
.resolve_frames = DDOG_CRASHT_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER,
.timeout_secs = FIX2INT(upload_timeout_seconds),
// Waits for crash tracker to finish reporting the issue before letting the Ruby process die; see
// https://github.com/DataDog/libdatadog/pull/477 for details
.wait_for_receiver = true,
};

ddog_prof_CrashtrackerMetadata metadata = {
.profiling_library_name = DDOG_CHARSLICE_C("dd-trace-rb"),
.profiling_library_version = char_slice_from_ruby_string(version),
ddog_crasht_Metadata metadata = {
.library_name = DDOG_CHARSLICE_C("dd-trace-rb"),
.library_version = char_slice_from_ruby_string(version),
.family = DDOG_CHARSLICE_C("ruby"),
.tags = &tags,
};

ddog_prof_EnvVar ld_library_path_env = {
ddog_crasht_EnvVar ld_library_path_env = {
.key = DDOG_CHARSLICE_C("LD_LIBRARY_PATH"),
.val = char_slice_from_ruby_string(ld_library_path),
};

ddog_prof_CrashtrackerReceiverConfig receiver_config = {
ddog_crasht_ReceiverConfig receiver_config = {
.args = {},
.env = {.ptr = &ld_library_path_env, .len = 1},
.path_to_receiver_binary = char_slice_from_ruby_string(path_to_crashtracking_receiver_binary),
.optional_stderr_filename = {},
.optional_stdout_filename = {},
};

ddog_prof_CrashtrackerResult result =
ddog_crasht_Result result =
action == start_action ?
ddog_prof_Crashtracker_init_with_receiver(config, receiver_config, metadata) :
ddog_prof_Crashtracker_update_on_fork(config, receiver_config, metadata);
ddog_crasht_init_with_receiver(config, receiver_config, metadata) :
ddog_crasht_update_on_fork(config, receiver_config, metadata);

// Clean up before potentially raising any exceptions
ddog_Vec_Tag_drop(tags);
ddog_endpoint_drop(endpoint);
// }} End of exception-free zone to prevent leaks

if (result.tag == DDOG_PROF_CRASHTRACKER_RESULT_ERR) {
if (result.tag == DDOG_CRASHT_RESULT_ERR) {
rb_raise(rb_eRuntimeError, "Failed to start/update the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
}

return Qtrue;
}

static VALUE _native_stop(DDTRACE_UNUSED VALUE _self) {
ddog_prof_CrashtrackerResult result = ddog_prof_Crashtracker_shutdown();
ddog_crasht_Result result = ddog_crasht_shutdown();

if (result.tag == DDOG_PROF_CRASHTRACKER_RESULT_ERR) {
if (result.tag == DDOG_CRASHT_RESULT_ERR) {
rb_raise(rb_eRuntimeError, "Failed to stop the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
}

Expand Down
27 changes: 0 additions & 27 deletions ext/libdatadog_api/datadog_ruby_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,6 @@ VALUE datadog_gem_version(void) {
return version_string;
}

__attribute__((warn_unused_result))
ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
ENFORCE_TYPE(exporter_configuration, T_ARRAY);

VALUE exporter_working_mode = rb_ary_entry(exporter_configuration, 0);
ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
ID working_mode = SYM2ID(exporter_working_mode);

ID agentless_id = rb_intern("agentless");
ID agent_id = rb_intern("agent");

if (working_mode != agentless_id && working_mode != agent_id) {
rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
}

if (working_mode == agentless_id) {
VALUE site = rb_ary_entry(exporter_configuration, 1);
VALUE api_key = rb_ary_entry(exporter_configuration, 2);

return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
} else { // agent_id
VALUE base_url = rb_ary_entry(exporter_configuration, 1);

return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
}
}

static VALUE log_failure_to_process_tag(VALUE err_details) {
VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
Expand Down
3 changes: 0 additions & 3 deletions ext/libdatadog_api/datadog_ruby_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ static inline ddog_CharSlice char_slice_from_ruby_string(VALUE string) {
return char_slice;
}

__attribute__((warn_unused_result))
ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration);

__attribute__((warn_unused_result))
ddog_Vec_Tag convert_tags(VALUE tags_as_array);

Expand Down
2 changes: 1 addition & 1 deletion ext/libdatadog_extconf_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Datadog
module LibdatadogExtconfHelpers
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
LIBDATADOG_VERSION = '~> 11.0.0.1.0'
LIBDATADOG_VERSION = '~> 12.0.0.1.0'

# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
# libdatadog are moved after the extension gets compiled.
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/jruby_9.2_activesupport.gemfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gemfiles/jruby_9.2_aws.gemfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gemfiles/jruby_9.2_contrib.gemfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gemfiles/jruby_9.2_contrib_old.gemfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gemfiles/jruby_9.2_core_old.gemfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cb78dc6

Please sign in to comment.