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

feat: prom support drop metrics and external_labels #2018

Merged
merged 5 commits into from
Jan 8, 2025
Merged
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
15 changes: 15 additions & 0 deletions core/plugin/processor/inner/ProcessorPromRelabelMetricNative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ bool ProcessorPromRelabelMetricNative::ProcessEvent(PipelineEventPtr& e,
sourceEvent.DelTag(k);
}

for (const auto& [k, v] : mScrapeConfigPtr->mExternalLabels) {
if (sourceEvent.HasTag(k)) {
if (!mScrapeConfigPtr->mHonorLabels) {
// metric event labels is secondary
// if confiliction, then rename it exported_<label_name>
auto key = prometheus::EXPORTED_PREFIX + k;
auto b = sourceEvent.GetSourceBuffer()->CopyString(key);
sourceEvent.SetTagNoCopy(StringView(b.data, b.size), sourceEvent.GetTag(k));
sourceEvent.SetTagNoCopy(k, v);
}
} else {
sourceEvent.SetTagNoCopy(k, v);
}
}

// set metricEvent name
sourceEvent.SetTagNoCopy(prometheus::NAME, sourceEvent.GetName());

Expand Down
2 changes: 2 additions & 0 deletions core/prometheus/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const char* const SOURCE_LABELS = "source_labels";
const char* const SEPARATOR = "separator";
const char* const TARGET_LABEL = "target_label";
const char* const REGEX = "regex";
const char* const MATCH_LIST = "match_list";
const char* const REPLACEMENT = "replacement";
const char* const ACTION = "action";
const char* const MODULUS = "modulus";
Expand Down Expand Up @@ -78,6 +79,7 @@ const char* const KEY_FILE = "key_file";
const char* const SERVER_NAME = "server_name";
const char* const HOST = "Host";
const char* const INSECURE_SKIP_VERIFY = "insecure_skip_verify";
const char* const EXTERNAL_LABELS = "external_labels";

// scrape protocols, from https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config
// text/plain, application/openmetrics-text will be used
Expand Down
40 changes: 34 additions & 6 deletions core/prometheus/labels/Relabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@

#include <openssl/md5.h>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/regex.hpp>
#include <string>
#include <vector>

#include "boost/algorithm/string.hpp"
#include "boost/algorithm/string/join.hpp"
#include "boost/regex.hpp"

#include "common/ParamExtractor.h"
#include "common/StringTools.h"
#include "logger/Logger.h"
Expand All @@ -49,7 +48,8 @@ Action StringToAction(const string& action) {
STRING_TO_ENUM_CASE(LABELDROP),
STRING_TO_ENUM_CASE(LABELKEEP),
STRING_TO_ENUM_CASE(LOWERCASE),
STRING_TO_ENUM_CASE(UPPERCASE)};
STRING_TO_ENUM_CASE(UPPERCASE),
STRING_TO_ENUM_CASE(DROPMETRIC)};

auto it = sActionStrings.find(action);
if (it != sActionStrings.end()) {
Expand All @@ -69,7 +69,9 @@ const std::string& ActionToString(Action action) {
ENUM_TO_STRING_CASE(LABELDROP),
ENUM_TO_STRING_CASE(LABELKEEP),
ENUM_TO_STRING_CASE(LOWERCASE),
ENUM_TO_STRING_CASE(UPPERCASE)};
ENUM_TO_STRING_CASE(UPPERCASE),
ENUM_TO_STRING_CASE(DROPMETRIC)};

