Merge pull request #6502 from elsa-workflows/enh/otel

Improve OTEL Spans and Tags for Workflow and Activity Execution
This commit is contained in:
Sipke Schoorstra 2025-03-17 15:23:13 +01:00 committed by GitHub
commit ebe32288d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 467 additions and 325 deletions

2
.gitignore vendored
View file

@ -78,3 +78,5 @@ unlist.sh
/artifacts
/docker/data/
docker/docker-compose-datadog.yml

View file

@ -1,206 +1,254 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Antlr4.Runtime.Standard" Version="4.13.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.MySql" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.PostgreSQL" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.SqlServer" Version="0.5.1" />
<PackageVersion Include="AutoMapper" Version="14.0.0" PrivateAssets="All" />
<PackageVersion Include="Azure.Identity" Version="1.13.2" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.18.4" />
<PackageVersion Include="Azure.ResourceManager" Version="1.13.0" />
<PackageVersion Include="Azure.ResourceManager.AppContainers" Version="1.3.0" />
<PackageVersion Include="Azure.ResourceManager.Resources" Version="1.9.0" />
<PackageVersion Include="Azure.ResourceManager.ServiceBus" Version="1.1.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="Bogus" Version="35.6.2" />
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" PrivateAssets="All" />
<PackageVersion Include="Confluent.Kafka" Version="2.8.0" />
<PackageVersion Include="Confluent.SchemaRegistry.Serdes.Avro" Version="2.8.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" PrivateAssets="All" />
<PackageVersion Include="Cronos" Version="0.9.0" />
<PackageVersion Include="Dapper" Version="2.1.66" />
<PackageVersion Include="DistributedLock.Core" Version="1.0.8" />
<PackageVersion Include="DistributedLock.FileSystem" Version="1.0.3" />
<PackageVersion Include="DistributedLock.Postgres" Version="1.3.0" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.3" />
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="8.17.1" />
<PackageVersion Include="Elsa.Studio" Version="3.3.4" />
<PackageVersion Include="Elsa.Studio.Agents" Version="3.3.4" />
<PackageVersion Include="Elsa.Studio.Core.BlazorWasm" Version="3.3.4" />
<PackageVersion Include="Elsa.Studio.Login.BlazorWasm" Version="3.3.4" />
<PackageVersion Include="FastEndpoints" Version="5.35.0" />
<PackageVersion Include="FastEndpoints.Security" Version="5.35.0" />
<PackageVersion Include="FastEndpoints.Swagger" Version="5.35.0" />
<PackageVersion Include="FluentMigrator" Version="6.2.0" />
<PackageVersion Include="FluentMigrator.Runner" Version="6.2.0" />
<PackageVersion Include="FluentStorage" Version="5.6.0" />
<PackageVersion Include="FluentStorage.Azure.Blobs" Version="5.3.0" />
<PackageVersion Include="Fluid.Core" Version="2.19.0" />
<PackageVersion Include="Fody" Version="6.9.2" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
<PackageVersion Include="Google.Protobuf" Version="3.30.0" />
<PackageVersion Include="Grpc.Net.Client" Version="2.70.0" />
<PackageVersion Include="Grpc.Tools" Version="2.71.0" />
<PackageVersion Include="Hangfire" Version="1.8.18" />
<PackageVersion Include="Hangfire.MemoryStorage" Version="1.8.1.1" />
<PackageVersion Include="Hangfire.PostgreSql" Version="1.20.10" />
<PackageVersion Include="Hangfire.Storage.SQLite" Version="0.4.2" />
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
<PackageVersion Include="IronCompress" Version="1.6.3" />
<PackageVersion Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageVersion Include="Jint" Version="4.2.1" />
<PackageVersion Include="LinqKit.Core" Version="1.2.8" />
<PackageVersion Include="MailKit" Version="4.11.0" />
<PackageVersion Include="MassTransit" Version="8.3.7" />
<PackageVersion Include="MassTransit.Azure.ServiceBus.Core" Version="8.3.7" />
<PackageVersion Include="MassTransit.Extensions.DependencyInjection" Version="7.3.1" />
<PackageVersion Include="MassTransit.RabbitMQ" Version="8.3.7" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.13.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.6" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.0.1" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.69.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.2.1" />
<PackageVersion Include="MongoDB.Driver.Core.Extensions.DiagnosticSources" Version="2.0.0" />
<PackageVersion Include="MongoDB.Driver.Extensions" Version="2.0.2" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="NuGet.Packaging" Version="6.13.2" />
<PackageVersion Include="NuGet.Protocol" Version="6.13.2" />
<PackageVersion Include="Nuke.Components" Version="9.0.4" />
<PackageVersion Include="Open.Linq.AsyncExtensions" Version="1.2.0" />
<PackageVersion Include="OpenTelemetry.AutoInstrumentation" Version="1.11.0" />
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.11.2" />
<PackageVersion Include="OpenTelemetry.Instrumentation.StackExchangeRedis" Version="1.11.0-beta.2" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="PolySharp" Version="1.15.0" />
<PackageVersion Include="Proto.Actor" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.CodeGen" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.AzureContainerApps" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.Kubernetes" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.TestProvider" Version="1.7.0" />
<PackageVersion Include="Proto.OpenTelemetry" Version="1.7.0" />
<PackageVersion Include="Proto.Persistence" Version="1.7.0" />
<PackageVersion Include="Proto.Persistence.Sqlite" Version="1.7.0" />
<PackageVersion Include="Proto.Persistence.SqlServer" Version="1.7.0" />
<PackageVersion Include="Proto.Remote" Version="1.7.0" />
<PackageVersion Include="pythonnet" Version="3.1.0-preview2024-09-06" />
<PackageVersion Include="Quartz.Extensions.Hosting" Version="3.14.0" />
<PackageVersion Include="Quartz.Serialization.Json" Version="3.14.0" />
<PackageVersion Include="Scrutor" Version="6.0.1" />
<PackageVersion Include="ShortGuid" Version="2.0.1" />
<PackageVersion Include="StackExchange.Redis" Version="2.8.31" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.Data.SqlClient" Version="4.9.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Linq.Dynamic.Core" Version="1.6.0.2" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="Testcontainers" Version="4.3.0" />
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.3.0" />
<PackageVersion Include="Testcontainers.RabbitMq" Version="4.3.0" />
<PackageVersion Include="Testcontainers.Redis" Version="4.3.0" />
<PackageVersion Include="ThrottleDebounce" Version="2.0.0" />
<PackageVersion Include="WebhooksCore" Version="0.0.1" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.abstractions" Version="2.0.3" />
<PackageVersion Include="xunit.extensibility.core" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
<PackageVersion Include="Yarp.ReverseProxy" Version="2.3.0" />
<PackageVersion Include="AspNetCore.Authentication.ApiKey" Version="8.0.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="8.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.14" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.14" />
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="8.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.14" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.14" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageVersion Include="MySql.Data" Version="9.1.0" />
<PackageVersion Include="Npgsql" Version="8.0.7" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="8.23.70" />
<PackageVersion Include="Polly" Version="8.5.2" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
<PackageVersion Include="Refit" Version="8.0.0" />
<PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0" />
<PackageVersion Include="System.Formats.Asn1" Version="8.0.2" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="8.10.0" />
<PackageVersion Include="Microsoft.Extensions.Resilience" Version="8.10.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.3" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.3" />
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.3" />
<PackageVersion Include="MySql.Data" Version="9.2.0" />
<PackageVersion Include="Npgsql" Version="9.0.3" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.60" />
<PackageVersion Include="Polly" Version="8.5.2" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.3.efcore.9.0.0" />
<PackageVersion Include="Refit" Version="8.0.0" />
<PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0" />
<PackageVersion Include="System.Formats.Asn1" Version="9.0.3" />
<PackageVersion Include="System.Text.Json" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.3.0" />
<PackageVersion Include="Microsoft.Extensions.Resilience" Version="9.3.0" />
</ItemGroup>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Antlr4.Runtime.Standard" Version="4.13.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.MySql" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.PostgreSQL" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.SQLite" Version="0.5.1" />
<PackageVersion Include="AppAny.Quartz.EntityFrameworkCore.Migrations.SqlServer" Version="0.5.1" />
<PackageVersion Include="AutoMapper" Version="14.0.0" PrivateAssets="All" />
<PackageVersion Include="Azure.Identity" Version="1.13.2" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.18.4" />
<PackageVersion Include="Azure.ResourceManager" Version="1.13.0" />
<PackageVersion Include="Azure.ResourceManager.AppContainers" Version="1.3.0" />
<PackageVersion Include="Azure.ResourceManager.Resources" Version="1.9.0" />
<PackageVersion Include="Azure.ResourceManager.ServiceBus" Version="1.1.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="Bogus" Version="35.6.2" />
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" PrivateAssets="All" />
<PackageVersion Include="Confluent.Kafka" Version="2.8.0" />
<PackageVersion Include="Confluent.SchemaRegistry.Serdes.Avro" Version="2.8.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" PrivateAssets="All" />
<PackageVersion Include="Cronos" Version="0.9.0" />
<PackageVersion Include="Dapper" Version="2.1.66" />
<PackageVersion Include="Datadog.Trace.Bundle" Version="3.12.0" />
<PackageVersion Include="DistributedLock.Core" Version="1.0.8" />
<PackageVersion Include="DistributedLock.FileSystem" Version="1.0.3" />
<PackageVersion Include="DistributedLock.Postgres" Version="1.3.0" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.3" />
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="8.17.1" />
<PackageVersion Include="Elsa.Studio" Version="3.3.4" />
<PackageVersion Include="Elsa.Studio.Agents" Version="3.3.4" />
<PackageVersion Include="Elsa.Studio.Core.BlazorWasm" Version="3.3.4" />
<PackageVersion Include="Elsa.Studio.Login.BlazorWasm" Version="3.3.4" />
<PackageVersion Include="FastEndpoints" Version="5.35.0" />
<PackageVersion Include="FastEndpoints.Security" Version="5.35.0" />
<PackageVersion Include="FastEndpoints.Swagger" Version="5.35.0" />
<PackageVersion Include="FluentMigrator" Version="6.2.0" />
<PackageVersion Include="FluentMigrator.Runner" Version="6.2.0" />
<PackageVersion Include="FluentStorage" Version="5.6.0" />
<PackageVersion Include="FluentStorage.Azure.Blobs" Version="5.3.0" />
<PackageVersion Include="Fluid.Core" Version="2.19.0" />
<PackageVersion Include="Fody" Version="6.9.2" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
<PackageVersion Include="Google.Protobuf" Version="3.30.0" />
<PackageVersion Include="Grpc.Net.Client" Version="2.70.0" />
<PackageVersion Include="Grpc.Tools" Version="2.71.0" />
<PackageVersion Include="Hangfire" Version="1.8.18" />
<PackageVersion Include="Hangfire.MemoryStorage" Version="1.8.1.1" />
<PackageVersion Include="Hangfire.PostgreSql" Version="1.20.10" />
<PackageVersion Include="Hangfire.Storage.SQLite" Version="0.4.2" />
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
<PackageVersion Include="IronCompress" Version="1.6.3" />
<PackageVersion Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageVersion Include="Jint" Version="4.2.1" />
<PackageVersion Include="LinqKit.Core" Version="1.2.8" />
<PackageVersion Include="MailKit" Version="4.11.0" />
<PackageVersion Include="MassTransit" Version="8.3.7" />
<PackageVersion Include="MassTransit.Azure.ServiceBus.Core" Version="8.3.7" />
<PackageVersion Include="MassTransit.Extensions.DependencyInjection" Version="7.3.1" />
<PackageVersion Include="MassTransit.RabbitMQ" Version="8.3.7" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.13.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.6" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.0.1" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.69.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.2.1" />
<PackageVersion Include="MongoDB.Driver.Core.Extensions.DiagnosticSources" Version="2.0.0" />
<PackageVersion Include="MongoDB.Driver.Extensions" Version="2.0.2" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="NuGet.Packaging" Version="6.13.2" />
<PackageVersion Include="NuGet.Protocol" Version="6.13.2" />
<PackageVersion Include="Nuke.Components" Version="9.0.4" />
<PackageVersion Include="Open.Linq.AsyncExtensions" Version="1.2.0" />
<PackageVersion Include="OpenTelemetry" Version="1.11.2" />
<PackageVersion Include="OpenTelemetry.AutoInstrumentation" Version="1.11.0" />
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.2" />
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.11.2" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.11.2" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.11.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.11.1" />
<PackageVersion Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.11.0-beta.2" />
<PackageVersion Include="OpenTelemetry.Instrumentation.StackExchangeRedis" Version="1.11.0-beta.2" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="PolySharp" Version="1.15.0" />
<PackageVersion Include="Proto.Actor" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.CodeGen" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.AzureContainerApps" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.Kubernetes" Version="1.7.0" />
<PackageVersion Include="Proto.Cluster.TestProvider" Version="1.7.0" />
<PackageVersion Include="Proto.OpenTelemetry" Version="1.7.0" />
<PackageVersion Include="Proto.Persistence" Version="1.7.0" />
<PackageVersion Include="Proto.Persistence.Sqlite" Version="1.7.0" />
<PackageVersion Include="Proto.Persistence.SqlServer" Version="1.7.0" />
<PackageVersion Include="Proto.Remote" Version="1.7.0" />
<PackageVersion Include="pythonnet" Version="3.1.0-preview2024-09-06" />
<PackageVersion Include="Quartz.Extensions.Hosting" Version="3.14.0" />
<PackageVersion Include="Quartz.Serialization.Json" Version="3.14.0" />
<PackageVersion Include="Scrutor" Version="6.0.1" />
<PackageVersion Include="ShortGuid" Version="2.0.1" />
<PackageVersion Include="StackExchange.Redis" Version="2.8.31" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.Data.SqlClient" Version="4.9.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Linq.Dynamic.Core" Version="1.6.0.2" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="Testcontainers" Version="4.3.0" />
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.3.0" />
<PackageVersion Include="Testcontainers.RabbitMq" Version="4.3.0" />
<PackageVersion Include="Testcontainers.Redis" Version="4.3.0" />
<PackageVersion Include="ThrottleDebounce" Version="2.0.0" />
<PackageVersion Include="WebhooksCore" Version="0.0.1" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.abstractions" Version="2.0.3" />
<PackageVersion Include="xunit.extensibility.core" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
<PackageVersion Include="Yarp.ReverseProxy" Version="2.3.0" />
<PackageVersion Include="AspNetCore.Authentication.ApiKey" Version="8.0.1" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.3" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.3" />
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.3" />
<PackageVersion Include="MySql.Data" Version="9.2.0" />
<PackageVersion Include="Npgsql" Version="9.0.3" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.60" />
<PackageVersion Include="Polly" Version="8.5.2" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.3.efcore.9.0.0" />
<PackageVersion Include="Refit" Version="8.0.0" />
<PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0" />
<PackageVersion Include="System.Formats.Asn1" Version="9.0.3" />
<PackageVersion Include="System.Text.Json" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.3.0" />
<PackageVersion Include="Microsoft.Extensions.Resilience" Version="9.3.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<!-- <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="8.0.2" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.14" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />-->
<!-- <PackageVersion Include="MySql.Data" Version="9.1.0" />-->
<!-- <PackageVersion Include="Npgsql" Version="8.0.7" />-->
<!-- <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />-->
<!-- <PackageVersion Include="Oracle.EntityFrameworkCore" Version="8.23.70" />-->
<!-- <PackageVersion Include="Polly" Version="8.5.2" />-->
<!-- <PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />-->
<!-- <PackageVersion Include="Refit" Version="8.0.0" />-->
<!-- <PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0" />-->
<!-- <PackageVersion Include="System.Formats.Asn1" Version="8.0.2" />-->
<!-- <PackageVersion Include="System.Text.Json" Version="8.0.5" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="8.10.0" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Resilience" Version="8.10.0" />-->
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<!-- <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.3" />-->
<!-- <PackageVersion Include="MySql.Data" Version="9.2.0" />-->
<!-- <PackageVersion Include="Npgsql" Version="9.0.3" />-->
<!-- <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />-->
<!-- <PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.60" />-->
<!-- <PackageVersion Include="Polly" Version="8.5.2" />-->
<!-- <PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.3.efcore.9.0.0" />-->
<!-- <PackageVersion Include="Refit" Version="8.0.0" />-->
<!-- <PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0" />-->
<!-- <PackageVersion Include="System.Formats.Asn1" Version="9.0.3" />-->
<!-- <PackageVersion Include="System.Text.Json" Version="9.0.3" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.3.0" />-->
<!-- <PackageVersion Include="Microsoft.Extensions.Resilience" Version="9.3.0" />-->
</ItemGroup>
</Project>

