Adding a counter trace macro to the tracing for getting insights from counters in chip and implemented the macro for ESP32 platform... (#30591)

* Set up the tracing to support counter macro and added the macro to none and multiplexed

* Added the support of counter macro for esp32

* Added the support of counter macro in perfetto

* Added support of counters for json backend and few traces

* Restyled the code

* Added few counter traces

* Refactored some code

* Addressed Review Comments

* Removed the group from counter trace macro

* Refactored some code

* Addressed the string and class documentation related review comments
diff --git a/scripts/tools/check_includes_config.py b/scripts/tools/check_includes_config.py
index b4e933f..42920c4 100644
--- a/scripts/tools/check_includes_config.py
+++ b/scripts/tools/check_includes_config.py
@@ -158,7 +158,7 @@
 
     # Library meant for non-embedded
     'src/tracing/json/json_tracing.cpp': {'string', 'sstream'},
-    'src/tracing/json/json_tracing.h': {'fstream'},
+    'src/tracing/json/json_tracing.h': {'fstream', 'unordered_map'},
 
     # Not intended for embedded clients
     'src/lib/support/jsontlv/JsonToTlv.cpp': {'sstream'},
diff --git a/src/protocols/secure_channel/CASEServer.cpp b/src/protocols/secure_channel/CASEServer.cpp
index d701d8c..2ad196a 100644
--- a/src/protocols/secure_channel/CASEServer.cpp
+++ b/src/protocols/secure_channel/CASEServer.cpp
@@ -183,6 +183,7 @@
     MATTER_TRACE_SCOPE("OnSessionEstablishmentError", "CASEServer");
     ChipLogError(Inet, "CASE Session establishment failed: %" CHIP_ERROR_FORMAT, err.Format());
 
+    MATTER_TRACE_SCOPE("CASEFail", "CASESession");
     PrepareForSessionEstablishment();
 }
 
diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp
index 8573d15..1d6cb27 100644
--- a/src/protocols/secure_channel/CASESession.cpp
+++ b/src/protocols/secure_channel/CASESession.cpp
@@ -552,6 +552,7 @@
     VerifyOrReturn(mExchangeCtxt == ec, ChipLogError(SecureChannel, "CASESession::OnResponseTimeout exchange doesn't match"));
     ChipLogError(SecureChannel, "CASESession timed out while waiting for a response from the peer. Current state was %u",
                  to_underlying(mState));
+    MATTER_TRACE_COUNTER("CASETimeout");
     // Discard the exchange so that Clear() doesn't try aborting it.  The
     // exchange will handle that.
     DiscardExchange();
@@ -844,6 +845,7 @@
     ByteSpan initiatorRandom;
 
     ChipLogProgress(SecureChannel, "Received Sigma1 msg");
+    MATTER_TRACE_COUNTER("Sigma1");
 
     bool sessionResumptionRequested = false;
     ByteSpan resumptionId;
@@ -1100,6 +1102,7 @@
     mState = State::kSentSigma2;
 
     ChipLogProgress(SecureChannel, "Sent Sigma2 msg");
+    MATTER_TRACE_COUNTER("Sigma2");
 
     return CHIP_NO_ERROR;
 }
@@ -1116,6 +1119,7 @@
     uint32_t decodeTagIdSeq = 0;
 
     ChipLogDetail(SecureChannel, "Received Sigma2Resume msg");
+    MATTER_TRACE_COUNTER("Sigma2Resume");
 
     uint8_t sigma2ResumeMIC[CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES];
 
@@ -1585,6 +1589,7 @@
     uint8_t msg_salt[kIPKSize + kSHA256_Hash_Length];
 
     ChipLogProgress(SecureChannel, "Received Sigma3 msg");
+    MATTER_TRACE_COUNTER("Sigma3");
 
     auto helper = WorkHelper<HandleSigma3Data>::Create(*this, &HandleSigma3b, &CASESession::HandleSigma3c);
     VerifyOrExit(helper, err = CHIP_ERROR_NO_MEMORY);
