Skip to content
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

remote config: more code review comments #83

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ cc_library(
"src/datadog/tags.cpp",
"src/datadog/threaded_event_scheduler.cpp",
"src/datadog/tracer_config.cpp",
"src/datadog/tracer_signature.cpp",
"src/datadog/tracer_telemetry.cpp",
"src/datadog/tracer.cpp",
"src/datadog/trace_id.cpp",
Expand Down Expand Up @@ -102,10 +103,10 @@ cc_library(
"src/datadog/tags.h",
"src/datadog/threaded_event_scheduler.h",
"src/datadog/tracer_config.h",
"src/datadog/tracer_signature.h",
"src/datadog/tracer_telemetry.h",
"src/datadog/tracer.h",
"src/datadog/trace_id.h",
"src/datadog/tracer_id.h",
"src/datadog/trace_sampler_config.h",
"src/datadog/trace_sampler.h",
"src/datadog/trace_segment.h",
Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ target_sources(dd_trace_cpp-objects PRIVATE
src/datadog/tags.cpp
src/datadog/threaded_event_scheduler.cpp
src/datadog/tracer_config.cpp
src/datadog/tracer_signature.cpp
src/datadog/tracer_telemetry.cpp
src/datadog/tracer.cpp
src/datadog/trace_id.cpp
Expand Down Expand Up @@ -208,10 +209,10 @@ target_sources(dd_trace_cpp-objects PUBLIC
src/datadog/tags.h
src/datadog/threaded_event_scheduler.h
src/datadog/tracer_config.h
src/datadog/tracer_signature.h
src/datadog/tracer_telemetry.h
src/datadog/tracer.h
src/datadog/trace_id.h
src/datadog/tracer_id.h
src/datadog/trace_sampler_config.h
src/datadog/trace_sampler.h
src/datadog/trace_segment.h
Expand Down
2 changes: 2 additions & 0 deletions src/datadog/config_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "config_manager.h"

#include "trace_sampler.h"

namespace datadog {
namespace tracing {

Expand Down
7 changes: 5 additions & 2 deletions src/datadog/config_update.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#pragma once

// TODO: Document

#include "optional"
#include "trace_sampler.h"
#include "trace_sampler_config.h"

namespace datadog {
namespace tracing {

// TODO: Document
struct ConfigUpdate {
Optional<TraceSamplerConfig> trace_sampler;
};
Expand Down
18 changes: 9 additions & 9 deletions src/datadog/datadog_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ std::variant<CollectorResponse, std::string> parse_agent_traces_response(
DatadogAgent::DatadogAgent(
const FinalizedDatadogAgentConfig& config,
const std::shared_ptr<TracerTelemetry>& tracer_telemetry,
const std::shared_ptr<Logger>& logger, const TracerID& tracer_id,
ConfigManager& config_manager)
const std::shared_ptr<Logger>& logger,
const TracerSignature& tracer_signature, ConfigManager& config_manager)
: tracer_telemetry_(tracer_telemetry),
clock_(config.clock),
logger_(logger),
Expand All @@ -164,7 +164,7 @@ DatadogAgent::DatadogAgent(
flush_interval_(config.flush_interval),
request_timeout_(config.request_timeout),
shutdown_timeout_(config.shutdown_timeout),
remote_config_(tracer_id, config_manager) {
remote_config_(tracer_signature, config_manager) {
assert(logger_);
assert(tracer_telemetry_);
if (tracer_telemetry_->enabled()) {
Expand Down Expand Up @@ -401,12 +401,11 @@ void DatadogAgent::get_and_apply_remote_configuration_updates() {
std::string response_body) {
if (response_status < 200 || response_status >= 300) {
if (response_status == 404) {
/*
* 404 is not considered as an error as the agent use it to
* signal remote configuration is disabled. At any point, the
* feature could be enabled, so the tracer must continuously check
* for new remote configuration.
*/
// If the Datadog Agent doesn't understand remote configuration,
// or if remote configuration is disabled in the agent, then it
// will return 404. This is not an error.
// We'll keep polling, though, because the agent's configuration
// might change.
return;
}

Expand All @@ -431,6 +430,7 @@ void DatadogAgent::get_and_apply_remote_configuration_updates() {
return;
}

// TODO(@dgoffredo): When is the parsed JSON object empty?
if (!response_json.empty()) {
// TODO (during Active Configuration): `process_response` should
// return a list of configuration update and should be consumed by
Expand Down
4 changes: 2 additions & 2 deletions src/datadog/datadog_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class FinalizedDatadogAgentConfig;
class Logger;
struct SpanData;
class TraceSampler;
struct TracerID;
class TracerSignature;

class DatadogAgent : public Collector {
public:
Expand Down Expand Up @@ -65,7 +65,7 @@ class DatadogAgent : public Collector {
public:
DatadogAgent(const FinalizedDatadogAgentConfig&,
const std::shared_ptr<TracerTelemetry>&,
const std::shared_ptr<Logger>&, const TracerID& id,
const std::shared_ptr<Logger>&, const TracerSignature& id,
ConfigManager& config_manager);
~DatadogAgent();

Expand Down
18 changes: 9 additions & 9 deletions src/datadog/remote_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ ConfigUpdate parse_dynamic_config(const nlohmann::json& j) {
} // namespace

RemoteConfigurationManager::RemoteConfigurationManager(
const TracerID& tracer_id, ConfigManager& config_manager)
: tracer_id_(tracer_id),
const TracerSignature& tracer_signature, ConfigManager& config_manager)
: tracer_signature_(tracer_signature),
config_manager_(config_manager),
client_id_(uuid()) {}

Expand All @@ -87,11 +87,11 @@ nlohmann::json RemoteConfigurationManager::make_request_payload() {
{"is_tracer", true},
{"capabilities", k_apm_capabilities},
{"client_tracer", {
{"runtime_id", tracer_id_.runtime_id.string()},
{"language", "cpp"},
{"tracer_version", tracer_version},
{"service", tracer_id_.service},
{"env", tracer_id_.environment}
{"runtime_id", tracer_signature_.runtime_id().string()},
{"language", tracer_signature_.library_language()},
{"tracer_version", tracer_signature_.library_version()},
{"service", tracer_signature_.default_service()},
{"env", tracer_signature_.default_environment()}
}},
{"state", {
{"root_version", 1},
Expand Down Expand Up @@ -178,9 +178,9 @@ void RemoteConfigurationManager::process_response(const nlohmann::json& json) {

const auto& targeted_service = config_json.at("service_target");
if (targeted_service.at("service").get<StringView>() !=
tracer_id_.service ||
tracer_signature_.default_service() ||
targeted_service.at("env").get<StringView>() !=
tracer_id_.environment) {
tracer_signature_.default_environment()) {
continue;
}

Expand Down
15 changes: 12 additions & 3 deletions src/datadog/remote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,53 @@
#include "runtime_id.h"
#include "string_view.h"
#include "trace_sampler_config.h"
#include "tracer_id.h"
#include "tracer_signature.h"

namespace datadog {
namespace tracing {

class RemoteConfigurationManager {
// TODO: document
struct State {
uint64_t targets_version = 1;
std::string opaque_backend_state;
Optional<std::string> error_message;
};

// TODO: document
struct Configuration {
std::string id;
std::string hash;
std::size_t version;
ConfigUpdate content;
};

TracerID tracer_id_;
TracerSignature tracer_signature_;
ConfigManager& config_manager_;
// TODO: document
std::string client_id_;

State state_;
// TODO: document
std::unordered_map<std::string, Configuration> applied_config_;

public:
RemoteConfigurationManager(const TracerID& tracer_id,
RemoteConfigurationManager(const TracerSignature& tracer_signature,
ConfigManager& config_manager);

// TODO: document
nlohmann::json make_request_payload();

// TODO: document
void process_response(const nlohmann::json& json);

private:
// TODO: document
bool is_new_config(StringView config_path, const nlohmann::json& config_meta);

// TODO: document
void apply_config(Configuration config);
// TODO: document
void revert_config(Configuration config);
};

Expand Down
12 changes: 7 additions & 5 deletions src/datadog/tracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "tags.h"
#include "trace_sampler.h"
#include "trace_segment.h"
#include "tracer_id.h"
#include "tracer_signature.h"
#include "version.h"
#include "w3c_propagation.h"

Expand All @@ -40,9 +40,10 @@ Tracer::Tracer(const FinalizedTracerConfig& config,
defaults_(std::make_shared<SpanDefaults>(config.defaults)),
runtime_id_(config.runtime_id ? *config.runtime_id
: RuntimeID::generate()),
id_{runtime_id_, config.defaults.service, config.defaults.environment},
signature_{runtime_id_, config.defaults.service,
config.defaults.environment},
tracer_telemetry_(std::make_shared<TracerTelemetry>(
config.report_telemetry, config.clock, logger_, id_)),
config.report_telemetry, config.clock, logger_, signature_)),
span_sampler_(
std::make_shared<SpanSampler>(config.span_sampler, config.clock)),
generator_(generator),
Expand All @@ -59,8 +60,9 @@ Tracer::Tracer(const FinalizedTracerConfig& config,
auto& agent_config =
std::get<FinalizedDatadogAgentConfig>(config.collector);

auto agent = std::make_shared<DatadogAgent>(
agent_config, tracer_telemetry_, config.logger, id_, config_manager_);
auto agent = std::make_shared<DatadogAgent>(agent_config, tracer_telemetry_,
config.logger, signature_,
config_manager_);
collector_ = agent;

if (tracer_telemetry_->enabled()) {
Expand Down
4 changes: 2 additions & 2 deletions src/datadog/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "optional.h"
#include "span.h"
#include "tracer_config.h"
#include "tracer_signature.h"
#include "tracer_telemetry.h"

namespace datadog {
Expand All @@ -28,14 +29,13 @@ class DictReader;
struct SpanConfig;
class TraceSampler;
class SpanSampler;
struct TracerID;

class Tracer {
std::shared_ptr<Logger> logger_;
std::shared_ptr<Collector> collector_;
std::shared_ptr<const SpanDefaults> defaults_;
RuntimeID runtime_id_;
TracerID id_;
TracerSignature signature_;
std::shared_ptr<TracerTelemetry> tracer_telemetry_;
std::shared_ptr<SpanSampler> span_sampler_;
std::shared_ptr<const IDGenerator> generator_;
Expand Down
16 changes: 0 additions & 16 deletions src/datadog/tracer_id.h

This file was deleted.

33 changes: 33 additions & 0 deletions src/datadog/tracer_signature.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "tracer_signature.h"

#include "version.h"

namespace datadog {
namespace tracing {

TracerSignature::TracerSignature(const RuntimeID& runtime_id,
const std::string& default_service,
const std::string& default_environment)
: runtime_id_(runtime_id),
default_service_(default_service),
default_environment_(default_environment) {}

const RuntimeID& TracerSignature::runtime_id() const { return runtime_id_; }

StringView TracerSignature::default_service() const { return default_service_; }

StringView TracerSignature::default_environment() const {
return default_environment_;
}

StringView TracerSignature::library_version() const { return tracer_version; }

StringView TracerSignature::library_language() const { return "cpp"; }

StringView TracerSignature::library_language_version() const {
static const std::string value = std::to_string(__cplusplus);
return value;
}

} // namespace tracing
} // namespace datadog
63 changes: 63 additions & 0 deletions src/datadog/tracer_signature.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

// This component provides a class, `TracerSignature`, that contains the parts
// of a tracer's configuration that are used to refer to the tracer in Datadog's
// telemetry and remote configuration APIs.
//
// `TracerSignature` is used in three contexts:
//
// 1. When telemetry is sent to the Datadog Agent, the tracer signature is
// included in the request payload. See
// `TracerTelemetry::generate_telemetry_body` in `tracer_telemetry.cpp`.
// 2. When the Datadog Agent is polled for configuration updates, part of the
// tracer signature (all but the language version) is included in the request
// payload. See `RemoteConfigurationManager::make_request_payload` in
// `remote_config.h`.
// 3. When the Datadog Agent responds with configuration updates, the service
// and environment of the tracer signature are used to determine whether the
// updates are relevant to the `Tracer` that created the collector that is
// polling the Datadog Agent. See
// `RemoteConfigurationManager::process_response` in `remote_config.h`.

#include <string>

#include "runtime_id.h"
#include "string_view.h"

namespace datadog {
namespace tracing {

class TracerSignature {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it have to be a class with getter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the two (well, more than two) JSON payloads that use service, environment, and runtime_id, I saw that library language, library version, and library language version (all constants) were also there on an equal footing. Who's to say that those are not also part of the signature?

So, either I would keep it a struct having only the three fields, and leave the code that pulls the other values from the appropriate constants; or, I could wrap those constants into the type. I chose the latter, but am not committed to the idea.

I justified it to myself by saying "this makes the notion of a tracer signature more substantial."

Copy link
Collaborator

@dmehala dmehala Jan 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a third option where it's still a struct or class but with all fields accessible:

struct TracerSignature {
  RuntimeID runtime_id_;
  std::string default_service_;
  std::string default_environment_;
  StringView library_version = tracer_version;
  StringView library_language = "cpp";
  StringView library_version = __cplusplus;

  TracerSignature() = delete;
  TracerSignature(const RuntimeID& runtime_id, ...) : runtime_id(runtime_id) ... {}
};

Copy link
Contributor Author

@dgoffredo dgoffredo Jan 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works.

__cplusplus is an integer literal, though.

Options that I considered:

  1. Just use std::string. That would work.
  2. Use the preprocessor to stringify __cplusplus. This works, but then you get a trailing "L" due to the definition of the __cplusplus token. :(
  3. Use member functions. :D

It also ever so slightly bothers me that library_* as data members implies that the values might mutate, when in actuality they never will. Maybe this is an indication that it's not such a good idea to put them in TraceSignature after all.

const data members aren't worth the trouble, seeing how they disable assignments and moves, though that might not matter for TracerSignature's usage.

Anything will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect. Will replace substr with:

std::string_view version = std::string_view{STRINGIFY(__cplusplus), 6};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::string_view version = "most likely 201703";

Copy link
Collaborator

@dmehala dmehala Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static_assert(__cplusplus == 201703L);
std::string_view version = "201703";

😈

if constexpr(__cplusplus == "199711") {
   constexpr std::string_view version = "199711";
} else if constexpr(__cplusplus == "201103") {
   constexpr std::string_view version = "201103";
}
...

I have no idea if it compiles.

RuntimeID runtime_id_;
std::string default_service_;
std::string default_environment_;

public:
// Create a tracer signature having the specified `runtime_id`,
// `default_service`, and `default_environment`. `default_service` and
// `default_environment` refer to the corresponding fields from
// `SpanDefaults`.
TracerSignature(const RuntimeID& runtime_id,
const std::string& default_service,
const std::string& default_environment);

// Return the runtime ID with which the tracer was configured.
const RuntimeID& runtime_id() const;
// Return the `SpanDefaults::service` with which the tracer was configured.
StringView default_service() const;
// Return the `SpanDefaults::environment` with which the tracer was
// configured.
StringView default_environment() const;
// Return the version of this tracing library (`tracer_version` from
// `version.h`).
StringView library_version() const;
// Return the name of the programming language in which this library is
// written: "cpp".
StringView library_language() const;
// Return the version of C++ standard used to compile this library. It should
// be "201703".
StringView library_language_version() const;
};

} // namespace tracing
} // namespace datadog
Loading