YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/metrics.h
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
#ifndef YB_UTIL_METRICS_H
33
#define YB_UTIL_METRICS_H
34
35
/////////////////////////////////////////////////////
36
// YB Metrics
37
/////////////////////////////////////////////////////
38
//
39
// Summary
40
// ------------------------------------------------------------
41
//
42
// This API provides a basic set of metrics primitives along the lines of the Coda Hale's
43
// metrics library along with JSON formatted output of running metrics.
44
//
45
// The metrics system has a few main concepts in its data model:
46
//
47
// Metric Prototypes
48
// -----------------
49
// Every metric that may be emitted is constructed from a prototype. The prototype defines
50
// the name of the metric, the entity it is attached to, its type, its units, and a description.
51
//
52
// Metric prototypes are defined statically using the METRIC_DEFINE_*(...) macros. This
53
// allows us to easily enumerate a full list of every metric that might be emitted from a
54
// server, thus allowing auto-generation of metric metadata for integration with
55
// monitoring systems such as Prometheus.
56
//
57
// Metric Entity Prototypes
58
// ------------------------
59
// The other main type in the data model is the Metric Entity. The most basic entity is the
60
// "server" entity -- metrics such as memory usage, RPC rates, etc, are typically associated
61
// with the server as a whole.
62
//
63
// Users of the metrics framework can define more entity types using the
64
// METRIC_DEFINE_entity(...) macro.
65
//
66
// MetricEntity instances
67
// -----------------------
68
// Each defined Metric Entity Type serves as a prototype allowing instantiation of a
69
// MetricEntity object. Each instance then has its own unique set of metrics. For
70
// example, we define a Metric Entity Type called 'tablet', and the
71
// Tablet Server instantiates one MetricEntity instance per tablet that it hosts.
72
//
73
// MetricEntity instances are instantiated within a MetricRegistry, and each instance is
74
// expected to have a unique string identifier within that registry. To continue the
75
// example above, a tablet entity uses its tablet ID as its unique identifier. These
76
// identifiers are exposed to the operator and surfaced in monitoring tools.
77
//
78
// MetricEntity instances may also carry a key-value map of string attributes. These
79
// attributes are directly exposed to monitoring systems via the JSON output. Monitoring
80
// systems may use this information to allow hierarchical aggregation beteween entities,
81
// display them to the user, etc.
82
//
83
// Metric instances
84
// ----------------
85
// Given a MetricEntity instance and a Metric Prototype, one can instantiate a Metric
86
// instance. For example, the YB Tablet Server instantiates one MetricEntity instance
87
// for each tablet, and then instantiates the 'tablet_rows_inserted' prototype within that
88
// entity. Thus, each tablet then has a separate instance of the metric, allowing the end
89
// operator to track the metric on a per-tablet basis.
90
//
91
//
92
// Types of metrics
93
// ------------------------------------------------------------
94
// Gauge: Set or get a point-in-time value.
95
//  - string: Gauge for a string value.
96
//  - Primitive types (bool, int64_t/uint64_t, double): Lock-free gauges.
97
// Counter: Get, reset, increment or decrement an int64_t value.
98
// Histogram: Increment buckets of values segmented by configurable max and precision.
99
//
100
// Gauge vs. Counter
101
// ------------------------------------------------------------
102
//
103
// A Counter is a metric we expect to only monotonically increase. A
104
// Gauge is a metric that can decrease and increase. Use a Gauge to
105
// reflect a sample, e.g., the number of transaction in-flight at a
106
// given time; use a Counter when considering a metric over time,
107
// e.g., exposing the number of transactions processed since start to
108
// produce a metric for the number of transactions processed over some
109
// time period.
110
//
111
// The one exception to this rule is that occasionally it may be more convenient to
112
// implement a metric as a Gauge, even when it is logically a counter, due to Gauge's
113
// support for fetching metric values via a bound function. In that case, you can
114
// use the 'EXPOSE_AS_COUNTER' flag when defining the gauge prototype. For example:
115
//
116
// METRIC_DEFINE_gauge_uint64(server, threads_started,
117
//                            "Threads Started",
118
//                            yb::MetricUnit::kThreads,
119
//                            "Total number of threads started on this server",
120
//                            yb::EXPOSE_AS_COUNTER);
121
//
122
//
123
// Metrics ownership
124
// ------------------------------------------------------------
125
//
126
// Metrics are reference-counted, and one of the references is always held by a metrics
127
// entity itself. Users of metrics should typically hold a scoped_refptr to their metrics
128
// within class instances, so that they also hold a reference. The one exception to this
129
// is FunctionGauges: see the class documentation below for a typical Gauge ownership pattern.
130
//
131
// Because the metrics entity holds a reference to the metric, this means that metrics will
132
// not be immediately destructed when your class instance publishing them is destructed.
133
// This is on purpose: metrics are retained for a configurable time interval even after they
134
// are no longer being published. The purpose of this is to allow monitoring systems, which
135
// only poll metrics infrequently (eg once a minute) to see the last value of a metric whose
136
// owner was destructed in between two polls.
137
//
138
//
139
// Example usage for server-level metrics
140
// ------------------------------------------------------------
141
//
142
// 1) In your server class, define the top-level registry and the server entity:
143
//
144
//   MetricRegistry metric_registry_;
145
//   scoped_refptr<MetricEntity> metric_entity_;
146
//
147
// 2) In your server constructor/initialization, construct metric_entity_. This instance
148
//    will be plumbed through into other subsystems that want to register server-level
149
//    metrics.
150
//
151
//   metric_entity_ = METRIC_ENTITY_server.Instantiate(&registry_, "some server identifier)");
152
//
153
// 3) At the top of your .cc file where you want to emit a metric, define the metric prototype:
154
//
155
//   METRIC_DEFINE_counter(server, ping_requests, "Ping Requests", yb::MetricUnit::kRequests,
156
//       "Number of Ping() RPC requests this server has handled since start");
157
//
158
// 4) In your class where you want to emit metrics, define the metric instance itself:
159
//   scoped_refptr<Counter> ping_counter_;
160
//
161
// 5) In your class constructor, instantiate the metric based on the MetricEntity plumbed in:
162
//
163
//   MyClass(..., const scoped_refptr<MetricEntity>& metric_entity) :
164
//     ping_counter_(METRIC_ping_requests.Instantiate(metric_entity)) {
165
//   }
166
//
167
// 6) Where you want to change the metric value, just use the instance variable:
168
//
169
//   ping_counter_->IncrementBy(100);
170
//
171
//
172
// Example usage for custom entity metrics
173
// ------------------------------------------------------------
174
// Follow the same pattern as above, but also define a metric entity somewhere. For example:
175
//
176
// At the top of your CC file:
177
//
178
//   METRIC_DEFINE_entity(my_entity);
179
//   METRIC_DEFINE_counter(my_entity, ping_requests, "Ping Requests", yb::MetricUnit::kRequests,
180
//       "Number of Ping() RPC requests this particular entity has handled since start");
181
//
182
// In whatever class represents the entity:
183
//
184
//   entity_ = METRIC_ENTITY_my_entity.Instantiate(&registry_, my_entity_id);
185
//
186
// In whatever classes emit metrics:
187
//
188
//   scoped_refptr<Counter> ping_requests_ = METRIC_ping_requests.Instantiate(entity);
189
//   ping_requests_->Increment();
190
//
191
// NOTE: at runtime, the metrics system prevents you from instantiating a metric in the
192
// wrong entity type. This ensures that the metadata can fully describe the set of metric-entity
193
// relationships.
194
//
195
// Plumbing of MetricEntity and MetricRegistry objects
196
// ------------------------------------------------------------
197
// Generally, the rule of thumb to follow when plumbing through entities and registries is
198
// this: if you're creating new entities or you need to dump the registry contents
199
// (e.g. path handlers), pass in the registry. Otherwise, pass in the entity.
200
//
201
// ===========
202
// JSON output
203
// ===========
204
//
205
// The first-class output format for metrics is pretty-printed JSON.
206
// Such a format is relatively easy for humans and machines to read.
207
//
208
// The top level JSON object is an array, which contains one element per
209
// entity. Each entity is an object which has its type, id, and an array
210
// of metrics. Each metric contains its type, name, unit, description, value,
211
// etc.
212
// TODO: Output to HTML.
213
//
214
// Example JSON output:
215
//
216
// [
217
//     {
218
//         "type": "tablet",
219
//         "id": "e95e57ba8d4d48458e7c7d35020d4a46",
220
//         "attributes": {
221
//           "table_id": "12345",
222
//           "table_name": "my_table"
223
//         },
224
//         "metrics": [
225
//             {
226
//                 "type": "counter",
227
//                 "name": "log_reader_bytes_read",
228
//                 "label": "Log Reader Bytes Read",
229
//                 "unit": "bytes",
230
//                 "description": "Number of bytes read since tablet start",
231
//                 "value": 0
232
//             },
233
//             ...
234
//           ]
235
//      },
236
//      ...
237
// ]
238
//
239
/////////////////////////////////////////////////////
240
241
#include <stdint.h>
242
243
#include <cstdint>
244
#include <cstdlib>
245
#include <set>
246
#include <string>
247
248
#include <boost/preprocessor/cat.hpp>
249
#include <boost/preprocessor/stringize.hpp>
250
#include <gflags/gflags_declare.h>
251
252
#include <gtest/gtest_prod.h>
253
254
#include "yb/gutil/casts.h"
255
#include "yb/gutil/integral_types.h"
256
257
#include "yb/util/metrics_fwd.h"
258
#include "yb/util/status_fwd.h"
259
#include "yb/util/atomic.h"
260
#include "yb/util/jsonwriter.h"
261
#include "yb/util/metrics_writer.h"
262
#include "yb/util/monotime.h"
263
#include "yb/util/shared_lock.h"
264
#include "yb/util/striped64.h"
265
266
// Define a new entity type.
267
//
268
// The metrics subsystem itself defines the entity type 'server', but other
269
// entity types can be registered using this macro.
270
#define METRIC_DEFINE_entity(name)                               \
271
  ::yb::MetricEntityPrototype METRIC_ENTITY_##name(#name)
