Bug: [CHORE] add metrics for ignored incoming webhooks



In some scenarios, application need to acknowledge webhook requests with 200 even though the resource was not found for avoiding the webhooks to queue in connector systems. For such scenarios, incoming webhook flow can fail and even then the response is 200.

A metric needs to be introduced to keep an eye on the volume of such scenarios happening.
diff --git a/crates/router/src/core/metrics.rs b/crates/router/src/core/metrics.rs
index efb463b3a37..4110f470cee 100644
--- a/crates/router/src/core/metrics.rs
+++ b/crates/router/src/core/metrics.rs
@@ -48,6 +48,7 @@ counter_metric!(
     WEBHOOK_EVENT_TYPE_IDENTIFICATION_FAILURE_COUNT,
     GLOBAL_METER
 );
+counter_metric!(WEBHOOK_FLOW_FAILED_BUT_ACKNOWLEDGED, GLOBAL_METER);
 
 counter_metric!(ROUTING_CREATE_REQUEST_RECEIVED, GLOBAL_METER);
 counter_metric!(ROUTING_CREATE_SUCCESS_RESPONSE, GLOBAL_METER);
diff --git a/crates/router/src/core/webhooks/incoming.rs b/crates/router/src/core/webhooks/incoming.rs
index ce183002834..0e8b879f456 100644
--- a/crates/router/src/core/webhooks/incoming.rs
+++ b/crates/router/src/core/webhooks/incoming.rs
@@ -284,6 +284,7 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
                     &connector,
                     connector_name.as_str(),
                     &request_details,
+                    merchant_context.get_merchant_account().get_id(),
                 );
                 match error_result {
                     Ok((response, webhook_tracker, serialized_request)) => {
@@ -373,6 +374,7 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
                         &connector,
                         connector_name.as_str(),
                         &final_request_details,
+                        merchant_context.get_merchant_account().get_id(),
                     );
                     match error_result {
                         Ok((_, webhook_tracker, _)) => webhook_tracker,
@@ -559,8 +561,13 @@ async fn process_webhook_business_logic(
     {
         Ok(mca) => mca,
         Err(error) => {
-            let result =
-                handle_incoming_webhook_error(error, connector, connector_name, request_details);
+            let result = handle_incoming_webhook_error(
+                error,
+                connector,
+                connector_name,
+                request_details,
+                merchant_context.get_merchant_account().get_id(),
+            );
             match result {
                 Ok((_, webhook_tracker, _)) => return Ok(webhook_tracker),
                 Err(e) => return Err(e),
@@ -850,8 +857,13 @@ async fn process_webhook_business_logic(
     match result_response {
         Ok(response) => Ok(response),
         Err(error) => {
-            let result =
-                handle_incoming_webhook_error(error, connector, connector_name, request_details);
+            let result = handle_incoming_webhook_error(
+                error,
+                connector,
+                connector_name,
+                request_details,
+                merchant_context.get_merchant_account().get_id(),
+            );
             match result {
                 Ok((_, webhook_tracker, _)) => Ok(webhook_tracker),
                 Err(e) => Err(e),
@@ -865,6 +877,7 @@ fn handle_incoming_webhook_error(
     connector: &ConnectorEnum,
     connector_name: &str,
     request_details: &IncomingWebhookRequestDetails<'_>,
+    merchant_id: &common_utils::id_type::MerchantId,
 ) -> errors::RouterResult<(
     services::ApplicationResponse<serde_json::Value>,
     WebhookResponseTracker,
@@ -881,6 +894,13 @@ fn handle_incoming_webhook_error(
 
     // get the error response from the connector
     if connector_enum.should_acknowledge_webhook_for_resource_not_found_errors() {
+        metrics::WEBHOOK_FLOW_FAILED_BUT_ACKNOWLEDGED.add(
+            1,
+            router_env::metric_attributes!(
+                ("connector", connector_name.to_string()),
+                ("merchant_id", merchant_id.get_string_repr().to_string())
+            ),
+        );
         let response = connector
             .get_webhook_api_response(
                 request_details,

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

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

## Description
This PR adds a metric `WEBHOOK_FLOW_FAILED_BUT_ACKNOWLEDGED` to track incoming webhooks that failed processing but were acknowledged with 200 status to prevent queueing in connector systems.

The metric includes the following attributes:
- connector
- merchant_id

### 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
In some scenarios, applications need to acknowledge webhook requests with 200 even though the resource was not found, to avoid webhooks queueing in connector systems. This metric provides visibility into the volume of such scenarios, enabling better monitoring and alerting (if needed).

## How did you test it?
Cannot be tested. Metrics will be visible on Grafana.

Can be queried using:

```promql
webhook_flow_failed_but_acknowledged_total{connector="adyen",merchant_id="merchant_123"}
```


## 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
