diff options
author | 2016-07-28 17:05:02 -0800 | |
---|---|---|
committer | 2016-07-28 18:17:53 -0700 | |
commit | 3aaeb88b29bcb7703df7bc23fb1d3b2a11ffc8ec (patch) | |
tree | b4a831f7a0780f12567c63605e50b85fb50efba0 /tensorflow/core/lib/monitoring | |
parent | f1acb3bd828a73b15670fc8019f06a5cd51bd564 (diff) |
Metric definition for the monitoring API.
- Implements MetricDef, and AbstractMetricDef.
- A metric is defined by its kind, name, description and the description of
its labels.
- Moves CounterCell's implementation from cc file to header to allow inlining.
Change: 128763990
Diffstat (limited to 'tensorflow/core/lib/monitoring')
-rw-r--r-- | tensorflow/core/lib/monitoring/counter.cc | 31 | ||||
-rw-r--r-- | tensorflow/core/lib/monitoring/counter.h | 18 | ||||
-rw-r--r-- | tensorflow/core/lib/monitoring/counter_test.cc | 28 | ||||
-rw-r--r-- | tensorflow/core/lib/monitoring/metric_def.h | 128 |
4 files changed, 162 insertions, 43 deletions
diff --git a/tensorflow/core/lib/monitoring/counter.cc b/tensorflow/core/lib/monitoring/counter.cc deleted file mode 100644 index 37960a4acd..0000000000 --- a/tensorflow/core/lib/monitoring/counter.cc +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. - -Licensed 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 "tensorflow/core/lib/monitoring/counter.h" - -#include "tensorflow/core/platform/logging.h" - -namespace tensorflow { -namespace monitoring { - -void CounterCell::IncrementBy(const int64 step) { - DCHECK_LE(0, step) << "Must not decrement cumulative metrics."; - value_ += step; -} - -int64 CounterCell::value() const { return value_; } - -} // namespace monitoring -} // namespace tensorflow diff --git a/tensorflow/core/lib/monitoring/counter.h b/tensorflow/core/lib/monitoring/counter.h index af76884012..7de85b75cb 100644 --- a/tensorflow/core/lib/monitoring/counter.h +++ b/tensorflow/core/lib/monitoring/counter.h @@ -20,6 +20,8 @@ limitations under the License. #include <atomic> #include <map> +#include "tensorflow/core/lib/monitoring/metric_def.h" +#include "tensorflow/core/platform/logging.h" #include "tensorflow/core/platform/macros.h" #include "tensorflow/core/platform/mutex.h" #include "tensorflow/core/platform/thread_annotations.h" @@ -71,9 +73,12 @@ class CounterCell { template <int NumLabels> class Counter { public: - Counter() {} ~Counter() {} + explicit Counter( + const MetricDef<MetricKind::CUMULATIVE, int64, NumLabels>& metric_def) + : metric_def_(metric_def) {} + // Retrieves the cell for the specified labels, creating it on demand if // not already present. template <typename... Labels> @@ -82,6 +87,10 @@ class Counter { private: mutable mutex mu_; + // The metric definition. This will be used to identify the metric when we + // register it for exporting. + const MetricDef<MetricKind::CUMULATIVE, int64, NumLabels> metric_def_; + using LabelArray = std::array<string, NumLabels>; std::map<LabelArray, CounterCell> cells_ GUARDED_BY(mu_); @@ -92,6 +101,13 @@ class Counter { // Implementation details follow. API readers may skip. //// +inline void CounterCell::IncrementBy(const int64 step) { + DCHECK_LE(0, step) << "Must not decrement cumulative metrics."; + value_ += step; +} + +inline int64 CounterCell::value() const { return value_; } + template <int NumLabels> template <typename... Labels> CounterCell* Counter<NumLabels>::GetCell(const Labels&... labels) diff --git a/tensorflow/core/lib/monitoring/counter_test.cc b/tensorflow/core/lib/monitoring/counter_test.cc index 0010662e26..0e42aed794 100644 --- a/tensorflow/core/lib/monitoring/counter_test.cc +++ b/tensorflow/core/lib/monitoring/counter_test.cc @@ -19,26 +19,28 @@ limitations under the License. namespace tensorflow { namespace monitoring { +namespace { class LabeledCounterTest : public ::testing::Test { protected: LabeledCounterTest() {} - Counter<1> counter_; + Counter<1> counter_with_labels_{{"/tensorflow/test/counter_with_labels_", + "Counter with one label.", "One label"}}; }; TEST_F(LabeledCounterTest, InitializedWithZero) { - EXPECT_EQ(0, counter_.GetCell("Empty")->value()); + EXPECT_EQ(0, counter_with_labels_.GetCell("Empty")->value()); } TEST_F(LabeledCounterTest, GetCell) { - auto* cell = counter_.GetCell("GetCellOp"); + auto* cell = counter_with_labels_.GetCell("GetCellOp"); EXPECT_EQ(0, cell->value()); cell->IncrementBy(42); EXPECT_EQ(42, cell->value()); - auto* same_cell = counter_.GetCell("GetCellOp"); + auto* same_cell = counter_with_labels_.GetCell("GetCellOp"); EXPECT_EQ(42, same_cell->value()); same_cell->IncrementBy(58); @@ -49,29 +51,31 @@ TEST_F(LabeledCounterTest, GetCell) { using LabeledCounterDeathTest = LabeledCounterTest; TEST_F(LabeledCounterDeathTest, DiesOnDecrement) { - EXPECT_DEBUG_DEATH({ counter_.GetCell("DyingOp")->IncrementBy(-1); }, - "decrement"); + EXPECT_DEBUG_DEATH( + { counter_with_labels_.GetCell("DyingOp")->IncrementBy(-1); }, + "decrement"); } class UnlabeledCounterTest : public ::testing::Test { protected: UnlabeledCounterTest() {} - Counter<0> counter_; + Counter<0> counter_without_labels_{ + {"/tensorflow/test/counter0", "Counter without any labels."}}; }; TEST_F(UnlabeledCounterTest, InitializedWithZero) { - EXPECT_EQ(0, counter_.GetCell()->value()); + EXPECT_EQ(0, counter_without_labels_.GetCell()->value()); } TEST_F(UnlabeledCounterTest, GetCell) { - auto* cell = counter_.GetCell(); + auto* cell = counter_without_labels_.GetCell(); EXPECT_EQ(0, cell->value()); cell->IncrementBy(42); EXPECT_EQ(42, cell->value()); - auto* same_cell = counter_.GetCell(); + auto* same_cell = counter_without_labels_.GetCell(); EXPECT_EQ(42, same_cell->value()); same_cell->IncrementBy(58); @@ -82,8 +86,10 @@ TEST_F(UnlabeledCounterTest, GetCell) { using UnlabeledCounterDeathTest = UnlabeledCounterTest; TEST_F(UnlabeledCounterDeathTest, DiesOnDecrement) { - EXPECT_DEBUG_DEATH({ counter_.GetCell()->IncrementBy(-1); }, "decrement"); + EXPECT_DEBUG_DEATH({ counter_without_labels_.GetCell()->IncrementBy(-1); }, + "decrement"); } +} // namespace } // namespace monitoring } // namespace tensorflow diff --git a/tensorflow/core/lib/monitoring/metric_def.h b/tensorflow/core/lib/monitoring/metric_def.h new file mode 100644 index 0000000000..f7037359eb --- /dev/null +++ b/tensorflow/core/lib/monitoring/metric_def.h @@ -0,0 +1,128 @@ +/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. + +Licensed 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. +==============================================================================*/ + +#ifndef THIRD_PARTY_TENSORFLOW_CORE_LIB_MONITORING_METRIC_DEF_H_ +#define THIRD_PARTY_TENSORFLOW_CORE_LIB_MONITORING_METRIC_DEF_H_ + +#include <array> +#include <vector> + +#include "tensorflow/core/lib/core/stringpiece.h" + +namespace tensorflow { +namespace monitoring { + +// Everything in the internal namespace is implementation details. Do not depend +// on this. +namespace internal { + +// Ensures that the string is a compile-time string literal. +class StringLiteral { + public: + // We allow implicit conversions here on purpose. + template <int N> + StringLiteral(const char (&data)[N]) : literal_(data, N) {} + + // This ctor will be called for non-literals, causing compile-time failure. + template <typename NotStringLiteral> + StringLiteral(const NotStringLiteral& not_string_literal) = delete; + + // Implicit conversion to StringPiece. + operator StringPiece() const { return literal_; } + + private: + const StringPiece literal_; +}; + +} // namespace internal + +// The different metric kinds available. +// +// Gauge indicates that the metric's values are instantaneous measurements of a +// (typically) continuously varying quantity. Examples: a process's current heap +// size, a queue's current length. +// +// Cumulative indicates that the metric's values represent non-negative changes +// over specified time periods. Example: the number of rpc calls to a service. +enum MetricKind { GAUGE, CUMULATIVE }; + +// Abstract base class for a metric definition. +// +// Unlike MetricDef, this class is non-templatized and allows storing and +// accessing metric definitions without the full type information. +// +// Everything except the value type of a metric is stored here. Please read +// MetricDef class comments for more details. +class AbstractMetricDef { + public: + MetricKind kind() const { return kind_; } + + StringPiece name() const { return name_; } + + StringPiece description() const { return description_; } + + const std::vector<StringPiece> label_descriptions() const { + return label_descriptions_; + } + + private: + template <MetricKind kind, typename Value, int NumLabels> + friend class MetricDef; + + AbstractMetricDef( + const MetricKind kind, const internal::StringLiteral name, + const internal::StringLiteral description, + const std::vector<internal::StringLiteral>& label_descriptions) + : kind_(kind), + name_(name), + description_(description), + label_descriptions_( + {label_descriptions.begin(), label_descriptions.end()}) {} + + const MetricKind kind_; + const StringPiece name_; + const StringPiece description_; + const std::vector<StringPiece> label_descriptions_; +}; + +// Metric definition. +// +// A metric is defined by its kind, value-type, name, description and the +// description of its labels. +// +// NOTE: We allow only string literals for the name, description and label +// descriptions because these should be fixed at compile-time and shouldn't be +// dynamic. +template <MetricKind metric_kind, typename Value, int NumLabels> +class MetricDef : public AbstractMetricDef { + public: + using value_type = Value; + + template <typename... LabelDesc> + MetricDef(const internal::StringLiteral name, + const internal::StringLiteral description, + const LabelDesc&... label_descriptions) + : AbstractMetricDef(metric_kind, name, description, + {label_descriptions...}) { + static_assert(sizeof...(LabelDesc) == NumLabels, + "Mismatch between Counter<NumLabels> and number of label " + "descriptions."); + } +}; + +} // namespace monitoring +} // namespace tensorflow + +#endif // THIRD_PARTY_TENSORFLOW_CORE_LIB_MONITORING_METRIC_DEF_H_ |