Added macro variants with metric support matching the ones in CodeUtils (#32553)

- Added Verify/Return/Log/Succ/Exit XYZ WithMetric macro variants for
  use in metrics
- Added unit tests for these macro variants
diff --git a/src/tracing/metric_macros.h b/src/tracing/metric_macros.h
index 4ff85f3..26dde8c 100644
--- a/src/tracing/metric_macros.h
+++ b/src/tracing/metric_macros.h
@@ -27,13 +27,258 @@
 #if MATTER_TRACING_ENABLED
 
 /**
- *  @def SuccessOrExitWithMetric(kMetriKey, error)
+ *  @def ReturnErrorOnFailureWithMetric(kMetricKey, expr)
+ *
+ *  @brief
+ *    This macros emits the specified metric with error code and returns the error code,
+ *    if the expression returns an error. For a CHIP_ERROR expression, this means any value
+ *    other than CHIP_NO_ERROR. For an integer expression, this means non-zero.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    ReturnErrorOnFailureWithMetric(kMetricKey, channel->SendMsg(msg));
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          does not evaluate to CHIP_NO_ERROR. Value of the metric is to the
+ *                          result of the expression.
+ *  @param[in]  expr        An expression to be tested.
+ */
+#define ReturnErrorOnFailureWithMetric(kMetricKey, expr)                                                                           \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        auto __err = (expr);                                                                                                       \
+        if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, __err);                                                                                  \
+            return __err;                                                                                                          \
+        }                                                                                                                          \
+    } while (false)
+
+/**
+ *  @def ReturnLogErrorOnFailureWithMetric(kMetricKey, expr)
+ *
+ *  @brief
+ *    Returns the error code if the expression returns something different
+ *    than CHIP_NO_ERROR. In addition, a metric is emitted with the specified metric key and
+ *    error code as the value of the metric.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    ReturnLogErrorOnFailureWithMetric(kMetricKey, channel->SendMsg(msg));
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          does not evaluate to CHIP_NO_ERROR. Value of the metric is to the
+ *                          result of the expression.
+ *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
+ */
+#define ReturnLogErrorOnFailureWithMetric(kMetricKey, expr)                                                                        \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        CHIP_ERROR __err = (expr);                                                                                                 \
+        if (__err != CHIP_NO_ERROR)                                                                                                \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, __err);                                                                                  \
+            ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(__err), __FILE__, __LINE__);                                        \
+            return __err;                                                                                                          \
+        }                                                                                                                          \
+    } while (false)
+
+/**
+ *  @def ReturnOnFailureWithMetric(kMetricKey, expr)
+ *
+ *  @brief
+ *    Returns if the expression returns an error. For a CHIP_ERROR expression, this means any value other
+ *    than CHIP_NO_ERROR. For an integer expression, this means non-zero. If the expression evaluates to
+ *    anything but CHIP_NO_ERROR, a metric with the specified key is emitted along with error as the value.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    ReturnOnFailureWithMetric(kMetricKey, channel->SendMsg(msg));
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          does not evaluate to CHIP_NO_ERROR. Value of the metric is to the
+ *                          result of the expression.
+ *  @param[in]  expr        An expression to be tested.
+ */
+#define ReturnOnFailureWithMetric(kMetricKey, expr)                                                                                \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        auto __err = (expr);                                                                                                       \
+        if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, __err);                                                                                  \
+            return;                                                                                                                \
+        }                                                                                                                          \
+    } while (false)
+
+/**
+ *  @def VerifyOrReturnWithMetric(kMetricKey, expr, ...)
+ *
+ *  @brief
+ *    Returns from the void function if expression evaluates to false. If the expression evaluates
+ *    to false, a metric with the specified key is emitted.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    VerifyOrReturnWithMetric(kMetricKey, param != nullptr, LogError("param is nullptr"));
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          to false. Value of the metric is set to false.
+ *  @param[in]  expr        A Boolean expression to be evaluated.
+ *  @param[in]  ...         Statements to execute before returning. Optional.
+ */
+#define VerifyOrReturnWithMetric(kMetricKey, expr, ...)                                                                            \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        if (!(expr))                                                                                                               \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, false);                                                                                  \
+            __VA_ARGS__;                                                                                                           \
+            return;                                                                                                                \
+        }                                                                                                                          \
+    } while (false)
+
+/**
+ *  @def VerifyOrReturnErrorWithMetric(kMetricKey, expr, code, ...)
+ *
+ *  @brief
+ *    Returns a specified error code if expression evaluates to false. If the expression evaluates
+ *    to false, a metric with the specified key is emitted with the value set to the code.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    VerifyOrReturnErrorWithMetric(kMetricKey, param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          to false. Value of the metric is to code.
+ *  @param[in]  expr        A Boolean expression to be evaluated.
+ *  @param[in]  code        A value to return if @a expr is false.
+ *  @param[in]  ...         Statements to execute before returning. Optional.
+ */
+#define VerifyOrReturnErrorWithMetric(kMetricKey, expr, code, ...)                                                                 \
+    VerifyOrReturnValueWithMetric(kMetricKey, expr, code, ##__VA_ARGS__)
+
+/**
+ *  @def VerifyOrReturnValueWithMetric(kMetricKey, expr, value, ...)
+ *
+ *  @brief
+ *    Returns a specified value if expression evaluates to false. If the expression evaluates
+ *    to false, a metric with the specified key is emitted with the value set to value.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    VerifyOrReturnValueWithMetric(kMetricKey, param != nullptr, Foo());
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          to false. Value of the metric is to value.
+ *  @param[in]  expr        A Boolean expression to be evaluated.
+ *  @param[in]  value       A value to return if @a expr is false.
+ *  @param[in]  ...         Statements to execute before returning. Optional.
+ */
+#define VerifyOrReturnValueWithMetric(kMetricKey, expr, value, ...)                                                                \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        if (!(expr))                                                                                                               \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, value);                                                                                  \
+            __VA_ARGS__;                                                                                                           \
+            return (value);                                                                                                        \
+        }                                                                                                                          \
+    } while (false)
+
+/**
+ *  @def VerifyOrReturnLogErrorWithMetric(kMetricKey, expr, code)
+ *
+ *  @brief
+ *    Returns and print a specified error code if expression evaluates to false.
+ *    If the expression evaluates to false, a metric with the specified key is emitted
+ *    with the value set to code.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    VerifyOrReturnLogErrorWithMetric(kMetricKey, param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          to false. Value of the metric is to code.
+ *  @param[in]  expr        A Boolean expression to be evaluated.
+ *  @param[in]  code        A value to return if @a expr is false.
+ */
+#if CHIP_CONFIG_ERROR_SOURCE
+#define VerifyOrReturnLogErrorWithMetric(kMetricKey, expr, code)                                                                   \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        if (!(expr))                                                                                                               \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, code);                                                                                   \
+            ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(code), __FILE__, __LINE__);                                         \
+            return code;                                                                                                           \
+        }                                                                                                                          \
+    } while (false)
+#else // CHIP_CONFIG_ERROR_SOURCE
+#define VerifyOrReturnLogErrorWithMetric(kMetricKey, expr, code)                                                                   \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        if (!(expr))                                                                                                               \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, code);                                                                                   \
+            ChipLogError(NotSpecified, "%s:%d false: %" CHIP_ERROR_FORMAT, #expr, __LINE__, code.Format());                        \
+            return code;                                                                                                           \
+        }                                                                                                                          \
+    } while (false)
+#endif // CHIP_CONFIG_ERROR_SOURCE
+
+/**
+ *  @def ReturnErrorCodeWithMetricIf(kMetricKey, expr, code)
+ *
+ *  @brief
+ *    Returns a specified error code if expression evaluates to true
+ *    If the expression evaluates to true, a metric with the specified key is emitted
+ *    with the value set to code.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    ReturnErrorCodeWithMetricIf(kMetricKey, state == kInitialized, CHIP_NO_ERROR);
+ *    ReturnErrorCodeWithMetricIf(kMetricKey, state == kInitialized, CHIP_ERROR_INCORRECT_STATE);
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          to true. Value of the metric is to code.
+ *  @param[in]  expr        A Boolean expression to be evaluated.
+ *  @param[in]  code        A value to return if @a expr is false.
+ */
+#define ReturnErrorCodeWithMetricIf(kMetricKey, expr, code)                                                                        \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        if (expr)                                                                                                                  \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, code);                                                                                   \
+            return code;                                                                                                           \
+        }                                                                                                                          \
+    } while (false)
+
+/**
+ *  @def SuccessOrExitWithMetric(kMetricKey, error)
  *
  *  @brief
  *    This checks for the specified error, which is expected to
  *    commonly be successful (CHIP_NO_ERROR), and branches to
  *    the local label 'exit' if the error is not success.
- *    If error is not a success, a metric with key kMetriKey is emitted with
+ *    If error is not a success, a metric with key kMetricKey is emitted with
  *    the error code as the value of the metric.
  *
  *  Example Usage:
@@ -100,9 +345,110 @@
 #define VerifyOrExitWithMetric(kMetricKey, aCondition, anAction)                                                                   \
     nlEXPECT_ACTION(aCondition, exit, MATTER_LOG_METRIC((kMetricKey), (anAction)))
 
-/*
- * Utility Macros to support optional arguments for MATTER_LOG_METRIC_XYZ macros
+/**
+ *  @def ExitNowWithMetric(kMetricKey, ...)
+ *
+ *  @brief
+ *    This unconditionally executes @a ... and branches to the local
+ *    label 'exit'. In addition a metric is emitted with the specified key.
+ *
+ *  @note The use of this interface implies neither success nor
+ *        failure for the overall exit status of the enclosing function
+ *        body.
+ *
+ *  Example Usage:
+ *
+ *  @code
+ *  CHIP_ERROR ReadAll(Reader& reader)
+ *  {
+ *      CHIP_ERROR err;
+ *
+ *      while (true)
+ *      {
+ *          err = reader.ReadNext();
+ *          if (err == CHIP_ERROR_AT_END)
+ *              ExitNowWithMetric(kMetricKey, err = CHIP_NO_ERROR);
+ *          SuccessOrExit(err);
+ *          DoSomething();
+ *      }
+ *
+ *  exit:
+ *      return err;
+ *  }
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted.
+ *  @param[in]  ...         Statements to execute. Optional.
  */
