Line data Source code
1 : /*
2 : * Copyright (c) 2024 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * 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, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 : #pragma once
18 :
19 : #include <lib/core/CHIPError.h>
20 : #include <lib/support/CodeUtils.h>
21 : #include <tracing/metric_keys.h>
22 : #include <tracing/metric_macros.h>
23 : #include <tracing/registry.h>
24 :
25 : namespace chip {
26 : namespace Tracing {
27 :
28 : /**
29 : * Define a metric that can be logged. A metric consists of a key and an optional value pair.
30 : * The value is currently limited to simple scalar values.
31 : *
32 : * Additionally a metric is tagged as either an instant event or marked with a begin/end
33 : * for the event. When the latter is used, a duration can be associated between the two events.
34 : */
35 : class MetricEvent
36 : {
37 : public:
38 : MetricEvent(const MetricEvent &) = default;
39 : MetricEvent(MetricEvent &&) = default;
40 : MetricEvent & operator=(const MetricEvent &) = default;
41 : MetricEvent & operator=(MetricEvent &&) = default;
42 :
43 : // This specifies the different categories of metric events that can created. In addition to
44 : // emitting an event, events paired with a kBeginEvent and kEndEvent can be used to track
45 : // duration for the event. A kInstantEvent represents a one shot event.
46 : enum class Type
47 : {
48 : // This specifies an event marked to track the Begin of an operation
49 : kBeginEvent,
50 :
51 : // This specifies an event marked to track the End of an operation
52 : kEndEvent,
53 :
54 : // This specifies a one shot event
55 : kInstantEvent
56 : };
57 :
58 : // This defines the different types of values that can stored when a metric is emitted
59 : struct Value
60 : {
61 : Value(const Value &) = default;
62 : Value(Value &&) = default;
63 : Value & operator=(const Value &) = default;
64 : Value & operator=(Value &&) = default;
65 :
66 : enum class Type : uint8_t
67 : {
68 : kUndefined, // Value is not valid
69 : kInt32, // int32_t
70 : kUInt32, // uint32_t
71 : kChipErrorCode // chip::ChipError
72 : };
73 :
74 : union Store
75 : {
76 : int32_t int32_value;
77 : uint32_t uint32_value;
78 :
79 : Store() {}
80 :
81 : Store(int32_t v) : int32_value(v) {}
82 :
83 : Store(uint32_t v) : uint32_value(v) {}
84 : };
85 :
86 : Store store;
87 : Type type;
88 :
89 : Value() : type(Type::kUndefined) {}
90 :
91 : Value(uint32_t value) : store(value), type(Type::kUInt32) {}
92 :
93 : Value(int32_t value) : store(value), type(Type::kInt32) {}
94 :
95 : Value(const ChipError & err) : store(err.AsInteger()), type(Type::kChipErrorCode) {}
96 : };
97 :
98 : MetricEvent(Type type, MetricKey key) : mType(type), mKey(key) {}
99 :
100 : MetricEvent(Type type, MetricKey key, int32_t value) : mType(type), mKey(key), mValue(value) {}
101 :
102 : MetricEvent(Type type, MetricKey key, uint32_t value) : mType(type), mKey(key), mValue(value) {}
103 :
104 : MetricEvent(Type type, MetricKey key, const ChipError & error) : mType(type), mKey(key), mValue(error) {}
105 :
106 : MetricEvent(Type type, MetricKey key, Value value) : mType(type), mKey(key), mValue(value) {}
107 :
108 : MetricEvent(Type type, MetricKey key, int8_t value) : MetricEvent(type, key, int32_t(value)) {}
109 :
110 : MetricEvent(Type type, MetricKey key, uint8_t value) : MetricEvent(type, key, uint32_t(value)) {}
111 :
112 : MetricEvent(Type type, MetricKey key, int16_t value) : MetricEvent(type, key, int32_t(value)) {}
113 :
114 : MetricEvent(Type type, MetricKey key, uint16_t value) : MetricEvent(type, key, uint32_t(value)) {}
115 :
116 : Type type() const { return mType; }
117 :
118 0 : MetricKey key() const { return mKey; }
119 :
120 0 : Value::Type ValueType() const { return mValue.type; }
121 :
122 0 : uint32_t ValueUInt32() const
123 : {
124 0 : VerifyOrDie(mValue.type == Value::Type::kUInt32);
125 0 : return mValue.store.uint32_value;
126 : }
127 :
128 0 : int32_t ValueInt32() const
129 : {
130 0 : VerifyOrDie(mValue.type == Value::Type::kInt32);
131 0 : return mValue.store.int32_value;
132 : }
133 :
134 0 : uint32_t ValueErrorCode() const
135 : {
136 0 : VerifyOrDie(mValue.type == Value::Type::kChipErrorCode);
137 0 : return mValue.store.uint32_value;
138 : }
139 :
140 : private:
141 : Type mType;
142 : MetricKey mKey;
143 : Value mValue;
144 : };
145 :
146 : namespace ErrorHandling {
147 :
148 : /**
149 : * Utility to emit an instant metric if the error is not a success.
150 : */
151 : inline bool LogMetricIfError(MetricKey metricKey, const ::chip::ChipError & err)
152 : {
153 : bool success = ::chip::ChipError::IsSuccess(err);
154 : if (!success)
155 : {
156 : MATTER_LOG_METRIC(metricKey, err);
157 : }
158 : return success;
159 : }
160 :
161 : } // namespace ErrorHandling
162 :
163 : /**
164 : * This utility class helps generate a Begin and End metric event within the scope of a block using RAII.
165 : */
166 : class ScopedMetricEvent
167 : {
168 : public:
169 : ScopedMetricEvent(const ScopedMetricEvent &) = delete;
170 : ScopedMetricEvent(ScopedMetricEvent &&) = delete;
171 : ScopedMetricEvent & operator=(const ScopedMetricEvent &) = delete;
172 : ScopedMetricEvent & operator=(ScopedMetricEvent &&) = delete;
173 :
174 : ScopedMetricEvent(MetricKey key, ChipError & error) : mKey(key), mError(error)
175 : {
176 : MATTER_LOG_METRIC_BEGIN(mKey);
177 : IgnoreUnusedVariable(mKey);
178 : IgnoreUnusedVariable(mError);
179 : }
180 :
181 : ~ScopedMetricEvent() { MATTER_LOG_METRIC_END(mKey, mError); }
182 :
183 : private:
184 : MetricKey mKey;
185 : ChipError & mError;
186 : };
187 :
188 : } // namespace Tracing
189 : } // namespace chip
|