Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions examples/Server/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Count;
using Greet;
using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
Expand All @@ -44,14 +42,14 @@ public void ConfigureServices(IServiceCollection services)
{
// This registers a global interceptor with a Singleton lifetime. The interceptor must be added to the service collection in addition to being registered here.
options.Interceptors.Add<MaxConcurrentCallsInterceptor>();
// This registers a global interceptor with a Scoped lifetime.
options.Interceptors.Add<MaxStreamingRequestTimeoutInterceptor>(TimeSpan.FromSeconds(30));
})
.AddServiceOptions<GreeterService>(options =>
{
// This registers an interceptor for the Greeter service with a Singleton lifetime.
// NOTE: Not all calls should be cached. Since the response of this service only depends on the request and no other state, adding caching here is acceptable.
options.Interceptors.Add<UnaryCachingInterceptor>();
// This registers an interceptor for the Greeter service with a Scoped lifetime.
options.Interceptors.Add<MaxStreamingRequestTimeoutInterceptor>(TimeSpan.FromSeconds(30));
});
services.AddGrpcReflection();
services.AddSingleton(new MaxConcurrentCallsInterceptor(200));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ namespace Grpc.AspNetCore.Microbenchmarks.Internal
{
internal static class MessageHelpers
{
private static readonly HttpContextServerCallContext TestServerCallContext = new HttpContextServerCallContext(new DefaultHttpContext(), new GrpcServiceOptions(), NullLogger.Instance);
private static readonly HttpContextServerCallContext TestServerCallContext = new HttpContextServerCallContext(
new DefaultHttpContext(),
new GrpcServiceOptions(),
NullLogger.Instance);

static MessageHelpers()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#endregion

using System;
using System.Threading.Tasks;
using Grpc.AspNetCore.Server.Model;
using Grpc.Core;
Expand Down Expand Up @@ -113,6 +112,8 @@ protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpC

var responseBodyWriter = httpContext.Response.BodyWriter;
await responseBodyWriter.WriteMessageAsync(response, serverCallContext, Method.ResponseMarshaller.ContextualSerializer, canFlush: false);

GrpcEventSource.Log.MessageSent();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#endregion

using System;
using System.Threading.Tasks;
using Grpc.AspNetCore.Server.Model;
using Grpc.Core;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@

namespace Grpc.AspNetCore.Server.Internal.CallHandlers
{
internal abstract class ServerCallHandlerBase<TService, TRequest, TResponse> : IServerCallHandler
internal abstract class ServerCallHandlerBase<TService, TRequest, TResponse>
{
protected Method<TRequest, TResponse> Method { get; }
protected GrpcServiceOptions ServiceOptions { get; }
protected ILogger Logger { get; }

protected ServerCallHandlerBase(Method<TRequest, TResponse> method, GrpcServiceOptions serviceOptions, ILoggerFactory loggerFactory)
protected ServerCallHandlerBase(
Method<TRequest, TResponse> method,
GrpcServiceOptions serviceOptions,
ILoggerFactory loggerFactory)
{
Method = method;
ServiceOptions = serviceOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#endregion

using System;
using System.Threading.Tasks;
using Grpc.AspNetCore.Server.Model;
using Grpc.Core;
Expand Down Expand Up @@ -77,6 +76,8 @@ protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpC
var request = Method.RequestMarshaller.ContextualDeserializer(serverCallContext.DeserializationContext);
serverCallContext.DeserializationContext.SetPayload(null);

GrpcEventSource.Log.MessageReceived();

if (_pipelineInvoker == null)
{
var activator = httpContext.RequestServices.GetRequiredService<IGrpcServiceActivator<TService>>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#endregion

using System;
using System.Threading.Tasks;
using Grpc.AspNetCore.Server.Model;
using Grpc.Core;
Expand Down Expand Up @@ -76,6 +75,8 @@ protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpC
var request = Method.RequestMarshaller.ContextualDeserializer(serverCallContext.DeserializationContext);
serverCallContext.DeserializationContext.SetPayload(null);

GrpcEventSource.Log.MessageReceived();

TResponse? response = null;

if (_pipelineInvoker == null)
Expand Down Expand Up @@ -108,6 +109,8 @@ protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpC

var responseBodyWriter = httpContext.Response.BodyWriter;
await responseBodyWriter.WriteMessageAsync(response, serverCallContext, Method.ResponseMarshaller.ContextualSerializer, canFlush: false);

GrpcEventSource.Log.MessageSent();
}
}
}
159 changes: 159 additions & 0 deletions src/Grpc.AspNetCore.Server/Internal/GrpcEventSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#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.Diagnostics.Tracing;
using System.Runtime.CompilerServices;
using System.Threading;
using Grpc.Core;

namespace Grpc.AspNetCore.Server.Internal
{
internal class GrpcEventSource : EventSource
{
public static readonly GrpcEventSource Log = new GrpcEventSource();

private PollingCounter? _totalCallsCounter;
private PollingCounter? _currentCallsCounter;
private PollingCounter? _messagesSentCounter;
private PollingCounter? _messagesReceivedCounter;
private PollingCounter? _callsFailedCounter;
private PollingCounter? _callsDeadlineExceededCounter;
private PollingCounter? _callsUnimplementedCounter;

private long _totalCalls;
private long _currentCalls;
private long _messageSent;
private long _messageReceived;
private long _callsFailed;
private long _callsDeadlineExceeded;
private long _callsUnimplemented;

internal GrpcEventSource()
: base("Grpc.AspNetCore.Server")
{
}

// Used for testing
internal GrpcEventSource(string eventSourceName)
: base(eventSourceName)
{
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 1, Level = EventLevel.Verbose)]
public void CallStart(string method)
{
Interlocked.Increment(ref _totalCalls);
Interlocked.Increment(ref _currentCalls);

WriteEvent(1, method);
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 2, Level = EventLevel.Verbose)]
public void CallStop()
{
Interlocked.Decrement(ref _currentCalls);

WriteEvent(2);
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 3, Level = EventLevel.Error)]
public void CallFailed(StatusCode statusCode)
{
Interlocked.Increment(ref _callsFailed);

WriteEvent(3, (int)statusCode);
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 4, Level = EventLevel.Error)]
public void CallDeadlineExceeded()
{
Interlocked.Increment(ref _callsDeadlineExceeded);

WriteEvent(4);
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 5, Level = EventLevel.Verbose)]
public void MessageSent()
{
Interlocked.Increment(ref _messageSent);

WriteEvent(5);
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 6, Level = EventLevel.Verbose)]
public void MessageReceived()
{
Interlocked.Increment(ref _messageReceived);

WriteEvent(6);
}

