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();
                }
            }
        }
Пример #2
0
        public async Task <object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            if (methodInfo.Name == nameof(One) && methodInfo.GetParameters().Length == 0)
            {
                if (request.MethodId != 14142)
                {
                    throw new Exception($"Method id of 'One' must be 14142, not {request.MethodId}.");
                }
                return("intercepted one with no args");
            }

            var result = await invoker.Invoke(this, request);

            // To prove that the MethodInfo is from the implementation and not the interface,
            // we check for this attribute which is only present on the implementation. This could be
            // done in a simpler fashion, but this demonstrates a potential usage scenario.
            var shouldMessWithResult = methodInfo.GetCustomAttribute <MessWithResultAttribute>();
            var resultString         = result as string;

            if (shouldMessWithResult != null && resultString != null)
            {
                result = string.Concat(resultString.Reverse());
            }

            return(result);
        }
Пример #3
0
        private Task <object> InvokeWithInterceptors(IAddressable target, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            // If the target has a grain-level interceptor or there is a silo-level interceptor, intercept the
            // call.
            var siloWideInterceptor  = this.CurrentStreamProviderRuntime.GetInvokeInterceptor();
            var grainWithInterceptor = target as IGrainInvokeInterceptor;

            // Silo-wide interceptors do not operate on system targets.
            var hasSiloWideInterceptor   = siloWideInterceptor != null && target is IGrain;
            var hasGrainLevelInterceptor = grainWithInterceptor != null;

            if (!hasGrainLevelInterceptor && !hasSiloWideInterceptor)
            {
                // The call is not intercepted at either the silo or the grain level, so call the invoker
                // directly.
                return(invoker.Invoke(target, request));
            }

            // If the request is intended for an extension object, use that as the implementation type, otherwise use
            // the target object.
            Type            implementationType;
            var             extensionMap = invoker as IGrainExtensionMap;
            IGrainExtension extension;

            if (extensionMap != null && extensionMap.TryGetExtension(request.InterfaceId, out extension))
            {
                implementationType = extension.GetType();
            }
            else
            {
                implementationType = target.GetType();
            }

            // Get an invoker which delegates to the grain's IGrainInvocationInterceptor implementation.
            // If the grain does not implement IGrainInvocationInterceptor, then the invoker simply delegates
            // calls to the provided invoker.
            var interceptedMethodInvoker = interceptedMethodInvokerCache.GetOrCreate(
                implementationType,
                request.InterfaceId,
                invoker);
            var methodInfo = interceptedMethodInvoker.GetMethodInfo(request.MethodId);

            if (hasSiloWideInterceptor)
            {
                // There is a silo-level interceptor and possibly a grain-level interceptor.
                // As a minor optimization, only pass the intercepted invoker if there is a grain-level
                // interceptor.
                return(siloWideInterceptor(
                           methodInfo,
                           request,
                           (IGrain)target,
                           hasGrainLevelInterceptor ? interceptedMethodInvoker : invoker));
            }

            // The grain has an invoke method, but there is no silo-wide interceptor.
            return(grainWithInterceptor.Invoke(methodInfo, request, invoker));
        }
Пример #4
0
        public Task <object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            if (methodInfo.Name == nameof(GetInputAsString))
            {
                return(Task.FromResult <object>($"Hah! You wanted {request.Arguments[0]}, but you got me!"));
            }

            return(invoker.Invoke(this, request));
        }
Пример #5
0
 public async Task <object> Invoke(MethodInfo method, InvokeMethodRequest request, IGrainMethodInvoker invoker)
 {
     try
     {
         return(await invoker.Invoke(this, request));
     }
     catch (Exception e)
     {
         PrettyConsole.Line("Exception in interceptor");
         DeactivateOnIdle();
         throw;
     }
 }
        public async Task <object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            var initialLastStreamValue = this.lastStreamValue;
            var result = await invoker.Invoke(this, request);

            // If the last stream value changed after the invoke, then the stream must have produced a value, double
            // it for testing purposes.
            if (this.lastStreamValue != initialLastStreamValue)
            {
                this.lastStreamValue *= 2;
            }

            return(result);
        }
