public async Task Invoke(IIncomingGrainCallContext context)
        {
            bool isOrleansGrain = context.InterfaceMethod == null || context.InterfaceMethod.DeclaringType == null || context.InterfaceMethod.Module.Assembly.FullName.StartsWith("Orleans");
            //TODO add test that validate that we are not introducing new grain in micro dot
            bool isMicrodotGrain = isOrleansGrain == false && context.InterfaceMethod.DeclaringType.Name == nameof(IRequestProcessingGrain);
            bool isServiceGrain  = isOrleansGrain == false && isMicrodotGrain == false;

            var grainTags = new Lazy <GrainTags>(() => new GrainTags(context));
            // Drop the request if we're overloaded
            var loadSheddingConfig = _loadSheddingConfig();

            if (
                (loadSheddingConfig.ApplyToMicrodotGrains && isMicrodotGrain) ||
                (loadSheddingConfig.ApplyToServiceGrains && isServiceGrain)
                )
            {
                //Can brake the flow by throwing Overloaded
                RejectRequestIfLateOrOverloaded(grainTags);
            }
            var loggingConfig = _grainLoggingConfig();

            bool shouldLog = (loggingConfig.LogOrleansGrains && isOrleansGrain) ||
                             (loggingConfig.LogMicrodotGrains && isMicrodotGrain) ||
                             (loggingConfig.LogServiceGrains && isServiceGrain);

            shouldLog = shouldLog && !ShouldSkipLoggingUnderRatio(loggingConfig, TracingContext.TryGetRequestID());
            GrainCallEvent grainEvent = null;

            if (shouldLog)
            {
                RequestTimings.GetOrCreate(); // Ensure request timings is created here and not in the grain call.
                RequestTimings.Current.Request.Start();
                grainEvent = _eventPublisher.CreateEvent();

                grainEvent.ParentSpanId = TracingContext.TryGetParentSpanID();
                grainEvent.SpanId       = Guid.NewGuid().ToString("N");
                TracingContext.SetParentSpan(grainEvent.SpanId);
            }

            Exception ex = null;

            try
            {
                await context.Invoke();
            }
            catch (Exception e)
            {
                ex = e;
                throw;
            }
            finally
            {
                if (shouldLog)
                {
                    RequestTimings.Current.Request.Stop();
                    PublishEvent(ex, grainTags, grainEvent);
                }
            }
        }
        private async Task <object> Interceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain target, IGrainMethodInvoker invoker)
        {
            if (targetMethod == null)
            {
                throw new ArgumentNullException(nameof(targetMethod));
            }

            var declaringNameSpace = targetMethod.DeclaringType?.Namespace;

            // Do not intercept Orleans grains or other grains which should not be included in statistics.
            if (targetMethod.DeclaringType.GetCustomAttribute <ExcludeGrainFromStatisticsAttribute>() != null ||
                declaringNameSpace?.StartsWith("Orleans") == true)
            {
                return(await invoker.Invoke(target, request));
            }

            RequestTimings.GetOrCreate(); // Ensure request timings is created here and not in the grain call.

            RequestTimings.Current.Request.Start();
            Exception ex = null;

            try
            {
                return(await invoker.Invoke(target, request));
            }
            catch (Exception e)
            {
                ex = e;
                throw;
            }
            finally
            {
                RequestTimings.Current.Request.Stop();
                var grainEvent = EventPublisher.CreateEvent();
                grainEvent.TargetType   = targetMethod.DeclaringType?.FullName;
                grainEvent.TargetMethod = targetMethod.Name;
                grainEvent.Exception    = ex;
                grainEvent.ErrCode      = ex != null ? null : (int?)0;

                try
                {
                    EventPublisher.TryPublish(grainEvent);
                }
                catch (Exception)
                {
                    EventsDiscarded.Increment();
                }
            }
        }