diff --git a/src/protocols/secure_channel/PASESession.cpp b/src/protocols/secure_channel/PASESession.cpp
index 67da1d1..980a30d 100644
--- a/src/protocols/secure_channel/PASESession.cpp
+++ b/src/protocols/secure_channel/PASESession.cpp
@@ -251,6 +251,7 @@
     // If we were waiting for something, mNextExpectedMsg had better have a value.
     ChipLogError(SecureChannel, "PASESession timed out while waiting for a response from the peer. Expected message type was %u",
                  to_underlying(mNextExpectedMsg.Value()));
+    MATTER_TRACE_COUNTER("PASETimeout");
     // Discard the exchange so that Clear() doesn't try closing it.  The
     // exchange will handle that.
     DiscardExchange();
@@ -572,6 +573,7 @@
     size_t verifier_len = kMAX_Hash_Length;
 
     ChipLogDetail(SecureChannel, "Received spake2p msg1");
+    MATTER_TRACE_SCOPE("Pake1", "PASESession");
 
     System::PacketBufferTLVReader tlvReader;
     TLV::TLVType containerType = TLV::kTLVType_Structure;
@@ -620,6 +622,7 @@
     }
 
     ChipLogDetail(SecureChannel, "Sent spake2p msg2");
+    MATTER_TRACE_COUNTER("Pake2");
 
 exit:
 
@@ -711,6 +714,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
 
     ChipLogDetail(SecureChannel, "Received spake2p msg3");
+    MATTER_TRACE_COUNTER("Pake3");
 
     mNextExpectedMsg.ClearValue();
 
@@ -871,6 +875,7 @@
         DiscardExchange();
         Clear();
         ChipLogError(SecureChannel, "Failed during PASE session setup: %" CHIP_ERROR_FORMAT, err.Format());
+        MATTER_TRACE_COUNTER("PASEFail");
         // Do this last in case the delegate frees us.
         NotifySessionEstablishmentError(err);
     }
diff --git a/src/tracing/backend.h b/src/tracing/backend.h
index 7e04490..3d8bec8 100644
--- a/src/tracing/backend.h
+++ b/src/tracing/backend.h
@@ -63,6 +63,7 @@
     /// Trace a zero-sized event
     virtual void TraceInstant(const char * label, const char * group) {}
 
+    virtual void TraceCounter(const char * label) {}
     virtual void LogMessageSend(MessageSendInfo &) { TraceInstant("MessageSent", "Messaging"); }
     virtual void LogMessageReceived(MessageReceivedInfo &) { TraceInstant("MessageReceived", "Messaging"); }
 
diff --git a/src/tracing/esp32_trace/BUILD.gn b/src/tracing/esp32_trace/BUILD.gn
index 7548894..294cf1f 100644
--- a/src/tracing/esp32_trace/BUILD.gn
+++ b/src/tracing/esp32_trace/BUILD.gn
@@ -29,6 +29,8 @@
   output_dir = "${root_out_dir}/lib"
 
   sources = [
+    "counter.cpp",
+    "counter.h",
     "esp32_tracing.cpp",
     "esp32_tracing.h",
   ]
@@ -43,7 +45,10 @@
       "${chip_root}/src/system",
     ]
   }
