Skip to content
Open
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
7 changes: 0 additions & 7 deletions appsec/src/extension/commands/client_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,6 @@ static void _process_meta_and_metrics(

mpack_node_t metrics = mpack_node_array_at(root, 4);
dd_command_process_metrics(metrics, span);

// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
if (mpack_node_array_length(root) >= 6) {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
mpack_node_t tel_metrics = mpack_node_array_at(root, 5);
dd_command_process_telemetry_metrics(tel_metrics);
}
}

static dd_result _check_helper_version(mpack_node_t root)
Expand Down
6 changes: 5 additions & 1 deletion appsec/src/extension/commands/request_shutdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ static const char *nullable _header_content_type_zend_array(
static const dd_command_spec _spec = {
.name = "request_shutdown",
.name_len = sizeof("request_shutdown") - 1,
.num_args = 3, // a map, api sec sampling key, and sidecar queue id
.num_args =
4, // a map, api sec sampling key, sidecar queue id, and input_truncated
.outgoing_cb = _request_pack,
.incoming_cb = dd_command_proc_resp_verd_span_data,
.config_features_cb = dd_command_process_config_features_unexpected,
Expand Down Expand Up @@ -101,6 +102,9 @@ static dd_result _request_pack(mpack_writer_t *nonnull w, void *nonnull ctx)
// 3.
mpack_write(w, dd_trace_get_sidecar_queue_id());

// 4.
mpack_write_bool(w, dd_msgpack_helpers_is_data_truncated());

return dd_success;
}

Expand Down
141 changes: 0 additions & 141 deletions appsec/src/extension/commands_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@
#include <mpack.h>
#include <stdatomic.h>

static const char WAF_REQUEST_METRIC[] = "waf.requests";
static const size_t WAF_REQUEST_METRIC_LEN = sizeof(WAF_REQUEST_METRIC) - 1;
static const char TRUNCATED_TAG[] = "input_truncated=true";
static const size_t TRUNCATED_TAG_LEN = sizeof(TRUNCATED_TAG);
static const char TAG_SEPARATOR = ',';
static const size_t TAG_SEPARATOR_LEN = sizeof(TAG_SEPARATOR);

typedef struct _dd_omsg {
zend_llist iovecs;
mpack_writer_t writer;
Expand Down Expand Up @@ -508,8 +501,6 @@ static void dd_command_process_settings(mpack_node_t root);
* 2: [force keep: bool]
* 3: [meta: map]
* 4: [metrics: map]
* 5: [telemetry metrics: map string ->
* array(array(value: double, tags: string)])
* )
*/
#define RESP_INDEX_ACTION_PARAMS 0
Expand All @@ -518,7 +509,6 @@ static void dd_command_process_settings(mpack_node_t root);
#define RESP_INDEX_SETTINGS 3
#define RESP_INDEX_SPAN_META 4
#define RESP_INDEX_SPAN_METRICS 5
#define RESP_INDEX_TELEMETRY_METRICS 6

dd_result dd_command_proc_resp_verd_span_data(
mpack_node_t root, void *unspecnull _ctx)
Expand Down Expand Up @@ -557,11 +547,6 @@ dd_result dd_command_proc_resp_verd_span_data(
dd_command_process_metrics(metrics, span);
}

if (mpack_node_array_length(root) >= RESP_INDEX_TELEMETRY_METRICS + 1) {
dd_command_process_telemetry_metrics(
mpack_node_array_at(root, RESP_INDEX_TELEMETRY_METRICS));
}

return res;
}

Expand Down Expand Up @@ -795,132 +780,6 @@ bool dd_command_process_metrics(mpack_node_t root, zend_object *nonnull span)
return true;
}

static void _handle_telemetry_metric(const char *nonnull key_str,
size_t key_len, double value, const char *nonnull tags_str,
size_t tags_len);

