aboutsummaryrefslogtreecommitdiffstats
path: root/metrics/src/tests/metricsettest.cpp
blob: 8cbcd2fbdd2d9dd120ee2109b6b281be8c7f0fbe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/metrics/metrics.h>
#include <vespa/vespalib/gtest/gtest.h>
#include <vespa/vespalib/objects/floatingpointtype.h>

namespace metrics {

namespace {
struct TestMetricVisitor : public MetricVisitor {
    std::ostringstream ost;
    uint32_t setsToVisit;

    TestMetricVisitor(uint32_t setsToVisit_ = 100)
        : ost(), setsToVisit(setsToVisit_) {}

    bool visitMetricSet(const MetricSet& set, bool autoGenerated) override {
        ost << "[" << (autoGenerated ? "*" : "") << set.getName() << "]\n";
        if (setsToVisit > 0) {
            --setsToVisit;
            return true;
        }
        return false;
    }
    bool visitMetric(const Metric& m, bool autoGenerated) override {
        ost << (autoGenerated ? "*" : "") << m.getName() << "\n";
        return true;
    }
};
}

TEST(MetricSetTest, test_normal_usage)
{
    // Set up some metrics to test..
    MetricSet set("a", {{"foo"}}, "");
    DoubleValueMetric v1("c", {{"foo"}}, "", &set);
    LongAverageMetric v2("b", {}, "", &set);
    LongCountMetric v3("d", {{"bar"}}, "", &set);
    MetricSet set2("e", {{"bar"}}, "", &set);
    LongCountMetric v4("f", {{"foo"}}, "", &set2);

    // Give them some values
    v1.addValue(4.2);
    v2.addValue(8);
    v3.inc();
    v4.inc(3);

    // Check that we can register through registerMetric function too.
    LongCountMetric v5("g", {}, "");
    set.registerMetric(v5);
    v5.inc(3);
    v5.dec();

    // Check that getMetric works, and doesn't return copy.
    LongAverageMetric* v2copy(
            dynamic_cast<LongAverageMetric*>(set.getMetric("b")));
    ASSERT_TRUE(v2copy != 0);
    v2copy->addValue(9);
    Metric* nonExistingCopy = set.getMetric("nonexisting");
    EXPECT_TRUE(nonExistingCopy == 0);
    nonExistingCopy = set.getMetric("non.existing");
    EXPECT_TRUE(nonExistingCopy == 0);

    // Check that paths are set
    MetricSet topSet("top", {}, "");
    topSet.registerMetric(set);
    EXPECT_EQ(vespalib::string("a"), set.getPath());
    EXPECT_EQ(vespalib::string("a.c"), v1.getPath());
    EXPECT_EQ(vespalib::string("a.b"), v2.getPath());
    EXPECT_EQ(vespalib::string("a.d"), v3.getPath());
    EXPECT_EQ(vespalib::string("a.e"), set2.getPath());
    EXPECT_EQ(vespalib::string("a.e.f"), v4.getPath());
    EXPECT_EQ(vespalib::string("a.g"), v5.getPath());
    EXPECT_EQ(vespalib::string("a.b"), v2copy->getPath());

    // Verify XML output. Should be in register order.
    std::string expected("'\n"
            "a:\n"
            "  c average=4.2 last=4.2 min=4.2 max=4.2 count=1 total=4.2\n"
            "  b average=8.5 last=9 min=8 max=9 count=2 total=17\n"
            "  d count=1\n"
            "  e:\n"
            "    f count=3\n"
            "  g count=2'"
    );
    EXPECT_EQ(expected, "'\n" + set.toString() + "'");

    // Verify that visiting works. That you get all metrics if you answer
    // true to all sets, and that you don't get members of sets you answer
    // false to get.
    {
        TestMetricVisitor visitor(2);
        set.visit(visitor);
        expected = "[a]\nc\nb\nd\n[e]\nf\ng\n";
        EXPECT_EQ("\n" + expected, "\n" + visitor.ost.str());
    }
    {
        TestMetricVisitor visitor(1);
        set.visit(visitor);
        expected = "[a]\nc\nb\nd\n[e]\ng\n";
        EXPECT_EQ("\n" + expected, "\n" + visitor.ost.str());
    }
    {
        TestMetricVisitor visitor(0);
        set.visit(visitor);
        expected = "[a]\n";
        EXPECT_EQ("\n" + expected, "\n" + visitor.ost.str());
    }
}

TEST(MetricSetTest, support_multiple_metrics_with_same_name_different_dimensions)
{
    MetricSet set("dimset", {{"foo", "bar"}}, "");
    DoubleValueMetric v1("stuff", {{"baz", "blarg"}}, "", &set);
    LongAverageMetric v2("stuff", {{"flarn", "yarn"}}, "", &set);

    EXPECT_EQ(size_t(2), set.getRegisteredMetrics().size());
}

TEST(MetricSetTest, unique_target_metrics_are_added_to_metric_set)
{
    MetricSet set1("a", {{"foo"}}, "");
    LongCountMetric v1("wow", {{"foo"}}, "", &set1);
    MetricSet set2("e", {{"bar"}}, "");
    LongCountMetric v2("doge", {{"foo"}}, "", &set2);

    // Have to actually assign a value to metrics or they won't be carried over.
    v1.inc();
    v2.inc();

    // 'doge' metric in set2 must be preserved even though it does not exist
    // in set1.
    std::vector<Metric::UP> ownerList;
    set1.addToSnapshot(set2, ownerList);

    EXPECT_TRUE(set2.getMetric("wow") != nullptr);
    EXPECT_TRUE(set2.getMetric("doge") != nullptr);
}

}