View file

@ -87,6 +87,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{986E54
docker\ElsaStudio.Dockerfile = docker\ElsaStudio.Dockerfile
docker\otel-collector-config.yaml = docker\otel-collector-config.yaml
docker\init-db-postgres.sh = docker\init-db-postgres.sh
docker\docker-compose-datadog+otel-collector.yml = docker\docker-compose-datadog+otel-collector.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Elasticsearch", "src\modules\Elsa.Elasticsearch\Elsa.Elasticsearch.csproj", "{3246883E-2FA7-4B4A-BDC5-99039A2869BC}"

View file

@ -10,7 +10,7 @@ COPY ./NuGet.Config ./
COPY *.props ./
# Restore packages.
RUN dotnet restore "./src/bundles/Elsa.Server.Web/Elsa.Server.Web.csproj"
RUN dotnet restore "./src/apps/Elsa.Server.Web/Elsa.Server.Web.csproj"
# Build and publish (UseAppHost=false creates platform independent binaries).
WORKDIR /source/src/bundles/Elsa.Server.Web

View file

@ -91,7 +91,7 @@ services:
datadog-agent:
image: datadog/agent:latest
environment:
DD_API_KEY: "<HIDDEN>"
DD_API_KEY: "<hidden>"
DD_SITE: "datadoghq.eu"
DD_HOSTNAME: "otel-collector"
DD_LOGS_ENABLED: "true"

View file

@ -59,6 +59,7 @@
<ItemGroup>
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Bogus" />
<PackageReference Include="Datadog.Trace.Bundle" />
<PackageReference Include="DistributedLock.Postgres" />
<PackageReference Include="DistributedLock.Redis" />
<PackageReference Include="FluentStorage.Azure.Blobs" />
@ -68,7 +69,13 @@
<PackageReference Include="DistributedLock.Redis" />
<PackageReference Include="FluentStorage.Azure.Blobs" />
<PackageReference Include="Hangfire.PostgreSql" />
<PackageReference Include="OpenTelemetry" />
<PackageReference Include="OpenTelemetry.Exporter.Console" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" />
<PackageReference Include="Proto.Cluster.Kubernetes" />
<PackageReference Include="Grpc.Net.Client" />
<PackageReference Include="Proto.Persistence.Sqlite" />

View file

@ -70,6 +70,10 @@ using Medallion.Threading.Redis;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Options;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Proto.Cluster.Kubernetes;
using Proto.Persistence.Sqlite;
@ -98,7 +102,7 @@ const bool useTenantsFromConfiguration = true;
const bool useSecrets = false;
const bool disableVariableWrappers = false;
const bool disableVariableCopying = false;
const bool useOtel = false;
const bool useManualOtelInstrumentation = true;
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
@ -125,14 +129,39 @@ var sqlDatabaseProvider = Enum.Parse<SqlDatabaseProvider>(configuration["Databas
TypeAliasRegistry.RegisterAlias("OrderReceivedProducerFactory", typeof(GenericProducerFactory<string, OrderReceived>));
TypeAliasRegistry.RegisterAlias("OrderReceivedConsumerFactory", typeof(GenericConsumerFactory<string, OrderReceived>));
if (useOtel)
if (useManualOtelInstrumentation)
{
// 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();
services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddService("elsa-workflows", serviceVersion: "3.4.0").AddTelemetrySdk())
.WithTracing(tracing =>
{
tracing
.AddSource("*")
.SetSampler(new AlwaysOnSampler())
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddSqlClientInstrumentation()
//.AddConsoleExporter()
.AddOtlpExporter()
;
})
.WithMetrics(metrics =>
{
metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
//.AddConsoleExporter()
.AddOtlpExporter()
;
});
// Enable OpenTelemetry Logging (optional)
builder.Logging.AddOpenTelemetry(options =>
{
options.IncludeFormattedMessage = true;
options.IncludeScopes = true;
options.ParseStateValues = true;
});
}
// Add Elsa services.
@ -223,7 +252,9 @@ services
ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString, new()
{ SchemaName = "ELSA"});
{
SchemaName = "ELSA"
});
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -271,7 +302,9 @@ services
ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString, new()
{ SchemaName = "ELSA"});
{
SchemaName = "ELSA"
});
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -324,7 +357,9 @@ services
ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString, new()
{ SchemaName = "ELSA"});
{
SchemaName = "ELSA"
});
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -476,7 +511,9 @@ services
ef.UsePostgreSql(cockroachDbConnectionString);
else if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString, new()
{ SchemaName = "ELSA"});
{
SchemaName = "ELSA"
});
else
ef.UseSqlite(sp => sp.GetSqliteConnectionString());
@ -579,7 +616,7 @@ services
}
});
}
if (useKafka)
{
elsa.UseKafka(kafka =>
@ -587,7 +624,7 @@ services
kafka.ConfigureOptions(options => configuration.GetSection("Kafka").Bind(options));
});
}
if (useSecrets)
{
elsa
@ -663,8 +700,11 @@ services
if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) ef.UsePostgreSql(postgresConnectionString);
if (sqlDatabaseProvider == SqlDatabaseProvider.Citus) ef.UsePostgreSql(citusConnectionString);
if (sqlDatabaseProvider == SqlDatabaseProvider.YugabyteDb) ef.UsePostgreSql(yugabyteDbConnectionString);
if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle) ef.UseOracle(oracleConnectionString, new()
{ SchemaName = "ELSA"});
if (sqlDatabaseProvider == SqlDatabaseProvider.Oracle)
ef.UseOracle(oracleConnectionString, new()
{
SchemaName = "ELSA"
});
#if !NET9_0
if (sqlDatabaseProvider == SqlDatabaseProvider.MySql)
ef.UseMySql(mySqlConnectionString);
@ -684,7 +724,7 @@ services
tenantHttpRouting.WithTenantHeader("X-Tenant-ID");
});
}
elsa.UseWebhooks(webhooks => webhooks.ConfigureSinks += options => builder.Configuration.GetSection("Webhooks").Bind(options));
elsa.InstallDropIns(options => options.DropInRootDirectory = Path.Combine(Directory.GetCurrentDirectory(), "App_Data", "DropIns"));
elsa.AddSwagger();

