public void CreateTraceMonitor_AllErrors()
        {
            ParameterInfo parameter = typeof(Functions).GetMethod("AllErrors").GetParameters()[0];

            TraceMonitor traceMonitor = ErrorTriggerListener.CreateTraceMonitor(parameter, _mockExecutor.Object);

            TraceFilter.AnonymousTraceFilter traceFilter = (TraceFilter.AnonymousTraceFilter)traceMonitor.Filters.Single();
            Assert.Equal("One or more WebJob errors have occurred.", traceFilter.Message);

            int notification = 0;

            traceMonitor.Subscribe(p => notification++);
            Assert.Equal(0, traceFilter.GetEvents().Count());
            traceMonitor.Trace(new TraceEvent(TraceLevel.Error, "Error1"));
            IEnumerable <TraceEvent> traceEvents = traceFilter.GetEvents();

            Assert.Equal(1, traceEvents.Count());
            Assert.Equal("Error1", traceEvents.Single().Message);

            traceMonitor.Trace(new TraceEvent(TraceLevel.Error, "Error2"));
            traceEvents = traceFilter.GetEvents();
            Assert.Equal(1, traceEvents.Count());
            Assert.Equal("Error2", traceEvents.Single().Message);
            Assert.Equal(2, notification);
        }
        public void CreateTraceMonitor_AllErrors_Customized()
        {
            ParameterInfo parameter = typeof(Functions).GetMethod("AllErrors_Customized").GetParameters()[0];

            TraceMonitor traceMonitor = ErrorTriggerListener.CreateTraceMonitor(parameter, _mockExecutor.Object);

            Assert.Equal(TimeSpan.Parse("00:30:00"), traceMonitor.NotificationThrottle);

            TraceFilter.AnonymousTraceFilter traceFilter = (TraceFilter.AnonymousTraceFilter)traceMonitor.Filters.Single();
            Assert.Equal("Custom Message", traceFilter.Message);

            int notification = 0;

            traceMonitor.Subscribe(p => notification++);

            Assert.Equal(0, traceFilter.GetEvents().Count());
            traceMonitor.Trace(new TraceEvent(TraceLevel.Error, "Error1"));
            Assert.Equal(1, traceFilter.GetEvents().Count());
            Assert.Equal("Error1", traceFilter.GetEvents().Single().Message);

            traceMonitor.Trace(new TraceEvent(TraceLevel.Error, "Error2"));
            Assert.Equal(1, traceFilter.GetEvents().Count());
            Assert.Equal("Error2", traceFilter.GetEvents().Single().Message);

            // expect second notification to be ignored due to throttle
            Assert.Equal(1, notification);
        }
        internal static TraceMonitor CreateTraceMonitor(ParameterInfo parameter, ITriggeredFunctionExecutor executor)
        {
            ErrorTriggerAttribute attribute = parameter.GetCustomAttribute<ErrorTriggerAttribute>(inherit: false);

            // Determine whether this is a method level filter, and if so, create the filter
            Func<TraceEvent, bool> methodFilter = null;
            MethodInfo method = (MethodInfo)parameter.Member;
            string functionLevelMessage = null;
            if (method.Name.EndsWith(ErrorHandlerSuffix, StringComparison.OrdinalIgnoreCase))
            {
                string sourceMethodName = method.Name.Substring(0, method.Name.Length - ErrorHandlerSuffix.Length);
                MethodInfo sourceMethod = method.DeclaringType.GetMethod(sourceMethodName);
                if (sourceMethod != null)
                {
                    string sourceMethodFullName = string.Format("{0}.{1}", method.DeclaringType.FullName, sourceMethod.Name);
                    methodFilter = p =>
                    {
                        FunctionInvocationException functionException = p.Exception as FunctionInvocationException;
                        return p.Level == System.Diagnostics.TraceLevel.Error && functionException != null &&
                               string.Compare(functionException.MethodName, sourceMethodFullName, StringComparison.OrdinalIgnoreCase) == 0;
                    };

                    string sourceMethodShortName = string.Format("{0}.{1}", method.DeclaringType.Name, sourceMethod.Name);
                    functionLevelMessage = string.Format("Function '{0}' failed.", sourceMethodShortName);
                }
            }

            string errorHandlerFullName = string.Format("{0}.{1}", method.DeclaringType.FullName, method.Name);
            ErrorHandlers.Add(errorHandlerFullName);

            // Create the TraceFilter instance
            TraceFilter traceFilter = null;
            if (attribute.FilterType != null)
            {
                if (methodFilter != null)
                {
                    TraceFilter innerTraceFilter = (TraceFilter)Activator.CreateInstance(attribute.FilterType);
                    traceFilter = new CompositeTraceFilter(innerTraceFilter, methodFilter, attribute.Message ?? functionLevelMessage);
                }
                else
                {
                    traceFilter = (TraceFilter)Activator.CreateInstance(attribute.FilterType);
                }
            }
            else if (!string.IsNullOrEmpty(attribute.Window))
            {
                TimeSpan window = TimeSpan.Parse(attribute.Window);
                traceFilter = new SlidingWindowTraceFilter(window, attribute.Threshold, methodFilter, attribute.Message);
            }
            else
            {
                traceFilter = TraceFilter.Create(methodFilter, attribute.Message ?? functionLevelMessage);
            }
            TraceMonitor traceMonitor = new TraceMonitor().Filter(traceFilter);

            // Apply any additional monitor options
            if (!string.IsNullOrEmpty(attribute.Throttle))
            {
                TimeSpan throttle = TimeSpan.Parse(attribute.Throttle);
                traceMonitor.Throttle(throttle);
            }

            // Subscribe the error handler function to the error stream
            traceMonitor.Subscribe(p =>
            {
                TriggeredFunctionData triggerData = new TriggeredFunctionData
                {
                    TriggerValue = p
                };
                Task<FunctionResult> task = executor.TryExecuteAsync(triggerData, CancellationToken.None);
                task.Wait();
            });

            return traceMonitor;
        }
