Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2025 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #include <algorithm>
20 : #include <cctype>
21 : #include <lib/support/CHIPMemString.h>
22 : #include <system/SystemClock.h>
23 : #include <tracing/esp32_diagnostics/Counter.h>
24 : #include <tracing/esp32_diagnostics/DiagnosticTracing.h>
25 :
26 : namespace chip {
27 : namespace Tracing {
28 : namespace Diagnostics {
29 :
30 : namespace {
31 : // Implements a murmurhash with 0 seed.
32 116 : uint32_t MurmurHash(const void * key)
33 : {
34 116 : const uint32_t kMultiplier = 0x5bd1e995;
35 116 : const uint32_t kShift = 24;
36 116 : const unsigned char * data = static_cast<const unsigned char *>(key);
37 116 : uint32_t hash = 0;
38 :
39 1632 : while (*data)
40 : {
41 1516 : uint32_t value = static_cast<uint32_t>(tolower(static_cast<unsigned char>(*data++)));
42 1516 : value *= kMultiplier;
43 1516 : value ^= value >> kShift;
44 1516 : value *= kMultiplier;
45 1516 : hash *= kMultiplier;
46 1516 : hash ^= value;
47 : }
48 :
49 116 : hash ^= hash >> 13;
50 116 : hash *= kMultiplier;
51 116 : hash ^= hash >> 15;
52 :
53 116 : if (hash == 0)
54 : {
55 0 : ChipLogError(DeviceLayer, "MurmurHash resulted in a hash value of 0");
56 : }
57 :
58 116 : return hash;
59 : }
60 : } // anonymous namespace
61 :
62 10 : ESP32Diagnostics::ESP32Diagnostics(CircularDiagnosticBuffer * storageInstance) : mStorageInstance(storageInstance)
63 : {
64 10 : ClearFilters();
65 10 : InitializeDefaultFilters();
66 10 : }
67 :
68 10 : void ESP32Diagnostics::InitializeDefaultFilters()
69 : {
70 : static constexpr const char * kDefaultFilters[] = {
71 : "PASESession", "CASESession", "NetworkCommissioning", "GeneralCommissioning", "OperationalCredentials",
72 : "CASEServer", "Fabric",
73 : };
74 80 : for (const auto & filter : kDefaultFilters)
75 : {
76 70 : mEnabledFilters.insert(MurmurHash(filter));
77 : }
78 10 : }
79 :
80 13 : CHIP_ERROR ESP32Diagnostics::AddFilter(const char * scope)
81 : {
82 13 : VerifyOrReturnError(scope != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
83 12 : VerifyOrReturnError(strlen(scope) > 0, CHIP_ERROR_INVALID_ARGUMENT);
84 11 : mEnabledFilters.insert(MurmurHash(scope));
85 11 : return CHIP_NO_ERROR;
86 : }
87 :
88 5 : CHIP_ERROR ESP32Diagnostics::RemoveFilter(const char * scope)
89 : {
90 5 : VerifyOrReturnError(scope != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
91 4 : VerifyOrReturnError(strlen(scope) > 0, CHIP_ERROR_INVALID_ARGUMENT);
92 3 : auto it = mEnabledFilters.find(MurmurHash(scope));
93 3 : VerifyOrReturnError(it != mEnabledFilters.end(), CHIP_ERROR_INCORRECT_STATE);
94 2 : mEnabledFilters.erase(it);
95 2 : return CHIP_NO_ERROR;
96 : }
97 :
98 18 : void ESP32Diagnostics::ClearFilters()
99 : {
100 18 : mEnabledFilters.clear();
101 18 : }
102 :
103 43 : bool ESP32Diagnostics::IsEnabled(const char * scope)
104 : {
105 : // If no filters are set, all scopes are enabled
106 43 : if (mEnabledFilters.empty())
107 : {
108 11 : return true;
109 : }
110 32 : return mEnabledFilters.count(MurmurHash(scope)) > 0;
111 : }
112 :
113 : #ifdef CONFIG_ENABLE_ESP_DIAGNOSTIC_METRICS
114 0 : void ESP32Diagnostics::LogMessageReceived(MessageReceivedInfo & info) {}
115 :
116 0 : void ESP32Diagnostics::LogMessageSend(MessageSendInfo & info) {}
117 :
118 0 : void ESP32Diagnostics::LogNodeLookup(NodeLookupInfo & info) {}
119 :
120 0 : void ESP32Diagnostics::LogNodeDiscovered(NodeDiscoveredInfo & info) {}
121 :
122 0 : void ESP32Diagnostics::LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo & info) {}
123 :
124 0 : void ESP32Diagnostics::LogMetricEvent(const MetricEvent & event)
125 : {
126 0 : VerifyOrReturn(mStorageInstance != nullptr, ChipLogError(DeviceLayer, "Diagnostic Storage Instance cannot be NULL"));
127 : DiagnosticEntry entry;
128 0 : switch (event.ValueType())
129 : {
130 0 : case ValueType::kInt32:
131 0 : ChipLogDetail(DeviceLayer, "The value of %s is %" PRId32, event.key(), event.ValueInt32());
132 0 : Platform::CopyString(entry.label, event.key());
133 0 : entry.intValue = event.ValueInt32();
134 0 : entry.type = Diagnostics::ValueType::kSignedInteger;
135 0 : entry.timestamps_ms_since_boot = static_cast<uint32_t>(chip::System::SystemClock().GetMonotonicMilliseconds64().count());
136 0 : ReturnOnFailure(mStorageInstance->Store(entry));
137 0 : break;
138 0 : case ValueType::kUInt32:
139 0 : ChipLogDetail(DeviceLayer, "The value of %s is %" PRIu32, event.key(), event.ValueUInt32());
140 0 : Platform::CopyString(entry.label, event.key());
141 0 : entry.uintValue = event.ValueUInt32();
142 0 : entry.type = Diagnostics::ValueType::kUnsignedInteger;
143 0 : entry.timestamps_ms_since_boot = static_cast<uint32_t>(chip::System::SystemClock().GetMonotonicMilliseconds64().count());
144 0 : ReturnOnFailure(mStorageInstance->Store(entry));
145 0 : break;
146 0 : case ValueType::kChipErrorCode:
147 0 : ChipLogDetail(DeviceLayer, "The value of %s is error with code %" PRIu32, event.key(), event.ValueErrorCode());
148 0 : break;
149 0 : case ValueType::kUndefined:
150 0 : ChipLogDetail(DeviceLayer, "The value of %s is undefined", event.key());
151 0 : break;
152 0 : default:
153 0 : ChipLogDetail(DeviceLayer, "The value of %s is of an UNKNOWN TYPE", event.key());
154 0 : break;
155 : }
156 : }
157 :
158 0 : void ESP32Diagnostics::TraceCounter(const char * label)
159 : {
160 0 : ESPDiagnosticCounter & counter = ESPDiagnosticCounter::GetInstance();
161 0 : counter.IncreaseCount(label);
162 0 : ReturnOnFailure(counter.ReportMetrics(label, mStorageInstance));
163 : }
164 : #endif // CONFIG_ENABLE_ESP_DIAGNOSTIC_METRICS
165 :
166 : #ifdef CONFIG_ENABLE_ESP_DIAGNOSTIC_TRACES
167 2 : void ESP32Diagnostics::TraceBegin(const char * label, const char * group)
168 : {
169 2 : VerifyOrReturn(IsEnabled(group));
170 1 : ReturnOnFailure(StoreDiagnostics(label, group));
171 : }
172 :
173 0 : void ESP32Diagnostics::TraceEnd(const char * label, const char * group) {}
174 :
175 2 : void ESP32Diagnostics::TraceInstant(const char * label, const char * value)
176 : {
177 2 : VerifyOrReturn(IsEnabled(value));
178 1 : ReturnOnFailure(StoreDiagnostics(label, value));
179 : }
180 : #endif // CONFIG_ENABLE_ESP_DIAGNOSTIC_TRACES
181 :
182 2 : CHIP_ERROR ESP32Diagnostics::StoreDiagnostics(const char * label, const char * group)
183 : {
184 2 : VerifyOrReturnError(label != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
185 2 : VerifyOrReturnError(group != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
186 2 : VerifyOrReturnError(mStorageInstance != nullptr, CHIP_ERROR_INCORRECT_STATE,
187 : ChipLogError(DeviceLayer, "Diagnostic Storage Instance cannot be NULL"));
188 : DiagnosticEntry entry;
189 2 : Platform::CopyString(entry.label, label);
190 2 : Platform::CopyString(entry.stringValue, group);
191 2 : entry.type = Diagnostics::ValueType::kCharString;
192 2 : entry.timestamps_ms_since_boot = static_cast<uint32_t>(chip::System::SystemClock().GetMonotonicMilliseconds64().count());
193 :
194 2 : return mStorageInstance->Store(entry);
195 : }
196 :
197 : } // namespace Diagnostics
198 : } // namespace Tracing
199 : } // namespace chip
|