|
1 | 1 | #pragma once |
2 | 2 |
|
3 | | -// This component provides an interface, `Metric`, and specific classes for |
4 | | -// Counter and Gauge metrics. A metric has a name, type, and set of key:value |
5 | | -// tags associated with it. Metrics can be general to APM or language-specific. |
6 | | -// General metrics have `common` set to `true`, and language-specific metrics |
7 | | -// have `common` set to `false`. |
8 | | - |
9 | | -#include <atomic> |
10 | 3 | #include <string> |
11 | | -#include <vector> |
12 | 4 |
|
13 | 5 | namespace datadog { |
14 | 6 | namespace telemetry { |
15 | 7 |
|
16 | | -class Metric { |
17 | | - // The name of the metric that will be published. A transformation occurs |
18 | | - // based on the name and whether it is "common" or "language-specific" when it |
19 | | - // is recorded. |
20 | | - std::string name_; |
21 | | - // The type of the metric. This will currently be count or gauge. |
22 | | - std::string type_; |
23 | | - // Namespace of the metric. |
24 | | - std::string scope_; |
25 | | - // Tags associated with this specific instance of the metric. |
26 | | - std::vector<std::string> tags_; |
27 | | - // This affects the transformation of the metric name, where it can be a |
28 | | - // common telemetry metric, or a language-specific metric that is prefixed |
29 | | - // with the language name. |
30 | | - bool common_; |
31 | | - |
32 | | - protected: |
33 | | - std::atomic<uint64_t> value_ = 0; |
34 | | - Metric(std::string name, std::string type, std::string scope, |
35 | | - std::vector<std::string> tags, bool common); |
36 | | - |
37 | | - Metric(Metric&& rhs) |
38 | | - : name_(std::move(rhs.name_)), |
39 | | - type_(std::move(rhs.type_)), |
40 | | - scope_(std::move(rhs.scope_)), |
41 | | - tags_(std::move(rhs.tags_)) { |
42 | | - rhs.value_.store(value_.exchange(rhs.value_)); |
43 | | - } |
44 | | - |
45 | | - Metric& operator=(Metric&& rhs) { |
46 | | - if (&rhs != this) { |
47 | | - std::swap(name_, rhs.name_); |
48 | | - std::swap(type_, rhs.type_); |
49 | | - std::swap(scope_, rhs.scope_); |
50 | | - std::swap(tags_, rhs.tags_); |
51 | | - rhs.value_.store(value_.exchange(rhs.value_)); |
52 | | - } |
53 | | - return *this; |
54 | | - } |
55 | | - |
56 | | - public: |
57 | | - // Accessors for name, type, tags, common and capture_and_reset_value are used |
58 | | - // when producing the JSON message for reporting metrics. |
59 | | - std::string name(); |
60 | | - std::string type(); |
61 | | - std::string scope(); |
62 | | - std::vector<std::string> tags(); |
63 | | - bool common(); |
64 | | - uint64_t value(); |
65 | | - uint64_t capture_and_reset_value(); |
66 | | -}; |
67 | | - |
68 | | -// A count metric is used for measuring activity, and has methods for adding a |
69 | | -// number of actions, or incrementing the current number of actions by 1. |
70 | | -class CounterMetric : public Metric { |
71 | | - public: |
72 | | - CounterMetric(std::string name, std::string scope, |
73 | | - std::vector<std::string> tags, bool common); |
74 | | - void inc(); |
75 | | - void add(uint64_t amount); |
| 8 | +namespace details { |
| 9 | +enum class MetricType : char { counter, rate, distribution }; |
| 10 | +} |
| 11 | + |
| 12 | +/// TODO: pre-compute hash? |
| 13 | +template <details::MetricType T> |
| 14 | +struct Metric final { |
| 15 | + /// The type of the metric. |
| 16 | + static constexpr details::MetricType type = T; |
| 17 | + /// The name of the metric that will be published. A transformation occurs |
| 18 | + /// based on the name and whether it is "common" or "language-specific" when |
| 19 | + /// it is recorded. |
| 20 | + std::string name; |
| 21 | + /// Namespace of the metric. |
| 22 | + std::string scope; |
| 23 | + /// This affects the transformation of the metric name, where it can be a |
| 24 | + /// common telemetry metric, or a language-specific metric that is prefixed |
| 25 | + /// with the language name. |
| 26 | + bool common; |
76 | 27 | }; |
77 | 28 |
|
78 | | -// A gauge metric is used for measuring state, and mas methods to set the |
79 | | -// current state, add or subtract from it, or increment/decrement the current |
80 | | -// state by 1. |
81 | | -class GaugeMetric : public Metric { |
82 | | - public: |
83 | | - GaugeMetric(std::string name, std::string scope, |
84 | | - std::vector<std::string> tags, bool common); |
85 | | - void set(uint64_t value); |
86 | | - void inc(); |
87 | | - void add(uint64_t amount); |
88 | | - void dec(); |
89 | | - void sub(uint64_t amount); |
90 | | -}; |
91 | | - |
92 | | -// This structure contains all the metrics that are exposed by tracer |
93 | | -// telemetry. |
94 | | -struct DefaultMetrics { |
95 | | - struct { |
96 | | - telemetry::CounterMetric spans_created = { |
97 | | - "spans_created", "tracers", {}, true}; |
98 | | - telemetry::CounterMetric spans_finished = { |
99 | | - "spans_finished", "tracers", {}, true}; |
100 | | - |
101 | | - telemetry::CounterMetric trace_segments_created_new = { |
102 | | - "trace_segments_created", "tracers", {"new_continued:new"}, true}; |
103 | | - telemetry::CounterMetric trace_segments_created_continued = { |
104 | | - "trace_segments_created", "tracers", {"new_continued:continued"}, true}; |
105 | | - telemetry::CounterMetric trace_segments_closed = { |
106 | | - "trace_segments_closed", "tracers", {}, true}; |
107 | | - telemetry::CounterMetric baggage_items_exceeded = { |
108 | | - "context_header.truncated", |
109 | | - "tracers", |
110 | | - {{"truncation_reason:baggage_item_count_exceeded"}}, |
111 | | - true, |
112 | | - }; |
113 | | - telemetry::CounterMetric baggage_bytes_exceeded = { |
114 | | - "context_header.truncated", |
115 | | - "tracers", |
116 | | - {{"truncation_reason:baggage_byte_count_exceeded"}}, |
117 | | - true, |
118 | | - }; |
119 | | - } tracer; |
120 | | - struct { |
121 | | - telemetry::CounterMetric requests = { |
122 | | - "trace_api.requests", "tracers", {}, true}; |
123 | | - |
124 | | - telemetry::CounterMetric responses_1xx = { |
125 | | - "trace_api.responses", "tracers", {"status_code:1xx"}, true}; |
126 | | - telemetry::CounterMetric responses_2xx = { |
127 | | - "trace_api.responses", "tracers", {"status_code:2xx"}, true}; |
128 | | - telemetry::CounterMetric responses_3xx = { |
129 | | - "trace_api.responses", "tracers", {"status_code:3xx"}, true}; |
130 | | - telemetry::CounterMetric responses_4xx = { |
131 | | - "trace_api.responses", "tracers", {"status_code:4xx"}, true}; |
132 | | - telemetry::CounterMetric responses_5xx = { |
133 | | - "trace_api.responses", "tracers", {"status_code:5xx"}, true}; |
134 | | - |
135 | | - telemetry::CounterMetric errors_timeout = { |
136 | | - "trace_api.errors", "tracers", {"type:timeout"}, true}; |
137 | | - telemetry::CounterMetric errors_network = { |
138 | | - "trace_api.errors", "tracers", {"type:network"}, true}; |
139 | | - telemetry::CounterMetric errors_status_code = { |
140 | | - "trace_api.errors", "tracers", {"type:status_code"}, true}; |
141 | | - |
142 | | - } trace_api; |
143 | | -}; |
| 29 | +using Counter = Metric<details::MetricType::counter>; |
| 30 | +using Rate = Metric<details::MetricType::rate>; |
| 31 | +using Distribution = Metric<details::MetricType::distribution>; |
144 | 32 |
|
145 | 33 | } // namespace telemetry |
146 | 34 | } // namespace datadog |
0 commit comments