Skip to content

Commit 6776ca3

Browse files
committed
Address review comments; preserve final /
1 parent 98ee6e8 commit 6776ca3

20 files changed

+230
-190
lines changed

BUILD.bazel

Lines changed: 3 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",
@@ -99,6 +99,7 @@ cc_library(
9999
"include/datadog/event_scheduler.h",
100100
"include/datadog/expected.h",
101101
"include/datadog/http_client.h",
102+
"include/datadog/http_endpoint_calculation_mode.h",
102103
"include/datadog/id_generator.h",
103104
"include/datadog/injection_options.h",
104105
"include/datadog/logger.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
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
// This component provides an enumeration that controls how the http.endpoint
4+
// tag is calculated for HTTP spans.
5+
6+
#include <cstdint>
7+
8+
namespace datadog {
9+
namespace tracing {
10+
11+
// `HttpEndpointCalculationMode` determines when and how the http.endpoint tag
12+
// is inferred from http.url for HTTP spans.
13+
//
14+
// The http.endpoint tag provides a normalized, parameterized version of the
15+
// HTTP path (e.g., "/users/{param:int}" instead of "/users/123"). This helps
16+
// aggregate similar requests and reduce cardinality in monitoring systems.
17+
enum class HttpEndpointCalculationMode : std::uint8_t {
18+
// Do not calculate http.endpoint. The tag will not be set unless explicitly
19+
// provided by the user.
20+
DISABLED,
21+
22+
// Calculate http.endpoint from http.url only when http.route is not present.
23+
// This mode acts as a fallback - if instrumentation provides http.route,
24+
// use that; otherwise, infer http.endpoint from the URL path.
25+
FALLBACK,
26+
27+
// Always calculate http.endpoint from http.url, even when http.route is
28+
// present. Both tags will be set, allowing for comparison between
29+
// user-provided routes and automatically inferred endpoints.
30+
ALWAYS_CALCULATE,
31+
};
32+
33+
} // namespace tracing
34+
} // namespace datadog

include/datadog/trace_segment.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class TraceSegment {
8080

8181
std::shared_ptr<ConfigManager> config_manager_;
8282

83-
ResourceRenamingMode resource_renaming_mode_;
83+
HttpEndpointCalculationMode resource_renaming_mode_;
8484

8585
bool tracing_enabled_;
8686

@@ -100,7 +100,7 @@ class TraceSegment {
100100
Optional<std::string> additional_w3c_tracestate,
101101
Optional<std::string> additional_datadog_w3c_tracestate,
102102
std::unique_ptr<SpanData> local_root,
103-
ResourceRenamingMode resource_renaming_mode,
103+
HttpEndpointCalculationMode resource_renaming_mode,
104104
bool tracing_enabled = true);
105105

106106
const SpanDefaults& defaults() const;

include/datadog/tracer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Tracer {
5555
bool baggage_injection_enabled_;
5656
bool baggage_extraction_enabled_;
5757
bool tracing_enabled_;
58-
ResourceRenamingMode resource_renaming_mode_;
58+
HttpEndpointCalculationMode resource_renaming_mode_;
5959

6060
public:
6161
// Create a tracer configured using the specified `config`, and optionally:

include/datadog/tracer_config.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clock.h"
1616
#include "datadog_agent_config.h"
1717
#include "expected.h"
18+
#include "http_endpoint_calculation_mode.h"
1819
#include "propagation_style.h"
1920
#include "runtime_id.h"
2021
#include "span_defaults.h"
@@ -189,12 +190,6 @@ struct TracerConfig {
189190
Optional<bool> resource_renaming_always_simplified_endpoint;
190191
};
191192

192-
enum class ResourceRenamingMode : std::uint8_t {
193-
DISABLED,
194-
FALLBACK, // only if http.route is not present
195-
ALWAYS_CALCULATE,
196-
};
197-
198193
// `FinalizedTracerConfig` contains `Tracer` implementation details derived from
199194
// a valid `TracerConfig` and accompanying environment.
200195
// `FinalizedTracerConfig` must be obtained by calling `finalize_config`.
@@ -233,7 +228,7 @@ class FinalizedTracerConfig final {
233228
std::shared_ptr<EventScheduler> event_scheduler;
234229
std::shared_ptr<HTTPClient> http_client;
235230
bool tracing_enabled;
236-
ResourceRenamingMode resource_renaming_mode;
231+
HttpEndpointCalculationMode resource_renaming_mode;
237232
};
238233

239234
// Return a `FinalizedTracerConfig` from the specified `config` and from any

src/datadog/endpoint_guessing.h

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 25 additions & 25 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,17 @@ 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
60-
}
61+
inline uint8_t bool2mask(bool x) { return x ? 0xFF : 0x00; }
6162

62-
component_type component_replacement(std::string_view path) noexcept {
63+
component_type component_replacement(StringView path) noexcept {
6364
// viable_components is a bitset of the component types not yet excluded
6465
std::uint8_t viable_components = 0x1F; // (is_str << 1) - 1
6566
bool found_special_char = false;
@@ -121,31 +122,26 @@ component_type component_replacement(std::string_view path) noexcept {
121122
}
122123
} // namespace
123124

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-
125+
std::string infer_endpoint(StringView path) {
126+
// Expects a clean path without query string (e.g., "/api/users/123")
133127
if (path.empty() || path.front() != '/') {
134128
return "/";
135129
}
136130

137131
std::string result{};
138132
size_t component_count = 0;
133+
bool final_slash = true;
139134

140-
path.remove_prefix(1);
135+
path.remove_prefix(1); // drop the leading '/'
141136
while (!path.empty()) {
142137
auto slash_pos = path.find('/');
143138

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

146-
// remove current component from the path
147-
if (slash_pos == std::string_view::npos) {
148-
path = std::string_view{};
141+
// remove current component from the path (for the next iteration)
142+
if (slash_pos == StringView::npos) {
143+
path = StringView{};
144+
final_slash = false;
149145
} else {
150146
path.remove_prefix(slash_pos + 1);
151147
}
@@ -173,6 +169,10 @@ std::string guess_endpoint(std::string_view orig_path) {
173169
return "/";
174170
}
175171

172+
if (final_slash) {
173+
result.append("/");
174+
}
175+
176176
return result;
177177
}
178178

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+
} // namespace datadog::tracing

0 commit comments

Comments
 (0)