Skip to content

Commit 1ac3a3f

Browse files
Use IHttpActivityFeature to get host activity (#1545)
Co-authored-by: Safia Abdalla <[email protected]>
1 parent 9c936f3 commit 1ac3a3f

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

src/Grpc.AspNetCore.Server/Internal/HttpContextServerCallContext.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,16 @@ public void Initialize(ISystemClock? clock = null)
400400

401401
private Activity? GetHostActivity()
402402
{
403+
#if NET6_0_OR_GREATER
404+
// Feature always returns the host activity
405+
var feature = HttpContext.Features.Get<IHttpActivityFeature>();
406+
if (feature != null)
407+
{
408+
return feature.Activity;
409+
}
410+
#endif
411+
412+
// If feature isn't available, or not supported, then fallback to Activity.Current.
403413
var activity = Activity.Current;
404414
while (activity != null)
405415
{
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#region Copyright notice and license
2+
3+
// Copyright 2019 The gRPC Authors
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
#endregion
18+
19+
using System.Net;
20+
using Greet;
21+
using Grpc.AspNetCore.FunctionalTests.Infrastructure;
22+
using Grpc.Tests.Shared;
23+
using NUnit.Framework;
24+
25+
namespace Grpc.AspNetCore.FunctionalTests.Server
26+
{
27+
[TestFixture]
28+
public class DiagnosticsTests : FunctionalTestBase
29+
{
30+
[Test]
31+
public async Task HostActivityTags_ReturnedInTrailers_Success()
32+
{
33+
// Arrange
34+
var requestMessage = new HelloRequest
35+
{
36+
Name = "World"
37+
};
38+
39+
var ms = new MemoryStream();
40+
MessageHelpers.WriteMessage(ms, requestMessage);
41+
42+
var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");
43+
httpRequest.Content = new GrpcStreamContent(ms);
44+
httpRequest.Headers.Add("return-tags-trailers", "true");
45+
46+
// Act
47+
var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();
48+
49+
// Assert
50+
var responseMessage = await response.GetSuccessfulGrpcMessageAsync<HelloReply>().DefaultTimeout();
51+
Assert.AreEqual("Hello World", responseMessage.Message);
52+
response.AssertTrailerStatus();
53+
54+
var trailers = response.TrailingHeaders;
55+
Assert.AreEqual("0", trailers.GetValues("grpc.status_code").Single());
56+
Assert.AreEqual("/Greet.Greeter/SayHello", trailers.GetValues("grpc.method").Single());
57+
}
58+
}
59+
}

testassets/FunctionalTestsWebsite/FunctionalTestsWebsite.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
<Protobuf Include="..\Proto\echo.proto" Link="Protos\echo.proto" />
3030
<Protobuf Include="..\Proto\issue.proto" Link="Protos\issue.proto" />
3131
<Protobuf Include="..\Proto\test.proto" Link="Protos\test.proto" />
32+
33+
<Compile Include="..\..\test\Shared\ActivityReplacer.cs" Link="Infrastructure\ActivityReplacer.cs" />
3234
</ItemGroup>
3335

3436
</Project>

testassets/FunctionalTestsWebsite/Startup.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616

1717
#endregion
1818

19+
using System.Diagnostics;
1920
using System.IdentityModel.Tokens.Jwt;
2021
using System.Security.Claims;
2122
using FunctionalTestsWebsite.Infrastructure;
2223
using FunctionalTestsWebsite.Services;
2324
using Greet;
2425
using Grpc.AspNetCore.Server.Model;
26+
using Grpc.Tests.Shared;
2527
using Microsoft.AspNetCore.Authentication.JwtBearer;
2628
using Microsoft.Extensions.DependencyInjection.Extensions;
2729
using Microsoft.IdentityModel.Tokens;
@@ -132,6 +134,33 @@ public void Configure(IApplicationBuilder app)
132134
await next();
133135
});
134136

137+
app.Use(async (context, next) =>
138+
{
139+
// Allow a call to specify activity tags are returned as trailers.
140+
if (context.Request.Headers.TryGetValue("return-tags-trailers", out var value) &&
141+
bool.TryParse(value.ToString(), out var remove) && remove)
142+
{
143+
logger.LogInformation("Replacing activity.");
144+
145+
// Replace the activity to check that tags are added to the host activity.
146+
using (new ActivityReplacer("GrpcFunctionalTests"))
147+
{
148+
await next();
149+
}
150+
151+
logger.LogInformation("Adding tags to trailers.");
152+
153+
foreach (var tag in Activity.Current!.Tags)
154+
{
155+
context.Response.AppendTrailer(tag.Key, tag.Value);
156+
}
157+
}
158+
else
159+
{
160+
await next();
161+
}
162+
});
163+
135164
app.UseRouting();
136165

137166
app.UseAuthorization();

0 commit comments

Comments
 (0)