summaryrefslogtreecommitdiffstats
path: root/staging_vespalib
diff options
context:
space:
mode:
authorArne Juul <arnej@yahoo-inc.com>2017-11-26 09:25:53 +0000
committerArne Juul <arnej@yahoo-inc.com>2017-12-03 20:05:01 +0000
commit2634665462f58cb5219ffe226b7f9e192350e0af (patch)
tree459f928da267aba066070c1a9de82139d9dc539e /staging_vespalib
parent00404e5b3966e20dac4a012ad8329b49bac281e9 (diff)
update metrics library after review
* Fix PointMap comparison bug and style. * Rename ReAllocBunch to StableStore, and GC its unused lookup method. Rename method apply -> for_each * Rename CounterIncrement -> Counter::Increment and GaugeMeasurement -> Gauge::Measurement * Rename PointMapBacking -> PointMap::BackingMap * Make single-argument constructors explicit. * Do not use actual time in dummy. * Rename mergeWithMap -> mergeFromSamples, and do some refactoring of it. * Refactor opaque handle implementation into its own class * Copy strings into snapshot, do not refer to strings owned elsewhere. * Refactor _pointMaps code into new PointMapCollection class * Split aggregators into their own files, move Bucket into its own files, and rename files for CurrentSamples. * Make Counter and Gauge only hold the MetricName and supply an empty Point via default argument instead. * Split out StableStore test, and test for pointer equality. * Separate out ticker thread, and arrange for fast stop. * Use less swap. * Add totalSnapshot() facility.
Diffstat (limited to 'staging_vespalib')
-rw-r--r--staging_vespalib/src/tests/metrics/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/metrics/simple_metrics_test.cpp48
-rw-r--r--staging_vespalib/src/tests/metrics/stable_store_test.cpp65
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/CMakeLists.txt11
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/bucket.cpp90
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/bucket.h40
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/clock.cpp2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/clock.h2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/counter.cpp23
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/counter.h31
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.cpp28
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.h22
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/current_samples.cpp15
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/current_samples.h33
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/dimension.h11
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.cpp13
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.h16
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/gauge.cpp12
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/gauge.h26
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.cpp52
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.h26
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/handle.cpp2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/handle.h53
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/json_formatter.cpp2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/label.h10
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/mergers.cpp174
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/mergers.h81
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/metric_identifier.h34
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/metric_name.cpp2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/metric_name.h18
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/metric_types.cpp9
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/metric_types.h2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/metrics_manager.h9
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/name_collection.cpp15
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/name_collection.h2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/point.h14
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/point_builder.cpp6
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/point_builder.h4
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/point_map.cpp33
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/point_map.h10
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.cpp39
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.h29
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.cpp99
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.h29
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/snapshots.h24
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/stable_store.cpp (renamed from staging_vespalib/src/vespa/vespalib/metrics/no_realloc_bunch.cpp)2
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/stable_store.h (renamed from staging_vespalib/src/vespa/vespalib/metrics/no_realloc_bunch.h)37
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.cpp43
-rw-r--r--staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.h36
49 files changed, 833 insertions, 559 deletions
diff --git a/staging_vespalib/src/tests/metrics/CMakeLists.txt b/staging_vespalib/src/tests/metrics/CMakeLists.txt
index 5319511e769..fc9a496c972 100644
--- a/staging_vespalib/src/tests/metrics/CMakeLists.txt
+++ b/staging_vespalib/src/tests/metrics/CMakeLists.txt
@@ -6,3 +6,11 @@ vespa_add_executable(staging_vespalib_metrics_test_app TEST
staging_vespalib
)
vespa_add_test(NAME staging_vespalib_metrics_test_app COMMAND staging_vespalib_metrics_test_app)
+
+vespa_add_executable(staging_vespalib_stablestore_test_app TEST
+ SOURCES
+ stable_store_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_stablestore_test_app COMMAND staging_vespalib_stablestore_test_app)
diff --git a/staging_vespalib/src/tests/metrics/simple_metrics_test.cpp b/staging_vespalib/src/tests/metrics/simple_metrics_test.cpp
index 0adef8d353f..1bd10d90384 100644
--- a/staging_vespalib/src/tests/metrics/simple_metrics_test.cpp
+++ b/staging_vespalib/src/tests/metrics/simple_metrics_test.cpp
@@ -2,7 +2,7 @@
#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/vespalib/metrics/simple_metrics.h>
#include <vespa/vespalib/metrics/simple_metrics_manager.h>
-#include <vespa/vespalib/metrics/no_realloc_bunch.h>
+#include <vespa/vespalib/metrics/stable_store.h>
#include <vespa/vespalib/metrics/json_formatter.h>
#include <stdio.h>
#include <unistd.h>
@@ -12,7 +12,7 @@ using namespace vespalib::metrics;
TEST("require that simple metrics gauge merge works")
{
- MetricIdentifier id(42);
+ MetricIdentifier id(MetricName(42));
GaugeAggregator a(id), b(id), c(id);
b.observedCount = 3;
b.sumValue = 24.0;
@@ -52,44 +52,6 @@ TEST("require that simple metrics gauge merge works")
EXPECT_EQUAL(a.lastValue, 1.0);
}
-struct Foo {
- int a;
- char *p;
- explicit Foo(int v) : a(v), p(nullptr) {}
- bool operator==(const Foo &other) const {
- return a == other.a;
- }
-};
-
-TEST("require that no_realloc_bunch works")
-{
- vespalib::NoReallocBunch<Foo> bunch;
- bunch.add(Foo(1));
- bunch.add(Foo(2));
- bunch.add(Foo(3));
- bunch.add(Foo(5));
- bunch.add(Foo(8));
- bunch.add(Foo(13));
- bunch.add(Foo(21));
- bunch.add(Foo(34));
- bunch.add(Foo(55));
- bunch.add(Foo(89));
-
- EXPECT_EQUAL(bunch.size(), 10u);
-
- int sum = 0;
-
- bunch.apply([&sum](const Foo& value) { sum += value.a; });
- EXPECT_EQUAL(231, sum);
-
- const Foo& val = bunch.lookup(8);
- EXPECT_TRUE(Foo(55) == val);
-
- for (int i = 0; i < 20000; ++i) {
- bunch.add(Foo(i));
- }
- EXPECT_TRUE(Foo(19999) == bunch.lookup(20009));
-}
TEST("use simple_metrics_collector")
{
@@ -132,9 +94,11 @@ TEST("use simple_metrics_collector")
myGauge.sample(14.0, two);
myGauge.sample(11.0, three);
- // sleep(2);
+ for (int i = 0; i < 61; ++i) {
+ ((SimpleMetricsManager &)*manager).tick();
+ }
- Snapshot snap = manager->snapshot();
+ Snapshot snap = manager->totalSnapshot();
fprintf(stdout, "snap begin: %15f\n", snap.startTime());
fprintf(stdout, "snap end: %15f\n", snap.endTime());
diff --git a/staging_vespalib/src/tests/metrics/stable_store_test.cpp b/staging_vespalib/src/tests/metrics/stable_store_test.cpp
new file mode 100644
index 00000000000..03b6663cd64
--- /dev/null
+++ b/staging_vespalib/src/tests/metrics/stable_store_test.cpp
@@ -0,0 +1,65 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/metrics/simple_metrics.h>
+#include <vespa/vespalib/metrics/simple_metrics_manager.h>
+#include <vespa/vespalib/metrics/stable_store.h>
+#include <vespa/vespalib/metrics/json_formatter.h>
+#include <stdio.h>
+#include <unistd.h>
+
+using namespace vespalib;
+using namespace vespalib::metrics;
+
+struct Foo {
+ int a;
+ char *p;
+ explicit Foo(int v) : a(v), p(nullptr) {}
+ bool operator==(const Foo &other) const {
+ return a == other.a;
+ }
+};
+
+TEST("require that stable_store works")
+{
+ vespalib::StableStore<Foo> bunch;
+ bunch.add(Foo(1));
+ bunch.add(Foo(2));
+ bunch.add(Foo(3));
+ bunch.add(Foo(5));
+ bunch.add(Foo(8));
+ bunch.add(Foo(13));
+ bunch.add(Foo(21));
+ bunch.add(Foo(34));
+ bunch.add(Foo(55));
+ bunch.add(Foo(89));
+
+ EXPECT_EQUAL(bunch.size(), 10u);
+
+ int sum = 0;
+
+ bunch.for_each([&sum](const Foo& value) { sum += value.a; });
+ EXPECT_EQUAL(231, sum);
+
+ std::vector<const Foo *> pointers;
+ bunch.for_each([&pointers](const Foo& value)
+ { pointers.push_back(&value); });
+ EXPECT_EQUAL(1, pointers[0]->a);
+ EXPECT_EQUAL(2, pointers[1]->a);
+ EXPECT_EQUAL(55, pointers[8]->a);
+ EXPECT_EQUAL(89, pointers[9]->a);
+
+ for (int i = 0; i < 20000; ++i) {
+ bunch.add(Foo(i));
+ }
+ bunch.for_each([&sum](const Foo& value) { sum -= value.a; });
+ EXPECT_EQUAL(-199990000, sum);
+
+ std::vector<const Foo *> after;
+ bunch.for_each([&after](const Foo& value)
+ { if (after.size() < 10) after.push_back(&value); });
+
+ EXPECT_EQUAL(pointers[0], after[0]);
+ EXPECT_EQUAL(pointers[9], after[9]);
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/CMakeLists.txt b/staging_vespalib/src/vespa/vespalib/metrics/CMakeLists.txt
index 657565fc974..c56605c9181 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/CMakeLists.txt
+++ b/staging_vespalib/src/vespa/vespalib/metrics/CMakeLists.txt
@@ -1,26 +1,33 @@
# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(staging_vespalib_vespalib_metrics OBJECT
SOURCES
+ bucket.cpp
clock.cpp
+ counter_aggregator.cpp
counter.cpp
+ current_samples.cpp
dimension.cpp
dummy_metrics_manager.cpp
+ gauge_aggregator.cpp
gauge.cpp
+ handle.cpp
json_formatter.cpp
label.cpp
- mergers.cpp
metric_identifier.cpp
+ metric_name.cpp
metrics_manager.cpp
metric_types.cpp
name_collection.cpp
- no_realloc_bunch.cpp
point_builder.cpp
point.cpp
+ point_map_collection.cpp
point_map.cpp
producer.cpp
simple_metrics.cpp
simple_metrics_manager.cpp
snapshots.cpp
+ stable_store.cpp
+ ticker_thread.cpp
DEPENDS
)
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/bucket.cpp b/staging_vespalib/src/vespa/vespalib/metrics/bucket.cpp
new file mode 100644
index 00000000000..e0d456a5259
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/bucket.cpp
@@ -0,0 +1,90 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "bucket.h"
+#include <assert.h>
+#include <map>
+
+namespace vespalib {
+namespace metrics {
+
+namespace {
+
+template<typename T>
+std::vector<typename T::aggregator_type>
+mergeFromSamples(const StableStore<typename T::sample_type> &source)
+{
+ using Aggregator = typename T::aggregator_type;
+ using Sample = typename T::sample_type;
+ using Map = std::map<MetricIdentifier, Aggregator>;
+ using MapValue = typename Map::value_type;
+
+ Map map;
+ source.for_each([&map] (const Sample &sample) {
+ MetricIdentifier id = sample.idx;
+ auto iter_check = map.emplace(id, Aggregator(id));
+ iter_check.first->second.merge(sample);
+ });
+ std::vector<typename T::aggregator_type> result;
+ for (const MapValue &entry : map) {
+ result.push_back(entry.second);
+ }
+ return result;
+}
+
+template<typename T>
+std::vector<T>
+mergeVectors(const std::vector<T> &a,
+ const std::vector<T> &b)
+{
+ std::vector<T> result;
+ auto a_iter = a.begin();
+ auto b_iter = b.begin();
+ while (a_iter != a.end() &&
+ b_iter != b.end())
+ {
+ if (a_iter->idx < b_iter->idx) {
+ result.push_back(*a_iter);
+ ++a_iter;
+ } else if (b_iter->idx < a_iter->idx) {
+ result.push_back(*b_iter);
+ ++b_iter;
+ } else {
+ result.push_back(*a_iter);
+ result.back().merge(*b_iter);
+ ++a_iter;
+ ++b_iter;
+ }
+ }
+ while (a_iter != a.end()) {
+ result.push_back(*a_iter);
+ ++a_iter;
+ }
+ while (b_iter != b.end()) {
+ result.push_back(*b_iter);
+ ++b_iter;
+ }
+ return result;
+}
+
+} // namespace <unnamed>
+
+void Bucket::merge(const CurrentSamples &samples)
+{
+ counters = mergeFromSamples<Counter>(samples.counterIncrements);
+ gauges = mergeFromSamples<Gauge>(samples.gaugeMeasurements);
+}
+
+void Bucket::merge(const Bucket &other)
+{
+ assert(startTime <= other.startTime);
+ assert(endTime <= other.endTime);
+ endTime = other.endTime;
+
+ std::vector<CounterAggregator> nextCounters = mergeVectors(counters, other.counters);
+ counters = std::move(nextCounters);
+
+ std::vector<GaugeAggregator> nextGauges = mergeVectors(gauges, other.gauges);
+ gauges = std::move(nextGauges);
+}
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/bucket.h b/staging_vespalib/src/vespa/vespalib/metrics/bucket.h
new file mode 100644
index 00000000000..c35be945343
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/bucket.h
@@ -0,0 +1,40 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <mutex>
+#include "stable_store.h"
+#include "metric_identifier.h"
+#include "counter.h"
+#include "gauge.h"
+#include "clock.h"
+#include "counter_aggregator.h"
+#include "gauge_aggregator.h"
+#include "current_samples.h"
+
+namespace vespalib {
+namespace metrics {
+
+// internal
+struct Bucket {
+ InternalTimeStamp startTime;
+ InternalTimeStamp endTime;
+ std::vector<CounterAggregator> counters;
+ std::vector<GaugeAggregator> gauges;
+
+ void merge(const CurrentSamples &other);
+ void merge(const Bucket &other);
+
+ Bucket(InternalTimeStamp started, InternalTimeStamp ended)
+ : startTime(started),
+ endTime(ended),
+ counters(),
+ gauges()
+ {}
+ ~Bucket() {}
+ Bucket(Bucket &&) = default;
+ Bucket(const Bucket &) = default;
+ Bucket& operator= (Bucket &&) = default;
+};
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/clock.cpp b/staging_vespalib/src/vespa/vespalib/metrics/clock.cpp
index 088dd721cbf..32f7eaec1ad 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/clock.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/clock.cpp
@@ -2,6 +2,7 @@
#include "clock.h"
namespace vespalib {
+namespace metrics {
std::chrono::microseconds since_epoch(InternalTimeStamp stamp)
{
@@ -24,4 +25,5 @@ std::chrono::microseconds since_epoch(InternalTimeStamp stamp)
return microseconds(stampms + difference + adjust);
}
+} // namespace metrics
} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/clock.h b/staging_vespalib/src/vespa/vespalib/metrics/clock.h
index 9bdb8241139..eebfab58336 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/clock.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/clock.h
@@ -4,6 +4,7 @@
#include <chrono>
namespace vespalib {
+namespace metrics {
using InternalClock = std::chrono::steady_clock;
using InternalTimeStamp = std::chrono::time_point<std::chrono::steady_clock,
@@ -20,4 +21,5 @@ inline InternalTimeStamp now_stamp()
std::chrono::microseconds since_epoch(InternalTimeStamp stamp);
+} // namespace metrics
} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/counter.cpp b/staging_vespalib/src/vespa/vespalib/metrics/counter.cpp
index 2eb3719801b..08f72e6aa34 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/counter.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/counter.cpp
@@ -5,32 +5,13 @@
namespace vespalib {
namespace metrics {
-void
-Counter::add() const
-{
- add(1);
-}
-
-void
-Counter::add(Point p) const
-{
- add(1, p);
-}
-
-void
-Counter::add(size_t count) const
-{
- if (_manager) {
- _manager->add(CounterIncrement(ident(), count));
- }
-}
void
Counter::add(size_t count, Point point) const
{
if (_manager) {
- MetricIdentifier id(_idx.name_idx, point.id());
- _manager->add(CounterIncrement(id, count));
+ MetricIdentifier fullId(_id, point);
+ _manager->add(Increment(fullId, count));
}
}
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/counter.h b/staging_vespalib/src/vespa/vespalib/metrics/counter.h
index 56b5d277e90..efa4e29f18a 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/counter.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/counter.h
@@ -11,34 +11,33 @@ namespace metrics {
class MetricsManager;
class CounterAggregator;
-struct CounterIncrement {
- MetricIdentifier idx;
- size_t value;
- CounterIncrement() = delete;
- CounterIncrement(MetricIdentifier id, size_t v) : idx(id), value(v) {}
-};
class Counter {
std::shared_ptr<MetricsManager> _manager;
- MetricIdentifier _idx;
- MetricIdentifier ident() const { return _idx; }
+ MetricName _id;
public:
- Counter() : _manager(), _idx() {}
+ Counter() : _manager(), _id(0) {}
Counter(const Counter&) = delete;
Counter(Counter &&other) = default;
Counter& operator= (const Counter &) = delete;
Counter& operator= (Counter &&other) = default;
- Counter(std::shared_ptr<MetricsManager> m, MetricIdentifier id)
- : _manager(std::move(m)), _idx(id)
+ Counter(std::shared_ptr<MetricsManager> m, MetricName id)
+ : _manager(std::move(m)), _id(id)
{}
- void add() const;
- void add(size_t count) const;
- void add(Point p) const;
- void add(size_t count, Point p) const;
+ void add() const { add(1, Point::empty); }
+ void add(Point p) { add(1, p); }
+ void add(size_t count, Point p = Point::empty) const;
+
+ struct Increment {
+ MetricIdentifier idx;
+ size_t value;
+ Increment() = delete;
+ Increment(MetricIdentifier id, size_t v) : idx(id), value(v) {}
+ };
typedef CounterAggregator aggregator_type;
- typedef CounterIncrement sample_type;
+ typedef Increment sample_type;
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.cpp b/staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.cpp
new file mode 100644
index 00000000000..6c7e42da193
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.cpp
@@ -0,0 +1,28 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "counter_aggregator.h"
+#include <assert.h>
+#include <map>
+
+namespace vespalib {
+namespace metrics {
+
+CounterAggregator::CounterAggregator(MetricIdentifier id)
+ : idx(id), count(0)
+{}
+
+void
+CounterAggregator::merge(const Counter::Increment &increment)
+{
+ assert(idx == increment.idx);
+ count += increment.value;
+}
+
+void
+CounterAggregator::merge(const CounterAggregator &other)
+{
+ assert(idx == other.idx);
+ count += other.count;
+}
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.h b/staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.h
new file mode 100644
index 00000000000..969c80337a0
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/counter_aggregator.h
@@ -0,0 +1,22 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include "metric_identifier.h"
+#include "counter.h"
+
+namespace vespalib {
+namespace metrics {
+
+// internal
+struct CounterAggregator {
+ MetricIdentifier idx;
+ size_t count;
+
+ CounterAggregator(MetricIdentifier id);
+
+ void merge(const Counter::Increment &other);
+ void merge(const CounterAggregator &other);
+};
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/current_samples.cpp b/staging_vespalib/src/vespa/vespalib/metrics/current_samples.cpp
new file mode 100644
index 00000000000..4dbd5b6063e
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/current_samples.cpp
@@ -0,0 +1,15 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "current_samples.h"
+
+namespace vespalib {
+namespace metrics {
+
+void swap(CurrentSamples& a, CurrentSamples& b)
+{
+ using std::swap;
+ swap(a.counterIncrements, b.counterIncrements);
+ swap(a.gaugeMeasurements, b.gaugeMeasurements);
+}
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/current_samples.h b/staging_vespalib/src/vespa/vespalib/metrics/current_samples.h
new file mode 100644
index 00000000000..78667a3020a
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/current_samples.h
@@ -0,0 +1,33 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <mutex>
+#include "stable_store.h"
+#include "counter.h"
+#include "gauge.h"
+
+namespace vespalib {
+namespace metrics {
+
+// internal
+struct CurrentSamples {
+ std::mutex lock;
+ StableStore<Counter::Increment> counterIncrements;
+ StableStore<Gauge::Measurement> gaugeMeasurements;
+
+ ~CurrentSamples() {}
+
+ void add(Counter::Increment inc) {
+ std::lock_guard<std::mutex> guard(lock);
+ counterIncrements.add(inc);
+ }
+ void sample(Gauge::Measurement value) {
+ std::lock_guard<std::mutex> guard(lock);
+ gaugeMeasurements.add(value);
+ }
+};
+
+void swap(CurrentSamples& a, CurrentSamples& b);
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/dimension.h b/staging_vespalib/src/vespa/vespalib/metrics/dimension.h
index 3d6e2cc0eea..680370ba84c 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/dimension.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/dimension.h
@@ -2,18 +2,19 @@
#pragma once
#include <vespa/vespalib/stllike/string.h>
+#include "handle.h"
namespace vespalib {
namespace metrics {
using DimensionName = vespalib::string;
-class Dimension {
- const size_t _dimension_idx;
+/**
+ * Opaque handle representing an uniquely named dimension.
+ **/
+class Dimension : public Handle<Dimension> {
public:
- size_t id() const { return _dimension_idx; }
- Dimension(size_t id) : _dimension_idx(id) {}
- bool operator< (const Dimension &other) const { return id() < other.id(); }
+ explicit Dimension(size_t id) : Handle<Dimension>(id) {}
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.cpp b/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.cpp
index 50b26cf60fb..cd7a3abb1eb 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.cpp
@@ -9,11 +9,14 @@ DummyMetricsManager::~DummyMetricsManager() {}
Snapshot
DummyMetricsManager::snapshot()
{
- InternalTimeStamp endTime = now_stamp();
- std::chrono::microseconds s = since_epoch(_startTime);
- std::chrono::microseconds e = since_epoch(endTime);
- const double micro = 0.000001;
- Snapshot snap(s.count() * micro, e.count() * micro);
+ Snapshot snap(0, 0);
+ return snap;
+}
+
+Snapshot
+DummyMetricsManager::totalSnapshot()
+{
+ Snapshot snap(0, 0);
return snap;
}
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.h b/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.h
index 1eeda79e117..59e23e6ea84 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/dummy_metrics_manager.h
@@ -5,7 +5,7 @@
#include <thread>
#include <vespa/vespalib/stllike/string.h>
#include "name_collection.h"
-#include "mergers.h"
+#include "current_samples.h"
#include "snapshots.h"
#include "metrics_manager.h"
#include "clock.h"
@@ -21,8 +21,7 @@ namespace metrics {
class DummyMetricsManager : public MetricsManager
{
private:
- InternalTimeStamp _startTime;
- DummyMetricsManager() : _startTime(now_stamp()) {}
+ DummyMetricsManager() {}
public:
~DummyMetricsManager();
@@ -31,10 +30,10 @@ public:
}
Counter counter(const vespalib::string &) override {
- return Counter(shared_from_this(), MetricIdentifier(0));
+ return Counter(shared_from_this(), MetricName(0));
}
Gauge gauge(const vespalib::string &) override {
- return Gauge(shared_from_this(), MetricIdentifier(0));
+ return Gauge(shared_from_this(), MetricName(0));
}
Dimension dimension(const vespalib::string &) override {
@@ -46,16 +45,17 @@ public:
PointBuilder pointBuilder(Point) override {
return PointBuilder(shared_from_this());
}
- Point pointFrom(PointMapBacking &&) override {
+ Point pointFrom(PointMap::BackingMap) override {
return Point(0);
}
Snapshot snapshot() override;
+ Snapshot totalSnapshot() override;
// for use from Counter only
- void add(CounterIncrement) override {}
+ void add(Counter::Increment) override {}
// for use from Gauge only
- void sample(GaugeMeasurement) override {}
+ void sample(Gauge::Measurement) override {}
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/gauge.cpp b/staging_vespalib/src/vespa/vespalib/metrics/gauge.cpp
index b2d9f6b946a..af98ba2de18 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/gauge.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/gauge.cpp
@@ -6,19 +6,11 @@ namespace vespalib {
namespace metrics {
void
-Gauge::sample(double value) const
-{
- if (_manager) {
- _manager->sample(GaugeMeasurement(ident(), value));
- }
-}
-
-void
Gauge::sample(double value, Point point) const
{
if (_manager) {
- MetricIdentifier id(_idx.name_idx, point.id());
- _manager->sample(GaugeMeasurement(id, value));
+ MetricIdentifier fullId(_id, point);
+ _manager->sample(Measurement(fullId, value));
}
}
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/gauge.h b/staging_vespalib/src/vespa/vespalib/metrics/gauge.h
index c5a1bfb25d8..5f15a573b73 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/gauge.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/gauge.h
@@ -11,28 +11,26 @@ namespace metrics {
class MetricsManager;
class GaugeAggregator;
-struct GaugeMeasurement {
- MetricIdentifier idx;
- double value;
- GaugeMeasurement() = delete;
- GaugeMeasurement(MetricIdentifier id, double v) : idx(id), value(v) {}
-};
-
class Gauge {
private:
std::shared_ptr<MetricsManager> _manager;
- MetricIdentifier _idx;
- MetricIdentifier ident() const { return _idx; }
+ MetricName _id;
public:
- Gauge(std::shared_ptr<MetricsManager> m, MetricIdentifier id)
- : _manager(std::move(m)), _idx(id)
+ Gauge(std::shared_ptr<MetricsManager> m, MetricName id)
+ : _manager(std::move(m)), _id(id)
{}
- void sample(double value) const;
- void sample(double value, Point p) const;
+ void sample(double value, Point p = Point::empty) const;
+
+ struct Measurement {
+ MetricIdentifier idx;
+ double value;
+ Measurement() = delete;
+ Measurement(MetricIdentifier id, double v) : idx(id), value(v) {}
+ };
typedef GaugeAggregator aggregator_type;
- typedef GaugeMeasurement sample_type;
+ typedef Measurement sample_type;
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.cpp b/staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.cpp
new file mode 100644
index 00000000000..3e36b4e1b30
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.cpp
@@ -0,0 +1,52 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "gauge_aggregator.h"
+#include <assert.h>
+#include <map>
+
+namespace vespalib {
+namespace metrics {
+
+GaugeAggregator::GaugeAggregator(MetricIdentifier id)
+ : idx(id),
+ observedCount(0),
+ sumValue(0.0),
+ minValue(0.0),
+ maxValue(0.0),
+ lastValue(0.0)
+{}
+
+void
+GaugeAggregator::merge(const Gauge::Measurement &other)
+{
+ assert(idx == other.idx);
+ if (observedCount == 0) {
+ sumValue = other.value;
+ minValue = other.value;
+ maxValue = other.value;
+ } else {
+ sumValue += other.value;
+ minValue = std::min(minValue, other.value);
+ maxValue = std::max(maxValue, other.value);
+ }
+ lastValue = other.value;
+ ++observedCount;
+}
+
+void
+GaugeAggregator::merge(const GaugeAggregator &other)
+{
+ assert(idx == other.idx);
+ if (observedCount == 0) {
+ minValue = other.minValue;
+ maxValue = other.maxValue;
+ } else {
+ minValue = std::min(minValue, other.minValue);
+ maxValue = std::max(maxValue, other.maxValue);
+ }
+ sumValue += other.sumValue;
+ lastValue = other.lastValue;
+ observedCount += other.observedCount;
+}
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.h b/staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.h
new file mode 100644
index 00000000000..231f5650dca
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/gauge_aggregator.h
@@ -0,0 +1,26 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include "metric_identifier.h"
+#include "gauge.h"
+
+namespace vespalib {
+namespace metrics {
+
+// internal
+struct GaugeAggregator {
+ MetricIdentifier idx;
+ size_t observedCount;
+ double sumValue;
+ double minValue;
+ double maxValue;
+ double lastValue;
+
+ GaugeAggregator(MetricIdentifier id);
+
+ void merge(const Gauge::Measurement &other);
+ void merge(const GaugeAggregator &other);
+};
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/handle.cpp b/staging_vespalib/src/vespa/vespalib/metrics/handle.cpp
new file mode 100644
index 00000000000..2b806caeaea
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/handle.cpp
@@ -0,0 +1,2 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "handle.h"
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/handle.h b/staging_vespalib/src/vespa/vespalib/metrics/handle.h
new file mode 100644
index 00000000000..cd5d0c9e940
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/handle.h
@@ -0,0 +1,53 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <cstddef>
+
+namespace vespalib {
+namespace metrics {
+
+/**
+ * Common implementation of an opaque handle identified only
+ * by a (64-bit) integer. Templated to avoid different concepts
+ * sharing a superclass.
+ **/
+template <typename T>
+class Handle {
+private:
+ const size_t _id;
+protected:
+ explicit Handle(size_t id) : _id(id) {}
+public:
+ size_t id() const { return _id; }
+};
+
+template <typename T>
+bool
+operator< (const Handle<T> &a, const Handle<T> &b)
+{
+ return a.id() < b.id();
+}
+
+template <typename T>
+bool
+operator> (const Handle<T> &a, const Handle<T> &b)
+{
+ return a.id() > b.id();
+}
+
+template <typename T>
+bool
+operator== (const Handle<T> &a, const Handle<T> &b)
+{
+ return a.id() == b.id();
+}
+
+template <typename T>
+bool
+operator!= (const Handle<T> &a, const Handle<T> &b)
+{
+ return a.id() != b.id();
+}
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/json_formatter.cpp b/staging_vespalib/src/vespa/vespalib/metrics/json_formatter.cpp
index 58ef76ce8b0..280211bd780 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/json_formatter.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/json_formatter.cpp
@@ -66,7 +66,7 @@ JsonFormatter::handle(const PointSnapshot &snapshot, vespalib::slime::Cursor &ta
return;
}
Cursor& inner = target.setObject("dimensions");
- for (const AxisMeasure &entry : snapshot.dimensions) {
+ for (const DimensionBinding &entry : snapshot.dimensions) {
inner.setString(entry.dimensionName(), entry.labelValue());
}
}
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/label.h b/staging_vespalib/src/vespa/vespalib/metrics/label.h
index 09c5b20e45b..81e96728c27 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/label.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/label.h
@@ -2,17 +2,19 @@
#pragma once
#include <vespa/vespalib/stllike/string.h>
+#include "handle.h"
namespace vespalib {
namespace metrics {
using LabelValue = vespalib::string;
-class Label {
- const size_t _coord_idx;
+/**
+ * Opaque handle representing an uniquely named label.
+ **/
+class Label : public Handle<Label> {
public:
- size_t id() const { return _coord_idx; }
- Label(size_t id) : _coord_idx(id) {}
+ explicit Label(size_t id) : Handle<Label>(id) {}
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/mergers.cpp b/staging_vespalib/src/vespa/vespalib/metrics/mergers.cpp
deleted file mode 100644
index 1a4731065b5..00000000000
--- a/staging_vespalib/src/vespa/vespalib/metrics/mergers.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include "mergers.h"
-#include <assert.h>
-#include <map>
-
-namespace vespalib {
-namespace metrics {
-
-CounterAggregator::CounterAggregator(MetricIdentifier id)
- : idx(id), count(0)
-{}
-
-void
-CounterAggregator::merge(const CounterIncrement &increment)
-{
- assert(idx == increment.idx);
- count += increment.value;
-}
-
-void
-CounterAggregator::merge(const CounterAggregator &other)
-{
- assert(idx == other.idx);
- count += other.count;
-}
-
-
-GaugeAggregator::GaugeAggregator(MetricIdentifier id)
- : idx(id),
- observedCount(0),
- sumValue(0.0),
- minValue(0.0),
- maxValue(0.0),
- lastValue(0.0)
-{}
-
-void
-GaugeAggregator::merge(const GaugeMeasurement &other)
-{
- assert(idx == other.idx);
- if (observedCount == 0) {
- sumValue = other.value;
- minValue = other.value;
- maxValue = other.value;
- } else {
- sumValue += other.value;
- minValue = std::min(minValue, other.value);
- maxValue = std::max(maxValue, other.value);
- }
- lastValue = other.value;
- ++observedCount;
-}
-
-void
-GaugeAggregator::merge(const GaugeAggregator &other)
-{
- assert(idx == other.idx);
- if (observedCount == 0) {
- minValue = other.minValue;
- maxValue = other.maxValue;
- } else {
- minValue = std::min(minValue, other.minValue);
- maxValue = std::max(maxValue, other.maxValue);
- }
- sumValue += other.sumValue;
- lastValue = other.lastValue;
- observedCount += other.observedCount;
-}
-
-namespace {
-
-template<typename T>
-void
-mergeWithMap(const NoReallocBunch<typename T::sample_type> &other,
- std::vector<typename T::aggregator_type> &result)
-{
- using Aggregator = typename T::aggregator_type;
- using Sample = typename T::sample_type;
- using Map = std::map<MetricIdentifier, Aggregator>;
- using MapValue = typename Map::value_type;
-
- assert(result.size() == 0);
- Map map;
- other.apply([&map] (const Sample &sample) {
- MetricIdentifier id = sample.idx;
- auto iter = map.find(id);
- if (iter != map.end()) {
- iter->second.merge(sample);
- } else {
- auto check_iter = map.insert(MapValue(id, Aggregator(id)));
- assert(check_iter.second);
- check_iter.first->second.merge(sample);
- }
- });
- for (const MapValue &entry : map) {
- result.push_back(entry.second);
- }
-}
-
-template<typename T>
-std::vector<T>
-mergeVectors(const std::vector<T> &a,
- const std::vector<T> &b)
-{
- std::vector<T> result;
- auto a_iter = a.begin();
- auto b_iter = b.begin();
- while (a_iter != a.end() &&
- b_iter != b.end())
- {
- if (a_iter->idx < b_iter->idx) {
- result.push_back(*a_iter);
- ++a_iter;
- } else if (b_iter->idx < a_iter->idx) {
- result.push_back(*b_iter);
- ++b_iter;
- } else {
- T both = *a_iter;
- both.merge(*b_iter);
- result.push_back(both);
- ++a_iter;
- ++b_iter;
- }
- }
- while (a_iter != a.end()) {
- result.push_back(*a_iter);
- ++a_iter;
- }
- while (b_iter != b.end()) {
- result.push_back(*b_iter);
- ++b_iter;
- }
- return result;
-}
-
-} // namespace <unnamed>
-
-void Bucket::merge(const CurrentSamples &other)
-{
- mergeWithMap<Counter>(other.counterIncrements, counters);
- mergeWithMap<Gauge>(other.gaugeMeasurements, gauges);
-}
-
-void Bucket::merge(const Bucket &other)
-{
- assert(startTime <= other.startTime);
- assert(endTime <= other.endTime);
- endTime = other.endTime;
-
- std::vector<CounterAggregator> nextCounters = mergeVectors(counters, other.counters);
- counters = std::move(nextCounters);
-
- std::vector<GaugeAggregator> nextGauges = mergeVectors(gauges, other.gauges);
- gauges = std::move(nextGauges);
-}
-
-void swap(CurrentSamples& a, CurrentSamples& b)
-{
- using std::swap;
- swap(a.counterIncrements, b.counterIncrements);
- swap(a.gaugeMeasurements, b.gaugeMeasurements);
-}
-
-void swap(Bucket& a, Bucket& b)
-{
- using std::swap;
- swap(a.startTime, b.startTime);
- swap(a.endTime, b.endTime);
- swap(a.counters, b.counters);
- swap(a.gauges, b.gauges);
-}
-
-} // namespace vespalib::metrics
-} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/mergers.h b/staging_vespalib/src/vespa/vespalib/metrics/mergers.h
deleted file mode 100644
index e08efff1599..00000000000
--- a/staging_vespalib/src/vespa/vespalib/metrics/mergers.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#pragma once
-
-#include <mutex>
-#include "no_realloc_bunch.h"
-#include "metric_identifier.h"
-#include "counter.h"
-#include "gauge.h"
-#include "clock.h"
-
-namespace vespalib {
-namespace metrics {
-
-// internal
-struct CounterAggregator {
- MetricIdentifier idx;
- size_t count;
-
- CounterAggregator(MetricIdentifier id);
-
- void merge(const CounterIncrement &other);
- void merge(const CounterAggregator &other);
-};
-
-// internal
-struct GaugeAggregator {
- MetricIdentifier idx;
- size_t observedCount;
- double sumValue;
- double minValue;
- double maxValue;
- double lastValue;
-
- GaugeAggregator(MetricIdentifier id);
-
- void merge(const GaugeMeasurement &other);
- void merge(const GaugeAggregator &other);
-};
-
-// internal
-struct CurrentSamples {
- std::mutex lock;
- NoReallocBunch<CounterIncrement> counterIncrements;
- NoReallocBunch<GaugeMeasurement> gaugeMeasurements;
-
- ~CurrentSamples() {}
-
- void add(CounterIncrement inc) {
- std::lock_guard<std::mutex> guard(lock);
- counterIncrements.add(inc);
- }
- void sample(GaugeMeasurement value) {
- std::lock_guard<std::mutex> guard(lock);
- gaugeMeasurements.add(value);
- }
-};
-
-// internal
-struct Bucket {
- InternalTimeStamp startTime;
- InternalTimeStamp endTime;
- std::vector<CounterAggregator> counters;
- std::vector<GaugeAggregator> gauges;
-
- void merge(const CurrentSamples &other);
- void merge(const Bucket &other);
-
- Bucket(InternalTimeStamp started, InternalTimeStamp ended)
- : startTime(started),
- endTime(ended),
- counters(),
- gauges()
- {}
- ~Bucket() {}
-};
-
-void swap(CurrentSamples& a, CurrentSamples& b);
-void swap(Bucket& a, Bucket& b);
-
-} // namespace vespalib::metrics
-} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/metric_identifier.h b/staging_vespalib/src/vespa/vespalib/metrics/metric_identifier.h
index 4feb8f1a22d..0fbff69658e 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/metric_identifier.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/metric_identifier.h
@@ -1,35 +1,39 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <cstddef>
+#include "metric_name.h"
+#include "point.h"
#include <functional>
namespace vespalib {
namespace metrics {
struct MetricIdentifier {
- const size_t name_idx;
- const size_t point_idx;
+ const MetricName _name;
+ const Point _point;
- MetricIdentifier() : name_idx(-1), point_idx(0) {}
+ MetricIdentifier() = delete;
- explicit MetricIdentifier(size_t id)
- : name_idx(id), point_idx(0) {}
+ explicit MetricIdentifier(MetricName name)
+ : _name(name), _point(0) {}
- MetricIdentifier(size_t id, size_t pt)
- : name_idx(id), point_idx(pt) {}
+ MetricIdentifier(MetricName name, Point point)
+ : _name(name), _point(point) {}
bool operator< (const MetricIdentifier &other) const {
- if (name_idx < other.name_idx) return true;
- if (name_idx == other.name_idx) {
- return (point_idx < other.point_idx);
+ if (_name != other._name) {
+ return _name < other._name;
}
- return false;
+ return _point < other._point;
}
bool operator== (const MetricIdentifier &other) const {
- return (name_idx == other.name_idx &&
- point_idx == other.point_idx);
+ return (_name == other._name &&
+ _point == other._point);
}
+
+ MetricName name() const { return _name; }
+ Point point() const { return _point; }
+
};
} // namespace vespalib::metrics
@@ -43,7 +47,7 @@ namespace std
typedef std::size_t result_type;
result_type operator()(argument_type const& ident) const noexcept
{
- return (ident.point_idx << 20) + ident.name_idx;
+ return (ident.point().id() << 20) + ident.name().id();
}
};
}
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/metric_name.cpp b/staging_vespalib/src/vespa/vespalib/metrics/metric_name.cpp
new file mode 100644
index 00000000000..2a58d55e945
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/metric_name.cpp
@@ -0,0 +1,2 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "metric_name.h"
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/metric_name.h b/staging_vespalib/src/vespa/vespalib/metrics/metric_name.h
new file mode 100644
index 00000000000..baf35b05e45
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/metric_name.h
@@ -0,0 +1,18 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include "handle.h"
+
+namespace vespalib {
+namespace metrics {
+
+/**
+ * Opaque handle representing an uniquely named metric.
+ **/
+class MetricName : public Handle<MetricName> {
+public:
+ explicit MetricName(size_t id) : Handle<MetricName>(id) {}
+};
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/metric_types.cpp b/staging_vespalib/src/vespa/vespalib/metrics/metric_types.cpp
index 2f34390f7c9..1d633553796 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/metric_types.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/metric_types.cpp
@@ -1,5 +1,6 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "metric_types.h"
+#include <assert.h>
#include <vespa/log/log.h>
LOG_SETUP(".vespalib.metrics.metric_types");
@@ -24,16 +25,10 @@ MetricTypes::check(size_t id, const vespalib::string &name, MetricType ty)
if (old == ty) {
return;
}
- if (old == NONE) {
- _seen[id] = ty;
- return;
- }
LOG(warning, "metric '%s' with different types %s and %s, this will be confusing",
name.c_str(), _typeNames[ty], _typeNames[old]);
}
- while (_seen.size() < id) {
- _seen.push_back(NONE);
- }
+ assert (_seen.size() == id);
_seen.push_back(ty);
}
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/metric_types.h b/staging_vespalib/src/vespa/vespalib/metrics/metric_types.h
index e2f30d18b4c..5bda0230bd4 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/metric_types.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/metric_types.h
@@ -12,7 +12,7 @@ class MetricTypes {
static const char *_typeNames[];
public:
enum MetricType {
- NONE,
+ INVALID,
COUNTER,
GAUGE,
HISTOGRAM,
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/metrics_manager.h b/staging_vespalib/src/vespa/vespalib/metrics/metrics_manager.h
index e05d42810cb..2742252ed44 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/metrics_manager.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/metrics_manager.h
@@ -7,7 +7,7 @@
#include "name_collection.h"
#include "counter.h"
#include "gauge.h"
-#include "mergers.h"
+#include "current_samples.h"
#include "snapshots.h"
#include "point.h"
#include "point_builder.h"
@@ -34,15 +34,16 @@ public:
}
virtual PointBuilder pointBuilder(Point from) = 0;
- virtual Point pointFrom(PointMapBacking &&map) = 0;
+ virtual Point pointFrom(PointMap::BackingMap map) = 0;
virtual Snapshot snapshot() = 0;
+ virtual Snapshot totalSnapshot() = 0;
// for use from Counter only
- virtual void add(CounterIncrement inc) = 0;
+ virtual void add(Counter::Increment inc) = 0;
// for use from Gauge only
- virtual void sample(GaugeMeasurement value) = 0;
+ virtual void sample(Gauge::Measurement value) = 0;
};
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/name_collection.cpp b/staging_vespalib/src/vespa/vespalib/metrics/name_collection.cpp
index 61dec6ef048..697d41c4c6b 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/name_collection.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/name_collection.cpp
@@ -8,9 +8,8 @@ namespace metrics {
using Guard = std::lock_guard<std::mutex>;
const vespalib::string &
-NameCollection::lookup(int idx) const
+NameCollection::lookup(size_t id) const
{
- size_t id = idx;
Guard guard(_lock);
assert(id < _names_by_id.size());
return _names_by_id[id]->first;
@@ -20,16 +19,12 @@ size_t
NameCollection::resolve(const vespalib::string& name)
{
Guard guard(_lock);
- Map::const_iterator iter = _names.find(name);
- if (iter != _names.end()) {
- return iter->second;
- } else {
- size_t id = _names_by_id.size();
- auto iter_check = _names.insert(Map::value_type(name, id));
- assert(iter_check.second);
+ size_t nextId = _names_by_id.size();
+ auto iter_check = _names.emplace(name, nextId);
+ if (iter_check.second) {
_names_by_id.push_back(iter_check.first);
- return id;
}
+ return iter_check.first->second;
}
size_t
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/name_collection.h b/staging_vespalib/src/vespa/vespalib/metrics/name_collection.h
index 536075b2987..6fd25552d6e 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/name_collection.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/name_collection.h
@@ -16,7 +16,7 @@ private:
Map _names;
std::vector<Map::const_iterator> _names_by_id;
public:
- const vespalib::string &lookup(int idx) const;
+ const vespalib::string &lookup(size_t id) const;
size_t resolve(const vespalib::string& name);
size_t size() const;
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/point.h b/staging_vespalib/src/vespa/vespalib/metrics/point.h
index 5843f6d3c51..3ef66f731f6 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/point.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/point.h
@@ -1,20 +1,18 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <cstddef>
+#include "handle.h"
namespace vespalib {
namespace metrics {
-class Point {
-private:
- const size_t _point_idx;
+/**
+ * Opaque handle representing an unique N-dimensional point
+ **/
+class Point : public Handle<Point> {
public:
- size_t id() const { return _point_idx; }
-
static Point empty;
-
- explicit Point(size_t id) : _point_idx(id) {}
+ explicit Point(size_t id) : Handle<Point>(id) {}
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/point_builder.cpp b/staging_vespalib/src/vespa/vespalib/metrics/point_builder.cpp
index c2846ef592e..7ee4ca35d0e 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/point_builder.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/point_builder.cpp
@@ -10,7 +10,7 @@ PointBuilder::PointBuilder(std::shared_ptr<MetricsManager> m)
{}
PointBuilder::PointBuilder(std::shared_ptr<MetricsManager> m,
- const PointMapBacking &copyFrom)
+ const PointMap::BackingMap &copyFrom)
: _owner(std::move(m)), _map(copyFrom)
{}
@@ -18,7 +18,7 @@ PointBuilder &&
PointBuilder::bind(Dimension dimension, Label label) &&
{
_map.erase(dimension);
- _map.insert(PointMapBacking::value_type(dimension, label));
+ _map.emplace(dimension, label);
return std::move(*this);
}
@@ -40,7 +40,7 @@ PointBuilder::bind(DimensionName dimension, LabelValue label) &&
Point
PointBuilder::build()
{
- return _owner->pointFrom(PointMapBacking(_map));
+ return _owner->pointFrom(PointMap::BackingMap(_map));
}
PointBuilder::operator Point() &&
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/point_builder.h b/staging_vespalib/src/vespa/vespalib/metrics/point_builder.h
index ca0d21b9b8a..84d4c7fb569 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/point_builder.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/point_builder.h
@@ -15,11 +15,11 @@ class MetricsManager;
class PointBuilder {
private:
std::shared_ptr<MetricsManager> _owner;
- PointMapBacking _map;
+ PointMap::BackingMap _map;
public:
PointBuilder(std::shared_ptr<MetricsManager> m);
- PointBuilder(std::shared_ptr<MetricsManager> m, const PointMapBacking &from);
+ PointBuilder(std::shared_ptr<MetricsManager> m, const PointMap::BackingMap &from);
~PointBuilder() {}
PointBuilder &&bind(Dimension dimension, Label label) &&;
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/point_map.cpp b/staging_vespalib/src/vespa/vespalib/metrics/point_map.cpp
index 5fb29cee005..ca62a3a7d6e 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/point_map.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/point_map.cpp
@@ -5,11 +5,11 @@
namespace vespalib {
namespace metrics {
-PointMap::PointMap(PointMapBacking &&from)
+PointMap::PointMap(BackingMap &&from)
: _map(std::move(from)),
_hash(0)
{
- for (const PointMapBacking::value_type &entry : _map) {
+ for (const BackingMap::value_type &entry : _map) {
_hash = (_hash << 7) + (_hash >> 31) + entry.first.id();
_hash = (_hash << 7) + (_hash >> 31) + entry.second.id();
}
@@ -19,21 +19,26 @@ bool
PointMap::operator< (const PointMap &other) const
{
// cheap comparison first
- if (_hash < other._hash) return true;
- if (_hash > other._hash) return false;
+ if (_hash != other._hash) {
+ return _hash < other._hash;
+ }
+ if (_map.size() != other._map.size()) {
+ return _map.size() < other._map.size();
+ }
+ // sizes equal, iterate in parallel
auto m = _map.begin();
auto o = other._map.begin();
while (m != _map.end()) {
- size_t my_f = m->first.id();
- size_t ot_f = o->first.id();
- if (my_f < ot_f) return true;
- if (my_f > ot_f) return false;
-
- size_t my_s = m->second.id();
- size_t ot_s = o->second.id();
- if (my_s < ot_s) return true;
- if (my_s > ot_s) return false;
-
+ const Dimension& d1 = m->first;
+ const Dimension& d2 = o->first;
+ if (d1 != d2) {
+ return d1 < d2;
+ }
+ const Label &l1 = m->second;
+ const Label &l2 = o->second;
+ if (l1 != l2) {
+ return l1 != l2;
+ }
++m;
++o;
}
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/point_map.h b/staging_vespalib/src/vespa/vespalib/metrics/point_map.h
index fd4498e1b20..2810aa1aa9d 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/point_map.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/point_map.h
@@ -8,18 +8,18 @@
namespace vespalib {
namespace metrics {
-using PointMapBacking = std::map<Dimension, Label>;
-
class PointMap {
+public:
+ using BackingMap = std::map<Dimension, Label>;
private:
- const PointMapBacking _map;
+ const PointMap::BackingMap _map;
size_t _hash;
public:
PointMap() : _map(), _hash(0) {}
- PointMap(PointMapBacking &&from);
+ PointMap(BackingMap &&from);
bool operator< (const PointMap &other) const;
- const PointMapBacking &backing() const { return _map; }
+ const BackingMap &backingMap() const { return _map; }
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.cpp b/staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.cpp
new file mode 100644
index 00000000000..7b09fbf7746
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.cpp
@@ -0,0 +1,39 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "point_map_collection.h"
+#include <assert.h>
+
+namespace vespalib {
+namespace metrics {
+
+using Guard = std::lock_guard<std::mutex>;
+
+const PointMap &
+PointMapCollection::lookup(size_t id)
+{
+ Guard guard(_lock);
+ assert(id < _vec.size());
+ PointMapMap::const_iterator iter = _vec[id];
+ return iter->first;
+}
+
+size_t
+PointMapCollection::resolve(PointMap map)
+{
+ Guard guard(_lock);
+ size_t nextId = _vec.size();
+ auto iter_check = _map.emplace(std::move(map), nextId);
+ if (iter_check.second) {
+ _vec.push_back(iter_check.first);
+ }
+ return iter_check.first->second;
+}
+
+size_t
+PointMapCollection::size() const
+{
+ Guard guard(_lock);
+ return _vec.size();
+}
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.h b/staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.h
new file mode 100644
index 00000000000..83891e7fa0c
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/point_map_collection.h
@@ -0,0 +1,29 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <mutex>
+#include <map>
+#include <vector>
+#include "point_map.h"
+
+namespace vespalib {
+namespace metrics {
+
+class PointMapCollection {
+private:
+ using PointMapMap = std::map<PointMap, size_t>;
+
+ mutable std::mutex _lock;
+ PointMapMap _map;
+ std::vector<PointMapMap::const_iterator> _vec;
+public:
+ const PointMap &lookup(size_t id);
+ size_t resolve(PointMap map);
+ size_t size() const;
+
+ PointMapCollection() = default;
+ ~PointMapCollection() {}
+};
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.cpp b/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.cpp
index 9c55a4e2aff..4d906df8624 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.cpp
@@ -20,18 +20,17 @@ SimpleMetricsManager::SimpleMetricsManager(const SimpleManagerConfig &config)
_buckets(),
_firstBucket(0),
_maxBuckets(config.sliding_window_seconds),
- _stopFlag(false),
- _collectorThread(doCollectLoop, this)
+ _totalsBucket(_startTime, _startTime),
+ _ticker(this)
{
if (_maxBuckets < 1) _maxBuckets = 1;
- Point empty = pointFrom(PointMapBacking());
+ Point empty = pointFrom(PointMap::BackingMap());
assert(empty.id() == 0);
}
SimpleMetricsManager::~SimpleMetricsManager()
{
- _stopFlag = true;
- _collectorThread.join();
+ _ticker.stop();
}
@@ -46,18 +45,18 @@ Counter
SimpleMetricsManager::counter(const vespalib::string &name)
{
size_t id = _metricNames.resolve(name);
- _metricTypes.check(id, name, MetricTypes::COUNTER);
- LOG(debug, "metric name %s -> %zd", name.c_str(), id);
- return Counter(shared_from_this(), MetricIdentifier(id));
+ _metricTypes.check(id, name, MetricTypes::MetricType::COUNTER);
+ LOG(debug, "counter with metric name %s -> %zd", name.c_str(), id);
+ return Counter(shared_from_this(), MetricName(id));
}
Gauge
SimpleMetricsManager::gauge(const vespalib::string &name)
{
size_t id = _metricNames.resolve(name);
- _metricTypes.check(id, name, MetricTypes::GAUGE);
- LOG(debug, "metric name %s -> %zd", name.c_str(), id);
- return Gauge(shared_from_this(), MetricIdentifier(id));
+ _metricTypes.check(id, name, MetricTypes::MetricType::GAUGE);
+ LOG(debug, "gauge with metric name %s -> %zd", name.c_str(), id);
+ return Gauge(shared_from_this(), MetricName(id));
}
Bucket
@@ -78,36 +77,34 @@ SimpleMetricsManager::mergeBuckets()
}
Snapshot
-SimpleMetricsManager::snapshot()
+SimpleMetricsManager::snapshotFrom(const Bucket &bucket)
{
- Bucket merged = mergeBuckets();
std::vector<PointSnapshot> points;
- std::chrono::microseconds s = since_epoch(merged.startTime);
- std::chrono::microseconds e = since_epoch(merged.endTime);
+ std::chrono::microseconds s = since_epoch(bucket.startTime);
+ std::chrono::microseconds e = since_epoch(bucket.endTime);
const double micro = 0.000001;
Snapshot snap(s.count() * micro, e.count() * micro);
{
- Guard guard(_pointMaps.lock);
- for (auto entry : _pointMaps.vec) {
- const PointMapBacking &map = entry->first.backing();
+ for (size_t i = 0; i < _pointMaps.size(); ++i) {
+ const PointMap::BackingMap &map = _pointMaps.lookup(i).backingMap();
PointSnapshot point;
- for (const PointMapBacking::value_type &kv : map) {
+ for (const PointMap::BackingMap::value_type &kv : map) {
point.dimensions.emplace_back(nameFor(kv.first), valueFor(kv.second));
}
snap.add(point);
}
}
- for (const CounterAggregator& entry : merged.counters) {
- size_t ni = entry.idx.name_idx;
- size_t pi = entry.idx.point_idx;
+ for (const CounterAggregator& entry : bucket.counters) {
+ size_t ni = entry.idx.name().id();
+ size_t pi = entry.idx.point().id();
const vespalib::string &name = _metricNames.lookup(ni);
CounterSnapshot val(name, snap.points()[pi], entry);
snap.add(val);
}
- for (const GaugeAggregator& entry : merged.gauges) {
- size_t ni = entry.idx.name_idx;
- size_t pi = entry.idx.point_idx;
+ for (const GaugeAggregator& entry : bucket.gauges) {
+ size_t ni = entry.idx.name().id();
+ size_t pi = entry.idx.point().id();
const vespalib::string &name = _metricNames.lookup(ni);
GaugeSnapshot val(name, snap.points()[pi], entry);
snap.add(val);
@@ -115,19 +112,18 @@ SimpleMetricsManager::snapshot()
return snap;
}
-void
-SimpleMetricsManager::doCollectLoop(SimpleMetricsManager *me)
+Snapshot
+SimpleMetricsManager::snapshot()
{
- const std::chrono::milliseconds jiffy{20};
- const std::chrono::seconds oneSec{1};
- while (!me->_stopFlag) {
- std::this_thread::sleep_for(jiffy);
- InternalTimeStamp now = now_stamp();
- InternalTimeStamp::duration elapsed = now - me->_curTime;
- if (elapsed >= oneSec) {
- me->collectCurrentBucket();
- }
- }
+ Bucket merged = mergeBuckets();
+ return snapshotFrom(merged);
+}
+
+Snapshot
+SimpleMetricsManager::totalSnapshot()
+{
+ Guard guard(_bucketsLock);
+ return snapshotFrom(_totalsBucket);
}
void
@@ -141,15 +137,15 @@ SimpleMetricsManager::collectCurrentBucket()
Guard guard(_currentBucket.lock);
swap(samples, _currentBucket);
}
+ Bucket newBucket(prev, curr);
+ newBucket.merge(samples);
- Bucket merger(prev, curr);
Guard guard(_bucketsLock);
+ _totalsBucket.merge(newBucket);
if (_buckets.size() < _maxBuckets) {
- _buckets.push_back(merger);
- _buckets.back().merge(samples);
+ _buckets.emplace_back(std::move(newBucket));
} else {
- merger.merge(samples);
- swap(_buckets[_firstBucket], merger);
+ _buckets[_firstBucket] = std::move(newBucket);
_firstBucket = (_firstBucket + 1) % _buckets.size();
}
_curTime = curr;
@@ -174,24 +170,15 @@ SimpleMetricsManager::label(const vespalib::string &value)
PointBuilder
SimpleMetricsManager::pointBuilder(Point from)
{
- Guard guard(_pointMaps.lock);
- const PointMap &map = _pointMaps.vec[from.id()]->first;
- return PointBuilder(shared_from_this(), map.backing());
+ const PointMap &map = _pointMaps.lookup(from.id());
+ return PointBuilder(shared_from_this(), map.backingMap());
}
Point
-SimpleMetricsManager::pointFrom(PointMapBacking &&map)
+SimpleMetricsManager::pointFrom(PointMap::BackingMap map)
{
- Guard guard(_pointMaps.lock);
- size_t nextId = _pointMaps.vec.size();
- auto iter_check = _pointMaps.map.emplace(std::move(map), nextId);
- if (iter_check.second) {
- LOG(debug, "new point map -> %zd / %zd", nextId, iter_check.first->second);
- _pointMaps.vec.push_back(iter_check.first);
- } else {
- LOG(debug, "found point map -> %zd", iter_check.first->second);
- }
- return Point(iter_check.first->second);
+ size_t id = _pointMaps.resolve(PointMap(std::move(map)));
+ return Point(id);
}
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.h b/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.h
index a768ef7f29e..5f6cb881480 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/simple_metrics_manager.h
@@ -5,11 +5,14 @@
#include <thread>
#include <vespa/vespalib/stllike/string.h>
#include "name_collection.h"
-#include "mergers.h"
+#include "current_samples.h"
#include "snapshots.h"
#include "metrics_manager.h"
#include "metric_types.h"
#include "clock.h"
+#include "point_map_collection.h"
+#include "bucket.h"
+#include "ticker_thread.h"
namespace vespalib {
namespace metrics {
@@ -26,7 +29,7 @@ struct SimpleManagerConfig {
* single global repo with std::mutex locks used around
* most operations. Only implements sliding window
* and a fixed (1 Hz) collecting interval.
- * Consider renaming to "LockingManager" or "SlidingWindowManager".
+ * XXX: Consider renaming this to "SlidingWindowManager".
**/
class SimpleMetricsManager : public MetricsManager
{
@@ -35,12 +38,7 @@ private:
MetricTypes _metricTypes;
NameCollection _dimensionNames;
NameCollection _labelValues;
- using PointMapMap = std::map<PointMap, size_t>;
- struct {
- std::mutex lock;
- PointMapMap map;
- std::vector<PointMapMap::const_iterator> vec;
- } _pointMaps;
+ PointMapCollection _pointMaps;
const vespalib::string& nameFor(Dimension dimension) { return _dimensionNames.lookup(dimension.id()); }
const vespalib::string& valueFor(Label label) { return _labelValues.lookup(label.id()); }
@@ -54,12 +52,12 @@ private:
std::vector<Bucket> _buckets;
size_t _firstBucket;
size_t _maxBuckets;
+ Bucket _totalsBucket;
- bool _stopFlag;
- std::thread _collectorThread;
- static void doCollectLoop(SimpleMetricsManager *me);
+ TickerThread _ticker;
void collectCurrentBucket(); // called once per second from another thread
Bucket mergeBuckets();
+ Snapshot snapshotFrom(const Bucket &bucket);
SimpleMetricsManager(const SimpleManagerConfig &config);
public:
@@ -71,17 +69,20 @@ public:
Dimension dimension(const vespalib::string &name) override;
Label label(const vespalib::string &value) override;
PointBuilder pointBuilder(Point from) override;
- Point pointFrom(PointMapBacking &&map) override;
+ Point pointFrom(PointMap::BackingMap map) override;
Snapshot snapshot() override;
+ Snapshot totalSnapshot() override;
// for use from Counter only
- void add(CounterIncrement inc) override {
+ void add(Counter::Increment inc) override {
_currentBucket.add(inc);
}
// for use from Gauge only
- void sample(GaugeMeasurement value) override {
+ void sample(Gauge::Measurement value) override {
_currentBucket.sample(value);
}
+
+ void tick() { collectCurrentBucket(); }
};
} // namespace vespalib::metrics
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/snapshots.h b/staging_vespalib/src/vespa/vespalib/metrics/snapshots.h
index 87be72d2d52..406df44d894 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/snapshots.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/snapshots.h
@@ -2,37 +2,41 @@
#pragma once
#include <vespa/vespalib/stllike/string.h>
-#include "mergers.h"
+#include <vector>
+#include "counter_aggregator.h"
+#include "gauge_aggregator.h"
namespace vespalib {
namespace metrics {
-class AxisMeasure {
+class DimensionBinding {
private:
- const vespalib::string &_dimensionName;
- const vespalib::string &_labelValue;
+ const vespalib::string _dimensionName;
+ const vespalib::string _labelValue;
public:
const vespalib::string &dimensionName() const { return _dimensionName; }
const vespalib::string &labelValue() const { return _labelValue; }
- AxisMeasure(const vespalib::string &a,
- const vespalib::string &v)
+ DimensionBinding(const vespalib::string &a,
+ const vespalib::string &v)
: _dimensionName(a), _labelValue(v)
{}
+ ~DimensionBinding() {}
};
struct PointSnapshot {
- std::vector<AxisMeasure> dimensions;
+ std::vector<DimensionBinding> dimensions;
};
class CounterSnapshot {
private:
- const vespalib::string &_name;
+ const vespalib::string _name;
const PointSnapshot &_point;
const size_t _count;
public:
CounterSnapshot(const vespalib::string &n, const PointSnapshot &p, const CounterAggregator &c)
: _name(n), _point(p), _count(c.count)
{}
+ ~CounterSnapshot() {}
const vespalib::string &name() const { return _name; }
const PointSnapshot &point() const { return _point; }
size_t count() const { return _count; }
@@ -40,7 +44,7 @@ public:
class GaugeSnapshot {
private:
- const vespalib::string &_name;
+ const vespalib::string _name;
const PointSnapshot &_point;
const size_t _observedCount;
const double _averageValue;
@@ -57,6 +61,7 @@ public:
_maxValue(c.maxValue),
_lastValue(c.lastValue)
{}
+ ~GaugeSnapshot() {}
const vespalib::string &name() const { return _name; }
const PointSnapshot &point() const { return _point; }
size_t observedCount() const { return _observedCount; }
@@ -91,6 +96,7 @@ public:
Snapshot(double s, double e)
: _start(s), _end(e), _counters(), _gauges()
{}
+ ~Snapshot() {}
void add(const PointSnapshot &entry) { _points.push_back(entry); }
void add(const CounterSnapshot &entry) { _counters.push_back(entry); }
void add(const GaugeSnapshot &entry) { _gauges.push_back(entry); }
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/no_realloc_bunch.cpp b/staging_vespalib/src/vespa/vespalib/metrics/stable_store.cpp
index 4e641ff1c31..dd649133988 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/no_realloc_bunch.cpp
+++ b/staging_vespalib/src/vespa/vespalib/metrics/stable_store.cpp
@@ -1,4 +1,4 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include "no_realloc_bunch.h"
+#include "stable_store.h"
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/no_realloc_bunch.h b/staging_vespalib/src/vespa/vespalib/metrics/stable_store.h
index e5bd8f7af62..ca9db21a2d8 100644
--- a/staging_vespalib/src/vespa/vespalib/metrics/no_realloc_bunch.h
+++ b/staging_vespalib/src/vespa/vespalib/metrics/stable_store.h
@@ -9,16 +9,16 @@
namespace vespalib {
template <typename T>
-class NoReallocBunch
+class StableStore
{
- using MyClass = NoReallocBunch<T>;
+ using MyClass = StableStore<T>;
template<typename U>
- friend void swap(NoReallocBunch<U> &a, NoReallocBunch<U> &b);
+ friend void swap(StableStore<U> &a, StableStore<U> &b);
public:
typedef std::unique_ptr<MyClass> UP;
- NoReallocBunch();
- ~NoReallocBunch() {}
+ StableStore();
+ ~StableStore() {}
void add(T t) {
size_t sz = _mine.size();
@@ -33,7 +33,7 @@ public:
}
template<typename FUNC>
- void apply(FUNC &&func) const {
+ void for_each(FUNC &&func) const {
std::vector<const MyClass *> vv;
dffill(vv);
for (const MyClass *p : vv) {
@@ -45,28 +45,13 @@ public:
size_t size() const { return _size; }
- const T& lookup(size_t idx) const {
- assert(idx < _size);
- std::vector<const MyClass *> vv;
- dffill(vv);
- for (const MyClass *p : vv) {
- size_t sz = p->_mine.size();
- if (idx < sz) {
- return p->_mine[idx];
- }
- idx -= sz;
- }
- // assert:
- return *((T*)nullptr);
- }
-
private:
void dffill(std::vector<const MyClass *> &vv) const {
if (_more) { _more->dffill(vv); }
vv.push_back(this);
}
- NoReallocBunch(size_t sz, UP &&more, std::vector<T> &&mine);
+ StableStore(size_t sz, UP &&more, std::vector<T> &&mine);
size_t _size;
UP _more;
@@ -74,7 +59,7 @@ private:
};
template<typename T>
-NoReallocBunch<T>::NoReallocBunch()
+StableStore<T>::StableStore()
: _size(0),
_more(),
_mine()
@@ -83,15 +68,15 @@ NoReallocBunch<T>::NoReallocBunch()
}
template<typename T>
-NoReallocBunch<T>::NoReallocBunch(size_t sz, UP &&more, std::vector<T> &&mine)
+StableStore<T>::StableStore(size_t sz, UP &&more, std::vector<T> &&mine)
: _size(sz),
_more(std::move(more)),
_mine(std::move(mine))
{}
template <typename T>
-void swap(NoReallocBunch<T> &a,
- NoReallocBunch<T> &b)
+void swap(StableStore<T> &a,
+ StableStore<T> &b)
{
using std::swap;
swap(a._size, b._size);
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.cpp b/staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.cpp
new file mode 100644
index 00000000000..dfed3bd053d
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.cpp
@@ -0,0 +1,43 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "ticker_thread.h"
+#include "simple_metrics_manager.h"
+#include <chrono>
+
+#include <vespa/log/log.h>
+LOG_SETUP(".vespalib.metrics.ticker_thread");
+
+namespace vespalib {
+namespace metrics {
+
+void
+TickerThread::doTickerLoop(TickerThread *me)
+{
+ me->tickerLoop();
+}
+
+void
+TickerThread::tickerLoop()
+{
+ const std::chrono::seconds oneSec{1};
+ std::unique_lock<std::mutex> locker(_lock);
+ while (_runFlag) {
+ auto r = _cond.wait_for(locker, oneSec);
+ if (r == std::cv_status::timeout) {
+ _owner->tick();
+ }
+ }
+}
+
+void
+TickerThread::stop()
+{
+ std::unique_lock<std::mutex> locker(_lock);
+ _runFlag.store(false);
+ _cond.notify_all();
+ locker.unlock();
+ _thread.join();
+}
+
+
+} // namespace vespalib::metrics
+} // namespace vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.h b/staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.h
new file mode 100644
index 00000000000..e00b68e8486
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/metrics/ticker_thread.h
@@ -0,0 +1,36 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+namespace vespalib {
+namespace metrics {
+
+class SimpleMetricsManager;
+
+class TickerThread {
+private:
+ SimpleMetricsManager *_owner;
+ std::mutex _lock;
+ std::atomic<bool> _runFlag;
+ std::condition_variable _cond;
+ std::thread _thread;
+
+ static void doTickerLoop(TickerThread *me);
+ void tickerLoop();
+public:
+ TickerThread(SimpleMetricsManager * owner)
+ : _owner(owner),
+ _runFlag(true),
+ _thread(doTickerLoop, this)
+ {}
+ ~TickerThread() {}
+
+ void stop();
+};
+
+} // namespace vespalib::metrics
+} // namespace vespalib