Skip to content

Commit

Permalink
Add tags to activity
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK committed Jun 21, 2019
1 parent f39a94d commit be0f551
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/Grpc.AspNetCore.Server/Internal/GrpcEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ internal GrpcEventSource(string eventSourceName)
{
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 1, Level = EventLevel.Verbose)]
public void CallStart(string method)
{
Expand All @@ -61,6 +62,7 @@ public void CallStart(string method)
WriteEvent(1, method);
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 2, Level = EventLevel.Verbose)]
public void CallStop()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,8 @@ private void ProcessHandlerError(Exception ex, string method)
{
HttpContext.Response.ConsolidateTrailers(this);
}

GrpcEventSource.Log.CallFailed(_status.StatusCode);
GrpcEventSource.Log.CallStop();

LogCallEnd();

_callComplete = true;
}
Expand Down Expand Up @@ -260,11 +259,25 @@ private void EndCallCore()
HttpContext.Response.ConsolidateTrailers(this);
}

GrpcEventSource.Log.CallStop();
LogCallEnd();

_callComplete = true;
}

private void LogCallEnd()
{
var currentActivity = Activity.Current;
if (currentActivity != null)
{
currentActivity.AddTag("GrpcStatus", _status.StatusCode.ToTrailerString());
}
if (_status.StatusCode != StatusCode.OK)
{
GrpcEventSource.Log.CallFailed(_status.StatusCode);
}
GrpcEventSource.Log.CallStop();
}

protected override WriteOptions? WriteOptionsCore { get; set; }

protected override AuthContext AuthContextCore
Expand Down Expand Up @@ -329,6 +342,12 @@ protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders)

public void Initialize()
{
var currentActivity = Activity.Current;
if (currentActivity != null)
{
Activity.Current.AddTag("GrpcMethod", MethodCore);
}

GrpcEventSource.Log.CallStart(MethodCore);

var timeout = GetTimeout();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<ItemGroup>
<Protobuf Include="Proto\*.proto" GrpcServices="Both" />

<Compile Include="..\Shared\ActivityReplacer.cs" Link="Infrastructure\ActivityReplacer.cs" />
<Compile Include="..\Shared\HttpContextHelpers.cs" Link="Infrastructure\HttpContextHelpers.cs" />
<Compile Include="..\Shared\HttpContextServerCallContextHelpers.cs" Link="Infrastructure\HttpContextServerCallContextHelpers.cs" />
<Compile Include="..\Shared\MessageHelpers.cs" Link="Infrastructure\MessageHelpers.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
Expand Down Expand Up @@ -608,6 +609,62 @@ private async Task LongRunningDeadlineAbort_WaitsUntilDeadlineAbortIsFinished(st
Assert.IsTrue(serverCallContext._callComplete);
}

[Test]
public void Initialize_MethodInPath_SetsMethodOnActivity()
{
using (new ActivityReplacer())
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.Request.Path = "/Package.Service/Method";
var context = CreateServerCallContext(httpContext);

// Act
context.Initialize();

// Assert
Assert.AreEqual("/Package.Service/Method", Activity.Current.Tags.Single(t => t.Key == "GrpcMethod").Value);
}
}

[Test]
public async Task EndCallAsync_StatusSet_SetsStatusOnActivity()
{
using (new ActivityReplacer())
{
// Arrange
var httpContext = new DefaultHttpContext();
var context = CreateServerCallContext(httpContext);
context.Status = new Status(StatusCode.ResourceExhausted, string.Empty);

// Act
context.Initialize();
await context.EndCallAsync();

// Assert
Assert.AreEqual("8", Activity.Current.Tags.Single(t => t.Key == "GrpcStatus").Value);
}
}

[Test]
public async Task ProcessHandlerErrorAsync_Exception_SetsStatusOnActivity()
{
using (new ActivityReplacer())
{
// Arrange
var httpContext = new DefaultHttpContext();
var context = CreateServerCallContext(httpContext);
context.Status = new Status(StatusCode.ResourceExhausted, string.Empty);

// Act
context.Initialize();
await context.ProcessHandlerErrorAsync(new Exception(), "MethodName");

// Assert
Assert.AreEqual("2", Activity.Current.Tags.Single(t => t.Key == "GrpcStatus").Value);
}
}

private HttpContextServerCallContext CreateServerCallContext(HttpContext httpContext, ILogger? logger = null)
{
return new HttpContextServerCallContext(httpContext, new GrpcServiceOptions(), logger ?? NullLogger.Instance);
Expand Down
40 changes: 40 additions & 0 deletions test/Shared/ActivityReplacer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using System;
using System.Diagnostics;

namespace Grpc.Tests.Shared
{
public class ActivityReplacer : IDisposable
{
private readonly Activity _activity;

public ActivityReplacer()
{
_activity = new Activity("Test");
_activity.Start();
}

public void Dispose()
{
Debug.Assert(Activity.Current == _activity);
_activity.Stop();
}
}
}

0 comments on commit be0f551

Please sign in to comment.