-  public_deps = [ "${chip_root}/src/tracing" ]
+  public_deps = [
+    "${chip_root}/src/lib/core",
+    "${chip_root}/src/tracing",
+  ]
 }
 
 source_set("esp32_trace_tracing") {
diff --git a/src/tracing/esp32_trace/counter.cpp b/src/tracing/esp32_trace/counter.cpp
new file mode 100644
index 0000000..0b315a8
--- /dev/null
+++ b/src/tracing/esp32_trace/counter.cpp
@@ -0,0 +1,72 @@
+/*
+ *
+ *    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 <string.h>
+#include <tracing/esp32_trace/counter.h>
+
+using namespace chip;
+
+namespace Insights {
+
+// This is a one time allocation for counters. It is not supposed to be freed.
+ESPInsightsCounter * ESPInsightsCounter::mHead = nullptr;
+
+ESPInsightsCounter * ESPInsightsCounter::GetInstance(const char * label)
+{
+    ESPInsightsCounter * current = mHead;
+
+    while (current != nullptr)
+    {
+        if (strcmp(current->label, label) == 0)
+        {
+            current->instanceCount++;
+            return current;
+        }
+        current = current->mNext;
+    }
+
+    // Allocate a new instance if counter is not present in the list.
+    void * ptr = Platform::MemoryAlloc(sizeof(ESPInsightsCounter));
+    VerifyOrDie(ptr != nullptr);
+
+    ESPInsightsCounter * newInstance = new (ptr) ESPInsightsCounter(label);
+    newInstance->mNext               = mHead;
+    mHead                            = newInstance;
+
+    return newInstance;
+}
+
+int ESPInsightsCounter::GetInstanceCount() const
+{
+    return instanceCount;
+}
+
+void ESPInsightsCounter::ReportMetrics()
+{
+    if (!registered)
+    {
+        esp_diag_metrics_register("SYS_CNT" /* Tag of metrics */, label /* Unique key 8 */,
+                                  label /* label displayed on dashboard */, "insights.cnt" /* hierarchical path */,
+                                  ESP_DIAG_DATA_TYPE_UINT /* data_type */);
+        registered = true;
+    }
+    ESP_LOGI("mtr", "Label = %s Count = %d", label, instanceCount);
+    esp_diag_metrics_add_uint(label, instanceCount);
+}
+
+} // namespace Insights
diff --git a/src/tracing/esp32_trace/counter.h b/src/tracing/esp32_trace/counter.h
new file mode 100644
index 0000000..bfa6205
--- /dev/null
+++ b/src/tracing/esp32_trace/counter.h
@@ -0,0 +1,55 @@
+/*
+ *
+ *    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_diagnostics_metrics.h>
+#include <esp_log.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/CHIPMemString.h>
+#include <string.h>
+
+namespace Insights {
+
+/*
+ *
+ * This class is used to monotonically increment the counters as per the label of the counter macro
+ * 'MATTER_TRACE_COUNTER(label)' and report the metrics to esp-insights.
+ * As per the label of the counter macro, it adds the counter in the linked list with the name label if not
+ * present and returns the same instance and increments the value if the counter is already present
+ * in the list.
+ */
+
+class ESPInsightsCounter
+{
+private:
+    static ESPInsightsCounter * mHead; // head of the counter list
+    const char * label;                // unique key
+    int instanceCount;
+    ESPInsightsCounter * mNext; // pointer to point to the next entry in the list
+    bool registered = false;
+
+    ESPInsightsCounter(const char * labelParam) : label(labelParam), instanceCount(1), mNext(nullptr) {}
+
+public:
+    static ESPInsightsCounter * GetInstance(const char * label);
+
+    int GetInstanceCount() const;
+
+    void ReportMetrics();
+};
+
+} // namespace Insights
diff --git a/src/tracing/esp32_trace/esp32_tracing.cpp b/src/tracing/esp32_trace/esp32_tracing.cpp
index 7a13130..7937772 100644
--- a/src/tracing/esp32_trace/esp32_tracing.cpp
+++ b/src/tracing/esp32_trace/esp32_tracing.cpp
@@ -16,13 +16,14 @@
  *    limitations under the License.
  */
 
-#include "esp32_tracing.h"
 #include <algorithm>
 #include <esp_heap_caps.h>
 #include <esp_insights.h>
 #include <esp_log.h>
 #include <memory>
 #include <tracing/backend.h>