Esempio n. 3
0
        private async Task <object> IncomingCallInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain target, IGrainMethodInvoker invoker)
        {
            if (targetMethod == null)
            {
                throw new ArgumentNullException(nameof(targetMethod));
            }

            var declaringNameSpace = targetMethod.DeclaringType?.Namespace;

            // Do not intercept Orleans grains or other grains which should not be included in statistics.
            if (targetMethod.DeclaringType.GetCustomAttribute <ExcludeGrainFromStatisticsAttribute>() != null ||
                declaringNameSpace?.StartsWith("Orleans") == true)
            {
                return(await invoker.Invoke(target, request));
            }

            RequestTimings.GetOrCreate(); // Ensure request timings is created here and not in the grain call.

            RequestTimings.Current.Request.Start();
            Exception ex = null;

            try
            {
                RejectRequestIfLateOrOverloaded();
                return(await invoker.Invoke(target, request));
            }
            catch (Exception e)
            {
                ex = e;
                throw;
            }
            finally
            {
                RequestTimings.Current.Request.Stop();
                PublishEvent(targetMethod, target, ex);
            }
        }
Esempio n. 4
0
        private async Task HandleRequest(HttpListenerContext context)
        {
            RequestTimings.ClearCurrentTimings();
            using (context.Response)
            {
                var sw = Stopwatch.StartNew();

                // Special endpoints should not be logged/measured/traced like regular endpoints
                try
                {
                    foreach (var customEndpoint in CustomEndpoints)
                    {
                        if (await customEndpoint.TryHandle(context, (data, status, type) => TryWriteResponse(context, data, status, type)))
                        {
                            if (RequestTimings.Current.Request.ElapsedMS != null)
                            {
                                _metaEndpointsRoundtripTime.Record((long)RequestTimings.Current.Request.ElapsedMS, TimeUnit.Milliseconds);
                            }
                            return;
                        }
                    }
                }
                catch (Exception e)
                {
                    var ex = GetRelevantException(e);
                    await TryWriteResponse(context, ExceptionSerializer.Serialize(ex), GetExceptionStatusCode(ex));

                    return;
                }

                // Regular endpoint handling
                using (_activeRequestsCounter.NewContext("Request"))
                {
                    TracingContext.SetUpStorage();
                    RequestTimings.GetOrCreate(); // initialize request timing context

                    Exception ex;
                    Exception actualException = null;
                    string    methodName      = null;
                    // Initialize with empty object for protocol backwards-compatibility.

                    var requestData = new HttpServiceRequest {
                        TracingData = new TracingData()
                    };

                    ServiceMethod serviceMethod = null;
                    try
                    {
                        try
                        {
                            ValidateRequest(context);
                            await CheckSecureConnection(context);

                            requestData = await ParseRequest(context);

                            TracingContext.SetOverrides(requestData.Overrides);

                            serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                            methodName    = serviceMethod.ServiceInterfaceMethod.Name;
                        }
                        catch (Exception e)
                        {
                            actualException = e;
                            if (e is RequestException)
                            {
                                throw;
                            }

                            throw new RequestException("Invalid request", e);
                        }

                        var responseJson = await GetResponse(context, serviceMethod, requestData);
                        await TryWriteResponse(context, responseJson);

                        _successCounter.Increment();
                    }
                    catch (Exception e)
                    {
                        actualException = actualException ?? e;
                        _failureCounter.Increment();
                        ex = GetRelevantException(e);

                        string json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex));
                        await TryWriteResponse(context, json, GetExceptionStatusCode(ex));
                    }
                    finally
                    {
                        sw.Stop();
                        _roundtripTime.Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        if (methodName != null)
                        {
                            _endpointContext.Timer(methodName, Unit.Requests).Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        }
                        PublishEvent(requestData, actualException, serviceMethod, sw.Elapsed.TotalMilliseconds);
                    }
                }
            }
        }