272
273
// Convenience macros to define metric prototypes.
274
// See the documentation at the top of this file for example usage.
275
#define METRIC_DEFINE_counter_with_level(entity, name, label, unit, desc, level)   \
276
  ::yb::CounterPrototype BOOST_PP_CAT(METRIC_, name)(                        \
277
      ::yb::MetricPrototype::CtorArgs(BOOST_PP_STRINGIZE(entity), \
278
                                      BOOST_PP_STRINGIZE(name), \
279
                                      label, \
280
                                      unit, \
281
                                      desc, \
282
                                      level))
283
284
#define METRIC_DEFINE_counter(entity, name, label, unit, desc)   \
285
  METRIC_DEFINE_counter_with_level(entity, name, label, unit, desc, yb::MetricLevel::kInfo)
286
287
#define METRIC_DEFINE_simple_counter(entity, name, label, unit) \
288
    METRIC_DEFINE_counter(entity, name, label, unit, label)
289
290
#define METRIC_DEFINE_lag_with_level(entity, name, label, desc, level, ...) \
291
  ::yb::MillisLagPrototype BOOST_PP_CAT(METRIC_, name)( \
292
      ::yb::MetricPrototype::CtorArgs(BOOST_PP_STRINGIZE(entity), \
293
                                      BOOST_PP_STRINGIZE(name), \
294
                                      label, \
295
                                      yb::MetricUnit::kMilliseconds, \
296
                                      desc, \
297
                                      level, \
298
                                      ## __VA_ARGS__))
299
300
#define METRIC_DEFINE_lag(entity, name, label, desc, ...) \
301
  METRIC_DEFINE_lag_with_level(entity, name, label, desc, yb::MetricLevel::kInfo, ## __VA_ARGS__)
302
303
#define METRIC_DEFINE_gauge(type, entity, name, label, unit, desc, level, ...) \
304
  ::yb::GaugePrototype<type> BOOST_PP_CAT(METRIC_, name)(         \
305
      ::yb::MetricPrototype::CtorArgs(BOOST_PP_STRINGIZE(entity), \
306
                                      BOOST_PP_STRINGIZE(name), \
307
                                      label, \
308
                                      unit, \
309
                                      desc, \
310
                                      level, \
311
                                      ## __VA_ARGS__))
312
313
#define METRIC_DEFINE_gauge_string(entity, name, label, unit, desc, ...) \
314
    METRIC_DEFINE_gauge(std::string, entity, name, label, unit, desc, \
315
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
316
#define METRIC_DEFINE_gauge_bool(entity, name, label, unit, desc, ...) \
317
    METRIC_DEFINE_gauge(bool, entity, name, label, unit, desc, \
318
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
319
#define METRIC_DEFINE_gauge_int32(entity, name, label, unit, desc, ...) \
320
    METRIC_DEFINE_gauge(int32_t, entity, name, label, unit, desc, \
321
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
322
#define METRIC_DEFINE_gauge_uint32(entity, name, label, unit, desc, ...) \
323
    METRIC_DEFINE_gauge(uint32_t, entity, name, label, unit, desc, \
324
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
325
#define METRIC_DEFINE_gauge_int64(entity, name, label, unit, desc, ...) \
326
    METRIC_DEFINE_gauge(int64, entity, name, label, unit, desc, \
327
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
328
#define METRIC_DEFINE_gauge_uint64(entity, name, label, unit, desc, ...) \
329
    METRIC_DEFINE_gauge(uint64_t, entity, name, label, unit, desc, \
330
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
331
#define METRIC_DEFINE_simple_gauge_uint64(entity, name, label, unit, ...) \
332
    METRIC_DEFINE_gauge(uint64_t, entity, name, label, unit, label, \
333
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
334
#define METRIC_DEFINE_gauge_double(entity, name, label, unit, desc, ...) \
335
    METRIC_DEFINE_gauge(double, entity, name, label, unit, desc, \
336
        yb::MetricLevel::kInfo, ## __VA_ARGS__)
337
338
#define METRIC_DEFINE_histogram_with_percentiles(                              \
339
    entity, name, label, unit, desc, max_val, num_sig_digits)                  \
340
  ::yb::HistogramPrototype BOOST_PP_CAT(METRIC_, name)(                        \
341
      ::yb::MetricPrototype::CtorArgs(BOOST_PP_STRINGIZE(entity),              \
342
                                      BOOST_PP_STRINGIZE(name), label, unit,   \
343
                                      desc,                                    \
344
                                      yb::MetricLevel::kInfo),                 \
345
      max_val, num_sig_digits, yb::ExportPercentiles::kTrue)
346
347
#define METRIC_DEFINE_coarse_histogram(entity, name, label, unit, desc)        \
348
  ::yb::HistogramPrototype BOOST_PP_CAT(METRIC_, name)(                        \
349
      ::yb::MetricPrototype::CtorArgs(BOOST_PP_STRINGIZE(entity),              \
350
                                      BOOST_PP_STRINGIZE(name), label, unit,   \
351
                                      desc,                                    \
352
                                      yb::MetricLevel::kInfo),                 \
353
      2, 1, yb::ExportPercentiles::kFalse)
354
355
// The following macros act as forward declarations for entity types and metric prototypes.
356
#define METRIC_DECLARE_entity(name) \
357
  extern ::yb::MetricEntityPrototype METRIC_ENTITY_##name
358
#define METRIC_DECLARE_counter(name)                             \
359
  extern ::yb::CounterPrototype METRIC_##name
360
#define METRIC_DECLARE_lag(name) \
361
  extern ::yb::LagPrototype METRIC_##name
362
#define METRIC_DECLARE_gauge_string(name) \
363
  extern ::yb::GaugePrototype<std::string> METRIC_##name
364
#define METRIC_DECLARE_gauge_bool(name) \
365
  extern ::yb::GaugePrototype<bool> METRIC_##name
366
#define METRIC_DECLARE_gauge_int32(name) \
367
  extern ::yb::GaugePrototype<int32_t> METRIC_##name
368
#define METRIC_DECLARE_gauge_uint32(name) \
369
  extern ::yb::GaugePrototype<uint32_t> METRIC_##name
370
#define METRIC_DECLARE_gauge_int64(name) \
371
  extern ::yb::GaugePrototype<int64_t> METRIC_##name
372
#define METRIC_DECLARE_gauge_uint64(name) \
373
  extern ::yb::GaugePrototype<uint64_t> METRIC_##name
374
#define METRIC_DECLARE_gauge_double(name) \
375
  extern ::yb::GaugePrototype<double> METRIC_##name
376
#define METRIC_DECLARE_histogram(name) \
377
  extern ::yb::HistogramPrototype METRIC_##name
378
379
#if defined(__APPLE__)
380
#define METRIC_DEFINE_gauge_size(entity, name, label, unit, desc, ...) \
381
  ::yb::GaugePrototype<size_t> METRIC_##name(                    \
382
      ::yb::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
383
#define METRIC_DECLARE_gauge_size(name) \
384
  extern ::yb::GaugePrototype<size_t> METRIC_##name
385
#else
386
#define METRIC_DEFINE_gauge_size METRIC_DEFINE_gauge_uint64
387
#define METRIC_DECLARE_gauge_size METRIC_DECLARE_gauge_uint64
388
#endif
389
390
// Forward-declare the generic 'server' entity type.
391
// We have to do this here below the forward declarations, but not
392
// in the yb namespace.
393
METRIC_DECLARE_entity(server);
394
395
namespace yb {
396
397
class JsonWriter;
398
399
// Unit types to be used with metrics.
400
// As additional units are required, add them to this enum and also to Name().
401
struct MetricUnit {
402
  enum Type {
403
    kCacheHits,
404
    kCacheQueries,
405
    kBytes,
406
    kRequests,
407
    kEntries,
408
    kRows,
409
    kCells,
410
    kConnections,
411
    kOperations,
412
    kProbes,
413
    kNanoseconds,
414
    kMicroseconds,
415
    kMilliseconds,
416
    kSeconds,
417
    kThreads,
418
    kTransactions,
419
    kUnits,
420
    kMaintenanceOperations,
421
    kBlocks,
422
    kLogBlockContainers,
423
    kTasks,
424
    kMessages,
425
    kContextSwitches,
426
    kFiles,
427
  };
428
  static const char* Name(Type unit);
429
};
430
431
class MetricType {
432
 public:
433
  enum Type { kGauge, kCounter, kHistogram, kLag };
434
  static const char* Name(Type t);
435
 private:
436
  static const char* const kGaugeType;
437
  static const char* const kCounterType;
438
  static const char* const kHistogramType;
439
};
440
441
// Base class to allow for putting all metrics into a single container.
442
// See documentation at the top of this file for information on metrics ownership.
443
class Metric : public RefCountedThreadSafe<Metric> {
444
 public:
445
  // All metrics must be able to render themselves as JSON.
446
  virtual CHECKED_STATUS WriteAsJson(JsonWriter* writer,
447
                                     const MetricJsonOptions& opts) const = 0;
448
449
  virtual CHECKED_STATUS WriteForPrometheus(
450
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
451
      const MetricPrometheusOptions& opts) const = 0;
452
453
4.91M
  const MetricPrototype* prototype() const { return prototype_; }
454
455
 protected:
456
  explicit Metric(const MetricPrototype* prototype);
457
  explicit Metric(std::unique_ptr<MetricPrototype> prototype);
458
  virtual ~Metric();
459
460
  std::unique_ptr<MetricPrototype> prototype_holder_;
461
  const MetricPrototype* const prototype_;
462
463
 private:
464
  friend class MetricEntity;
465
  friend class RefCountedThreadSafe<Metric>;
466
467
  // The time at which we should retire this metric if it is still un-referenced outside
468
  // of the metrics subsystem. If this metric is not due for retirement, this member is
469
  // uninitialized.
470
  MonoTime retire_time_;
471
472
  DISALLOW_COPY_AND_ASSIGN(Metric);
473
};
474
475
using MetricPtr = scoped_refptr<Metric>;
476
477
// Registry of all the metrics for a server.
478
//
479
// This aggregates the MetricEntity objects associated with the server.
480
class MetricRegistry {
481
 public:
482
  MetricRegistry();
483
  ~MetricRegistry();
484
485
  scoped_refptr<MetricEntity> FindOrCreateEntity(const MetricEntityPrototype* prototype,
486
                                                 const std::string& id,
487
                                                 const MetricEntity::AttributeMap& initial_attrs);
488
489
  // Writes metrics in this registry to 'writer'.
490
  //
491
  // 'requested_metrics' is a set of substrings to match metric names against,
492
  // where '*' matches all metrics.
493
  //
494
  // The string matching can either match an entity ID or a metric name.
495
  // If it matches an entity ID, then all metrics for that entity will be printed.
496
  //
497
  // See the MetricJsonOptions struct definition above for options changing the
498
  // output of this function.
499
  CHECKED_STATUS WriteAsJson(JsonWriter* writer,
500
                     const std::vector<std::string>& requested_metrics,
501
                     const MetricJsonOptions& opts) const;
502
503
  // Writes metrics in this registry to 'writer'.
504
  //
505
  // See the MetricPrometheusOptions struct definition above for options changing the
506
  // output of this function.
507
  CHECKED_STATUS WriteForPrometheus(PrometheusWriter* writer,
508
                     const MetricPrometheusOptions& opts) const;
509
  // Writes metrics in this registry to 'writer'.
510
  //
511
  // 'requested_metrics' is a set of substrings to match metric names against,
512
  // where '*' matches all metrics.
513
  //
514
  // The string matching can either match an entity ID or a metric name.
515
  // If it matches an entity ID, then all metrics for that entity will be printed.
516
  //
517
  // See the MetricPrometheusOptions struct definition above for options changing the
518
  // output of this function.
519
  CHECKED_STATUS WriteForPrometheus(PrometheusWriter* writer,
520
                     const std::vector<std::string>& requested_metrics,
521
                     const MetricPrometheusOptions& opts) const;
522
523
  // For each registered entity, retires orphaned metrics. If an entity has no more
524
  // metrics and there are no external references, entities are removed as well.
525
  //
526
  // See MetricEntity::RetireOldMetrics().
527
  void RetireOldMetrics();
528
529
  // Return the number of entities in this registry.
530
  size_t num_entities() const {
531
    std::lock_guard<simple_spinlock> l(lock_);
532
    return entities_.size();
533
  }
534
535
75.4k
  void tablets_shutdown_insert(std::string id) {
536
75.4k
    std::lock_guard<std::shared_timed_mutex> l(tablets_shutdown_lock_);
537
75.4k
    tablets_shutdown_.insert(id);
538
75.4k
  }
539
540
155k
  void tablets_shutdown_erase(std::string id) {
541
155k
    std::lock_guard<std::shared_timed_mutex> l(tablets_shutdown_lock_);
542
155k
    (void)tablets_shutdown_.erase(id);
543
155k
  }
544
545
543k
  bool tablets_shutdown_find(std::string id) const {
546
543k
    SharedLock<std::shared_timed_mutex> l(tablets_shutdown_lock_);
547
543k
    return tablets_shutdown_.find(id) != tablets_shutdown_.end();
548
543k
  }
549
550
 private:
551
  typedef std::unordered_map<std::string, scoped_refptr<MetricEntity> > EntityMap;
552
  EntityMap entities_;
553
554
  mutable std::shared_timed_mutex tablets_shutdown_lock_;
555
556
  // Set of tablets that have been shutdown. Protected by tablets_shutdown_lock_.
557
  std::set<std::string> tablets_shutdown_;
558
559
  // Returns whether a tablet has been shutdown.
560
  bool TabletHasBeenShutdown(const scoped_refptr<MetricEntity> entity) const;
561
562
  mutable simple_spinlock lock_;
563
  DISALLOW_COPY_AND_ASSIGN(MetricRegistry);
564
};
565
566
enum PrototypeFlags {
567
  // Flag which causes a Gauge prototype to expose itself as if it
568
  // were a counter.
569
  EXPOSE_AS_COUNTER = 1 << 0
570
};
571
572
class MetricPrototype {
573
 public:
574
  struct OptionalArgs {
575
    OptionalArgs(uint32_t flags = 0,
576
                 AggregationFunction aggregation_function = AggregationFunction::kSum)
577
      : flags_(flags),
578
36.9M
        aggregation_function_(aggregation_function) {
579
36.9M
    }
580
581
    const uint32_t flags_;
582
    const AggregationFunction aggregation_function_;
583
  };
584
585
  // Simple struct to aggregate the arguments common to all prototypes.
586
  // This makes constructor chaining a little less tedious.
587
  struct CtorArgs {
588
    CtorArgs(const char* entity_type,
589
             const char* name,
590
             const char* label,
591
             MetricUnit::Type unit,
592
             const char* description,
593
             MetricLevel level,
594
             OptionalArgs optional_args = OptionalArgs())
595
      : entity_type_(entity_type),
596
        name_(name),
597
        label_(label),
598
        unit_(unit),
599
        description_(description),
600
        level_(level),
601
        flags_(optional_args.flags_),
602
36.9M
        aggregation_function_(optional_args.aggregation_function_) {
603
36.9M
    }
604
605
    const char* const entity_type_;
606
    const char* const name_;
607
    const char* const label_;
608
    const MetricUnit::Type unit_;
609
    const char* const description_;
610
    const MetricLevel level_;
611
    const uint32_t flags_;
612
    const AggregationFunction aggregation_function_;
613
  };
614
615
58.1M
  const char* entity_type() const { return args_.entity_type_; }
616
223M
  const char* name() const { return args_.name_; }
617
35
  const char* label() const { return args_.label_; }
618
35
  MetricUnit::Type unit() const { return args_.unit_; }
619
42
  const char* description() const { return args_.description_; }
620
80.8M
  MetricLevel level() const { return args_.level_; }
621
84.0k
  AggregationFunction aggregation_function() const { return args_.aggregation_function_; }
622
  virtual MetricType::Type type() const = 0;
623
624
  // Writes the fields of this prototype to the given JSON writer.
625
  void WriteFields(JsonWriter* writer,
626
                   const MetricJsonOptions& opts) const;
627
628
27.5M
  virtual ~MetricPrototype() {}
629
630
 protected:
631
  explicit MetricPrototype(CtorArgs args);
632
633
  const CtorArgs args_;
634
635
 private:
636
  DISALLOW_COPY_AND_ASSIGN(MetricPrototype);
637
};
638
639
// A description of a Gauge.
640
template<typename T>
641
class GaugePrototype : public MetricPrototype {
642
 public:
643
  explicit GaugePrototype(const MetricPrototype::CtorArgs& args)
644
7.39M
    : MetricPrototype(args) {
645
7.39M
  }
yb::GaugePrototype<unsigned long long>::GaugePrototype(yb::MetricPrototype::CtorArgs const&)
Line
Count
Source
644
4.26M
    : MetricPrototype(args) {
645
4.26M
  }
yb::GaugePrototype<long long>::GaugePrototype(yb::MetricPrototype::CtorArgs const&)
Line
Count
Source
644
2.97M
    : MetricPrototype(args) {
645
2.97M
  }
yb::GaugePrototype<unsigned int>::GaugePrototype(yb::MetricPrototype::CtorArgs const&)
Line
Count
Source
644
152k
    : MetricPrototype(args) {
645
152k
  }
646
647
  // Instantiate a "manual" gauge.
648
  scoped_refptr<AtomicGauge<T> > Instantiate(
649
      const scoped_refptr<MetricEntity>& entity,
650
16.1M
      const T& initial_value) const {
651
16.1M
    return entity->FindOrCreateGauge(this, initial_value);
652
16.1M
  }
yb::GaugePrototype<unsigned long long>::Instantiate(scoped_refptr<yb::MetricEntity> const&, unsigned long long const&) const
Line
Count
Source
650
15.0M
      const T& initial_value) const {
651
15.0M
    return entity->FindOrCreateGauge(this, initial_value);
652
15.0M
  }
yb::GaugePrototype<unsigned int>::Instantiate(scoped_refptr<yb::MetricEntity> const&, unsigned int const&) const
Line
Count
Source
650
170k
      const T& initial_value) const {
651
170k
    return entity->FindOrCreateGauge(this, initial_value);
652
170k
  }
yb::GaugePrototype<long long>::Instantiate(scoped_refptr<yb::MetricEntity> const&, long long const&) const
Line
Count
Source
650
998k
      const T& initial_value) const {
651
998k
    return entity->FindOrCreateGauge(this, initial_value);
652
998k
  }
653
654
  // Instantiate a gauge that is backed by the given callback.
655
  scoped_refptr<FunctionGauge<T> > InstantiateFunctionGauge(
656
      const scoped_refptr<MetricEntity>& entity,
657
420k
      const Callback<T()>& function) const {
658
420k
    return entity->FindOrCreateFunctionGauge(this, function);
659
420k
  }
yb::GaugePrototype<unsigned long long>::InstantiateFunctionGauge(scoped_refptr<yb::MetricEntity> const&, yb::Callback<unsigned long long ()> const&) const
Line
Count
Source
657
394k
      const Callback<T()>& function) const {
658
394k
    return entity->FindOrCreateFunctionGauge(this, function);
659
394k
  }
yb::GaugePrototype<long long>::InstantiateFunctionGauge(scoped_refptr<yb::MetricEntity> const&, yb::Callback<long long ()> const&) const
Line
Count
Source
657
25.7k
      const Callback<T()>& function) const {
658
25.7k
    return entity->FindOrCreateFunctionGauge(this, function);
659
25.7k
  }
660
661
23
  virtual MetricType::Type type() const override {
662
23
    if (args_.flags_ & EXPOSE_AS_COUNTER) {
663
8
      return MetricType::kCounter;
664
15
    } else {
665
15
      return MetricType::kGauge;
666
15
    }
667
23
  }
yb::GaugePrototype<unsigned long long>::type() const
Line
Count
Source
661
22
  virtual MetricType::Type type() const override {
662
22
    if (args_.flags_ & EXPOSE_AS_COUNTER) {
663
8
      return MetricType::kCounter;
664
14
    } else {
665
14
      return MetricType::kGauge;
666
14
    }
667
22
  }
yb::GaugePrototype<long long>::type() const
Line
Count
Source
661
1
  virtual MetricType::Type type() const override {
662
1
    if (args_.flags_ & EXPOSE_AS_COUNTER) {
663
0
      return MetricType::kCounter;
664
1
    } else {
665
1
      return MetricType::kGauge;
666
1
    }
667
1
  }
Unexecuted instantiation: yb::GaugePrototype<unsigned int>::type() const
668
669
 private:
670
  DISALLOW_COPY_AND_ASSIGN(GaugePrototype);
671
};
672
673
// Abstract base class to provide point-in-time metric values.
674
class Gauge : public Metric {
675
 public:
676
  explicit Gauge(const MetricPrototype* prototype)
677
16.8M
      : Metric(prototype) {
678
16.8M
  }
679
680
  explicit Gauge(std::unique_ptr<MetricPrototype> prototype)
681
3.15M
      : Metric(std::move(prototype)) {
682
3.15M
  }
683
684
2.24M
  virtual ~Gauge() {}
685
  virtual CHECKED_STATUS WriteAsJson(JsonWriter* w,
686
                             const MetricJsonOptions& opts) const override;
687
 protected:
688
  virtual void WriteValue(JsonWriter* writer) const = 0;
689
 private:
690
  DISALLOW_COPY_AND_ASSIGN(Gauge);
691
};
692
693
// Gauge implementation for string that uses locks to ensure thread safety.
694
class StringGauge : public Gauge {
695
 public:
696
  StringGauge(const GaugePrototype<std::string>* proto,
697
              std::string initial_value);
698
  std::string value() const;
699
  void set_value(const std::string& value);
700
701
  CHECKED_STATUS WriteForPrometheus(
702
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
703
      const MetricPrometheusOptions& opts) const override;
704
 protected:
705
  virtual void WriteValue(JsonWriter* writer) const override;
706
 private:
707
  std::string value_;
708
  mutable simple_spinlock lock_;  // Guards value_
709
  DISALLOW_COPY_AND_ASSIGN(StringGauge);
710
};
711
712
// Lock-free implementation for types that are convertible to/from int64_t.
713
template <typename T>
714
class AtomicGauge : public Gauge {
715
 public:
716
  AtomicGauge(const GaugePrototype<T>* proto, T initial_value)
717
16.4M
      : Gauge(proto), value_(initial_value) {
718
16.4M
  }
yb::AtomicGauge<unsigned long long>::AtomicGauge(yb::GaugePrototype<unsigned long long> const*, unsigned long long)
Line
Count
Source
717
15.0M
      : Gauge(proto), value_(initial_value) {
718
15.0M
  }
yb::AtomicGauge<unsigned int>::AtomicGauge(yb::GaugePrototype<unsigned int> const*, unsigned int)
Line
Count
Source
717
49.5k
      : Gauge(proto), value_(initial_value) {
718
49.5k
  }
yb::AtomicGauge<long long>::AtomicGauge(yb::GaugePrototype<long long> const*, long long)
Line
Count
Source
717
1.29M
      : Gauge(proto), value_(initial_value) {
718
1.29M
  }
719
720
  AtomicGauge(std::unique_ptr<GaugePrototype<T>> proto, T initial_value)
721
3.15M
      : Gauge(std::move(proto)), value_(initial_value) {}
yb::AtomicGauge<long long>::AtomicGauge(std::__1::unique_ptr<yb::GaugePrototype<long long>, std::__1::default_delete<yb::GaugePrototype<long long> > >, long long)
Line
Count
Source
721
2.61M
      : Gauge(std::move(proto)), value_(initial_value) {}
yb::AtomicGauge<unsigned long long>::AtomicGauge(std::__1::unique_ptr<yb::GaugePrototype<unsigned long long>, std::__1::default_delete<yb::GaugePrototype<unsigned long long> > >, unsigned long long)
Line
Count
Source
721
545k
      : Gauge(std::move(proto)), value_(initial_value) {}
722
723
121M
  T value() const {
724
121M
    return static_cast<T>(value_.Load(kMemOrderRelease));
725
121M
  }
yb::AtomicGauge<unsigned long long>::value() const
Line
Count
Source
723
113M
  T value() const {
724
113M
    return static_cast<T>(value_.Load(kMemOrderRelease));
725
113M
  }
yb::AtomicGauge<unsigned int>::value() const
Line
Count
Source
723
140k
  T value() const {
724
140k
    return static_cast<T>(value_.Load(kMemOrderRelease));
725
140k
  }
yb::AtomicGauge<long long>::value() const
Line
Count
Source
723
8.09M
  T value() const {
724
8.09M
    return static_cast<T>(value_.Load(kMemOrderRelease));
725
8.09M
  }
726
145M
  virtual void set_value(const T& value) {
727
145M
    value_.Store(static_cast<int64_t>(value), kMemOrderNoBarrier);
728
145M
  }
yb::AtomicGauge<unsigned long long>::set_value(unsigned long long const&)
Line
Count
Source
726
13.7M
  virtual void set_value(const T& value) {
727
13.7M
    value_.Store(static_cast<int64_t>(value), kMemOrderNoBarrier);
728
13.7M
  }
yb::AtomicGauge<unsigned int>::set_value(unsigned int const&)
Line
Count
Source
726
5.12M
  virtual void set_value(const T& value) {
727
5.12M
    value_.Store(static_cast<int64_t>(value), kMemOrderNoBarrier);
728
5.12M
  }
yb::AtomicGauge<long long>::set_value(long long const&)
Line
Count
Source
726
126M
  virtual void set_value(const T& value) {
727
126M
    value_.Store(static_cast<int64_t>(value), kMemOrderNoBarrier);
728
126M
  }
729
349M
  void Increment() {
730
349M
    value_.IncrementBy(1, kMemOrderNoBarrier);
731
349M
  }
yb::AtomicGauge<unsigned long long>::Increment()
Line
Count
Source
729
66.5M
  void Increment() {
730
66.5M
    value_.IncrementBy(1, kMemOrderNoBarrier);
731
66.5M
  }
yb::AtomicGauge<unsigned int>::Increment()
Line
Count
Source
729
810k
  void Increment() {
730
810k
    value_.IncrementBy(1, kMemOrderNoBarrier);
731
810k
  }
yb::AtomicGauge<long long>::Increment()
Line
Count
Source
729
282M
  void Increment() {
730
282M
    value_.IncrementBy(1, kMemOrderNoBarrier);
731
282M
  }
732
6.08G
  virtual void IncrementBy(int64_t amount) {
733
6.08G
    value_.IncrementBy(amount, kMemOrderNoBarrier);
734
6.08G
  }
yb::AtomicGauge<unsigned long long>::IncrementBy(long long)
Line
Count
Source
732
3.04G
  virtual void IncrementBy(int64_t amount) {
733
3.04G
    value_.IncrementBy(amount, kMemOrderNoBarrier);
734
3.04G
  }
yb::AtomicGauge<unsigned int>::IncrementBy(long long)
Line
Count
Source
732
806k
  virtual void IncrementBy(int64_t amount) {
733
806k
    value_.IncrementBy(amount, kMemOrderNoBarrier);
734
806k
  }
yb::AtomicGauge<long long>::IncrementBy(long long)
Line
Count
Source
732
3.03G
  virtual void IncrementBy(int64_t amount) {
733
3.03G
    value_.IncrementBy(amount, kMemOrderNoBarrier);
734
3.03G
  }
735
354M
  void Decrement() {
736
354M
    IncrementBy(-1);
737
354M
  }
yb::AtomicGauge<unsigned long long>::Decrement()
Line
Count
Source
735
63.7M
  void Decrement() {
736
63.7M
    IncrementBy(-1);
737
63.7M
  }
yb::AtomicGauge<unsigned int>::Decrement()
Line
Count
Source
735
806k
  void Decrement() {
736
806k
    IncrementBy(-1);
737
806k
  }
yb::AtomicGauge<long long>::Decrement()
Line
Count
Source
735
290M
  void Decrement() {
736
290M
    IncrementBy(-1);
737
290M
  }
738
25.6M
  void DecrementBy(int64_t amount) {
739
25.6M
    IncrementBy(-amount);
740
25.6M
  }
yb::AtomicGauge<unsigned long long>::DecrementBy(long long)
Line
Count
Source
738
357k
  void DecrementBy(int64_t amount) {
739
357k
    IncrementBy(-amount);
740
357k
  }
yb::AtomicGauge<long long>::DecrementBy(long long)
Line
Count
Source
738
25.2M
  void DecrementBy(int64_t amount) {
739
25.2M
    IncrementBy(-amount);
740
25.2M
  }
741
742
  CHECKED_STATUS WriteForPrometheus(
743
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
744
22.8k
      const MetricPrometheusOptions& opts) const override {
745
22.8k
    if (prototype_->level() < opts.level) {
746
0
      return Status::OK();
747
0
    }
748
749
22.8k
    return writer->WriteSingleEntry(attr, prototype_->name(), value(),
750
22.8k
                                    prototype()->aggregation_function());
751
22.8k
  }
yb::AtomicGauge<unsigned long long>::WriteForPrometheus(yb::PrometheusWriter*, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, yb::MetricPrometheusOptions const&) const
Line
Count
Source
744
19.4k
      const MetricPrometheusOptions& opts) const override {
745
19.4k
    if (prototype_->level() < opts.level) {
746
0
      return Status::OK();
747
0
    }
748
749
19.4k
    return writer->WriteSingleEntry(attr, prototype_->name(), value(),
750
19.4k
                                    prototype()->aggregation_function());
751
19.4k
  }
yb::AtomicGauge<unsigned int>::WriteForPrometheus(yb::PrometheusWriter*, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, yb::MetricPrometheusOptions const&) const
Line
Count
Source
744
91
      const MetricPrometheusOptions& opts) const override {
745
91
    if (prototype_->level() < opts.level) {
746
0
      return Status::OK();
747
0
    }
748
749
91
    return writer->WriteSingleEntry(attr, prototype_->name(), value(),
750
91
                                    prototype()->aggregation_function());
751
91
  }
yb::AtomicGauge<long long>::WriteForPrometheus(yb::PrometheusWriter*, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, yb::MetricPrometheusOptions const&) const
Line
Count
Source
744
3.40k
      const MetricPrometheusOptions& opts) const override {
745
3.40k
    if (prototype_->level() < opts.level) {
746
0
      return Status::OK();
747
0
    }
748
749
3.40k
    return writer->WriteSingleEntry(attr, prototype_->name(), value(),
750
3.40k
                                    prototype()->aggregation_function());
751
3.40k
  }
752
753
 protected:
754
58.6M
  virtual void WriteValue(JsonWriter* writer) const override {
755
58.6M
    writer->Value(value());
756
58.6M
  }
yb::AtomicGauge<unsigned long long>::WriteValue(yb::JsonWriter*) const
Line
Count
Source
754
50.4M
  virtual void WriteValue(JsonWriter* writer) const override {
755
50.4M
    writer->Value(value());
756
50.4M
  }
yb::AtomicGauge<unsigned int>::WriteValue(yb::JsonWriter*) const
Line
Count
Source
754
140k
  virtual void WriteValue(JsonWriter* writer) const override {
755
140k
    writer->Value(value());
756
140k
  }
yb::AtomicGauge<long long>::WriteValue(yb::JsonWriter*) const
Line
Count
Source
754
8.09M
  virtual void WriteValue(JsonWriter* writer) const override {
755
8.09M
    writer->Value(value());
756
8.09M
  }
757
  AtomicInt<int64_t> value_;
758
 private:
759
  DISALLOW_COPY_AND_ASSIGN(AtomicGauge);
760
};
761
762
template <class T>
763
181M
void IncrementGauge(const scoped_refptr<AtomicGauge<T>>& gauge) {
764
181M
  if (gauge) {
765
180M
    gauge->Increment();
766
180M
  }
767
181M
}
void yb::IncrementGauge<long long>(scoped_refptr<yb::AtomicGauge<long long> > const&)
Line
Count
Source
763
180M
void IncrementGauge(const scoped_refptr<AtomicGauge<T>>& gauge) {
764
180M
  if (gauge) {
765
179M
    gauge->Increment();
766
179M
  }
767
180M
}
void yb::IncrementGauge<unsigned int>(scoped_refptr<yb::AtomicGauge<unsigned int> > const&)
Line
Count
Source
763
810k
void IncrementGauge(const scoped_refptr<AtomicGauge<T>>& gauge) {
764
810k
  if (gauge) {
765
810k
    gauge->Increment();
766
810k
  }
767
810k
}
768
769
template <class T>
770
181M
void DecrementGauge(const scoped_refptr<AtomicGauge<T>>& gauge) {
771
181M
  if (gauge) {
772
179M
    gauge->Decrement();
773
179M
  }
774
181M
}
void yb::DecrementGauge<long long>(scoped_refptr<yb::AtomicGauge<long long> > const&)
Line
Count
Source
770
180M
void DecrementGauge(const scoped_refptr<AtomicGauge<T>>& gauge) {
771
180M
  if (gauge) {
772
178M
    gauge->Decrement();
773
178M
  }
774
180M
}
void yb::DecrementGauge<unsigned int>(scoped_refptr<yb::AtomicGauge<unsigned int> > const&)
Line
Count
Source
770
806k
void DecrementGauge(const scoped_refptr<AtomicGauge<T>>& gauge) {
771
806k
  if (
gauge806k
) {
772
806k
    gauge->Decrement();
773
806k
  }
774
806k
}
775
776
// A Gauge that calls back to a function to get its value.
777
//
778
// This metric type should be used in cases where it is difficult to keep a running
779
// measure of a metric, but instead would like to compute the metric value whenever it is
780
// requested by a user.
781
//
782
// The lifecycle should be carefully considered when using a FunctionGauge. In particular,
783
// the bound function needs to always be safe to run -- so if it references a particular
784
// non-singleton class instance, the instance must out-live the function. Typically,
785
// the easiest way to ensure this is to use a FunctionGaugeDetacher (see above).
786
template <typename T>
787
class FunctionGauge : public Gauge {
788
 public:
789
245k
  T value() const {
790
245k
    std::lock_guard<simple_spinlock> l(lock_);
791
245k
    return function_.Run();
792
245k
  }
yb::FunctionGauge<unsigned long long>::value() const
Line
Count
Source
789
230k
  T value() const {
790
230k
    std::lock_guard<simple_spinlock> l(lock_);
791
230k
    return function_.Run();
792
230k
  }
yb::FunctionGauge<long long>::value() const
Line
Count
Source
789
15.5k
  T value() const {
790
15.5k
    std::lock_guard<simple_spinlock> l(lock_);
791
15.5k
    return function_.Run();
792
15.5k
  }
793
794
244k
  virtual void WriteValue(JsonWriter* writer) const override {
795
244k
    writer->Value(value());
796
244k
  }
yb::FunctionGauge<unsigned long long>::WriteValue(yb::JsonWriter*) const
Line
Count
Source
794
229k
  virtual void WriteValue(JsonWriter* writer) const override {
795
229k
    writer->Value(value());
796
229k
  }
yb::FunctionGauge<long long>::WriteValue(yb::JsonWriter*) const
Line
Count
Source
794
15.3k
  virtual void WriteValue(JsonWriter* writer) const override {
795
15.3k
    writer->Value(value());
796
15.3k
  }
797
798
  // Reset this FunctionGauge to return a specific value.
799
  // This should be used during destruction. If you want a settable
800
  // Gauge, use a normal Gauge instead of a FunctionGauge.
801
495
  void DetachToConstant(T v) {
802
495
    std::lock_guard<simple_spinlock> l(lock_);
803
495
    function_ = Bind(&FunctionGauge::Return, v);
804
495
  }
yb::FunctionGauge<unsigned long long>::DetachToConstant(unsigned long long)
Line
Count
Source
801
331
  void DetachToConstant(T v) {
802
331
    std::lock_guard<simple_spinlock> l(lock_);
803
331
    function_ = Bind(&FunctionGauge::Return, v);
804
331
  }
yb::FunctionGauge<long long>::DetachToConstant(long long)
Line
Count
Source
801
164
  void DetachToConstant(T v) {
802
164
    std::lock_guard<simple_spinlock> l(lock_);
803
164
    function_ = Bind(&FunctionGauge::Return, v);
804
164
  }
805
806
  // Get the current value of the gauge, and detach so that it continues to return this
807
  // value in perpetuity.
808
493
  void DetachToCurrentValue() {
809
493
    T last_value = value();
810
493
    DetachToConstant(last_value);
811
493
  }
yb::FunctionGauge<unsigned long long>::DetachToCurrentValue()
Line
Count
Source
808
331
  void DetachToCurrentValue() {
809
331
    T last_value = value();
810
331
    DetachToConstant(last_value);
811
331
  }
yb::FunctionGauge<long long>::DetachToCurrentValue()
Line
Count
Source
808
162
  void DetachToCurrentValue() {
809
162
    T last_value = value();
810
162
    DetachToConstant(last_value);
811
162
  }
812
813
  // Automatically detach this gauge when the given 'detacher' destructs.
814
  // After detaching, the metric will return 'value' in perpetuity.
815
  void AutoDetach(std::shared_ptr<void>* detacher, T value = T()) {
816
    auto old_value = *detacher;
817
    *detacher = std::shared_ptr<void>(nullptr,
818
        [self = make_scoped_refptr(this), value, old_value](auto) {
819
      self->DetachToConstant(value);
820
    });
821
  }
822
823
  // Automatically detach this gauge when the given 'detacher' destructs.
824
  // After detaching, the metric will return whatever its value was at the
825
  // time of detaching.
826
  //
827
  // Note that, when using this method, you should be sure that the FunctionGaugeDetacher
828
  // is destructed before any objects which are required by the gauge implementation.
829
  // In typical usage (see the FunctionGaugeDetacher class documentation) this means you
830
  // should declare the detacher member after all other class members that might be
831
  // accessed by the gauge function implementation.
832
77.3k
  void AutoDetachToLastValue(std::shared_ptr<void>* detacher) {
833
77.3k
    auto old_value = *detacher;
834
77.3k
    *detacher = std::shared_ptr<void>(nullptr, [self = make_scoped_refptr(this), old_value](auto) {
835
492
      self->DetachToCurrentValue();
836
492
    });
auto yb::FunctionGauge<unsigned long long>::AutoDetachToLastValue(std::__1::shared_ptr<void>*)::'lambda'(auto)::operator()<std::nullptr_t>(auto) const
Line
Count
Source
834
331
    *detacher = std::shared_ptr<void>(nullptr, [self = make_scoped_refptr(this), old_value](auto) {
835
331
      self->DetachToCurrentValue();
836
331
    });
auto yb::FunctionGauge<long long>::AutoDetachToLastValue(std::__1::shared_ptr<void>*)::'lambda'(auto)::operator()<std::nullptr_t>(auto) const
Line
Count
Source
834
161
    *detacher = std::shared_ptr<void>(nullptr, [self = make_scoped_refptr(this), old_value](auto) {
835
161
      self->DetachToCurrentValue();
836
161
    });
837
77.3k
  }
yb::FunctionGauge<unsigned long long>::AutoDetachToLastValue(std::__1::shared_ptr<void>*)
Line
Count
Source
832
51.6k
  void AutoDetachToLastValue(std::shared_ptr<void>* detacher) {
833
51.6k
    auto old_value = *detacher;
834
51.6k
    *detacher = std::shared_ptr<void>(nullptr, [self = make_scoped_refptr(this), old_value](auto) {
835
51.6k
      self->DetachToCurrentValue();
836
51.6k
    });
837
51.6k
  }
yb::FunctionGauge<long long>::AutoDetachToLastValue(std::__1::shared_ptr<void>*)
Line
Count
Source
832
25.7k
  void AutoDetachToLastValue(std::shared_ptr<void>* detacher) {
833
25.7k
    auto old_value = *detacher;
834
25.7k
    *detacher = std::shared_ptr<void>(nullptr, [self = make_scoped_refptr(this), old_value](auto) {
835
25.7k
      self->DetachToCurrentValue();
836
25.7k
    });
837
25.7k
  }
838
839
  CHECKED_STATUS WriteForPrometheus(
840
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
841
496
      const MetricPrometheusOptions& opts) const override {
842
496
    if (prototype_->level() < opts.level) {
843
0
      return Status::OK();
844
0
    }
845
846
496
    return writer->WriteSingleEntry(attr, prototype_->name(), value(),
847
496
                                    prototype()->aggregation_function());
848
496
  }
yb::FunctionGauge<unsigned long long>::WriteForPrometheus(yb::PrometheusWriter*, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, yb::MetricPrometheusOptions const&) const
Line
Count
Source
841
465
      const MetricPrometheusOptions& opts) const override {
842
465
    if (prototype_->level() < opts.level) {
843
0
      return Status::OK();
844
0
    }
845
846
465
    return writer->WriteSingleEntry(attr, prototype_->name(), value(),
847
465
                                    prototype()->aggregation_function());
848
465
  }
yb::FunctionGauge<long long>::WriteForPrometheus(yb::PrometheusWriter*, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, yb::MetricPrometheusOptions const&) const
Line
Count
Source
841
31
      const MetricPrometheusOptions& opts) const override {
842
31
    if (prototype_->level() < opts.level) {
843
0
      return Status::OK();
844
0
    }
845
846
31
    return writer->WriteSingleEntry(attr, prototype_->name(), value(),
847
31
                                    prototype()->aggregation_function());
848
31
  }
849
850
 private:
851
  friend class MetricEntity;
852
853
  FunctionGauge(const GaugePrototype<T>* proto, Callback<T()> function)
854
420k
      : Gauge(proto), function_(std::move(function)) {}
yb::FunctionGauge<unsigned long long>::FunctionGauge(yb::GaugePrototype<unsigned long long> const*, yb::Callback<unsigned long long ()>)
Line
Count
Source
854
394k
      : Gauge(proto), function_(std::move(function)) {}
yb::FunctionGauge<long long>::FunctionGauge(yb::GaugePrototype<long long> const*, yb::Callback<long long ()>)
Line
Count
Source
854
25.7k
      : Gauge(proto), function_(std::move(function)) {}
855
856
6
  static T Return(T v) {
857
6
    return v;
858
6
  }
Unexecuted instantiation: yb::FunctionGauge<unsigned long long>::Return(unsigned long long)
yb::FunctionGauge<long long>::Return(long long)
Line
Count
Source
856
6
  static T Return(T v) {
857
6
    return v;
858
6
  }
859
860
  mutable simple_spinlock lock_;
861
  Callback<T()> function_;
862
  DISALLOW_COPY_AND_ASSIGN(FunctionGauge);
863
};
864
865
// Prototype for a counter.
866
class CounterPrototype : public MetricPrototype {
867
 public:
868
  explicit CounterPrototype(const MetricPrototype::CtorArgs& args)
869
22.1M
    : MetricPrototype(args) {
870
22.1M
  }
871
  scoped_refptr<Counter> Instantiate(const scoped_refptr<MetricEntity>& entity) const;
872
873
8
  virtual MetricType::Type type() const override { return MetricType::kCounter; }
874
875
 private:
876
  DISALLOW_COPY_AND_ASSIGN(CounterPrototype);
877
};
878
879
// Simple incrementing 64-bit integer.
880
// Only use Counters in cases that we expect the count to only increase. For example,
881
// a counter is appropriate for "number of transactions processed by the server",
882
// but not for "number of transactions currently in flight". Monitoring software
883
// knows that counters only increase and thus can compute rates over time, rates
884
// across multiple servers, etc, which aren't appropriate in the case of gauges.
885
class Counter : public Metric {
886
 public:
887
  int64_t value() const;
888
  void Increment();
889
  void IncrementBy(int64_t amount);
890
  virtual CHECKED_STATUS WriteAsJson(JsonWriter* w,
891
                             const MetricJsonOptions& opts) const override;
892
893
  CHECKED_STATUS WriteForPrometheus(
894
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
895
      const MetricPrometheusOptions& opts) const override;
896
897
 private:
898
  FRIEND_TEST(MetricsTest, SimpleCounterTest);
899
  FRIEND_TEST(MultiThreadedMetricsTest, CounterIncrementTest);
900
  friend class MetricEntity;
901
902
  explicit Counter(const CounterPrototype* proto);
903
  explicit Counter(std::unique_ptr<CounterPrototype> proto);
904
905
  LongAdder value_;
906
  DISALLOW_COPY_AND_ASSIGN(Counter);
907
};
908
909
using CounterPtr = scoped_refptr<Counter>;
910
911
class MillisLagPrototype : public MetricPrototype {
912
 public:
913
43.4k
  explicit MillisLagPrototype(const MetricPrototype::CtorArgs& args) : MetricPrototype(args) {
914
43.4k
  }
915
  scoped_refptr<MillisLag> Instantiate(const scoped_refptr<MetricEntity>& entity) const;
916
917
2
  virtual MetricType::Type type() const override { return MetricType::kLag; }
918
919
 private:
920
  DISALLOW_COPY_AND_ASSIGN(MillisLagPrototype);
921
};
922
923
// Metric used to calculate the lag of a specific metric.
924
// The metric is in charge of updating the metric timestamp, and this method
925
// will be in charge of calculating the lag by doing now() - metric_timestamp_.
926
class MillisLag : public Metric {
927
 public:
928
3
  virtual int64_t lag_ms() const {
929
3
    return std::max(static_cast<int64_t>(0),
930
3
        static_cast<int64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
931
3
            std::chrono::system_clock::now().time_since_epoch()).count()) - timestamp_ms_);
932
3
  }
933
2
  virtual void UpdateTimestampInMilliseconds(int64_t timestamp) {
934
2
    timestamp_ms_ = timestamp;
935
2
  }
936
  virtual CHECKED_STATUS WriteAsJson(JsonWriter* w,
937
      const MetricJsonOptions& opts) const override;
938
  virtual CHECKED_STATUS WriteForPrometheus(
939
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
940
      const MetricPrometheusOptions& opts) const override;
941
942
 private:
943
  friend class MetricEntity;
944
  friend class AtomicMillisLag;
945
  friend class MetricsTest;
946
947
  explicit MillisLag(const MillisLagPrototype* proto);
948
949
  int64_t timestamp_ms_;
950
};
951
952
class AtomicMillisLag : public MillisLag {
953
 public:
954
  explicit AtomicMillisLag(const MillisLagPrototype* proto);
955
956
517k
  int64_t lag_ms() const override {
957
517k
    return std::max(static_cast<int64_t>(0),
958
517k
        static_cast<int64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
959
517k
            std::chrono::system_clock::now().time_since_epoch()).count()) -
960
517k
                atomic_timestamp_ms_.load(std::memory_order_acquire));
961
517k
  }
