Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ESP32] Platform diagnostics framework #36532

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e73460d
esp32 diagnostic trace
pimpalemahesh Oct 10, 2024
3a65f88
esp32 diagnostic trace changes
pimpalemahesh Oct 25, 2024
018bcc5
example/temperature-measurement-app
pimpalemahesh Nov 14, 2024
5a9056e
backend: Add description for diagnosticstorage interface, remove unnc…
pimpalemahesh Nov 15, 2024
42c7597
temperature_measurement_app: Review changes
pimpalemahesh Nov 19, 2024
b35d816
esp32_diagnostic_trace: Review changes
pimpalemahesh Nov 26, 2024
ba7a654
backend: Replace linkedlist with map for counter diagnostics
pimpalemahesh Nov 21, 2024
6bfc6c4
backend: Pass diagnostic storage as a parameter to backend
pimpalemahesh Nov 27, 2024
e3f41ec
esp32_diagnostic_trace: Return actual data size
pimpalemahesh Dec 1, 2024
54eb600
temperature_measurement_app: Review changes
pimpalemahesh Nov 19, 2024
da03378
backend: Replace linkedlist with map for counter diagnostics
pimpalemahesh Nov 21, 2024
eb403eb
esp32_diagnostic_trace: add CircularDiagnosticBuffer class to improve…
pimpalemahesh Dec 6, 2024
0e41be7
esp32_diagnostic_trace: add extra tlv closing bytes check before copy…
pimpalemahesh Dec 9, 2024
b4f0e76
diagnostic_storage: unify diagnostic entries into a single type
pimpalemahesh Dec 10, 2024
3e1958f
diagnostic_storage: remove redundant code
pimpalemahesh Dec 10, 2024
4d2d9e2
backend: Remove redundant code, allow only permited value to trace in…
pimpalemahesh Dec 11, 2024
3e1cf1a
example: Remove redundant code
pimpalemahesh Dec 11, 2024
6835f62
diagnostic-buffer: clear buffer after successful bdx log transfer
pimpalemahesh Dec 23, 2024
00cac01
diagnostic-storage: Remove singltone design for storage instance
pimpalemahesh Dec 26, 2024
e848b4e
temperature-measurement-app: use seperate buffer for retrieval of dia…
pimpalemahesh Dec 27, 2024
aabef4c
temperature-measurement-app: pass diagnostic storage Instance as poin…
pimpalemahesh Jan 6, 2025
d75e86d
backend: update methods to propagate error to level up
pimpalemahesh Jan 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions config/esp32/components/chip/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -294,6 +294,11 @@ 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_DIAGNOSTICS_TRACE)
chip_gn_arg_bool("matter_enable_tracing_support" "true")
chip_gn_arg_append("matter_trace_config" "\"${CHIP_ROOT}/src/tracing/esp32_diagnostic_trace:esp32_diagnostic_tracing\"")
endif()

if (CONFIG_ENABLE_ESP_INSIGHTS_SYSTEM_STATS)
chip_gn_arg_append("matter_enable_esp_insights_system_stats" "true")
endif()
@@ -306,6 +311,10 @@ if (CONFIG_ENABLE_ESP_INSIGHTS_TRACE)
target_include_directories(${COMPONENT_LIB} INTERFACE "${CHIP_ROOT}/src/tracing/esp32_trace/include")
endif()

if (CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE)
target_include_directories(${COMPONENT_LIB} INTERFACE "${CHIP_ROOT}/src/tracing/esp32_diagnostic_trace/include")
endif()

if (CONFIG_CHIP_DEVICE_ENABLE_DYNAMIC_SERVER)
chip_gn_arg_append("chip_build_controller_dynamic_server" "true")
endif()
@@ -371,6 +380,11 @@ if (CONFIG_ENABLE_ESP_INSIGHTS_TRACE)
list(APPEND chip_libraries "${CMAKE_CURRENT_BINARY_DIR}/lib/libEsp32TracingBackend.a")
endif()

if (CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE)
list(APPEND chip_libraries "${CMAKE_CURRENT_BINARY_DIR}/lib/libEsp32DiagnosticsBackend.a")
endif()


