public void FileLoggerLocalTime()
 {
     using (var localTimeLogger = new FileBackedLogger(
                new LogConfiguration("loctime", LogType.Text, LogManager.DefaultSubscriptions)
     {
         Directory = ".",
         RotationInterval = LogManager.MinRotationInterval,
         TimestampLocal = true,
     }, DateTime.UtcNow))
     {
         using (var utcTimeLogger = new FileBackedLogger(
                    new LogConfiguration("utctime", LogType.Text, LogManager.DefaultSubscriptions)
         {
             Directory = ".",
             RotationInterval = LogManager.MinRotationInterval,
             TimestampLocal = false,
         }, DateTime.UtcNow))
         {
             Assert.AreEqual(localTimeLogger.FilenameTemplate,
                             LogManager.DefaultLocalTimeFilenameTemplate + FileBackedLogger.TextLogExtension);
             Assert.AreEqual(utcTimeLogger.FilenameTemplate,
                             LogManager.DefaultFilenameTemplate + FileBackedLogger.TextLogExtension);
             // local time filename should be longer. (has timezone)
             Assert.IsTrue(localTimeLogger.Logger.Filename.Length > utcTimeLogger.Logger.Filename.Length);
         }
     }
 }
        public void CreateFileBackedLogger()
        {
            LogManager.Start();
            try
            {
                new FileBackedLogger(new LogConfiguration("badlogger", LogType.MemoryBuffer,
                                                          LogManager.DefaultSubscriptions), DateTime.UtcNow);
                Assert.Fail();
            }
            catch (ArgumentException) { }

            using (var logger = new FileBackedLogger(
                       new LogConfiguration("testfile", LogType.Text, LogManager.DefaultSubscriptions)
            {
                Directory = Path.GetFullPath("."),
                RotationInterval = 0,
                FilenameTemplate = "{0}"
            }, DateTime.UtcNow))
            {
                Assert.IsNotNull(logger.Logger);
                Assert.AreEqual(0, logger.RotationInterval);
                string fullFilename = (logger.Logger as TextFileLogger).Filename;
                string dName        = Path.GetDirectoryName(fullFilename);
                Assert.AreEqual(dName, Path.GetFullPath("."));
                string fName = Path.GetFileName(fullFilename);
                Assert.AreEqual(fName, "testfile.log");
            }

            LogManager.Shutdown();
        }
Example #3
0
        private IEventLogger CreateFileLogger(LoggerType type, string baseName, string directory, int bufferSizeMB,
                                              int rotation, string filenameTemplate, bool timestampLocal)
        {
            if (rotation < 0 && DefaultRotate)
            {
                rotation = this.defaultRotationInterval;
            }

            if (rotation > 0)
            {
                CheckRotationInterval(rotation);
            }

            CheckFileBufferSize(bufferSizeMB);
            GetQualifiedDirectory(ref directory);

            if (baseName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1)
            {
                throw new ArgumentException("base filename contains invalid characters", "baseName");
            }

            lock (this.loggersLock)
            {
                if (this.GetNamedFileLogger(baseName) != null)
                {
                    throw new InvalidOperationException("logger named " + baseName + " already exists");
                }

                var logger = new FileBackedLogger(baseName, directory, type, bufferSizeMB, rotation, filenameTemplate,
                                                  timestampLocal);
                this.fileLoggers[baseName] = logger;
                return(logger.Logger);
            }
        }
Example #4
0
        /// <summary>
        /// Retrieve the named file logger.
        /// </summary>
        /// <param name="name">Name of the logger.</param>
        /// <returns>The logger, or null if no logger of the given name exists.</returns>
        public static IEventLogger GetFileLogger(string name)
        {
            FileBackedLogger logger = singleton.GetNamedFileLogger(name);

            if (logger != null)
            {
                return(logger.Logger);
            }
            return(null);
        }