Esempio n. 5
0
        private async Task <object> Interceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain target, IGrainMethodInvoker invoker)
        {
            if (targetMethod == null)
            {
                throw new ArgumentNullException(nameof(targetMethod));
            }

            var declaringNameSpace = targetMethod.DeclaringType?.Namespace;

            // Do not intercept Orleans grains or other grains which should not be included in statistics.
            if (targetMethod.DeclaringType.GetCustomAttribute <ExcludeGrainFromStatisticsAttribute>() != null ||
                declaringNameSpace?.StartsWith("Orleans") == true)
            {
                return(await invoker.Invoke(target, request));
            }

            RequestTimings.GetOrCreate(); // Ensure request timings is created here and not in the grain call.

            RequestTimings.Current.Request.Start();
            Exception ex = null;

            try
            {
                return(await invoker.Invoke(target, request));
            }
            catch (Exception e)
            {
                ex = e;
                throw;
            }
            finally
            {
                RequestTimings.Current.Request.Stop();
                var grainEvent = EventPublisher.CreateEvent();

                if (target.GetPrimaryKeyString() != null)
                {
                    grainEvent.GrainKeyString = target.GetPrimaryKeyString();
                }
                else if (target.IsPrimaryKeyBasedOnLong())
                {
                    grainEvent.GrainKeyLong      = target.GetPrimaryKeyLong(out var keyExt);
                    grainEvent.GrainKeyExtention = keyExt;
                }
                else
                {
                    grainEvent.GrainKeyGuid      = target.GetPrimaryKey(out var keyExt);
                    grainEvent.GrainKeyExtention = keyExt;
                }

                if (target is Grain grainTarget)
                {
                    grainEvent.SiloAddress = grainTarget.RuntimeIdentity;
                }

                grainEvent.SiloDeploymentId = ConfigBuilder.ClusterConfiguration.Globals.DeploymentId;


                grainEvent.TargetType   = targetMethod.DeclaringType?.FullName;
                grainEvent.TargetMethod = targetMethod.Name;
                grainEvent.Exception    = ex;
                grainEvent.ErrCode      = ex != null ? null : (int?)0;

                try
                {
                    EventPublisher.TryPublish(grainEvent);
                }
                catch (Exception)
                {
                    EventsDiscarded.Increment();
                }
            }
        }
        private async Task HandleRequest(HttpListenerContext context, long ticks, long timeFromLastReq)
        {
            try
            {
                var deltaDelayTicks = DateTime.UtcNow.Ticks - ticks;
                var sw = Stopwatch.StartNew();
                RequestTimings.ClearCurrentTimings();
                using (context.Response)
                {
                    // Special endpoints should not be logged/measured/traced like regular endpoints
                    // Access is allowed without HTTPS verifications since they don't expose anything sensitive (e.g. config values are encrypted)
                    if (await TryHandleSpecialEndpoints(context))
                    {
                        return;
                    }

                    // Regular endpoint handling
                    using (_activeRequestsCounter.NewContext("Request"))
                    {
                        RequestTimings.GetOrCreate(); // initialize request timing context

                        string methodName = null;
                        // Initialize with empty object for protocol backwards-compatibility.

                        var requestData = new HttpServiceRequest {
                            TracingData = new TracingData()
                        };
                        object[]         argumentsWithDefaults = null;
                        ServiceMethod    serviceMethod         = null;
                        ServiceCallEvent callEvent             = _serverRequestPublisher.GetNewCallEvent();
                        try
                        {
                            try
                            {
                                await CheckSecureConnection(context);

                                ValidateRequest(context);

                                requestData = await ParseRequest(context);


                                //-----------------------------------------------------------------------------------------
                                // Don't move TracingContext writes main flow, IT have to be here, to avoid side changes
                                //-----------------------------------------------------------------------------------------
                                TracingContext.SetRequestID(requestData.TracingData.RequestID);
                                TracingContext.SpanStartTime    = requestData.TracingData.SpanStartTime;
                                TracingContext.AbandonRequestBy = requestData.TracingData.AbandonRequestBy;
                                TracingContext.SetParentSpan(
                                    requestData.TracingData.SpanID ?? Guid.NewGuid().ToString("N"));
                                TracingContext.SetOverrides(requestData.Overrides);
                                if (requestData.TracingData.Tags != null)
                                {
                                    TracingContext.Tags = new ContextTags(requestData.TracingData.Tags);
                                }
                                TracingContext.AdditionalProperties = requestData.TracingData.AdditionalProperties;

                                callEvent.ServiceMethodSchema = context.Request.IsSecureConnection ? "HTTPS" : "HTTP";
                                SetCallEventRequestData(callEvent, requestData);

                                serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                                callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name;
                                methodName = serviceMethod.ServiceInterfaceMethod.Name;
                                var arguments = requestData.Target.IsWeaklyTyped
                                    ? GetParametersByName(serviceMethod, requestData.Arguments)
                                    : requestData.Arguments.Values.Cast <object>().ToArray();
                                argumentsWithDefaults =
                                    GetConvertedAndDefaultArguments(serviceMethod.ServiceInterfaceMethod, arguments);

                                if (_extendedDelayTimeLogging)
                                {
                                    callEvent.RecvDateTicks        = ticks;
                                    callEvent.ReqStartupDeltaTicks = deltaDelayTicks;
                                    callEvent.TimeFromLastReq      = timeFromLastReq;
                                    var outstandingReqs = Interlocked.Read(ref OutstandingRequests);
                                    callEvent.OutstandingRequests = outstandingReqs;
                                    if (deltaDelayTicks > 10_000_000)
                                    {
                                        callEvent.CollectionCountGen0 = GC.CollectionCount(0);
                                        callEvent.CollectionCountGen1 = GC.CollectionCount(1);
                                        callEvent.CollectionCountGen2 = GC.CollectionCount(2);
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                callEvent.Exception = e;
                                if (e is RequestException)
                                {
                                    throw;
                                }

                                throw new RequestException("Invalid request", e);
                            }

                            RejectRequestIfLateOrOverloaded();

                            var responseJson = await GetResponse(context, serviceMethod, requestData,
                                                                 argumentsWithDefaults);

                            if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent))
                            {
                                callEvent.ErrCode = 0;
                                _successCounter.Increment();
                            }
                            else
                            {
                                _failureCounter.Increment();
                            }
                        }
                        catch (Exception e)
                        {
                            callEvent.Exception = callEvent.Exception ?? e;
                            _failureCounter.Increment();
                            Exception ex   = GetRelevantException(e);
                            string    json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex));
                            await TryWriteResponse(context, json, GetExceptionStatusCode(ex),
                                                   serviceCallEvent : callEvent);
                        }
                        finally
                        {
                            sw.Stop();
                            callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds;

                            _roundtripTime.Record((long)(sw.Elapsed.TotalMilliseconds * 1000000),
                                                  TimeUnit.Nanoseconds);
                            if (methodName != null)
                            {
                                _endpointContext.Timer(methodName, Unit.Requests)
                                .Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                            }

                            _serverRequestPublisher.TryPublish(callEvent, argumentsWithDefaults, serviceMethod);
                        }
                    }
                }
            }
            finally
            {
                Interlocked.Decrement(ref OutstandingRequests);
            }
        }
        private async Task HandleRequest(HttpListenerContext context)
        {
            RequestTimings.ClearCurrentTimings();
            using (context.Response)
            {
                var       sw = Stopwatch.StartNew();
                Exception ex;

                // Special endpoints should not be logged/measured/traced like regular endpoints
                try
                {
                    foreach (var customEndpoint in CustomEndpoints)
                    {
                        if (await customEndpoint.TryHandle(context, (data, status, type) => TryWriteResponse(context, data, status, type)))
                        {
                            return;
                        }
                    }
                }
                catch (Exception e)
                {
                    ex = GetRelevantException(e);
                    await TryWriteResponse(context, ExceptionSerializer.Serialize(ex), GetExceptionStatusCode(ex));

                    return;
                }

                // Regular endpoint handling
                TracingContext.SetUpStorage();
                RequestTimings.GetOrCreate(); // initialize request timing context

                Exception actualException = null;
                string    methodName      = null;
                // Initialize with empty object for protocol backwards-compatibility.

                var requestData = new HttpServiceRequest {
                    TracingData = new TracingData()
                };
                ServiceMethod serviceMethod = null;
                try
                {
                    try
                    {
                        ValidateRequest(context);
                        await CheckSecureConnection(context);

                        requestData = await ParseRequest(context);

                        TracingContext.SetOverrides(requestData.Overrides);

                        serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                        methodName    = serviceMethod.ServiceInterfaceMethod.Name;
                    }
                    catch (Exception e)
                    {
                        actualException = e;
                        if (e is RequestException)
                        {
                            throw;
                        }

                        throw new RequestException("Invalid request", e);
                    }

                    RejectRequestIfLateOrOverloaded();

                    var responseJson = await GetResponse(context, serviceMethod, requestData);
                    await TryWriteResponse(context, responseJson);
                }
                catch (Exception e)
                {
                    actualException = actualException ?? e;
                    ex = GetRelevantException(e);

                    string json = ExceptionSerializer.Serialize(ex);
                    await TryWriteResponse(context, json, GetExceptionStatusCode(ex));
                }
                finally
                {
                    sw.Stop();
                    _serverRequestPublisher.TryPublish(requestData, actualException, serviceMethod, sw.Elapsed.TotalMilliseconds);
                }
            }
        }