# When using the pregenerated files, there is a edge case where an error appears for
# undeclared argument chip_code_pre_generated_directory. To get around with it we are
# disabling the --fail-on-unused-args flag.
24 changes: 15 additions & 9 deletions config/esp32/components/chip/Kconfig
Original file line number Diff line number Diff line change
@@ -838,6 +838,13 @@ menu "CHIP Device Layer"
NVS namespace. If this option is enabled, the application can use an API to set a CD,
the configured CD will be used for subsequent CD reads.

config ENABLE_ESP_DIAGNOSTICS_TRACE
bool "Enable ESP Platform Diagnostics for Matter"
default n
help
Enables the ESP Diagnostics platform to collect, store, and retrieve diagnostic data for the Matter protocol.
This feature helps monitor system health and performance by providing insights through diagnostics logs.

config ENABLE_ESP_INSIGHTS_TRACE
bool "Enable Matter ESP Insights"
depends on ESP_INSIGHTS_ENABLED
@@ -854,15 +861,14 @@ menu "CHIP Device Layer"
help
This option enables the system statistics to be sent to the insights cloud.

config MAX_PERMIT_LIST_SIZE
int "Set permit list size for Insights traces"
range 5 30
depends on ESP_INSIGHTS_ENABLED
default 20
help
Maximum number of group entries that can be included in the permit list for reporting
the traces to insights.

config MAX_PERMIT_LIST_SIZE
int "Set permit list size for Insights traces"
range 5 30
depends on ESP_INSIGHTS_ENABLED || ENABLE_ESP_DIAGNOSTICS_TRACE
default 20
help
Set the maximum number of group entries that can be included in the permit list for reporting
traces to Insights or diagnostics. This ensures proper management of trace reporting capacity.
endmenu


Original file line number Diff line number Diff line change
@@ -83,3 +83,21 @@ depends on ENABLE_PW_RPC
about available pin numbers for UART.

endmenu

menu "Platform Diagnostics"

config END_USER_BUFFER_SIZE
int "Set buffer size for end user diagnostic data"
depends on ENABLE_ESP_DIAGNOSTICS_TRACE
default 4096
help
Defines the buffer size (in bytes) for storing diagnostic data related to end user activity.
This buffer will hold logs and traces relevant to user interactions with the Matter protocol.

config RETRIEVAL_BUFFER_SIZE
int "Set buffer size for retrieval of diagnostics from diagnostic storage"
depends on ENABLE_ESP_DIAGNOSTICS_TRACE
default 4096
help
Defines the buffer size (in bytes) for retrieval of diagnostic data.
endmenu
Original file line number Diff line number Diff line change
@@ -29,6 +29,11 @@ using namespace chip::app::Clusters::DiagnosticLogs;
LogProvider LogProvider::sInstance;
LogProvider::CrashLogContext LogProvider::sCrashLogContext;

#if CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
static uint32_t sReadEntries = 0;
static uint8_t retrievalBuffer[CONFIG_RETRIEVAL_BUFFER_SIZE];
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE

