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(); }
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); } }
/// <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); }
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."); } } } }
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(); }
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(); }
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"); } }
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); }
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 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(); }