Exemple #4
0
        internal static TraceMonitor CreateTraceMonitor(ParameterInfo parameter, ITriggeredFunctionExecutor executor)
        {
            ErrorTriggerAttribute attribute = parameter.GetCustomAttribute <ErrorTriggerAttribute>(inherit: false);

            // Determine whether this is a method level filter, and if so, create the filter
            Func <TraceEvent, bool> methodFilter = null;
            MethodInfo method = (MethodInfo)parameter.Member;
            string     functionLevelMessage = null;

            if (method.Name.EndsWith(ErrorHandlerSuffix, StringComparison.OrdinalIgnoreCase))
            {
                string     sourceMethodName = method.Name.Substring(0, method.Name.Length - ErrorHandlerSuffix.Length);
                MethodInfo sourceMethod     = method.DeclaringType.GetMethod(sourceMethodName);
                if (sourceMethod != null)
                {
                    string sourceMethodFullName = string.Format("{0}.{1}", method.DeclaringType.FullName, sourceMethod.Name);
                    methodFilter = p =>
                    {
                        FunctionInvocationException functionException = p.Exception as FunctionInvocationException;
                        return(p.Level == System.Diagnostics.TraceLevel.Error && functionException != null &&
                               string.Compare(functionException.MethodName, sourceMethodFullName, StringComparison.OrdinalIgnoreCase) == 0);
                    };

                    string sourceMethodShortName = string.Format("{0}.{1}", method.DeclaringType.Name, sourceMethod.Name);
                    functionLevelMessage = string.Format("Function '{0}' failed.", sourceMethodShortName);
                }
            }

            string errorHandlerFullName = string.Format("{0}.{1}", method.DeclaringType.FullName, method.Name);

            ErrorHandlers.Add(errorHandlerFullName);

            // Create the TraceFilter instance
            TraceFilter traceFilter = null;

            if (attribute.FilterType != null)
            {
                if (methodFilter != null)
                {
                    TraceFilter innerTraceFilter = (TraceFilter)Activator.CreateInstance(attribute.FilterType);
                    traceFilter = new CompositeTraceFilter(innerTraceFilter, methodFilter, attribute.Message ?? functionLevelMessage);
                }
                else
                {
                    traceFilter = (TraceFilter)Activator.CreateInstance(attribute.FilterType);
                }
            }
            else if (!string.IsNullOrEmpty(attribute.Window))
            {
                TimeSpan window = TimeSpan.Parse(attribute.Window);
                traceFilter = new SlidingWindowTraceFilter(window, attribute.Threshold, methodFilter, attribute.Message);
            }
            else
            {
                traceFilter = TraceFilter.Create(methodFilter, attribute.Message ?? functionLevelMessage);
            }
            TraceMonitor traceMonitor = new TraceMonitor().Filter(traceFilter);

            // Apply any additional monitor options
            if (!string.IsNullOrEmpty(attribute.Throttle))
            {
                TimeSpan throttle = TimeSpan.Parse(attribute.Throttle);
                traceMonitor.Throttle(throttle);
            }

            // Subscribe the error handler function to the error stream
            traceMonitor.Subscribe(p =>
            {
                TriggeredFunctionData triggerData = new TriggeredFunctionData
                {
                    TriggerValue = p
                };
                Task <FunctionResult> task = executor.TryExecuteAsync(triggerData, CancellationToken.None);
                task.Wait();
            });

            return(traceMonitor);
        }