Example #5
0
        public void CheckedFileLoggerRotation()
        {
            // Create a file with a 5 minute rotation time, then attempt to rotate it every minute and ensure it
            // only changes names once.
            DateTime now = DateTime.UtcNow;

            using (var utcLogger = new FileBackedLogger("loctime", ".", LoggerType.TextLogFile,
                                                        LogManager.DefaultFileBufferSizeMB, 300,
                                                        FileBackedLogger.DefaultFilenameTemplate, false))
            {
                using (var localLogger = new FileBackedLogger("utctime", ".", LoggerType.TextLogFile,
                                                              LogManager.DefaultFileBufferSizeMB, 300,
                                                              FileBackedLogger.DefaultFilenameTemplate, true))
                {
                    Assert.IsNotNull(utcLogger);
                    utcLogger.CheckedRotate(now);
                    string currentUtcFilename = utcLogger.Logger.Filename;
                    int    utcFilenameChanges = 0;

                    Assert.IsNotNull(localLogger);
                    localLogger.CheckedRotate(now);
                    string currentLocalFilename = localLogger.Logger.Filename;
                    int    localFilenameChanges = 0;

                    for (int i = 0; i < 5; ++i)
                    {
                        now += new TimeSpan(0, 1, 0);
                        utcLogger.CheckedRotate(now);
                        localLogger.CheckedRotate(now);

                        if (
                            string.Compare(currentUtcFilename, utcLogger.Logger.Filename,
                                           StringComparison.OrdinalIgnoreCase) !=
                            0)
                        {
                            ++utcFilenameChanges;
                            currentUtcFilename = utcLogger.Logger.Filename;
                        }

                        if (
                            string.Compare(currentLocalFilename, localLogger.Logger.Filename,
                                           StringComparison.OrdinalIgnoreCase) !=
                            0)
                        {
                            ++localFilenameChanges;
                            currentLocalFilename = localLogger.Logger.Filename;
                        }
                    }

                    Assert.AreEqual(1, utcFilenameChanges, "UTC timestamp filename changed more than once.");
                    Assert.AreEqual(1, localFilenameChanges, "Local timestamp filename changed more than once.");
                }
            }
        }
        public void CheckedFileLoggerRotation()
        {
            // Create a file with a 5 minute rotation time, then attempt to rotate it every minute and ensure it
            // only changes names once.
            DateTime now = DateTime.UtcNow;
            using (var utcLogger = new FileBackedLogger("loctime", ".", LoggerType.TextLogFile,
                                                        LogManager.DefaultFileBufferSizeMB, 300,
                                                        FileBackedLogger.DefaultFilenameTemplate, false))
            {
                using (var localLogger = new FileBackedLogger("utctime", ".", LoggerType.TextLogFile,
                                                              LogManager.DefaultFileBufferSizeMB, 300,
                                                              FileBackedLogger.DefaultFilenameTemplate, true))
                {
                    Assert.IsNotNull(utcLogger);
                    utcLogger.CheckedRotate(now);
                    string currentUtcFilename = utcLogger.Logger.Filename;
                    int utcFilenameChanges = 0;

                    Assert.IsNotNull(localLogger);
                    localLogger.CheckedRotate(now);
                    string currentLocalFilename = localLogger.Logger.Filename;
                    int localFilenameChanges = 0;

                    for (int i = 0; i < 5; ++i)
                    {
                        now += new TimeSpan(0, 1, 0);
                        utcLogger.CheckedRotate(now);
                        localLogger.CheckedRotate(now);

                        if (
                            string.Compare(currentUtcFilename, utcLogger.Logger.Filename,
                                           StringComparison.OrdinalIgnoreCase) !=
                            0)
                        {
                            ++utcFilenameChanges;
                            currentUtcFilename = utcLogger.Logger.Filename;
                        }

                        if (
                            string.Compare(currentLocalFilename, localLogger.Logger.Filename,
                                           StringComparison.OrdinalIgnoreCase) !=
                            0)
                        {
                            ++localFilenameChanges;
                            currentLocalFilename = localLogger.Logger.Filename;
                        }
                    }

                    Assert.AreEqual(1, utcFilenameChanges, "UTC timestamp filename changed more than once.");
                    Assert.AreEqual(1, localFilenameChanges, "Local timestamp filename changed more than once.");
                }
            }
        }
        /// <summary>
        /// Validate the full set of configuration. Throws InvalidConfigurationException in the event of invalid
        /// applied configuration.
        /// </summary>
        public void Validate()
        {
            if (this.Type == LogType.Network)
            {
                if (this.hostname == null)
                {
                    throw new InvalidConfigurationException($"Log {this.Name} has no hostname set.");
                }
                if (this.Port == 0)
                {
                    throw new InvalidConfigurationException($"Log {this.Name} has no port set.");
                }
            }

            if (this.Type.HasFeature(Features.FileBacked))
            {
                if (this.RotationInterval > 0 &&
                    !FileBackedLogger.IsValidFilenameTemplate(this.FilenameTemplate,
                                                              TimeSpan.FromSeconds(this.RotationInterval)))
                {
                    throw new InvalidConfigurationException(
                              $"Rotation interval {this.RotationInterval} cannot be used with template {this.FilenameTemplate}.");
                }

                var retentionPolicySet = (this.MaximumAge > TimeSpan.Zero || this.MaximumSize > 0);
                if (retentionPolicySet && this.RotationInterval <= 0)
                {
                    throw new InvalidConfigurationException(
                              $"Log {this.Name} has retention configuration but is not rotated.");
                }

                if (this.MaximumAge > TimeSpan.Zero)
                {
                    if (this.MaximumAge < TimeSpan.FromSeconds(this.RotationInterval) ||
                        this.MaximumAge.Ticks % TimeSpan.TicksPerSecond != 0)
                    {
                        throw new InvalidConfigurationException(
                                  $"Log {this.Name} has a maximum age which is either shorter than the rotation interval or not evenly divisible by seconds.");
                    }
                }
            }
        }
