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
This commit is contained in:
parent
f1acb3bd82
commit
3aaeb88b29
@ -156,6 +156,7 @@ cc_library(
|
||||
"lib/io/table_options.h",
|
||||
"lib/jpeg/jpeg_mem.h",
|
||||
"lib/monitoring/counter.h",
|
||||
"lib/monitoring/metric_def.h",
|
||||
"lib/random/distribution_sampler.h",
|
||||
"lib/random/philox_random.h",
|
||||
"lib/random/simple_philox.h", # TODO(josh11b): make internal
|
||||
|
@ -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
|
@ -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)
|
||||
|
@ -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
|
||||
|
128
tensorflow/core/lib/monitoring/metric_def.h
Normal file
128
tensorflow/core/lib/monitoring/metric_def.h
Normal file
@ -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_
|
Loading…
x
Reference in New Issue
Block a user