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);
        }
        public void CreateTraceMonitor_FunctionErrorHandler_CustomFilterType()
        {
            ParameterInfo parameter = typeof(Functions).GetMethod("Test2ErrorHandler").GetParameters()[0];

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

            ErrorTriggerListener.CompositeTraceFilter traceFilter = (ErrorTriggerListener.CompositeTraceFilter)traceMonitor.Filters.Single();
            Assert.NotNull(traceFilter);
            Assert.Equal(typeof(Functions.CustomTraceFilter), traceFilter.InnerTraceFilter.GetType());

            // first log a function exception for a *different* function
            // don't expect it to pass filter
            FunctionInvocationException functionException = new FunctionInvocationException("Function failed", Guid.Empty,
                                                                                            "Microsoft.Azure.WebJobs.Extensions.Tests.Core.ErrorTriggerListenerTests+Functions.Foo", new Exception("Kaboom!"));

            TraceEvent traceEvent = new TraceEvent(TraceLevel.Error, "Kaboom!", null, functionException);

            traceMonitor.Trace(traceEvent);
            Assert.Equal(0, traceFilter.GetEvents().Count());

            functionException = new FunctionInvocationException("Function failed", Guid.Empty,
                                                                "Microsoft.Azure.WebJobs.Extensions.Tests.Core.ErrorTriggerListenerTests+Functions.Test2", new Exception("Kaboom!"));

            traceEvent = new TraceEvent(TraceLevel.Error, "Kaboom!", null, functionException);
            traceMonitor.Trace(traceEvent);
            Assert.Equal(1, traceFilter.GetEvents().Count());
            Assert.Same(functionException, traceFilter.GetEvents().Single().Exception);
        }
        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 Trace_WithThrottle_NotificationsAreSuspendedThenResumed()
        {
            int notificationCount = 0;
            int filterCount = 0;

            int throttleSeconds = 1;
            var monitor = new TraceMonitor()
                .Filter(p =>
                {
                    filterCount++;
                    return true;
                })
                .Subscribe(p =>
                {
                    notificationCount++;
                })
                .Throttle(TimeSpan.FromSeconds(throttleSeconds));

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(1, notificationCount);

            Thread.Sleep(throttleSeconds * 1000);

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(2, notificationCount);

            Thread.Sleep(throttleSeconds * 1000);

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));

            Assert.Equal(5, filterCount);
            Assert.Equal(3, notificationCount);
        }
        public void Trace_WithThrottle_NotificationsAreSuspendedThenResumed()
        {
            int notificationCount = 0;
            int filterCount       = 0;

            int throttleSeconds = 1;
            var monitor         = new TraceMonitor()
                                  .Filter(p =>
            {
                filterCount++;
                return(true);
            })
                                  .Subscribe(p =>
            {
                notificationCount++;
            })
                                  .Throttle(TimeSpan.FromSeconds(throttleSeconds));

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(1, notificationCount);

            Thread.Sleep(throttleSeconds * 1000);

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(2, notificationCount);

            Thread.Sleep(throttleSeconds * 1000);

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));

            Assert.Equal(5, filterCount);
            Assert.Equal(3, notificationCount);
        }
        public void CreateTraceMonitor_FunctionErrorHandler()
        {
            ParameterInfo parameter = typeof(Functions).GetMethod("TestErrorHandler").GetParameters()[0];

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

            TraceFilter.AnonymousTraceFilter traceFilter = (TraceFilter.AnonymousTraceFilter)traceMonitor.Filters.Single();
            Assert.Equal("Function 'Functions.Test' failed.", traceFilter.Message);

            // first log a function exception for a *different* function
            // don't expect it to pass filter
            FunctionInvocationException functionException = new FunctionInvocationException("Function failed", new Exception("Kaboom!"))
            {
                MethodName = "Microsoft.Azure.WebJobs.Extensions.Tests.Core.ErrorTriggerListenerTests+Functions.Foo"
            };
            TraceEvent traceEvent = new TraceEvent(TraceLevel.Error, "Kaboom!", null, functionException);

            traceMonitor.Trace(traceEvent);
            Assert.Equal(0, traceFilter.GetEvents().Count());

            functionException = new FunctionInvocationException("Function failed", new Exception("Kaboom!"))
            {
                MethodName = "Microsoft.Azure.WebJobs.Extensions.Tests.Core.ErrorTriggerListenerTests+Functions.Test"
            };
            traceEvent = new TraceEvent(TraceLevel.Error, "Kaboom!", null, functionException);
            traceMonitor.Trace(traceEvent);
            Assert.Equal(1, traceFilter.GetEvents().Count());
            Assert.Same(functionException, traceFilter.GetEvents().Single().Exception);
        }
        public void Trace_NoFilters_AlwaysNotify()
        {
            int notificationCount = 0;

            var monitor = new TraceMonitor()
                          .Subscribe(p =>
            {
                notificationCount++;
            });

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(3, notificationCount);
        }
        public void Trace_SubscribersAreNotified()
        {
            int notificationCount = 0;

            var monitor = new TraceMonitor()
                          .Filter(p => { return(true); })
                          .Subscribe(p =>
            {
                notificationCount++;
            });

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(3, notificationCount);
        }
        public void Trace_SubscribersAreNotified()
        {
            int notificationCount = 0;

            var monitor = new TraceMonitor()
                .Filter(p => { return true; })
                .Subscribe(p =>
                {
                    notificationCount++;
                });

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(3, notificationCount);
        }
        public void Trace_IgnoresDuplicateErrors()
        {
            int notificationCount = 0;
            int filterCount       = 0;

            var monitor = new TraceMonitor()
                          .Filter(p =>
            {
                filterCount++;
                return(true);
            })
                          .Subscribe(p =>
            {
                notificationCount++;
            });

            Exception ex = new Exception("Kaboom!");

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!", null, ex));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!", null, ex));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!", null, ex));
            Assert.Equal(1, filterCount);
            Assert.Equal(1, notificationCount);
        }
        public void Trace_MultipleFilters_AllFiltersInvoked()
        {
            int filterCount = 0;

            Func <TraceEvent, bool> filter = p =>
            {
                filterCount++;
                return(true);
            };

            var monitor = new TraceMonitor()
                          .Filter(filter)
                          .Filter(filter)
                          .Filter(filter);

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));

            Assert.Equal(3, filterCount);
        }
        public void Trace_AnonymousFilter_NotifiesAsExpected()
        {
            TraceFilter filter = null;

            var monitor = new TraceMonitor()
                          .Filter(p =>
            {
                return(true);
            }, "Custom Message")
                          .Subscribe(p =>
            {
                filter = p;
            });

            TraceEvent traceEvent = new TraceEvent(TraceLevel.Error, "Error!");

            monitor.Trace(traceEvent);

            Assert.Equal("Custom Message", filter.Message);
            Assert.Equal(1, filter.Events.Count);
            Assert.Same(traceEvent, filter.Events.Single());
        }
        public void Trace_NoFilters_AlwaysNotify()
        {
            int notificationCount = 0;

            var monitor = new TraceMonitor()
                .Subscribe(p =>
                {
                    notificationCount++;
                });

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));
            Assert.Equal(3, notificationCount);
        }
        public void Trace_IgnoresDuplicateErrors()
        {
            int notificationCount = 0;
            int filterCount = 0;

            var monitor = new TraceMonitor()
                .Filter(p => 
                {
                    filterCount++;
                    return true;
                })
                .Subscribe(p =>
                {
                    notificationCount++;
                });

            Exception ex = new Exception("Kaboom!");

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!", null, ex));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!", null, ex));
            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!", null, ex));
            Assert.Equal(1, filterCount);
            Assert.Equal(1, notificationCount);
        }
        public void Trace_MultipleFilters_AllFiltersInvoked()
        {
            int filterCount = 0;

            Func<TraceEvent, bool> filter = p =>
            {
                filterCount++;
                return true;
            };

            var monitor = new TraceMonitor()
                .Filter(filter)
                .Filter(filter)
                .Filter(filter);

            monitor.Trace(new TraceEvent(TraceLevel.Error, "Error!"));

            Assert.Equal(3, filterCount);
        }
        public void Trace_AnonymousFilter_NotifiesAsExpected()
        {
            TraceFilter filter = null;

            var monitor = new TraceMonitor()
                .Filter(p =>
                {
                    return true;
                }, "Custom Message")
                .Subscribe(p =>
                {
                    filter = p;
                });

            TraceEvent traceEvent = new TraceEvent(TraceLevel.Error, "Error!");
            monitor.Trace(traceEvent);

            Assert.Equal("Custom Message", filter.Message);
            Assert.Equal(1, filter.Events.Count);
            Assert.Same(traceEvent, filter.Events.Single());
        }