コード例 #1
0
        public static DateTime?GetCurrentCheckpoint(this PersistentFileRollingInterval interval, DateTime instant)
        {
            switch (interval)
            {
            case PersistentFileRollingInterval.Infinite:
                return(null);

            case PersistentFileRollingInterval.Year:
                return(new DateTime(instant.Year, 1, 1, 0, 0, 0, instant.Kind));

            case PersistentFileRollingInterval.Month:
                return(new DateTime(instant.Year, instant.Month, 1, 0, 0, 0, instant.Kind));

            case PersistentFileRollingInterval.Day:
                return(new DateTime(instant.Year, instant.Month, instant.Day, 0, 0, 0, instant.Kind));

            case PersistentFileRollingInterval.Hour:
                return(new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, 0, 0, instant.Kind));

            case PersistentFileRollingInterval.Minute:
                return(new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, instant.Minute, 0, instant.Kind));

            default:
                throw new ArgumentException("Invalid rolling interval");
            }
        }
コード例 #2
0
        public static DateTime?GetNextCheckpoint(this PersistentFileRollingInterval interval, DateTime instant)
        {
            var current = GetCurrentCheckpoint(interval, instant);

            if (current == null)
            {
                return(null);
            }

            switch (interval)
            {
            case PersistentFileRollingInterval.Year:
                return(current.Value.AddYears(1));

            case PersistentFileRollingInterval.Month:
                return(current.Value.AddMonths(1));

            case PersistentFileRollingInterval.Day:
                return(current.Value.AddDays(1));

            case PersistentFileRollingInterval.Hour:
                return(current.Value.AddHours(1));

            case PersistentFileRollingInterval.Minute:
                return(current.Value.AddMinutes(1));

            default:
                throw new ArgumentException("Invalid rolling interval");
            }
        }
コード例 #3
0
        public static string GetFormat(this PersistentFileRollingInterval interval)
        {
            switch (interval)
            {
            case PersistentFileRollingInterval.Infinite:
                return("");

            case PersistentFileRollingInterval.Year:
                return("yyyy");

            case PersistentFileRollingInterval.Month:
                return("yyyyMM");

            case PersistentFileRollingInterval.Day:
                return("yyyyMMdd");

            case PersistentFileRollingInterval.Hour:
                return("yyyyMMddHH");

            case PersistentFileRollingInterval.Minute:
                return("yyyyMMddHHmm");

            default:
                throw new ArgumentException("Invalid rolling interval");
            }
        }
コード例 #4
0
        public PathRoller(string path, PersistentFileRollingInterval interval)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            _interval     = interval;
            _periodFormat = interval.GetFormat();

            var pathDirectory = Path.GetDirectoryName(path);

            if (string.IsNullOrEmpty(pathDirectory))
            {
                pathDirectory = Directory.GetCurrentDirectory();
            }

            _directory       = Path.GetFullPath(pathDirectory);
            _filenamePrefix  = Path.GetFileNameWithoutExtension(path);
            _filenameSuffix  = Path.GetExtension(path);
            _filenameMatcher = new Regex(
                "^" +
                Regex.Escape(_filenamePrefix) +
                "(?<" + PeriodMatchGroup + ">\\d{" + _periodFormat.Length + "})" +
                "(?<" + SequenceNumberMatchGroup + ">_[0-9]{3,}){0,1}" +
                Regex.Escape(_filenameSuffix) +
                "$");

            DirectorySearchPattern = $"{_filenamePrefix}*{_filenameSuffix}";
        }