+#define ExitNowWithMetric(kMetricKey, ...)                                                                                         \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        MATTER_LOG_METRIC(kMetricKey);                                                                                             \
+        __VA_ARGS__;                                                                                                               \
+        goto exit;                                                                                                                 \
+    } while (0)
+
+/**
+ *  @def LogErrorOnFailureWithMetric(kMetricKey, expr)
+ *
+ *  @brief
+ *    Logs a message if the expression returns something different than CHIP_NO_ERROR.
+ *    In addition, a metric is emitted with the specified key and value set to result
+ *    of the expression in case it evaluates to anything other than CHIP_NO_ERROR.
+ *
+ *  Example usage:
+ *
+ *  @code
+ *    LogErrorOnFailureWithMetric(kMetricKey, channel->SendMsg(msg));
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted if the expr evaluates
+ *                          does not evaluate to CHIP_NO_ERROR. Value of the metric is to the
+ *                          result of the expression.
+ *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
+ */
+#define LogErrorOnFailureWithMetric(kMetricKey, expr)                                                                              \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        CHIP_ERROR __err = (expr);                                                                                                 \
+        if (__err != CHIP_NO_ERROR)                                                                                                \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, __err);                                                                                  \
+            ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(__err), __FILE__, __LINE__);                                        \
+        }                                                                                                                          \
+    } while (false)
+
+/**
+ *  @def VerifyOrDoWithMetric(kMetricKey, expr, ...)
+ *
+ *  @brief
+ *    Do something if expression evaluates to false. If the expression evaluates to false a metric
+ *    with the specified key is emitted with value set to false.
+ *
+ *  Example usage:
+ *
+ * @code
+ *    VerifyOrDoWithMetric(param != nullptr, LogError("param is nullptr"));
+ *  @endcode
+ *
+ *  @param[in]  kMetricKey  Metric key for the metric event to be emitted.
+ *                          Value of the metric is set to false.
+ *  @param[in]  expr        A Boolean expression to be evaluated.
+ *  @param[in]  ...         Statements to execute.
+ */
+#define VerifyOrDoWithMetric(kMetricKey, expr, ...)                                                                                \
+    do                                                                                                                             \
+    {                                                                                                                              \
+        if (!(expr))                                                                                                               \
+        {                                                                                                                          \
+            MATTER_LOG_METRIC(kMetricKey, false);                                                                                  \
+            __VA_ARGS__;                                                                                                           \
+        }                                                                                                                          \
+    } while (false)
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Utility Macros to support optional arguments for MATTER_LOG_METRIC_XYZ macros
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 // Utility to always return the 4th argument from macro parameters
 #define __GET_4TH_ARG(_a1, _a2, _a3, _a4, ...) _a4