Пример #7
0
        public async Task<object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            var initialLastStreamValue = this.lastStreamValue;
            var result = await invoker.Invoke(this, request);

            // If the last stream value changed after the invoke, then the stream must have produced a value, double
            // it for testing purposes.
            if (this.lastStreamValue != initialLastStreamValue)
            {
                this.lastStreamValue *= 2;
            }

            return result;
        }
Пример #8
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);
            }
        }
Пример #9
0
        /// <inheritdoc />
        public async Task Invoke()
        {
            try
            {
                // Execute each stage in the pipeline. Each successive call to this method will invoke the next stage.
                // Stages which are not implemented (eg, because the user has not specified an interceptor) are skipped.
                var numFilters = filters.Count;
                if (stage < numFilters)
                {
                    // Call each of the specified interceptors.
                    var systemWideFilter = this.filters[stage];
                    stage++;
                    await systemWideFilter.Invoke(this);

                    return;
                }

                if (stage == numFilters)
                {
                    stage++;

                    // Grain-level invoker, if present.
                    if (this.Grain is IIncomingGrainCallFilter grainClassLevelFilter)
                    {
                        await grainClassLevelFilter.Invoke(this);

                        return;
                    }
                }

                if (stage == numFilters + 1)
                {
                    // Finally call the root-level invoker.
                    stage++;
                    this.Result = await rootInvoker.Invoke(this.grainContext, this.request);

                    return;
                }
            }
            finally
            {
                stage--;
            }

            // If this method has been called more than the expected number of times, that is invalid.
            ThrowInvalidCall();
        }
Пример #10
0
        // capture stats
        async Task <object> InvokeInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain, IGrainMethodInvoker invoker)
        {
            // round down to nearest 10 seconds to group results
            var grainName = grain.GetType().FullName;
            var stopwatch = Stopwatch.StartNew();

            // invoke grain
            object result = null;

            if (this.innerInterceptor != null)
            {
                result = await this.innerInterceptor(targetMethod, request, grain, invoker);
            }
            else
            {
                result = await invoker.Invoke(grain, request);
            }

            stopwatch.Stop();

            var elapsedMs = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond;

            var key = $"{grainName}.{targetMethod?.Name ?? "Unknown"}";

            grainTrace.AddOrUpdate(key, _ => {
                return(new GrainTraceEntry
                {
                    Count = 1,
                    SiloAddress = siloAddress,
                    ElapsedTime = elapsedMs,
                    Grain = grainName,
                    Method = targetMethod?.Name ?? "Unknown",
                    Period = DateTime.UtcNow
                });
            },
                                   (_, last) => {
                last.Count       += 1;
                last.ElapsedTime += elapsedMs;
                return(last);
            });

            return(result);
        }
Пример #11
0
        // capture stats
        async Task<object> InvokeInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain, IGrainMethodInvoker invoker)
        {
            // round down to nearest 10 seconds to group results
            var grainName = grain.GetType().FullName;
            var stopwatch = Stopwatch.StartNew();

            // invoke grain
            object result = null;
            if (this.innerInterceptor != null)
            {
                result = await this.innerInterceptor(targetMethod, request, grain, invoker);
            }
            else
            {
                result = await invoker.Invoke(grain, request);
            }

            stopwatch.Stop();

            var elapsedMs = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond;

            var key = $"{grainName}.{targetMethod?.Name ?? "Unknown"}";

            grainTrace.AddOrUpdate(key, _ => {
                return new GrainTraceEntry
                {
                    Count = 1,
                    SiloAddress = siloAddress,
                    ElapsedTime = elapsedMs,
                    Grain = grainName,
                    Method = targetMethod?.Name ?? "Unknown",
                    Period = DateTime.UtcNow
                };
            },
            (_, last) => {
                last.Count += 1;
                last.ElapsedTime += elapsedMs;
                return last;
            });

            return result;
        }
Пример #12
0
        public async Task<object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            if (methodInfo.Name == "One" && methodInfo.GetParameters().Length == 0)
            {
                return "intercepted one with no args";
            }

            var result = await invoker.Invoke(this, request);

            // To prove that the MethodInfo is from the implementation and not the interface,
            // we check for this attribute which is only present on the implementation. This could be
            // done in a simpler fashion, but this demonstrates a potential usage scenario.
            var shouldMessWithResult = methodInfo.GetCustomAttribute<MessWithResultAttribute>();
            var resultString = result as string;
            if (shouldMessWithResult != null && resultString !=null)
            {
                result = string.Concat(resultString.Reverse());
            }

            return result;
        }
