Files

109 lines
3.6 KiB
C++

// Pure Metric JSON (de)serialization (no Libp2pModuleImpl, links without libp2p.so).
#include <logos_test.h>
#include <plugin.h>
#include <string>
using json = nlohmann::json;
LOGOS_TEST(metric_from_json_basic_fields) {
const auto j = json::parse(R"({
"name": "libp2p_peers",
"type": "gauge",
"help": "Number of connected peers",
"labels": [],
"value": 3,
"timestamp": 0
})");
const auto m = j.get<Metric>();
LOGOS_ASSERT_TRUE(m.name == "libp2p_peers");
LOGOS_ASSERT_TRUE(m.type == "gauge");
LOGOS_ASSERT_TRUE(m.help == "Number of connected peers");
LOGOS_ASSERT_EQ(m.value, 3.0);
LOGOS_ASSERT_TRUE(m.labels.empty());
LOGOS_ASSERT_EQ(m.timestamp, 0);
}
LOGOS_TEST(metric_from_json_flattens_label_pair_array) {
// cbind emits labels as a sequence of {name,value} pairs, but openmetrics-
// module's renderer wants a flat {key:value} object. Verify the flattening.
const auto j = json::parse(R"({
"name": "libp2p_open_streams",
"type": "gauge",
"help": "",
"labels": [
{"name": "dir", "value": "in"},
{"name": "proto", "value": "ping"}
],
"value": 4,
"timestamp": 0
})");
const auto m = j.get<Metric>();
LOGOS_ASSERT_EQ(m.labels.size(), 2u);
LOGOS_ASSERT_TRUE(m.labels.at("dir") == "in");
LOGOS_ASSERT_TRUE(m.labels.at("proto") == "ping");
}
LOGOS_TEST(metric_from_json_handles_missing_labels) {
const auto j = json::parse(R"({
"name": "x", "type": "gauge", "help": "", "value": 0
})");
const auto m = j.get<Metric>();
LOGOS_ASSERT_TRUE(m.labels.empty());
LOGOS_ASSERT_EQ(m.timestamp, 0);
}
LOGOS_TEST(metric_from_json_records_timestamp) {
const auto j = json::parse(R"({
"name": "x", "type": "gauge", "help": "",
"labels": [], "value": 1, "timestamp": 1700000000000
})");
const auto m = j.get<Metric>();
LOGOS_ASSERT_EQ(m.timestamp, 1700000000000);
}
LOGOS_TEST(metric_to_json_emits_labels_as_object) {
// openmetrics_format.cpp:82 requires labels.is_object(); round-trip must
// produce that shape, not the inbound array-of-pairs.
Metric m;
m.name = "libp2p_peers";
m.type = "gauge";
m.help = "Number of connected peers";
m.labels = {{"dir", "in"}};
m.value = 7;
const json j = m;
LOGOS_ASSERT_TRUE(j["labels"].is_object());
LOGOS_ASSERT_TRUE(j["labels"]["dir"].get<std::string>() == "in");
LOGOS_ASSERT_FALSE(j.contains("timestamp"));
}
LOGOS_TEST(metric_to_json_keeps_nonzero_timestamp) {
Metric m;
m.name = "x";
m.type = "gauge";
m.timestamp = 1700000000000;
const json j = m;
LOGOS_ASSERT_TRUE(j.contains("timestamp"));
LOGOS_ASSERT_EQ(j["timestamp"].get<int64_t>(), 1700000000000);
}
LOGOS_TEST(metric_array_round_trips_through_payload_shape) {
// End-to-end: take a cbind-shaped JSON array, parse it to vector<Metric>,
// wrap it as payload["metrics"], and check the result matches what
// openmetrics-module expects as input.
const auto in = json::parse(R"([
{"name":"libp2p_peers","type":"gauge","help":"peers",
"labels":[],"value":2,"timestamp":0},
{"name":"libp2p_failed_dials_total","type":"counter","help":"fails",
"labels":[{"name":"err","value":"timeout"}],"value":9,"timestamp":0}
])");
const auto series = in.get<std::vector<Metric>>();
json payload;
payload["metrics"] = series;
LOGOS_ASSERT_EQ(payload["metrics"].size(), 2u);
LOGOS_ASSERT_TRUE(payload["metrics"][1]["labels"].is_object());
LOGOS_ASSERT_TRUE(
payload["metrics"][1]["labels"]["err"].get<std::string>() == "timeout");
}