Example #8
0
 public void FileLoggerLocalTime()
 {
     using (var localTimeLogger = new FileBackedLogger("loctime", ".", LoggerType.TextLogFile,
                                                       LogManager.DefaultFileBufferSizeMB, 1,
                                                       FileBackedLogger.DefaultFilenameTemplate, true))
     {
         using (var utcTimeLogger = new FileBackedLogger("utctime", ".", LoggerType.TextLogFile,
                                                         LogManager.DefaultFileBufferSizeMB, 1,
                                                         FileBackedLogger.DefaultFilenameTemplate, false))
         {
             Assert.AreEqual(localTimeLogger.FilenameTemplate,
                             FileBackedLogger.DefaultLocalTimeFilenameTemplate +
                             FileBackedLogger.TextLogExtension);
             Assert.AreEqual(utcTimeLogger.FilenameTemplate,
                             FileBackedLogger.DefaultFilenameTemplate + FileBackedLogger.TextLogExtension);
             // local time filename should be longer. (has timezone)
             Assert.IsTrue(localTimeLogger.Logger.Filename.Length > utcTimeLogger.Logger.Filename.Length);
         }
     }
 }
        public void LogCreationAndDestruction()
        {
            LogManager.Start();

            var consoleLogger = LogManager.GetLogger <ConsoleLogger>(null);

            Assert.IsNotNull(consoleLogger);
            try
            {
                LogManager.DestroyLogger(consoleLogger);
                Assert.Fail();
            }
            catch (ArgumentException) { }

            var config     = new LogConfiguration("testlog", LogType.Text, LogManager.DefaultSubscriptions);
            var someLogger = LogManager.CreateLogger <TextFileLogger>(config);

            Assert.IsNotNull(someLogger);
            Assert.AreSame(someLogger, LogManager.GetLogger <TextFileLogger>("testlog"));
            LogManager.DestroyLogger(someLogger);
            Assert.IsNull(LogManager.GetLogger <TextFileLogger>("testlog"));

            FileBackedLogger externalLogger = null;

            try
            {
                externalLogger =
                    new FileBackedLogger(new LogConfiguration("external", LogType.Text, LogManager.DefaultSubscriptions)
                {
                    Directory = "."
                }, DateTime.UtcNow);
                LogManager.DestroyLogger(externalLogger.Logger);
                Assert.Fail();
            }
            catch (ArgumentException) { }
            finally
            {
                externalLogger?.Dispose();
            }
            LogManager.Shutdown();
        }