bool dd_command_process_telemetry_metrics(mpack_node_t metrics)
{
if (mpack_node_type(metrics) != mpack_type_map) {
return false;
}

if (!ddtrace_metric_register_buffer) {
mlog_g(dd_log_debug, "ddtrace_metric_register_buffer unavailable");
return true;
}

for (size_t i = 0; i < mpack_node_map_count(metrics); i++) {
mpack_node_t key = mpack_node_map_key_at(metrics, i);

const char *key_str = mpack_node_str(key);
if (!key_str) {
continue;
}

size_t key_len = mpack_node_strlen(key);
mpack_node_t arr_value = mpack_node_map_value_at(metrics, i);

for (size_t j = 0; j < mpack_node_array_length(arr_value); j++) {
mpack_node_t value = mpack_node_array_at(arr_value, j);
mpack_node_t dval_node = mpack_node_array_at(value, 0);
double dval = mpack_node_double(dval_node);

const char *tags_str = "";
char *modified_tags_str = NULL;
size_t tags_len = 0;
if (mpack_node_array_length(value) >= 2) {
mpack_node_t tags = mpack_node_array_at(value, 1);
tags_str = mpack_node_str(tags);
tags_len = mpack_node_strlen(tags);
}
if (mpack_node_error(metrics) != mpack_ok) {
break;
}
if (dd_msgpack_helpers_is_data_truncated() &&
WAF_REQUEST_METRIC_LEN == key_len &&
memcmp(WAF_REQUEST_METRIC, key_str, WAF_REQUEST_METRIC_LEN) ==
0) {
size_t separator = 0;
if (tags_len > 0) {
separator = TAG_SEPARATOR_LEN;
}
modified_tags_str =
emalloc(tags_len + TRUNCATED_TAG_LEN + 1 + separator);
if (modified_tags_str) {
memcpy(modified_tags_str, tags_str, tags_len);
if (separator > 0) {
modified_tags_str[tags_len] = TAG_SEPARATOR;
}
memcpy(modified_tags_str + tags_len + separator,
TRUNCATED_TAG, TRUNCATED_TAG_LEN);
tags_len += TRUNCATED_TAG_LEN + separator;
tags_str = modified_tags_str;
}
}

_handle_telemetry_metric(
key_str, key_len, dval, tags_str, tags_len);
if (modified_tags_str) {
efree(modified_tags_str);
}
}
}

return true;
}

static void _init_zstr(
zend_string *_Atomic *nonnull zstr, const char *nonnull str, size_t len)
{
zend_string *zstr_cur = atomic_load_explicit(zstr, memory_order_acquire);
if (zstr_cur != NULL) {
return;
}
zend_string *zstr_new = zend_string_init(str, len, 1);
if (atomic_compare_exchange_strong_explicit(zstr, &(zend_string *){NULL},
zstr_new, memory_order_release, memory_order_relaxed)) {
return;
}
zend_string_release(zstr_new);
}

// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
void _handle_telemetry_metric(const char *nonnull key_str, size_t key_len,
double value, const char *nonnull tags_str, size_t tags_len)
{
#define HANDLE_METRIC(name, type) \
do { \
if (key_len == LSTRLEN(name) && memcmp(key_str, name, key_len) == 0) { \
static zend_string *_Atomic key_zstr; \
_init_zstr(&key_zstr, name, LSTRLEN(name)); \
zend_string *tags_zstr = zend_string_init(tags_str, tags_len, 0); \
dd_telemetry_add_metric(key_zstr, value, tags_zstr, type); \
zend_string_release(tags_zstr); \
mlog_g(dd_log_debug, \
"Telemetry metric %.*s added with tags %.*s and value %f", \
(int)key_len, key_str, (int)tags_len, tags_str, value); \
return; \
} \
} while (0)

HANDLE_METRIC("waf.requests", DDTRACE_METRIC_TYPE_COUNT);
HANDLE_METRIC("waf.updates", DDTRACE_METRIC_TYPE_COUNT);
HANDLE_METRIC("waf.init", DDTRACE_METRIC_TYPE_COUNT);
HANDLE_METRIC("waf.config_errors", DDTRACE_METRIC_TYPE_COUNT);

HANDLE_METRIC("remote_config.first_pull", DDTRACE_METRIC_TYPE_GAUGE);
HANDLE_METRIC("remote_config.last_success", DDTRACE_METRIC_TYPE_GAUGE);

// Rasp
HANDLE_METRIC("rasp.timeout", DDTRACE_METRIC_TYPE_COUNT);
HANDLE_METRIC("rasp.rule.match", DDTRACE_METRIC_TYPE_COUNT);
HANDLE_METRIC("rasp.rule.eval", DDTRACE_METRIC_TYPE_COUNT);
HANDLE_METRIC("rasp.error", DDTRACE_METRIC_TYPE_COUNT);

mlog_g(dd_log_info, "Unknown telemetry metric %.*s", (int)key_len, key_str);
}

