public void CreateTraceMonitor_SlidingWindow() { ParameterInfo parameter = typeof(Functions).GetMethod("SlidingWindowErrorHandler").GetParameters()[0]; TraceMonitor traceMonitor = ErrorTriggerListener.CreateTraceMonitor(parameter, _mockExecutor.Object); SlidingWindowTraceFilter traceFilter = (SlidingWindowTraceFilter)traceMonitor.Filters.Single(); Assert.Equal(5, traceFilter.Threshold); Assert.Equal("5 events at level 'Error' or lower have occurred within time window 00:05:00.", traceFilter.Message); }
public void CreateTraceMonitor_SlidingWindow_Customized() { ParameterInfo parameter = typeof(Functions).GetMethod("SlidingWindowErrorHandler_Customized").GetParameters()[0]; TraceMonitor traceMonitor = ErrorTriggerListener.CreateTraceMonitor(parameter, _mockExecutor.Object); SlidingWindowTraceFilter traceFilter = (SlidingWindowTraceFilter)traceMonitor.Filters.Single(); Assert.Equal(5, traceFilter.Threshold); Assert.Equal("Custom Message", traceFilter.Message); }
public void Constructor_DefaultsMessage() { SlidingWindowTraceFilter filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 5); Assert.Equal("5 events at level 'Error' or lower have occurred within time window 00:10:00.", filter.Message); filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 5, message: "Custom Message"); Assert.Equal("Custom Message", filter.Message); filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 5, level: TraceLevel.Warning); Assert.Equal("5 events at level 'Warning' or lower have occurred within time window 00:10:00.", filter.Message); }
public void Filter_ReturnsTrueWhenThresholdReached() { SlidingWindowTraceFilter filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 3); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 1"))); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 2"))); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Info, "Error 3"))); // expect this to be ignored based on Level Assert.True(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 4"))); Assert.Equal(3, filter.Events.Count); Assert.Equal("Error 1", filter.Events[0].Message); Assert.Equal("Error 2", filter.Events[1].Message); Assert.Equal("Error 4", filter.Events[2].Message); }
public void RemoveOldEvents_RemovesEventsOutsideWindow() { SlidingWindowTraceFilter filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 5); DateTime now = DateTime.Now - TimeSpan.FromMinutes(10); Assert.Equal(0, filter.GetEvents().Count()); filter.RemoveOldEvents(now); Assert.Equal(0, filter.GetEvents().Count()); // add some events over a few minutes for (int i = 0; i < 10; i++) { now += TimeSpan.FromMinutes(1); var traceEvent = new TraceEvent(TraceLevel.Error, string.Format("Error {0}", i)) { Timestamp = now }; filter.AddEvent(traceEvent); } Assert.Equal(10, filter.GetEvents().Count()); filter.RemoveOldEvents(now); IEnumerable <TraceEvent> traceEvents = filter.GetEvents(); Assert.Equal(10, traceEvents.Count()); Assert.Equal("Error 0", traceEvents.First().Message); Assert.Equal("Error 9", traceEvents.Last().Message); // now advance forward a minute now += TimeSpan.FromMinutes(1); filter.RemoveOldEvents(now); traceEvents = filter.GetEvents(); Assert.Equal(9, traceEvents.Count()); Assert.Equal("Error 1", traceEvents.First().Message); Assert.Equal("Error 9", traceEvents.Last().Message); // now advance forward a few more minutes now += TimeSpan.FromMinutes(5); filter.RemoveOldEvents(now); traceEvents = filter.GetEvents(); Assert.Equal(4, traceEvents.Count()); Assert.Equal("Error 6", traceEvents.First().Message); Assert.Equal("Error 9", traceEvents.Last().Message); // finally advance forward past all existing events now += TimeSpan.FromMinutes(5); filter.RemoveOldEvents(now); Assert.Equal(0, filter.GetEvents().Count()); }
public void Filter_AppliesInnerFilter() { Func <TraceEvent, bool> innerFilter = p => !p.Message.Contains("Ignore"); SlidingWindowTraceFilter filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 3, innerFilter); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 1"))); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 2"))); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Info, "Error 3"))); // expect this to be ignored based on Level Assert.False(filter.Filter(new TraceEvent(TraceLevel.Info, "Error 4 (Ignore)"))); // expect this to be ignored based inner filter Assert.True(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 5"))); Assert.Equal(3, filter.Events.Count); Assert.Equal("Error 1", filter.Events[0].Message); Assert.Equal("Error 2", filter.Events[1].Message); Assert.Equal("Error 5", filter.Events[2].Message); }
public void RemoveOldEvents_RemovesEventsOutsideWindow() { SlidingWindowTraceFilter filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 5); DateTime now = DateTime.UtcNow - TimeSpan.FromMinutes(10); Assert.Equal(0, filter.Events.Count); filter.RemoveOldEvents(now); Assert.Equal(0, filter.Events.Count); // add some events over a few minutes for (int i = 0; i < 10; i++) { now += TimeSpan.FromMinutes(1); var traceEvent = new TraceEvent(TraceLevel.Error, string.Format("Error {0}", i)) { Timestamp = now }; filter.Events.Add(traceEvent); } Assert.Equal(10, filter.Events.Count); filter.RemoveOldEvents(now); Assert.Equal(10, filter.Events.Count); Assert.Equal("Error 0", filter.Events.First().Message); Assert.Equal("Error 9", filter.Events.Last().Message); // now advance forward a minute now += TimeSpan.FromMinutes(1); filter.RemoveOldEvents(now); Assert.Equal(9, filter.Events.Count); Assert.Equal("Error 1", filter.Events.First().Message); Assert.Equal("Error 9", filter.Events.Last().Message); // now advance forward a few more minutes now += TimeSpan.FromMinutes(5); filter.RemoveOldEvents(now); Assert.Equal(4, filter.Events.Count); Assert.Equal("Error 6", filter.Events.First().Message); Assert.Equal("Error 9", filter.Events.Last().Message); // finally advance forward past all existing events now += TimeSpan.FromMinutes(5); filter.RemoveOldEvents(now); Assert.Equal(0, filter.Events.Count); }
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; }
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); }
public void Filter_AppliesInnerFilter() { Func<TraceEvent, bool> innerFilter = p => !p.Message.Contains("Ignore"); SlidingWindowTraceFilter filter = new SlidingWindowTraceFilter(TimeSpan.FromMinutes(10), 3, innerFilter); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 1"))); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 2"))); Assert.False(filter.Filter(new TraceEvent(TraceLevel.Info, "Error 3"))); // expect this to be ignored based on Level Assert.False(filter.Filter(new TraceEvent(TraceLevel.Info, "Error 4 (Ignore)"))); // expect this to be ignored based inner filter Assert.True(filter.Filter(new TraceEvent(TraceLevel.Error, "Error 5"))); Assert.Equal(3, filter.Events.Count); Assert.Equal("Error 1", filter.Events[0].Message); Assert.Equal("Error 2", filter.Events[1].Message); Assert.Equal("Error 5", filter.Events[2].Message); }