[MethodImpl(MethodImplOptions.NoInlining)]
[Event(eventId: 7, Level = EventLevel.Verbose)]
public void CallUnimplemented(string method)
{
Interlocked.Increment(ref _callsUnimplemented);

WriteEvent(7, method);
}

protected override void OnEventCommand(EventCommandEventArgs command)
{
if (command.Command == EventCommand.Enable)
{
// This is the convention for initializing counters in the RuntimeEventSource (lazily on the first enable command).
// They aren't disabled afterwards...

_totalCallsCounter ??= new PollingCounter("total-calls", this, () => _totalCalls)
{
DisplayName = "Total Calls",
};
_currentCallsCounter ??= new PollingCounter("current-calls", this, () => _currentCalls)
{
DisplayName = "Current Calls"
};
_callsFailedCounter ??= new PollingCounter("calls-failed", this, () => _callsFailed)
{
DisplayName = "Total Calls Failed",
};
_callsDeadlineExceededCounter ??= new PollingCounter("calls-deadline-exceeded", this, () => _callsDeadlineExceeded)
{
DisplayName = "Total Calls Deadline Exceeded",
};
_messagesSentCounter ??= new PollingCounter("messages-sent", this, () => _messageSent)
{
DisplayName = "Total Messages Sent",
};
_messagesReceivedCounter ??= new PollingCounter("messages-received", this, () => _messageReceived)
{
DisplayName = "Total Messages Received",
};
_callsUnimplementedCounter ??= new PollingCounter("calls-unimplemented", this, () => _callsUnimplemented)
{
DisplayName = "Total Calls Unimplemented",
};
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

#region Copyright notice and license
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
Expand All @@ -17,13 +16,14 @@

#endregion

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace Grpc.AspNetCore.Server.Internal
{
internal interface IServerCallHandler
internal static class GrpcServerConstants
{
Task HandleCallAsync(HttpContext httpContext);
internal const string HostActivityName = "Microsoft.AspNetCore.Hosting.HttpRequestIn";
internal const string HostActivityChanged = HostActivityName + ".Changed";

internal const string ActivityStatusCodeTag = "grpc.status_code";
internal const string ActivityMethodTag = "grpc.method";
}
}
Loading