From 14491928bc6b86080183b268957169f6ffbaecde Mon Sep 17 00:00:00 2001 From: shripad621git <79364691+shripad621git@users.noreply.github.com> Date: Wed, 6 Dec 2023 20:20:24 +0530 Subject: [PATCH] [ESP32] Added the support to report the chip system statistics to the esp-insights. (#29158) * Added the support to report the chip system statistics to the esp-insights. - The system stats from src/system/SystemStats.h are reported on enabling a config option to esp-insights. * Addressed review comments --- config/esp32/components/chip/CMakeLists.txt | 4 + config/esp32/components/chip/Kconfig | 6 + examples/lighting-app/esp32/main/main.cpp | 10 ++ src/tracing/esp32_trace/BUILD.gn | 15 ++ .../esp32_trace/insights_sys_stats.cpp | 161 ++++++++++++++++++ src/tracing/esp32_trace/insights_sys_stats.h | 69 ++++++++ 6 files changed, 265 insertions(+) create mode 100644 src/tracing/esp32_trace/insights_sys_stats.cpp create mode 100644 src/tracing/esp32_trace/insights_sys_stats.h diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index e32588db436e2c..e812480598a583 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -262,6 +262,10 @@ if (CONFIG_ENABLE_ESP_INSIGHTS_TRACE) chip_gn_arg_append("matter_trace_config" "\"${CHIP_ROOT}/src/tracing/esp32_trace:esp32_trace_tracing\"") endif() +if (CONFIG_ENABLE_ESP_INSIGHTS_SYSTEM_STATS) + chip_gn_arg_append("matter_enable_esp_insights_system_stats" "true") +endif() + if (CONFIG_USE_ESP32_ECDSA_PERIPHERAL) chip_gn_arg_append("chip_use_esp32_ecdsa_peripheral" "true") endif() diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index b73398bca4c2bf..ec2ab1a6b26d64 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -876,6 +876,12 @@ menu "CHIP Device Layer" Enabling the above option will enable the esp32 specific tracing functionality and report the diagnostic information to the insights cloud. + config ENABLE_ESP_INSIGHTS_SYSTEM_STATS + bool "Enable System Stats for insights" + depends on ESP_INSIGHTS_ENABLED + default n + help + This option enables the system statistics to be sent to the insights cloud. endmenu diff --git a/examples/lighting-app/esp32/main/main.cpp b/examples/lighting-app/esp32/main/main.cpp index 5b79e3d7083e14..5957a683589c26 100644 --- a/examples/lighting-app/esp32/main/main.cpp +++ b/examples/lighting-app/esp32/main/main.cpp @@ -39,6 +39,11 @@ #include #include +#if CONFIG_ENABLE_ESP_INSIGHTS_SYSTEM_STATS +#include +#define START_TIMEOUT_MS 600000 +#endif + #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER #include #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER @@ -115,6 +120,7 @@ static void InitServer(intptr_t context) DeviceCallbacksDelegate::Instance().SetAppDelegate(&sAppDeviceCallbacksDelegate); Esp32AppServer::Init(); // Init ZCL Data Model and CHIP App Server AND Initialize device attestation config + #if CONFIG_ENABLE_ESP_INSIGHTS_TRACE esp_insights_config_t config = { .log_type = ESP_DIAG_LOG_TYPE_ERROR | ESP_DIAG_LOG_TYPE_WARNING | ESP_DIAG_LOG_TYPE_EVENT, @@ -130,6 +136,10 @@ static void InitServer(intptr_t context) static Tracing::Insights::ESP32Backend backend; Tracing::Register(backend); + +#if CONFIG_ENABLE_ESP_INSIGHTS_SYSTEM_STATS + chip::System::Stats::InsightsSystemMetrics::GetInstance().RegisterAndEnable(chip::System::Clock::Timeout(START_TIMEOUT_MS)); +#endif #endif } diff --git a/src/tracing/esp32_trace/BUILD.gn b/src/tracing/esp32_trace/BUILD.gn index cb41004a74289b..7548894ab072ce 100644 --- a/src/tracing/esp32_trace/BUILD.gn +++ b/src/tracing/esp32_trace/BUILD.gn @@ -20,6 +20,10 @@ config("tracing") { include_dirs = [ "include" ] } +declare_args() { + matter_enable_esp_insights_system_stats = false +} + static_library("backend") { output_name = "libEsp32TracingBackend" output_dir = "${root_out_dir}/lib" @@ -28,6 +32,17 @@ static_library("backend") { "esp32_tracing.cpp", "esp32_tracing.h", ] + if (matter_enable_esp_insights_system_stats) { + sources += [ + "insights_sys_stats.cpp", + "insights_sys_stats.h", + ] + deps = [ + "${chip_root}/src/lib/core", + "${chip_root}/src/platform", + "${chip_root}/src/system", + ] + } public_deps = [ "${chip_root}/src/tracing" ] } diff --git a/src/tracing/esp32_trace/insights_sys_stats.cpp b/src/tracing/esp32_trace/insights_sys_stats.cpp new file mode 100644 index 00000000000000..128afc911c85d5 --- /dev/null +++ b/src/tracing/esp32_trace/insights_sys_stats.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023 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 "insights_sys_stats.h" +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace System { +namespace Stats { + +InsightsSystemMetrics & InsightsSystemMetrics::GetInstance() +{ + static InsightsSystemMetrics instance; + return instance; +} + +void InsightsSystemMetrics::SamplingHandler(Layer * systemLayer, void * context) +{ + auto instance = static_cast(context); + count_t * highwatermarks = GetHighWatermarks(); + for (int i = 0; i < System::Stats::kNumEntries; i++) + { + esp_err_t err = esp_diag_metrics_add_uint(instance->mLabels[i], static_cast(highwatermarks[i])); + if (err != ESP_OK) + { + ESP_LOGE(kTag, "Failed to add the metric:%s, err:%d", instance->mLabels[i], err); + } + } + DeviceLayer::SystemLayer().StartTimer(instance->GetSamplingInterval(), SamplingHandler, instance); +} + +CHIP_ERROR InsightsSystemMetrics::Unregister(intptr_t arg) +{ + InsightsSystemMetrics * instance = reinterpret_cast(arg); + if (!mRegistered) + { + return CHIP_ERROR_INCORRECT_STATE; + } + for (int i = 0; i < System::Stats::kNumEntries; i++) + { + if (mLabels[i] != nullptr) + { + esp_err_t err = esp_diag_metrics_unregister(mLabels[i]); + if (err != ESP_OK) + { + ESP_LOGE(kTag, "Failed to unregister metric:%s, err:%d", mLabels[i], err); + } + free(mLabels[i]); + mLabels[i] = nullptr; + } + } + mRegistered = false; + DeviceLayer::SystemLayer().CancelTimer(SamplingHandler, instance); + return CHIP_NO_ERROR; +} + +void InsightsSystemMetrics::SetSamplingHandler(intptr_t arg) +{ + InsightsSystemMetrics * instance = reinterpret_cast(arg); + + if (instance->mTimeout == System::Clock::kZero) + { + DeviceLayer::SystemLayer().CancelTimer(SamplingHandler, instance); + } + else + { + DeviceLayer::SystemLayer().CancelTimer(SamplingHandler, instance); + CHIP_ERROR err = DeviceLayer::SystemLayer().StartTimer(instance->mTimeout, SamplingHandler, instance); + if (err != CHIP_NO_ERROR) + { + ESP_LOGE(kTag, "Failed to start the new timer %" CHIP_ERROR_FORMAT, err.Format()); + } + } +} + +CHIP_ERROR InsightsSystemMetrics::SetSamplingInterval(chip::System::Clock::Timeout aTimeout) +{ + if (!mRegistered) + { + return CHIP_ERROR_INCORRECT_STATE; + } + mTimeout = aTimeout; + + return DeviceLayer::PlatformMgr().ScheduleWork(SetSamplingHandler, reinterpret_cast(this)); +} + +CHIP_ERROR InsightsSystemMetrics::RegisterAndEnable(chip::System::Clock::Timeout aTimeout) +{ + if (mRegistered) + { + return CHIP_NO_ERROR; + } + + if (aTimeout == System::Clock::kZero) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + const Label * labels = GetStrings(); + for (int i = 0; i < System::Stats::kNumEntries; i++) + { + size_t labelLength = strlen(labels[i]); + if (labelLength >= kMaxStringLength) + { + labelLength = kMaxStringLength; + mLabels[i] = strndup(labels[i], labelLength - 1); + } + else + { + mLabels[i] = strndup(labels[i], labelLength); + } + + if (mLabels[i] == NULL) + { + Unregister(reinterpret_cast(this)); + return CHIP_ERROR_NO_MEMORY; + } + + esp_err_t err = esp_diag_metrics_register(kTag, mLabels[i], labels[i], kPath, ESP_DIAG_DATA_TYPE_UINT); + if (err != ESP_OK) + { + ESP_LOGE(kTag, "Failed to register metric:%s, err:%d", mLabels[i], err); + Unregister(reinterpret_cast(this)); + return CHIP_ERROR_INCORRECT_STATE; + } + } + + mTimeout = System::Clock::Milliseconds32(aTimeout); + + CHIP_ERROR err = DeviceLayer::SystemLayer().StartTimer(GetSamplingInterval(), SamplingHandler, this); + if (err != CHIP_NO_ERROR) + { + ESP_LOGE(kTag, "Failed to start the timer, err:%" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + mRegistered = true; + return CHIP_NO_ERROR; +} + +} // namespace Stats +} // namespace System +} // namespace chip diff --git a/src/tracing/esp32_trace/insights_sys_stats.h b/src/tracing/esp32_trace/insights_sys_stats.h new file mode 100644 index 00000000000000..6d043b0587fe61 --- /dev/null +++ b/src/tracing/esp32_trace/insights_sys_stats.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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 +#include +#include +#include +namespace chip { +namespace System { +namespace Stats { + +class InsightsSystemMetrics +{ +public: + static InsightsSystemMetrics & GetInstance(); + + /* + * This api registers the system metrics to the insights and starts the + * timer to enable system stats periodically to the insights. + */ + CHIP_ERROR RegisterAndEnable(chip::System::Clock::Timeout aTimeout); + + /* + * This api unregisters the system stats which are registered + * as metrics to the esp-insights. + */ + CHIP_ERROR Unregister(intptr_t arg); + + /* + * This api cancels the timeout providing the user the flexibility + * to increase or decrease the frequency of sampling the System + * Stats. It cancels the timer if new timeout value is zero. + * If the value of timeout differs from existing value, then + * it cancels the previous timer and starts a new timer. + */ + CHIP_ERROR SetSamplingInterval(chip::System::Clock::Timeout aTimeout); + + System::Clock::Timeout GetSamplingInterval() { return mTimeout; } + +private: + InsightsSystemMetrics() {} + static constexpr int kMaxStringLength = 16; + bool mRegistered = false; + static constexpr char kPath[] = "sys.mtr"; + static constexpr char kTag[] = "MTR"; + System::Clock::Timeout mTimeout; + char * mLabels[chip::System::Stats::kNumEntries]; + + static void SamplingHandler(System::Layer * systemLayer, void * context); + static void SetSamplingHandler(intptr_t arg); +}; + +} // namespace Stats +} // namespace System +} // namespace chip