Пример #13
0
        public async Task Invoke(HttpContext context)
        {
            try
            {
                var route  = this.ResplveRouteData(context);
                var grain  = this._grainBuilder.GetGrain(route);
                var result = await _grainInvoker.Invoke(grain, route);

                context.Response.StatusCode  = 200;
                context.Response.ContentType = "application/json";
                using (var writer = new StreamWriter(context.Response.Body))
                {
                    _serializer.Serialize(writer, result);
                    await writer.FlushAsync();
                }
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex, "Request url " + context.Request.Host.ToString());
                throw ex;
            }
        }
Пример #14
0
        public async Task <object> Invoke(MethodInfo method, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            var value = RequestContext.Get(Key) as string;

            if (value != null)
            {
                RequestContext.Set(Key, value + '5');
            }

            if (string.Equals(method?.Name, nameof(CallWithBadInterceptors)) && (bool)request.Arguments[0])
            {
                await context.Invoke();
            }

            var result = await invoker.Invoke(this, request);

            if (string.Equals(method?.Name, nameof(CallWithBadInterceptors)) && (bool)request.Arguments[1])
            {
                await context.Invoke();
            }

            return(result);
        }
Пример #15
0
        /// <summary>
        /// Handles the an InvokeMethodRequest message on given target.
        /// </summary>
        /// <remarks>
        /// Options when we receive a InvokeMethodRequest
        /// ----------------------------------------------
        /// 1) Intercepted RPC
        /// 2) Request to start a reactive computation for this method invocation
        /// 3) KeepAlive request of the reactive computation for this method invocation
        /// 4) Normal Application RPC
        /// 5) System RPC
        /// </remarks>
        /// <returns></returns>
        internal async Task Invoke(IAddressable target, IInvokable invokable, Message message)
        {
            try
            {
                // Don't process messages that have already timed out
                if (message.IsExpired)
                {
                    message.DropExpiredMessage(MessagingStatisticsGroup.Phase.Invoke);
                    return;
                }

                RequestContext.Import(message.RequestContextData);
                if (Config.Globals.PerformDeadlockDetection && !message.TargetGrain.IsSystemTarget)
                {
                    UpdateDeadlockInfoInRequestContext(new RequestInvocationHistory(message));
                    // RequestContext is automatically saved in the msg upon send and propagated to the next hop
                    // in RuntimeClient.CreateMessage -> RequestContext.ExportToMessage(message);
                }

                object resultObject;
                try
                {
                    var request = (InvokeMethodRequest)message.BodyObject;
                    if (request.Arguments != null)
                    {
                        CancellationSourcesExtension.RegisterCancellationTokens(target, request, logger);
                    }

                    // Get the invoker for this invocation
                    IGrainMethodInvoker invoker = GetGrainMethodInvoker(target, invokable, message, request);

                    // Check whether this call should be intercepted
                    var siloWideInterceptor  = SiloProviderRuntime.Instance.GetInvokeInterceptor();
                    var grainWithInterceptor = target as IGrainInvokeInterceptor;

                    // Silo-wide interceptors do not operate on system targets.
                    var hasSiloWideInterceptor   = siloWideInterceptor != null && target is IGrain;
                    var hasGrainLevelInterceptor = grainWithInterceptor != null;

                    // Normal Application Call = an application call made from grain to grain or from client to grain.
                    // Some system-related calls such as the IReminderTable are encoded as Application messages, therefore we needed this check.
                    var NormalApplicationCall = message.Category == Message.Categories.Application && message.TargetGrain.IsGrain && (message.SendingGrain.IsGrain || message.SendingGrain.IsClient);

                    // 1) If the target has a grain-level interceptor or there is a silo-level interceptor, intercept the
                    // call.
                    if (hasGrainLevelInterceptor || hasSiloWideInterceptor)
                    {
                        resultObject = await InvokeWithInterceptors(target, request, invoker, hasSiloWideInterceptor, siloWideInterceptor, hasGrainLevelInterceptor, grainWithInterceptor);
                    }

                    else if (NormalApplicationCall)
                    {
                        // 2) Request to start a reactive computation for this method invocation
                        if (message.IsRcExecute())
                        {
                            HandleReactiveComputationExecute(target, request, message, invoker);
                            return; // Does not expect a return (OneWay Message)
                        }

                        // 3) Refresh Reactive Computation Subscription
                        else if (message.IsRcKeepAlive())
                        {
                            HandleReactiveComputationExecute(target, request, message, invoker, true);
                            return; // Does not expect a return (OneWay Message)
                        }

                        // 4) Normal application RPC call
                        else
                        {
                            // Invoke the method
                            resultObject = await invoker.Invoke(target, request);

                            // Check if there are any active reactive computations in this grain that require recomputation after this call
                            InsideRcManager.RecomputeSummaries();
                        }
                    }

                    // 5) System RPC call
                    else
                    {
                        resultObject = await invoker.Invoke(target, request);
                    }
                }
                catch (Exception exc1)
                {
                    if (invokeExceptionLogger.IsVerbose || message.Direction == Message.Directions.OneWay)
                    {
                        invokeExceptionLogger.Warn(ErrorCode.GrainInvokeException,
                                                   "Exception during Grain method call of message: " + message, exc1);
                    }
                    if (message.Direction != Message.Directions.OneWay)
                    {
                        SafeSendExceptionResponse(message, exc1);
                    }
                    return;
                }

                if (message.Direction == Message.Directions.OneWay)
                {
                    return;
                }

                SafeSendResponse(message, resultObject);
            }
            catch (Exception exc2)
            {
                logger.Warn(ErrorCode.Runtime_Error_100329, "Exception during Invoke of message: " + message, exc2);
                if (message.Direction != Message.Directions.OneWay)
                {
                    SafeSendExceptionResponse(message, exc2);
                }
            }
        }
