Skip to content

Commit e5d5bec

Browse files
committed
Address review comments; preserve final /
1 parent 1f2f760 commit e5d5bec

15 files changed

+180
-167
lines changed

BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ cc_library(
1717
"src/datadog/datadog_agent_config.cpp",
1818
"src/datadog/datadog_agent.cpp",
1919
"src/datadog/default_http_client_null.cpp",
20-
"src/datadog/endpoint_guessing.cpp",
20+
"src/datadog/endpoint_inferral.cpp",
2121
"src/datadog/environment.cpp",
2222
"src/datadog/error.cpp",
2323
"src/datadog/extraction_util.cpp",
@@ -61,7 +61,7 @@ cc_library(
6161
"src/datadog/datadog_agent.h",
6262
"src/datadog/default_http_client.h",
6363
"src/datadog/extracted_data.h",
64-
"src/datadog/endpoint_guessing.h",
64+
"src/datadog/endpoint_inferral.h",
6565
"src/datadog/extraction_util.h",
6666
"src/datadog/glob.h",
6767
"src/datadog/hex.h",

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ target_sources(dd-trace-cpp-objects
173173
src/datadog/collector_response.cpp
174174
src/datadog/datadog_agent_config.cpp
175175
src/datadog/datadog_agent.cpp
176-
src/datadog/endpoint_guessing.cpp
176+
src/datadog/endpoint_inferral.cpp
177177
src/datadog/environment.cpp
178178
src/datadog/error.cpp
179179
src/datadog/extraction_util.cpp

include/datadog/http_client.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class HTTPClient {
2626
std::string scheme; // http, https, or unix
2727
std::string authority; // domain:port or /path/to/socket
2828
std::string path; // resource, e.g. /v0.4/traces
29+
std::string query; // query string without '?'
2930

3031
static Expected<HTTPClient::URL> parse(StringView input);
3132
};

src/datadog/endpoint_guessing.h

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "endpoint_guessing.h"
1+
#include "endpoint_inferral.h"
22

33
#include <cstdint>
44

@@ -8,14 +8,14 @@ namespace {
88

99
constexpr size_t MAX_COMPONENTS = 8;
1010

11-
inline constexpr bool is_digit(char c) noexcept { return c >= '0' && c <= '9'; }
12-
inline constexpr bool is_hex_alpha(char c) noexcept {
11+
inline constexpr bool is_digit(char c) { return c >= '0' && c <= '9'; }
12+
inline constexpr bool is_hex_alpha(char c) {
1313
return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
1414
}
15-
inline constexpr bool is_delim(char c) noexcept {
15+
inline constexpr bool is_delim(char c) {
1616
return c == '.' || c == '_' || c == '-';
1717
}
18-
inline constexpr bool is_str_special(char c) noexcept {
18+
inline constexpr bool is_str_special(char c) {
1919
return c == '%' || c == '&' || c == '\'' || c == '(' || c == ')' ||
2020
c == '*' || c == '+' || c == ',' || c == ':' || c == '=' || c == '@';
2121
}
@@ -38,7 +38,7 @@ enum component_type : std::uint8_t {
3838
is_str = 1 << 4,
3939
};
4040

41-
std::string_view to_string(component_type type) noexcept {
41+
StringView to_string(component_type type) {
4242
switch (type) {
4343
case component_type::is_int:
4444
return "{param:int}";
@@ -50,16 +50,19 @@ std::string_view to_string(component_type type) noexcept {
5050
return "{param:hex_id}";
5151
case component_type::is_str:
5252
return "{param:str}";
53-
default:
53+
case component_type::none:
54+
// should not be reached
5455
return "";
5556
}
57+
// should never reach here
58+
return "";
5659
}
5760

58-
inline uint8_t bool2mask(bool x) noexcept {
59-
return static_cast<uint8_t>(-int{x}); // 0 -> 0x00, 1 -> 0xFF
61+
inline uint8_t bool2mask(bool x) {
62+
return x ? 0xFF : 0x00;
6063
}
6164

62-
component_type component_replacement(std::string_view path) noexcept {
65+
component_type component_replacement(StringView path) noexcept {
6366
// viable_components is a bitset of the component types not yet excluded
6467
std::uint8_t viable_components = 0x1F; // (is_str << 1) - 1
6568
bool found_special_char = false;
@@ -121,31 +124,26 @@ component_type component_replacement(std::string_view path) noexcept {
121124
}
122125
} // namespace
123126

124-
std::string guess_endpoint(std::string_view orig_path) {
125-
auto path = orig_path;
126-
127-
// remove the query string if any
128-
auto query_pos = path.find('?');
129-
if (query_pos != std::string_view::npos) {
130-
path = path.substr(0, query_pos);
131-
}
132-
127+
std::string infer_endpoint(StringView path) {
128+
// Expects a clean path without query string (e.g., "/api/users/123")
133129
if (path.empty() || path.front() != '/') {
134130
return "/";
135131
}
136132

137133
std::string result{};
138134
size_t component_count = 0;
135+
bool final_slash = true;
139136

140-
path.remove_prefix(1);
137+
path.remove_prefix(1); // drop the leading '/'
141138
while (!path.empty()) {
142139
auto slash_pos = path.find('/');
143140

144-
std::string_view component = path.substr(0, slash_pos);
141+
StringView component = path.substr(0, slash_pos);
145142

146-
// remove current component from the path
147-
if (slash_pos == std::string_view::npos) {
148-
path = std::string_view{};
143+
// remove current component from the path (for the next iteration)
144+
if (slash_pos == StringView::npos) {
145+
path = StringView{};
146+
final_slash = false;
149147
} else {
150148
path.remove_prefix(slash_pos + 1);
151149
}
@@ -173,6 +171,10 @@ std::string guess_endpoint(std::string_view orig_path) {
173171
return "/";
174172
}
175173

174+
if (final_slash) {
175+
result.append("/");
176+
}
177+
176178
return result;
177179
}
178180

src/datadog/endpoint_inferral.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include <datadog/string_view.h>
4+
5+
#include <string>
6+
7+
namespace datadog::tracing {
8+
9+
// Infer the endpoint pattern from a URL path by replacing parameters with
10+
// placeholders like {param:int}, {param:hex}, etc.
11+
//
12+
// The input should be a clean path without query string (e.g.,
13+
// "/api/users/123"). URL parsing should be handled by the caller using
14+
// HTTPClient::URL::parse().
15+
std::string infer_endpoint(StringView path);
16+
17+
}

src/datadog/http_client.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Expected<HTTPClient::URL> HTTPClient::URL::parse(StringView input) {
6161
std::move(message)};
6262
}
6363
return HTTPClient::URL{std::string(scheme), std::string(authority_and_path),
64-
""};
64+
"", ""};
6565
}
6666

6767
// The scheme is either "http" or "https". This means that the part after
@@ -70,12 +70,25 @@ Expected<HTTPClient::URL> HTTPClient::URL::parse(StringView input) {
7070
// the Datadog Agent service, and so they will not have a resource
7171
// location. Still, let's parse it properly.
7272
const auto after_authority = authority_and_path.find('/');
73+
74+
std::string path;
75+
std::string query;
76+
if (after_authority != StringView::npos) {
77+
StringView path_and_query = authority_and_path.substr(after_authority);
78+
const auto query_pos = path_and_query.find('?');
79+
if (query_pos != StringView::npos) {
80+
path = std::string(path_and_query.substr(0, query_pos));
81+
query = std::string(path_and_query.substr(query_pos + 1));
82+
} else {
83+
path = std::string(path_and_query);
84+
}
85+
}
86+
7387
return HTTPClient::URL{
7488
std::string(scheme),
7589
std::string(authority_and_path.substr(0, after_authority)),
76-
(after_authority == StringView::npos)
77-
? ""
78-
: std::string(authority_and_path.substr(after_authority))};
90+
std::move(path),
91+
std::move(query)};
7992
}
8093

8194
} // namespace tracing

src/datadog/tags.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ const std::string span_type = "span.type";
1010
const std::string operation_name = "operation";
1111
const std::string resource_name = "resource.name";
1212
const std::string version = "version";
13+
const std::string http_endpoint = "http.endpoint";
14+
const std::string http_route = "http.route";
15+
const std::string http_url = "http.url";
1316

1417
namespace internal {
1518

@@ -30,9 +33,6 @@ const std::string process_id = "process_id";
3033
const std::string language = "language";
3134
const std::string runtime_id = "runtime-id";
3235
const std::string w3c_parent_id = "_dd.parent_id";
33-
const std::string http_endpoint = "http.endpoint";
34-
const std::string http_route = "http.route";
35-
const std::string http_url = "http.url";
3636
const std::string trace_source = "_dd.p.ts";
3737
const std::string apm_enabled = "_dd.apm.enabled";
3838
const std::string ksr = "_dd.p.ksr";

src/datadog/tags.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ extern const std::string span_type;
1919
extern const std::string operation_name;
2020
extern const std::string resource_name;
2121
extern const std::string version;
22+
extern const std::string http_endpoint;
23+
extern const std::string http_route;
24+
extern const std::string http_url;
2225

2326
namespace internal {
2427
extern const std::string propagation_error;
@@ -38,9 +41,6 @@ extern const std::string process_id;
3841
extern const std::string language;
3942
extern const std::string runtime_id;
4043
extern const std::string w3c_parent_id;
41-
extern const std::string http_endpoint;
42-
extern const std::string http_route;
43-
extern const std::string http_url;
4444
extern const std::string trace_source; // _dd.p.ts
4545
extern const std::string apm_enabled; // _dd.apm.enabled
4646
extern const std::string ksr; // _dd.p.ksr

src/datadog/trace_segment.cpp

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <datadog/dict_reader.h>
33
#include <datadog/dict_writer.h>
44
#include <datadog/error.h>
5+
#include <datadog/http_client.h>
56
#include <datadog/injection_options.h>
67
#include <datadog/logger.h>
78
#include <datadog/optional.h>
@@ -18,7 +19,7 @@
1819
#include <vector>
1920

2021
#include "config_manager.h"
21-
#include "endpoint_guessing.h"
22+
#include "endpoint_inferral.h"
2223
#include "hex.h"
2324
#include "platform_util.h"
2425
#include "span_data.h"
@@ -254,33 +255,22 @@ void TraceSegment::span_finished() {
254255
// c) http.url is set, and
255256
// d) http.route is not set or resource_renaming_mode is ALWAYS_CALCULATE
256257
if (resource_renaming_mode_ != ResourceRenamingMode::DISABLED &&
257-
local_root.tags.find(tags::internal::http_endpoint) ==
258+
local_root.tags.find(tags::http_endpoint) ==
258259
local_root.tags.end()) {
259-
auto http_url_tag = local_root.tags.find(tags::internal::http_url);
260+
auto http_url_tag = local_root.tags.find(tags::http_url);
260261
const bool should_calculate_endpoint =
261262
http_url_tag != local_root.tags.end() &&
262263
(resource_renaming_mode_ == ResourceRenamingMode::ALWAYS_CALCULATE ||
263-
local_root.tags.find(tags::internal::http_route) ==
264+
local_root.tags.find(tags::http_route) ==
264265
local_root.tags.end());
265266

266267
if (should_calculate_endpoint) {
267-
// extract just the path from the http.url for endpoint guessing
268-
// http.url format is: scheme://host:port/path?query
269-
std::string_view path = http_url_tag->second;
270-
271-
auto scheme_end = path.find("://");
272-
if (scheme_end != std::string_view::npos) {
273-
path.remove_prefix(scheme_end + 3); // skip scheme and ://
274-
auto path_start = path.find('/');
275-
if (path_start != std::string_view::npos) {
276-
path.remove_prefix(path_start);
277-
} else {
278-
path = "/";
279-
}
280-
281-
// query string is ignored by guess_endpoint
282-
283-
local_root.tags[tags::internal::http_endpoint] = guess_endpoint(path);
268+
Expected<HTTPClient::URL> url_result =
269+
HTTPClient::URL::parse(http_url_tag->second);
270+
if (url_result.has_value()) {
271+
const std::string& path = url_result->path;
272+
local_root.tags[tags::http_endpoint] =
273+
infer_endpoint(path.empty() ? "/" : path);
284274
}
285275
}
286276
}

0 commit comments

Comments
 (0)