962
963
25.6M
  void UpdateTimestampInMilliseconds(int64_t timestamp) override {
964
25.6M
    atomic_timestamp_ms_.store(timestamp, std::memory_order_release);
965
25.6M
  }
966
967
  CHECKED_STATUS WriteAsJson(JsonWriter* w,
968
                             const MetricJsonOptions& opts) const override;
969
970
  CHECKED_STATUS WriteForPrometheus(
971
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
972
212
      const MetricPrometheusOptions& opts) const override {
973
212
    if (prototype_->level() < opts.level) {
974
0
      return Status::OK();
975
0
    }
976
977
212
    return writer->WriteSingleEntry(attr, prototype_->name(), this->lag_ms(),
978
212
                                    prototype()->aggregation_function());
979
212
  }
980
981
 protected:
982
  std::atomic<int64_t> atomic_timestamp_ms_;
983
 private:
984
  DISALLOW_COPY_AND_ASSIGN(AtomicMillisLag);
985
};
986
987
181M
inline void IncrementCounter(const CounterPtr& counter) {
988
181M
  if (counter) {
989
180M
    counter->Increment();
990
180M
  }
991
181M
}
992
993
464M
inline void IncrementCounterBy(const CounterPtr& counter, int64_t amount) {
994
464M
  if (counter) {
995
460M
    counter->IncrementBy(amount);
996
460M
  }
997
464M
}
998
999
YB_STRONGLY_TYPED_BOOL(ExportPercentiles);
1000
1001
class HistogramPrototype : public MetricPrototype {
1002
 public:
1003
  HistogramPrototype(const MetricPrototype::CtorArgs& args,
1004
                     uint64_t max_trackable_value, int num_sig_digits,
1005
                     ExportPercentiles export_percentiles = ExportPercentiles::kFalse);
1006
  scoped_refptr<Histogram> Instantiate(const scoped_refptr<MetricEntity>& entity) const;
1007
1008
3.89M
  uint64_t max_trackable_value() const { return max_trackable_value_; }
1009
3.89M
  int num_sig_digits() const { return num_sig_digits_; }
1010
3.89M
  ExportPercentiles export_percentiles() const { return export_percentiles_; }
1011
1
  virtual MetricType::Type type() const override { return MetricType::kHistogram; }
1012
1013
 private:
1014
  const uint64_t max_trackable_value_;
1015
  const int num_sig_digits_;
1016
  const ExportPercentiles export_percentiles_;
1017
  DISALLOW_COPY_AND_ASSIGN(HistogramPrototype);
1018
};
1019
1020
class Histogram : public Metric {
1021
 public:
1022
  // Increment the histogram for the given value.
1023
  // 'value' must be non-negative.
1024
  void Increment(int64_t value);
1025
1026
  // Increment the histogram for the given value by the given amount.
1027
  // 'value' and 'amount' must be non-negative.
1028
  void IncrementBy(int64_t value, int64_t amount);
1029
1030
  // Return the total number of values added to the histogram (via Increment()
1031
  // or IncrementBy()).
1032
  uint64_t TotalCount() const;
1033
1034
  virtual CHECKED_STATUS WriteAsJson(JsonWriter* w,
1035
                             const MetricJsonOptions& opts) const override;
1036
1037
  CHECKED_STATUS WriteForPrometheus(
1038
      PrometheusWriter* writer, const MetricEntity::AttributeMap& attr,
1039
      const MetricPrometheusOptions& opts) const override;
1040
1041
  // Returns a snapshot of this histogram including the bucketed values and counts.
1042
  // Resets the bucketed counts, but not the total count/sum.
1043
  CHECKED_STATUS GetAndResetHistogramSnapshotPB(HistogramSnapshotPB* snapshot,
1044
                                const MetricJsonOptions& opts) const;
1045
1046
1047
  // Returns a pointer to the underlying histogram. The implementation of HdrHistogram
1048
  //   // is thread safe.
1049
28
  const HdrHistogram* histogram() const { return histogram_.get(); }
1050
1051
  uint64_t CountInBucketForValueForTests(uint64_t value) const;
1052
  uint64_t MinValueForTests() const;
1053
  uint64_t MaxValueForTests() const;
1054
  double MeanValueForTests() const;
1055
1056
 private:
1057
  FRIEND_TEST(MetricsTest, SimpleHistogramTest);
1058
  FRIEND_TEST(MetricsTest, ResetHistogramTest);
1059
  friend class MetricEntity;
1060
  explicit Histogram(const HistogramPrototype* proto);
1061
  explicit Histogram(std::unique_ptr<HistogramPrototype> proto, uint64_t highest_trackable_value,
1062
      int num_significant_digits, ExportPercentiles export_percentiles);
1063
1064
  const std::unique_ptr<HdrHistogram> histogram_;
1065
  const ExportPercentiles export_percentiles_;
1066
  DISALLOW_COPY_AND_ASSIGN(Histogram);
1067
};
1068
1069
using HistogramPtr = scoped_refptr<Histogram>;
1070
1071
406k
inline void IncrementHistogram(const scoped_refptr<Histogram>& histogram, int64_t value) {
1072
406k
  if (histogram) {
1073
406k
    histogram->Increment(value);
1074
406k
  }
1075
406k
}
1076
1077
YB_STRONGLY_TYPED_BOOL(Auto);
1078
1079
// Measures a duration while in scope. Adds this duration to specified histogram on destruction.
1080
class ScopedLatencyMetric {
1081
 public:
1082
  // If 'latency_hist' is NULL, this turns into a no-op.
1083
  // automatic - automatically update histogram when object is destroyed.
1084
  explicit ScopedLatencyMetric(const scoped_refptr<Histogram>& latency_hist,
1085
                               Auto automatic = Auto::kTrue);
1086
1087
  ScopedLatencyMetric(ScopedLatencyMetric&& rhs);
1088
  void operator=(ScopedLatencyMetric&& rhs);
1089
1090
  ScopedLatencyMetric(const ScopedLatencyMetric&) = delete;
1091
  void operator=(const ScopedLatencyMetric&) = delete;
1092
1093
  ~ScopedLatencyMetric();
1094
1095
  void Restart();
1096
  void Finish();
1097
1098
 private:
1099
  scoped_refptr<Histogram> latency_hist_;
1100
  MonoTime time_started_;
1101
  Auto auto_;
1102
};
1103
1104
////////////////////////////////////////////////////////////
1105
// Inline implementations of template methods
1106
////////////////////////////////////////////////////////////
1107
1108
template<typename T>
1109
inline scoped_refptr<AtomicGauge<T>> MetricEntity::FindOrCreateGauge(
1110
    const GaugePrototype<T>* proto,
1111
16.5M
    const T& initial_value) {
1112
16.5M
  CheckInstantiation(proto);
1113
16.5M
  std::lock_guard<simple_spinlock> l(lock_);
1114
16.5M
  auto it = metric_map_.find(proto);
1115
16.5M
  if (it == metric_map_.end()) {
1116
16.4M
    auto result = new AtomicGauge<T>(proto, initial_value);
1117
16.4M
    metric_map_.emplace(proto, result);
1118
16.4M
    return result;
1119
16.4M
  }
1120
127k
  return down_cast<AtomicGauge<T>*>(it->second.get());
1121
16.5M
}
scoped_refptr<yb::AtomicGauge<unsigned long long> > yb::MetricEntity::FindOrCreateGauge<unsigned long long>(yb::GaugePrototype<unsigned long long> const*, unsigned long long const&)
Line
Count
Source
1111
15.0M
    const T& initial_value) {
1112
15.0M
  CheckInstantiation(proto);
1113
15.0M
  std::lock_guard<simple_spinlock> l(lock_);
1114
15.0M
  auto it = metric_map_.find(proto);
1115
15.0M
  if (it == metric_map_.end()) {
1116
15.0M
    auto result = new AtomicGauge<T>(proto, initial_value);
1117
15.0M
    metric_map_.emplace(proto, result);
1118
15.0M
    return result;
1119
15.0M
  }
1120
5.40k
  return down_cast<AtomicGauge<T>*>(it->second.get());
1121
15.0M
}
scoped_refptr<yb::AtomicGauge<unsigned int> > yb::MetricEntity::FindOrCreateGauge<unsigned int>(yb::GaugePrototype<unsigned int> const*, unsigned int const&)
Line
Count
Source
1111
170k
    const T& initial_value) {
1112
170k
  CheckInstantiation(proto);
1113
170k
  std::lock_guard<simple_spinlock> l(lock_);
1114
170k
  auto it = metric_map_.find(proto);
1115
170k
  if (it == metric_map_.end()) {
1116
49.5k
    auto result = new AtomicGauge<T>(proto, initial_value);
1117
49.5k
    metric_map_.emplace(proto, result);
1118
49.5k
    return result;
1119
49.5k
  }
1120
120k
  return down_cast<AtomicGauge<T>*>(it->second.get());
1121
170k
}
scoped_refptr<yb::AtomicGauge<long long> > yb::MetricEntity::FindOrCreateGauge<long long>(yb::GaugePrototype<long long> const*, long long const&)
Line
Count
Source
1111
1.29M
    const T& initial_value) {
1112
1.29M
  CheckInstantiation(proto);
1113
1.29M
  std::lock_guard<simple_spinlock> l(lock_);
1114
1.29M
  auto it = metric_map_.find(proto);
1115
1.29M
  if (it == metric_map_.end()) {
1116
1.29M
    auto result = new AtomicGauge<T>(proto, initial_value);
1117
1.29M
    metric_map_.emplace(proto, result);
1118
1.29M
    return result;
1119
1.29M
  }
1120
1.37k
  return down_cast<AtomicGauge<T>*>(it->second.get());
1121
1.29M
}
1122
1123
template<typename T>
1124
inline scoped_refptr<AtomicGauge<T> > MetricEntity::FindOrCreateGauge(
1125
    std::unique_ptr<GaugePrototype<T>> proto,
1126
3.15M
    const T& initial_value) {
1127
3.15M
  CheckInstantiation(proto.get());
1128
3.15M
  std::lock_guard<simple_spinlock> l(lock_);
1129
3.15M
  auto it = metric_map_.find(proto.get());
1130
3.15M
  if (it != metric_map_.end()) {
1131
0
    return down_cast<AtomicGauge<T>*>(it->second.get());
1132
0
  }
1133
3.15M
  auto result = new AtomicGauge<T>(std::move(proto), initial_value);
1134
3.15M
  metric_map_.emplace(result->prototype(), result);
1135
3.15M
  return result;
1136
3.15M
}
scoped_refptr<yb::AtomicGauge<long long> > yb::MetricEntity::FindOrCreateGauge<long long>(std::__1::unique_ptr<yb::GaugePrototype<long long>, std::__1::default_delete<yb::GaugePrototype<long long> > >, long long const&)
Line
Count
Source
1126
2.61M
    const T& initial_value) {
1127
2.61M
  CheckInstantiation(proto.get());
1128
2.61M
  std::lock_guard<simple_spinlock> l(lock_);
1129
2.61M
  auto it = metric_map_.find(proto.get());
1130
2.61M
  if (it != metric_map_.end()) {
1131
0
    return down_cast<AtomicGauge<T>*>(it->second.get());
1132
0
  }
1133
2.61M
  auto result = new AtomicGauge<T>(std::move(proto), initial_value);
1134
2.61M
  metric_map_.emplace(result->prototype(), result);
1135
2.61M
  return result;
1136
2.61M
}
scoped_refptr<yb::AtomicGauge<unsigned long long> > yb::MetricEntity::FindOrCreateGauge<unsigned long long>(std::__1::unique_ptr<yb::GaugePrototype<unsigned long long>, std::__1::default_delete<yb::GaugePrototype<unsigned long long> > >, unsigned long long const&)
Line
Count
Source
1126
545k
    const T& initial_value) {
1127
545k
  CheckInstantiation(proto.get());
1128
545k
  std::lock_guard<simple_spinlock> l(lock_);
1129
545k
  auto it = metric_map_.find(proto.get());
1130
545k
  if (it != metric_map_.end()) {
1131
0
    return down_cast<AtomicGauge<T>*>(it->second.get());
1132
0
  }
1133
545k
  auto result = new AtomicGauge<T>(std::move(proto), initial_value);
1134
545k
  metric_map_.emplace(result->prototype(), result);
1135
545k
  return result;
1136
545k
}
1137
1138
template<typename T>
1139
inline scoped_refptr<FunctionGauge<T> > MetricEntity::FindOrCreateFunctionGauge(
1140
    const GaugePrototype<T>* proto,
1141
420k
    const Callback<T()>& function) {
1142
420k
  CheckInstantiation(proto);
1143
420k
  std::lock_guard<simple_spinlock> l(lock_);
1144
420k
  auto it = metric_map_.find(proto);
1145
420k
  if (it != metric_map_.end()) {
1146
0
    return down_cast<FunctionGauge<T>*>(it->second.get());
1147
0
  }
1148
420k
  auto result = new FunctionGauge<T>(proto, function);
1149
420k
  metric_map_.emplace(proto, result);
1150
420k
  return result;
1151
420k
}
scoped_refptr<yb::FunctionGauge<unsigned long long> > yb::MetricEntity::FindOrCreateFunctionGauge<unsigned long long>(yb::GaugePrototype<unsigned long long> const*, yb::Callback<unsigned long long ()> const&)
Line
Count
Source
1141
394k
    const Callback<T()>& function) {
1142
394k
  CheckInstantiation(proto);
1143
394k
  std::lock_guard<simple_spinlock> l(lock_);
1144
394k
  auto it = metric_map_.find(proto);
1145
394k
  if (it != metric_map_.end()) {
1146
0
    return down_cast<FunctionGauge<T>*>(it->second.get());
1147
0
  }
1148
394k
  auto result = new FunctionGauge<T>(proto, function);
1149
394k
  metric_map_.emplace(proto, result);
1150
394k
  return result;
1151
394k
}
scoped_refptr<yb::FunctionGauge<long long> > yb::MetricEntity::FindOrCreateFunctionGauge<long long>(yb::GaugePrototype<long long> const*, yb::Callback<long long ()> const&)
Line
Count
Source
1141
25.7k
    const Callback<T()>& function) {
1142
25.7k
  CheckInstantiation(proto);
1143
25.7k
  std::lock_guard<simple_spinlock> l(lock_);
1144
25.7k
  auto it = metric_map_.find(proto);
1145
25.7k
  if (it != metric_map_.end()) {
1146
0
    return down_cast<FunctionGauge<T>*>(it->second.get());
1147
0
  }
1148
25.7k
  auto result = new FunctionGauge<T>(proto, function);
1149
25.7k
  metric_map_.emplace(proto, result);
1150
25.7k
  return result;
1151
25.7k
}
1152
1153
class OwningMetricCtorArgs {
1154
 public:
1155
  OwningMetricCtorArgs(
1156
      std::string entity_type,
1157
      std::string name,
1158
      std::string label,
1159
      MetricUnit::Type unit,
1160
      std::string description,
1161
      MetricLevel level,
1162
      uint32_t flags = 0)
1163
    : entity_type_(std::move(entity_type)), name_(std::move(name)), label_(std::move(label)),
1164
3.22M
      unit_(unit), description_(std::move(description)), level_(std::move(level)), flags_(flags) {}
1165
 protected:
1166
  std::string entity_type_;
1167
  std::string name_;
1168
  std::string label_;
1169
  MetricUnit::Type unit_;
1170
  std::string description_;
1171
  MetricLevel level_;
1172
  uint32_t flags_;
1173
};
1174
1175
class OwningCounterPrototype : public OwningMetricCtorArgs, public CounterPrototype {
1176
 public:
1177
  template <class... Args>
1178
  explicit OwningCounterPrototype(Args&&... args)
1179
      : OwningMetricCtorArgs(std::forward<Args>(args)...),
1180
        CounterPrototype(MetricPrototype::CtorArgs(
1181
            entity_type_.c_str(), name_.c_str(), label_.c_str(), unit_, description_.c_str(),
1182
2
            level_, flags_)) {}
1183
};
1184
1185
template <class T>
1186
class OwningGaugePrototype : public OwningMetricCtorArgs, public GaugePrototype<T> {
1187
 public:
1188
  template <class... Args>
1189
  explicit OwningGaugePrototype(Args&&... args)
1190
      : OwningMetricCtorArgs(std::forward<Args>(args)...),
1191
        GaugePrototype<T>(MetricPrototype::CtorArgs(
1192
            entity_type_.c_str(), name_.c_str(), label_.c_str(), unit_, description_.c_str(),
1193
3.15M
            level_, flags_)) {}
yb::OwningGaugePrototype<long long>::OwningGaugePrototype<char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricUnit::Type, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricLevel>(char const*&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricUnit::Type&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricLevel&&)
Line
Count
Source
1193
209k
            level_, flags_)) {}
