diff --git a/build/Common.props b/build/Common.props
index 8f9490f903..0455be2fb7 100644
--- a/build/Common.props
+++ b/build/Common.props
@@ -34,6 +34,7 @@
Refer to https://docs.microsoft.com/en-us/nuget/concepts/package-versioning for semver syntax.
-->
[6.0.0,7.0)
+ [9.0.0,)
[2.1.0,5.0)
[9.0.0,)
[9.0.0,)
diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationTracerProviderBuilderExtensions.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationTracerProviderBuilderExtensions.cs
index 09a60868c6..fa3a322b7f 100644
--- a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationTracerProviderBuilderExtensions.cs
+++ b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationTracerProviderBuilderExtensions.cs
@@ -121,5 +121,12 @@ private static void AddAspNetCoreInstrumentationSources(
builder.AddSource(HttpInListener.ActivitySourceName);
builder.AddLegacySource(HttpInListener.ActivityOperationName); // for the activities created by AspNetCore
}
+
+ // SignalR activities first added in .NET 9.0
+ if (Environment.Version.Major >= 9)
+ {
+ // https://github.com/dotnet/aspnetcore/blob/6ae3ea387b20f6497b82897d613e9b8a6e31d69c/src/SignalR/server/Core/src/Internal/SignalRServerActivitySource.cs#L13C35-L13C70
+ builder.AddSource("Microsoft.AspNetCore.SignalR.Server");
+ }
}
}
diff --git a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs
index ac7a5929ec..2297a593dd 100644
--- a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs
+++ b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs
@@ -7,6 +7,7 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -1114,6 +1115,63 @@ public async Task ValidateUrlQueryRedaction(string urlQuery, string expectedUrlQ
Assert.Equal(expectedUrlQuery, activity.GetTagValue(SemanticConventions.AttributeUrlQuery));
}
+#if NET9_0_OR_GREATER
+ [Fact]
+ public async Task SignalRActivitesAreListenedTo()
+ {
+ var exportedItems = new List();
+ void ConfigureTestServices(IServiceCollection services)
+ {
+ this.tracerProvider = Sdk.CreateTracerProviderBuilder()
+ .AddAspNetCoreInstrumentation()
+ .AddInMemoryExporter(exportedItems)
+ .Build();
+ }
+
+ // Arrange
+ using (var server = this.factory
+ .WithWebHostBuilder(builder =>
+ {
+ builder.ConfigureTestServices(ConfigureTestServices);
+ builder.ConfigureLogging(loggingBuilder => loggingBuilder.ClearProviders());
+ }))
+ {
+ await using var client = new HubConnectionBuilder()
+ .WithUrl(server.Server.BaseAddress + "testHub", o =>
+ {
+ o.HttpMessageHandlerFactory = _ => server.Server.CreateHandler();
+ o.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.LongPolling;
+ }).Build();
+ await client.StartAsync();
+
+ await client.SendAsync("Send", "text");
+
+ await client.StopAsync();
+ }
+
+ WaitForActivityExport(exportedItems, 11);
+
+ var hubActivity = exportedItems
+ .Where(a => a.DisplayName.StartsWith("TestApp.AspNetCore.TestHub", StringComparison.InvariantCulture));
+
+ Assert.Equal(3, hubActivity.Count());
+ Assert.Collection(
+ hubActivity,
+ one =>
+ {
+ Assert.Equal("TestApp.AspNetCore.TestHub/OnConnectedAsync", one.DisplayName);
+ },
+ two =>
+ {
+ Assert.Equal("TestApp.AspNetCore.TestHub/Send", two.DisplayName);
+ },
+ three =>
+ {
+ Assert.Equal("TestApp.AspNetCore.TestHub/OnDisconnectedAsync", three.DisplayName);
+ });
+ }
+#endif
+
public void Dispose()
{
this.tracerProvider?.Dispose();
diff --git a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/OpenTelemetry.Instrumentation.AspNetCore.Tests.csproj b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/OpenTelemetry.Instrumentation.AspNetCore.Tests.csproj
index 11def19721..d0bf16a02e 100644
--- a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/OpenTelemetry.Instrumentation.AspNetCore.Tests.csproj
+++ b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/OpenTelemetry.Instrumentation.AspNetCore.Tests.csproj
@@ -18,6 +18,7 @@
+
diff --git a/test/TestApp.AspNetCore/Program.cs b/test/TestApp.AspNetCore/Program.cs
index 5cbe2b5e3a..110693b6fa 100644
--- a/test/TestApp.AspNetCore/Program.cs
+++ b/test/TestApp.AspNetCore/Program.cs
@@ -20,6 +20,8 @@ public static void Main(string[] args)
builder.Services.AddMvc();
+ builder.Services.AddSignalR();
+
builder.Services.AddSingleton();
builder.Services.AddSingleton(
@@ -43,6 +45,8 @@ public static void Main(string[] args)
app.MapControllers();
+ app.MapHub("/testHub");
+
app.UseMiddleware();
app.UseMiddleware();
diff --git a/test/TestApp.AspNetCore/TestHub.cs b/test/TestApp.AspNetCore/TestHub.cs
new file mode 100644
index 0000000000..73a8a09bb0
--- /dev/null
+++ b/test/TestApp.AspNetCore/TestHub.cs
@@ -0,0 +1,15 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+using Microsoft.AspNetCore.SignalR;
+
+namespace TestApp.AspNetCore;
+
+public class TestHub : Hub
+{
+ public override Task OnConnectedAsync() => base.OnConnectedAsync();
+
+ public void Send(string message)
+ {
+ }
+}