コード例 #5
0
ファイル: Program.cs プロジェクト: saltydk/SARotate
        private static Logger CreateLogger(string cwd, string?logFilePath, bool verboseFlagExists)
        {
            string logPath = logFilePath ?? _configuration["Serilog:WriteTo:0:Args:configure:0:Args:path"] ?? cwd + "/sarotate.log";
            string minimumLogLevelConfig  = verboseFlagExists ? "Verbose" : _configuration["Serilog:WriteTo:0:Args:configure:0:Args:restrictedToMinimumLevel"] ?? "Information";
            string rollingIntervalConfig  = _configuration["Serilog:WriteTo:0:Args:configure:0:Args:rollingInterval"] ?? "Day";
            int    fileSizeLimitBytes     = int.Parse(_configuration["Serilog:WriteTo:0:Args:configure:0:Args:fileSizeLimitBytes"] ?? "5000000");
            int    retainedFileCountLimit = int.Parse(_configuration["Serilog:WriteTo:0:Args:configure:0:Args:retainedFileCountLimit"] ?? "5");

            LogEventLevel minimumLogEventLevel            = ConvertMinimumLogLevelConfigToLogEventLevel(minimumLogLevelConfig);
            PersistentFileRollingInterval rollingInterval = ConvertRollingIntervalConfigValueToEnum(rollingIntervalConfig);

            Logger logger = new LoggerConfiguration()
                            .Enrich.FromLogContext()
                            .Enrich.WithProperty("Application", "SARotate")
                            .Enrich.With <GenericLogEnricher>()
                            .MinimumLevel.ControlledBy(new LoggingLevelSwitch(minimumLogEventLevel))
                            .WriteTo.PersistentFile(logPath,
                                                    fileSizeLimitBytes: fileSizeLimitBytes,
                                                    persistentFileRollingInterval: rollingInterval,
                                                    retainedFileCountLimit: retainedFileCountLimit)
                            .WriteTo.Async(a => a.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:j}{NewLine}{Exception}"))
                            .CreateLogger();

            Log.Logger = logger;

            return(logger);
        }
コード例 #6
0
        public void NextIntervalTests(PersistentFileRollingInterval interval, DateTime instant, DateTime?currentCheckpoint, DateTime?nextCheckpoint)
        {
            var current = interval.GetCurrentCheckpoint(instant);

            Assert.Equal(currentCheckpoint, current);

            var next = interval.GetNextCheckpoint(instant);

            Assert.Equal(nextCheckpoint, next);
        }
コード例 #7
0
 public static LoggerConfiguration PersistentFile(
     this LoggerSinkConfiguration sinkConfiguration,
     ITextFormatter formatter,
     string path,
     LogEventLevel restrictedToMinimumLevel,
     long?fileSizeLimitBytes,
     LoggingLevelSwitch levelSwitch,
     bool buffered,
     bool shared,
     TimeSpan?flushToDiskInterval,
     PersistentFileRollingInterval persistentFileRollingInterval,
     bool rollOnFileSizeLimit,
     int?retainedFileCountLimit,
     Encoding encoding)
 {
     return(PersistentFile(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch, buffered,
                           shared, flushToDiskInterval, persistentFileRollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null));
 }
コード例 #8
0
        public RollingFileSink(string path,
                               ITextFormatter textFormatter,
                               long?fileSizeLimitBytes,
                               int?retainedFileCountLimit,
                               Encoding encoding,
                               bool buffered,
                               bool shared,
                               PersistentFileRollingInterval persistentFileRollingInterval,
                               bool rollOnFileSizeLimit,
                               FileLifecycleHooks hooks,
                               bool keepFilename            = false,
                               bool rollOnEachProcessRun    = true,
                               bool useLastWriteAsTimestamp = false)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0)
            {
                throw new ArgumentException("Negative value provided; file size limit must be non-negative.");
            }
            if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1)
            {
                throw new ArgumentException(
                          "Zero or negative value provided; retained file count limit must be at least 1.");
            }

            _roller                 = new PathRoller(path, persistentFileRollingInterval);
            _textFormatter          = textFormatter;
            _fileSizeLimitBytes     = fileSizeLimitBytes;
            _retainedFileCountLimit = retainedFileCountLimit;
            _encoding               = encoding;
            _buffered               = buffered;
            _shared                 = shared;
            _rollOnFileSizeLimit    = rollOnFileSizeLimit;
            _hooks                   = hooks;
            _keepFilename            = keepFilename;
            _rollOnEachProcessRun    = rollOnEachProcessRun;
            _useLastWriteAsTimestamp = useLastWriteAsTimestamp;
        }