yb::OwningGaugePrototype<unsigned long long>::OwningGaugePrototype<char const (&) [7], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricUnit::Type, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricLevel, yb::PrototypeFlags>(char const (&) [7], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricUnit::Type&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricLevel&&, yb::PrototypeFlags&&)
Line
Count
Source
1193
32.9k
            level_, flags_)) {}
yb::OwningGaugePrototype<unsigned long long>::OwningGaugePrototype<char const (&) [7], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricUnit::Type, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricLevel>(char const (&) [7], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricUnit::Type&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, yb::MetricLevel&&)
Line
Count
Source
1193
32.9k
            level_, flags_)) {}
yb::OwningGaugePrototype<long long>::OwningGaugePrototype<char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, yb::MetricUnit::Type, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, yb::MetricLevel>(char const*&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, yb::MetricUnit::Type&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, yb::MetricLevel&&)
Line
Count
Source
1193
2.40M
            level_, flags_)) {}
yb::OwningGaugePrototype<unsigned long long>::OwningGaugePrototype<char const (&) [7], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, yb::MetricUnit::Type, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, yb::MetricLevel, yb::PrototypeFlags>(char const (&) [7], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, yb::MetricUnit::Type&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, yb::MetricLevel&&, yb::PrototypeFlags&&)
Line
Count
Source
1193
480k
            level_, flags_)) {}
