From 7261cd84435a2faf2aafb9651713eaba135de417 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 20 Feb 2025 20:34:07 +0100 Subject: [PATCH] Add OpenTelemetry tracing and error handling enhancements Introduced OpenTelemetry tracing with AlwaysOnSampler and console exporter, integrated into the Elsa framework. Added error handling capabilities via custom `IErrorSpanHandler` implementations. Updated project dependencies to include OpenTelemetry-related packages. --- Directory.Packages.props | 392 +++++++++--------- src/apps/Elsa.Server.Web/Program.cs | 11 + .../Features/OpenTelemetryFeature.cs | 6 + ...metryTracingActivityExecutionMiddleware.cs | 11 +- 4 files changed, 220 insertions(+), 200 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 8d70a9957..1ea00d408 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,197 +1,199 @@ - - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs index aeceb8079..9d22d91de 100644 --- a/src/apps/Elsa.Server.Web/Program.cs +++ b/src/apps/Elsa.Server.Web/Program.cs @@ -68,6 +68,8 @@ using Medallion.Threading.Postgres; using Medallion.Threading.Redis; using Microsoft.Data.Sqlite; using Microsoft.Extensions.Options; +using OpenTelemetry; +using OpenTelemetry.Trace; using Proto.Cluster.Kubernetes; using Proto.Persistence.Sqlite; using Proto.Persistence.SqlServer; @@ -121,6 +123,14 @@ var sqlDatabaseProvider = Enum.Parse(configuration["Databas TypeAliasRegistry.RegisterAlias("OrderReceivedProducerFactory", typeof(GenericProducerFactory)); TypeAliasRegistry.RegisterAlias("OrderReceivedConsumerFactory", typeof(GenericConsumerFactory)); +// Configure OpenTelemetry Tracing +using var tracerProvider = Sdk.CreateTracerProviderBuilder() + .AddSource("Elsa.Workflows") // Match your ActivitySource name here + .SetSampler(new AlwaysOnSampler()) // Always record traces for testing + .AddConsoleExporter() // Export spans to the console (optional) + .Build(); + + // Add Elsa services. services .AddElsa(elsa => @@ -455,6 +465,7 @@ services alterations.UseMassTransitDispatcher(); } }) + .UseOpenTelemetry() .UseWorkflowContexts(); if (useQuartz) diff --git a/src/modules/Elsa.OpenTelemetry/Features/OpenTelemetryFeature.cs b/src/modules/Elsa.OpenTelemetry/Features/OpenTelemetryFeature.cs index 67201c44d..d80f308b7 100644 --- a/src/modules/Elsa.OpenTelemetry/Features/OpenTelemetryFeature.cs +++ b/src/modules/Elsa.OpenTelemetry/Features/OpenTelemetryFeature.cs @@ -1,5 +1,8 @@ using Elsa.Features.Abstractions; using Elsa.Features.Services; +using Elsa.OpenTelemetry.Contracts; +using Elsa.OpenTelemetry.Handlers; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.OpenTelemetry.Features; @@ -7,5 +10,8 @@ public class OpenTelemetryFeature(IModule module) : FeatureBase(module) { public override void Configure() { + Services + .AddScoped() + .AddScoped(); } } \ No newline at end of file diff --git a/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs b/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs index 0045fde75..5410d70bf 100644 --- a/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs +++ b/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs @@ -1,6 +1,8 @@ using System.Diagnostics; using Elsa.Common; +using Elsa.OpenTelemetry.Contracts; using Elsa.OpenTelemetry.Helpers; +using Elsa.OpenTelemetry.Models; using Elsa.Workflows; using Elsa.Workflows.Pipelines.ActivityExecution; using JetBrains.Annotations; @@ -40,14 +42,13 @@ public class OpenTelemetryTracingActivityExecutionMiddleware(ActivityMiddlewareD { span.AddEvent(new("Faulted", tags: CreateStatusTags(context))); span.SetStatus(ActivityStatusCode.Error); - span.SetTag("error", true); span.SetTag("activityInstance.hasIncidents", true); - var errorMessage = string.IsNullOrWhiteSpace(context.Exception?.Message) ? "Unknown error" : context.Exception.Message; - span.SetTag("error.message", errorMessage); + var errorSpanHandlers = context.GetServices(); + var errorSpanHandlerContext = new ErrorSpanContext(span, context.Exception); - if (!string.IsNullOrEmpty(context.Exception?.StackTrace)) - span.SetTag("error.stackTrace", context.Exception.StackTrace); + foreach (var handler in errorSpanHandlers) + handler.Handle(errorSpanHandlerContext); } else {