static string sUndefined = prometheus::UNDEFINED;
auto it = sActionStrings.find(action);
if (it != sActionStrings.end()) {
Expand Down Expand Up @@ -107,6 +109,26 @@ bool RelabelConfig::Init(const Json::Value& config) {
if (config.isMember(prometheus::ACTION) && config[prometheus::ACTION].isString()) {
string actionString = config[prometheus::ACTION].asString();
mAction = StringToAction(actionString);
} else {
LOG_ERROR(sLogger, ("no action specified", ""));
return false;
}

if (mAction == Action::DROPMETRIC) {
mSourceLabels.emplace_back(prometheus::NAME);
if (config.isMember(prometheus::MATCH_LIST) && config[prometheus::MATCH_LIST].isArray()) {
for (const auto& item : config[prometheus::MATCH_LIST]) {
if (item.isString()) {
mMatchList.insert(item.asString());
} else {
LOG_ERROR(sLogger, ("invalid match_list item", ""));
return false;
}
}
} else {
LOG_ERROR(sLogger, ("no match_list specified", ""));
return false;
}
}

if (config.isMember(prometheus::MODULUS) && config[prometheus::MODULUS].isUInt64()) {
Expand Down Expand Up @@ -219,6 +241,12 @@ bool RelabelConfig::Process(Labels& l, vector<string>& toDelete) const {
}
break;
}
case Action::DROPMETRIC: {
if (mMatchList.find(val) != mMatchList.end()) {
return false;
}
break;
}
default:
// error
LOG_ERROR(sLogger, ("relabel: unknown relabel action type", ActionToString(mAction)));
Expand Down
9 changes: 6 additions & 3 deletions core/prometheus/labels/Relabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
*/

#pragma once
#include <string>
#include <json/json.h>

#include "boost/regex.hpp"
#include "json/json.h"
#include <boost/regex.hpp>
#include <string>

#include "prometheus/labels/Labels.h"

Expand All @@ -36,6 +36,7 @@ enum class Action {
LABELKEEP,
LOWERCASE,
UPPERCASE,
DROPMETRIC,
UNDEFINED
};

Expand Down Expand Up @@ -65,6 +66,8 @@ class RelabelConfig {
// Action is the action to be performed for the relabeling.
Action mAction;

std::set<std::string> mMatchList;

private:
void CollectLabelsToDelete(const std::string& labelName, std::vector<std::string>& toDelete) const;
};
Expand Down
23 changes: 23 additions & 0 deletions core/prometheus/schedulers/ScrapeConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ bool ScrapeConfig::InitStaticConfig(const Json::Value& scrapeConfig) {
return false;
}
}

if (scrapeConfig.isMember(prometheus::EXTERNAL_LABELS)) {
if (!InitExternalLabels(scrapeConfig[prometheus::EXTERNAL_LABELS])) {
LOG_ERROR(sLogger, ("external labels config error", ""));
return false;
}
}
return true;
}

Expand Down Expand Up @@ -397,4 +404,20 @@ bool ScrapeConfig::InitTLSConfig(const Json::Value& tlsConfig) {
return true;
}

bool ScrapeConfig::InitExternalLabels(const Json::Value& externalLabels) {
if (!externalLabels.isObject()) {
LOG_ERROR(sLogger, ("external_labels config error", ""));
return false;
}
for (auto& key : externalLabels.getMemberNames()) {
if (externalLabels[key].isString()) {
mExternalLabels.emplace_back(key, externalLabels[key].asString());
} else {
LOG_ERROR(sLogger, ("external_labels config error", ""));
return false;
}
}
return true;
}

} // namespace logtail
3 changes: 3 additions & 0 deletions core/prometheus/schedulers/ScrapeConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class ScrapeConfig {

std::string mQueryString;

std::vector<std::pair<std::string, std::string>> mExternalLabels;

ScrapeConfig();
bool Init(const Json::Value& config);
bool InitStaticConfig(const Json::Value& config);
Expand All @@ -54,6 +56,7 @@ class ScrapeConfig {
bool InitScrapeProtocols(const Json::Value& scrapeProtocols);
void InitEnableCompression(bool enableCompression);
bool InitTLSConfig(const Json::Value& tlsConfig);
bool InitExternalLabels(const Json::Value& externalLabels);

#ifdef APSARA_UNIT_TEST_MAIN
friend class ScrapeConfigUnittest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ void ProcessorPromRelabelMetricNativeUnittest::TestProcess() {
],
"target_label": "__address__"
}
]
],
"external_labels": {
"test_key1": "test_value1",
"test_key2": "test_value2"
}
}
)";

Expand Down Expand Up @@ -151,6 +155,10 @@ test_metric8{k1="v1", k3="v2", } 9.9410452992e+10 1715829785083
APSARA_TEST_EQUAL("test_metric6", eventGroup.GetEvents().at(5).Cast<MetricEvent>().GetName());
APSARA_TEST_EQUAL("test_metric7", eventGroup.GetEvents().at(6).Cast<MetricEvent>().GetName());
// test_metric8 is dropped by relabel config