1194
};
1195
1196
class OwningHistogramPrototype : public OwningMetricCtorArgs, public HistogramPrototype {
1197
 public:
1198
  template <class... Args>
1199
  explicit OwningHistogramPrototype(const std::string& entity_type,
1200
                                    const std::string& name,
1201
                                    const std::string& label,
1202
                                    MetricUnit::Type unit,
1203
                                    const std::string& description,
1204
                                    MetricLevel level,
1205
                                    uint32_t flags,
1206
                                    uint64_t max_trackable_value,
1207
                                    int num_sig_digits,
1208
                                    ExportPercentiles export_percentiles =
1209
                                        ExportPercentiles::kFalse)
1210
      : OwningMetricCtorArgs(entity_type, name, label, unit, description, level, flags),
1211
        HistogramPrototype(MetricPrototype::CtorArgs(
1212
            OwningMetricCtorArgs::entity_type_.c_str(), OwningMetricCtorArgs::name_.c_str(),
1213
            OwningMetricCtorArgs::label_.c_str(), OwningMetricCtorArgs::unit_,
1214
            OwningMetricCtorArgs::description_.c_str(), OwningMetricCtorArgs::level_, flags_),
1215
65.7k
                           max_trackable_value, num_sig_digits, export_percentiles) {}
1216
};
1217
1218
// Replace specific chars with underscore to pass PrometheusNameRegex().
1219
void EscapeMetricNameForPrometheus(std::string *id);
1220
1221
} // namespace yb
1222
1223
#endif // YB_UTIL_METRICS_H