Skip to content

Added intervalMultiplier #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ public static LoggerConfiguration File(
TimeSpan? flushToDiskInterval)
{
return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, fileSizeLimitBytes,
levelSwitch, buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, null, null, null);
levelSwitch, buffered, shared, flushToDiskInterval, RollingInterval.Infinite, 1,false, null, null, null);
}

/// <summary>
@@ -110,7 +110,7 @@ public static LoggerConfiguration File(
TimeSpan? flushToDiskInterval)
{
return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch,
buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, null, null, null);
buffered, shared, flushToDiskInterval, RollingInterval.Infinite,1, false, null, null, null);
}

/// <summary>
@@ -133,6 +133,7 @@ public static LoggerConfiguration File(
/// <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="rollingInterval">The interval at which logging will roll over to a new file.</param>
/// <param name="intervalMultiplier">The number is multiplied by the interval.</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,
@@ -152,12 +153,13 @@ public static LoggerConfiguration File(
bool shared,
TimeSpan? flushToDiskInterval,
RollingInterval rollingInterval,
int intervalMultiplier,
bool rollOnFileSizeLimit,
int? retainedFileCountLimit,
Encoding encoding)
{
return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, fileSizeLimitBytes, levelSwitch, buffered,
shared, flushToDiskInterval, rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
shared, flushToDiskInterval, rollingInterval, intervalMultiplier,rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
}

/// <summary>
@@ -166,7 +168,7 @@ public static LoggerConfiguration File(
/// <param name="sinkConfiguration">Logger sink configuration.</param>
/// <param name="formatter">A formatter, such as <see cref="JsonFormatter"/>, to convert the log events into
/// text for the file. If control of regular text formatting is required, use the other
/// overload of <see cref="File(LoggerSinkConfiguration, string, LogEventLevel, string, IFormatProvider, long?, LoggingLevelSwitch, bool, bool, TimeSpan?, RollingInterval, bool, int?, Encoding, FileLifecycleHooks, TimeSpan?)"/>
/// overload of <see cref="File(LoggerSinkConfiguration, string, LogEventLevel, string, IFormatProvider, long?, LoggingLevelSwitch, bool, bool, TimeSpan?, RollingInterval, int, bool, int?, Encoding, FileLifecycleHooks, TimeSpan?)"/>
/// and specify the outputTemplate parameter instead.
/// </param>
/// <param name="path">Path to the file.</param>
@@ -182,6 +184,7 @@ public static LoggerConfiguration File(
/// <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="rollingInterval">The interval at which logging will roll over to a new file.</param>
/// <param name="intervalMultiplier">The number is multiplied by the interval.</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,
@@ -200,12 +203,13 @@ public static LoggerConfiguration File(
bool shared,
TimeSpan? flushToDiskInterval,
RollingInterval rollingInterval,
int intervalMultiplier,
bool rollOnFileSizeLimit,
int? retainedFileCountLimit,
Encoding encoding)
{
return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch, buffered,
shared, flushToDiskInterval, rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
shared, flushToDiskInterval, rollingInterval, intervalMultiplier, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
}

/// <summary>
@@ -228,6 +232,7 @@ public static LoggerConfiguration File(
/// <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="rollingInterval">The interval at which logging will roll over to a new file.</param>
/// <param name="intervalMultiplier">The number is multiplied by the interval.</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,
@@ -260,6 +265,7 @@ public static LoggerConfiguration File(
bool shared = false,
TimeSpan? flushToDiskInterval = null,
RollingInterval rollingInterval = RollingInterval.Infinite,
int intervalMultiplier = 1,
bool rollOnFileSizeLimit = false,
int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
Encoding? encoding = null,
@@ -273,7 +279,7 @@ public static LoggerConfiguration File(
var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes,
levelSwitch, buffered, shared, flushToDiskInterval,
rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, hooks, retainedFileTimeLimit);
rollingInterval, intervalMultiplier, rollOnFileSizeLimit, retainedFileCountLimit, encoding, hooks, retainedFileTimeLimit);
}

/// <summary>
@@ -282,7 +288,7 @@ public static LoggerConfiguration File(
/// <param name="sinkConfiguration">Logger sink configuration.</param>
/// <param name="formatter">A formatter, such as <see cref="JsonFormatter"/>, to convert the log events into
/// text for the file. If control of regular text formatting is required, use the other
/// overload of <see cref="File(LoggerSinkConfiguration, string, LogEventLevel, string, IFormatProvider, long?, LoggingLevelSwitch, bool, bool, TimeSpan?, RollingInterval, bool, int?, Encoding, FileLifecycleHooks, TimeSpan?)"/>
/// overload of <see cref="File(LoggerSinkConfiguration, string, LogEventLevel, string, IFormatProvider, long?, LoggingLevelSwitch, bool, bool, TimeSpan?, RollingInterval,int, bool, int?, Encoding, FileLifecycleHooks, TimeSpan?)"/>
/// and specify the outputTemplate parameter instead.
/// </param>
/// <param name="path">Path to the file.</param>
@@ -298,6 +304,7 @@ public static LoggerConfiguration File(
/// <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="rollingInterval">The interval at which logging will roll over to a new file.</param>
/// <param name="intervalMultiplier">The number is multiplied by the interval.</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,
@@ -329,6 +336,7 @@ public static LoggerConfiguration File(
bool shared = false,
TimeSpan? flushToDiskInterval = null,
RollingInterval rollingInterval = RollingInterval.Infinite,
int intervalMultiplier = 1,
bool rollOnFileSizeLimit = false,
int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
Encoding? encoding = null,
@@ -340,7 +348,7 @@ public static LoggerConfiguration File(
if (path == null) throw new ArgumentNullException(nameof(path));

return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch,
buffered, false, shared, flushToDiskInterval, encoding, rollingInterval, rollOnFileSizeLimit,
buffered, false, shared, flushToDiskInterval, encoding, rollingInterval, intervalMultiplier, rollOnFileSizeLimit,
retainedFileCountLimit, hooks, retainedFileTimeLimit);
}

@@ -496,7 +504,7 @@ public static LoggerConfiguration File(
if (path == null) throw new ArgumentNullException(nameof(path));

return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, null, levelSwitch, false, true,
false, null, encoding, RollingInterval.Infinite, false, null, hooks, null);
false, null, encoding, RollingInterval.Infinite, 1, false, null, hooks, null);
}

static LoggerConfiguration ConfigureFile(
@@ -512,6 +520,7 @@ static LoggerConfiguration ConfigureFile(
TimeSpan? flushToDiskInterval,
Encoding? encoding,
RollingInterval rollingInterval,
int intervalMultiplier,
bool rollOnFileSizeLimit,
int? retainedFileCountLimit,
FileLifecycleHooks? hooks,
@@ -532,7 +541,7 @@ static LoggerConfiguration ConfigureFile(
{
if (rollOnFileSizeLimit || rollingInterval != RollingInterval.Infinite)
{
sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, rollingInterval, rollOnFileSizeLimit, hooks, retainedFileTimeLimit);
sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, rollingInterval, intervalMultiplier, rollOnFileSizeLimit, hooks, retainedFileTimeLimit);
}
else
{
6 changes: 4 additions & 2 deletions src/Serilog.Sinks.File/Sinks/File/PathRoller.cs
Original file line number Diff line number Diff line change
@@ -31,12 +31,14 @@ class PathRoller
readonly Regex _filenameMatcher;

readonly RollingInterval _interval;
private readonly int _intervalMultiplier;
readonly string _periodFormat;

public PathRoller(string path, RollingInterval interval)
public PathRoller(string path, RollingInterval interval, int intervalMultiplier)
{
if (path == null) throw new ArgumentNullException(nameof(path));
_interval = interval;
_intervalMultiplier = intervalMultiplier;
_periodFormat = interval.GetFormat();

var pathDirectory = Path.GetDirectoryName(path);
@@ -112,6 +114,6 @@ public IEnumerable<RollingLogFile> SelectMatches(IEnumerable<string> filenames)

public DateTime? GetCurrentCheckpoint(DateTime instant) => _interval.GetCurrentCheckpoint(instant);

public DateTime? GetNextCheckpoint(DateTime instant) => _interval.GetNextCheckpoint(instant);
public DateTime? GetNextCheckpoint(DateTime instant) => _interval.GetNextCheckpoint(_intervalMultiplier, instant);
}
}
4 changes: 3 additions & 1 deletion src/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@ public RollingFileSink(string path,
bool buffered,
bool shared,
RollingInterval rollingInterval,
int intervalMultiplier,
bool rollOnFileSizeLimit,
FileLifecycleHooks? hooks,
TimeSpan? retainedFileTimeLimit)
@@ -58,8 +59,9 @@ public RollingFileSink(string path,
if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 1) throw new ArgumentException("Invalid value provided; file size limit must be at least 1 byte, or null.");
if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1) throw new ArgumentException("Zero or negative value provided; retained file count limit must be at least 1");
if (retainedFileTimeLimit.HasValue && retainedFileTimeLimit < TimeSpan.Zero) throw new ArgumentException("Negative value provided; retained file time limit must be non-negative.", nameof(retainedFileTimeLimit));
if (intervalMultiplier < 1) intervalMultiplier = 1;

_roller = new PathRoller(path, rollingInterval);
_roller = new PathRoller(path, rollingInterval, intervalMultiplier);
_textFormatter = textFormatter;
_fileSizeLimitBytes = fileSizeLimitBytes;
_retainedFileCountLimit = retainedFileCountLimit;
12 changes: 6 additions & 6 deletions src/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ public static string GetFormat(this RollingInterval interval)
}
}

public static DateTime? GetNextCheckpoint(this RollingInterval interval, DateTime instant)
public static DateTime? GetNextCheckpoint(this RollingInterval interval, int intervalMultiiplier, DateTime instant)
{
var current = GetCurrentCheckpoint(interval, instant);
if (current == null)
@@ -69,15 +69,15 @@ public static string GetFormat(this RollingInterval interval)
switch (interval)
{
case RollingInterval.Year:
return current.Value.AddYears(1);
return current.Value.AddYears(intervalMultiiplier);
case RollingInterval.Month:
return current.Value.AddMonths(1);
return current.Value.AddMonths(intervalMultiiplier);
case RollingInterval.Day:
return current.Value.AddDays(1);
return current.Value.AddDays(intervalMultiiplier);
case RollingInterval.Hour:
return current.Value.AddHours(1);
return current.Value.AddHours(intervalMultiiplier);
case RollingInterval.Minute:
return current.Value.AddMinutes(1);
return current.Value.AddMinutes(intervalMultiiplier);
default:
throw new ArgumentException("Invalid rolling interval");
}
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ public void NextIntervalTests(RollingInterval interval, DateTime instant, DateTi
var current = interval.GetCurrentCheckpoint(instant);
Assert.Equal(currentCheckpoint, current);

var next = interval.GetNextCheckpoint(instant);
var next = interval.GetNextCheckpoint(1, instant);
Assert.Equal(nextCheckpoint, next);
}
}
18 changes: 9 additions & 9 deletions test/Serilog.Sinks.File.Tests/TemplatedPathRollerTests.cs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ public class PathRollerTests
[Fact]
public void TheLogFileIncludesDateToken()
{
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day, 1);
var now = new DateTime(2013, 7, 14, 3, 24, 9, 980);
roller.GetLogFilePath(now, null, out var path);
AssertEqualAbsolute(Path.Combine("Logs", "log-20130714.txt"), path);
@@ -19,7 +19,7 @@ public void TheLogFileIncludesDateToken()
[Fact]
public void ANonZeroIncrementIsIncludedAndPadded()
{
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day, 1);
var now = new DateTime(2013, 7, 14, 3, 24, 9, 980);
roller.GetLogFilePath(now, 12, out var path);
AssertEqualAbsolute(Path.Combine("Logs", "log-20130714_012.txt"), path);
@@ -35,14 +35,14 @@ static void AssertEqualAbsolute(string path1, string path2)
[Fact]
public void TheRollerReturnsTheLogFileDirectory()
{
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day, 1);
AssertEqualAbsolute("Logs", roller.LogFileDirectory);
}

[Fact]
public void TheLogFileIsNotRequiredToIncludeAnExtension()
{
var roller = new PathRoller(Path.Combine("Logs", "log-"), RollingInterval.Day);
var roller = new PathRoller(Path.Combine("Logs", "log-"), RollingInterval.Day, 1);
var now = new DateTime(2013, 7, 14, 3, 24, 9, 980);
roller.GetLogFilePath(now, null, out var path);
AssertEqualAbsolute(Path.Combine("Logs", "log-20130714"), path);
@@ -51,7 +51,7 @@ public void TheLogFileIsNotRequiredToIncludeAnExtension()
[Fact]
public void TheLogFileIsNotRequiredToIncludeADirectory()
{
var roller = new PathRoller("log-", RollingInterval.Day);
var roller = new PathRoller("log-", RollingInterval.Day, 1);
var now = new DateTime(2013, 7, 14, 3, 24, 9, 980);
roller.GetLogFilePath(now, null, out var path);
AssertEqualAbsolute("log-20130714", path);
@@ -60,7 +60,7 @@ public void TheLogFileIsNotRequiredToIncludeADirectory()
[Fact]
public void MatchingExcludesSimilarButNonMatchingFiles()
{
var roller = new PathRoller("log-.txt", RollingInterval.Day);
var roller = new PathRoller("log-.txt", RollingInterval.Day, 1);
const string similar1 = "log-0.txt";
const string similar2 = "log-hello.txt";
var matched = roller.SelectMatches(new[] { similar1, similar2 });
@@ -70,7 +70,7 @@ public void MatchingExcludesSimilarButNonMatchingFiles()
[Fact]
public void TheDirectorSearchPatternUsesWildcardInPlaceOfDate()
{
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day, 1);
Assert.Equal("log-*.txt", roller.DirectorySearchPattern);
}

@@ -79,7 +79,7 @@ public void TheDirectorSearchPatternUsesWildcardInPlaceOfDate()
[InlineData("log-.txt", "log-2013121013.txt", "log-2013121013_031.txt", RollingInterval.Hour)]
public void MatchingSelectsFiles(string template, string zeroth, string thirtyFirst, RollingInterval interval)
{
var roller = new PathRoller(template, interval);
var roller = new PathRoller(template, interval, 1);
var matched = roller.SelectMatches(new[] { zeroth, thirtyFirst }).ToArray();
Assert.Equal(2, matched.Length);
Assert.Null(matched[0].SequenceNumber);
@@ -91,7 +91,7 @@ public void MatchingSelectsFiles(string template, string zeroth, string thirtyFi
[InlineData("log-.txt", "log-2015010110.txt", "log-2015010109.txt", RollingInterval.Hour)]
public void MatchingParsesSubstitutions(string template, string newer, string older, RollingInterval interval)
{
var roller = new PathRoller(template, interval);
var roller = new PathRoller(template, interval, 1);
var matched = roller.SelectMatches(new[] { older, newer }).OrderByDescending(m => m.DateTime).Select(m => m.Filename).ToArray();
Assert.Equal(new[] { newer, older }, matched);
}