blob: ab2362d6facc86fdbf5d74b72f3e036e5dae00d8 [file] [log] [blame]
/*
*
* Copyright (c) 2025 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#include <cctype>
#include <lib/support/CHIPMemString.h>
#include <system/SystemClock.h>
#include <tracing/esp32_diagnostics/Counter.h>
#include <tracing/esp32_diagnostics/DiagnosticTracing.h>
namespace chip {
namespace Tracing {
namespace Diagnostics {
namespace {
// Implements a murmurhash with 0 seed.
uint32_t MurmurHash(const void * key)
{
const uint32_t kMultiplier = 0x5bd1e995;
const uint32_t kShift = 24;
const unsigned char * data = static_cast<const unsigned char *>(key);
uint32_t hash = 0;
while (*data)
{
uint32_t value = static_cast<uint32_t>(tolower(static_cast<unsigned char>(*data++)));
value *= kMultiplier;
value ^= value >> kShift;
value *= kMultiplier;
hash *= kMultiplier;
hash ^= value;
}
hash ^= hash >> 13;
hash *= kMultiplier;
hash ^= hash >> 15;
if (hash == 0)
{
ChipLogError(DeviceLayer, "MurmurHash resulted in a hash value of 0");
}
return hash;
}
} // anonymous namespace
ESP32Diagnostics::ESP32Diagnostics(CircularDiagnosticBuffer * storageInstance) : mStorageInstance(storageInstance)
{
ClearFilters();
InitializeDefaultFilters();
}
void ESP32Diagnostics::InitializeDefaultFilters()
{
static constexpr const char * kDefaultFilters[] = {
"PASESession", "CASESession", "NetworkCommissioning", "GeneralCommissioning", "OperationalCredentials",
"CASEServer", "Fabric",
};
for (const auto & filter : kDefaultFilters)
{
mEnabledFilters.insert(MurmurHash(filter));
}
}
CHIP_ERROR ESP32Diagnostics::AddFilter(const char * scope)
{
VerifyOrReturnError(scope != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(strlen(scope) > 0, CHIP_ERROR_INVALID_ARGUMENT);
mEnabledFilters.insert(MurmurHash(scope));
return CHIP_NO_ERROR;
}
CHIP_ERROR ESP32Diagnostics::RemoveFilter(const char * scope)
{
VerifyOrReturnError(scope != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(strlen(scope) > 0, CHIP_ERROR_INVALID_ARGUMENT);
auto it = mEnabledFilters.find(MurmurHash(scope));
VerifyOrReturnError(it != mEnabledFilters.end(), CHIP_ERROR_INCORRECT_STATE);
mEnabledFilters.erase(it);
return CHIP_NO_ERROR;
}
void ESP32Diagnostics::ClearFilters()
{
mEnabledFilters.clear();
}
bool ESP32Diagnostics::IsEnabled(const char * scope)
{
// If no filters are set, all scopes are enabled
if (mEnabledFilters.empty())
{
return true;
}
return mEnabledFilters.count(MurmurHash(scope)) > 0;
}
#ifdef CONFIG_ENABLE_ESP_DIAGNOSTIC_METRICS
void ESP32Diagnostics::LogMessageReceived(MessageReceivedInfo & info) {}
void ESP32Diagnostics::LogMessageSend(MessageSendInfo & info) {}
void ESP32Diagnostics::LogNodeLookup(NodeLookupInfo & info) {}
void ESP32Diagnostics::LogNodeDiscovered(NodeDiscoveredInfo & info) {}
void ESP32Diagnostics::LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo & info) {}
void ESP32Diagnostics::LogMetricEvent(const MetricEvent & event)
{
VerifyOrReturn(mStorageInstance != nullptr, ChipLogError(DeviceLayer, "Diagnostic Storage Instance cannot be NULL"));
DiagnosticEntry entry;
switch (event.ValueType())
{
case ValueType::kInt32:
ChipLogDetail(DeviceLayer, "The value of %s is %" PRId32, event.key(), event.ValueInt32());
Platform::CopyString(entry.label, event.key());
entry.intValue = event.ValueInt32();
entry.type = Diagnostics::ValueType::kSignedInteger;
entry.timestamps_ms_since_boot = static_cast<uint32_t>(chip::System::SystemClock().GetMonotonicMilliseconds64().count());
ReturnOnFailure(mStorageInstance->Store(entry));
break;
case ValueType::kUInt32:
ChipLogDetail(DeviceLayer, "The value of %s is %" PRIu32, event.key(), event.ValueUInt32());
Platform::CopyString(entry.label, event.key());
entry.uintValue = event.ValueUInt32();
entry.type = Diagnostics::ValueType::kUnsignedInteger;
entry.timestamps_ms_since_boot = static_cast<uint32_t>(chip::System::SystemClock().GetMonotonicMilliseconds64().count());
ReturnOnFailure(mStorageInstance->Store(entry));
break;
case ValueType::kChipErrorCode:
ChipLogDetail(DeviceLayer, "The value of %s is error with code %" PRIu32, event.key(), event.ValueErrorCode());
break;
case ValueType::kUndefined:
ChipLogDetail(DeviceLayer, "The value of %s is undefined", event.key());
break;
default:
ChipLogDetail(DeviceLayer, "The value of %s is of an UNKNOWN TYPE", event.key());
break;
}
}
void ESP32Diagnostics::TraceCounter(const char * label)
{
ESPDiagnosticCounter & counter = ESPDiagnosticCounter::GetInstance();
counter.IncreaseCount(label);
ReturnOnFailure(counter.ReportMetrics(label, mStorageInstance));
}
#endif // CONFIG_ENABLE_ESP_DIAGNOSTIC_METRICS
#ifdef CONFIG_ENABLE_ESP_DIAGNOSTIC_TRACES
void ESP32Diagnostics::TraceBegin(const char * label, const char * group)
{
VerifyOrReturn(IsEnabled(group));
ReturnOnFailure(StoreDiagnostics(label, group));
}
void ESP32Diagnostics::TraceEnd(const char * label, const char * group) {}
void ESP32Diagnostics::TraceInstant(const char * label, const char * value)
{
VerifyOrReturn(IsEnabled(value));
ReturnOnFailure(StoreDiagnostics(label, value));
}
#endif // CONFIG_ENABLE_ESP_DIAGNOSTIC_TRACES
CHIP_ERROR ESP32Diagnostics::StoreDiagnostics(const char * label, const char * group)
{
VerifyOrReturnError(label != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(group != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(mStorageInstance != nullptr, CHIP_ERROR_INCORRECT_STATE,
ChipLogError(DeviceLayer, "Diagnostic Storage Instance cannot be NULL"));
DiagnosticEntry entry;
Platform::CopyString(entry.label, label);
Platform::CopyString(entry.stringValue, group);
entry.type = Diagnostics::ValueType::kCharString;
entry.timestamps_ms_since_boot = static_cast<uint32_t>(chip::System::SystemClock().GetMonotonicMilliseconds64().count());
return mStorageInstance->Store(entry);
}
} // namespace Diagnostics
} // namespace Tracing
} // namespace chip