Files
doris/be/test/util/new_metrics_test.cpp
chenhao7253886 37b4cafe87 Change variable and namespace name in BE (#268)
Change 'palo' to 'doris'
2018-11-02 10:22:32 +08:00

298 lines
9.2 KiB
C++

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <gtest/gtest.h>
#include <iostream>
#include <thread>
#include "common/config.h"
#include "util/logging.h"
#include "util/metrics.h"
#include "util/stopwatch.hpp"
namespace doris {
class MetricsTest : public testing::Test {
public:
MetricsTest() { }
virtual ~MetricsTest() {
}
};
TEST_F(MetricsTest, Counter) {
{
IntCounter counter;
ASSERT_EQ(0, counter.value());
counter.increment(100);
ASSERT_EQ(100, counter.value());
ASSERT_STREQ("100", counter.to_string().c_str());
}
{
DoubleCounter counter;
ASSERT_EQ(0.0, counter.value());
counter.increment(1.23);
ASSERT_EQ(1.23, counter.value());
ASSERT_STREQ("1.23", counter.to_string().c_str());
}
}
void mt_updater(IntCounter* counter, std::atomic<uint64_t>* used_time) {
sleep(1);
MonotonicStopWatch watch;
watch.start();
for (int i = 0; i < 1000000L; ++i) {
counter->increment(1);
}
uint64_t elapsed = watch.elapsed_time();
used_time->fetch_add(elapsed);
}
TEST_F(MetricsTest, CounterPerf) {
IntCounter counter;
volatile int64_t sum = 0;
{
MonotonicStopWatch watch;
watch.start();
for (int i = 0; i < 100000000; ++i) {
counter.increment(1);
}
uint64_t elapsed = watch.elapsed_time();
LOG(INFO) << "counter elapsed: " << elapsed
<< "ns, ns/iter:" << elapsed / 100000000;
}
{
MonotonicStopWatch watch;
watch.start();
for (int i = 0; i < 100000000; ++i) {
sum += 1;
}
uint64_t elapsed = watch.elapsed_time();
LOG(INFO) << "value elapsed: " << elapsed
<< "ns, ns/iter:" << elapsed / 100000000;
}
ASSERT_EQ(100000000, counter.value());
ASSERT_EQ(100000000, sum);
{
IntCounter mt_counter;
std::vector<std::thread> updaters;
std::atomic<uint64_t> used_time(0);
for (int i = 0; i < 8; ++i) {
updaters.emplace_back(&mt_updater, &mt_counter, &used_time);
}
for (int i = 0; i < 8; ++i) {
updaters[i].join();
}
LOG(INFO) << "mt_counter elapsed: " << used_time.load()
<< "ns, ns/iter:" << used_time.load() / (8 * 1000000L);
ASSERT_EQ(8 * 1000000L, mt_counter.value());
}
}
TEST_F(MetricsTest, Gauge) {
{
IntGauge gauge;
ASSERT_EQ(0, gauge.value());
gauge.set_value(100);
ASSERT_EQ(100, gauge.value());
ASSERT_STREQ("100", gauge.to_string().c_str());
}
{
DoubleGauge gauge;
ASSERT_EQ(0.0, gauge.value());
gauge.set_value(1.23);
ASSERT_EQ(1.23, gauge.value());
ASSERT_STREQ("1.23", gauge.to_string().c_str());
}
}
TEST_F(MetricsTest, MetricLabel) {
std::string put("put");
MetricLabel label("type", put);
ASSERT_TRUE(label == MetricLabel("type", "put"));
ASSERT_TRUE(label != MetricLabel("type", "get"));
ASSERT_TRUE(label < MetricLabel("type", "quit"));
ASSERT_TRUE(label < MetricLabel("typee", "put"));
ASSERT_TRUE(label.compare(MetricLabel("type", "put")) == 0);
ASSERT_TRUE(label.compare(MetricLabel("typee", "put")) < 0);
ASSERT_STREQ("type=put", label.to_string().c_str());
}
TEST_F(MetricsTest, MetricLabels) {
MetricLabels empty_labels;
ASSERT_TRUE(empty_labels == MetricLabels());
ASSERT_TRUE(empty_labels < MetricLabels().add("type", "put"));
ASSERT_TRUE(empty_labels.empty());
ASSERT_STREQ("", empty_labels.to_string().c_str());
MetricLabels labels;
labels.add("path", "/home").add("type", "put");
ASSERT_TRUE(labels == MetricLabels().add("path", "/home").add("type", "put"));
ASSERT_FALSE(labels == MetricLabels().add("path", "/home").add("type", "get"));
ASSERT_FALSE(labels == MetricLabels().add("path", "/home"));
ASSERT_TRUE(labels < MetricLabels().add("path", "/sports"));
ASSERT_TRUE(labels < MetricLabels().add("path", "/home").add("type", "put").add("xstatus", "404"));
ASSERT_FALSE(labels < MetricLabels().add("path", "/abc"));
ASSERT_FALSE(labels < MetricLabels().add("path", "/home").add("type", "put"));
ASSERT_STREQ("path=/home,type=put", labels.to_string().c_str());
}
class TestMetricsVisitor : public MetricsVisitor {
public:
virtual ~TestMetricsVisitor() { }
void visit(const std::string& prefix, const std::string& name,
MetricCollector* collector) {
for (auto& it : collector->metrics()) {
Metric* metric = it.second;
auto& labels = it.first;
switch (metric->type()) {
case MetricType::COUNTER: {
bool has_prev = false;
if (!prefix.empty()) {
_ss << prefix;
has_prev = true;
}
if (!name.empty()) {
if (has_prev) {
_ss << "_";
}
_ss << name;
}
if (!labels.empty()) {
if (has_prev) {
_ss << "_";
}
_ss << labels.to_string();
}
_ss << " " << ((SimpleMetric*)metric)->to_string() << std::endl;
break;
}
default:
break;
}
}
}
std::string to_string() {
return _ss.str();
}
private:
std::stringstream _ss;
};
TEST_F(MetricsTest, MetricCollector) {
IntCounter puts;
puts.increment(101);
IntCounter gets;
gets.increment(201);
MetricCollector collector;
ASSERT_TRUE(collector.add_metic(MetricLabels().add("type", "put"), &puts));
ASSERT_TRUE(collector.add_metic(MetricLabels().add("type", "get"), &gets));
ASSERT_FALSE(collector.add_metic(MetricLabels().add("type", "get"), &gets));
{
// Can't add different type to one collector
IntGauge post;
ASSERT_FALSE(collector.add_metic(MetricLabels().add("type", "post"), &post));
}
{
TestMetricsVisitor visitor;
collector.collect("", "", &visitor);
ASSERT_STREQ("type=get 201\ntype=put 101\n", visitor.to_string().c_str());
}
collector.remove_metric(&puts);
{
TestMetricsVisitor visitor;
collector.collect("", "", &visitor);
ASSERT_STREQ("type=get 201\n", visitor.to_string().c_str());
}
// test get_metric
ASSERT_TRUE(collector.get_metric(MetricLabels()) == nullptr);
ASSERT_TRUE(collector.get_metric(MetricLabels().add("type" ,"get")) != nullptr);
std::vector<Metric*> metrics;
collector.get_metrics(&metrics);
ASSERT_EQ(1, metrics.size());
}
TEST_F(MetricsTest, MetricRegistry) {
MetricRegistry registry("test");
IntCounter cpu_idle;
cpu_idle.increment(12);
ASSERT_TRUE(registry.register_metric("cpu_idle", &cpu_idle));
// registry failed
IntCounter dummy;
ASSERT_FALSE(registry.register_metric("cpu_idle", &dummy));
IntCounter memory_usage;
memory_usage.increment(24);
ASSERT_TRUE(registry.register_metric("memory_usage", &memory_usage));
{
TestMetricsVisitor visitor;
registry.collect(&visitor);
ASSERT_STREQ("test_cpu_idle 12\ntest_memory_usage 24\n", visitor.to_string().c_str());
}
registry.deregister_metric(&memory_usage);
{
TestMetricsVisitor visitor;
registry.collect(&visitor);
ASSERT_STREQ("test_cpu_idle 12\n", visitor.to_string().c_str());
}
// test get_metric
ASSERT_TRUE(registry.get_metric("cpu_idle") != nullptr);
ASSERT_TRUE(registry.get_metric("memory_usage") == nullptr);
}
TEST_F(MetricsTest, MetricRegistry2) {
MetricRegistry registry("test");
IntCounter cpu_idle;
cpu_idle.increment(12);
ASSERT_TRUE(registry.register_metric("cpu_idle", &cpu_idle));
{
// memory_usage will deregister after this block
IntCounter memory_usage;
memory_usage.increment(24);
ASSERT_TRUE(registry.register_metric("memory_usage", &memory_usage));
TestMetricsVisitor visitor;
registry.collect(&visitor);
ASSERT_STREQ("test_cpu_idle 12\ntest_memory_usage 24\n", visitor.to_string().c_str());
}
{
TestMetricsVisitor visitor;
registry.collect(&visitor);
ASSERT_STREQ("test_cpu_idle 12\n", visitor.to_string().c_str());
}
}
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}