Bug: [REFACTOR] add basic counter metrics for IMC



Introduce metrics for IMC - 
* hits (successful read), 
* misses (failed read), 
* manual invalidations (done by applications)

Also add eviction listener on moka that can help identify strategy based evictions.
diff --git a/crates/analytics/src/api_event/core.rs b/crates/analytics/src/api_event/core.rs
index 7225a6322d4..c7d6d9ac339 100644
--- a/crates/analytics/src/api_event/core.rs
+++ b/crates/analytics/src/api_event/core.rs
@@ -12,6 +12,7 @@ use common_utils::errors::ReportSwitchExt;
 use error_stack::ResultExt;
 use router_env::{
     instrument, logger,
+    metrics::add_attributes,
     tracing::{self, Instrument},
 };
 
@@ -135,10 +136,10 @@ pub async fn get_api_event_metrics(
         .change_context(AnalyticsError::UnknownError)?
     {
         let data = data?;
-        let attributes = &[
-            metrics::request::add_attributes("metric_type", metric.to_string()),
-            metrics::request::add_attributes("source", pool.to_string()),
-        ];
+        let attributes = &add_attributes([
+            ("metric_type", metric.to_string()),
+            ("source", pool.to_string()),
+        ]);
 
         let value = u64::try_from(data.len());
         if let Ok(val) = value {
diff --git a/crates/analytics/src/disputes/core.rs b/crates/analytics/src/disputes/core.rs
index dfba5fea112..d2279180255 100644
--- a/crates/analytics/src/disputes/core.rs
+++ b/crates/analytics/src/disputes/core.rs
@@ -11,6 +11,7 @@ use api_models::analytics::{
 use error_stack::ResultExt;
 use router_env::{
     logger,
+    metrics::add_attributes,
     tracing::{self, Instrument},
 };
 
@@ -70,10 +71,10 @@ pub async fn get_metrics(
         .change_context(AnalyticsError::UnknownError)?
     {
         let data = data?;
-        let attributes = &[
-            metrics::request::add_attributes("metric_type", metric.to_string()),
-            metrics::request::add_attributes("source", pool.to_string()),
-        ];
+        let attributes = &add_attributes([
+            ("metric_type", metric.to_string()),
+            ("source", pool.to_string()),
+        ]);
 
         let value = u64::try_from(data.len());
         if let Ok(val) = value {
diff --git a/crates/analytics/src/metrics/request.rs b/crates/analytics/src/metrics/request.rs
index 3d1a78808f3..39375d391a3 100644
--- a/crates/analytics/src/metrics/request.rs
+++ b/crates/analytics/src/metrics/request.rs
@@ -1,9 +1,6 @@
-pub fn add_attributes<T: Into<router_env::opentelemetry::Value>>(
-    key: &'static str,
-    value: T,
-) -> router_env::opentelemetry::KeyValue {
-    router_env::opentelemetry::KeyValue::new(key, value)
-}
+use std::time;
+
+use router_env::metrics::add_attributes;
 
 #[inline]
 pub async fn record_operation_time<F, R, T>(
@@ -17,10 +14,10 @@ where
     T: ToString,
 {
     let (result, time) = time_future(future).await;
-    let attributes = &[
-        add_attributes("metric_name", metric_name.to_string()),
-        add_attributes("source", source.to_string()),
-    ];
+    let attributes = &add_attributes([
+        ("metric_name", metric_name.to_string()),
+        ("source", source.to_string()),
+    ]);
     let value = time.as_secs_f64();
     metric.record(&super::CONTEXT, value, attributes);
 
@@ -28,8 +25,6 @@ where
     result
 }
 
-use std::time;
-
 #[inline]
 pub async fn time_future<F, R>(future: F) -> (R, time::Duration)
 where
diff --git a/crates/analytics/src/payments/core.rs b/crates/analytics/src/payments/core.rs
index a3f24b65a17..2508866626a 100644
--- a/crates/analytics/src/payments/core.rs
+++ b/crates/analytics/src/payments/core.rs
@@ -13,6 +13,7 @@ use common_utils::errors::CustomResult;
 use error_stack::ResultExt;
 use router_env::{
     instrument, logger,
+    metrics::add_attributes,
     tracing::{self, Instrument},
 };
 
@@ -120,10 +121,10 @@ pub async fn get_metrics(
         match task_type {
             TaskType::MetricTask(metric, data) => {
                 let data = data?;
-                let attributes = &[
-                    metrics::request::add_attributes("metric_type", metric.to_string()),
-                    metrics::request::add_attributes("source", pool.to_string()),
-                ];
+                let attributes = &add_attributes([
+                    ("metric_type", metric.to_string()),
+                    ("source", pool.to_string()),
+                ]);
 
                 let value = u64::try_from(data.len());
                 if let Ok(val) = value {
@@ -172,10 +173,10 @@ pub async fn get_metrics(
             }
             TaskType::DistributionTask(distribution, data) => {
                 let data = data?;
-                let attributes = &[
-                    metrics::request::add_attributes("distribution_type", distribution.to_string()),
-                    metrics::request::add_attributes("source", pool.to_string()),
-                ];
+                let attributes = &add_attributes([
+                    ("distribution_type", distribution.to_string()),
+                    ("source", pool.to_string()),
+                ]);
 
                 let value = u64::try_from(data.len());
                 if let Ok(val) = value {
diff --git a/crates/analytics/src/refunds/core.rs b/crates/analytics/src/refunds/core.rs
index b53d482e620..57480c7cec7 100644
--- a/crates/analytics/src/refunds/core.rs
+++ b/crates/analytics/src/refunds/core.rs
@@ -11,6 +11,7 @@ use api_models::analytics::{
 use error_stack::ResultExt;
 use router_env::{
     logger,
+    metrics::add_attributes,
     tracing::{self, Instrument},
 };
 
@@ -69,10 +70,10 @@ pub async fn get_metrics(
         .change_context(AnalyticsError::UnknownError)?
     {
         let data = data?;
-        let attributes = &[
-            metrics::request::add_attributes("metric_type", metric.to_string()),
-            metrics::request::add_attributes("source", pool.to_string()),
-        ];
+        let attributes = &add_attributes([
+            ("metric_type", metric.to_string()),
+            ("source", pool.to_string()),
+        ]);
 
         let value = u64::try_from(data.len());
         if let Ok(val) = value {
diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs
index 63cbc6dabf8..ac397cfa075 100644
--- a/crates/hyperswitch_interfaces/src/api.rs
+++ b/crates/hyperswitch_interfaces/src/api.rs
@@ -6,6 +6,7 @@ use common_utils::{
 };
 use hyperswitch_domain_models::router_data::{ErrorResponse, RouterData};
 use masking::Maskable;
+use router_env::metrics::add_attributes;
 use serde_json::json;
 
 use crate::{
@@ -87,7 +88,7 @@ pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Re
         metrics::UNIMPLEMENTED_FLOW.add(
             &metrics::CONTEXT,
             1,
-            &[metrics::add_attributes("connector", req.connector.clone())],
+            &add_attributes([("connector", req.connector.clone())]),
         );
         Ok(None)
     }
diff --git a/crates/hyperswitch_interfaces/src/metrics.rs b/crates/hyperswitch_interfaces/src/metrics.rs
index a03215a175d..fc374eba8e2 100644
--- a/crates/hyperswitch_interfaces/src/metrics.rs
+++ b/crates/hyperswitch_interfaces/src/metrics.rs
@@ -1,16 +1,8 @@
 //! Metrics interface
 
-use router_env::{counter_metric, global_meter, metrics_context, opentelemetry};
+use router_env::{counter_metric, global_meter, metrics_context};
 
 metrics_context!(CONTEXT);
 global_meter!(GLOBAL_METER, "ROUTER_API");
 
 counter_metric!(UNIMPLEMENTED_FLOW, GLOBAL_METER);
-
-/// fn add attributes
-pub fn add_attributes<T: Into<opentelemetry::Value>>(
-    key: &'static str,
-    value: T,
-) -> opentelemetry::KeyValue {
-    opentelemetry::KeyValue::new(key, value)
-}
diff --git a/crates/router/src/connector/boku.rs b/crates/router/src/connector/boku.rs
index 7c456d2ec1c..d565cc6567e 100644
--- a/crates/router/src/connector/boku.rs
+++ b/crates/router/src/connector/boku.rs
@@ -6,6 +6,7 @@ use diesel_models::enums;
 use error_stack::{report, Report, ResultExt};
 use masking::{ExposeInterface, PeekInterface, Secret, WithType};
 use ring::hmac;
+use router_env::metrics::add_attributes;
 use roxmltree;
 use time::OffsetDateTime;
 use transformers as boku;
@@ -665,7 +666,7 @@ fn get_xml_deserialized(
     metrics::RESPONSE_DESERIALIZATION_FAILURE.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes("connector", "boku")],
+        &add_attributes([("connector", "boku")]),
     );
 
     let response_data = String::from_utf8(res.response.to_vec())
diff --git a/crates/router/src/connector/braintree.rs b/crates/router/src/connector/braintree.rs
index f7e142a9af9..750e2e6e3cc 100644
--- a/crates/router/src/connector/braintree.rs
+++ b/crates/router/src/connector/braintree.rs
@@ -155,7 +155,7 @@ impl ConnectorCommon for Braintree {
             Err(error_msg) => {
                 event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
                 logger::error!(deserialization_error =? error_msg);
-                utils::handle_json_response_deserialization_failure(res, "braintree".to_owned())
+                utils::handle_json_response_deserialization_failure(res, "braintree")
             }
         }
     }
diff --git a/crates/router/src/connector/cybersource.rs b/crates/router/src/connector/cybersource.rs
index 1f8de468846..7bd3fa08dda 100644
--- a/crates/router/src/connector/cybersource.rs
+++ b/crates/router/src/connector/cybersource.rs
@@ -229,10 +229,7 @@ impl ConnectorCommon for Cybersource {
             Err(error_msg) => {
                 event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
                 router_env::logger::error!(deserialization_error =? error_msg);
-                crate::utils::handle_json_response_deserialization_failure(
-                    res,
-                    "cybersource".to_owned(),
-                )
+                crate::utils::handle_json_response_deserialization_failure(res, "cybersource")
             }
         }
     }
diff --git a/crates/router/src/connector/noon.rs b/crates/router/src/connector/noon.rs
index 23e15b2cfdc..909f7a435c1 100644
--- a/crates/router/src/connector/noon.rs
+++ b/crates/router/src/connector/noon.rs
@@ -155,7 +155,7 @@ impl ConnectorCommon for Noon {
             Err(error_message) => {
                 event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
                 logger::error!(deserialization_error =? error_message);
-                utils::handle_json_response_deserialization_failure(res, "noon".to_owned())
+                utils::handle_json_response_deserialization_failure(res, "noon")
             }
         }
     }
diff --git a/crates/router/src/connector/payme.rs b/crates/router/src/connector/payme.rs
index 397715d102d..88b2ec67595 100644
--- a/crates/router/src/connector/payme.rs
+++ b/crates/router/src/connector/payme.rs
@@ -111,7 +111,7 @@ impl ConnectorCommon for Payme {
             Err(error_msg) => {
                 event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
                 router_env::logger::error!(deserialization_error =? error_msg);
-                handle_json_response_deserialization_failure(res, "payme".to_owned())
+                handle_json_response_deserialization_failure(res, "payme")
             }
         }
     }
diff --git a/crates/router/src/connector/rapyd.rs b/crates/router/src/connector/rapyd.rs
index 5d4579fffa7..f4bd0997627 100644
--- a/crates/router/src/connector/rapyd.rs
+++ b/crates/router/src/connector/rapyd.rs
@@ -114,7 +114,7 @@ impl ConnectorCommon for Rapyd {
             Err(error_msg) => {
                 event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
                 logger::error!(deserialization_error =? error_msg);
-                utils::handle_json_response_deserialization_failure(res, "rapyd".to_owned())
+                utils::handle_json_response_deserialization_failure(res, "rapyd")
             }
         }
     }
diff --git a/crates/router/src/connector/threedsecureio.rs b/crates/router/src/connector/threedsecureio.rs
index 75a746648f1..a051cf471f1 100644
--- a/crates/router/src/connector/threedsecureio.rs
+++ b/crates/router/src/connector/threedsecureio.rs
@@ -126,10 +126,7 @@ impl ConnectorCommon for Threedsecureio {
             }
             Err(err) => {
                 router_env::logger::error!(deserialization_error =? err);
-                utils::handle_json_response_deserialization_failure(
-                    res,
-                    "threedsecureio".to_owned(),
-                )
+                utils::handle_json_response_deserialization_failure(res, "threedsecureio")
             }
         }
     }
diff --git a/crates/router/src/connector/trustpay.rs b/crates/router/src/connector/trustpay.rs
index 1f9e77de9cd..e2904221e59 100644
--- a/crates/router/src/connector/trustpay.rs
+++ b/crates/router/src/connector/trustpay.rs
@@ -153,7 +153,7 @@ impl ConnectorCommon for Trustpay {
             Err(error_msg) => {
                 event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
                 logger::error!(deserialization_error =? error_msg);
-                utils::handle_json_response_deserialization_failure(res, "trustpay".to_owned())
+                utils::handle_json_response_deserialization_failure(res, "trustpay")
             }
         }
     }
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 71e91373454..b9ac5a02b7e 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -15,6 +15,7 @@ use error_stack::{report, FutureExt, ResultExt};
 use futures::future::try_join_all;
 use masking::{PeekInterface, Secret};
 use pm_auth::connector::plaid::transformers::PlaidAuthType;
+use router_env::metrics::add_attributes;
 use uuid::Uuid;
 
 use crate::{
@@ -1009,10 +1010,10 @@ pub async fn create_payment_connector(
     metrics::MCA_CREATE.add(
         &metrics::CONTEXT,
         1,
-        &[
-            metrics::request::add_attributes("connector", req.connector_name.to_string()),
-            metrics::request::add_attributes("merchant", merchant_id.to_string()),
-        ],
+        &add_attributes([
+            ("connector", req.connector_name.to_string()),
+            ("merchant", merchant_id.to_string()),
+        ]),
     );
 
     let mca_response = mca.try_into()?;
diff --git a/crates/router/src/core/api_keys.rs b/crates/router/src/core/api_keys.rs
index ef81e3c190d..5d41b9c1854 100644
--- a/crates/router/src/core/api_keys.rs
+++ b/crates/router/src/core/api_keys.rs
@@ -3,7 +3,7 @@ use common_utils::date_time;
 use diesel_models::{api_keys::ApiKey, enums as storage_enums};
 use error_stack::{report, ResultExt};
 use masking::{PeekInterface, StrongSecret};
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 
 use crate::{
     configs::settings,
@@ -151,7 +151,7 @@ pub async fn create_api_key(
     metrics::API_KEY_CREATED.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes("merchant", merchant_id)],
+        &add_attributes([("merchant", merchant_id)]),
     );
 
     // Add process to process_tracker for email reminder, only if expiry is set to future date
@@ -236,7 +236,7 @@ pub async fn add_api_key_expiry_task(
     metrics::TASKS_ADDED_COUNT.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes("flow", "ApiKeyExpiry")],
+        &add_attributes([("flow", "ApiKeyExpiry")]),
     );
 
     Ok(())
diff --git a/crates/router/src/core/mandate.rs b/crates/router/src/core/mandate.rs
index f484467f354..9fa4b478217 100644
--- a/crates/router/src/core/mandate.rs
+++ b/crates/router/src/core/mandate.rs
@@ -5,7 +5,7 @@ use common_utils::{ext_traits::Encode, id_type};
 use diesel_models::{enums as storage_enums, Mandate};
 use error_stack::{report, ResultExt};
 use futures::future;
-use router_env::{instrument, logger, tracing};
+use router_env::{instrument, logger, metrics::add_attributes, tracing};
 
 use super::payments::helpers as payment_helper;
 use crate::{
@@ -404,10 +404,7 @@ where
             metrics::SUBSEQUENT_MANDATE_PAYMENT.add(
                 &metrics::CONTEXT,
                 1,
-                &[metrics::request::add_attributes(
-                    "connector",
-                    mandate.connector,
-                )],
+                &add_attributes([("connector", mandate.connector)]),
             );
             Ok(Some(mandate_id.clone()))
         }
@@ -463,7 +460,7 @@ where
             metrics::MANDATE_COUNT.add(
                 &metrics::CONTEXT,
                 1,
-                &[metrics::request::add_attributes("connector", connector)],
+                &add_attributes([("connector", connector)]),
             );
             Ok(Some(res_mandate_id))
         }
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index 66940fa9508..8df78d28187 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -36,7 +36,7 @@ use euclid::{
 use hyperswitch_constraint_graph as cgraph;
 use kgraph_utils::transformers::IntoDirValue;
 use masking::Secret;
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 use strum::IntoEnumIterator;
 
 use super::surcharge_decision_configs::{
@@ -3958,7 +3958,7 @@ impl TempLockerCardSupport {
         metrics::TASKS_ADDED_COUNT.add(
             &metrics::CONTEXT,
             1,
-            &[request::add_attributes("flow", "DeleteTokenizeData")],
+            &add_attributes([("flow", "DeleteTokenizeData")]),
         );
         Ok(card)
     }
diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs
index f37385b80c6..4e17ec6abd3 100644
--- a/crates/router/src/core/payment_methods/vault.rs
+++ b/crates/router/src/core/payment_methods/vault.rs
@@ -7,7 +7,7 @@ use common_utils::{
 };
 use error_stack::{report, ResultExt};
 use masking::PeekInterface;
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 use scheduler::{types::process_data, utils as process_tracker_utils};
 
 #[cfg(feature = "payouts")]
@@ -1232,10 +1232,7 @@ pub async fn retry_delete_tokenize(
             metrics::TASKS_RESET_COUNT.add(
                 &metrics::CONTEXT,
                 1,
-                &[metrics::request::add_attributes(
-                    "flow",
-                    "DeleteTokenizeData",
-                )],
+                &add_attributes([("flow", "DeleteTokenizeData")]),
             );
             retry_schedule
         }
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 50eedcfb568..9cf46477b28 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -42,7 +42,7 @@ pub use hyperswitch_domain_models::{
 };
 use masking::{ExposeInterface, Secret};
 use redis_interface::errors::RedisError;
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 #[cfg(feature = "olap")]
 use router_types::transformers::ForeignFrom;
 use scheduler::utils as pt_utils;
@@ -857,16 +857,13 @@ pub trait PaymentRedirectFlow: Sync {
         metrics::REDIRECTION_TRIGGERED.add(
             &metrics::CONTEXT,
             1,
-            &[
-                metrics::request::add_attributes(
+            &add_attributes([
+                (
                     "connector",
                     req.connector.to_owned().unwrap_or("null".to_string()),
                 ),
-                metrics::request::add_attributes(
-                    "merchant_id",
-                    merchant_account.merchant_id.to_owned(),
-                ),
-            ],
+                ("merchant_id", merchant_account.merchant_id.to_owned()),
+            ]),
         );
         let connector = req.connector.clone().get_required_value("connector")?;
 
diff --git a/crates/router/src/core/payments/access_token.rs b/crates/router/src/core/payments/access_token.rs
index 4241db6742d..a53a3d405a9 100644
--- a/crates/router/src/core/payments/access_token.rs
+++ b/crates/router/src/core/payments/access_token.rs
@@ -2,6 +2,7 @@ use std::fmt::Debug;
 
 use common_utils::ext_traits::AsyncExt;
 use error_stack::ResultExt;
+use router_env::metrics::add_attributes;
 
 use crate::{
     consts,
@@ -94,10 +95,7 @@ pub async fn add_access_token<
                 metrics::ACCESS_TOKEN_CACHE_HIT.add(
                     &metrics::CONTEXT,
                     1,
-                    &[metrics::request::add_attributes(
-                        "connector",
-                        connector.connector_name.to_string(),
-                    )],
+                    &add_attributes([("connector", connector.connector_name.to_string())]),
                 );
                 Ok(Some(access_token))
             }
@@ -105,10 +103,7 @@ pub async fn add_access_token<
                 metrics::ACCESS_TOKEN_CACHE_MISS.add(
                     &metrics::CONTEXT,
                     1,
-                    &[metrics::request::add_attributes(
-                        "connector",
-                        connector.connector_name.to_string(),
-                    )],
+                    &add_attributes([("connector", connector.connector_name.to_string())]),
                 );
 
                 let cloned_router_data = router_data.clone();
@@ -247,10 +242,7 @@ pub async fn refresh_connector_auth(
     metrics::ACCESS_TOKEN_CREATION.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes(
-            "connector",
-            connector.connector_name.to_string(),
-        )],
+        &add_attributes([("connector", connector.connector_name.to_string())]),
     );
     Ok(access_token_router_data)
 }
diff --git a/crates/router/src/core/payments/customers.rs b/crates/router/src/core/payments/customers.rs
index 448e5fedb8b..67fdd7746af 100644
--- a/crates/router/src/core/payments/customers.rs
+++ b/crates/router/src/core/payments/customers.rs
@@ -1,4 +1,4 @@
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 
 use crate::{
     core::{
@@ -54,10 +54,7 @@ pub async fn create_connector_customer<F: Clone, T: Clone>(
     metrics::CONNECTOR_CUSTOMER_CREATE.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes(
-            "connector",
-            connector.connector_name.to_string(),
-        )],
+        &add_attributes([("connector", connector.connector_name.to_string())]),
     );
 
     let connector_customer_id = match resp.response {
diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs
index 7497ca6a9e5..433274587a8 100644
--- a/crates/router/src/core/payments/flows/authorize_flow.rs
+++ b/crates/router/src/core/payments/flows/authorize_flow.rs
@@ -1,4 +1,5 @@
 use async_trait::async_trait;
+use router_env::metrics::add_attributes;
 
 // use router_env::tracing::Instrument;
 use super::{ConstructFlowSpecificData, Feature};
@@ -209,13 +210,10 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
                 metrics::EXECUTE_PRETASK_COUNT.add(
                     &metrics::CONTEXT,
                     1,
-                    &[
-                        metrics::request::add_attributes(
-                            "connector",
-                            connector.connector_name.to_string(),
-                        ),
-                        metrics::request::add_attributes("flow", format!("{:?}", api::Authorize)),
-                    ],
+                    &add_attributes([
+                        ("connector", connector.connector_name.to_string()),
+                        ("flow", format!("{:?}", api::Authorize)),
+                    ]),
                 );
 
                 logger::debug!(completed_pre_tasks=?true);
@@ -333,13 +331,10 @@ pub async fn authorize_preprocessing_steps<F: Clone>(
         metrics::PREPROCESSING_STEPS_COUNT.add(
             &metrics::CONTEXT,
             1,
-            &[
-                metrics::request::add_attributes("connector", connector.connector_name.to_string()),
-                metrics::request::add_attributes(
-                    "payment_method",
-                    router_data.payment_method.to_string(),
-                ),
-                metrics::request::add_attributes(
+            &add_attributes([
+                ("connector", connector.connector_name.to_string()),
+                ("payment_method", router_data.payment_method.to_string()),
+                (
                     "payment_method_type",
                     router_data
                         .request
@@ -348,7 +343,7 @@ pub async fn authorize_preprocessing_steps<F: Clone>(
                         .map(|inner| inner.to_string())
                         .unwrap_or("null".to_string()),
                 ),
-            ],
+            ]),
         );
         let mut authorize_router_data = helpers::router_data_type_conversion::<_, F, _, _, _, _>(
             resp.clone(),
diff --git a/crates/router/src/core/payments/flows/cancel_flow.rs b/crates/router/src/core/payments/flows/cancel_flow.rs
index d7e8cc3d9b5..2a6774a91e2 100644
--- a/crates/router/src/core/payments/flows/cancel_flow.rs
+++ b/crates/router/src/core/payments/flows/cancel_flow.rs
@@ -1,4 +1,5 @@
 use async_trait::async_trait;
+use router_env::metrics::add_attributes;
 
 use super::{ConstructFlowSpecificData, Feature};
 use crate::{
@@ -55,10 +56,7 @@ impl Feature<api::Void, types::PaymentsCancelData>
         metrics::PAYMENT_CANCEL_COUNT.add(
             &metrics::CONTEXT,
             1,
-            &[metrics::request::add_attributes(
-                "connector",
-                connector.connector_name.to_string(),
-            )],
+            &add_attributes([("connector", connector.connector_name.to_string())]),
         );
 
         let connector_integration: services::BoxedConnectorIntegration<
diff --git a/crates/router/src/core/payments/flows/complete_authorize_flow.rs b/crates/router/src/core/payments/flows/complete_authorize_flow.rs
index 5d0cb9f9f38..bb2c959f290 100644
--- a/crates/router/src/core/payments/flows/complete_authorize_flow.rs
+++ b/crates/router/src/core/payments/flows/complete_authorize_flow.rs
@@ -1,4 +1,5 @@
 use async_trait::async_trait;
+use router_env::metrics::add_attributes;
 
 use super::{ConstructFlowSpecificData, Feature};
 use crate::{
@@ -191,13 +192,10 @@ pub async fn complete_authorize_preprocessing_steps<F: Clone>(
         metrics::PREPROCESSING_STEPS_COUNT.add(
             &metrics::CONTEXT,
             1,
-            &[
-                metrics::request::add_attributes("connector", connector.connector_name.to_string()),
-                metrics::request::add_attributes(
-                    "payment_method",
-                    router_data.payment_method.to_string(),
-                ),
-            ],
+            &add_attributes([
+                ("connector", connector.connector_name.to_string()),
+                ("payment_method", router_data.payment_method.to_string()),
+            ]),
         );
 
         let mut router_data_request = router_data.request.to_owned();
diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs
index 14a3b9327dc..e279e6f7c34 100644
--- a/crates/router/src/core/payments/flows/session_flow.rs
+++ b/crates/router/src/core/payments/flows/session_flow.rs
@@ -3,6 +3,7 @@ use async_trait::async_trait;
 use common_utils::{ext_traits::ByteSliceExt, request::RequestContent};
 use error_stack::{Report, ResultExt};
 use masking::ExposeInterface;
+use router_env::metrics::add_attributes;
 
 use super::{ConstructFlowSpecificData, Feature};
 use crate::{
@@ -64,10 +65,7 @@ impl Feature<api::Session, types::PaymentsSessionData> for types::PaymentsSessio
         metrics::SESSION_TOKEN_CREATED.add(
             &metrics::CONTEXT,
             1,
-            &[metrics::request::add_attributes(
-                "connector",
-                connector.connector_name.to_string(),
-            )],
+            &add_attributes([("connector", connector.connector_name.to_string())]),
         );
         self.decide_flow(
             state,
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 7eada733aed..49cc20528a1 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -26,7 +26,7 @@ use openssl::{
     pkey::PKey,
     symm::{decrypt_aead, Cipher},
 };
-use router_env::{instrument, logger, tracing};
+use router_env::{instrument, logger, metrics::add_attributes, tracing};
 use uuid::Uuid;
 use x509_parser::parse_x509_certificate;
 
@@ -1219,10 +1219,7 @@ where
                     metrics::TASKS_ADDED_COUNT.add(
                         &metrics::CONTEXT,
                         1,
-                        &[metrics::request::add_attributes(
-                            "flow",
-                            format!("{:#?}", operation),
-                        )],
+                        &add_attributes([("flow", format!("{:#?}", operation))]),
                     );
                     super::add_process_sync_task(&*state.store, payment_attempt, stime)
                         .await
@@ -1233,10 +1230,7 @@ where
                     metrics::TASKS_RESET_COUNT.add(
                         &metrics::CONTEXT,
                         1,
-                        &[metrics::request::add_attributes(
-                            "flow",
-                            format!("{:#?}", operation),
-                        )],
+                        &add_attributes([("flow", format!("{:#?}", operation))]),
                     );
                     super::reset_process_sync_task(&*state.store, payment_attempt, stime)
                         .await
@@ -3406,10 +3400,7 @@ pub fn get_attempt_type(
                 metrics::MANUAL_RETRY_REQUEST_COUNT.add(
                     &metrics::CONTEXT,
                     1,
-                    &[metrics::request::add_attributes(
-                        "merchant_id",
-                        payment_attempt.merchant_id.clone(),
-                    )],
+                    &add_attributes([("merchant_id", payment_attempt.merchant_id.clone())]),
                 );
                 match payment_attempt.status {
                     enums::AttemptStatus::Started
@@ -3433,10 +3424,7 @@ pub fn get_attempt_type(
                         metrics::MANUAL_RETRY_VALIDATION_FAILED.add(
                             &metrics::CONTEXT,
                             1,
-                            &[metrics::request::add_attributes(
-                                "merchant_id",
-                                payment_attempt.merchant_id.clone(),
-                            )],
+                            &add_attributes([("merchant_id", payment_attempt.merchant_id.clone())]),
                         );
                         Err(errors::ApiErrorResponse::InternalServerError)
                             .attach_printable("Payment Attempt unexpected state")
@@ -3448,10 +3436,7 @@ pub fn get_attempt_type(
                         metrics::MANUAL_RETRY_VALIDATION_FAILED.add(
                             &metrics::CONTEXT,
                             1,
-                            &[metrics::request::add_attributes(
-                                "merchant_id",
-                                payment_attempt.merchant_id.clone(),
-                            )],
+                            &add_attributes([("merchant_id", payment_attempt.merchant_id.clone())]),
                         );
                         Err(report!(errors::ApiErrorResponse::PreconditionFailed {
                             message:
@@ -3466,10 +3451,7 @@ pub fn get_attempt_type(
                         metrics::MANUAL_RETRY_COUNT.add(
                             &metrics::CONTEXT,
                             1,
-                            &[metrics::request::add_attributes(
-                                "merchant_id",
-                                payment_attempt.merchant_id.clone(),
-                            )],
+                            &add_attributes([("merchant_id", payment_attempt.merchant_id.clone())]),
                         );
                         Ok(AttemptType::New)
                     }
diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs
index b014f42a5ce..41a45c29d24 100644
--- a/crates/router/src/core/payments/tokenization.rs
+++ b/crates/router/src/core/payments/tokenization.rs
@@ -8,7 +8,7 @@ use common_utils::{
 };
 use error_stack::{report, ResultExt};
 use masking::ExposeInterface;
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 
 use super::helpers;
 use crate::{
@@ -762,16 +762,10 @@ pub async fn add_payment_method_token<F: Clone, T: types::Tokenizable + Clone>(
             metrics::CONNECTOR_PAYMENT_METHOD_TOKENIZATION.add(
                 &metrics::CONTEXT,
                 1,
-                &[
-                    metrics::request::add_attributes(
-                        "connector",
-                        connector.connector_name.to_string(),
-                    ),
-                    metrics::request::add_attributes(
-                        "payment_method",
-                        router_data.payment_method.to_string(),
-                    ),
-                ],
+                &add_attributes([
+                    ("connector", connector.connector_name.to_string()),
+                    ("payment_method", router_data.payment_method.to_string()),
+                ]),
             );
 
             let pm_token = match resp.response {
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index 604bc5cda99..6b54427d87a 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -11,7 +11,7 @@ use common_utils::{consts::X_HS_LATENCY, fp_utils, types::MinorUnit};
 use diesel_models::ephemeral_key;
 use error_stack::{report, ResultExt};
 use masking::{Maskable, PeekInterface, Secret};
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 
 use super::{flows::Feature, types::AuthenticationData, PaymentData};
 use crate::{
@@ -844,12 +844,12 @@ where
     metrics::PAYMENT_OPS_COUNT.add(
         &metrics::CONTEXT,
         1,
-        &[
-            metrics::request::add_attributes("operation", format!("{:?}", operation)),
-            metrics::request::add_attributes("merchant", merchant_id),
-            metrics::request::add_attributes("payment_method_type", payment_method_type),
-            metrics::request::add_attributes("payment_method", payment_method),
-        ],
+        &add_attributes([
+            ("operation", format!("{:?}", operation)),
+            ("merchant", merchant_id),
+            ("payment_method_type", payment_method_type),
+            ("payment_method", payment_method),
+        ]),
     );
 
     Ok(output)
diff --git a/crates/router/src/core/payouts/access_token.rs b/crates/router/src/core/payouts/access_token.rs
index 5e40720f4ef..2f1892af821 100644
--- a/crates/router/src/core/payouts/access_token.rs
+++ b/crates/router/src/core/payouts/access_token.rs
@@ -1,5 +1,6 @@
 use common_utils::ext_traits::AsyncExt;
 use error_stack::ResultExt;
+use router_env::metrics::add_attributes;
 
 use crate::{
     consts,
@@ -185,10 +186,7 @@ pub async fn refresh_connector_auth(
     metrics::ACCESS_TOKEN_CREATION.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes(
-            "connector",
-            connector.connector_name.to_string(),
-        )],
+        &add_attributes([("connector", connector.connector_name.to_string())]),
     );
     Ok(access_token_router_data)
 }
diff --git a/crates/router/src/core/refunds.rs b/crates/router/src/core/refunds.rs
index 164fd1ec784..78b4762777f 100644
--- a/crates/router/src/core/refunds.rs
+++ b/crates/router/src/core/refunds.rs
@@ -12,7 +12,7 @@ use common_utils::{
 use diesel_models::process_tracker::business_status;
 use error_stack::{report, ResultExt};
 use masking::PeekInterface;
-use router_env::{instrument, tracing};
+use router_env::{instrument, metrics::add_attributes, tracing};
 use scheduler::{consumer::types::process_data, utils as process_tracker_utils};
 #[cfg(feature = "olap")]
 use strum::IntoEnumIterator;
@@ -154,10 +154,7 @@ pub async fn trigger_refund_to_gateway(
     metrics::REFUND_COUNT.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes(
-            "connector",
-            routed_through.clone(),
-        )],
+        &add_attributes([("connector", routed_through.clone())]),
     );
 
     let connector: api::ConnectorData = api::ConnectorData::get_connector_by_name(
@@ -280,10 +277,7 @@ pub async fn trigger_refund_to_gateway(
                 metrics::SUCCESSFUL_REFUND.add(
                     &metrics::CONTEXT,
                     1,
-                    &[metrics::request::add_attributes(
-                        "connector",
-                        connector.connector_name.to_string(),
-                    )],
+                    &add_attributes([("connector", connector.connector_name.to_string())]),
                 )
             }
             storage::RefundUpdate::Update {
@@ -1246,11 +1240,7 @@ pub async fn add_refund_sync_task(
                 refund.refund_id
             )
         })?;
-    metrics::TASKS_ADDED_COUNT.add(
-        &metrics::CONTEXT,
-        1,
-        &[metrics::request::add_attributes("flow", "Refund")],
-    );
+    metrics::TASKS_ADDED_COUNT.add(&metrics::CONTEXT, 1, &add_attributes([("flow", "Refund")]));
 
     Ok(response)
 }
diff --git a/crates/router/src/core/webhooks/incoming.rs b/crates/router/src/core/webhooks/incoming.rs
index 2f1a37981ec..503a67855d9 100644
--- a/crates/router/src/core/webhooks/incoming.rs
+++ b/crates/router/src/core/webhooks/incoming.rs
@@ -10,7 +10,7 @@ use api_models::{
 use common_utils::{errors::ReportSwitchExt, events::ApiEventsType};
 use error_stack::{report, ResultExt};
 use masking::ExposeInterface;
-use router_env::{instrument, tracing, tracing_actix_web::RequestId};
+use router_env::{instrument, metrics::add_attributes, tracing, tracing_actix_web::RequestId};
 
 use super::{types, utils, MERCHANT_ID};
 use crate::{
@@ -25,9 +25,7 @@ use crate::{
     logger,
     routes::{
         app::{ReqState, SessionStateInfo},
-        lock_utils,
-        metrics::request::add_attributes,
-        SessionState,
+        lock_utils, SessionState,
     },
     services::{self, authentication as auth},
     types::{
@@ -567,10 +565,7 @@ async fn payments_incoming_webhook_flow(
                     metrics::WEBHOOK_PAYMENT_NOT_FOUND.add(
                         &metrics::CONTEXT,
                         1,
-                        &[add_attributes(
-                            "merchant_id",
-                            merchant_account.merchant_id.clone(),
-                        )],
+                        &add_attributes([("merchant_id", merchant_account.merchant_id.clone())]),
                     );
                     return Ok(WebhookResponseTracker::NoEffect);
                 }
diff --git a/crates/router/src/core/webhooks/outgoing.rs b/crates/router/src/core/webhooks/outgoing.rs
index 07fe78f51ce..410d6c3d851 100644
--- a/crates/router/src/core/webhooks/outgoing.rs
+++ b/crates/router/src/core/webhooks/outgoing.rs
@@ -8,6 +8,7 @@ use error_stack::{report, ResultExt};
 use masking::{ExposeInterface, Mask, PeekInterface, Secret};
 use router_env::{
     instrument,
+    metrics::add_attributes,
     tracing::{self, Instrument},
 };
 
@@ -22,7 +23,7 @@ use crate::{
     db::StorageInterface,
     events::outgoing_webhook_logs::{OutgoingWebhookEvent, OutgoingWebhookEventMetric},
     logger,
-    routes::{app::SessionStateInfo, metrics::request::add_attributes, SessionState},
+    routes::{app::SessionStateInfo, SessionState},
     services,
     types::{
         api,
@@ -501,7 +502,7 @@ pub(crate) async fn add_outgoing_webhook_retry_task_to_process_tracker(
             crate::routes::metrics::TASKS_ADDED_COUNT.add(
                 &metrics::CONTEXT,
                 1,
-                &[add_attributes("flow", "OutgoingWebhookRetry")],
+                &add_attributes([("flow", "OutgoingWebhookRetry")]),
             );
             Ok(process_tracker)
         }
@@ -509,7 +510,7 @@ pub(crate) async fn add_outgoing_webhook_retry_task_to_process_tracker(
             crate::routes::metrics::TASK_ADDITION_FAILURES_COUNT.add(
                 &metrics::CONTEXT,
                 1,
-                &[add_attributes("flow", "OutgoingWebhookRetry")],
+                &add_attributes([("flow", "OutgoingWebhookRetry")]),
             );
             Err(error)
         }
diff --git a/crates/router/src/routes/metrics.rs b/crates/router/src/routes/metrics.rs
index eef85410981..fffb5e20c9d 100644
--- a/crates/router/src/routes/metrics.rs
+++ b/crates/router/src/routes/metrics.rs
@@ -2,7 +2,7 @@ pub mod bg_metrics_collector;
 pub mod request;
 pub mod utils;
 
-use router_env::{counter_metric, gauge_metric, global_meter, histogram_metric, metrics_context};
+use router_env::{counter_metric, global_meter, histogram_metric, metrics_context};
 
 metrics_context!(CONTEXT);
 global_meter!(GLOBAL_METER, "ROUTER_API");
@@ -135,6 +135,3 @@ counter_metric!(ACCESS_TOKEN_CACHE_HIT, GLOBAL_METER);
 
 // A counter to indicate the access token cache miss
 counter_metric!(ACCESS_TOKEN_CACHE_MISS, GLOBAL_METER);
-
-// Metrics for In-memory cache
-gauge_metric!(CACHE_ENTRY_COUNT, GLOBAL_METER);
diff --git a/crates/router/src/routes/metrics/bg_metrics_collector.rs b/crates/router/src/routes/metrics/bg_metrics_collector.rs
index 65cb7a13e5e..52d7777f5aa 100644
--- a/crates/router/src/routes/metrics/bg_metrics_collector.rs
+++ b/crates/router/src/routes/metrics/bg_metrics_collector.rs
@@ -2,40 +2,25 @@ use storage_impl::redis::cache;
 
 const DEFAULT_BG_METRICS_COLLECTION_INTERVAL_IN_SECS: u16 = 15;
 
-macro_rules! gauge_metrics_for_imc {
-    ($($cache:ident),*) => {
-        $(
-            {
-                cache::$cache.run_pending_tasks().await;
-
-                super::CACHE_ENTRY_COUNT.observe(
-                    &super::CONTEXT,
-                    cache::$cache.get_entry_count(),
-                    &[super::request::add_attributes(
-                        "cache_type",
-                        stringify!($cache),
-                    )],
-                );
-            }
-        )*
-    };
-}
-
 pub fn spawn_metrics_collector(metrics_collection_interval_in_secs: &Option<u16>) {
     let metrics_collection_interval = metrics_collection_interval_in_secs
         .unwrap_or(DEFAULT_BG_METRICS_COLLECTION_INTERVAL_IN_SECS);
 
+    let cache_instances = [
+        &cache::CONFIG_CACHE,
+        &cache::ACCOUNTS_CACHE,
+        &cache::ROUTING_CACHE,
+        &cache::CGRAPH_CACHE,
+        &cache::PM_FILTERS_CGRAPH_CACHE,
+        &cache::DECISION_MANAGER_CACHE,
+        &cache::SURCHARGE_CACHE,
+    ];
+
     tokio::spawn(async move {
         loop {
-            gauge_metrics_for_imc!(
-                CONFIG_CACHE,
-                ACCOUNTS_CACHE,
-                ROUTING_CACHE,
-                CGRAPH_CACHE,
-                PM_FILTERS_CGRAPH_CACHE,
-                DECISION_MANAGER_CACHE,
-                SURCHARGE_CACHE
-            );
+            for instance in cache_instances {
+                instance.record_entry_count_metric().await
+            }
 
             tokio::time::sleep(std::time::Duration::from_secs(
                 metrics_collection_interval.into(),
diff --git a/crates/router/src/routes/metrics/request.rs b/crates/router/src/routes/metrics/request.rs
index ef53ad83f2c..905f089a0c6 100644
--- a/crates/router/src/routes/metrics/request.rs
+++ b/crates/router/src/routes/metrics/request.rs
@@ -1,4 +1,4 @@
-use router_env::opentelemetry;
+use router_env::{metrics::add_attributes, opentelemetry};
 
 use super::utils as metric_utils;
 use crate::services::ApplicationResponse;
@@ -11,12 +11,16 @@ where
     F: futures::Future<Output = R>,
 {
     let key = "request_type";
-    super::REQUESTS_RECEIVED.add(&super::CONTEXT, 1, &[add_attributes(key, flow.to_string())]);
+    super::REQUESTS_RECEIVED.add(
+        &super::CONTEXT,
+        1,
+        &add_attributes([(key, flow.to_string())]),
+    );
     let (result, time) = metric_utils::time_future(future).await;
     super::REQUEST_TIME.record(
         &super::CONTEXT,
         time.as_secs_f64(),
-        &[add_attributes(key, flow.to_string())],
+        &add_attributes([(key, flow.to_string())]),
     );
     result
 }
@@ -35,22 +39,15 @@ where
     result
 }
 
-pub fn add_attributes<T: Into<opentelemetry::Value>>(
-    key: &'static str,
-    value: T,
-) -> opentelemetry::KeyValue {
-    opentelemetry::KeyValue::new(key, value)
-}
-
-pub fn status_code_metrics(status_code: i64, flow: String, merchant_id: String) {
+pub fn status_code_metrics(status_code: String, flow: String, merchant_id: String) {
     super::REQUEST_STATUS.add(
         &super::CONTEXT,
         1,
-        &[
-            add_attributes("status_code", status_code),
-            add_attributes("flow", flow),
-            add_attributes("merchant_id", merchant_id),
-        ],
+        &add_attributes([
+            ("status_code", status_code),
+            ("flow", flow),
+            ("merchant_id", merchant_id),
+        ]),
     )
 }
 
diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs
index cccbaa496e1..928b3a400eb 100644
--- a/crates/router/src/services/api.rs
+++ b/crates/router/src/services/api.rs
@@ -29,7 +29,7 @@ pub use hyperswitch_interfaces::api::{
     BoxedConnectorIntegration, CaptureSyncMethod, ConnectorIntegration, ConnectorIntegrationAny,
 };
 use masking::{Maskable, PeekInterface};
-use router_env::{instrument, tracing, tracing_actix_web::RequestId, Tag};
+use router_env::{instrument, metrics::add_attributes, tracing, tracing_actix_web::RequestId, Tag};
 use serde::Serialize;
 use serde_json::json;
 use tera::{Context, Tera};
@@ -178,9 +178,9 @@ where
             metrics::CONNECTOR_CALL_COUNT.add(
                 &metrics::CONTEXT,
                 1,
-                &[
-                    metrics::request::add_attributes("connector", req.connector.to_string()),
-                    metrics::request::add_attributes(
+                &add_attributes([
+                    ("connector", req.connector.to_string()),
+                    (
                         "flow",
                         std::any::type_name::<T>()
                             .split("::")
@@ -188,7 +188,7 @@ where
                             .unwrap_or_default()
                             .to_string(),
                     ),
-                ],
+                ]),
             );
 
             let connector_request = match connector_request {
@@ -204,10 +204,7 @@ where
                             metrics::REQUEST_BUILD_FAILURE.add(
                                 &metrics::CONTEXT,
                                 1,
-                                &[metrics::request::add_attributes(
-                                    "connector",
-                                    req.connector.to_string(),
-                                )],
+                                &add_attributes([("connector", req.connector.to_string())]),
                             )
                         }
                         error
@@ -272,10 +269,10 @@ where
                                             metrics::RESPONSE_DESERIALIZATION_FAILURE.add(
                                                 &metrics::CONTEXT,
                                                 1,
-                                                &[metrics::request::add_attributes(
+                                                &add_attributes([(
                                                     "connector",
                                                     req.connector.to_string(),
-                                                )],
+                                                )]),
                                             )
                                         }
                                             error
@@ -313,10 +310,7 @@ where
                                     metrics::CONNECTOR_ERROR_RESPONSE_COUNT.add(
                                         &metrics::CONTEXT,
                                         1,
-                                        &[metrics::request::add_attributes(
-                                            "connector",
-                                            req.connector.clone(),
-                                        )],
+                                        &add_attributes([("connector", req.connector.clone())]),
                                     );
 
                                     let error = match body.status_code {
@@ -915,7 +909,11 @@ where
     );
     state.event_handler().log_event(&api_event);
 
-    metrics::request::status_code_metrics(status_code, flow.to_string(), merchant_id.to_string());
+    metrics::request::status_code_metrics(
+        status_code.to_string(),
+        flow.to_string(),
+        merchant_id.to_string(),
+    );
 
     output
 }
diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs
index 701eda5d1c0..2aabed475b9 100644
--- a/crates/router/src/utils.rs
+++ b/crates/router/src/utils.rs
@@ -29,6 +29,7 @@ use image::Luma;
 use masking::ExposeInterface;
 use nanoid::nanoid;
 use qrcode;
+use router_env::metrics::add_attributes;
 use serde::de::DeserializeOwned;
 use serde_json::Value;
 use tracing_futures::Instrument;
@@ -553,12 +554,12 @@ pub async fn get_mca_from_object_reference_id(
 // validate json format for the error
 pub fn handle_json_response_deserialization_failure(
     res: types::Response,
-    connector: String,
+    connector: &'static str,
 ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
     metrics::RESPONSE_DESERIALIZATION_FAILURE.add(
         &metrics::CONTEXT,
         1,
-        &[metrics::request::add_attributes("connector", connector)],
+        &add_attributes([("connector", connector)]),
     );
 
     let response_data = String::from_utf8(res.response.to_vec())
@@ -781,24 +782,24 @@ pub fn add_apple_pay_flow_metrics(
             domain::ApplePayFlow::Simplified(_) => metrics::APPLE_PAY_SIMPLIFIED_FLOW.add(
                 &metrics::CONTEXT,
                 1,
-                &[
-                    metrics::request::add_attributes(
+                &add_attributes([
+                    (
                         "connector",
                         connector.to_owned().unwrap_or("null".to_string()),
                     ),
-                    metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
-                ],
+                    ("merchant_id", merchant_id.to_owned()),
+                ]),
             ),
             domain::ApplePayFlow::Manual => metrics::APPLE_PAY_MANUAL_FLOW.add(
                 &metrics::CONTEXT,
                 1,
-                &[
-                    metrics::request::add_attributes(
+                &add_attributes([
+                    (
                         "connector",
                         connector.to_owned().unwrap_or("null".to_string()),
                     ),
-                    metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
-                ],
+                    ("merchant_id", merchant_id.to_owned()),
+                ]),
             ),
         }
     }
@@ -817,26 +818,26 @@ pub fn add_apple_pay_payment_status_metrics(
                     metrics::APPLE_PAY_SIMPLIFIED_FLOW_SUCCESSFUL_PAYMENT.add(
                         &metrics::CONTEXT,
                         1,
-                        &[
-                            metrics::request::add_attributes(
+                        &add_attributes([
+                            (
                                 "connector",
                                 connector.to_owned().unwrap_or("null".to_string()),
                             ),
-                            metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
-                        ],
+                            ("merchant_id", merchant_id.to_owned()),
+                        ]),
                     )
                 }
                 domain::ApplePayFlow::Manual => metrics::APPLE_PAY_MANUAL_FLOW_SUCCESSFUL_PAYMENT
                     .add(
                         &metrics::CONTEXT,
                         1,
-                        &[
-                            metrics::request::add_attributes(
+                        &add_attributes([
+                            (
                                 "connector",
                                 connector.to_owned().unwrap_or("null".to_string()),
                             ),
-                            metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
-                        ],
+                            ("merchant_id", merchant_id.to_owned()),
+                        ]),
                     ),
             }
         }
@@ -847,25 +848,25 @@ pub fn add_apple_pay_payment_status_metrics(
                     metrics::APPLE_PAY_SIMPLIFIED_FLOW_FAILED_PAYMENT.add(
                         &metrics::CONTEXT,
                         1,
-                        &[
-                            metrics::request::add_attributes(
+                        &add_attributes([
+                            (
                                 "connector",
                                 connector.to_owned().unwrap_or("null".to_string()),
                             ),
-                            metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
-                        ],
+                            ("merchant_id", merchant_id.to_owned()),
+                        ]),
                     )
                 }
                 domain::ApplePayFlow::Manual => metrics::APPLE_PAY_MANUAL_FLOW_FAILED_PAYMENT.add(
                     &metrics::CONTEXT,
                     1,
-                    &[
-                        metrics::request::add_attributes(
+                    &add_attributes([
+                        (
                             "connector",
                             connector.to_owned().unwrap_or("null".to_string()),
                         ),
-                        metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
-                    ],
+                        ("merchant_id", merchant_id.to_owned()),
+                    ]),
                 ),
             }
         }
diff --git a/crates/router/src/workflows/api_key_expiry.rs b/crates/router/src/workflows/api_key_expiry.rs
index c24671be34d..8d8f1aa6c85 100644
--- a/crates/router/src/workflows/api_key_expiry.rs
+++ b/crates/router/src/workflows/api_key_expiry.rs
@@ -2,7 +2,7 @@ use common_utils::{errors::ValidationError, ext_traits::ValueExt};
 use diesel_models::{
     enums as storage_enums, process_tracker::business_status, ApiKeyExpiryTrackingData,
 };
-use router_env::logger;
+use router_env::{logger, metrics::add_attributes};
 use scheduler::{workflows::ProcessTrackerWorkflow, SchedulerSessionState};
 
 use crate::{
@@ -130,7 +130,7 @@ impl ProcessTrackerWorkflow<SessionState> for ApiKeyExpiryWorkflow {
             metrics::TASKS_RESET_COUNT.add(
                 &metrics::CONTEXT,
                 1,
-                &[metrics::request::add_attributes("flow", "ApiKeyExpiry")],
+                &add_attributes([("flow", "ApiKeyExpiry")]),
             );
         }
 
diff --git a/crates/router_env/src/metrics.rs b/crates/router_env/src/metrics.rs
index e75cacaa3c9..780c010579f 100644
--- a/crates/router_env/src/metrics.rs
+++ b/crates/router_env/src/metrics.rs
@@ -120,3 +120,18 @@ macro_rules! gauge_metric {
         > = once_cell::sync::Lazy::new(|| $meter.u64_observable_gauge($description).init());
     };
 }
+
+pub use helpers::add_attributes;
+
+mod helpers {
+    pub fn add_attributes<T, U>(attributes: U) -> Vec<opentelemetry::KeyValue>
+    where
+        T: Into<opentelemetry::Value>,
+        U: IntoIterator<Item = (&'static str, T)>,
+    {
+        attributes
+            .into_iter()
+            .map(|(key, value)| opentelemetry::KeyValue::new(key, value))
+            .collect::<Vec<_>>()
+    }
+}
diff --git a/crates/storage_impl/src/metrics.rs b/crates/storage_impl/src/metrics.rs
index 2f22d578133..cb7a6b216e4 100644
--- a/crates/storage_impl/src/metrics.rs
+++ b/crates/storage_impl/src/metrics.rs
@@ -1,4 +1,4 @@
-use router_env::{counter_metric, global_meter, metrics_context};
+use router_env::{counter_metric, gauge_metric, global_meter, metrics_context};
 
 metrics_context!(CONTEXT);
 global_meter!(GLOBAL_METER, "ROUTER_API");
@@ -11,3 +11,9 @@ counter_metric!(KV_OPERATION_FAILED, GLOBAL_METER);
 counter_metric!(KV_PUSHED_TO_DRAINER, GLOBAL_METER);
 counter_metric!(KV_FAILED_TO_PUSH_TO_DRAINER, GLOBAL_METER);
 counter_metric!(KV_SOFT_KILL_ACTIVE_UPDATE, GLOBAL_METER);
+
+// Metrics for In-memory cache
+gauge_metric!(IN_MEMORY_CACHE_ENTRY_COUNT, GLOBAL_METER);
+counter_metric!(IN_MEMORY_CACHE_HIT, GLOBAL_METER);
+counter_metric!(IN_MEMORY_CACHE_MISS, GLOBAL_METER);
+counter_metric!(IN_MEMORY_CACHE_EVICTION_COUNT, GLOBAL_METER);
diff --git a/crates/storage_impl/src/redis/cache.rs b/crates/storage_impl/src/redis/cache.rs
index 6ad96be2795..81e7e38b1be 100644
--- a/crates/storage_impl/src/redis/cache.rs
+++ b/crates/storage_impl/src/redis/cache.rs
@@ -9,10 +9,14 @@ use error_stack::{Report, ResultExt};
 use moka::future::Cache as MokaCache;
 use once_cell::sync::Lazy;
 use redis_interface::{errors::RedisError, RedisConnectionPool, RedisValue};
-use router_env::tracing::{self, instrument};
+use router_env::{
+    metrics::add_attributes,
+    tracing::{self, instrument},
+};
 
 use crate::{
     errors::StorageError,
+    metrics,
     redis::{PubSubInterface, RedisConnInterface},
 };
 
@@ -53,31 +57,44 @@ const CACHE_TTI: u64 = 10 * 60;
 const MAX_CAPACITY: u64 = 30;
 
 /// Config Cache with time_to_live as 30 mins and time_to_idle as 10 mins.
-pub static CONFIG_CACHE: Lazy<Cache> = Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, None));
+pub static CONFIG_CACHE: Lazy<Cache> =
+    Lazy::new(|| Cache::new("CONFIG_CACHE", CACHE_TTL, CACHE_TTI, None));
 
 /// Accounts cache with time_to_live as 30 mins and size limit
 pub static ACCOUNTS_CACHE: Lazy<Cache> =
-    Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
+    Lazy::new(|| Cache::new("ACCOUNTS_CACHE", CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
 
 /// Routing Cache
 pub static ROUTING_CACHE: Lazy<Cache> =
-    Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
+    Lazy::new(|| Cache::new("ROUTING_CACHE", CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
 
 /// 3DS Decision Manager Cache
-pub static DECISION_MANAGER_CACHE: Lazy<Cache> =
-    Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
+pub static DECISION_MANAGER_CACHE: Lazy<Cache> = Lazy::new(|| {
+    Cache::new(
+        "DECISION_MANAGER_CACHE",
+        CACHE_TTL,
+        CACHE_TTI,
+        Some(MAX_CAPACITY),
+    )
+});
 
 /// Surcharge Cache
 pub static SURCHARGE_CACHE: Lazy<Cache> =
-    Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
+    Lazy::new(|| Cache::new("SURCHARGE_CACHE", CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
 
 /// CGraph Cache
 pub static CGRAPH_CACHE: Lazy<Cache> =
-    Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
+    Lazy::new(|| Cache::new("CGRAPH_CACHE", CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
 
 /// PM Filter CGraph Cache
-pub static PM_FILTERS_CGRAPH_CACHE: Lazy<Cache> =
-    Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY)));
+pub static PM_FILTERS_CGRAPH_CACHE: Lazy<Cache> = Lazy::new(|| {
+    Cache::new(
+        "PM_FILTERS_CGRAPH_CACHE",
+        CACHE_TTL,
+        CACHE_TTI,
+        Some(MAX_CAPACITY),
+    )
+});
 
 /// Trait which defines the behaviour of types that's gonna be stored in Cache
 pub trait Cacheable: Any + Send + Sync + DynClone {
@@ -150,6 +167,7 @@ where
 dyn_clone::clone_trait_object!(Cacheable);
 
 pub struct Cache {
+    name: &'static str,
     inner: MokaCache<String, Arc<dyn Cacheable>>,
 }
 
@@ -173,19 +191,38 @@ impl From<CacheKey> for String {
 impl Cache {
     /// With given `time_to_live` and `time_to_idle` creates a moka cache.
     ///
+    /// `name`        : Cache type name to be used as an attribute in metrics
     /// `time_to_live`: Time in seconds before an object is stored in a caching system before it’s deleted
     /// `time_to_idle`: Time in seconds before a `get` or `insert` operation an object is stored in a caching system before it's deleted
     /// `max_capacity`: Max size in MB's that the cache can hold
-    pub fn new(time_to_live: u64, time_to_idle: u64, max_capacity: Option<u64>) -> Self {
+    pub fn new(
+        name: &'static str,
+        time_to_live: u64,
+        time_to_idle: u64,
+        max_capacity: Option<u64>,
+    ) -> Self {
+        // Record the metrics of manual invalidation of cache entry by the application
+        let eviction_listener = move |_, _, cause| {
+            metrics::IN_MEMORY_CACHE_EVICTION_COUNT.add(
+                &metrics::CONTEXT,
+                1,
+                &add_attributes([
+                    ("cache_type", name.to_owned()),
+                    ("removal_cause", format!("{:?}", cause)),
+                ]),
+            );
+        };
         let mut cache_builder = MokaCache::builder()
             .time_to_live(std::time::Duration::from_secs(time_to_live))
-            .time_to_idle(std::time::Duration::from_secs(time_to_idle));
+            .time_to_idle(std::time::Duration::from_secs(time_to_idle))
+            .eviction_listener(eviction_listener);
 
         if let Some(capacity) = max_capacity {
             cache_builder = cache_builder.max_capacity(capacity * 1024 * 1024);
         }
 
         Self {
+            name,
             inner: cache_builder.build(),
         }
     }
@@ -195,8 +232,26 @@ impl Cache {
     }
 
     pub async fn get_val<T: Clone + Cacheable>(&self, key: CacheKey) -> Option<T> {
-        let val = self.inner.get::<String>(&key.into()).await?;
-        (*val).as_any().downcast_ref::<T>().cloned()
+        let val = self.inner.get::<String>(&key.into()).await;
+
+        // Add cache hit and cache miss metrics
+        if val.is_some() {
+            metrics::IN_MEMORY_CACHE_HIT.add(
+                &metrics::CONTEXT,
+                1,
+                &add_attributes([("cache_type", self.name)]),
+            );
+        } else {
+            metrics::IN_MEMORY_CACHE_MISS.add(
+                &metrics::CONTEXT,
+                1,
+                &add_attributes([("cache_type", self.name)]),
+            );
+        }
+
+        let val = (*val?).as_any().downcast_ref::<T>().cloned();
+
+        val
     }
 
     /// Check if a key exists in cache
@@ -209,14 +264,28 @@ impl Cache {
     }
 
     /// Performs any pending maintenance operations needed by the cache.
-    pub async fn run_pending_tasks(&self) {
+    async fn run_pending_tasks(&self) {
         self.inner.run_pending_tasks().await;
     }
 
     /// Returns an approximate number of entries in this cache.
-    pub fn get_entry_count(&self) -> u64 {
+    fn get_entry_count(&self) -> u64 {
         self.inner.entry_count()
     }
+
+    pub fn name(&self) -> &'static str {
+        self.name
+    }
+
+    pub async fn record_entry_count_metric(&self) {
+        self.run_pending_tasks().await;
+
+        metrics::IN_MEMORY_CACHE_ENTRY_COUNT.observe(
+            &metrics::CONTEXT,
+            self.get_entry_count(),
+            &add_attributes([("cache_type", self.name)]),
+        );
+    }
 }
 
 #[instrument(skip_all)]
@@ -390,7 +459,7 @@ mod cache_tests {
 
     #[tokio::test]
     async fn construct_and_get_cache() {
-        let cache = Cache::new(1800, 1800, None);
+        let cache = Cache::new("test", 1800, 1800, None);
         cache
             .push(
                 CacheKey {
@@ -413,7 +482,7 @@ mod cache_tests {
 
     #[tokio::test]
     async fn eviction_on_size_test() {
-        let cache = Cache::new(2, 2, Some(0));
+        let cache = Cache::new("test", 2, 2, Some(0));
         cache
             .push(
                 CacheKey {
@@ -436,7 +505,7 @@ mod cache_tests {
 
     #[tokio::test]
     async fn invalidate_cache_for_key() {
-        let cache = Cache::new(1800, 1800, None);
+        let cache = Cache::new("test", 1800, 1800, None);
         cache
             .push(
                 CacheKey {
@@ -467,7 +536,7 @@ mod cache_tests {
 
     #[tokio::test]
     async fn eviction_on_time_test() {
-        let cache = Cache::new(2, 2, None);
+        let cache = Cache::new("test", 2, 2, None);
         cache
             .push(
                 CacheKey {

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [ ] New feature
- [ ] Enhancement
- [x] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
This PR introduces basic counter metrics for IMC -

* hits (successful read)
* misses (failed read)
* manual invalidations (done by applications) - makes use of eviction listener on moka that can help identify strategy based evictions

This PR also moves the `add_attribute` method of metrics to `router_env` crate. This method now takes a list of attributes as an argument as opposed to just one (key,value) pair.

### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
1. Insert new config key value pair. Data is not cached in IMC during insertion

```
curl --location 'http://localhost:8080/configs/' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin' \
--data '{
    "key": "test_key",
    "value": "test_val_1"
}'
```

2. Retrieve the inserted config so that the data gets cached to IMC. Since this is the first time the data is getting retrieved, there'll be a cache mis

```
curl --location 'http://localhost:8080/configs/test_key' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin' \
--data ''
```

![image](https://github.com/juspay/hyperswitch/assets/70657455/99f05a27-3ddd-4e5d-9458-f5673423ddc8)

3.  Again retrieve the same config. Since in the previous retrieve, the data was cached, this retrieve will be a cache hit

```
curl --location 'http://localhost:8080/configs/test_key' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin' \
--data ''
```

![image](https://github.com/juspay/hyperswitch/assets/70657455/b3ecd6da-3268-4830-be0b-7ca677f6c4d4)

4. Update the inserted config. This time the cache data has to be invalidated. This should increment the `IN_MEMORY_CACHE_EVICTION_COUNT` metric

```
curl --location 'http://localhost:8080/configs/test_key' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin' \
--data '{
    "key": "test_key",
    "value": "test_val_2"
}'
```

![image](https://github.com/juspay/hyperswitch/assets/70657455/d9492d34-9767-4e41-83a0-c0462af047b5)


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