@@ -222,10 +568,32 @@
 // Remap Success, Return, and Verify macros to the ones without metrics
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+#define ReturnErrorOnFailureWithMetric(kMetricKey, expr) ReturnErrorOnFailure(expr)
+
+#define ReturnLogErrorOnFailureWithMetric(kMetricKey, expr) ReturnLogErrorOnFailure(expr)
+
+#define ReturnOnFailureWithMetric(kMetricKey, expr) ReturnOnFailure(expr)
+
+#define VerifyOrReturnWithMetric(kMetricKey, expr, ...) VerifyOrReturn(expr, ##__VA_ARGS__)
+
+#define VerifyOrReturnErrorWithMetric(kMetricKey, expr, code, ...) VerifyOrReturnValue(expr, code, ##__VA_ARGS__)
+
+#define VerifyOrReturnValueWithMetric(kMetricKey, expr, value, ...) VerifyOrReturnValue(expr, value, ##__VA_ARGS__)
+
+#define VerifyOrReturnLogErrorWithMetric(kMetricKey, expr, code) VerifyOrReturnLogError(expr, code)
+
+#define ReturnErrorCodeWithMetricIf(kMetricKey, expr, code) ReturnErrorCodeIf(expr, code)
+
 #define SuccessOrExitWithMetric(kMetricKey, aStatus) SuccessOrExit(aStatus)
 
 #define VerifyOrExitWithMetric(kMetricKey, aCondition, anAction) VerifyOrExit(aCondition, anAction)
 
