/// <summary> /// Initializes a new <see cref="Group"/> object. /// </summary> /// <param name="logger">The logger.</param> /// <param name="level">The <see cref="GroupLevel"/>.</param> /// <param name="text">The <see cref="GroupText"/>.</param> /// <param name="defaultConclusionText"> /// Optional delegate to call on close to obtain a conclusion text if no /// explicit conclusion is provided through <see cref="IActivityLogger.CloseGroup"/>. /// </param> /// <param name="ex">Optional exception associated to the group.</param> internal protected Group(ActivityLogger logger, LogLevel level, string text, Func <string> defaultConclusionText, Exception ex) { _logger = logger; Parent = logger._current; Depth = logger._depth; Filter = logger.Filter; // Logs everything when a Group is an error: we then have full details without // logging all with Error or Fatal. if (level >= LogLevel.Error) { logger.Filter = LogLevelFilter.Trace; } GroupLevel = level; GroupText = text; GetConclusionText = defaultConclusionText; Exception = ex; }
public void ErrorCounterTests() { var logger = new ActivityLogger(); // Binds the TestHelper.Logger logger to this one. logger.Output.RegisterMuxClient( TestHelper.Logger.Output.ExternalInput ); // Registers the ErrorCounter first: it will be the last one to be called, but // this does not prevent the PathCatcher to work: the path elements reference the group // so that aany conclusion arriving after PathCatcher.OnClosing are available. ActivityLoggerErrorCounter c = new ActivityLoggerErrorCounter(); logger.Output.RegisterMuxClient( c ); // Registers the PathCatcher now: it will be called BEFORE the ErrorCounter. ActivityLoggerPathCatcher p = new ActivityLoggerPathCatcher(); logger.Output.RegisterClient( p ); Assert.That( c.GenerateConclusion, Is.True, "Must be the default." ); Assert.That( c.Root.MaxLogLevel == LogLevel.None ); logger.Trace( "T1" ); Assert.That( !c.Root.HasWarnOrError && !c.Root.HasError ); Assert.That( c.Root.MaxLogLevel == LogLevel.Trace ); Assert.That( c.Root.ToString(), Is.Null ); logger.Warn( "W1" ); Assert.That( c.Root.HasWarnOrError && !c.Root.HasError ); Assert.That( c.Root.MaxLogLevel == LogLevel.Warn ); Assert.That( c.Root.ToString(), Is.Not.Null.And.Not.Empty ); logger.Error( "E2" ); Assert.That( c.Root.HasWarnOrError && c.Root.HasError ); Assert.That( c.Root.ErrorCount == 1 ); Assert.That( c.Root.MaxLogLevel == LogLevel.Error ); Assert.That( c.Root.ToString(), Is.Not.Null.And.Not.Empty ); c.Root.ClearError(); Assert.That( c.Root.HasWarnOrError && !c.Root.HasError ); Assert.That( c.Root.ErrorCount == 0 ); Assert.That( c.Root.MaxLogLevel == LogLevel.Warn ); Assert.That( c.Root.ToString(), Is.Not.Null ); c.Root.ClearWarn(); Assert.That( !c.Root.HasWarnOrError && !c.Root.HasError ); Assert.That( c.Root.MaxLogLevel == LogLevel.Info ); Assert.That( c.Root.ToString(), Is.Null ); using( logger.OpenGroup( LogLevel.Trace, "G1" ) ) { using( logger.OpenGroup( LogLevel.Info, "G2" ) ) { logger.Error( "E1" ); logger.Fatal( "F1" ); Assert.That( c.Root.HasWarnOrError && c.Root.HasError ); Assert.That( c.Root.ErrorCount == 1 && c.Root.FatalCount == 1 ); Assert.That( c.Root.WarnCount == 0 ); using( logger.OpenGroup( LogLevel.Info, "G3" ) ) { Assert.That( !c.Current.HasWarnOrError && !c.Current.HasError ); Assert.That( c.Current.ErrorCount == 0 && c.Current.FatalCount == 0 && c.Current.WarnCount == 0 ); logger.Error( "E2" ); Assert.That( c.Current.HasWarnOrError && c.Current.HasError ); Assert.That( c.Current.ErrorCount == 1 && c.Current.FatalCount == 0 && c.Current.WarnCount == 0 ); } } Assert.That( String.Join( ">", p.LastErrorPath.Select( e => e.Text + '-' + e.GroupConclusion.ToStringGroupConclusion() ) ), Is.EqualTo( "G1->G2-1 Fatal error, 2 Errors>G3-1 Error>E2-" ) ); logger.Error( "E3" ); logger.Fatal( "F2" ); logger.Warn( "W2" ); Assert.That( c.Root.HasWarnOrError && c.Root.HasError ); Assert.That( c.Root.FatalCount == 2 ); Assert.That( c.Root.ErrorCount == 3 ); Assert.That( c.Root.MaxLogLevel == LogLevel.Fatal ); } Assert.That( String.Join( ">", p.LastErrorPath.Select( e => e.Text + '-' + e.GroupConclusion.ToStringGroupConclusion() ) ), Is.EqualTo( "G1-2 Fatal errors, 3 Errors, 1 Warning>F2-" ) ); Assert.That( String.Join( ">", p.LastWarnOrErrorPath.Select( e => e.Text + '-' + e.GroupConclusion.ToStringGroupConclusion() ) ), Is.EqualTo( "G1-2 Fatal errors, 3 Errors, 1 Warning>W2-" ) ); }
internal object GroupClose( object externalConclusion ) { object conclusion = OnGroupClose( externalConclusion ); _logger = null; return conclusion; }
/// <summary> /// Initializes a new <see cref="Group"/> object. /// </summary> /// <param name="logger">The logger.</param> /// <param name="level">The <see cref="GroupLevel"/>.</param> /// <param name="text">The <see cref="GroupText"/>.</param> /// <param name="defaultConclusionText"> /// Optional delegate to call on close to obtain a conclusion text if no /// explicit conclusion is provided through <see cref="IActivityLogger.CloseGroup"/>. /// </param> /// <param name="ex">Optional exception associated to the group.</param> protected internal Group( ActivityLogger logger, LogLevel level, string text, Func<string> defaultConclusionText, Exception ex ) { _logger = logger; Parent = logger._current; Depth = logger._depth; Filter = logger.Filter; // Logs everything when a Group is an error: we then have full details without // logging all with Error or Fatal. if( level >= LogLevel.Error ) logger.Filter = LogLevelFilter.Trace; GroupLevel = level; GroupText = text; GetConclusionText = defaultConclusionText; Exception = ex; }