From e28b11ebe6f2994fca5a30bdc23d9c3fa72ae6fd Mon Sep 17 00:00:00 2001 From: Konstantin Savosteev Date: Wed, 29 Apr 2026 09:25:03 +0200 Subject: [PATCH 1/4] feat: switch to Activityi telemetry --- .../GraphQLHttpMiddlewareWithLogs.cs | 70 ++++++++----------- ...ePlainCoreXapiGraphQLTelemetryProcessor.cs | 40 +++++------ .../VirtoCommerce.Xapi.Core.csproj | 6 +- .../VirtoCommerce.Xapi.Data.csproj | 4 +- src/VirtoCommerce.Xapi.Web/Module.cs | 7 +- src/VirtoCommerce.Xapi.Web/module.manifest | 4 +- 6 files changed, 58 insertions(+), 73 deletions(-) diff --git a/src/VirtoCommerce.Xapi.Core/Infrastructure/GraphQLHttpMiddlewareWithLogs.cs b/src/VirtoCommerce.Xapi.Core/Infrastructure/GraphQLHttpMiddlewareWithLogs.cs index 061f060..32126a0 100644 --- a/src/VirtoCommerce.Xapi.Core/Infrastructure/GraphQLHttpMiddlewareWithLogs.cs +++ b/src/VirtoCommerce.Xapi.Core/Infrastructure/GraphQLHttpMiddlewareWithLogs.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Net.WebSockets; using System.Threading.Tasks; @@ -7,10 +8,7 @@ using GraphQL.Server.Transports.AspNetCore; using GraphQL.Transport; using GraphQL.Types; -using Microsoft.ApplicationInsights; -using Microsoft.ApplicationInsights.DataContracts; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -18,11 +16,15 @@ namespace VirtoCommerce.Xapi.Core.Infrastructure { + /// + /// Relies solely on telemetry + /// instead of direct Microsoft.ApplicationInsights types. Any configured + /// OpenTelemetry exporter (Application Insights, OTLP, etc.) picks up the data automatically. + /// public class GraphQLHttpMiddlewareWithLogs : GraphQLHttpMiddleware where TSchema : ISchema { private readonly ILogger _logger; - private readonly TelemetryClient _telemetryClient; public GraphQLHttpMiddlewareWithLogs( RequestDelegate next, @@ -31,58 +33,46 @@ public GraphQLHttpMiddlewareWithLogs( IServiceScopeFactory serviceScopeFactory, GraphQLHttpMiddlewareOptions options, IHostApplicationLifetime hostApplicationLifetime, - ILogger> logger, - TelemetryClient telemetryClient = null) + ILogger> logger) : base(next, serializer, documentExecuter, serviceScopeFactory, options, hostApplicationLifetime) { _logger = logger; - _telemetryClient = telemetryClient; } - protected override async Task ExecuteRequestAsync(HttpContext context, GraphQLRequest request, IServiceProvider serviceProvider, IDictionary userContext) + protected override async Task ExecuteRequestAsync( + HttpContext context, + GraphQLRequest request, + IServiceProvider serviceProvider, + IDictionary userContext) { - // process Playground schema introspection queries without AppInsights logging - if (_telemetryClient is null || request?.OperationName == "IntrospectionQuery") + // skip Playground schema introspection queries + if (request?.OperationName == "IntrospectionQuery") { return await base.ExecuteRequestAsync(context, request, serviceProvider, userContext); } - // prepare AppInsights telemetry - var appInsightsOperationName = $"POST graphql/{request?.OperationName}"; - - var requestTelemetry = new RequestTelemetry + // enrich the server activity created by AspNetCore OTel instrumentation + var activity = Activity.Current; + if (activity != null && request?.OperationName.IsNullOrEmpty() == false) { - Name = appInsightsOperationName, - Url = new Uri(context.Request.GetEncodedUrl()), - }; - - //Replace W3C Trace Context id generation https://www.w3.org/TR/trace-context/ to unique value - requestTelemetry.Context.Operation.Id = Guid.NewGuid().ToString("N"); - requestTelemetry.Context.Operation.Name = appInsightsOperationName; - requestTelemetry.Properties["Type"] = "GraphQL"; - - using var operation = _telemetryClient.StartOperation(requestTelemetry); + activity.DisplayName = $"POST graphql/{request.OperationName}"; + activity.SetTag("url.path", $"graphql/{request.OperationName}"); + activity.SetTag("graphql.type", "GraphQL"); + } - // execute GraphQL query var result = await base.ExecuteRequestAsync(context, request, serviceProvider, userContext); - requestTelemetry.Success = result.Errors.IsNullOrEmpty(); - if (requestTelemetry.Success != true) + if (!result.Errors.IsNullOrEmpty() && activity != null) { - // pass an error response code to trigger AppInsights operation failure state - requestTelemetry.ResponseCode = "500"; - - Exception exception = result.Errors?.Count > 1 - ? new AggregateException(result.Errors) - : result.Errors?.FirstOrDefault(); - - var exceptionTelemetry = new ExceptionTelemetry(exception); - - // link exception with the operation - exceptionTelemetry.Context.Operation.ParentId = requestTelemetry.Context.Operation.Id; - exceptionTelemetry.Context.Operation.Name = appInsightsOperationName; + var exception = result.Errors.Count > 1 + ? (Exception)new AggregateException(result.Errors) + : result.Errors.FirstOrDefault(); - _telemetryClient.TrackException(exceptionTelemetry); + activity.SetStatus(ActivityStatusCode.Error, exception?.Message); + if (exception != null) + { + activity.AddException(exception); + } } return result; diff --git a/src/VirtoCommerce.Xapi.Core/Infrastructure/IgnorePlainCoreXapiGraphQLTelemetryProcessor.cs b/src/VirtoCommerce.Xapi.Core/Infrastructure/IgnorePlainCoreXapiGraphQLTelemetryProcessor.cs index 19f32d0..041b1c8 100644 --- a/src/VirtoCommerce.Xapi.Core/Infrastructure/IgnorePlainCoreXapiGraphQLTelemetryProcessor.cs +++ b/src/VirtoCommerce.Xapi.Core/Infrastructure/IgnorePlainCoreXapiGraphQLTelemetryProcessor.cs @@ -1,31 +1,25 @@ -using Microsoft.ApplicationInsights.Channel; -using Microsoft.ApplicationInsights.DataContracts; -using Microsoft.ApplicationInsights.Extensibility; +using System.Diagnostics; +using OpenTelemetry; using VirtoCommerce.Platform.Core.Common; -namespace VirtoCommerce.Xapi.Core.Infrastructure -{ - /// - /// AppInsights telemetry processor that skips default Graphql queries - /// - public class IgnorePlainCoreXapiGraphQLTelemetryProcessor : ITelemetryProcessor - { - private ITelemetryProcessor Next { get; set; } - public IgnorePlainCoreXapiGraphQLTelemetryProcessor(ITelemetryProcessor next) - { - Next = next; - } +namespace VirtoCommerce.ApplicationInsights.Data.Telemetry; - public void Process(ITelemetry item) +/// +/// OpenTelemetry processor that suppresses activities whose urls match GraphQL related path but +/// graphql.type tag is empty meaning this activity was not generated by GraphQLHttpMiddlewareWithLogs. +/// Clearing the flag prevents the activity +/// from being exported to Application Insights. +/// +public class IgnorePlainCoreXapiGraphQLTelemetryProcessor : BaseProcessor +{ + public override void OnEnd(Activity activity) + { + var urlPath = activity?.GetTagItem("url.path")?.ToString(); + var graphQlTag = activity?.GetTagItem("graphql.type"); + if (urlPath != null && urlPath.ContainsIgnoreCase("/graphql") && graphQlTag == null) { - // skip plain "POST /graphql" (without operation name) requests to reduce AppInsights telemetry flood - if (item is RequestTelemetry request && request.Name?.EqualsIgnoreCase("POST /graphql") == true) - { - return; - } - - Next.Process(item); + activity.ActivityTraceFlags &= ~ActivityTraceFlags.Recorded; } } } diff --git a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj index 5b43fce..fbcc7a0 100644 --- a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj +++ b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj @@ -1,4 +1,4 @@ - + Experiene API functionality net10.0 @@ -22,13 +22,13 @@ - - + + diff --git a/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj b/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj index 297aef4..401d1e4 100644 --- a/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj +++ b/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj @@ -1,4 +1,4 @@ - + net10.0 @@ -10,7 +10,7 @@ - + diff --git a/src/VirtoCommerce.Xapi.Web/Module.cs b/src/VirtoCommerce.Xapi.Web/Module.cs index 4f7faa2..c3180f5 100644 --- a/src/VirtoCommerce.Xapi.Web/Module.cs +++ b/src/VirtoCommerce.Xapi.Web/Module.cs @@ -8,15 +8,16 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using OpenTelemetry.Trace; +using VirtoCommerce.ApplicationInsights.Data.Telemetry; using VirtoCommerce.Platform.Core.DeveloperTools; using VirtoCommerce.Platform.Core.Modularity; using VirtoCommerce.Platform.Core.Settings; using VirtoCommerce.StoreModule.Core.Model; using VirtoCommerce.Xapi.Core; using VirtoCommerce.Xapi.Core.Extensions; -using VirtoCommerce.Xapi.Core.Infrastructure; using VirtoCommerce.Xapi.Core.Infrastructure.Validation; using VirtoCommerce.Xapi.Core.Models; using VirtoCommerce.Xapi.Core.Subscriptions; @@ -51,7 +52,7 @@ private bool IsComplexityValidationEnabled public void Initialize(IServiceCollection serviceCollection) { - serviceCollection.AddApplicationInsightsTelemetryProcessor(); + serviceCollection.AddOpenTelemetry().WithTracing(t => t.AddProcessor(new IgnorePlainCoreXapiGraphQLTelemetryProcessor())); #pragma warning disable CS0618 // Type or member is obsolete // Use legacy type naming for backward compatibility diff --git a/src/VirtoCommerce.Xapi.Web/module.manifest b/src/VirtoCommerce.Xapi.Web/module.manifest index 9ef55f8..81be3e2 100644 --- a/src/VirtoCommerce.Xapi.Web/module.manifest +++ b/src/VirtoCommerce.Xapi.Web/module.manifest @@ -4,9 +4,9 @@ 3.1007.0 - 3.1000.0 + 3.1020.0 - + From 8a0cd221eb5ae4640a75bb6356484ecdd6bdb86e Mon Sep 17 00:00:00 2001 From: Konstantin Savosteev Date: Wed, 17 Jun 2026 16:00:12 +0200 Subject: [PATCH 2/4] fix: change csproj (local dep) --- .../VirtoCommerce.Xapi.Core.csproj | 19 +++++++++---------- src/VirtoCommerce.Xapi.Web/module.manifest | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj index c8a0eab..009dcd8 100644 --- a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj +++ b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj @@ -1,4 +1,4 @@ - + Experiene API functionality net10.0 @@ -21,19 +21,18 @@ + - - + - + - - - - + + + + - - \ No newline at end of file + diff --git a/src/VirtoCommerce.Xapi.Web/module.manifest b/src/VirtoCommerce.Xapi.Web/module.manifest index d93350c..2575c5b 100644 --- a/src/VirtoCommerce.Xapi.Web/module.manifest +++ b/src/VirtoCommerce.Xapi.Web/module.manifest @@ -6,7 +6,7 @@ 3.1027.0 - + From 37f42b5d7e3a790d5a5d885a4b7f4915a218d0b7 Mon Sep 17 00:00:00 2001 From: Konstantin Savosteev Date: Wed, 17 Jun 2026 18:17:50 +0200 Subject: [PATCH 3/4] feat: update dependency --- src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj | 2 +- src/VirtoCommerce.Xapi.Web/module.manifest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj index 009dcd8..bc60727 100644 --- a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj +++ b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj @@ -27,7 +27,7 @@ - + diff --git a/src/VirtoCommerce.Xapi.Web/module.manifest b/src/VirtoCommerce.Xapi.Web/module.manifest index 2575c5b..26ae724 100644 --- a/src/VirtoCommerce.Xapi.Web/module.manifest +++ b/src/VirtoCommerce.Xapi.Web/module.manifest @@ -6,7 +6,7 @@ 3.1027.0 - + From c845be8c1e125a5e121204be90f2c335fa1b4db8 Mon Sep 17 00:00:00 2001 From: Konstantin Savosteev Date: Fri, 19 Jun 2026 15:06:57 +0200 Subject: [PATCH 4/4] feat: update platform dependency --- src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj | 2 +- src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj | 2 +- src/VirtoCommerce.Xapi.Web/module.manifest | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj index bc60727..7e9120a 100644 --- a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj +++ b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj @@ -28,7 +28,7 @@ - + diff --git a/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj b/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj index 3da32c6..8b4ff46 100644 --- a/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj +++ b/src/VirtoCommerce.Xapi.Data/VirtoCommerce.Xapi.Data.csproj @@ -9,7 +9,7 @@ snupkg - + diff --git a/src/VirtoCommerce.Xapi.Web/module.manifest b/src/VirtoCommerce.Xapi.Web/module.manifest index 26ae724..8a461c7 100644 --- a/src/VirtoCommerce.Xapi.Web/module.manifest +++ b/src/VirtoCommerce.Xapi.Web/module.manifest @@ -4,7 +4,7 @@ 3.1012.0 - 3.1027.0 + 3.1039.0-alpha.13307-vcst-4717