namespace {
bool IsValidIntent(IntentEnum intent)
{
@@ -75,8 +80,16 @@ size_t LogProvider::GetSizeForIntent(IntentEnum intent)
{
switch (intent)
{
case IntentEnum::kEndUserSupport:
case IntentEnum::kEndUserSupport: {
#if CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
VerifyOrReturnError(mStorageInstance != nullptr, 0,
ChipLogError(DeviceLayer, "Diagnostic Storage instance cannot be null."));
return mStorageInstance->GetDataSize();
#else
return static_cast<size_t>(endUserSupportLogEnd - endUserSupportLogStart);
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
}
break;
case IntentEnum::kNetworkDiag:
return static_cast<size_t>(networkDiagnosticLogEnd - networkDiagnosticLogStart);
case IntentEnum::kCrashLogs:
@@ -108,8 +121,24 @@ CHIP_ERROR LogProvider::PrepareLogContextForIntent(LogContext * context, IntentE
switch (intent)
{
case IntentEnum::kEndUserSupport: {
#if CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
VerifyOrReturnError(mStorageInstance != nullptr, CHIP_ERROR_INTERNAL,
ChipLogError(DeviceLayer, "Diagnostic Storage instance cannot be null."));
MutableByteSpan endUserSupportSpan(retrievalBuffer, CONFIG_RETRIEVAL_BUFFER_SIZE);
VerifyOrReturnError(!mStorageInstance->IsBufferEmpty(), CHIP_ERROR_NOT_FOUND,
ChipLogError(DeviceLayer, "Empty Diagnostic buffer"));
// Retrieve data from the diagnostic storage
CHIP_ERROR err = mStorageInstance->Retrieve(endUserSupportSpan, sReadEntries);
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Failed to retrieve data: %s", chip::ErrorStr(err));
return err;
}
context->EndUserSupport.span = endUserSupportSpan;
#else
context->EndUserSupport.span =
ByteSpan(&endUserSupportLogStart[0], static_cast<size_t>(endUserSupportLogEnd - endUserSupportLogStart));
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
}
break;

@@ -278,11 +307,23 @@ CHIP_ERROR LogProvider::StartLogCollection(IntentEnum intent, LogSessionHandle &

CHIP_ERROR LogProvider::EndLogCollection(LogSessionHandle sessionHandle, CHIP_ERROR error)
{
if (error != CHIP_NO_ERROR)
#ifdef CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
VerifyOrReturnError(mStorageInstance != nullptr, CHIP_ERROR_INTERNAL,
ChipLogError(DeviceLayer, "Diagnostic Storage instance cannot be null."));
if (error == CHIP_NO_ERROR)
{
// Handle the error
ChipLogProgress(DeviceLayer, "End log collection reason: %s", ErrorStr(error));
CHIP_ERROR err = mStorageInstance->ClearReadMemory(sReadEntries);
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Failed to clear diagnostic read entries");
}
else
{
ChipLogProgress(DeviceLayer, "Cleared all read diagnostics successfully");
}
}
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE

VerifyOrReturnValue(sessionHandle != kInvalidLogSessionHandle, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnValue(mSessionContextMap.count(sessionHandle), CHIP_ERROR_INVALID_ARGUMENT);

Original file line number Diff line number Diff line change
@@ -19,12 +19,18 @@
#pragma once

#include <app/clusters/diagnostic-logs-server/DiagnosticLogsProviderDelegate.h>

#include <map>

#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
#include <esp_core_dump.h>
#endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)

#if CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
#include <tracing/esp32_diagnostic_trace/DiagnosticStorageManager.h>
using namespace chip::Tracing::Diagnostics;
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE

namespace chip {
namespace app {
namespace Clusters {
@@ -39,7 +45,16 @@ namespace DiagnosticLogs {
class LogProvider : public DiagnosticLogsProviderDelegate
{
public:
#ifdef CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
static inline LogProvider & GetInstance(CircularDiagnosticBuffer * bufferInstance)
{
VerifyOrReturnValue(bufferInstance != nullptr, sInstance);
sInstance.mStorageInstance = bufferInstance;
return sInstance;
}
#else
static inline LogProvider & GetInstance() { return sInstance; }
#endif

/////////// DiagnosticLogsProviderDelegate Interface /////////
CHIP_ERROR StartLogCollection(IntentEnum intent, LogSessionHandle & outHandle, Optional<uint64_t> & outTimeStamp,
@@ -58,6 +73,10 @@ class LogProvider : public DiagnosticLogsProviderDelegate
LogProvider(const LogProvider &) = delete;
LogProvider & operator=(const LogProvider &) = delete;

#ifdef CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
CircularDiagnosticBuffer * mStorageInstance = nullptr;
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE

struct CrashLogContext
{
#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF)
17 changes: 16 additions & 1 deletion examples/temperature-measurement-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
@@ -52,6 +52,13 @@
#include <DeviceInfoProviderImpl.h>
#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER

#if CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
#include <tracing/esp32_diagnostic_trace/DiagnosticTracing.h>
static uint8_t endUserBuffer[CONFIG_END_USER_BUFFER_SIZE]; // Global static buffer used to store diagnostics
using namespace chip::Tracing::Diagnostics;
CircularDiagnosticBuffer diagnosticStorage(endUserBuffer, CONFIG_END_USER_BUFFER_SIZE);
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE

namespace {
#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
chip::DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
@@ -75,14 +82,18 @@ static AppDeviceCallbacks EchoCallbacks;
static void InitServer(intptr_t context)
{
Esp32AppServer::Init(); // Init ZCL Data Model and CHIP App Server AND Initialize device attestation config
#if CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
diagnosticStorage.Init(endUserBuffer, CONFIG_END_USER_BUFFER_SIZE);
static ESP32Diagnostics diagnosticBackend(&diagnosticStorage);
Tracing::Register(diagnosticBackend);
#endif // CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
}

extern "C" void app_main()
{
#if CONFIG_ENABLE_PW_RPC
chip::rpc::Init();
#endif

ESP_LOGI(TAG, "Temperature sensor!");

// Initialize the ESP NVS layer.
@@ -133,6 +144,10 @@ extern "C" void app_main()
using namespace chip::app::Clusters::DiagnosticLogs;
void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint)
{
#ifdef CONFIG_ENABLE_ESP_DIAGNOSTICS_TRACE
auto & logProvider = LogProvider::GetInstance(&diagnosticStorage);
#else
auto & logProvider = LogProvider::GetInstance();
#endif
DiagnosticLogsServer::Instance().SetDiagnosticLogsProviderDelegate(endpoint, &logProvider);
}
3 changes: 3 additions & 0 deletions scripts/tools/check_includes_config.py
Original file line number Diff line number Diff line change
@@ -168,6 +168,9 @@
'src/tracing/json/json_tracing.cpp': {'string', 'sstream'},
'src/tracing/json/json_tracing.h': {'fstream', 'unordered_map', 'string'},

# esp32 diagnostic tracing
'src/tracing/esp32_diagnostic_trace/Counter.h': {'map'},

# esp32 tracing
'src/tracing/esp32_trace/esp32_tracing.h': {'unordered_map'},

46 changes: 46 additions & 0 deletions src/tracing/esp32_diagnostic_trace/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#
#Copyright (c) 2024 Project CHIP Authors
#
# 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.

import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")

config("tracing") {
include_dirs = [ "include" ]
}

static_library("backend") {
output_name = "libEsp32DiagnosticsBackend"
output_dir = "${root_out_dir}/lib"

sources = [
"Counter.cpp",
"Counter.h",
"DiagnosticStorageManager.h",
"DiagnosticTracing.cpp",
"DiagnosticTracing.h",
"Diagnostics.h",
]

public_deps = [
"${chip_root}/src/lib/core",
"${chip_root}/src/tracing",
]
}

source_set("esp32_diagnostic_tracing") {
public = [ "include/matter/tracing/macros_impl.h" ]
public_configs = [ ":tracing" ]
deps = [ ":backend" ]
}
56 changes: 56 additions & 0 deletions src/tracing/esp32_diagnostic_trace/Counter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
*
* Copyright (c) 2024 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 <esp_log.h>
#include <tracing/esp32_diagnostic_trace/Counter.h>

namespace chip {
namespace Tracing {
namespace Diagnostics {

std::map<const char *, uint32_t> ESPDiagnosticCounter::mCounterList;

void ESPDiagnosticCounter::IncreaseCount(const char * label)
{
if (mCounterList.find(label) != mCounterList.end())
{
mCounterList[label]++;
}
else
{
mCounterList[label] = 1;
}
}

uint32_t ESPDiagnosticCounter::GetInstanceCount(const char * label) const
{
return mCounterList[label];
}

CHIP_ERROR ESPDiagnosticCounter::ReportMetrics(const char * label, DiagnosticStorageInterface * mStorageInstance)
{
CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrReturnError(mStorageInstance != nullptr, err, ChipLogError(DeviceLayer, "Diagnostic Storage Instance cannot be NULL"));
Diagnostic<uint32_t> counter(label, GetInstanceCount(label), esp_log_timestamp());
err = mStorageInstance->Store(counter);
return err;
}

} // namespace Diagnostics
} // namespace Tracing
} // namespace chip
Loading
Loading