Example #10
0
        public void LogWrangling()
        {
            LogManager.Start();
            LogManager.SetConfiguration(""); // wipe any config

            Assert.IsNotNull(LogManager.ConsoleLogger);
            try
            {
                LogManager.DestroyLogger(LogManager.ConsoleLogger);
                Assert.Fail();
            }
            catch (ArgumentException) { }

            IEventLogger someLogger = LogManager.CreateTextLogger("testlog");

            Assert.IsNotNull(someLogger as TextFileLogger);
            Assert.AreSame(someLogger, LogManager.GetFileLogger("testlog"));
            LogManager.DestroyLogger(someLogger);
            Assert.IsNull(LogManager.GetFileLogger("testlog"));

            FileBackedLogger externalLogger = null;

            try
            {
                externalLogger = new FileBackedLogger("external", ".", LoggerType.TextLogFile,
                                                      LogManager.DefaultFileBufferSizeMB,
                                                      1, FileBackedLogger.DefaultFilenameTemplate,
                                                      false);
                LogManager.DestroyLogger(externalLogger.Logger);
                Assert.Fail();
            }
            catch (ArgumentException) { }
            finally
            {
                if (externalLogger != null)
                {
                    externalLogger.Dispose();
                }
            }
            LogManager.Shutdown();
        }
Example #11
0
        public void CreateFileLoggerManager()
        {
            try
            {
                new FileBackedLogger("badlogger", ".", LoggerType.MemoryBuffer,
                                     LogManager.DefaultFileBufferSizeMB, 0,
                                     FileBackedLogger.DefaultFilenameTemplate,
                                     false);
                Assert.Fail();
            }
            catch (ArgumentException) { }

            using (var logger = new FileBackedLogger("testfile", ".", LoggerType.TextLogFile,
                                                     LogManager.DefaultFileBufferSizeMB, 0, "{0}", false))
            {
                Assert.IsNotNull(logger.Logger);
                Assert.AreEqual(0, logger.RotationInterval);
                string fullFilename = (logger.Logger as TextFileLogger).Filename;
                string dName        = Path.GetDirectoryName(fullFilename);
                Assert.AreEqual(dName, Path.GetFullPath("."));
                string fName = Path.GetFileName(fullFilename);
                Assert.AreEqual(fName, "testfile.log");
            }
        }
 public void FileLoggerLocalTime()
 {
     using (var localTimeLogger = new FileBackedLogger("loctime", ".", LoggerType.TextLogFile,
                                                       LogManager.DefaultFileBufferSizeMB, 1,
                                                       FileBackedLogger.DefaultFilenameTemplate, true))
     {
         using (var utcTimeLogger = new FileBackedLogger("utctime", ".", LoggerType.TextLogFile,
                                                         LogManager.DefaultFileBufferSizeMB, 1,
                                                         FileBackedLogger.DefaultFilenameTemplate, false))
         {
             Assert.AreEqual(localTimeLogger.FilenameTemplate,
                             FileBackedLogger.DefaultLocalTimeFilenameTemplate +
                             FileBackedLogger.TextLogExtension);
             Assert.AreEqual(utcTimeLogger.FilenameTemplate,
                             FileBackedLogger.DefaultFilenameTemplate + FileBackedLogger.TextLogExtension);
             // local time filename should be longer. (has timezone)
             Assert.IsTrue(localTimeLogger.Logger.Filename.Length > utcTimeLogger.Logger.Filename.Length);
         }
     }
 }
        public void CreateFileLoggerManager()
        {
            try
            {
                new FileBackedLogger("badlogger", ".", LoggerType.MemoryBuffer,
                                     LogManager.DefaultFileBufferSizeMB, 0,
                                     FileBackedLogger.DefaultFilenameTemplate,
                                     false);
                Assert.Fail();
            }
            catch (ArgumentException) { }

            using (var logger = new FileBackedLogger("testfile", ".", LoggerType.TextLogFile,
                                                     LogManager.DefaultFileBufferSizeMB, 0, "{0}", false))
            {
                Assert.IsNotNull(logger.Logger);
                Assert.AreEqual(0, logger.RotationInterval);
                string fullFilename = (logger.Logger as TextFileLogger).Filename;
                string dName = Path.GetDirectoryName(fullFilename);
                Assert.AreEqual(dName, Path.GetFullPath("."));
                string fName = Path.GetFileName(fullFilename);
                Assert.AreEqual(fName, "testfile.log");
            }
        }
