diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 4bd448eaf18..48e7e05265a 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - extension: ["src/core"] + extension: ["src/core", "src/config"] steps: - uses: actions/checkout@v4 with: diff --git a/ddtrace/__init__.py b/ddtrace/__init__.py index 13647de3663..554f1084765 100644 --- a/ddtrace/__init__.py +++ b/ddtrace/__init__.py @@ -6,14 +6,13 @@ LOADED_MODULES = frozenset(sys.modules.keys()) # Configuration for the whole tracer from file. Do it before anything else happens. -from ddtrace.internal.datadog.profiling import library_config - -library_config.set_envp(["%s=%s" % (k, v) for k, v in os.environ.items()]) -library_config.set_args(sys.argv) -for key, value in library_config.get_config(debug_logs=False).items(): +from ddtrace.internal.config import PyConfigurator +configurator = PyConfigurator(debug_logs=False) +configurator.set_envp(["%s=%s" % (k, v) for k, v in os.environ.items()]) +configurator.set_args(sys.argv) +for key, value in configurator.get_configuration().items(): os.environ[key] = str(value).lower() - from ddtrace.internal.module import ModuleWatchdog diff --git a/ddtrace/internal/config/__init__.py b/ddtrace/internal/config/__init__.py new file mode 100644 index 00000000000..c8665b02968 --- /dev/null +++ b/ddtrace/internal/config/__init__.py @@ -0,0 +1 @@ +from ._config import PyConfigurator # noqa:F401 diff --git a/ddtrace/internal/config/_config.pyi b/ddtrace/internal/config/_config.pyi new file mode 100644 index 00000000000..a6012b01a97 --- /dev/null +++ b/ddtrace/internal/config/_config.pyi @@ -0,0 +1,7 @@ +from typing import List + +class PyConfigurator: + def __init__(self, debug_logs: bool): ... + def set_envp(self, envp: List[str]) -> None: ... + def set_args(self, args: List[str]) -> None: ... + def get_configuration(self) -> dict: ... diff --git a/ddtrace/internal/datadog/profiling/build_standalone.sh b/ddtrace/internal/datadog/profiling/build_standalone.sh index 314f5a4b903..c7bc4c14af9 100755 --- a/ddtrace/internal/datadog/profiling/build_standalone.sh +++ b/ddtrace/internal/datadog/profiling/build_standalone.sh @@ -78,7 +78,6 @@ target_dirs["ddup"]="ddup" target_dirs["crashtracker"]="crashtracker" target_dirs["stack_v2"]="stack_v2" target_dirs["dd_wrapper"]="dd_wrapper" -target_dirs["library_config"]="library_config" # Compiler options declare -A compiler_args @@ -220,8 +219,6 @@ print_help() { echo " ddup_test (also builds dd_wrapper_test)" echo " crashtracker (also builds dd_wrapper)" echo " crashtracker_test (also builds dd_wrapper_test)" - echo " library_config (also builds dd_wrapper)" - echo " library_config_test (also builds dd_wrapper_test)" } print_cmake_args() { @@ -346,7 +343,6 @@ add_target() { targets+=("stack_v2") targets+=("ddup") targets+=("crashtracker") - targets+=("library_config") ;; dd_wrapper) # `dd_wrapper` is a dependency of other targets, but the overall structure is weird when it's given explicitly @@ -362,9 +358,6 @@ add_target() { crashtracker) targets+=("crashtracker") ;; - library_config) - targets+=("library_config") - ;; *) echo "Unknown target: $1" exit 1 diff --git a/ddtrace/internal/datadog/profiling/dd_wrapper/CMakeLists.txt b/ddtrace/internal/datadog/profiling/dd_wrapper/CMakeLists.txt index 4c44000e1d0..c427abdcfbc 100644 --- a/ddtrace/internal/datadog/profiling/dd_wrapper/CMakeLists.txt +++ b/ddtrace/internal/datadog/profiling/dd_wrapper/CMakeLists.txt @@ -45,8 +45,6 @@ add_library( src/crashtracker.cpp src/crashtracker_interface.cpp src/ddup_interface.cpp - src/library_config.cpp - src/library_config_interface.cpp src/profile.cpp src/receiver_interface.cpp src/sample.cpp diff --git a/ddtrace/internal/datadog/profiling/dd_wrapper/include/library_config.hpp b/ddtrace/internal/datadog/profiling/dd_wrapper/include/library_config.hpp deleted file mode 100644 index 222caa29448..00000000000 --- a/ddtrace/internal/datadog/profiling/dd_wrapper/include/library_config.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -namespace Datadog { - -typedef struct ConfigEntry { - std::string key; - std::string value; -} ConfigEntry; - -typedef struct ConfigVec { - ConfigEntry* ptr; - size_t len; -} ConfigVec; - -class LibraryConfig -{ - private: - std::vector _envp; - std::vector _args; - ddog_Slice_CharSlice to_char_slice(const std::vector& vec); - - public: - // Setters -- these methods are used to set the library context - void set_envp(const std::vector& envp); - void set_args(const std::vector& args); - - // Main method - ConfigVec generate_config(bool debug_logs); -}; - -} // namespace Datadog diff --git a/ddtrace/internal/datadog/profiling/dd_wrapper/include/library_config_interface.hpp b/ddtrace/internal/datadog/profiling/dd_wrapper/include/library_config_interface.hpp deleted file mode 100644 index 9c90a41d155..00000000000 --- a/ddtrace/internal/datadog/profiling/dd_wrapper/include/library_config_interface.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - void libraryconfig_set_args(const std::vector& args); - void libraryconfig_set_envp(const std::vector& envp); - - Datadog::ConfigVec libraryconfig_generate_config(bool debug_logs); -#ifdef __cplusplus -} // extern "C" - -#endif diff --git a/ddtrace/internal/datadog/profiling/dd_wrapper/src/library_config.cpp b/ddtrace/internal/datadog/profiling/dd_wrapper/src/library_config.cpp deleted file mode 100644 index 3f8ae4d0b96..00000000000 --- a/ddtrace/internal/datadog/profiling/dd_wrapper/src/library_config.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -ddog_Slice_CharSlice -Datadog::LibraryConfig::to_char_slice(const std::vector& vec) { - ddog_CharSlice* slices = new ddog_CharSlice[vec.size()]; - for (size_t i = 0; i < vec.size(); i++) { - slices[i] = ddog_CharSlice{vec[i].data(), vec[i].size()}; - } - ddog_Slice_CharSlice result = {slices, vec.size()}; - return result; -} - -void -Datadog::LibraryConfig::set_envp(const std::vector& envp) -{ - // Copy string_views to strings to avoid garbage collection - std::vector new_envp; - for (size_t i = 0; i < envp.size(); i++) { - if(!envp[i].empty()) { - new_envp.push_back(std::string(envp[i])); - } - } - _envp = std::move(new_envp); -} - -void -Datadog::LibraryConfig::set_args(const std::vector& args) -{ - // Copy string_views to strings to avoid garbage collection - std::vector new_args; - for (size_t i = 0; i < args.size(); i++) { - if(!args[i].empty()) { - new_args.push_back(std::string(args[i])); - } - } - _args = std::move(new_args); -} - -Datadog::ConfigVec -Datadog::LibraryConfig::generate_config(bool debug_logs) -{ - // Build process info struct - ddog_ProcessInfo process_info{ - .args = to_char_slice(_args), - .envp = to_char_slice(_envp), - .language = DDOG_CHARSLICE_C("python"), - }; - - // Build config struct - ddog_Configurator *configurator = ddog_library_configurator_new(debug_logs); - - // Compute configs - ddog_Result_VecLibraryConfig config_result = ddog_library_configurator_get(configurator, process_info); - - // Check for errors - if (config_result.tag == DDOG_RESULT_VEC_LIBRARY_CONFIG_ERR_VEC_LIBRARY_CONFIG) { - ddog_Error err = config_result.err; - if (debug_logs) { - auto ddog_err = ddog_Error_message(&err); - std::string err_msg; - std::cerr << err_msg.assign(ddog_err.ptr, ddog_err.ptr + ddog_err.len) << std::endl; - } - ddog_Error_drop(&err); - return Datadog::ConfigVec{}; - } - - // Format to new type - ddog_Vec_LibraryConfig configs = config_result.ok; - Datadog::ConfigVec result{ - .ptr = new Datadog::ConfigEntry[configs.len], - .len = configs.len, - }; - - for (size_t i = 0; i < configs.len; i++) { - const ddog_LibraryConfig *cfg = &configs.ptr[i]; - ddog_CStr name = ddog_library_config_name_to_env(cfg->name); - const ddog_CString value = cfg->value; - - Datadog::ConfigEntry* new_entry = new Datadog::ConfigEntry{ - .key = name.ptr, - .value = value.ptr, - }; - - // Add to result - result.ptr[i] = *new_entry; - }; - - return result; -} diff --git a/ddtrace/internal/datadog/profiling/dd_wrapper/src/library_config_interface.cpp b/ddtrace/internal/datadog/profiling/dd_wrapper/src/library_config_interface.cpp deleted file mode 100644 index 0d1bfe7676b..00000000000 --- a/ddtrace/internal/datadog/profiling/dd_wrapper/src/library_config_interface.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include -#include -#include - -// A global instance of the library config is created here. -Datadog::LibraryConfig libconfig; - -void -libraryconfig_set_args(const std::vector& args) // cppcheck-suppress unusedFunction -{ - libconfig.set_args(args); -} - -void -libraryconfig_set_envp(const std::vector& envp) // cppcheck-suppress unusedFunction -{ - libconfig.set_envp(envp); -} - -Datadog::ConfigVec -libraryconfig_generate_config(bool debug_logs) // cppcheck-suppress unusedFunction -{ - return libconfig.generate_config(debug_logs); -} diff --git a/ddtrace/internal/datadog/profiling/library_config/CMakeLists.txt b/ddtrace/internal/datadog/profiling/library_config/CMakeLists.txt deleted file mode 100644 index ea0ae7d8011..00000000000 --- a/ddtrace/internal/datadog/profiling/library_config/CMakeLists.txt +++ /dev/null @@ -1,77 +0,0 @@ -cmake_minimum_required(VERSION 3.19) - -# This builds a C-extension for Python using Cython and a native dependency. The exact name of the extension has -# consequences for the build path, which is in turn used by setup.py to build the wheel. Otherwise, we have to propagate -# a lot of state all around. Thus, we use the same name as the Python package (i.e., the caller sets EXTENSION_NAME) -# library_config is used by a default for standalone/test builds. -set(EXTENSION_NAME - "_library_config.so" - CACHE STRING "Name of the extension") -project(${EXTENSION_NAME}) -message(STATUS "Building extension: ${EXTENSION_NAME}") - -# Get the cmake modules for this project -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake") - -# Having a common target in a subdirectory like this is a hack and a mistake, but it's fiddly to change it so we haven't -# been able to. Instead, make sure that the binary path set in the subdirectory is stable *as a string* in order to make -# sure the caches work. -get_filename_component(DD_WRAPPER_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/../dd_wrapper_build ABSOLUTE) -add_subdirectory(../dd_wrapper ${DD_WRAPPER_BUILD_DIR}) - -find_package(Python3 COMPONENTS Interpreter Development) - -# Make sure we have necessary Python variables -if(NOT Python3_INCLUDE_DIRS) - message(FATAL_ERROR "Python3_INCLUDE_DIRS not found") -endif() - -# If we still don't have a Python executable, we can't continue -if(NOT Python3_EXECUTABLE) - message(FATAL_ERROR "Python executable not found") -endif() - -# This sets some parameters for the target build -set(ENV{PY_MAJOR_VERSION} ${Python3_VERSION_MAJOR}) -set(ENV{PY_MINOR_VERSION} ${Python3_VERSION_MINOR}) -set(ENV{PY_MICRO_VERSION} ${Python3_VERSION_PATCH}) - -# Cythonize the .pyx file -set(DDUP_CPP_SRC ${CMAKE_CURRENT_BINARY_DIR}/_library_config.cpp) -add_custom_command( - OUTPUT ${DDUP_CPP_SRC} - COMMAND ${Python3_EXECUTABLE} -m cython ${CMAKE_CURRENT_LIST_DIR}/_library_config.pyx -o ${DDUP_CPP_SRC} - DEPENDS ${CMAKE_CURRENT_LIST_DIR}/_library_config.pyx) - -# Specify the target C-extension that we want to build -add_library(${EXTENSION_NAME} SHARED ${DDUP_CPP_SRC}) - -add_ddup_config(${EXTENSION_NAME}) -# Cython generates code that produces errors for the following, so relax compile options -target_compile_options(${EXTENSION_NAME} PRIVATE -Wno-old-style-cast -Wno-shadow -Wno-address) - -# cmake may mutate the name of the library (e.g., lib- and -.so for dynamic libraries). This suppresses that behavior, -# which is required to ensure all paths can be inferred correctly by setup.py. -set_target_properties(${EXTENSION_NAME} PROPERTIES PREFIX "") -set_target_properties(${EXTENSION_NAME} PROPERTIES SUFFIX "") - -# RPATH is needed for sofile discovery at runtime, since Python packages are not installed in the system path. This is -# typical. -set_target_properties(${EXTENSION_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN/..") -target_include_directories(${EXTENSION_NAME} PRIVATE ../dd_wrapper/include ${Datadog_INCLUDE_DIRS} - ${Python3_INCLUDE_DIRS}) - -if(Python3_LIBRARIES) - target_link_libraries(${EXTENSION_NAME} PRIVATE dd_wrapper ${Python3_LIBRARIES}) -else() - target_link_libraries(${EXTENSION_NAME} PRIVATE dd_wrapper) -endif() - -# Set the output directory for the built library -if(LIB_INSTALL_DIR) - install( - TARGETS ${EXTENSION_NAME} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} - RUNTIME DESTINATION ${LIB_INSTALL_DIR}) -endif() diff --git a/ddtrace/internal/datadog/profiling/library_config/__init__.py b/ddtrace/internal/datadog/profiling/library_config/__init__.py deleted file mode 100644 index 09c392616b8..00000000000 --- a/ddtrace/internal/datadog/profiling/library_config/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# See ../ddup/__init__.py for some discussion on the is_available attribute. -# The configuration for this feature is handled in ddtrace/settings/crashtracker.py. -is_available = False -failure_msg = "" - - -def _default_return_false(*args, **kwargs): - return False - - -try: - from ._library_config import * # noqa: F403, F401 - is_available = True - -except Exception as e: - failure_msg = str(e) - - # Crashtracker is used early during startup, and so it must be robust across installations. - # Here we just stub everything. - def __getattr__(name): - if name == "failure_msg": - return failure_msg - if name == "is_available": - return False - return _default_return_false diff --git a/ddtrace/internal/datadog/profiling/library_config/_library_config.pyi b/ddtrace/internal/datadog/profiling/library_config/_library_config.pyi deleted file mode 100644 index ac912de423a..00000000000 --- a/ddtrace/internal/datadog/profiling/library_config/_library_config.pyi +++ /dev/null @@ -1,6 +0,0 @@ -from .._types import StringType, ValueType -from typing import Dict - -def set_args(args: list[str]) -> None: ... -def set_envp(args: list[str]) -> None: ... -def get_config(debug_logs: bool) -> Dict[str, ValueType]: ... diff --git a/ddtrace/internal/datadog/profiling/library_config/_library_config.pyx b/ddtrace/internal/datadog/profiling/library_config/_library_config.pyx deleted file mode 100644 index 0203607895f..00000000000 --- a/ddtrace/internal/datadog/profiling/library_config/_library_config.pyx +++ /dev/null @@ -1,56 +0,0 @@ -# distutils: language = c++ -# cython: language_level=3 -# Right now, this file lives in the profiling-internal directory even though the interface itself is not specific to -# profiling. This is because the config code is bundled in the libdatadog Profiling FFI, which saves a -# considerable amount of binary size, # and it's cumbersome to set an RPATH on that dependency from a different location - -import os - -from libcpp.vector cimport vector -from libcpp.string cimport string - -from .._types import StringType -from ..util import ensure_binary_or_empty -from typing import Dict - -cdef extern from "" namespace "std" nogil: - cdef cppclass string_view: - string_view(const char* s, size_t count) - -# For now, the config code is bundled in the libdatadog Profiling FFI. -# This is primarily to reduce binary size. -cdef extern from "library_config_interface.hpp" nogil: - void libraryconfig_set_envp(vector[string_view] envp) - void libraryconfig_set_args(vector[string_view] args) - ConfigVec libraryconfig_generate_config(bint debug_logs) - -cdef extern from "library_config.hpp" namespace "Datadog" nogil: - cdef struct ConfigEntry: - string key - string value - cdef struct ConfigVec: - bint len - ConfigEntry *ptr - - -def set_envp(envp: list[str]): - cdef vector[string_view] cpp_envp - envp_bytes = [ensure_binary_or_empty(env) for env in envp] - for env in envp_bytes: - cpp_envp.push_back(string_view(env, len(env))) - libraryconfig_set_envp(cpp_envp) - -def set_args(args: list[str]): - cdef vector[string_view] cpp_args - args_bytes = [ensure_binary_or_empty(arg) for arg in args] - for arg in args_bytes: - cpp_args.push_back(string_view(arg, len(arg))) - libraryconfig_set_args(cpp_args) - -def get_config(debug_logs: bool) -> Dict[StringType, StringType]: - cdef ConfigVec cpp_config = libraryconfig_generate_config(debug_logs) - result = {} - for i in range(cpp_config.len): - config_entry = cpp_config.ptr[i] - result[config_entry.key.decode('utf-8')] = config_entry.value.decode('utf-8') - return result diff --git a/setup.py b/setup.py index 726c271f485..06c9f6ef952 100644 --- a/setup.py +++ b/setup.py @@ -51,7 +51,6 @@ IAST_DIR = HERE / "ddtrace" / "appsec" / "_iast" / "_taint_tracking" DDUP_DIR = HERE / "ddtrace" / "internal" / "datadog" / "profiling" / "ddup" CRASHTRACKER_DIR = HERE / "ddtrace" / "internal" / "datadog" / "profiling" / "crashtracker" -LIBRARY_CONFIG_DIR = HERE / "ddtrace" / "internal" / "datadog" / "profiling" / "library_config" STACK_V2_DIR = HERE / "ddtrace" / "internal" / "datadog" / "profiling" / "stack_v2" BUILD_PROFILING_NATIVE_TESTS = os.getenv("DD_PROFILING_NATIVE_TESTS", "0").lower() in ("1", "yes", "on", "true") @@ -556,14 +555,6 @@ def get_exts_for(name): ) ) - ext_modules.append( - CMakeExtension( - "ddtrace.internal.datadog.profiling.library_config._library_config", - source_dir=LIBRARY_CONFIG_DIR, - optional=False, - ) - ) - # Echion doesn't build on 3.7, so just skip it outright for now if sys.version_info >= (3, 8) and sys.version_info < (3, 13): ext_modules.append( @@ -675,5 +666,12 @@ def get_exts_for(name): binding=Binding.PyO3, debug=os.getenv("_DD_RUSTC_DEBUG") == "1", ), + RustExtension( + "ddtrace.internal.config._config", + path="src/config/Cargo.toml", + py_limited_api="auto", + binding=Binding.PyO3, + debug=os.getenv("_DD_RUSTC_DEBUG") == "1", + ), ], ) diff --git a/src/config/Cargo.lock b/src/config/Cargo.lock new file mode 100644 index 00000000000..4f5c5ea9d9e --- /dev/null +++ b/src/config/Cargo.lock @@ -0,0 +1,272 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "datadog-library-config" +version = "0.0.1" +source = "git+https://github.com/DataDog/libdatadog?tag=v15.0.0#0ef49864317b0728648b2b7f26fe2f1deeeeebc4" +dependencies = [ + "anyhow", + "serde", + "serde_yaml", +] + +[[package]] +name = "ddtrace-config" +version = "0.1.0" +dependencies = [ + "datadog-library-config", + "pyo3", + "pyo3-build-config 0.21.2", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15ee168e30649f7f234c3d49ef5a7a6cbf5134289bc46c29ff3155fa3221c225" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config 0.22.3", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-build-config" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e61cef80755fe9e46bb8a0b8f20752ca7676dcc07a5277d8b7768c6172e529b3" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ce096073ec5405f5ee2b8b31f03a68e02aa10d5d4f565eca04acc41931fa1c" +dependencies = [ + "libc", + "pyo3-build-config 0.22.3", +] + +[[package]] +name = "pyo3-macros" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2440c6d12bc8f3ae39f1e775266fa5122fd0c8891ce7520fa6048e683ad3de28" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be962f0e06da8f8465729ea2cb71a416d2257dff56cbe40a70d3e62a93ae5d1" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config 0.22.3", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "syn" +version = "2.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" diff --git a/src/config/Cargo.toml b/src/config/Cargo.toml new file mode 100644 index 00000000000..91b2de82cfa --- /dev/null +++ b/src/config/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "ddtrace-config" +version = "0.1.0" +edition = "2021" + +[profile.release] +lto = true +strip = "debuginfo" +opt-level = 3 + +[dependencies] +pyo3 = { version = "0.22.3", features = ["extension-module"] } +datadog-library-config = { git = "https://github.com/DataDog/libdatadog", tag = "v15.0.0" } + +[build-dependencies] +pyo3-build-config = "0.21.2" + +[lib] +name = "_config" +path = "lib.rs" +crate-type = ["cdylib"] + + +[net] +# Use git binary from the system instead of the built-in git client +# "Setting this to true can be helpful if you have special authentication requirements that Cargo does not support." +git-fetch-with-cli = true diff --git a/src/config/lib.rs b/src/config/lib.rs new file mode 100644 index 00000000000..265cc2c3173 --- /dev/null +++ b/src/config/lib.rs @@ -0,0 +1,9 @@ +mod library_config; + +use pyo3::prelude::*; + +#[pymodule] +fn _config(m: &Bound<'_, PyModule>) -> PyResult<()> { + m.add_class::()?; + Ok(()) +} diff --git a/src/config/library_config.rs b/src/config/library_config.rs new file mode 100644 index 00000000000..a283aa7476c --- /dev/null +++ b/src/config/library_config.rs @@ -0,0 +1,64 @@ +use datadog_library_config::{Configurator, ProcessInfo}; +use pyo3::exceptions::PyException; +use pyo3::prelude::*; +use pyo3::types::PyDict; + +#[pyclass(name = "PyConfigurator", module = "ddtrace.internal._core")] +pub struct PyConfigurator { + configurator: Box, + envp: Vec, + args: Vec, +} + +#[pymethods] +impl PyConfigurator { + #[new] + pub fn new(debug_logs: bool) -> Self { + PyConfigurator { + configurator: Box::new(Configurator::new(debug_logs)), + envp: Vec::new(), + args: Vec::new(), + } + } + + pub fn set_envp(&mut self, envp: Vec) -> PyResult<()> { + self.envp = envp; + Ok(()) + } + + pub fn set_args(&mut self, args: Vec) -> PyResult<()> { + self.args = args; + Ok(()) + } + + pub fn get_configuration(&self, py: Python<'_>) -> PyResult { + let envp: Vec<&[u8]> = self.envp.iter().map(|s| s.as_bytes()).collect(); + let args: Vec<&[u8]> = self.args.iter().map(|s| s.as_bytes()).collect(); + + let process_info = ProcessInfo { + envp: &envp, + args: &args, + language: b"python", + }; + + let res_config = self.configurator.get_config_from_file( + "/etc/datadog-agent/managed/datadog-apm-libraries/stable/libraries_config.yaml" + .as_ref(), + process_info, + ); + match res_config { + Ok(config) => { + let dict = PyDict::new_bound(py); + for c in config.iter() { + let key = c.name.to_str().to_owned(); + let _ = dict.set_item(key, c.value.clone()); + } + Ok(dict.into()) + } + Err(e) => { + let err_msg = format!("Failed to get configuration: {:?}", e); + Err(PyException::new_err(err_msg)) + } + } + } +}