Esempio n. 8
0
        private async Task HandleRequest(HttpListenerContext context)
        {
            RequestTimings.ClearCurrentTimings();
            using (context.Response)
            {
                var sw = Stopwatch.StartNew();

                // Special endpoints should not be logged/measured/traced like regular endpoints
                if (await TryHandleSpecialEndpoints(context))
                {
                    return;
                }

                // Regular endpoint handling
                using (_activeRequestsCounter.NewContext("Request"))
                {
                    RequestTimings.GetOrCreate(); // initialize request timing context

                    string methodName = null;
                    // Initialize with empty object for protocol backwards-compatibility.

                    var requestData = new HttpServiceRequest {
                        TracingData = new TracingData()
                    };
                    object[]         argumentsWithDefaults = null;
                    ServiceMethod    serviceMethod         = null;
                    ServiceCallEvent callEvent             = _serverRequestPublisher.GetNewCallEvent();
                    try
                    {
                        try
                        {
                            ValidateRequest(context);
                            await CheckSecureConnection(context);

                            requestData = await ParseRequest(context);


                            //-----------------------------------------------------------------------------------------
                            // Don't move TracingContext writes main flow, IT have to be here, to avoid side changes
                            //-----------------------------------------------------------------------------------------
                            TracingContext.SetRequestID(requestData.TracingData.RequestID);
                            TracingContext.SpanStartTime    = requestData.TracingData.SpanStartTime;
                            TracingContext.AbandonRequestBy = requestData.TracingData.AbandonRequestBy;
                            TracingContext.SetParentSpan(requestData.TracingData.SpanID ?? Guid.NewGuid().ToString("N"));

                            SetCallEventRequestData(callEvent, requestData);

                            TracingContext.SetOverrides(requestData.Overrides);

                            serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                            callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name;
                            methodName = serviceMethod.ServiceInterfaceMethod.Name;
                            var arguments = requestData.Target.IsWeaklyTyped ? GetParametersByName(serviceMethod, requestData.Arguments) : requestData.Arguments.Values.Cast <object>().ToArray();
                            argumentsWithDefaults = GetConvertedAndDefaultArguments(serviceMethod.ServiceInterfaceMethod, arguments);
                        }
                        catch (Exception e)
                        {
                            callEvent.Exception = e;
                            if (e is RequestException)
                            {
                                throw;
                            }

                            throw new RequestException("Invalid request", e);
                        }

                        RejectRequestIfLateOrOverloaded();

                        var responseJson = await GetResponse(context, serviceMethod, requestData, argumentsWithDefaults);

                        if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent))
                        {
                            callEvent.ErrCode = 0;
                            _successCounter.Increment();
                        }
                        else
                        {
                            _failureCounter.Increment();
                        }
                    }
                    catch (Exception e)
                    {
                        callEvent.Exception = callEvent.Exception ?? e;
                        _failureCounter.Increment();
                        Exception ex   = GetRelevantException(e);
                        string    json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex));
                        await TryWriteResponse(context, json, GetExceptionStatusCode(ex), serviceCallEvent : callEvent);
                    }
                    finally
                    {
                        sw.Stop();
                        callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds;

                        _roundtripTime.Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        if (methodName != null)
                        {
                            _endpointContext.Timer(methodName, Unit.Requests).Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        }

                        _serverRequestPublisher.TryPublish(callEvent, argumentsWithDefaults, serviceMethod);
                    }
                }
            }
        }
