-
Notifications
You must be signed in to change notification settings - Fork 15
feat: support origin detection #214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fdb6393
6274290
d7086f7
e1463ae
e48984d
29f6a50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,3 +53,4 @@ services: | |
| - DD_APM_ENABLED=true | ||
| - DD_LOG_LEVEL=ERROR | ||
| - DOCKER_HOST | ||
| - DD_SITE | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
|
|
||
| #include "default_http_client.h" | ||
| #include "parse_util.h" | ||
| #include "platform_util.h" | ||
| #include "threaded_event_scheduler.h" | ||
|
|
||
| namespace datadog { | ||
|
|
@@ -144,6 +145,12 @@ Expected<FinalizedDatadogAgentConfig> finalize_config( | |
| result.metadata[ConfigName::AGENT_URL] = | ||
| ConfigMetadata(ConfigName::AGENT_URL, url, origin); | ||
|
|
||
| /// Starting Agent X, the admission controller inject a unique identifier | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| /// through `DD_EXTERNAL_ENV`. This uid is used for origin detection. | ||
| if (auto external_env = lookup(environment::DD_EXTERNAL_ENV)) { | ||
| result.admission_controller_uid = std::string(*external_env); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,8 @@ | ||||||||||
| #include "platform_util.h" | ||||||||||
|
|
||||||||||
| #include <cstdint> | ||||||||||
| #include <fstream> | ||||||||||
|
|
||||||||||
| // clang-format off | ||||||||||
| #if defined(__x86_64__) || defined(_M_X64) | ||||||||||
| # define DD_SDK_CPU_ARCH "x86_64" | ||||||||||
|
|
@@ -24,11 +27,13 @@ | |||||||||
| # define DD_SDK_OS "GNU/Linux" | ||||||||||
| # define DD_SDK_KERNEL "Linux" | ||||||||||
| # include "string_util.h" | ||||||||||
| # include <errno.h> | ||||||||||
| # include <fstream> | ||||||||||
| # include <fcntl.h> | ||||||||||
| # include <sys/types.h> | ||||||||||
| # include <sys/mman.h> | ||||||||||
| # include <fcntl.h> | ||||||||||
| # include <errno.h> | ||||||||||
| # include <sys/stat.h> | ||||||||||
| # include <sys/statfs.h> | ||||||||||
| # endif | ||||||||||
| #elif defined(_MSC_VER) | ||||||||||
| # include <windows.h> | ||||||||||
|
|
@@ -281,5 +286,126 @@ Expected<InMemoryFile> InMemoryFile::make(StringView) { | |||||||||
| } | ||||||||||
| #endif | ||||||||||
|
|
||||||||||
| namespace container { | ||||||||||
| namespace { | ||||||||||
| #if defined(__linux__) || defined(__unix__) | ||||||||||
| /// Magic numbers from linux/magic.h: | ||||||||||
| /// <https://github.com/torvalds/linux/blob/ca91b9500108d4cf083a635c2e11c884d5dd20ea/include/uapi/linux/magic.h#L71> | ||||||||||
| constexpr uint64_t CGROUP_SUPER_MAGIC = 0x27e0eb; | ||||||||||
| constexpr uint64_t CGROUP2_SUPER_MAGIC = 0x63677270; | ||||||||||
|
|
||||||||||
| /// Magic number from linux/proc_ns.h: | ||||||||||
| /// <https://github.com/torvalds/linux/blob/5859a2b1991101d6b978f3feb5325dad39421f29/include/linux/proc_ns.h#L41-L49> | ||||||||||
| constexpr ino_t HOST_CGROUP_NAMESPACE_INODE = 0xeffffffb; | ||||||||||
|
|
||||||||||
| /// Represents the cgroup version of the current process. | ||||||||||
| enum class Cgroup : char { v1, v2 }; | ||||||||||
|
|
||||||||||
| Optional<ino_t> get_inode(std::string_view path) { | ||||||||||
| struct stat buf; | ||||||||||
| if (stat(path.data(), &buf) != 0) { | ||||||||||
| return nullopt; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return buf.st_ino; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Host namespace inode number are hardcoded, which allows for dectection of | ||||||||||
| // whether the binary is running in host or not. However, it does not work when | ||||||||||
| // running in a Docker in Docker environment. | ||||||||||
| bool is_running_in_host_namespace() { | ||||||||||
| // linux procfs file that represents the cgroup namespace of the current | ||||||||||
| // process. | ||||||||||
| if (auto inode = get_inode("/proc/self/ns/cgroup")) { | ||||||||||
| return *inode == HOST_CGROUP_NAMESPACE_INODE; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return false; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| Optional<Cgroup> get_cgroup_version() { | ||||||||||
| struct statfs buf; | ||||||||||
|
|
||||||||||
| if (statfs("/sys/fs/cgroup", &buf) != 0) { | ||||||||||
| return nullopt; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (buf.f_type == CGROUP_SUPER_MAGIC) | ||||||||||
| return Cgroup::v1; | ||||||||||
| else if (buf.f_type == CGROUP2_SUPER_MAGIC) | ||||||||||
| return Cgroup::v2; | ||||||||||
|
|
||||||||||
| return nullopt; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| Optional<std::string> find_docker_container_id_from_cgroup() { | ||||||||||
dmehala marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| auto cgroup_fd = std::ifstream("/proc/self/cgroup", std::ios::in); | ||||||||||
| if (!cgroup_fd.is_open()) return nullopt; | ||||||||||
|
|
||||||||||
| return find_docker_container_id(cgroup_fd); | ||||||||||
| } | ||||||||||
| #endif | ||||||||||
| } // namespace | ||||||||||
|
|
||||||||||
| Optional<std::string> find_docker_container_id(std::istream& source) { | ||||||||||
dubloom marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's litterally mentionned in the header file: dd-trace-cpp/src/datadog/platform_util.h Line 88 in 29f6a50
|
||||||||||
| constexpr std::string_view docker_str = "docker-"; | ||||||||||
|
|
||||||||||
| std::string line; | ||||||||||
| while (std::getline(source, line)) { | ||||||||||
| // Example: | ||||||||||
| // `0::/system.slice/docker-abcdef0123456789abcdef0123456789.scope` | ||||||||||
| if (auto beg = line.find(docker_str); beg != std::string::npos) { | ||||||||||
| beg += docker_str.size(); | ||||||||||
| auto end = line.find(".scope", beg); | ||||||||||
| if (end == std::string::npos || end - beg <= 0) { | ||||||||||
| continue; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| auto container_id = line.substr(beg, end - beg); | ||||||||||
| return container_id; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return nullopt; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| Optional<ContainerID> get_id() { | ||||||||||
| #if defined(__linux__) || defined(__unix__) | ||||||||||
| if (is_running_in_host_namespace()) { | ||||||||||
| // Not in a container, no need to continue. | ||||||||||
| return nullopt; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| auto maybe_cgroup = get_cgroup_version(); | ||||||||||
| if (!maybe_cgroup) return nullopt; | ||||||||||
|
|
||||||||||
| ContainerID id; | ||||||||||
| switch (*maybe_cgroup) { | ||||||||||
| case Cgroup::v1: { | ||||||||||
| if (auto maybe_id = find_docker_container_id_from_cgroup()) { | ||||||||||
dubloom marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| id.value = *maybe_id; | ||||||||||
| id.type = ContainerID::Type::container_id; | ||||||||||
| break; | ||||||||||
| } | ||||||||||
| } | ||||||||||
| // NOTE(@dmehala): failed to find the container ID, try getting the cgroup | ||||||||||
| // inode. | ||||||||||
| [[fallthrough]]; | ||||||||||
| case Cgroup::v2: { | ||||||||||
| if (auto maybe_inode = get_inode("/sys/fs/cgroup")) { | ||||||||||
| id.type = ContainerID::Type::cgroup_inode; | ||||||||||
| id.value = std::to_string(*maybe_inode); | ||||||||||
| } | ||||||||||
| }; break; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return id; | ||||||||||
| #else | ||||||||||
| return nullopt; | ||||||||||
| #endif | ||||||||||
| } | ||||||||||
|
|
||||||||||
| } // namespace container | ||||||||||
|
|
||||||||||
| } // namespace tracing | ||||||||||
| } // namespace datadog | ||||||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will be annoying but that would be cool to add documentation somewhere on how to use that (if it is supposed to be used by devs).
It does not need to be in that PR.