コード例 #9
0
        /// <summary>
        /// Write log events to the specified file.
        /// </summary>
        /// <param name="sinkConfiguration">Logger sink configuration.</param>
        /// <param name="path">Path to the file.</param>
        /// <param name="restrictedToMinimumLevel">The minimum level for
        /// events passed through the sink. Ignored when <paramref name="levelSwitch"/> is specified.</param>
        /// <param name="levelSwitch">A switch allowing the pass-through minimum level
        /// to be changed at runtime.</param>
        /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
        /// <param name="outputTemplate">A message template describing the format used to write to the sink.
        /// the default is "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}".</param>
        /// <param name="fileSizeLimitBytes">The approximate maximum size, in bytes, to which a log file will be allowed to grow.
        /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit
        /// will be written in full even if it exceeds the limit.</param>
        /// <param name="buffered">Indicates if flushing to the output file can be buffered or not. The default
        /// is false.</param>
        /// <param name="shared">Allow the log file to be shared by multiple processes. The default is false.</param>
        /// <param name="flushToDiskInterval">If provided, a full disk flush will be performed periodically at the specified interval.</param>
        /// <param name="persistentFileRollingInterval">The interval at which logging will roll over to a new file.</param>
        /// <param name="rollOnFileSizeLimit">If <code>true</code>, a new file will be created when the file size limit is reached. Filenames
        /// will have a number appended in the format <code>_NNN</code>, with the first filename given no number.</param>
        /// <param name="retainedFileCountLimit">The maximum number of log files that will be retained,
        /// including the current log file. For unlimited retention, pass null. The default is 31.</param>
        /// <param name="encoding">Character encoding used to write the text file. The default is UTF-8 without BOM.</param>
        /// <param name="hooks">Optionally enables hooking into log file lifecycle events.</param>
        /// <param name="preserveLogFilename">Avoid the log file name to change after each roll, on roll the log file is copied to a new file and the current file is restarted empty</param>
        /// <param name="rollOnEachProcessRun">Roll the name of the log file every time the process starts.</param>
        /// <param name="useLastWriteAsTimestamp">When the file is rolled, the last write timestamp of the log file is used instead of the current timestamp.</param>
        /// <returns>Configuration object allowing method chaining.</returns>
        public static LoggerConfiguration PersistentFile(
            this LoggerSinkConfiguration sinkConfiguration,
            string path,
            LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
            string outputTemplate          = DefaultOutputTemplate,
            IFormatProvider formatProvider = null,
            long?fileSizeLimitBytes        = DefaultFileSizeLimitBytes,
            LoggingLevelSwitch levelSwitch = null,
            bool buffered = false,
            bool shared   = false,
            TimeSpan?flushToDiskInterval = null,
            PersistentFileRollingInterval persistentFileRollingInterval = PersistentFileRollingInterval.Infinite,
            bool rollOnFileSizeLimit     = false,
            int?retainedFileCountLimit   = DefaultRetainedFileCountLimit,
            Encoding encoding            = null,
            FileLifecycleHooks hooks     = null,
            bool preserveLogFilename     = true,
            bool rollOnEachProcessRun    = true,
            bool useLastWriteAsTimestamp = false)
        {
            if (sinkConfiguration == null)
            {
                throw new ArgumentNullException(nameof(sinkConfiguration));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            if (outputTemplate == null)
            {
                throw new ArgumentNullException(nameof(outputTemplate));
            }

            var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);

            return(PersistentFile(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes,
                                  levelSwitch, buffered, shared, flushToDiskInterval,
                                  persistentFileRollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, hooks,
                                  preserveLogFilename, rollOnEachProcessRun, useLastWriteAsTimestamp));
        }