Пример #16
0
        // capture stats
        async Task <object> InvokeInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain, IGrainMethodInvoker invoker)
        {
            var grainName = grain.GetType().FullName;
            var stopwatch = Stopwatch.StartNew();

            // invoke grain
            object result      = null;
            var    isException = false;

            try
            {
                if (this.innerInterceptor != null)
                {
                    result = await this.innerInterceptor(targetMethod, request, grain, invoker).ConfigureAwait(false);
                }
                else
                {
                    result = await invoker.Invoke(grain, request).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                isException = true;
                throw;
            }
            finally
            {
                try
                {
                    stopwatch.Stop();

                    var elapsedMs = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond;

                    var key = string.Format("{0}.{1}", grainName, formatMethodName(targetMethod, request, grain));

                    grainTrace.AddOrUpdate(key, _ =>
                    {
                        return(new GrainTraceEntry
                        {
                            Count = 1,
                            ExceptionCount = (isException ? 1 : 0),
                            SiloAddress = siloAddress,
                            ElapsedTime = elapsedMs,
                            Grain = grainName,
                            Method = formatMethodName(targetMethod, request, grain),
                            Period = DateTime.UtcNow
                        });
                    },
                                           (_, last) =>
                    {
                        last.Count       += 1;
                        last.ElapsedTime += elapsedMs;
                        if (isException)
                        {
                            last.ExceptionCount += 1;
                        }
                        return(last);
                    });
                }
                catch (Exception ex)
                {
                    this.Logger.Error(100002, "error recording results for grain", ex);
                }
            }

            return(result);
        }
Пример #17
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();
                }
            }
        }
Пример #18
0
        private Task<object> InvokeWithInterceptors(IAddressable target, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            // If the target has a grain-level interceptor or there is a silo-level interceptor, intercept the
            // call.
            var siloWideInterceptor = SiloProviderRuntime.Instance.GetInvokeInterceptor();
            var grainWithInterceptor = target as IGrainInvokeInterceptor;
            
            // Silo-wide interceptors do not operate on system targets.
            var hasSiloWideInterceptor = siloWideInterceptor != null && target is IGrain;
            var hasGrainLevelInterceptor = grainWithInterceptor != null;
            
            if (!hasGrainLevelInterceptor && !hasSiloWideInterceptor)
            {
                // The call is not intercepted at either the silo or the grain level, so call the invoker
                // directly.
                return invoker.Invoke(target, request);
            }

            // Get an invoker which delegates to the grain's IGrainInvocationInterceptor implementation.
            // If the grain does not implement IGrainInvocationInterceptor, then the invoker simply delegates
            // calls to the provided invoker.
            var interceptedMethodInvoker = interceptedMethodInvokerCache.GetOrCreate(
                target.GetType(),
                request.InterfaceId,
                invoker);
            var methodInfo = interceptedMethodInvoker.GetMethodInfo(request.MethodId);
            if (hasSiloWideInterceptor)
            {
                // There is a silo-level interceptor and possibly a grain-level interceptor.
                // As a minor optimization, only pass the intercepted invoker if there is a grain-level
                // interceptor.
                return siloWideInterceptor(
                    methodInfo,
                    request,
                    (IGrain)target,
                    hasGrainLevelInterceptor ? interceptedMethodInvoker : invoker);
            }

            // The grain has an invoke method, but there is no silo-wide interceptor.
            return grainWithInterceptor.Invoke(methodInfo, request, invoker);
        }
