From 1de86a5c99a1b0cce7d38440e397f2e5e6ad08d2 Mon Sep 17 00:00:00 2001
From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com>
Date: Mon, 14 Sep 2026 18:30:49 +0000
Subject: [PATCH 1/4] Give every batch item its own request span
A GraphQL over HTTP batch shares a single transport span across items that
execute concurrently, so folding each item's operation details into that
shared span produced interleaved, meaningless tags. Mark the transport span
as a batch when a batch or operation batch request starts, and have the
execution listeners fall through to a dedicated request span per item
instead of reusing it.
---
.../Spans/Http/ExecuteHttpRequestSpan.cs | 9 +
.../ActivityExecutionDiagnosticListener.cs | 10 +-
.../ActivityServerDiagnosticListener.cs | 20 +-
.../ActivityServerDiagnosticListenerTests.cs | 31 +
...ery_Item_Its_Own_Request_Span_Default.snap | 353 ++++++++++++
..._Its_Own_Request_Span_Default_NET11_0.snap | 353 ++++++++++++
...ctivityExecutionDiagnosticEventListener.cs | 10 +-
.../FusionActivityServerDiagnosticListener.cs | 20 +-
...onActivityServerDiagnosticListenerTests.cs | 41 ++
...ery_Item_Its_Own_Request_Span_Default.snap | 533 ++++++++++++++++++
..._Its_Own_Request_Span_Default_NET11_0.snap | 533 ++++++++++++++++++
11 files changed, 1897 insertions(+), 16 deletions(-)
create mode 100644 src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
create mode 100644 src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
create mode 100644 src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
create mode 100644 src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
diff --git a/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs b/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
index a0a227fab65..d47b8df5110 100644
--- a/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
+++ b/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
@@ -61,6 +61,15 @@ internal sealed class ExecuteHttpRequestSpan(
return new ExecuteHttpRequestSpan(activity, httpContext, kind, enricher, options);
}
+ ///
+ /// Specifies whether this span covers more than one GraphQL request. The items of a
+ /// batch execute concurrently, so they must not write their own operation details
+ /// onto this shared span.
+ ///
+ public bool IsBatch { get; private set; }
+
+ public void MarkAsBatch() => IsBatch = true;
+
public void SetSingleRequestDetails(GraphQLRequest request)
{
Activity.SetTag(GraphQL.Http.Request.Type, GraphQL.Http.Request.Types.Single);
diff --git a/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs b/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs
index a4d945214ba..8b57dc14ee0 100644
--- a/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs
+++ b/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs
@@ -31,10 +31,12 @@ public override IDisposable ExecuteRequest(RequestContext context)
return EmptyScope;
}
- // A GraphQL over HTTP request reuses the transport span as the root request
- // span instead of emitting a second one. A transport that has no span of its
- // own, like a WebSocket session, falls through to a dedicated request span.
- if (httpContext.Features.Get() is { } httpRequestSpan)
+ // A single GraphQL over HTTP request reuses the transport span as the root
+ // request span instead of emitting a second one. A batch shares one transport
+ // span across concurrently executing items, and a transport without a span of
+ // its own, like a WebSocket session, has nothing to reuse, so both fall
+ // through to a dedicated request span.
+ if (httpContext.Features.Get() is { IsBatch: false } httpRequestSpan)
{
httpContextActivity = httpRequestSpan.Activity;
}
diff --git a/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityServerDiagnosticListener.cs b/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityServerDiagnosticListener.cs
index c81ef74843e..604d900eb8d 100644
--- a/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityServerDiagnosticListener.cs
+++ b/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityServerDiagnosticListener.cs
@@ -43,8 +43,14 @@ public override void StartSingleRequest(HttpContext context, GraphQLRequest requ
public override void StartBatchRequest(HttpContext context, IReadOnlyList batch)
{
- if (options.IncludeRequestDetails
- && context.Features.Get() is { } span)
+ if (context.Features.Get() is not { } span)
+ {
+ return;
+ }
+
+ span.MarkAsBatch();
+
+ if (options.IncludeRequestDetails)
{
span.SetBatchRequestDetails(batch);
}
@@ -55,8 +61,14 @@ public override void StartOperationBatchRequest(
GraphQLRequest request,
IReadOnlyList operations)
{
- if (options.IncludeRequestDetails
- && context.Features.Get() is { } span)
+ if (context.Features.Get() is not { } span)
+ {
+ return;
+ }
+
+ span.MarkAsBatch();
+
+ if (options.IncludeRequestDetails)
{
span.SetOperationBatchRequestDetails(request, operations);
}
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
index f281240ff33..ca115135690 100644
--- a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
@@ -154,6 +154,37 @@ public async Task Http_Get_PersistedOperationEndpoint_GetHeroName_Default()
}
}
+ [Fact]
+ public async Task Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default()
+ {
+ using (CaptureActivities(out var activities))
+ {
+ // arrange
+ // batch items execute concurrently and share one transport span, so with the
+ // default scopes they must not fold their operation details into it
+ using var server = CreateInstrumentedServer();
+ using var client = server.CreateClient();
+ client.BaseAddress = new Uri("http://localhost:5000");
+
+ const string batch =
+ """
+ [{"query":"query A { hero { name } }"},
+ {"query":"query B { human(id: \"1000\") { name } }"}]
+ """;
+
+ // act
+ using var content = new StringContent(batch, Encoding.UTF8, "application/json");
+ using var response = await client.PostAsync(
+ "/graphql",
+ content,
+ TestContext.Current.CancellationToken);
+ await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken);
+
+ // assert
+ activities.MatchSnapshot(Postfix([NET11_0]));
+ }
+ }
+
[Fact]
public async Task Http_Post_Variables_Are_Not_Automatically_Added_To_Activities()
{
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
new file mode 100644
index 00000000000..7c36f7d0ad5
--- /dev/null
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
@@ -0,0 +1,353 @@
+{
+ "source": {
+ "name": "HotChocolate.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "batch"
+ },
+ {
+ "Key": "graphql.http.request[0].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
+ }
+ },
+ {
+ "Key": "graphql.http.request[0].query.hash",
+ "Value": {
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "659bc020d413f3107839ff0cbbaf3440"
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.hash",
+ "Value": {
+ "Value": "659bc020d413f3107839ff0cbbaf3440",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:dbfe187a49b8b785c6471ccb9bb8c5e4"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:dbfe187a49b8b785c6471ccb9bb8c5e4"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:dbfe187a49b8b785c6471ccb9bb8c5e4"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.hero",
+ "DisplayName": "Query.hero",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.hero"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:659bc020d413f3107839ff0cbbaf3440"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:659bc020d413f3107839ff0cbbaf3440"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:659bc020d413f3107839ff0cbbaf3440"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.human",
+ "DisplayName": "Query.human",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.human"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
new file mode 100644
index 00000000000..8590ed1873d
--- /dev/null
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
@@ -0,0 +1,353 @@
+{
+ "source": {
+ "name": "HotChocolate.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "batch"
+ },
+ {
+ "Key": "graphql.http.request[0].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
+ }
+ },
+ {
+ "Key": "graphql.http.request[0].query.hash",
+ "Value": {
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "659bc020d413f3107839ff0cbbaf3440"
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.hash",
+ "Value": {
+ "Value": "659bc020d413f3107839ff0cbbaf3440",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:dbfe187a49b8b785c6471ccb9bb8c5e4"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:dbfe187a49b8b785c6471ccb9bb8c5e4"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:dbfe187a49b8b785c6471ccb9bb8c5e4"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.hero",
+ "DisplayName": "Query.hero",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.hero"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:659bc020d413f3107839ff0cbbaf3440"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:659bc020d413f3107839ff0cbbaf3440"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:659bc020d413f3107839ff0cbbaf3440"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.human",
+ "DisplayName": "Query.human",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.human"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs b/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs
index 3c8e42d88b7..91ebb177f10 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs
@@ -27,10 +27,12 @@ public override IDisposable ExecuteRequest(RequestContext context)
return EmptyScope;
}
- // A GraphQL over HTTP request reuses the transport span as the root request
- // span instead of emitting a second one. A transport that has no span of its
- // own, like a WebSocket session, falls through to a dedicated request span.
- if (httpContext.Features.Get() is { } httpRequestSpan)
+ // A single GraphQL over HTTP request reuses the transport span as the root
+ // request span instead of emitting a second one. A batch shares one transport
+ // span across concurrently executing items, and a transport without a span of
+ // its own, like a WebSocket session, has nothing to reuse, so both fall
+ // through to a dedicated request span.
+ if (httpContext.Features.Get() is { IsBatch: false } httpRequestSpan)
{
httpContextActivity = httpRequestSpan.Activity;
}
diff --git a/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityServerDiagnosticListener.cs b/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityServerDiagnosticListener.cs
index 6ed4d2e2ce3..0d6576415be 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityServerDiagnosticListener.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityServerDiagnosticListener.cs
@@ -44,8 +44,14 @@ public override void StartSingleRequest(HttpContext context, GraphQLRequest requ
public override void StartBatchRequest(HttpContext context, IReadOnlyList batch)
{
- if (options.IncludeRequestDetails
- && context.Features.Get() is { } span)
+ if (context.Features.Get() is not { } span)
+ {
+ return;
+ }
+
+ span.MarkAsBatch();
+
+ if (options.IncludeRequestDetails)
{
span.SetBatchRequestDetails(batch);
}
@@ -56,8 +62,14 @@ public override void StartOperationBatchRequest(
GraphQLRequest request,
IReadOnlyList operations)
{
- if (options.IncludeRequestDetails
- && context.Features.Get() is { } span)
+ if (context.Features.Get() is not { } span)
+ {
+ return;
+ }
+
+ span.MarkAsBatch();
+
+ if (options.IncludeRequestDetails)
{
span.SetOperationBatchRequestDetails(request, operations);
}
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
index 5a087f29163..5f476177373 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
@@ -3,6 +3,7 @@
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
+using HotChocolate.AspNetCore;
using HotChocolate.AspNetCore.Subscriptions;
using HotChocolate.AspNetCore.Subscriptions.Protocols;
using HotChocolate.Diagnostics;
@@ -88,6 +89,46 @@ public async Task Http_Post_Single_Request()
}
}
+ [Fact]
+ public async Task Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default()
+ {
+ using (CaptureActivities(out var activities))
+ {
+ // arrange
+ // batch items execute concurrently and share one transport span, so with the
+ // default scopes they must not fold their operation details into it
+ using var server = CreateSourceSchema(
+ "a",
+ b => b.AddQueryType());
+
+ using var gateway = await CreateCompositeSchemaAsync(
+ [("a", server)],
+ configureGatewayBuilder: b => b
+ .ModifyServerOptions(o => o.Batching = AllowedBatching.All)
+ .AddInstrumentation());
+
+ using var client = gateway.CreateClient();
+ client.BaseAddress = new Uri("http://localhost:5000");
+
+ const string batch =
+ """
+ [{"query":"query A { sayHello }"},
+ {"query":"query B { greeting(name: \"x\") }"}]
+ """;
+
+ // act
+ using var content = new StringContent(batch, Encoding.UTF8, "application/json");
+ using var response = await client.PostAsync(
+ "/graphql",
+ content,
+ TestContext.Current.CancellationToken);
+ await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken);
+
+ // assert
+ activities.MatchSnapshot(Postfix([NET11_0]));
+ }
+ }
+
[Fact]
public async Task Http_Post_PersistedOperationEndpoint_Default()
{
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
new file mode 100644
index 00000000000..c21938dd824
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
@@ -0,0 +1,533 @@
+{
+ "source": {
+ "name": "HotChocolate.Fusion.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "batch"
+ },
+ {
+ "Key": "graphql.http.request[0].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
+ }
+ },
+ {
+ "Key": "graphql.http.request[0].query.hash",
+ "Value": {
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "906bd3386334ff46441bf331680a58e4"
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.hash",
+ "Value": {
+ "Value": "906bd3386334ff46441bf331680a58e4",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "a39a0e2632168df91bf5ffa9d432107a58e7e788a80af2c6bfe7e0e276b0394b"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "A_722dc4ea_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:1f296352264c925d886fa9d9a6020bcba406ed0a3e617e3ffbc67272df03d408"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "93a468cff77cf20a1bd77063256532ae27dbc91266ddde838bad3d60bd9c1d8f"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "B_906bd338_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:baae930e2f254c1c548bd48328c129a57ed38176f05ec701268c04952ac8f88d"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
new file mode 100644
index 00000000000..0791f9598f5
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
@@ -0,0 +1,533 @@
+{
+ "source": {
+ "name": "HotChocolate.Fusion.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "batch"
+ },
+ {
+ "Key": "graphql.http.request[0].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
+ }
+ },
+ {
+ "Key": "graphql.http.request[0].query.hash",
+ "Value": {
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.id",
+ "Value": {
+ "IsEmpty": false,
+ "HasValue": true,
+ "Value": "906bd3386334ff46441bf331680a58e4"
+ }
+ },
+ {
+ "Key": "graphql.http.request[1].query.hash",
+ "Value": {
+ "Value": "906bd3386334ff46441bf331680a58e4",
+ "AlgorithmName": "md5",
+ "Format": "Hex",
+ "IsEmpty": false
+ }
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:722dc4ea59f88d2e746b3502ffa7e2d5"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "a39a0e2632168df91bf5ffa9d432107a58e7e788a80af2c6bfe7e0e276b0394b"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "A_722dc4ea_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:1f296352264c925d886fa9d9a6020bcba406ed0a3e617e3ffbc67272df03d408"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:906bd3386334ff46441bf331680a58e4"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "93a468cff77cf20a1bd77063256532ae27dbc91266ddde838bad3d60bd9c1d8f"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "B_906bd338_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:baae930e2f254c1c548bd48328c129a57ed38176f05ec701268c04952ac8f88d"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
From fd313eb8efcede96fc82700a885cf6bbbffb3a61 Mon Sep 17 00:00:00 2001
From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com>
Date: Tue, 15 Sep 2026 08:32:11 +0000
Subject: [PATCH 2/4] Fix batch request query id and hash tags serializing as
objects
---
.../Spans/Http/ExecuteHttpRequestSpan.cs | 4 +--
...ery_Item_Its_Own_Request_Span_Default.snap | 26 +++----------------
..._Its_Own_Request_Span_Default_NET11_0.snap | 26 +++----------------
...ery_Item_Its_Own_Request_Span_Default.snap | 26 +++----------------
..._Its_Own_Request_Span_Default_NET11_0.snap | 26 +++----------------
5 files changed, 18 insertions(+), 90 deletions(-)
diff --git a/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs b/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
index d47b8df5110..4392a67ef86 100644
--- a/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
+++ b/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
@@ -131,13 +131,13 @@ public void SetBatchRequestDetails(IReadOnlyList batch)
if (request.DocumentId is not null
&& (options.RequestDetails & RequestDetails.Id) == RequestDetails.Id)
{
- Activity.SetTag(GraphQL.Http.Request.BatchRequest.QueryId(i), request.DocumentId.Value);
+ Activity.SetTag(GraphQL.Http.Request.BatchRequest.QueryId(i), request.DocumentId.Value.Value);
}
if (request.DocumentHash is not null
&& (options.RequestDetails & RequestDetails.Hash) == RequestDetails.Hash)
{
- Activity.SetTag(GraphQL.Http.Request.BatchRequest.QueryHash(i), request.DocumentHash.Value);
+ Activity.SetTag(GraphQL.Http.Request.BatchRequest.QueryHash(i), request.DocumentHash.Value.Value);
}
if (request.Document is not null
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
index 7c36f7d0ad5..ec581acdf0e 100644
--- a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
@@ -64,37 +64,19 @@
},
{
"Key": "graphql.http.request[0].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
- }
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
},
{
"Key": "graphql.http.request[0].query.hash",
- "Value": {
- "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
},
{
"Key": "graphql.http.request[1].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "659bc020d413f3107839ff0cbbaf3440"
- }
+ "Value": "659bc020d413f3107839ff0cbbaf3440"
},
{
"Key": "graphql.http.request[1].query.hash",
- "Value": {
- "Value": "659bc020d413f3107839ff0cbbaf3440",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "659bc020d413f3107839ff0cbbaf3440"
}
],
"event": [],
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
index 8590ed1873d..062ad6756dc 100644
--- a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
@@ -64,37 +64,19 @@
},
{
"Key": "graphql.http.request[0].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
- }
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
},
{
"Key": "graphql.http.request[0].query.hash",
- "Value": {
- "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "dbfe187a49b8b785c6471ccb9bb8c5e4"
},
{
"Key": "graphql.http.request[1].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "659bc020d413f3107839ff0cbbaf3440"
- }
+ "Value": "659bc020d413f3107839ff0cbbaf3440"
},
{
"Key": "graphql.http.request[1].query.hash",
- "Value": {
- "Value": "659bc020d413f3107839ff0cbbaf3440",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "659bc020d413f3107839ff0cbbaf3440"
}
],
"event": [],
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
index c21938dd824..a07c0f4d755 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
@@ -64,37 +64,19 @@
},
{
"Key": "graphql.http.request[0].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
- }
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
},
{
"Key": "graphql.http.request[0].query.hash",
- "Value": {
- "Value": "722dc4ea59f88d2e746b3502ffa7e2d5",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
},
{
"Key": "graphql.http.request[1].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "906bd3386334ff46441bf331680a58e4"
- }
+ "Value": "906bd3386334ff46441bf331680a58e4"
},
{
"Key": "graphql.http.request[1].query.hash",
- "Value": {
- "Value": "906bd3386334ff46441bf331680a58e4",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "906bd3386334ff46441bf331680a58e4"
}
],
"event": [],
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
index 0791f9598f5..a888241702f 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
@@ -64,37 +64,19 @@
},
{
"Key": "graphql.http.request[0].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
- }
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
},
{
"Key": "graphql.http.request[0].query.hash",
- "Value": {
- "Value": "722dc4ea59f88d2e746b3502ffa7e2d5",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "722dc4ea59f88d2e746b3502ffa7e2d5"
},
{
"Key": "graphql.http.request[1].query.id",
- "Value": {
- "IsEmpty": false,
- "HasValue": true,
- "Value": "906bd3386334ff46441bf331680a58e4"
- }
+ "Value": "906bd3386334ff46441bf331680a58e4"
},
{
"Key": "graphql.http.request[1].query.hash",
- "Value": {
- "Value": "906bd3386334ff46441bf331680a58e4",
- "AlgorithmName": "md5",
- "Format": "Hex",
- "IsEmpty": false
- }
+ "Value": "906bd3386334ff46441bf331680a58e4"
}
],
"event": [],
From 754b43ae22b9c30abf09c89eb2b97893a712e9e6 Mon Sep 17 00:00:00 2001
From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com>
Date: Tue, 15 Sep 2026 08:53:18 +0000
Subject: [PATCH 3/4] Add operation batch regression test for per-item request
spans
The existing coverage only exercised the JSON request batch path. An operation
batch (?batchOperations=[A,B]) reaches StartOperationBatchRequest instead, a
separate MarkAsBatch call site, so it needs its own default-scope snapshot.
Add one for both the HotChocolate and Fusion listeners.
---
.../ActivityServerDiagnosticListenerTests.cs | 30 +
...ery_Item_Its_Own_Request_Span_Default.snap | 314 +++++++++++
..._Its_Own_Request_Span_Default_NET11_0.snap | 314 +++++++++++
...onActivityServerDiagnosticListenerTests.cs | 39 ++
...ery_Item_Its_Own_Request_Span_Default.snap | 511 ++++++++++++++++++
..._Its_Own_Request_Span_Default_NET11_0.snap | 511 ++++++++++++++++++
6 files changed, 1719 insertions(+)
create mode 100644 src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
create mode 100644 src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
create mode 100644 src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
create mode 100644 src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
index ca115135690..93c8508c6c9 100644
--- a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
@@ -185,6 +185,36 @@ public async Task Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_
}
}
+ [Fact]
+ public async Task Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default()
+ {
+ using (CaptureActivities(out var activities))
+ {
+ // arrange
+ // operation batch items execute concurrently and share one transport span, so
+ // with the default scopes they must not fold their operation details into it
+ using var server = CreateInstrumentedServer();
+ using var client = server.CreateClient();
+ client.BaseAddress = new Uri("http://localhost:5000");
+
+ const string request =
+ """
+ {"query":"query A { hero { name } } query B { human(id: \"1000\") { name } }"}
+ """;
+
+ // act
+ using var content = new StringContent(request, Encoding.UTF8, "application/json");
+ using var response = await client.PostAsync(
+ "/graphql?batchOperations=[A,B]",
+ content,
+ TestContext.Current.CancellationToken);
+ await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken);
+
+ // assert
+ activities.MatchSnapshot(Postfix([NET11_0]));
+ }
+ }
+
[Fact]
public async Task Http_Post_Variables_Are_Not_Automatically_Added_To_Activities()
{
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
new file mode 100644
index 00000000000..5977ff5c4dd
--- /dev/null
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
@@ -0,0 +1,314 @@
+{
+ "source": {
+ "name": "HotChocolate.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.query",
+ "Value": "?batchOperations=Redacted"
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "operation_batch"
+ },
+ {
+ "Key": "graphql.http.request.query.id",
+ "Value": "7da0832499d436dcd4788afc4e10d219"
+ },
+ {
+ "Key": "graphql.http.request.query.hash",
+ "Value": "7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.hero",
+ "DisplayName": "Query.hero",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.hero"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": [
+ {
+ "Name": "RetrievedDocumentFromCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.human",
+ "DisplayName": "Query.human",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.human"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
new file mode 100644
index 00000000000..c9dede45647
--- /dev/null
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/__snapshots__/ActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
@@ -0,0 +1,314 @@
+{
+ "source": {
+ "name": "HotChocolate.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "url.query",
+ "Value": "?batchOperations=Redacted"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "operation_batch"
+ },
+ {
+ "Key": "graphql.http.request.query.id",
+ "Value": "7da0832499d436dcd4788afc4e10d219"
+ },
+ {
+ "Key": "graphql.http.request.query.hash",
+ "Value": "7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.hero",
+ "DisplayName": "Query.hero",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "hero"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.hero"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ }
+ ],
+ "event": [
+ {
+ "Name": "RetrievedDocumentFromCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedOperationToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:7da0832499d436dcd4788afc4e10d219"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "Query.human",
+ "DisplayName": "Query.human",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "resolve"
+ },
+ {
+ "Key": "graphql.field.alias",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.path",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.name",
+ "Value": "human"
+ },
+ {
+ "Key": "graphql.field.schema_coordinate",
+ "Value": "Query.human"
+ },
+ {
+ "Key": "graphql.field.parent_type",
+ "Value": "Query"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
index 5f476177373..2d3182084e8 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
@@ -129,6 +129,45 @@ public async Task Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_
}
}
+ [Fact]
+ public async Task Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default()
+ {
+ using (CaptureActivities(out var activities))
+ {
+ // arrange
+ // operation batch items execute concurrently and share one transport span, so
+ // with the default scopes they must not fold their operation details into it
+ using var server = CreateSourceSchema(
+ "a",
+ b => b.AddQueryType());
+
+ using var gateway = await CreateCompositeSchemaAsync(
+ [("a", server)],
+ configureGatewayBuilder: b => b
+ .ModifyServerOptions(o => o.Batching = AllowedBatching.All)
+ .AddInstrumentation());
+
+ using var client = gateway.CreateClient();
+ client.BaseAddress = new Uri("http://localhost:5000");
+
+ const string request =
+ """
+ {"query":"query A { sayHello } query B { greeting(name: \"x\") }"}
+ """;
+
+ // act
+ using var content = new StringContent(request, Encoding.UTF8, "application/json");
+ using var response = await client.PostAsync(
+ "/graphql?batchOperations=[A,B]",
+ content,
+ TestContext.Current.CancellationToken);
+ await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken);
+
+ // assert
+ activities.MatchSnapshot(Postfix([NET11_0]));
+ }
+ }
+
[Fact]
public async Task Http_Post_PersistedOperationEndpoint_Default()
{
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
new file mode 100644
index 00000000000..f4faf6c2cf1
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default.snap
@@ -0,0 +1,511 @@
+{
+ "source": {
+ "name": "HotChocolate.Fusion.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.query",
+ "Value": "?batchOperations=Redacted"
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "operation_batch"
+ },
+ {
+ "Key": "graphql.http.request.query.id",
+ "Value": "397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.http.request.query.hash",
+ "Value": "397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "eefbeb39e428f34e4cafb51dc2962aab9c52f20a624e8b14eaa879356bac923f"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "A_397d1e0a_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:41b2382275bbadb2e46e28b01fb2d329542b2d7180ffbad1bfc64f037b1d7c59"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "846735be35f1149bdf8507517b950a7bd3143dc0ccb2362ba624f36ed28d50f5"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "B_397d1e0a_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:e0913d474bf80cd0cf55adeec6c8a117cd795ac6fdb6798ccf5d5287a8429350"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
new file mode 100644
index 00000000000..dc9e71ee675
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/__snapshots__/FusionActivityServerDiagnosticListenerTests.Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own_Request_Span_Default_NET11_0.snap
@@ -0,0 +1,511 @@
+{
+ "source": {
+ "name": "HotChocolate.Fusion.Diagnostics"
+ },
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "url.query",
+ "Value": "?batchOperations=Redacted"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "ExecuteHttpRequest",
+ "DisplayName": "GraphQL HTTP POST",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.http.kind",
+ "Value": "HttpPost"
+ },
+ {
+ "Key": "graphql.schema.name",
+ "Value": "_Default"
+ },
+ {
+ "Key": "graphql.http.request.type",
+ "Value": "operation_batch"
+ },
+ {
+ "Key": "graphql.http.request.query.id",
+ "Value": "397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.http.request.query.hash",
+ "Value": "397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Parse HTTP Request",
+ "DisplayName": "Parse HTTP Request",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "A"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "eefbeb39e428f34e4cafb51dc2962aab9c52f20a624e8b14eaa879356bac923f"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "A_397d1e0a_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:41b2382275bbadb2e46e28b01fb2d329542b2d7180ffbad1bfc64f037b1d7c59"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "OperationName": "GraphQL Operation",
+ "DisplayName": "query",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "request"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": [
+ {
+ "Name": "AddedOperationPlanToCache",
+ "Tags": []
+ },
+ {
+ "Name": "AddedDocumentToCache",
+ "Tags": []
+ }
+ ],
+ "activities": [
+ {
+ "OperationName": "GraphQL Document Validation",
+ "DisplayName": "GraphQL Document Validation",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "validate"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Operation Planning",
+ "DisplayName": "GraphQL Operation Planning",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "plan"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ }
+ ],
+ "event": []
+ },
+ {
+ "OperationName": "GraphQL Step Execution",
+ "DisplayName": "GraphQL Step Execution",
+ "Kind": "Internal",
+ "Status": "Ok",
+ "tags": [
+ {
+ "Key": "graphql.processing.type",
+ "Value": "step_execute"
+ },
+ {
+ "Key": "graphql.operation.type",
+ "Value": "query"
+ },
+ {
+ "Key": "graphql.operation.name",
+ "Value": "B"
+ },
+ {
+ "Key": "graphql.document.hash",
+ "Value": "md5:397d1e0a5c74c2617a1768fe1d74398f"
+ },
+ {
+ "Key": "graphql.operation.step.id",
+ "Value": "1"
+ },
+ {
+ "Key": "graphql.operation.step.kind",
+ "Value": "operation"
+ },
+ {
+ "Key": "graphql.operation.step.plan.id",
+ "Value": "846735be35f1149bdf8507517b950a7bd3143dc0ccb2362ba624f36ed28d50f5"
+ },
+ {
+ "Key": "graphql.source_schema.name",
+ "Value": "a"
+ },
+ {
+ "Key": "graphql.source_schema.operation.name",
+ "Value": "B_397d1e0a_1"
+ },
+ {
+ "Key": "graphql.source_schema.operation.hash",
+ "Value": "sha256:e0913d474bf80cd0cf55adeec6c8a117cd795ac6fdb6798ccf5d5287a8429350"
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "System.Net.Http.HttpRequestOut",
+ "DisplayName": "System.Net.Http.HttpRequestOut",
+ "Kind": "Client",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "url.full",
+ "Value": "http://localhost:5000/graphql"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ }
+ ],
+ "event": [],
+ "activities": [
+ {
+ "OperationName": "Microsoft.AspNetCore.Hosting.HttpRequestIn",
+ "DisplayName": "POST /graphql/{**slug}",
+ "Kind": "Server",
+ "Status": "Unset",
+ "tags": [
+ {
+ "Key": "server.address",
+ "Value": "localhost"
+ },
+ {
+ "Key": "server.port",
+ "Value": 5000
+ },
+ {
+ "Key": "http.request.method",
+ "Value": "POST"
+ },
+ {
+ "Key": "url.scheme",
+ "Value": "http"
+ },
+ {
+ "Key": "url.path",
+ "Value": "/graphql"
+ },
+ {
+ "Key": "network.protocol.version",
+ "Value": "1.1"
+ },
+ {
+ "Key": "http.response.status_code",
+ "Value": 200
+ },
+ {
+ "Key": "http.route",
+ "Value": "/graphql/{**slug}"
+ }
+ ],
+ "event": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
From 894de1ae8f9ae24a397a20814697917cc90f22cb Mon Sep 17 00:00:00 2001
From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com>
Date: Tue, 15 Sep 2026 08:57:36 +0000
Subject: [PATCH 4/4] Drop explanatory comments from batch span changes
The code states the condition directly, so the surrounding prose added nothing.
---
.../Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs | 5 -----
.../Listeners/ActivityExecutionDiagnosticListener.cs | 5 -----
.../ActivityServerDiagnosticListenerTests.cs | 4 ----
.../FusionActivityExecutionDiagnosticEventListener.cs | 5 -----
.../FusionActivityServerDiagnosticListenerTests.cs | 4 ----
5 files changed, 23 deletions(-)
diff --git a/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs b/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
index 4392a67ef86..b009cedcfbc 100644
--- a/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
+++ b/src/HotChocolate/Diagnostics/src/Diagnostics.Core/Spans/Http/ExecuteHttpRequestSpan.cs
@@ -61,11 +61,6 @@ internal sealed class ExecuteHttpRequestSpan(
return new ExecuteHttpRequestSpan(activity, httpContext, kind, enricher, options);
}
- ///
- /// Specifies whether this span covers more than one GraphQL request. The items of a
- /// batch execute concurrently, so they must not write their own operation details
- /// onto this shared span.
- ///
public bool IsBatch { get; private set; }
public void MarkAsBatch() => IsBatch = true;
diff --git a/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs b/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs
index 8b57dc14ee0..29d415a72a1 100644
--- a/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs
+++ b/src/HotChocolate/Diagnostics/src/Diagnostics/Listeners/ActivityExecutionDiagnosticListener.cs
@@ -31,11 +31,6 @@ public override IDisposable ExecuteRequest(RequestContext context)
return EmptyScope;
}
- // A single GraphQL over HTTP request reuses the transport span as the root
- // request span instead of emitting a second one. A batch shares one transport
- // span across concurrently executing items, and a transport without a span of
- // its own, like a WebSocket session, has nothing to reuse, so both fall
- // through to a dedicated request span.
if (httpContext.Features.Get() is { IsBatch: false } httpRequestSpan)
{
httpContextActivity = httpRequestSpan.Activity;
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
index 93c8508c6c9..6ed773e0697 100644
--- a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/ActivityServerDiagnosticListenerTests.cs
@@ -160,8 +160,6 @@ public async Task Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_
using (CaptureActivities(out var activities))
{
// arrange
- // batch items execute concurrently and share one transport span, so with the
- // default scopes they must not fold their operation details into it
using var server = CreateInstrumentedServer();
using var client = server.CreateClient();
client.BaseAddress = new Uri("http://localhost:5000");
@@ -191,8 +189,6 @@ public async Task Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own
using (CaptureActivities(out var activities))
{
// arrange
- // operation batch items execute concurrently and share one transport span, so
- // with the default scopes they must not fold their operation details into it
using var server = CreateInstrumentedServer();
using var client = server.CreateClient();
client.BaseAddress = new Uri("http://localhost:5000");
diff --git a/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs b/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs
index 91ebb177f10..6a79732dd4b 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Diagnostics/Listeners/FusionActivityExecutionDiagnosticEventListener.cs
@@ -27,11 +27,6 @@ public override IDisposable ExecuteRequest(RequestContext context)
return EmptyScope;
}
- // A single GraphQL over HTTP request reuses the transport span as the root
- // request span instead of emitting a second one. A batch shares one transport
- // span across concurrently executing items, and a transport without a span of
- // its own, like a WebSocket session, has nothing to reuse, so both fall
- // through to a dedicated request span.
if (httpContext.Features.Get() is { IsBatch: false } httpRequestSpan)
{
httpContextActivity = httpRequestSpan.Activity;
diff --git a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
index 2d3182084e8..607ce19acb3 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.Diagnostics.Tests/FusionActivityServerDiagnosticListenerTests.cs
@@ -95,8 +95,6 @@ public async Task Http_Post_BatchRequest_Should_Give_Every_Item_Its_Own_Request_
using (CaptureActivities(out var activities))
{
// arrange
- // batch items execute concurrently and share one transport span, so with the
- // default scopes they must not fold their operation details into it
using var server = CreateSourceSchema(
"a",
b => b.AddQueryType());
@@ -135,8 +133,6 @@ public async Task Http_Post_OperationBatchRequest_Should_Give_Every_Item_Its_Own
using (CaptureActivities(out var activities))
{
// arrange
- // operation batch items execute concurrently and share one transport span, so
- // with the default scopes they must not fold their operation details into it
using var server = CreateSourceSchema(
"a",
b => b.AddQueryType());