Example #14
0
        private static bool ParseLogNode(XmlNode xmlNode, LogConfiguration config)
        {
            bool clean = true;

            foreach (XmlAttribute logAttribute in xmlNode.Attributes)
            {
                switch (logAttribute.Name.ToLower(CultureInfo.InvariantCulture))
                {
                case LogBufferSizeAttribute:
                    if (!int.TryParse(logAttribute.Value, out config.BufferSize) ||
                        !IsValidFileBufferSize(config.BufferSize))
                    {
                        InternalLogger.Write.InvalidConfiguration("invalid buffer size " + logAttribute.Value);
                        config.BufferSize = DefaultFileBufferSizeMB;
                        clean             = false;
                    }
                    break;

                case LogDirectoryAttribute:
                    if (!IsValidDirectory(logAttribute.Value))
                    {
                        InternalLogger.Write.InvalidConfiguration("invalid directory name " + logAttribute.Value);
                        clean = false;
                    }
                    else
                    {
                        config.Directory = logAttribute.Value;
                    }
                    break;

                case LogFilenameTemplateAttribute:
                    if (!FileBackedLogger.IsValidFilenameTemplate(logAttribute.Value))
                    {
                        InternalLogger.Write.InvalidConfiguration("invalid filename template " + logAttribute.Value);
                        clean = false;
                    }
                    else
                    {
                        config.FilenameTemplate = logAttribute.Value;
                    }
                    break;

                case LogTimestampLocal:
                    if (!bool.TryParse(logAttribute.Value, out config.TimestampLocal))
                    {
                        InternalLogger.Write.InvalidConfiguration("invalid timestamplocal value " + logAttribute.Value);
                        config.TimestampLocal = false;
                        clean = false;
                    }
                    break;

                case LogRotationAttribute:
                    if (!int.TryParse(logAttribute.Value, out config.RotationInterval) ||
                        !IsValidRotationInterval(config.RotationInterval))
                    {
                        InternalLogger.Write.InvalidConfiguration("invalid rotation interval " + logAttribute.Value);
                        config.RotationInterval = DefaultRotationInterval;
                        clean = false;
                    }
                    break;

                case LogHostnameAttribute:
                    if (Uri.CheckHostName(logAttribute.Value) == UriHostNameType.Unknown)
                    {
                        InternalLogger.Write.InvalidConfiguration("invalid hostname name " + logAttribute.Value);
                        clean = false;
                    }
                    else
                    {
                        config.Hostname = logAttribute.Value;
                    }
                    break;

                case LogPortAttribute:
                    if (!int.TryParse(logAttribute.Value, out config.Port) ||
                        config.Port <= 0)
                    {
                        InternalLogger.Write.InvalidConfiguration("invalid port " + logAttribute.Value);
                        config.Port = 80;
                        clean       = false;
                    }
                    break;
                }
            }

            clean &= ParseLogSources(xmlNode, config);
            clean &= ParseLogFilters(xmlNode, config);
            return(clean);
        }