+#include <tracing/esp32_trace/counter.h>
+#include <tracing/esp32_trace/esp32_tracing.h>
 
 namespace chip {
 namespace Tracing {
@@ -148,6 +149,10 @@
 
 void ESP32Backend::LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo & info) {}
 
+void ESP32Backend::TraceCounter(const char * label)
+{
+    ::Insights::ESPInsightsCounter::GetInstance(label)->ReportMetrics();
+}
 void ESP32Backend::TraceBegin(const char * label, const char * group)
 {
     HashValue hashValue = MurmurHash(group);
diff --git a/src/tracing/esp32_trace/esp32_tracing.h b/src/tracing/esp32_trace/esp32_tracing.h
index 7fe783d..6d9a277 100644
--- a/src/tracing/esp32_trace/esp32_tracing.h
+++ b/src/tracing/esp32_trace/esp32_tracing.h
@@ -28,6 +28,8 @@
     /// Trace a zero-sized event
     void TraceInstant(const char * label, const char * group) override;
 
+    void TraceCounter(const char * label) override;
+
     void LogMessageSend(MessageSendInfo &) override;
     void LogMessageReceived(MessageReceivedInfo &) override;
 
diff --git a/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h b/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h
index 4d8a8a2..b95c207 100644
--- a/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h
+++ b/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h
@@ -28,6 +28,7 @@
 #define MATTER_TRACE_BEGIN(label, group) ::chip::Tracing::Internal::Begin(label, group)
 #define MATTER_TRACE_END(label, group) ::chip::Tracing::Internal::End(label, group)
 #define MATTER_TRACE_INSTANT(label, group) ::chip::Tracing::Internal::Instant(label, group)
+#define MATTER_TRACE_COUNTER(label) ::chip::Tracing::Internal::Counter(label)
 
 namespace chip {
 namespace Tracing {
diff --git a/src/tracing/json/json_tracing.cpp b/src/tracing/json/json_tracing.cpp
index 6c651b3..af66e12 100644
--- a/src/tracing/json/json_tracing.cpp
+++ b/src/tracing/json/json_tracing.cpp
@@ -23,9 +23,8 @@
 #include <lib/support/CHIPMem.h>
 #include <lib/support/StringBuilder.h>
 #include <lib/support/StringSplitter.h>
-#include <transport/TracingStructs.h>
-
 #include <log_json/log_json_build_config.h>
+#include <transport/TracingStructs.h>
 
 #include <json/json.h>
 
@@ -276,6 +275,26 @@
     OutputValue(value);
 }
 
+void JsonBackend::TraceCounter(const char * label)
+{
+    std::string counterId = std::string(label);
+    if (mCounters.find(counterId) == mCounters.end())
+    {
+        mCounters[counterId] = 1;
+    }
+    else
+    {
+        mCounters[counterId]++;
+    }
+    ::Json::Value value;
+    value["event"] = "TraceCounter";
+    value["label"] = label;
+    value["count"] = mCounters[counterId];
+
+    // Output the counter event
+    OutputValue(value);
+}
+
 void JsonBackend::LogMessageSend(MessageSendInfo & info)
 {
     ::Json::Value value;
diff --git a/src/tracing/json/json_tracing.h b/src/tracing/json/json_tracing.h
index 74451b7..302c4bd 100644
--- a/src/tracing/json/json_tracing.h
+++ b/src/tracing/json/json_tracing.h
@@ -19,6 +19,7 @@
 
 #include <fstream>
 #include <tracing/backend.h>
+#include <unordered_map>
 
 namespace Json {
 class Value;
@@ -50,6 +51,7 @@
     void TraceBegin(const char * label, const char * group) override;
     void TraceEnd(const char * label, const char * group) override;
     void TraceInstant(const char * label, const char * group) override;
+    void TraceCounter(const char * label) override;
     void LogMessageSend(MessageSendInfo &) override;
     void LogMessageReceived(MessageReceivedInfo &) override;
     void LogNodeLookup(NodeLookupInfo &) override;
@@ -61,6 +63,8 @@
     /// Does the actual write of the value
     void OutputValue(::Json::Value & value);
 
+    std::unordered_map<std::string, int> mCounters;
+
     // Output file if writing to a file. If closed, writing
     // to ChipLog*
     std::fstream mOutputFile;
diff --git a/src/tracing/macros.h b/src/tracing/macros.h
index 5f836e4..b456137 100644
--- a/src/tracing/macros.h
+++ b/src/tracing/macros.h
@@ -78,6 +78,7 @@
 #define MATTER_TRACE_END(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
 #define MATTER_TRACE_INSTANT(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
 #define MATTER_TRACE_SCOPE(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
+#define MATTER_TRACE_COUNTER(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
 
 #define MATTER_LOG_MESSAGE_SEND(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
 #define MATTER_LOG_MESSAGE_RECEIVED(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
diff --git a/src/tracing/multiplexed/include/matter/tracing/macros_impl.h b/src/tracing/multiplexed/include/matter/tracing/macros_impl.h
index e1f2adc..8b3e728 100644
--- a/src/tracing/multiplexed/include/matter/tracing/macros_impl.h
+++ b/src/tracing/multiplexed/include/matter/tracing/macros_impl.h
@@ -28,6 +28,7 @@
 #define MATTER_TRACE_BEGIN(label, group) ::chip::Tracing::Internal::Begin(label, group)
 #define MATTER_TRACE_END(label, group) ::chip::Tracing::Internal::End(label, group)
 #define MATTER_TRACE_INSTANT(label, group) ::chip::Tracing::Internal::Instant(label, group)
+#define MATTER_TRACE_COUNTER(label) ::chip::Tracing::Internal::Counter(label)
 
 namespace chip {
 namespace Tracing {
diff --git a/src/tracing/none/include/matter/tracing/macros_impl.h b/src/tracing/none/include/matter/tracing/macros_impl.h
index 3f7f052..3119dce 100644
--- a/src/tracing/none/include/matter/tracing/macros_impl.h
+++ b/src/tracing/none/include/matter/tracing/macros_impl.h
@@ -31,3 +31,4 @@
 #define MATTER_TRACE_END(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
 #define MATTER_TRACE_INSTANT(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
 #define MATTER_TRACE_SCOPE(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
+#define MATTER_TRACE_COUNTER(...) _MATTER_TRACE_DISABLE(__VA_ARGS__)
diff --git a/src/tracing/perfetto/include/matter/tracing/macros_impl.h b/src/tracing/perfetto/include/matter/tracing/macros_impl.h
index 266ac69..9b05d2f 100644
--- a/src/tracing/perfetto/include/matter/tracing/macros_impl.h
+++ b/src/tracing/perfetto/include/matter/tracing/macros_impl.h
@@ -30,3 +30,10 @@
 #define MATTER_TRACE_END(label, group) TRACE_EVENT_END("Matter")
 #define MATTER_TRACE_INSTANT(label, group) TRACE_EVENT_INSTANT("Matter", label, "class_name", group)
 #define MATTER_TRACE_SCOPE(label, group) TRACE_EVENT("Matter", label, "class_name", group)
+
+#define MATTER_TRACE_COUNTER(label)                                                                                                \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        static int count##_label = 0;                                                                                              \
+        TRACE_COUNTER("Matter", label, ++count##_label);                                                                           \
+    } while (0)
diff --git a/src/tracing/perfetto/perfetto_tracing.cpp b/src/tracing/perfetto/perfetto_tracing.cpp
index 6d89dbb..b68ec33 100644
--- a/src/tracing/perfetto/perfetto_tracing.cpp
+++ b/src/tracing/perfetto/perfetto_tracing.cpp
@@ -21,10 +21,9 @@
 #include <lib/address_resolve/TracingStructs.h>
 #include <lib/core/ErrorStr.h>
 #include <lib/support/StringBuilder.h>
-#include <transport/TracingStructs.h>
-
 #include <matter/tracing/macros_impl.h>
 #include <perfetto.h>
+#include <transport/TracingStructs.h>
 
 namespace chip {
 namespace Tracing {
diff --git a/src/tracing/registry.cpp b/src/tracing/registry.cpp
index 9f7507a..7c43442 100644
--- a/src/tracing/registry.cpp
+++ b/src/tracing/registry.cpp
@@ -76,6 +76,14 @@
     }
 }
 
+void Counter(const char * label)
+{
+    for (auto & backend : gTracingBackends)
+    {
+        backend.TraceCounter(label);
+    }
+}
+
 void LogMessageSend(::chip::Tracing::MessageSendInfo & info)
 {
     for (auto & backend : gTracingBackends)
diff --git a/src/tracing/registry.h b/src/tracing/registry.h
index 8533725..083ebcb 100644
--- a/src/tracing/registry.h
+++ b/src/tracing/registry.h
@@ -76,6 +76,7 @@
 void Begin(const char * label, const char * group);
 void End(const char * label, const char * group);
 void Instant(const char * label, const char * group);
+void Counter(const char * label);
 
 void LogMessageSend(::chip::Tracing::MessageSendInfo & info);
 void LogMessageReceived(::chip::Tracing::MessageReceivedInfo & info);