Esempio n. 9
0
        private async Task HandleRequest(HttpListenerContext context)
        {
            RequestTimings.ClearCurrentTimings();
            using (context.Response)
            {
                var sw = Stopwatch.StartNew();

                // Special endpoints should not be logged/measured/traced like regular endpoints
                if (await TryHandleSpecialEndpoints(context))
                {
                    return;
                }

                // Regular endpoint handling
                using (_activeRequestsCounter.NewContext("Request"))
                {
                    TracingContext.SetUpStorage();
                    RequestTimings.GetOrCreate(); // initialize request timing context

                    string methodName = null;
                    // Initialize with empty object for protocol backwards-compatibility.

                    var requestData = new HttpServiceRequest {
                        TracingData = new TracingData()
                    };
                    ServiceMethod    serviceMethod = null;
                    ServiceCallEvent callEvent     = _serverRequestPublisher.GetNewCallEvent();
                    try
                    {
                        try
                        {
                            ValidateRequest(context);
                            await CheckSecureConnection(context);

                            requestData = await ParseRequest(context);

                            SetCallEventRequestData(callEvent, requestData);

                            TracingContext.SetOverrides(requestData.Overrides);

                            serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                            callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name;
                            methodName = serviceMethod.ServiceInterfaceMethod.Name;
                        }
                        catch (Exception e)
                        {
                            callEvent.Exception = e;
                            if (e is RequestException)
                            {
                                throw;
                            }

                            throw new RequestException("Invalid request", e);
                        }

                        RejectRequestIfLateOrOverloaded();

                        var responseJson = await GetResponse(context, serviceMethod, requestData);

                        if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent))
                        {
                            callEvent.ErrCode = 0;
                            _successCounter.Increment();
                        }
                        else
                        {
                            _failureCounter.Increment();
                        }
                    }
                    catch (Exception e)
                    {
                        callEvent.Exception = callEvent.Exception ?? e;
                        _failureCounter.Increment();
                        Exception ex   = GetRelevantException(e);
                        string    json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex));
                        await TryWriteResponse(context, json, GetExceptionStatusCode(ex), serviceCallEvent : callEvent);
                    }
                    finally
                    {
                        sw.Stop();
                        callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds;

                        _roundtripTime.Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        if (methodName != null)
                        {
                            _endpointContext.Timer(methodName, Unit.Requests).Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        }

                        IEnumerable <DictionaryEntry> arguments = (requestData.Arguments ?? new OrderedDictionary()).Cast <DictionaryEntry>();
                        _serverRequestPublisher.TryPublish(callEvent, arguments, serviceMethod);
                    }
                }
            }
        }
        public async Task Invoke(IIncomingGrainCallContext context)
        {
            if (context.InterfaceMethod == null || context.InterfaceMethod.DeclaringType == null)
            {
                // We observing behavior when no interface method
                // We still don't want to prevent it happen.
                await context.Invoke();

                return;
            }
            // Identify the grain type

            bool isOrleansGrain = context.InterfaceMethod.Module.Assembly.FullName?.StartsWith("Orleans") == true;
            //TODO add test that validate that we are not introducing new grain in micro dot
            bool isMicrodotGrain = context.InterfaceMethod.DeclaringType.Name == nameof(IRequestProcessingGrain);
            bool isServiceGrain  = isOrleansGrain == false && isMicrodotGrain == false;

            // Drop the request if we're overloaded
            var loadSheddingConfig = _loadSheddingConfig();

            if (
                (loadSheddingConfig.ApplyToMicrodotGrains && isMicrodotGrain) ||
                (loadSheddingConfig.ApplyToServiceGrains && isServiceGrain)
                )
            {
                RejectRequestIfLateOrOverloaded(context);
            }
            var loggingConfig = _grainLoggingConfig();

            var shouldLoad = ((loggingConfig.LogOrleansGrains && isOrleansGrain) ||
                              (loggingConfig.LogMicrodotGrains && isMicrodotGrain) ||
                              (loggingConfig.LogServiceGrains && isServiceGrain));

            if (shouldLoad == false)
            {
                await context.Invoke();

                return;
            }

            string callId = TracingContext.TryGetRequestID();
            uint   max    = (uint)Math.Round(loggingConfig.LogRatio * uint.MaxValue);

            if (loggingConfig.LogRatio == 0 || callId == null || (uint)callId.GetHashCode() % uint.MaxValue > max)
            {
                await context.Invoke();

                return;
            }

            RequestTimings.GetOrCreate(); // Ensure request timings is created here and not in the grain call.
            RequestTimings.Current.Request.Start();
            Exception ex = null;

            try
            {
                await context.Invoke();
            }
            catch (Exception e)
            {
                ex = e;
                throw;
            }
            finally
            {
                RequestTimings.Current.Request.Stop();
                PublishEvent(context, ex);
            }
        }