Example #15
0
        public void TimeBasedRetention()
        {
            const string logName = "retention_time_test";

            LogManager.Start();
            var subscription = new[] { new EventProviderSubscription(TestLogger.Write, EventLevel.Verbose), };

            var config = new LogConfiguration(logName, LogType.Text, subscription)
            {
                RotationInterval = 86400,
                Directory        = ".",
            };
            var       files     = new List <string>();
            var       startTime = new DateTime(1776, 7, 4, 0, 0, 0, DateTimeKind.Utc);
            var       endTime   = startTime;
            const int rotations = 14;

            using (var log = new FileBackedLogger(config, startTime))
            {
                // XXX: this is cumbersome because of the way the file loggers are currently factored, needs fixing
                // in future refactor.
                var logger = (TextFileLogger)log.Logger;
                config.Logger = logger;
                files.Add(logger.Filename);
                for (var i = 0; i < rotations; ++i)
                {
                    TestLogger.Write.String("some string");

                    endTime = endTime + TimeSpan.FromSeconds(config.RotationInterval);
                    log.Rotate(endTime);
                    var newFile = logger.Filename;
                    Assert.IsFalse(files.Contains(newFile));
                    files.Add(logger.Filename);
                }
                TestLogger.Write.String("last string");
            }

            Assert.AreEqual(rotations + 1, files.Count);
            for (var i = 0; i < files.Count; ++i)
            {
                // XXX: this is a bit gross but for each file we need to set its creation time manually, in the normal
                // path we can trust wall time but that doesn't work here.
                var f = files[i];
                Assert.IsTrue(File.Exists(f));
                File.SetCreationTimeUtc(f, startTime + TimeSpan.FromSeconds(config.RotationInterval * i));
            }

            const int maxDays = rotations / 2;

            // XXX 2: have to re-create this because of the interplay between config + logger.
            config = new LogConfiguration(logName, LogType.Text, subscription)
            {
                RotationInterval = 86400,
                Directory        = ".",
                MaximumAge       = TimeSpan.FromDays(maxDays),
            };
            startTime = endTime;
            using (var log = new FileBackedLogger(config, startTime))
            {
                var logger = (TextFileLogger)log.Logger;
                config.Logger = logger;
                // expect the first half of 'maxDays' files to be gone.
                for (var i = 0; i < files.Count; ++i)
                {
                    if (i < maxDays)
                    {
                        Assert.IsFalse(File.Exists(files[i]));
                    }
                    else
                    {
                        Assert.IsTrue(File.Exists(files[i]));
                    }
                }
            }
            LogManager.Shutdown();
        }
        public void LogWrangling()
        {
            LogManager.Start();
            LogManager.SetConfiguration(""); // wipe any config

            Assert.IsNotNull(LogManager.ConsoleLogger);
            try
            {
                LogManager.DestroyLogger(LogManager.ConsoleLogger);
                Assert.Fail();
            }
            catch (ArgumentException) { }

            IEventLogger someLogger = LogManager.CreateTextLogger("testlog");
            Assert.IsNotNull(someLogger as TextFileLogger);
            Assert.AreSame(someLogger, LogManager.GetFileLogger("testlog"));
            LogManager.DestroyLogger(someLogger);
            Assert.IsNull(LogManager.GetFileLogger("testlog"));

            FileBackedLogger externalLogger = null;
            try
            {
                externalLogger = new FileBackedLogger("external", ".", LoggerType.TextLogFile,
                                                      LogManager.DefaultFileBufferSizeMB,
                                                      1, FileBackedLogger.DefaultFilenameTemplate,
                                                      false);
                LogManager.DestroyLogger(externalLogger.Logger);
                Assert.Fail();
            }
            catch (ArgumentException) { }
            finally
            {
                if (externalLogger != null)
                {
                    externalLogger.Dispose();
                }
            }
            LogManager.Shutdown();
        }
