-
Notifications
You must be signed in to change notification settings - Fork 318
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
249 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
build:asan --strip=never | ||
build:asan --copt -fsanitize=address | ||
build:asan --copt -O0 | ||
build:asan --copt -fno-omit-frame-pointer | ||
build:asan --copt -g | ||
build:asan --linkopt -fsanitize=address |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,81 @@ | ||
#include <chrono> | ||
#include <sstream> | ||
#include <string> | ||
#include <thread> | ||
#include <sstream> | ||
|
||
#include <google/protobuf/io/zero_copy_stream_impl.h> | ||
#include <google/protobuf/io/coded_stream.h> | ||
#include <google/protobuf/io/zero_copy_stream_impl.h> | ||
|
||
#include "exposer.h" | ||
|
||
#include "cpp/metrics.pb.h" | ||
|
||
namespace prometheus { | ||
MetricsHandler::MetricsHandler( | ||
const std::vector<std::weak_ptr<Collectable>>& collectables, | ||
Registry& registry) | ||
: collectables_(collectables), | ||
bytesTransferedFamily_(registry.add_counter( | ||
"exposer_bytes_transfered", "bytesTransferred to metrics services", | ||
{{"component", "exposer"}})), | ||
bytesTransfered_(bytesTransferedFamily_->add({})), | ||
numScrapesFamily_(registry.add_counter( | ||
"exposer_total_scrapes", "Number of times metrics were scraped", | ||
{{"component", "exposer"}})), | ||
numScrapes_(numScrapesFamily_->add({})) {} | ||
|
||
bool MetricsHandler::handleGet(CivetServer* server, | ||
struct mg_connection* conn) { | ||
using namespace io::prometheus::client; | ||
|
||
std::ostringstream ss; | ||
for (auto&& wcollectable : collectables_) { | ||
auto collectable = wcollectable.lock(); | ||
if (!collectable) { | ||
continue; | ||
} | ||
|
||
class MetricsHandler : public CivetHandler { | ||
public: | ||
bool handleGet(CivetServer* server, struct mg_connection* conn) { | ||
using namespace io::prometheus::client; | ||
|
||
MetricFamily message; | ||
message.set_name("Foo"); | ||
message.set_help("Foo help"); | ||
message.set_type(MetricType::COUNTER); | ||
auto metric1 = message.add_metric(); | ||
auto counter = metric1->mutable_counter(); | ||
counter->set_value(1337.0); | ||
|
||
std::ostringstream ss; | ||
{ | ||
for (auto&& metricFamily : collectable->collect()) { | ||
{ | ||
google::protobuf::io::OstreamOutputStream rawOutput{&ss}; | ||
google::protobuf::io::CodedOutputStream output(&rawOutput); | ||
|
||
// Write the size. | ||
const int size = message.ByteSize(); | ||
const int size = metricFamily.ByteSize(); | ||
output.WriteVarint32(size); | ||
} | ||
} | ||
|
||
auto buf = ss.str(); | ||
message.AppendToString(&buf); | ||
mg_printf(conn, | ||
"HTTP/1.1 200 OK\r\n" | ||
"Content-Type: " | ||
"application/vnd.google.protobuf; " | ||
"proto=io.prometheus.client.MetricFamily; " | ||
"encoding=delimited\r\n" | ||
"Content-Length: "); | ||
mg_printf(conn, "%lu\r\n\r\n", buf.size()); | ||
mg_write(conn, buf.data(), buf.size()); | ||
return true; | ||
auto buffer = std::string{}; | ||
metricFamily.SerializeToString(&buffer); | ||
ss << buffer; | ||
} | ||
} | ||
}; | ||
|
||
auto body = ss.str(); | ||
mg_printf(conn, | ||
"HTTP/1.1 200 OK\r\n" | ||
"Content-Type: " | ||
"application/vnd.google.protobuf; " | ||
"proto=io.prometheus.client.MetricFamily; " | ||
"encoding=delimited\r\n" | ||
"Content-Length: "); | ||
mg_printf(conn, "%lu\r\n\r\n", body.size()); | ||
mg_write(conn, body.data(), body.size()); | ||
bytesTransfered_->inc(body.size()); | ||
numScrapes_->inc(); | ||
return true; | ||
} | ||
|
||
Exposer::Exposer(std::uint16_t port) | ||
: server_({"listening_ports", std::to_string(port)}) { | ||
MetricsHandler handler; | ||
server_.addHandler("/metrics", &handler); | ||
std::this_thread::sleep_for(std::chrono::seconds(60000)); | ||
: server_({"listening_ports", std::to_string(port)}), | ||
exposerRegistry_( | ||
std::make_shared<Registry>(std::map<std::string, std::string>{})), | ||
metricsHandler_(collectables_, *exposerRegistry_) { | ||
registerCollectable(exposerRegistry_); | ||
server_.addHandler("/metrics", &metricsHandler_); | ||
} | ||
|
||
void Exposer::run() {} | ||
void Exposer::registerCollectable( | ||
const std::weak_ptr<Collectable>& collectable) { | ||
collectables_.push_back(collectable); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,37 @@ | ||
#pragma once | ||
|
||
#include <atomic> | ||
#include <cstdint> | ||
#include <memory> | ||
|
||
#include "CivetServer.h" | ||
#include "registry.h" | ||
|
||
namespace prometheus { | ||
|
||
class Exposer { | ||
class MetricsHandler : public CivetHandler { | ||
public: | ||
Exposer(std::uint16_t port); | ||
void run(); | ||
private: | ||
CivetServer server_; | ||
MetricsHandler(const std::vector<std::weak_ptr<Collectable>>& collectables, | ||
Registry& registry); | ||
|
||
bool handleGet(CivetServer* server, struct mg_connection* conn); | ||
|
||
const std::vector<std::weak_ptr<Collectable>>& collectables_; | ||
Family<Counter>* bytesTransferedFamily_; | ||
Counter* bytesTransfered_; | ||
Family<Counter>* numScrapesFamily_; | ||
Counter* numScrapes_; | ||
}; | ||
|
||
class Exposer { | ||
public: | ||
Exposer(std::uint16_t port); | ||
void registerCollectable(const std::weak_ptr<Collectable>& collectable); | ||
|
||
private: | ||
CivetServer server_; | ||
std::vector<std::weak_ptr<Collectable>> collectables_; | ||
std::shared_ptr<Registry> exposerRegistry_; | ||
MetricsHandler metricsHandler_; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include "registry.h" | ||
|
||
namespace prometheus { | ||
|
||
Registry::Registry(const std::map<std::string, std::string>& constLabels) | ||
: constLabels_(constLabels) {} | ||
|
||
Family<Counter>* Registry::add_counter( | ||
const std::string& name, const std::string& help, | ||
const std::map<std::string, std::string>& labels) { | ||
auto counterFamily = new Family<Counter>(name, help, labels); | ||
collectables_.push_back(std::unique_ptr<Collectable>{counterFamily}); | ||
return counterFamily; | ||
} | ||
|
||
Family<Gauge>* Registry::add_gauge( | ||
const std::string& name, const std::string& help, | ||
const std::map<std::string, std::string>& labels) { | ||
auto gaugeFamily = new Family<Gauge>(name, help, labels); | ||
collectables_.push_back(std::unique_ptr<Collectable>{gaugeFamily}); | ||
return gaugeFamily; | ||
} | ||
|
||
std::vector<io::prometheus::client::MetricFamily> Registry::collect() { | ||
auto results = std::vector<io::prometheus::client::MetricFamily>{}; | ||
for(auto&& collectable : collectables_) { | ||
auto metrics = collectable->collect(); | ||
results.insert(results.end(), metrics.begin(), metrics.end()); | ||
} | ||
|
||
for (auto&& metricFamily : results) { | ||
for (auto&& metric : *metricFamily.mutable_metric()) { | ||
for (auto&& constLabelPair : constLabels_) { | ||
auto label = metric.add_label(); | ||
label->set_name(constLabelPair.first); | ||
label->set_value(constLabelPair.second); | ||
} | ||
} | ||
} | ||
|
||
return results; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#pragma once | ||
|
||
#include <map> | ||
|
||
#include "collectable.h" | ||
#include "cpp/metrics.pb.h" | ||
#include "family.h" | ||
|
||
namespace prometheus { | ||
|
||
class Counter; | ||
class Gauge; | ||
|
||
class Registry : public Collectable { | ||
public: | ||
Registry() = default; | ||
Registry(const std::map<std::string, std::string>& constLabels); | ||
Family<Counter>* add_counter( | ||
const std::string& name, const std::string& help, | ||
const std::map<std::string, std::string>& labels); | ||
Family<Gauge>* add_gauge(const std::string& name, const std::string& help, | ||
const std::map<std::string, std::string>& labels); | ||
|
||
// collectable | ||
std::vector<io::prometheus::client::MetricFamily> collect() override; | ||
|
||
private: | ||
std::vector<std::unique_ptr<Collectable>> collectables_; | ||
std::map<std::string, std::string> constLabels_; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#include <vector> | ||
|
||
#include <gmock/gmock.h> | ||
|
||
#include "lib/registry.h" | ||
#include "lib/collectable.h" | ||
|
||
using namespace testing; | ||
using namespace prometheus; | ||
|
||
class MockCollectable : public Collectable { | ||
public: | ||
MOCK_METHOD0(collect, std::vector<io::prometheus::client::MetricFamily>()); | ||
}; | ||
|
||
class RegistryTest : public Test {}; | ||
|
||
TEST_F(RegistryTest, collectsSingleMetricFamily) { | ||
auto registry = Registry{}; | ||
auto counterFamily = registry.add_counter("test", "a test", {}); | ||
counterFamily->add({{"name", "counter1"}}); | ||
counterFamily->add({{"name", "counter2"}}); | ||
auto collected = registry.collect(); | ||
ASSERT_EQ(collected.size(), 1); | ||
EXPECT_EQ(collected[0].name(), "test"); | ||
EXPECT_EQ(collected[0].help(), "a test"); | ||
ASSERT_EQ(collected[0].metric_size(), 2); | ||
ASSERT_EQ(collected[0].metric(0).label_size(), 1); | ||
EXPECT_EQ(collected[0].metric(0).label(0).name(), "name"); | ||
ASSERT_EQ(collected[0].metric(1).label_size(), 1); | ||
EXPECT_EQ(collected[0].metric(1).label(0).name(), "name"); | ||
} |
Oops, something went wrong.