diff --git a/cmake/Findlibdatadog.cmake b/cmake/Findlibdatadog.cmake index 9a41c835e..69920f3fb 100644 --- a/cmake/Findlibdatadog.cmake +++ b/cmake/Findlibdatadog.cmake @@ -2,10 +2,9 @@ # License Version 2.0. This product includes software developed at Datadog # (https://www.datadoghq.com/). Copyright 2021-Present Datadog, Inc. -# libdatadog : common profiler imported libraries -# https://github.com/DataDog/libdatadog/releases/tag/v7.0.0 +# libdatadog : common profiler imported libraries https://github.com/DataDog/libdatadog/releases set(TAG_LIBDATADOG - "v19.1.0" + "v26.0.0" CACHE STRING "libdatadog github tag") set(Datadog_ROOT ${VENDOR_PATH}/libdatadog-${TAG_LIBDATADOG}) diff --git a/include/pprof/ddprof_pprof.hpp b/include/pprof/ddprof_pprof.hpp index e4e93688e..6da352556 100644 --- a/include/pprof/ddprof_pprof.hpp +++ b/include/pprof/ddprof_pprof.hpp @@ -36,7 +36,8 @@ struct DDProfValuePack { uint64_t timestamp; }; -DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx); +DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx, + const ddog_prof_ProfilesDictionaryHandle *dict); /** * Aggregate to the existing profile the provided unwinding output. diff --git a/include/symbol.hpp b/include/symbol.hpp index c38413869..62cd32ad6 100644 --- a/include/symbol.hpp +++ b/include/symbol.hpp @@ -17,7 +17,6 @@ class Symbol { public: Symbol() : _lineno(0) {} - // Warning : Generates some string copies (these are not rvalues) Symbol(std::string symname, std::string demangled_name, uint32_t lineno, std::string srcpath) : _symname(std::move(symname)), diff --git a/include/symbol_hdr.hpp b/include/symbol_hdr.hpp index 863343ed7..be56930e6 100644 --- a/include/symbol_hdr.hpp +++ b/include/symbol_hdr.hpp @@ -15,11 +15,30 @@ #include "runtime_symbol_lookup.hpp" #include +#include + +// Forward declarations for libdatadog types (must be at global scope) +struct ddog_prof_ProfilesDictionary; +using ddog_prof_ProfilesDictionaryHandle = ddog_prof_ProfilesDictionary *; namespace ddprof { + +struct ProfilesDictionaryDeleter { + void operator()(ddog_prof_ProfilesDictionaryHandle *handle) const; +}; + +using ProfilesDictionaryPtr = + std::unique_ptr; + struct SymbolHdr { - explicit SymbolHdr(std::string_view path_to_proc = "") - : _runtime_symbol_lookup(path_to_proc) {} + explicit SymbolHdr(std::string_view path_to_proc = ""); + ~SymbolHdr() = default; + + SymbolHdr(const SymbolHdr &) = delete; + SymbolHdr &operator=(const SymbolHdr &) = delete; + SymbolHdr(SymbolHdr &&) noexcept = default; + SymbolHdr &operator=(SymbolHdr &&) noexcept = default; void display_stats() const { _dso_symbol_lookup.stats_display(); } void cycle() { _runtime_symbol_lookup.cycle(); } @@ -44,6 +63,9 @@ struct SymbolHdr { // The mapping table MapInfoTable _mapinfo_table; + + // String interning dictionary (persists across profile exports) + ProfilesDictionaryPtr _profiles_dictionary; }; } // namespace ddprof diff --git a/src/ddog_profiling_utils.cc b/src/ddog_profiling_utils.cc index a5433b26f..1444166b2 100644 --- a/src/ddog_profiling_utils.cc +++ b/src/ddog_profiling_utils.cc @@ -27,7 +27,6 @@ std::string_view get_or_insert_demangled_sym( void write_function(const Symbol &symbol, ddog_prof_Function *ffi_func) { ffi_func->name = to_CharSlice(symbol._demangled_name); - // We can also send symbol._symname if useful ffi_func->system_name = {.ptr = nullptr, .len = 0}; ffi_func->filename = to_CharSlice(symbol._srcpath); } diff --git a/src/ddprof_worker.cc b/src/ddprof_worker.cc index aa1394370..1e1b907e1 100644 --- a/src/ddprof_worker.cc +++ b/src/ddprof_worker.cc @@ -710,8 +710,12 @@ DDRes ddprof_worker_init(DDProfContext &ctx, DDRES_CHECK_FWD( ddprof_exporter_new(ctx.worker_ctx.user_tags, ctx.worker_ctx.exp[1])); - DDRES_CHECK_FWD(pprof_create_profile(ctx.worker_ctx.pprof[0], ctx)); - DDRES_CHECK_FWD(pprof_create_profile(ctx.worker_ctx.pprof[1], ctx)); + DDRES_CHECK_FWD(pprof_create_profile( + ctx.worker_ctx.pprof[0], ctx, + ctx.worker_ctx.us->symbol_hdr._profiles_dictionary.get())); + DDRES_CHECK_FWD(pprof_create_profile( + ctx.worker_ctx.pprof[1], ctx, + ctx.worker_ctx.us->symbol_hdr._profiles_dictionary.get())); DDRES_CHECK_FWD(worker_init_stats(&ctx.worker_ctx)); } CatchExcept2DDRes(); diff --git a/src/exporter/ddprof_exporter.cc b/src/exporter/ddprof_exporter.cc index d7532c288..7e60296d2 100644 --- a/src/exporter/ddprof_exporter.cc +++ b/src/exporter/ddprof_exporter.cc @@ -263,10 +263,10 @@ DDRes ddprof_exporter_new(const UserTags *user_tags, DDProfExporter *exporter) { ddog_CharSlice const base_url = to_CharSlice(exporter->_url); ddog_prof_Endpoint endpoint; if (exporter->_agent) { - endpoint = ddog_prof_Endpoint_agent(base_url); + endpoint = ddog_prof_Endpoint_agent(base_url, k_timeout_ms); } else { ddog_CharSlice const api_key = to_CharSlice(exporter->_input.api_key); - endpoint = ddog_prof_Endpoint_agentless(base_url, api_key); + endpoint = ddog_prof_Endpoint_agentless(base_url, api_key, k_timeout_ms); } ddog_prof_ProfileExporter_Result res_exporter = ddog_prof_Exporter_new( @@ -283,14 +283,6 @@ DDRes ddprof_exporter_new(const UserTags *user_tags, DDProfExporter *exporter) { static_cast(res_exporter.err.message.len), res_exporter.err.message.ptr); } - auto result = - ddog_prof_Exporter_set_timeout(&exporter->_exporter, k_timeout_ms); - if (result.tag == DDOG_VOID_RESULT_ERR) { - defer { ddog_Error_drop(&result.err); }; - DDRES_RETURN_ERROR_LOG(DD_WHAT_EXPORTER, "Failure setting timeout - %.*s", - static_cast(result.err.message.len), - result.err.message.ptr); - } return {}; } @@ -335,53 +327,34 @@ DDRes ddprof_exporter_export(ddog_prof_Profile *profile, LG_NTC("[EXPORTER] Export buffer of size %lu", buffer->len); - // clang-format off - ddog_prof_Request_Result res_request = - ddog_prof_Exporter_Request_build(&exporter->_exporter, - encoded_profile, - ddog_prof_Exporter_Slice_File_empty(), // files_to_compress_and_export - ddog_prof_Exporter_Slice_File_empty(), // already compressed - &ffi_additional_tags, // optional tags - nullptr, // internal_metadata_json - nullptr // optional_info_json - ); - // clang-format on - - if (res_request.tag == DDOG_PROF_REQUEST_RESULT_OK_HANDLE_REQUEST) { - ddog_prof_Request request = res_request.ok; - - // dropping the request is not useful if we have a send - // however the send will replace the request by null when it takes - // ownership - defer { ddog_prof_Exporter_Request_drop(&request); }; - - ddog_prof_Result_HttpStatus result = - ddog_prof_Exporter_send(&exporter->_exporter, &request, nullptr); - - if (result.tag == DDOG_PROF_RESULT_HTTP_STATUS_ERR_HTTP_STATUS) { - defer { ddog_Error_drop(&result.err); }; - LG_WRN("Failure to establish connection, check url %s", - exporter->_url.c_str()); - LG_WRN("Failure to send profiles (%.*s)", (int)result.err.message.len, - result.err.message.ptr); - // Free error buffer (prefer this API to the free API) - if (exporter->_nb_consecutive_errors++ >= - k_max_nb_consecutive_errors_allowed) { - // this will shut down profiler - res = ddres_error(DD_WHAT_EXPORTER); - } else { - res = ddres_warn(DD_WHAT_EXPORTER); - } + ddog_prof_Result_HttpStatus result = ddog_prof_Exporter_send_blocking( + &exporter->_exporter, encoded_profile, + ddog_prof_Exporter_Slice_File_empty(), // files_to_compress_and_export + &ffi_additional_tags, // optional_additional_tags + nullptr, // optional_process_tags + nullptr, // optional_internal_metadata_json + nullptr, // optional_info_json + nullptr // cancellation_token + ); + + if (result.tag == DDOG_PROF_RESULT_HTTP_STATUS_ERR_HTTP_STATUS) { + defer { ddog_Error_drop(&result.err); }; + LG_WRN("Failure to establish connection, check url %s", + exporter->_url.c_str()); + LG_WRN("Failure to send profiles (%.*s)", (int)result.err.message.len, + result.err.message.ptr); + // Free error buffer (prefer this API to the free API) + if (exporter->_nb_consecutive_errors++ >= + k_max_nb_consecutive_errors_allowed) { + // this will shut down profiler + res = ddres_error(DD_WHAT_EXPORTER); } else { - // success establishing connection - exporter->_nb_consecutive_errors = 0; - res = check_send_response_code(result.ok.code); + res = ddres_warn(DD_WHAT_EXPORTER); } } else { - defer { ddog_Error_drop(&res_request.err); }; - LG_ERR("[EXPORTER] Failure to build request: %s", - res_request.err.message.ptr); - res = ddres_error(DD_WHAT_EXPORTER); + // success establishing connection + exporter->_nb_consecutive_errors = 0; + res = check_send_response_code(result.ok.code); } } return res; diff --git a/src/pprof/ddprof_pprof.cc b/src/pprof/ddprof_pprof.cc index 66f7c5739..2539bf345 100644 --- a/src/pprof/ddprof_pprof.cc +++ b/src/pprof/ddprof_pprof.cc @@ -388,7 +388,8 @@ DDRes process_symbolization( } // namespace -DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx) { +DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx, + const ddog_prof_ProfilesDictionaryHandle *dict) { size_t const num_watchers = ctx.watchers.size(); ActiveIdsResult active_ids = {}; @@ -463,15 +464,16 @@ DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx) { .value = default_period, }; } - auto prof_res = ddog_prof_Profile_new( - sample_types, + + ddog_prof_Status status = ddog_prof_Profile_with_dictionary( + &pprof->_profile, dict, sample_types, pprof_values.get_num_sample_type_ids() > 0 ? &period : nullptr); - if (prof_res.tag != DDOG_PROF_PROFILE_NEW_RESULT_OK) { - ddog_Error_drop(&prof_res.err); - DDRES_RETURN_ERROR_LOG(DD_WHAT_PPROF, "Unable to create new profile"); + if (status.err != nullptr) { + defer { ddog_prof_Status_drop(&status); }; + DDRES_RETURN_ERROR_LOG(DD_WHAT_PPROF, "Unable to create new profile: %s", + status.err); } - pprof->_profile = prof_res.ok; // Add relevant tags { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 01d4e6257..27cb074e4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -196,6 +196,7 @@ add_unit_test( ../src/ddog_profiling_utils.cc ../src/ddprof_cmdline_watcher.cc ../src/pprof/ddprof_pprof.cc + ../src/symbol_hdr.cc ../src/symbolizer.cc ../src/demangler/demangler.cc ../src/perf_watcher.cc @@ -209,6 +210,7 @@ add_unit_test( ../src/exporter/ddprof_exporter.cc ../src/pprof/ddprof_pprof.cc ../src/perf_watcher.cc + ../src/symbol_hdr.cc ../src/symbolizer.cc ../src/demangler/demangler.cc ../src/tags.cc @@ -266,6 +268,7 @@ add_unit_test( ../src/mapinfo_lookup.cc ../src/procutils.cc ../src/runtime_symbol_lookup.cc + ../src/symbol_hdr.cc ../src/symbol_map.cc ../src/signal_helper.cc ../src/statsd.cc @@ -313,6 +316,7 @@ set(ALLOCATION_TRACKER_UT_SRCS ../src/mapinfo_lookup.cc ../src/procutils.cc ../src/runtime_symbol_lookup.cc + ../src/symbol_hdr.cc ../src/symbol_map.cc ../src/signal_helper.cc ../src/statsd.cc diff --git a/test/ddprof_exporter-ut.cc b/test/ddprof_exporter-ut.cc index 648b3217c..9ead0d151 100644 --- a/test/ddprof_exporter-ut.cc +++ b/test/ddprof_exporter-ut.cc @@ -160,7 +160,8 @@ TEST(DDProfExporter, simple) { fill_unwind_symbols(table, mapinfo_table, mock_output); DDProfContext ctx = {}; ctx.watchers.push_back(*ewatcher_from_str("sCPU")); - res = pprof_create_profile(&pprofs, ctx); + res = pprof_create_profile(&pprofs, ctx, + symbol_hdr._profiles_dictionary.get()); EXPECT_TRUE(IsDDResOK(res)); res = pprof_aggregate(&mock_output, symbol_hdr, {1000, 1, 0}, &ctx.watchers[0], file_infos, false, kSumPos, diff --git a/test/ddprof_pprof-ut.cc b/test/ddprof_pprof-ut.cc index b6aaad6b4..3f402eabb 100644 --- a/test/ddprof_pprof-ut.cc +++ b/test/ddprof_pprof-ut.cc @@ -25,10 +25,13 @@ TEST(DDProfPProf, init_profiles) { DDProfPProf pprof; DDProfContext ctx = {}; ctx.watchers.push_back(*ewatcher_from_str("sCPU")); - DDRes res = pprof_create_profile(&pprof, ctx); + ddog_prof_ProfilesDictionaryHandle dict; + ddog_prof_ProfilesDictionary_new(&dict); + DDRes res = pprof_create_profile(&pprof, ctx, &dict); EXPECT_TRUE(IsDDResOK(res)); res = pprof_free_profile(&pprof); EXPECT_TRUE(IsDDResOK(res)); + ddog_prof_ProfilesDictionary_drop(&dict); } void test_pprof(DDProfPProf *pprofs) { @@ -47,8 +50,7 @@ void test_pprof(DDProfPProf *pprofs) { EXPECT_TRUE(buffer->ptr); - // Test that we are generating content - EXPECT_TRUE(buffer->len > 500); + EXPECT_TRUE(buffer->len > 100); ddog_prof_EncodedProfile_drop(&serialized_result.ok); } @@ -66,7 +68,8 @@ TEST(DDProfPProf, aggregate) { bool ok = watchers_from_str("sCPU", ctx.watchers); EXPECT_TRUE(ok); - DDRes res = pprof_create_profile(&pprof, ctx); + DDRes res = pprof_create_profile(&pprof, ctx, + symbol_hdr._profiles_dictionary.get()); EXPECT_TRUE(ctx.watchers[0].pprof_indices[kSumPos].pprof_index != -1); EXPECT_TRUE(ctx.watchers[0].pprof_indices[kSumPos].pprof_count_index != -1); res = pprof_aggregate(&mock_output, symbol_hdr, {1000, 1, 0}, @@ -102,7 +105,8 @@ TEST(DDProfPProf, just_live) { log_watcher(&(ctx.watchers[0]), 0); log_watcher(&(ctx.watchers[1]), 1); - DDRes res = pprof_create_profile(&pprof, ctx); + DDRes res = pprof_create_profile(&pprof, ctx, + symbol_hdr._profiles_dictionary.get()); EXPECT_TRUE(IsDDResOK(res)); EXPECT_TRUE(ctx.watchers[0].pprof_indices[kSumPos].pprof_index == -1); EXPECT_TRUE(ctx.watchers[0].pprof_indices[kSumPos].pprof_count_index == -1); diff --git a/tools/libdatadog_checksums.txt b/tools/libdatadog_checksums.txt index a7d23590b..a8b413867 100644 --- a/tools/libdatadog_checksums.txt +++ b/tools/libdatadog_checksums.txt @@ -1,6 +1,6 @@ -7c69a37cb335260610b61ae956192a6dbd104d05a8278c8ff894dbfebc2efd53 libdatadog-aarch64-alpine-linux-musl.tar.gz -b992a11b90ec5927646a0c96b74fe9fcd63e7e471307e74a670ddf42fc10eaf9 libdatadog-aarch64-apple-darwin.tar.gz -606b23f4de7defacd5d4a381816f8d7bfe26112c97fcdf21ec2eb998a6c5fbbd libdatadog-aarch64-unknown-linux-gnu.tar.gz -2008886021ddee573c0d539626d1d58d41e2a7dbc8deca22b3662da52de6f4d9 libdatadog-x86_64-alpine-linux-musl.tar.gz -6a12ef60fd7b00544343c2b6761ef801ad2e1237075711bd16dfb7247464bc43 libdatadog-x86_64-apple-darwin.tar.gz -4e5b05515ab180aec0819608aa5d277ff710055819654147a9d69caea27a0dbc libdatadog-x86_64-unknown-linux-gnu.tar.gz +38b83da2781f20f004d278c077b071441f40671de2e0adf72f7e14e37b10db15 libdatadog-x86_64-apple-darwin.tar.gz +1420ba4970ff9158aec4bd8a80d139abe8c19cfd71ae31c6c518f8a2ad1416b8 libdatadog-aarch64-apple-darwin.tar.gz +1778bed8bb4ec5a63af792ed6d7b0acd2564e5c7633d9b65d7c715e7f8635743 libdatadog-x86_64-unknown-linux-gnu.tar.gz +c90bd4959026f7fddb9012036fdc5b1e49bdf57d716cb429cdde291af6108740 libdatadog-aarch64-alpine-linux-musl.tar.gz +c67ada4359cd6a806adafcb44043bc8fb0dffd463e3aa328856496e2883142ac libdatadog-aarch64-unknown-linux-gnu.tar.gz +394b13591400b36d90755bc9851be047e6d31813347ed9d0e2638355cc9617d4 libdatadog-x86_64-alpine-linux-musl.tar.gz