Пример #19
0
        async Task <object> SiloInterceptor(MethodInfo method, InvokeMethodRequest request,
                                            IGrain grain, IGrainMethodInvoker invoker)
        {
            try
            {
                object result = PreviousInterceptor != null
                    ? await PreviousInterceptor(method, request, grain, invoker)
                    : await invoker.Invoke(grain, request);

                //if (PreviousInterceptor != null)
                //    result = await PreviousInterceptor(method, request, grain, invoker);

                //// Invoke the request and return the result back to the caller.
                //var result = await invoker.Invoke(grain, request);

                if (Configuration.TrackMethodGrainCalls)
                {
                    // Would be nice if we could figure out if this is a local or remote call,
                    // and perhaps caller / calling silo... Unless I've got something backwards
                    logger.IncrementMetric($"GrainMethodCall:{grain.GetType().Name}:{method.Name}");
                }

                return(result);
            }
            catch (TimeoutException ex) // Not sure if this is going to be an innerException here or if everything gets unrolled... Fingers crossed for now!
            {
                if (Configuration.TrackExceptionCounters)
                {
                    logger.IncrementMetric($"GrainInvokeTimeout:{grain.GetType().Name}:{method.Name}");
                }

                if (Configuration.LogExceptions)
                {
                    logger.TrackException(ex, new Dictionary <string, string>
                    {
                        { "GrainType", grain.GetType().Name },
                        { "MethodName", method.Name },
                    });
                }

                throw;
            }
            catch (Exception ex)
            {
                if (Configuration.TrackExceptionCounters)
                {
                    logger.IncrementMetric($"GrainException:{grain.GetType().Name}:{method.Name}");
                }

                if (Configuration.LogExceptions)
                {
                    logger.TrackException(ex, new Dictionary <string, string>
                    {
                        { "GrainType", grain.GetType().Name },
                        { "MethodName", method.Name },
                    });
                }

                throw;
            }
        }
        // capture stats
        async Task<object> InvokeInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain, IGrainMethodInvoker invoker)
        {
            var grainName = grain.GetType().FullName;
            var stopwatch = Stopwatch.StartNew();

            // invoke grain
            object result = null;
            var isException = false;

            try
            {
                if (this.innerInterceptor != null)
                {
                    result = await this.innerInterceptor(targetMethod, request, grain, invoker);
                }
                else
                {
                    result = await invoker.Invoke(grain, request);
                }
            }
            catch (Exception ex)
            {
                isException = true;
                throw;
            }
            finally
            {

                try
                {
                    stopwatch.Stop();

                    var elapsedMs = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond;

                    var key = string.Format("{0}.{1}", grainName, targetMethod?.Name ?? "Unknown");

                    grainTrace.AddOrUpdate(key, _ =>
                    {
                        return new GrainTraceEntry
                        {
                            Count = 1,
                            ExceptionCount = (isException ? 1 : 0),
                            SiloAddress = siloAddress,
                            ElapsedTime = elapsedMs,
                            Grain = grainName ,
                            Method = targetMethod?.Name ?? "Unknown",
                            Period = DateTime.UtcNow
                        };
                    },
                    (_, last) =>
                    {
                        last.Count += 1;
                        last.ElapsedTime += elapsedMs;
                        if (isException) last.ExceptionCount += 1;
                        return last;
                    });
                }
                catch (Exception ex)
                {
                    this.Logger.Error(100002, "error recording results for grain", ex);
                }
            }

            return result;
        }
        public async Task Invoke(DownstreamContext context)
        {
            var routeResponse = this._routeValuesBuilder.Build(context);

            if (routeResponse.IsError)
            {
                Logger.LogDebug("IRouteValuesBuilder Parsing Route Values errors");
                SetPipelineError(context, routeResponse.Errors);
                return;
            }

            //Olreans interface authorization verification
            var authorised = this._authorisation.Authorise(context.HttpContext.User, routeResponse.Data);

            if (authorised.IsError)
            {
                _logger.LogWarning("error orleas authorising user scopes");
                SetPipelineError(context, authorised.Errors);
                return;
            }

            var clientBuilderResponse = _clusterClientBuilder.Build(routeResponse.Data, context);

            if (clientBuilderResponse.IsError)
            {
                Logger.LogDebug("IClusterClientBuilder Building Cluster Client and connecting Orleans error");
                SetPipelineError(context, routeResponse.Errors);
                return;
            }

            //Get a Grain instance
            var grainResponse = this._grainReference.GetGrainReference(routeResponse.Data);

            if (grainResponse.IsError)
            {
                Logger.LogDebug("IGrainReference Get a Orleas Grain instance error");
                SetPipelineError(context, routeResponse.Errors);
                return;
            }

            try
            {
                //Orleans injects the DownstreamContext into the RequestContext when requested
                this._config.RequestContextInjection?.Invoke(context);
            }
            catch (Exception ex)
            {
                Logger.LogError("Orleans injects the DownstreamContext into the RequestContext when requested error", ex);
                SetPipelineError(context, new UnknownError("Orleans injects the DownstreamContext into the RequestContext when requested error"));
                return;
            }

            //Grain Dynamic request
            try
            {
                var resultResponse = await _grainInvoker.Invoke(grainResponse.Data, routeResponse.Data);

                if (resultResponse.IsError)
                {
                    Logger.LogDebug("IGrainMethodInvoker  Grain Dynamic request error");
                    SetPipelineError(context, resultResponse.Errors);
                    return;
                }
                Logger.LogDebug("setting http response message");
                context.HttpContext.Response.ContentType = resultResponse.Data.Content.ContentType;
                context.DownstreamResponse = new DownstreamResponse(resultResponse.Data.Content, resultResponse.Data.StatusCode, resultResponse.Data.Headers, "");
            }
            catch (Exception ex)
            {
                Logger.LogError($"Request Orleans Silo exception;Uri:{context.DownstreamRequest.ToUri()}", ex);
                throw new OrleansRequestException("Request Orleans Silo exception ");
            }
        }