View file

@ -2,6 +2,7 @@
"Logging": {
"LogLevel": {
"Default": "Warning",
"OpenTelemetry": "Debug",
"Microsoft.Hosting.Lifetime": "Information",
"Elsa": "Information",
"Elsa.Workflows.Runtime.Middleware.Workflows.WorkflowHeartbeatMiddleware": "Debug"

View file

@ -5,5 +5,7 @@ namespace Elsa.OpenTelemetry.Abstractions;
public abstract class ErrorSpanHandlerBase : IErrorSpanHandler
{
public virtual float Order => 0;
public abstract bool CanHandle(ErrorSpanContext context);
public abstract void Handle(ErrorSpanContext context);
}

View file

@ -4,6 +4,8 @@ namespace Elsa.OpenTelemetry.Contracts;
public interface IErrorSpanHandler
{
float Order { get; }
bool CanHandle(ErrorSpanContext context);
void Handle(ErrorSpanContext context);
}

View file

@ -5,20 +5,12 @@ namespace Elsa.OpenTelemetry.Handlers;
public class DefaultErrorSpanHandler : ErrorSpanHandlerBase
{
public override float Order => 100000;
public override bool CanHandle(ErrorSpanContext context) => context.Exception != null;
public override void Handle(ErrorSpanContext context)
{
var span = context.Span;
var exception = context.Exception;
var errorMessage = string.IsNullOrWhiteSpace(exception?.Message) ? "Unknown error" : exception.Message;
span.SetTag("error", true);
span.SetTag("error.message", errorMessage);
if (exception != null)
{
span.SetTag("error.exceptionType", exception.GetType().FullName);
if (!string.IsNullOrEmpty(exception.StackTrace))
span.SetTag("error.stackTrace", exception.StackTrace);
}
context.Span.AddException(context.Exception!);
}
}

View file

@ -6,14 +6,18 @@ namespace Elsa.OpenTelemetry.Handlers;
public class FaultExceptionErrorSpanHandler : ErrorSpanHandlerBase
{
public override bool CanHandle(ErrorSpanContext context) => context.Exception is FaultException;
public override void Handle(ErrorSpanContext context)
{
if(context.Exception is not FaultException faultException)
return;
var faultException = (FaultException)context.Exception!;
var span = context.Span;
span.SetTag("error.code", faultException.Code);
span.SetTag("error.category", faultException.Category);
span.SetTag("error.faultType", faultException.Type);
var tags = new Dictionary<string, object?>
{
["exception.code"] = faultException.Code,
["exception.category"] = faultException.Category,
["exception.type"] = faultException.Type
};
span.AddException(context.Exception, new(tags.ToArray()));
}
}

View file

@ -1,5 +1,6 @@
using System.Diagnostics;
using Elsa.Common;
using Elsa.Extensions;
using Elsa.OpenTelemetry.Contracts;
using Elsa.OpenTelemetry.Helpers;
using Elsa.OpenTelemetry.Models;
@ -19,7 +20,7 @@ public class OpenTelemetryTracingActivityExecutionMiddleware(ActivityMiddlewareD
public async ValueTask InvokeAsync(ActivityExecutionContext context)
{
var activity = context.Activity;
using var span = ElsaOpenTelemetry.ActivitySource.StartActivity("ActivityExecution", ActivityKind.Internal, Activity.Current?.Context ?? default);
using var span = ElsaOpenTelemetry.ActivitySource.StartActivity($"execute activity {activity.Type}", ActivityKind.Internal, Activity.Current?.Context ?? default);
if (span == null)
{
@ -27,46 +28,47 @@ public class OpenTelemetryTracingActivityExecutionMiddleware(ActivityMiddlewareD
return;
}
span.SetTag("activity.nodeId", activity.NodeId);
span.SetTag("operation.name", "elsa.activity.execution");
span.SetTag("activity.id", activity.NodeId);
span.SetTag("activity.node.id", activity.NodeId);
span.SetTag("activity.type", activity.Type);
span.SetTag("activity.name", activity.Name);
span.SetTag("activityInstance.id", context.Id);
span.SetTag("activityExecution.startTimeUtc", span.StartTimeUtc);
span.SetTag("tenantId", context.WorkflowExecutionContext.Workflow.Identity.TenantId);
span.AddEvent(new("Executing", tags: CreateStatusTags(context)));
span.SetTag("activity.version", activity.Version);
span.SetTag("activity.instance.id", context.Id);
span.SetTag("activity.tenant.id", context.WorkflowExecutionContext.Workflow.Identity.TenantId);
var activityKind = context.ActivityDescriptor.Kind;
if (activityKind == Elsa.Workflows.ActivityKind.Job || (activityKind == Workflows.ActivityKind.Task && activity.GetRunAsynchronously()))
span.SetTag("span.type", "job");
span.AddEvent(new("executing"));
await next(context);
if (context.Status == ActivityStatus.Faulted)
{
span.AddEvent(new("Faulted", tags: CreateStatusTags(context)));
span.AddEvent(new("faulted"));
span.SetStatus(ActivityStatusCode.Error);
span.SetTag("activityInstance.hasIncidents", true);
var errorSpanHandlers = context.GetServices<IErrorSpanHandler>();
var errorSpanHandlerContext = new ErrorSpanContext(span, context.Exception);
var errorSpanHandler = context.GetServices<IErrorSpanHandler>()
.OrderBy(x => x.Order)
.FirstOrDefault(x => x.CanHandle(errorSpanHandlerContext));
foreach (var handler in errorSpanHandlers)
handler.Handle(errorSpanHandlerContext);
errorSpanHandler?.Handle(errorSpanHandlerContext);
}
else
else if (context.Status == ActivityStatus.Canceled)
{
span.AddEvent(new("Executed", tags: CreateStatusTags(context)));
span.SetStatus(ActivityStatusCode.Ok);
span.AddEvent(new("canceled"));
}
var now = systemClock.UtcNow;
span.SetTag("activityExecution.endTimeUtc", now);
span.SetTag("activityExecution.durationMs", (now - span.StartTimeUtc).TotalMilliseconds);
}
private ActivityTagsCollection CreateStatusTags(ActivityExecutionContext context)
{
return new(new Dictionary<string, object?>
else if (context.Status == ActivityStatus.Completed)
{
["activityInstance.status"] = context.Status.ToString()
});
span.AddEvent(new("completed"));
}
else if (context.Status == ActivityStatus.Pending)
{
span.AddEvent(new("pending"));
}
}
}

View file

@ -1,10 +1,13 @@
using System.Diagnostics;
using System.Runtime.InteropServices.Marshalling;
using System.Text.Json;
using Elsa.Common;
using Elsa.Expressions.Services;
using Elsa.Extensions;
using Elsa.OpenTelemetry.Helpers;
using Elsa.Workflows;
using Elsa.Workflows.Activities;
using Elsa.Workflows.Models;
using Elsa.Workflows.Pipelines.WorkflowExecution;
using Elsa.Workflows.Serialization.Converters;
using JetBrains.Annotations;
@ -19,14 +22,22 @@ namespace Elsa.OpenTelemetry.Middleware;
[UsedImplicitly]
public class OpenTelemetryTracingWorkflowExecutionMiddleware(WorkflowMiddlewareDelegate next, ISystemClock systemClock) : WorkflowExecutionMiddleware(next)
{
private readonly JsonSerializerOptions? _incidentSerializerOptions = new JsonSerializerOptions().WithConverters(new TypeJsonConverter(WellKnownTypeRegistry.CreateDefault()));
/// <inheritdoc />
public override async ValueTask InvokeAsync(WorkflowExecutionContext context)
{
var workflowInstanceId = context.Id;
var workflow = context.Workflow;
using var span = ElsaOpenTelemetry.ActivitySource.StartActivity("WorkflowExecution", ActivityKind.Internal, Activity.Current?.Context ?? default);
var startNewTrace = context.Properties.TryGetValue("StartNewTrace", out var startNewTraceValue) && (bool)startNewTraceValue;
var parentTraceContext = startNewTrace ? default : Activity.Current?.Context ?? default;
var linkedTraceContext = startNewTrace ? Activity.Current : null;
if(startNewTrace)
{
Activity.Current?.Stop();
Activity.Current = null;
}
using var span = ElsaOpenTelemetry.ActivitySource.StartActivity($"execute workflow {workflow.WorkflowMetadata.Name}", ActivityKind.Server, parentTraceContext);
if (span == null) // No listener is registered.
{
@ -34,61 +45,77 @@ public class OpenTelemetryTracingWorkflowExecutionMiddleware(WorkflowMiddlewareD
return;
}
span.SetTag("workflowInstance.id", workflowInstanceId);
span.SetTag("workflowDefinition.definitionId", workflow.Identity.DefinitionId);
span.SetTag("workflowDefinition.version", workflow.Identity.Version);
span.SetTag("workflowDefinition.name", workflow.WorkflowMetadata.Name);
span.SetTag("workflowExecution.startTimeUtc", span.StartTimeUtc);
span.SetTag("tenantId", workflow.Identity.TenantId);
if(context.TriggerActivityId != null)
if(startNewTrace)
{
var activity = context.FindActivityById(context.TriggerActivityId) ?? throw new Exception($"Trigger activity with ID {context.TriggerActivityId} not found. This should not happen.");
span.SetTag("workflowExecution.trigger.activityId", activity.Id);
span.SetTag("workflowExecution.trigger.activityName", activity.Name);
span.SetTag("workflowExecution.trigger.activityType", activity.Type);
if (linkedTraceContext != null)
span.AddLink(new(linkedTraceContext.Context));
}
span.AddEvent(new ActivityEvent("Executing", tags: CreateStatusTags(context)));
span.SetTag("operation.name", "elsa.workflow.execution");
span.SetTag("span.type", "workflow");
span.SetTag("workflow.definition.id", workflow.Identity.DefinitionId);
span.SetTag("workflow.definition.version", workflow.Identity.Version);
span.SetTag("workflow.definition.name", workflow.WorkflowMetadata.Name);
span.SetTag("workflow.definition.tenant.id", workflow.Identity.TenantId);
span.SetTag("workflow.instance.id", workflowInstanceId);
if (context.TriggerActivityId != null)
{
var activity = context.FindActivityById(context.TriggerActivityId) ?? throw new($"Trigger activity with ID {context.TriggerActivityId} not found. This should not happen.");
span.SetTag("workflow.trigger.activity.id", activity.Id);
span.SetTag("workflow.trigger.activity.name", activity.Name);
span.SetTag("workflow.trigger.activity.type", activity.Type);
span.SetTag("workflow.trigger.activity.version", activity.Version);
}
span.AddEvent(new("executing"));
await Next(context);
if (context.SubStatus == WorkflowSubStatus.Faulted)
{
span.AddEvent(new ActivityEvent("Faulted", tags: CreateStatusTags(context)));
span.SetStatus(ActivityStatusCode.Error);
span.SetTag("error", true);
span.AddEvent(new("faulted"));
span.SetStatus(ActivityStatusCode.Error, "The workflow entered the Faulted state. See incidents for details.");
}
else
else if (context.SubStatus == WorkflowSubStatus.Finished)
{
span.AddEvent(new ActivityEvent("Executed", tags: CreateStatusTags(context)));
span.SetStatus(ActivityStatusCode.Ok);
span.AddEvent(new("finished"));
}
if(context.Incidents.Any())
else if (context.SubStatus == WorkflowSubStatus.Cancelled)
{
span.SetStatus(ActivityStatusCode.Error);
span.SetTag("workflowInstance.hasIncidents", true);
span.SetTag("error", true);
span.AddEvent(new("canceled"));
}
else if (context.SubStatus == WorkflowSubStatus.Suspended)
{
span.AddEvent(new("suspended"));
}
if (context.Incidents.Count > 0)
span.SetTag("error.message", JsonSerializer.Serialize(context.Incidents, _incidentSerializerOptions));
}
if (!string.IsNullOrWhiteSpace(context.CorrelationId))
span.SetTag("workflowInstance.correlationId", context.CorrelationId);
var now = systemClock.UtcNow;
span.SetTag("workflowExecution.endTimeUtc", now);
span.SetTag("workflowExecution.durationMs", (now - span.StartTimeUtc).TotalMilliseconds);
}
private ActivityTagsCollection CreateStatusTags(WorkflowExecutionContext context)
{
return new ActivityTagsCollection(new Dictionary<string, object?>
if (context.Incidents.Any())
{
["workflowInstance.status"] = context.Status.ToString(),
["workflowInstance.subStatus"] = context.SubStatus.ToString()
span.SetTag("workflow.incidents.count", context.Incidents.Count);
foreach (var incident in context.Incidents)
span.AddEvent(new("incident", incident.Timestamp, CreateIncidentTags(incident)));
}
if (!string.IsNullOrWhiteSpace(context.CorrelationId))
span.SetTag("workflow.correlation_id", context.CorrelationId);
}
private ActivityTagsCollection CreateIncidentTags(ActivityIncident incident)
{
var tags = new ActivityTagsCollection(new Dictionary<string, object?>
{
["incident.message"] = incident.Message,
});
if (incident.Exception != null)
{
tags["incident.exception.message"] = incident.Exception.Message;
tags["incident.exception.stackTrace"] = incident.Exception.StackTrace;
tags["incident.exception.type"] = incident.Exception.Type.FullName;
}
return tags;
}
}

View file

@ -78,6 +78,12 @@ public class BulkDispatchWorkflows : Activity
Description = "Wait for the dispatched workflows to complete before completing this activity.",
DefaultValue = true)]
public Input<bool> WaitForCompletion { get; set; } = new(true);
/// <summary>
/// Indicates whether a new trace context should be started for the workflow execution.
/// </summary>
[Input(Description = "Start a new trace context when using Open Telemetry.", Category = "Open Telemetry")]
public Input<bool> StartNewTrace { get; set; }
/// <summary>
/// The channel to dispatch the workflow to.
@ -104,12 +110,13 @@ public class BulkDispatchWorkflows : Activity
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
var waitForCompletion = WaitForCompletion.GetOrDefault(context);
var startNewTrace = StartNewTrace.GetOrDefault(context);
var items = await context.GetItemSource<object>(Items).ToListAsync(context.CancellationToken);
var count = items.Count;
// Dispatch the child workflows.
foreach (var item in items)
await DispatchChildWorkflowAsync(context, item, waitForCompletion);
await DispatchChildWorkflowAsync(context, item, waitForCompletion, startNewTrace);
// Store the number of dispatched instances for tracking.
context.SetProperty(DispatchedInstancesCountKey, count);
@ -139,7 +146,7 @@ public class BulkDispatchWorkflows : Activity
}
}
private async ValueTask<string> DispatchChildWorkflowAsync(ActivityExecutionContext context, object item, bool waitForCompletion)
private async ValueTask<string> DispatchChildWorkflowAsync(ActivityExecutionContext context, object item, bool waitForCompletion, bool startNewTrace)
{
var workflowDefinitionId = WorkflowDefinitionId.Get(context);
var workflowDefinitionService = context.GetRequiredService<IWorkflowDefinitionService>();
@ -157,8 +164,8 @@ public class BulkDispatchWorkflows : Activity
["ParentInstanceId"] = parentInstanceId
};
if (waitForCompletion)
properties["WaitForCompletion"] = true;
if (waitForCompletion) properties["WaitForCompletion"] = true;
if (startNewTrace) properties["StartNewTrace"] = true;
var itemDictionary = new Dictionary<string, object>
{

View file

@ -55,6 +55,12 @@ public class DispatchWorkflow : Activity<object>
[Input(Description = "Wait for the child workflow to complete before completing this activity.")]
public Input<bool> WaitForCompletion { get; set; } = null!;
/// <summary>
/// Indicates whether a new trace context should be started for the workflow execution.
/// </summary>
[Input(Description = "Start a new trace context when using Open Telemetry.", Category = "Open Telemetry")]
public Input<bool> StartNewTrace { get; set; }
/// <summary>
/// The channel to dispatch the workflow to.
/// </summary>
@ -103,16 +109,17 @@ public class DispatchWorkflow : Activity<object>
var input = Input.GetOrDefault(context) ?? new Dictionary<string, object>();
var channelName = ChannelName.GetOrDefault(context);
var startNewTrace = StartNewTrace.GetOrDefault(context);
var parentInstanceId = context.WorkflowExecutionContext.Id;
var properties = new Dictionary<string, object>
{
["ParentInstanceId"] = parentInstanceId
["ParentInstanceId"] = parentInstanceId,
};
// If we need to wait for the child workflow to complete, set the property. This will be used by the ResumeDispatchWorkflowActivity handler.
if (waitForCompletion)
properties["WaitForCompletion"] = true;
if (waitForCompletion) properties["WaitForCompletion"] = true;
if (startNewTrace) properties["StartNewTrace"] = true;
input["ParentInstanceId"] = parentInstanceId;
var correlationId = CorrelationId.GetOrDefault(context);

View file

@ -22,7 +22,7 @@ public class BackgroundWorkflowDispatcher : IWorkflowDispatcher
}
/// <inheritdoc />
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchWorkflowDefinitionRequest request, DispatchWorkflowOptions? options = default, CancellationToken cancellationToken = default)
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchWorkflowDefinitionRequest request, DispatchWorkflowOptions? options = null, CancellationToken cancellationToken = default)
{
var command = new DispatchWorkflowDefinitionCommand(request.DefinitionVersionId)
{
@ -38,7 +38,7 @@ public class BackgroundWorkflowDispatcher : IWorkflowDispatcher
}
/// <inheritdoc />
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchWorkflowInstanceRequest request, DispatchWorkflowOptions? options = default, CancellationToken cancellationToken = default)
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchWorkflowInstanceRequest request, DispatchWorkflowOptions? options = null, CancellationToken cancellationToken = default)
{
var command = new DispatchWorkflowInstanceCommand(request.InstanceId){
BookmarkId = request.BookmarkId,
@ -52,7 +52,7 @@ public class BackgroundWorkflowDispatcher : IWorkflowDispatcher
}
/// <inheritdoc />
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchTriggerWorkflowsRequest request, DispatchWorkflowOptions? options = default, CancellationToken cancellationToken = default)
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchTriggerWorkflowsRequest request, DispatchWorkflowOptions? options = null, CancellationToken cancellationToken = default)
{
var command = new DispatchTriggerWorkflowsCommand(request.ActivityTypeName, request.BookmarkPayload)
{
@ -67,7 +67,7 @@ public class BackgroundWorkflowDispatcher : IWorkflowDispatcher
}
/// <inheritdoc />
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchResumeWorkflowsRequest request, DispatchWorkflowOptions? options = default, CancellationToken cancellationToken = default)
public async Task<DispatchWorkflowResponse> DispatchAsync(DispatchResumeWorkflowsRequest request, DispatchWorkflowOptions? options = null, CancellationToken cancellationToken = default)
{
var command = new DispatchResumeWorkflowsCommand(request.ActivityTypeName, request.BookmarkPayload)
{