From 855b474e78759d24145f76e74ebb8f51a142208a Mon Sep 17 00:00:00 2001 From: jmaeagle99 <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 24 Aug 2026 16:14:09 -0700 Subject: [PATCH] Add failure_reason tag to activity execution failed metrics --- .../internal/activity/ActivityTaskHandlerImpl.java | 10 ++++++++-- .../internal/worker/ActivityFailedMetricsTests.java | 1 + .../test/java/io/temporal/workflow/MetricsTest.java | 1 + .../java/io/temporal/serviceclient/MetricsTag.java | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/temporal-sdk/src/main/java/io/temporal/internal/activity/ActivityTaskHandlerImpl.java b/temporal-sdk/src/main/java/io/temporal/internal/activity/ActivityTaskHandlerImpl.java index 48e9dbfabf..5b2b2bf90a 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/activity/ActivityTaskHandlerImpl.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/activity/ActivityTaskHandlerImpl.java @@ -195,11 +195,17 @@ static ActivityTaskHandler.Result mapToActivityFailure( metricsScope.tagged( ImmutableMap.of(MetricsTag.EXCEPTION, exception.getClass().getSimpleName())); if (!FailureUtils.isBenignApplicationFailure(exception)) { + // The deprecated counter keeps its original tags so that dashboards still reading it are + // not split into a new series. + Scope failureScope = + ms.tagged( + ImmutableMap.of( + MetricsTag.TASK_FAILURE_TYPE, MetricsTag.TASK_FAILURE_VALUE_ACTIVITY_ERROR)); if (isLocalActivity) { - ms.counter(MetricsType.LOCAL_ACTIVITY_EXEC_FAILED_COUNTER).inc(1); + failureScope.counter(MetricsType.LOCAL_ACTIVITY_EXEC_FAILED_COUNTER).inc(1); ms.counter(MetricsType.LOCAL_ACTIVITY_FAILED_COUNTER).inc(1); } else { - ms.counter(MetricsType.ACTIVITY_EXEC_FAILED_COUNTER).inc(1); + failureScope.counter(MetricsType.ACTIVITY_EXEC_FAILED_COUNTER).inc(1); } } Failure failure = dataConverter.exceptionToFailure(exception); diff --git a/temporal-sdk/src/test/java/io/temporal/internal/worker/ActivityFailedMetricsTests.java b/temporal-sdk/src/test/java/io/temporal/internal/worker/ActivityFailedMetricsTests.java index 1b0cf17d6b..86bd6c233a 100644 --- a/temporal-sdk/src/test/java/io/temporal/internal/worker/ActivityFailedMetricsTests.java +++ b/temporal-sdk/src/test/java/io/temporal/internal/worker/ActivityFailedMetricsTests.java @@ -137,6 +137,7 @@ private Map getActivityTagsWithWorkerType( tags.put("namespace", "UnitTest"); tags.put("activity_type", "Execute"); tags.put("exception", "ApplicationFailure"); + tags.put("failure_reason", "ActivityError"); tags.put("worker_type", workerType); tags.put("workflow_type", workflowType); return tags; diff --git a/temporal-sdk/src/test/java/io/temporal/workflow/MetricsTest.java b/temporal-sdk/src/test/java/io/temporal/workflow/MetricsTest.java index 17178b1996..5b4b9df97a 100644 --- a/temporal-sdk/src/test/java/io/temporal/workflow/MetricsTest.java +++ b/temporal-sdk/src/test/java/io/temporal/workflow/MetricsTest.java @@ -439,6 +439,7 @@ public void testTemporalActivityFailureMetric() throws InterruptedException { .putAll(TAGS_ACTIVITY_WORKER) .put(MetricsTag.ACTIVITY_TYPE, "ThrowIO") .put(MetricsTag.EXCEPTION, "IOException") + .put(MetricsTag.TASK_FAILURE_TYPE, MetricsTag.TASK_FAILURE_VALUE_ACTIVITY_ERROR) .put(MetricsTag.WORKFLOW_TYPE, "NoArgsWorkflow") .build(); diff --git a/temporal-serviceclient/src/main/java/io/temporal/serviceclient/MetricsTag.java b/temporal-serviceclient/src/main/java/io/temporal/serviceclient/MetricsTag.java index e41533e612..d894709d74 100644 --- a/temporal-serviceclient/src/main/java/io/temporal/serviceclient/MetricsTag.java +++ b/temporal-serviceclient/src/main/java/io/temporal/serviceclient/MetricsTag.java @@ -27,6 +27,7 @@ public class MetricsTag { public static final String TASK_FAILURE_VALUE_NON_DETERMINISM_ERROR = "NonDeterminismError"; public static final String TASK_FAILURE_VALUE_GRPC_MESSAGE_TOO_LARGE = "GrpcMessageTooLarge"; public static final String TASK_FAILURE_VALUE_WORKFLOW_ERROR = "WorkflowError"; + public static final String TASK_FAILURE_VALUE_ACTIVITY_ERROR = "ActivityError"; public static final String TASK_FAILURE_VALUE_OPERATION_FAILED = "operation_failed"; public static final String TASK_FAILURE_VALUE_OPERATION_CANCELED = "operation_canceled"; public static final String TASK_FAILURE_VALUE_HANDLER_ERROR_BAD_REQUEST =