// check external labels
APSARA_TEST_EQUAL("test_value1", eventGroup.GetEvents().at(0).Cast<MetricEvent>().GetTag("test_key1"));
APSARA_TEST_EQUAL("test_value2", eventGroup.GetEvents().at(0).Cast<MetricEvent>().GetTag("test_key2"));
}

void ProcessorPromRelabelMetricNativeUnittest::TestAddAutoMetrics() {
Expand Down
27 changes: 27 additions & 0 deletions core/unittest/prometheus/RelabelUnittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class RelabelConfigUnittest : public testing::Test {
void TestReplace();
void TestKeep();
void TestDrop();
void TestDropMetric();
void TestDropEqual();
void TestHashMod();
void TestLabelDrop();
Expand Down Expand Up @@ -200,6 +201,31 @@ void RelabelConfigUnittest::TestDrop() {
APSARA_TEST_FALSE(configList.Process(result, toDelete));
}

void RelabelConfigUnittest::TestDropMetric() {
Json::Value configJson;
string configStr;
string errorMsg;
RelabelConfigList configList;
Labels labels;
labels.Set("__meta_kubernetes_pod_ip", "172.17.0.3");
labels.Set("__meta_kubernetes_pod_label_app", "node-exporter");
labels.Set("__name__", "node_cpu_seconds_total");
// single relabel drop
configStr = R"(
[{
"action": "dropmetric",
"match_list": ["test_1","node_cpu_seconds_total"]
}]
)";

APSARA_TEST_TRUE(ParseJsonTable(configStr, configJson, errorMsg));
configList = RelabelConfigList();
APSARA_TEST_TRUE(configList.Init(configJson));
auto result = labels;
vector<string> toDelete;
APSARA_TEST_FALSE(configList.Process(result, toDelete));
}

void RelabelConfigUnittest::TestDropEqual() {
Json::Value configJson;
string configStr;
Expand Down Expand Up @@ -495,6 +521,7 @@ UNIT_TEST_CASE(ActionConverterUnittest, TestActionToString)
UNIT_TEST_CASE(RelabelConfigUnittest, TestRelabelConfig)
UNIT_TEST_CASE(RelabelConfigUnittest, TestReplace)
UNIT_TEST_CASE(RelabelConfigUnittest, TestDrop)
UNIT_TEST_CASE(RelabelConfigUnittest, TestDropMetric)
UNIT_TEST_CASE(RelabelConfigUnittest, TestKeep)
UNIT_TEST_CASE(RelabelConfigUnittest, TestHashMod)
UNIT_TEST_CASE(RelabelConfigUnittest, TestLabelMap)
Expand Down
11 changes: 11 additions & 0 deletions core/unittest/prometheus/ScrapeConfigUnittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ void ScrapeConfigUnittest::TestInit() {
]
}
],
"external_labels": {
"test_key1": "test_value1",
"test_key2": "test_value2"
},
"params" : {
"__param_query": [
"test_query"
Expand Down Expand Up @@ -142,6 +146,13 @@ void ScrapeConfigUnittest::TestInit() {
APSARA_TEST_EQUAL(scrapeConfig.mRelabelConfigs.mRelabelConfigs.size(), 1UL);
APSARA_TEST_EQUAL(scrapeConfig.mParams["__param_query"][0], "test_query");
APSARA_TEST_EQUAL(scrapeConfig.mParams["__param_query_1"][0], "test_query_1");

// external labels
APSARA_TEST_EQUAL(scrapeConfig.mExternalLabels.size(), 2UL);
APSARA_TEST_EQUAL(scrapeConfig.mExternalLabels[0].first, "test_key1");
APSARA_TEST_EQUAL(scrapeConfig.mExternalLabels[0].second, "test_value1");
APSARA_TEST_EQUAL(scrapeConfig.mExternalLabels[1].first, "test_key2");
APSARA_TEST_EQUAL(scrapeConfig.mExternalLabels[1].second, "test_value2");
}

void ScrapeConfigUnittest::TestAuth() {
Expand Down
Loading