Пример #22
0
        /// <inheritdoc />
        public async Task Invoke()
        {
            // Execute each stage in the pipeline. Each successive call to this method will invoke the next stage.
            // Stages which are not implemented (eg, because the user has not specified an interceptor) are skipped.
            var numFilters = filters.Count;

            if (stage < numFilters)
            {
                // Call each of the specified interceptors.
                var systemWideFilter = this.filters[stage];
                stage++;
                await systemWideFilter.Invoke(this);

                return;
            }

            if (stage == numFilters)
            {
                stage++;

                // Deprecated silo-level invoker, if present.
                var grain = this.Grain as IGrain;
                if (grain != null && deprecatedInvokeInterceptor != null)
                {
                    this.Result =
                        await deprecatedInvokeInterceptor.Invoke(this.Method, this.request, grain, this);

                    return;
                }
            }

            if (stage == numFilters + 1)
            {
                stage++;

                // Grain-level invoker, if present.
                var grainClassLevelFilter = this.Grain as IGrainCallFilter;
                if (grainClassLevelFilter != null)
                {
                    await grainClassLevelFilter.Invoke(this);

                    return;
                }
            }

#pragma warning disable 618
            if (stage == numFilters + 2)
            {
                stage++;

                // Deprecated grain-level invoker, if present.
                var intercepted = this.Grain as IGrainInvokeInterceptor;
                if (intercepted != null)
                {
                    this.Result = await intercepted.Invoke(this.Method, this.request, this);

                    return;
                }
            }
#pragma warning restore 618

            if (stage == numFilters + 3)
            {
                // Finally call the root-level invoker.
                stage++;
                this.Result = await rootInvoker.Invoke(this.Grain, this.request);

                return;
            }

            // If this method has been called more than the expected number of times, that is invalid.
            ThrowInvalidCall();
        }