+#define ExitNowWithMetric(kMetricKey, ...) ExitNow(##__VA_ARGS__)
+
+#define LogErrorOnFailureWithMetric(kMetricKey, expr) LogErrorOnFailure(expr)
+
+#define VerifyOrDoWithMetric(kMetricKey, expr, ...) VerifyOrDo(expr, ##__VA_ARGS__)
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // Map all MATTER_LOG_METRIC_XYZ macros to noops
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tracing/tests/TestMetricEvents.cpp b/src/tracing/tests/TestMetricEvents.cpp
index c52a5fc..72e159d 100644
--- a/src/tracing/tests/TestMetricEvents.cpp
+++ b/src/tracing/tests/TestMetricEvents.cpp
@@ -324,14 +324,335 @@
         inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
 }
 
+static CHIP_ERROR InvokeReturnErrorOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error)
+{
+    ReturnErrorOnFailureWithMetric(key, error);
+    return CHIP_NO_ERROR;
+}
+
+void TestReturnErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    CHIP_ERROR err = InvokeReturnErrorOnFailureWithMetric("event0", CHIP_NO_ERROR);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    err = InvokeReturnErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
+
+    err = InvokeReturnErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+static CHIP_ERROR InvokeReturnLogErrorOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error)
+{
+    ReturnLogErrorOnFailureWithMetric(key, error);
+    return CHIP_NO_ERROR;
+}
+
+void TestReturnLogErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    CHIP_ERROR err = InvokeReturnLogErrorOnFailureWithMetric("event0", CHIP_NO_ERROR);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    err = InvokeReturnLogErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
+
+    err = InvokeReturnLogErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+static void InvokeReturnOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error)
+{
+    ReturnOnFailureWithMetric(key, error);
+    return;
+}
+
+void TestReturnOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    InvokeReturnOnFailureWithMetric("event0", CHIP_NO_ERROR);
+
+    InvokeReturnOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
+
+    InvokeReturnOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+static void InvokeVerifyOrReturnWithMetric(MetricKey key, bool result)
+{
+    VerifyOrReturnWithMetric(key, result);
+    return;
+}
+
+void TestInvokeVerifyOrReturnWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    InvokeVerifyOrReturnWithMetric("event0", DoubleOf(2) == 4);
+    InvokeVerifyOrReturnWithMetric("event1", DoubleOf(3) == 9);
+    InvokeVerifyOrReturnWithMetric("event2", DoubleOf(4) == 8);
+    InvokeVerifyOrReturnWithMetric("event3", DoubleOf(5) == 11);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", false),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", false),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+static CHIP_ERROR InvokeVerifyOrReturnErrorWithMetric(MetricKey key, bool expr, const CHIP_ERROR & error)
+{
+    VerifyOrReturnErrorWithMetric(key, expr, error);
+    return CHIP_NO_ERROR;
+}
+
+void TestVerifyOrReturnErrorWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    CHIP_ERROR err = InvokeVerifyOrReturnErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_ERROR_BAD_REQUEST);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    err = InvokeVerifyOrReturnErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ACCESS_DENIED);
+
+    err = InvokeVerifyOrReturnErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BUSY);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    err = InvokeVerifyOrReturnErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_CANCELLED);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CANCELLED);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_ACCESS_DENIED),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_CANCELLED),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+template <typename return_code_type>
+static return_code_type InvokeVerifyOrReturnValueWithMetric(MetricKey key, bool expr, return_code_type retval)
+{
+    VerifyOrReturnValueWithMetric(key, expr, retval);
+    return return_code_type();
+}
+
+void TestVerifyOrReturnValueWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    auto retval = InvokeVerifyOrReturnValueWithMetric("event0", DoubleOf(2) == 4, 0);
+    NL_TEST_ASSERT(inSuite, retval == 0);
+
+    auto err = InvokeVerifyOrReturnValueWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ACCESS_DENIED);
+
+    err = InvokeVerifyOrReturnValueWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BAD_REQUEST);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    retval = InvokeVerifyOrReturnValueWithMetric("event3", DoubleOf(5) == 11, 16);
+    NL_TEST_ASSERT(inSuite, retval == 16);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_ACCESS_DENIED),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", 16),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+static CHIP_ERROR InvokeVerifyOrReturnLogErrorWithMetric(MetricKey key, bool expr, const CHIP_ERROR & error)
+{
+    VerifyOrReturnLogErrorWithMetric(key, expr, error);
+    return CHIP_NO_ERROR;
+}
+
+void TestVerifyOrReturnLogErrorWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    auto err = InvokeVerifyOrReturnLogErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_NO_ERROR);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    err = InvokeVerifyOrReturnLogErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_CANCELLED);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CANCELLED);
+
+    err = InvokeVerifyOrReturnLogErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_NO_ERROR);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    err = InvokeVerifyOrReturnLogErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_BAD_REQUEST);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_CANCELLED),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_BAD_REQUEST),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+template <typename return_code_type>
+static return_code_type InvokeReturnErrorCodeWithMetricIf(MetricKey key, bool expr, const return_code_type & code)
+{
+    ReturnErrorCodeWithMetricIf(key, expr, code);
+    return return_code_type();
+}
+
+void TestReturnErrorCodeWithMetricIf(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    auto err = InvokeReturnErrorCodeWithMetricIf("event0", DoubleOf(2) == 4, CHIP_ERROR_DUPLICATE_KEY_ID);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_DUPLICATE_KEY_ID);
+
+    auto retval = InvokeReturnErrorCodeWithMetricIf("event1", DoubleOf(3) == 9, 11);
+    NL_TEST_ASSERT(inSuite, retval == 0);
+
+    retval = InvokeReturnErrorCodeWithMetricIf("event2", DoubleOf(4) == 8, 22);
+    NL_TEST_ASSERT(inSuite, retval == 22);
+
+    err = InvokeReturnErrorCodeWithMetricIf("event3", DoubleOf(5) == 11, CHIP_ERROR_ACCESS_DENIED);
+    NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event0", CHIP_ERROR_DUPLICATE_KEY_ID),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", 22),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+void TestExitNowWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+    chip::ChipError err = CHIP_NO_ERROR;
+
+    ExitNowWithMetric("event0", err = CHIP_ERROR_BUSY);
+
+exit:
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event0"),
+    };
+
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUSY);
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+void TestLogErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    LogErrorOnFailureWithMetric("event0", CHIP_ERROR_BAD_REQUEST);
+    LogErrorOnFailureWithMetric("event1", CHIP_NO_ERROR);
+    LogErrorOnFailureWithMetric("event2", CHIP_ERROR_DATA_NOT_ALIGNED);
+    LogErrorOnFailureWithMetric("event3", CHIP_ERROR_BUSY);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event0", CHIP_ERROR_BAD_REQUEST),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_DATA_NOT_ALIGNED),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_BUSY),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
+void TestVerifyOrDoWithMetric(nlTestSuite * inSuite, void * inContext)
+{
+    MetricEventBackend backend;
+    ScopedRegistration scope(backend);
+
+    VerifyOrDoWithMetric("event0", DoubleOf(2) == 5);
+    VerifyOrDoWithMetric("event1", DoubleOf(3) == 6);
+    VerifyOrDoWithMetric("event2", DoubleOf(4) == 7, MATTER_LOG_METRIC("event4", 10));
+    VerifyOrDoWithMetric("event3", DoubleOf(5) == 8);
+    VerifyOrDoWithMetric("event5", DoubleOf(6) == 12);
+
+    std::vector<MetricEvent> expected = {
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event0", false),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", false),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event4", 10),
+        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", false),
+    };
+
+    NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
+    NL_TEST_ASSERT(
+        inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
+}
+
 static const nlTest sMetricTests[] = {
-    NL_TEST_DEF("BasicMetricEvent", TestBasicMetricEvent),               //
-    NL_TEST_DEF("InstantMetricEvent", TestInstantMetricEvent),           //
-    NL_TEST_DEF("BeginEndMetricEvent", TestBeginEndMetricEvent),         //
-    NL_TEST_DEF("ScopedMetricEvent", TestScopedMetricEvent),             //
-    NL_TEST_DEF("VerifyOrExitWithMetric", TestVerifyOrExitWithMetric),   //
-    NL_TEST_DEF("SuccessOrExitWithMetric", TestSuccessOrExitWithMetric), //
-    NL_TEST_SENTINEL()                                                   //
+    NL_TEST_DEF("BasicMetricEvent", TestBasicMetricEvent),                                   //
+    NL_TEST_DEF("InstantMetricEvent", TestInstantMetricEvent),                               //
+    NL_TEST_DEF("BeginEndMetricEvent", TestBeginEndMetricEvent),                             //
+    NL_TEST_DEF("ScopedMetricEvent", TestScopedMetricEvent),                                 //
+    NL_TEST_DEF("VerifyOrExitWithMetric", TestVerifyOrExitWithMetric),                       //
+    NL_TEST_DEF("SuccessOrExitWithMetric", TestSuccessOrExitWithMetric),                     //
+    NL_TEST_DEF("ReturnErrorOnFailureWithMetric", TestReturnErrorOnFailureWithMetric),       //
+    NL_TEST_DEF("ReturnLogErrorOnFailureWithMetric", TestReturnLogErrorOnFailureWithMetric), //
+    NL_TEST_DEF("ReturnOnFailureWithMetric", TestReturnOnFailureWithMetric),                 //
+    NL_TEST_DEF("VerifyOrReturnWithMetric", TestInvokeVerifyOrReturnWithMetric),             //
+    NL_TEST_DEF("VerifyOrReturnErrorWithMetric", TestVerifyOrReturnErrorWithMetric),         //
+    NL_TEST_DEF("VerifyOrReturnValueWithMetric", TestVerifyOrReturnValueWithMetric),         //
+    NL_TEST_DEF("VerifyOrReturnLogErrorWithMetric", TestVerifyOrReturnLogErrorWithMetric),   //
+    NL_TEST_DEF("ReturnErrorCodeWithMetricIf", TestReturnErrorCodeWithMetricIf),             //
+    NL_TEST_DEF("ExitNowWithMetric", TestExitNowWithMetric),                                 //
+    NL_TEST_DEF("LogErrorOnFailureWithMetric", TestLogErrorOnFailureWithMetric),             //
+    NL_TEST_DEF("VerifyOrDoWithMetric", TestVerifyOrDoWithMetric),                           //
+    NL_TEST_SENTINEL()                                                                       //
 };
 
 } // namespace