Example #17
0
        public void SizeBasedRetention()
        {
            const string logName     = "retention_size_test";
            const int    maxSize     = 5 * 1024 * 1024;
            const int    stringBytes = 32 * 1024;
            var          bigString   = new string('.', stringBytes / 2); // 2 byte characters

            LogManager.Start();
            var subscription = new[] { new EventProviderSubscription(TestLogger.Write, EventLevel.Verbose), };

            var config = new LogConfiguration(logName, LogType.Text, subscription)
            {
                RotationInterval = LogManager.MinRotationInterval,
                Directory        = ".",
            };
            var       files     = new List <string>();
            var       startTime = new DateTime(1776, 7, 4, 0, 0, 0, DateTimeKind.Utc);
            var       endTime   = startTime;
            const int rotations = (maxSize / stringBytes) * 2;

            using (var log = new FileBackedLogger(config, startTime))
            {
                // XXX: this is cumbersome because of the way the file loggers are currently factored, needs fixing
                // in future refactor.
                var logger = (TextFileLogger)log.Logger;
                config.Logger = logger;
                files.Add(logger.Filename);
                for (var i = 0; i < rotations; ++i)
                {
                    TestLogger.Write.String(bigString);

                    endTime = endTime + TimeSpan.FromSeconds(config.RotationInterval);
                    log.Rotate(endTime);
                    var newFile = logger.Filename;
                    Assert.IsFalse(files.Contains(newFile));
                    files.Add(logger.Filename);
                }
                TestLogger.Write.String(bigString);
            }

            long actualSize = 0;

            Assert.AreEqual(rotations + 1, files.Count);
            for (var i = 0; i < files.Count; ++i)
            {
                // XXX: this is a bit gross but for each file we need to set its creation time manually, in the normal
                // path we can trust wall time but that doesn't work here.
                var f    = files[i];
                var info = new FileInfo(f);
                Assert.IsTrue(info.Exists);
                actualSize += info.Length;
                File.SetCreationTimeUtc(f, startTime + TimeSpan.FromSeconds(config.RotationInterval * i));
            }

            // we want to determine the first file we expect to be gone by counting backwards over the size.
            long totalSize      = 0;
            int  firstRemaining = files.Count;

            for (var i = files.Count - 1; i >= 0; --i)
            {
                var info = new FileInfo(files[i]);
                totalSize += info.Length;
                if (totalSize > maxSize)
                {
                    firstRemaining = i + 1;
                    break;
                }
            }
            Assert.AreNotEqual(files.Count, firstRemaining);

            // XXX 2: have to re-create this because of the interplay between config + logger.
            config = new LogConfiguration(logName, LogType.Text, subscription)
            {
                RotationInterval = 86400,
                Directory        = ".",
                MaximumSize      = maxSize,
            };
            startTime = endTime;
            using (var log = new FileBackedLogger(config, startTime))
            {
                var logger = (TextFileLogger)log.Logger;
                config.Logger = logger;
                // Using the first remaining file detected above to ensure files we expected to go away have.
                long remainingSize = 0;
                for (var i = 0; i < files.Count; ++i)
                {
                    var info = new FileInfo(files[i]);
                    if (i < firstRemaining)
                    {
                        Assert.IsFalse(info.Exists);
                    }
                    else
                    {
                        Assert.IsTrue(info.Exists);
                        remainingSize += info.Length;
                    }
                }

                Assert.IsTrue(remainingSize <= maxSize);
            }
            LogManager.Shutdown();
        }