コード例 #10
0
        static LoggerConfiguration ConfigureFile(
            this Func <ILogEventSink, LogEventLevel, LoggingLevelSwitch, LoggerConfiguration> addSink,
            ITextFormatter formatter,
            string path,
            LogEventLevel restrictedToMinimumLevel,
            long?fileSizeLimitBytes,
            LoggingLevelSwitch levelSwitch,
            bool buffered,
            bool propagateExceptions,
            bool shared,
            TimeSpan?flushToDiskInterval,
            Encoding encoding,
            PersistentFileRollingInterval persistentFileRollingInterval,
            bool rollOnFileSizeLimit,
            int?retainedFileCountLimit,
            FileLifecycleHooks hooks,
            bool preserveLogFilename     = true,
            bool rollOnEachProcessRun    = true,
            bool useLastWriteAsTimestamp = false)
        {
            if (addSink == null)
            {
                throw new ArgumentNullException(nameof(addSink));
            }
            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0)
            {
                throw new ArgumentException("Negative value provided; file size limit must be non-negative.", nameof(fileSizeLimitBytes));
            }
            if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1)
            {
                throw new ArgumentException("At least one file must be retained.", nameof(retainedFileCountLimit));
            }
            if (shared && buffered)
            {
                throw new ArgumentException("Buffered writes are not available when file sharing is enabled.", nameof(buffered));
            }
            if (shared && hooks != null)
            {
                throw new ArgumentException("File lifecycle hooks are not currently supported for shared log files.", nameof(hooks));
            }

            ILogEventSink sink;

            if (rollOnFileSizeLimit || persistentFileRollingInterval != PersistentFileRollingInterval.Infinite)
            {
                sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, persistentFileRollingInterval, rollOnFileSizeLimit, hooks, preserveLogFilename, rollOnEachProcessRun, useLastWriteAsTimestamp);
            }
            else
            {
                try
                {
                    if (shared)
                    {
#pragma warning disable 618
                        sink = new SharedFileSink(path, formatter, fileSizeLimitBytes, encoding);
#pragma warning restore 618
                    }
                    else
                    {
                        sink = new FileSink(path, formatter, fileSizeLimitBytes, encoding, buffered, hooks);
                    }
                }
                catch (Exception ex)
                {
                    SelfLog.WriteLine("Unable to open file sink for {0}: {1}", path, ex);

                    if (propagateExceptions)
                    {
                        throw;
                    }

                    return(addSink(new NullSink(), LevelAlias.Maximum, null));
                }
            }

            if (flushToDiskInterval.HasValue)
            {
#pragma warning disable 618
                sink = new PeriodicFlushToDiskSink(sink, flushToDiskInterval.Value);
#pragma warning restore 618
            }

            return(addSink(sink, restrictedToMinimumLevel, levelSwitch));
        }
コード例 #11
0
        public void MatchingSelectsFiles(string template, string zeroth, string thirtyFirst, PersistentFileRollingInterval interval)
        {
            var roller  = new PathRoller(template, interval);
            var matched = roller.SelectMatches(new[] { zeroth, thirtyFirst }).ToArray();

            Assert.Equal(2, matched.Length);
            Assert.Equal(null, matched[0].SequenceNumber);
            Assert.Equal(31, matched[1].SequenceNumber);
        }
コード例 #12
0
        public void MatchingParsesSubstitutions(string template, string newer, string older, PersistentFileRollingInterval interval)
        {
            var roller  = new PathRoller(template, interval);
            var matched = roller.SelectMatches(new[] { older, newer }).OrderByDescending(m => m.DateTime).Select(m => m.Filename).ToArray();

            Assert.Equal(new[] { newer, older }, matched);
        }