static void _dump_in_msg(
dd_log_level_t lvl, const char *nonnull data, size_t data_len)
{
Expand Down
1 change: 0 additions & 1 deletion appsec/src/extension/commands_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ dd_result dd_command_proc_resp_verd_span_data(mpack_node_t root,
/* Common helpers */
void dd_command_process_meta(mpack_node_t root, zend_object *nonnull span);
bool dd_command_process_metrics(mpack_node_t root, zend_object *nonnull span);
bool dd_command_process_telemetry_metrics(mpack_node_t root);
dd_result dd_command_process_config_features(
mpack_node_t root, ATTR_UNUSED void *nullable ctx);
dd_result dd_command_process_config_features_unexpected(
Expand Down
73 changes: 41 additions & 32 deletions appsec/src/helper/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
#include "action.hpp"
#include "client.hpp"
#include "exception.hpp"
#include "metrics.hpp"
#include "network/broker.hpp"
#include "network/proto.hpp"
#include "service.hpp"
#include "service_config.hpp"
#include "std_logging.hpp"
#include "telemetry.hpp"

using namespace std::chrono_literals;

Expand All @@ -27,9 +27,11 @@ namespace dds {
namespace {

void collect_metrics(network::request_shutdown::response &response,
service &service, std::optional<engine::context> &context);
service &service, std::optional<engine::context> &context,
const sidecar_settings &sc_settings);
void collect_metrics(network::client_init::response &response, service &service,
std::optional<engine::context> &context);
std::optional<engine::context> &context,
const sidecar_settings &sc_settings);

template <typename M, typename... Mrest>
// NOLINTNEXTLINE(google-runtime-references)
Expand Down Expand Up @@ -195,9 +197,9 @@ bool client::handle_command(const network::client_init::request &command)
response->status = has_errors ? "fail" : "ok";
response->errors = std::move(errors);

if (service_) {
if (!service_.is_empty()) {
// may be null in testing
collect_metrics(*response, *service_, context_);
collect_metrics(*response, *service_, context_, sc_settings_);
}

try {
Expand All @@ -218,7 +220,7 @@ bool client::handle_command(const network::client_init::request &command)

template <typename T> bool client::service_guard()
{
if (!service_) {
if (service_.is_empty()) {
// This implies a failed client_init, we can't continue.
SPDLOG_DEBUG("no service available on {}", T::name);
send_error_response(*broker_);
Expand Down Expand Up @@ -349,7 +351,7 @@ bool client::compute_client_status()
return request_enabled_;
}

if (service_ == nullptr) {
if (service_.is_empty()) {
request_enabled_ = false;
return request_enabled_;
}
Expand Down Expand Up @@ -470,7 +472,9 @@ bool client::handle_command(network::request_shutdown::request &command)
return false;
}

collect_metrics(*response, *service_, context_);
context_->set_input_truncated(command.input_truncated);

collect_metrics(*response, *service_, context_, sc_settings_);
service_->drain_logs(sc_settings_);

return send_message<network::request_shutdown>(response);
Expand Down Expand Up @@ -503,8 +507,6 @@ void client::update_settings(
rc_settings.shmem_path = std::string{rc_path};
}

sidecar_settings const current_sc_settings =
service_->get_sidecar_settings();
std::shared_ptr<service> new_service =
service_manager_->get_or_create_service(
*engine_settings_, rc_settings, telemetry_settings);
Expand Down Expand Up @@ -552,7 +554,9 @@ void client::run(worker::queue_consumer &q)
namespace {

struct request_metrics_submitter : public telemetry::telemetry_submitter {
request_metrics_submitter() = default;
request_metrics_submitter(service &svc, bool input_truncated)
: service_{svc}, input_truncated_{input_truncated}
{}
~request_metrics_submitter() override = default;
request_metrics_submitter(const request_metrics_submitter &) = delete;
request_metrics_submitter &operator=(
Expand All @@ -563,16 +567,18 @@ struct request_metrics_submitter : public telemetry::telemetry_submitter {
void submit_metric(std::string_view name, double value,
telemetry::telemetry_tags tags) override
{
std::string tags_s = tags.consume();
if (input_truncated_ && name == metrics::waf_requests) {
tags.add("input_truncated", "true");
}
SPDLOG_TRACE("submit_metric [req]: name={}, value={}, tags={}", name,
value, tags_s);
tel_metrics[name].emplace_back(value, std::move(tags_s));
value, tags);
service_.submit_request_metric(name, value, std::move(tags));
};
void submit_span_metric(std::string_view name, double value) override
{
SPDLOG_TRACE(
"submit_span_metric [req]: name={}, value={}", name, value);
metrics[name] = value;
span_metrics[name] = value;
};
void submit_span_meta(std::string_view name, std::string value) override
{
Expand All @@ -596,39 +602,42 @@ struct request_metrics_submitter : public telemetry::telemetry_submitter {
}

std::map<std::string, std::string> meta;
std::map<std::string_view, double> metrics;
std::unordered_map<std::string_view,
std::vector<std::pair<double, std::string>>>
tel_metrics;
std::map<std::string_view, double> span_metrics;
service &service_; // NOLINT
bool input_truncated_;
};

template <typename Response>
void collect_metrics_impl(Response &response, service &service,
std::optional<engine::context> &context)
std::optional<engine::context> &context,
const sidecar_settings &sc_settings)
{
request_metrics_submitter msubmitter{};
request_metrics_submitter msubmitter{
service, context ? context->get_input_truncated() : false};
if (context) {
// span metrics/meta go to msubmitter.span_metrics/meta and are sent to
// the extension; request telemetry metrics are routed to the service
// and sent to sidecar
context->get_metrics(msubmitter);
}
service.drain_metrics(
[&msubmitter](std::string_view name, double value, auto tags) {
msubmitter.submit_metric(name, value, std::move(tags));
});
msubmitter.metrics.merge(service.drain_legacy_metrics());

service.drain_metrics(sc_settings);
msubmitter.span_metrics.merge(service.drain_legacy_metrics());
msubmitter.meta.merge(service.drain_legacy_meta());
response.tel_metrics = std::move(msubmitter.tel_metrics);
response.meta = std::move(msubmitter.meta);
response.metrics = std::move(msubmitter.metrics);
response.metrics = std::move(msubmitter.span_metrics);
}
void collect_metrics(network::request_shutdown::response &response,
service &service, std::optional<engine::context> &context)
service &service, std::optional<engine::context> &context,
const sidecar_settings &sc_settings)
{
collect_metrics_impl(response, service, context);
collect_metrics_impl(response, service, context, sc_settings);
}
void collect_metrics(network::client_init::response &response, service &service,
std::optional<engine::context> &context)
std::optional<engine::context> &context,
const sidecar_settings &sc_settings)
{
collect_metrics_impl(response, service, context);
collect_metrics_impl(response, service, context, sc_settings);
}
} // namespace

Expand Down
Loading
Loading