diff --git a/.editorconfig b/.editorconfig
index 102e19f..a853ae9 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,6 +5,7 @@ trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4
+charset = utf-8
[*.{csproj,json,config,yml,props}]
indent_size = 2
@@ -14,3 +15,8 @@ end_of_line = lf
[*.{cmd, bat}]
end_of_line = crlf
+
+# C# formatting settings - Namespace options
+csharp_style_namespace_declarations = file_scoped:suggestion
+
+csharp_style_prefer_switch_expression = true:suggestion
diff --git a/Build.ps1 b/Build.ps1
index 3c41f46..e0eebae 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -16,7 +16,7 @@ $commitHash = $(git rev-parse --short HEAD)
$buildSuffix = @{ $true = "$($suffix)-$($commitHash)"; $false = "$($branch)-$($commitHash)" }[$suffix -ne ""]
echo "build: Package version suffix is $suffix"
-echo "build: Build version suffix is $buildSuffix"
+echo "build: Build version suffix is $buildSuffix"
foreach ($src in ls src/*) {
Push-Location $src
@@ -29,7 +29,7 @@ foreach ($src in ls src/*) {
} else {
& dotnet pack -c Release -o ..\..\artifacts --no-build
}
- if($LASTEXITCODE -ne 0) { exit 1 }
+ if($LASTEXITCODE -ne 0) { exit 1 }
Pop-Location
}
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..d54992d
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,16 @@
+
+
+ latest
+ True
+ true
+ true
+ $(MSBuildThisFileDirectory)assets/Serilog.snk
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000..6132714
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.sh b/build.sh
index 3bb5fec..cf241dc 100755
--- a/build.sh
+++ b/build.sh
@@ -1,6 +1,6 @@
-#!/bin/bash
+#!/bin/bash
-set -e
+set -e
dotnet --info
dotnet --list-sdks
dotnet restore
diff --git a/example/Sample/Program.cs b/example/Sample/Program.cs
index 89e6c95..d980bd8 100644
--- a/example/Sample/Program.cs
+++ b/example/Sample/Program.cs
@@ -1,38 +1,35 @@
-using System;
-using System.IO;
using Serilog;
using Serilog.Debugging;
-namespace Sample
+namespace Sample;
+
+public class Program
{
- public class Program
+ public static void Main(string[] args)
{
- public static void Main(string[] args)
- {
- SelfLog.Enable(Console.Out);
+ SelfLog.Enable(Console.Out);
- var sw = System.Diagnostics.Stopwatch.StartNew();
+ var sw = System.Diagnostics.Stopwatch.StartNew();
- Log.Logger = new LoggerConfiguration()
- .WriteTo.File("log.txt")
- .CreateLogger();
+ Log.Logger = new LoggerConfiguration()
+ .WriteTo.File("log.txt")
+ .CreateLogger();
- for (var i = 0; i < 1000000; ++i)
- {
- Log.Information("Hello, file logger!");
- }
+ for (var i = 0; i < 1000000; ++i)
+ {
+ Log.Information("Hello, file logger!");
+ }
- Log.CloseAndFlush();
+ Log.CloseAndFlush();
- sw.Stop();
+ sw.Stop();
- Console.WriteLine($"Elapsed: {sw.ElapsedMilliseconds} ms");
- Console.WriteLine($"Size: {new FileInfo("log.txt").Length}");
+ Console.WriteLine($"Elapsed: {sw.ElapsedMilliseconds} ms");
+ Console.WriteLine($"Size: {new FileInfo("log.txt").Length}");
- Console.WriteLine("Press any key to delete the temporary log file...");
- Console.ReadKey(true);
+ Console.WriteLine("Press any key to delete the temporary log file...");
+ Console.ReadKey(true);
- File.Delete("log.txt");
- }
+ File.Delete("log.txt");
}
}
diff --git a/example/Sample/Sample.csproj b/example/Sample/Sample.csproj
index 5e5c833..a05ad36 100644
--- a/example/Sample/Sample.csproj
+++ b/example/Sample/Sample.csproj
@@ -1,12 +1,8 @@
-
+
net48;net6.0
- 8.0
- enable
- Sample
Exe
- Sample
true
diff --git a/serilog-sinks-file.sln b/serilog-sinks-file.sln
index 8d76bf7..b996c93 100644
--- a/serilog-sinks-file.sln
+++ b/serilog-sinks-file.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26730.15
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33424.131
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{037440DE-440B-4129-9F7A-09B42D00397E}"
EndProject
@@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{E9D1B5
appveyor.yml = appveyor.yml
Build.ps1 = Build.ps1
build.sh = build.sh
+ Directory.Build.props = Directory.Build.props
+ Directory.Build.targets = Directory.Build.targets
README.md = README.md
assets\Serilog.snk = assets\Serilog.snk
EndProjectSection
diff --git a/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs b/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs
index 3518322..42e21cb 100644
--- a/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs
+++ b/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright 2013-2017 Serilog Contributors
+// Copyright 2013-2017 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using System.ComponentModel;
-using System.IO;
using System.Text;
using Serilog.Configuration;
using Serilog.Core;
@@ -27,546 +25,545 @@
// ReSharper disable RedundantArgumentDefaultValue, MethodOverloadWithOptionalParameter
-namespace Serilog
+namespace Serilog;
+
+/// Extends with methods to add file sinks.
+public static class FileLoggerConfigurationExtensions
{
- /// Extends with methods to add file sinks.
- public static class FileLoggerConfigurationExtensions
- {
- const int DefaultRetainedFileCountLimit = 31; // A long month of logs
- const long DefaultFileSizeLimitBytes = 1L * 1024 * 1024 * 1024; // 1GB
- const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}";
+ const int DefaultRetainedFileCountLimit = 31; // A long month of logs
+ const long DefaultFileSizeLimitBytes = 1L * 1024 * 1024 * 1024; // 1GB
+ const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}";
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// Supplies culture-specific formatting information, or null.
- /// 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}".
- /// 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.
- /// Indicates if flushing to the output file can be buffered or not. The default
- /// is false.
- /// Allow the log file to be shared by multiple processes. The default is false.
- /// If provided, a full disk flush will be performed periodically at the specified interval.
- /// Configuration object allowing method chaining.
- /// The file will be written using the UTF-8 character set.
- [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
- public static LoggerConfiguration File(
- this LoggerSinkConfiguration sinkConfiguration,
- string path,
- LogEventLevel restrictedToMinimumLevel,
- string outputTemplate,
- IFormatProvider formatProvider,
- long? fileSizeLimitBytes,
- LoggingLevelSwitch levelSwitch,
- bool buffered,
- bool shared,
- TimeSpan? flushToDiskInterval)
- {
- return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, fileSizeLimitBytes,
- levelSwitch, buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, null, null, null);
- }
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// Supplies culture-specific formatting information, or null.
+ /// 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}".
+ /// 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.
+ /// Indicates if flushing to the output file can be buffered or not. The default
+ /// is false.
+ /// Allow the log file to be shared by multiple processes. The default is false.
+ /// If provided, a full disk flush will be performed periodically at the specified interval.
+ /// Configuration object allowing method chaining.
+ /// The file will be written using the UTF-8 character set.
+ [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
+ public static LoggerConfiguration File(
+ this LoggerSinkConfiguration sinkConfiguration,
+ string path,
+ LogEventLevel restrictedToMinimumLevel,
+ string outputTemplate,
+ IFormatProvider formatProvider,
+ long? fileSizeLimitBytes,
+ LoggingLevelSwitch levelSwitch,
+ bool buffered,
+ bool shared,
+ TimeSpan? flushToDiskInterval)
+ {
+ return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, fileSizeLimitBytes,
+ levelSwitch, buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, null, null, null);
+ }
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// A formatter, such as , to convert the log events into
- /// text for the file. If control of regular text formatting is required, use the other
- /// overload of
- /// and specify the outputTemplate parameter instead.
- ///
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// 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.
- /// Indicates if flushing to the output file can be buffered or not. The default
- /// is false.
- /// Allow the log file to be shared by multiple processes. The default is false.
- /// If provided, a full disk flush will be performed periodically at the specified interval.
- /// Configuration object allowing method chaining.
- /// The file will be written using the UTF-8 character set.
- [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
- public static LoggerConfiguration File(
- this LoggerSinkConfiguration sinkConfiguration,
- ITextFormatter formatter,
- string path,
- LogEventLevel restrictedToMinimumLevel,
- long? fileSizeLimitBytes,
- LoggingLevelSwitch levelSwitch,
- bool buffered,
- bool shared,
- TimeSpan? flushToDiskInterval)
- {
- return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch,
- buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, null, null, null);
- }
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// A formatter, such as , to convert the log events into
+ /// text for the file. If control of regular text formatting is required, use the other
+ /// overload of
+ /// and specify the outputTemplate parameter instead.
+ ///
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// 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.
+ /// Indicates if flushing to the output file can be buffered or not. The default
+ /// is false.
+ /// Allow the log file to be shared by multiple processes. The default is false.
+ /// If provided, a full disk flush will be performed periodically at the specified interval.
+ /// Configuration object allowing method chaining.
+ /// The file will be written using the UTF-8 character set.
+ [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
+ public static LoggerConfiguration File(
+ this LoggerSinkConfiguration sinkConfiguration,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel,
+ long? fileSizeLimitBytes,
+ LoggingLevelSwitch levelSwitch,
+ bool buffered,
+ bool shared,
+ TimeSpan? flushToDiskInterval)
+ {
+ return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch,
+ buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, null, null, null);
+ }
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// Supplies culture-specific formatting information, or null.
- /// 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}".
- /// 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.
- /// Indicates if flushing to the output file can be buffered or not. The default
- /// is false.
- /// Allow the log file to be shared by multiple processes. The default is false.
- /// If provided, a full disk flush will be performed periodically at the specified interval.
- /// The interval at which logging will roll over to a new file.
- /// If true
, a new file will be created when the file size limit is reached. Filenames
- /// will have a number appended in the format _NNN
, with the first filename given no number.
- /// The maximum number of log files that will be retained,
- /// including the current log file. For unlimited retention, pass null. The default is 31.
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Configuration object allowing method chaining.
- [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
- public static LoggerConfiguration File(
- this LoggerSinkConfiguration sinkConfiguration,
- string path,
- LogEventLevel restrictedToMinimumLevel,
- string outputTemplate,
- IFormatProvider formatProvider,
- long? fileSizeLimitBytes,
- LoggingLevelSwitch levelSwitch,
- bool buffered,
- bool shared,
- TimeSpan? flushToDiskInterval,
- RollingInterval rollingInterval,
- bool rollOnFileSizeLimit,
- int? retainedFileCountLimit,
- Encoding encoding)
- {
- return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, fileSizeLimitBytes, levelSwitch, buffered,
- shared, flushToDiskInterval, rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
- }
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// Supplies culture-specific formatting information, or null.
+ /// 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}".
+ /// 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.
+ /// Indicates if flushing to the output file can be buffered or not. The default
+ /// is false.
+ /// Allow the log file to be shared by multiple processes. The default is false.
+ /// If provided, a full disk flush will be performed periodically at the specified interval.
+ /// The interval at which logging will roll over to a new file.
+ /// If true
, a new file will be created when the file size limit is reached. Filenames
+ /// will have a number appended in the format _NNN
, with the first filename given no number.
+ /// The maximum number of log files that will be retained,
+ /// including the current log file. For unlimited retention, pass null. The default is 31.
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Configuration object allowing method chaining.
+ [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
+ public static LoggerConfiguration File(
+ this LoggerSinkConfiguration sinkConfiguration,
+ string path,
+ LogEventLevel restrictedToMinimumLevel,
+ string outputTemplate,
+ IFormatProvider formatProvider,
+ long? fileSizeLimitBytes,
+ LoggingLevelSwitch levelSwitch,
+ bool buffered,
+ bool shared,
+ TimeSpan? flushToDiskInterval,
+ RollingInterval rollingInterval,
+ bool rollOnFileSizeLimit,
+ int? retainedFileCountLimit,
+ Encoding encoding)
+ {
+ return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, fileSizeLimitBytes, levelSwitch, buffered,
+ shared, flushToDiskInterval, rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
+ }
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// A formatter, such as , to convert the log events into
- /// text for the file. If control of regular text formatting is required, use the other
- /// overload of
- /// and specify the outputTemplate parameter instead.
- ///
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// 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.
- /// Indicates if flushing to the output file can be buffered or not. The default
- /// is false.
- /// Allow the log file to be shared by multiple processes. The default is false.
- /// If provided, a full disk flush will be performed periodically at the specified interval.
- /// The interval at which logging will roll over to a new file.
- /// If true
, a new file will be created when the file size limit is reached. Filenames
- /// will have a number appended in the format _NNN
, with the first filename given no number.
- /// The maximum number of log files that will be retained,
- /// including the current log file. For unlimited retention, pass null. The default is 31.
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Configuration object allowing method chaining.
- [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
- public static LoggerConfiguration File(
- this LoggerSinkConfiguration sinkConfiguration,
- ITextFormatter formatter,
- string path,
- LogEventLevel restrictedToMinimumLevel,
- long? fileSizeLimitBytes,
- LoggingLevelSwitch levelSwitch,
- bool buffered,
- bool shared,
- TimeSpan? flushToDiskInterval,
- RollingInterval rollingInterval,
- bool rollOnFileSizeLimit,
- int? retainedFileCountLimit,
- Encoding encoding)
- {
- return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch, buffered,
- shared, flushToDiskInterval, rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
- }
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// A formatter, such as , to convert the log events into
+ /// text for the file. If control of regular text formatting is required, use the other
+ /// overload of
+ /// and specify the outputTemplate parameter instead.
+ ///
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// 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.
+ /// Indicates if flushing to the output file can be buffered or not. The default
+ /// is false.
+ /// Allow the log file to be shared by multiple processes. The default is false.
+ /// If provided, a full disk flush will be performed periodically at the specified interval.
+ /// The interval at which logging will roll over to a new file.
+ /// If true
, a new file will be created when the file size limit is reached. Filenames
+ /// will have a number appended in the format _NNN
, with the first filename given no number.
+ /// The maximum number of log files that will be retained,
+ /// including the current log file. For unlimited retention, pass null. The default is 31.
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Configuration object allowing method chaining.
+ [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
+ public static LoggerConfiguration File(
+ this LoggerSinkConfiguration sinkConfiguration,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel,
+ long? fileSizeLimitBytes,
+ LoggingLevelSwitch levelSwitch,
+ bool buffered,
+ bool shared,
+ TimeSpan? flushToDiskInterval,
+ RollingInterval rollingInterval,
+ bool rollOnFileSizeLimit,
+ int? retainedFileCountLimit,
+ Encoding encoding)
+ {
+ return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch, buffered,
+ shared, flushToDiskInterval, rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, null);
+ }
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// Supplies culture-specific formatting information, or null.
- /// 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}".
- /// 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.
- /// Indicates if flushing to the output file can be buffered or not. The default
- /// is false.
- /// Allow the log file to be shared by multiple processes. The default is false.
- /// If provided, a full disk flush will be performed periodically at the specified interval.
- /// The interval at which logging will roll over to a new file.
- /// If true
, a new file will be created when the file size limit is reached. Filenames
- /// will have a number appended in the format _NNN
, with the first filename given no number.
- /// The maximum number of log files that will be retained,
- /// including the current log file. For unlimited retention, pass null. The default is 31.
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Optionally enables hooking into log file lifecycle events.
- /// The maximum time after the end of an interval that a rolling log file will be retained.
- /// Must be greater than or equal to .
- /// Ignored if is .
- /// The default is to retain files indefinitely.
- /// Configuration object allowing method chaining.
- /// When is null
- /// When is null
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- public static LoggerConfiguration File(
- 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,
- RollingInterval rollingInterval = RollingInterval.Infinite,
- bool rollOnFileSizeLimit = false,
- int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
- Encoding? encoding = null,
- FileLifecycleHooks? hooks = null,
- TimeSpan? retainedFileTimeLimit = null)
- {
- if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
- if (path == null) throw new ArgumentNullException(nameof(path));
- if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// Supplies culture-specific formatting information, or null.
+ /// 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}".
+ /// 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.
+ /// Indicates if flushing to the output file can be buffered or not. The default
+ /// is false.
+ /// Allow the log file to be shared by multiple processes. The default is false.
+ /// If provided, a full disk flush will be performed periodically at the specified interval.
+ /// The interval at which logging will roll over to a new file.
+ /// If true
, a new file will be created when the file size limit is reached. Filenames
+ /// will have a number appended in the format _NNN
, with the first filename given no number.
+ /// The maximum number of log files that will be retained,
+ /// including the current log file. For unlimited retention, pass null. The default is 31.
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Optionally enables hooking into log file lifecycle events.
+ /// The maximum time after the end of an interval that a rolling log file will be retained.
+ /// Must be greater than or equal to .
+ /// Ignored if is .
+ /// The default is to retain files indefinitely.
+ /// Configuration object allowing method chaining.
+ /// When is null
+ /// When is null
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ public static LoggerConfiguration File(
+ 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,
+ RollingInterval rollingInterval = RollingInterval.Infinite,
+ bool rollOnFileSizeLimit = false,
+ int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
+ Encoding? encoding = null,
+ FileLifecycleHooks? hooks = null,
+ TimeSpan? retainedFileTimeLimit = null)
+ {
+ 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 File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes,
- levelSwitch, buffered, shared, flushToDiskInterval,
- rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, hooks, retainedFileTimeLimit);
- }
+ var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
+ return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes,
+ levelSwitch, buffered, shared, flushToDiskInterval,
+ rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding, hooks, retainedFileTimeLimit);
+ }
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// A formatter, such as , to convert the log events into
- /// text for the file. If control of regular text formatting is required, use the other
- /// overload of
- /// and specify the outputTemplate parameter instead.
- ///
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// 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.
- /// Indicates if flushing to the output file can be buffered or not. The default
- /// is false.
- /// Allow the log file to be shared by multiple processes. The default is false.
- /// If provided, a full disk flush will be performed periodically at the specified interval.
- /// The interval at which logging will roll over to a new file.
- /// If true
, a new file will be created when the file size limit is reached. Filenames
- /// will have a number appended in the format _NNN
, with the first filename given no number.
- /// The maximum number of log files that will be retained,
- /// including the current log file. For unlimited retention, pass null. The default is 31.
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Optionally enables hooking into log file lifecycle events.
- /// The maximum time after the end of an interval that a rolling log file will be retained.
- /// Must be greater than or equal to .
- /// Ignored if is .
- /// The default is to retain files indefinitely.
- /// Configuration object allowing method chaining.
- /// When is null
- /// When is null
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- public static LoggerConfiguration File(
- this LoggerSinkConfiguration sinkConfiguration,
- ITextFormatter formatter,
- string path,
- LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
- long? fileSizeLimitBytes = DefaultFileSizeLimitBytes,
- LoggingLevelSwitch? levelSwitch = null,
- bool buffered = false,
- bool shared = false,
- TimeSpan? flushToDiskInterval = null,
- RollingInterval rollingInterval = RollingInterval.Infinite,
- bool rollOnFileSizeLimit = false,
- int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
- Encoding? encoding = null,
- FileLifecycleHooks? hooks = null,
- TimeSpan? retainedFileTimeLimit = null)
- {
- if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
- if (formatter == null) throw new ArgumentNullException(nameof(formatter));
- if (path == null) throw new ArgumentNullException(nameof(path));
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// A formatter, such as , to convert the log events into
+ /// text for the file. If control of regular text formatting is required, use the other
+ /// overload of
+ /// and specify the outputTemplate parameter instead.
+ ///
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// 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.
+ /// Indicates if flushing to the output file can be buffered or not. The default
+ /// is false.
+ /// Allow the log file to be shared by multiple processes. The default is false.
+ /// If provided, a full disk flush will be performed periodically at the specified interval.
+ /// The interval at which logging will roll over to a new file.
+ /// If true
, a new file will be created when the file size limit is reached. Filenames
+ /// will have a number appended in the format _NNN
, with the first filename given no number.
+ /// The maximum number of log files that will be retained,
+ /// including the current log file. For unlimited retention, pass null. The default is 31.
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Optionally enables hooking into log file lifecycle events.
+ /// The maximum time after the end of an interval that a rolling log file will be retained.
+ /// Must be greater than or equal to .
+ /// Ignored if is .
+ /// The default is to retain files indefinitely.
+ /// Configuration object allowing method chaining.
+ /// When is null
+ /// When is null
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ public static LoggerConfiguration File(
+ this LoggerSinkConfiguration sinkConfiguration,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ long? fileSizeLimitBytes = DefaultFileSizeLimitBytes,
+ LoggingLevelSwitch? levelSwitch = null,
+ bool buffered = false,
+ bool shared = false,
+ TimeSpan? flushToDiskInterval = null,
+ RollingInterval rollingInterval = RollingInterval.Infinite,
+ bool rollOnFileSizeLimit = false,
+ int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
+ Encoding? encoding = null,
+ FileLifecycleHooks? hooks = null,
+ TimeSpan? retainedFileTimeLimit = null)
+ {
+ if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
+ if (formatter == null) throw new ArgumentNullException(nameof(formatter));
+ if (path == null) throw new ArgumentNullException(nameof(path));
- return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch,
- buffered, false, shared, flushToDiskInterval, encoding, rollingInterval, rollOnFileSizeLimit,
- retainedFileCountLimit, hooks, retainedFileTimeLimit);
- }
+ return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch,
+ buffered, false, shared, flushToDiskInterval, encoding, rollingInterval, rollOnFileSizeLimit,
+ retainedFileCountLimit, hooks, retainedFileTimeLimit);
+ }
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// Supplies culture-specific formatting information, or null.
- /// 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}".
- /// Configuration object allowing method chaining.
- /// The file will be written using the UTF-8 character set.
- /// When is null
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
- public static LoggerConfiguration File(
- this LoggerAuditSinkConfiguration sinkConfiguration,
- string path,
- LogEventLevel restrictedToMinimumLevel,
- string outputTemplate,
- IFormatProvider formatProvider,
- LoggingLevelSwitch levelSwitch)
- {
- return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, levelSwitch, null, null);
- }
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// Supplies culture-specific formatting information, or null.
+ /// 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}".
+ /// Configuration object allowing method chaining.
+ /// The file will be written using the UTF-8 character set.
+ /// When is null
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
+ public static LoggerConfiguration File(
+ this LoggerAuditSinkConfiguration sinkConfiguration,
+ string path,
+ LogEventLevel restrictedToMinimumLevel,
+ string outputTemplate,
+ IFormatProvider formatProvider,
+ LoggingLevelSwitch levelSwitch)
+ {
+ return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, levelSwitch, null, null);
+ }
- ///
- /// Write log events to the specified file.
- ///
- /// Logger sink configuration.
- /// A formatter, such as , to convert the log events into
- /// text for the file. If control of regular text formatting is required, use the other
- /// overload of
- /// and specify the outputTemplate parameter instead.
- ///
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// Configuration object allowing method chaining.
- /// The file will be written using the UTF-8 character set.
- /// When is null
- /// When is null
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
- public static LoggerConfiguration File(
- this LoggerAuditSinkConfiguration sinkConfiguration,
- ITextFormatter formatter,
- string path,
- LogEventLevel restrictedToMinimumLevel,
- LoggingLevelSwitch levelSwitch)
- {
- return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, levelSwitch, null, null);
- }
+ ///
+ /// Write log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// A formatter, such as , to convert the log events into
+ /// text for the file. If control of regular text formatting is required, use the other
+ /// overload of
+ /// and specify the outputTemplate parameter instead.
+ ///
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// Configuration object allowing method chaining.
+ /// The file will be written using the UTF-8 character set.
+ /// When is null
+ /// When is null
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
+ public static LoggerConfiguration File(
+ this LoggerAuditSinkConfiguration sinkConfiguration,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel,
+ LoggingLevelSwitch levelSwitch)
+ {
+ return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, levelSwitch, null, null);
+ }
- ///
- /// Write audit log events to the specified file.
- ///
- /// Logger sink configuration.
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// Supplies culture-specific formatting information, or null.
- /// 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}".
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Optionally enables hooking into log file lifecycle events.
- /// Configuration object allowing method chaining.
- /// When is null
- /// When is null
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- public static LoggerConfiguration File(
- this LoggerAuditSinkConfiguration sinkConfiguration,
- string path,
- LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
- string outputTemplate = DefaultOutputTemplate,
- IFormatProvider? formatProvider = null,
- LoggingLevelSwitch? levelSwitch = null,
- Encoding? encoding = null,
- FileLifecycleHooks? hooks = null)
- {
- if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
- if (path == null) throw new ArgumentNullException(nameof(path));
- if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));
+ ///
+ /// Write audit log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// Supplies culture-specific formatting information, or null.
+ /// 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}".
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Optionally enables hooking into log file lifecycle events.
+ /// Configuration object allowing method chaining.
+ /// When is null
+ /// When is null
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ public static LoggerConfiguration File(
+ this LoggerAuditSinkConfiguration sinkConfiguration,
+ string path,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ string outputTemplate = DefaultOutputTemplate,
+ IFormatProvider? formatProvider = null,
+ LoggingLevelSwitch? levelSwitch = null,
+ Encoding? encoding = null,
+ FileLifecycleHooks? hooks = null)
+ {
+ 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 File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, levelSwitch, encoding, hooks);
- }
+ var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
+ return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, levelSwitch, encoding, hooks);
+ }
- ///
- /// Write audit log events to the specified file.
- ///
- /// Logger sink configuration.
- /// A formatter, such as , to convert the log events into
- /// text for the file. If control of regular text formatting is required, use the other
- /// overload of
- /// and specify the outputTemplate parameter instead.
- ///
- /// Path to the file.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Optionally enables hooking into log file lifecycle events.
- /// Configuration object allowing method chaining.
- /// When is null
- /// When is null
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- public static LoggerConfiguration File(
- this LoggerAuditSinkConfiguration sinkConfiguration,
- ITextFormatter formatter,
- string path,
- LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
- LoggingLevelSwitch? levelSwitch = null,
- Encoding? encoding = null,
- FileLifecycleHooks? hooks = null)
- {
- if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
- if (formatter == null) throw new ArgumentNullException(nameof(formatter));
- if (path == null) throw new ArgumentNullException(nameof(path));
+ ///
+ /// Write audit log events to the specified file.
+ ///
+ /// Logger sink configuration.
+ /// A formatter, such as , to convert the log events into
+ /// text for the file. If control of regular text formatting is required, use the other
+ /// overload of
+ /// and specify the outputTemplate parameter instead.
+ ///
+ /// Path to the file.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Optionally enables hooking into log file lifecycle events.
+ /// Configuration object allowing method chaining.
+ /// When is null
+ /// When is null
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ public static LoggerConfiguration File(
+ this LoggerAuditSinkConfiguration sinkConfiguration,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ LoggingLevelSwitch? levelSwitch = null,
+ Encoding? encoding = null,
+ FileLifecycleHooks? hooks = null)
+ {
+ if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
+ if (formatter == null) throw new ArgumentNullException(nameof(formatter));
+ 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);
- }
+ return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, null, levelSwitch, false, true,
+ false, null, encoding, RollingInterval.Infinite, false, null, hooks, null);
+ }
- static LoggerConfiguration ConfigureFile(
- this Func addSink,
- ITextFormatter formatter,
- string path,
- LogEventLevel restrictedToMinimumLevel,
- long? fileSizeLimitBytes,
- LoggingLevelSwitch? levelSwitch,
- bool buffered,
- bool propagateExceptions,
- bool shared,
- TimeSpan? flushToDiskInterval,
- Encoding? encoding,
- RollingInterval rollingInterval,
- bool rollOnFileSizeLimit,
- int? retainedFileCountLimit,
- FileLifecycleHooks? hooks,
- TimeSpan? retainedFileTimeLimit)
- {
- 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 < 1) throw new ArgumentException("Invalid value provided; file size limit must be at least 1 byte, or null.", nameof(fileSizeLimitBytes));
- if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1) throw new ArgumentException("At least one file must be retained.", nameof(retainedFileCountLimit));
- if (retainedFileTimeLimit.HasValue && retainedFileTimeLimit < TimeSpan.Zero) throw new ArgumentException("Negative value provided; retained file time limit must be non-negative.", nameof(retainedFileTimeLimit));
- 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));
+ static LoggerConfiguration ConfigureFile(
+ this Func addSink,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel,
+ long? fileSizeLimitBytes,
+ LoggingLevelSwitch? levelSwitch,
+ bool buffered,
+ bool propagateExceptions,
+ bool shared,
+ TimeSpan? flushToDiskInterval,
+ Encoding? encoding,
+ RollingInterval rollingInterval,
+ bool rollOnFileSizeLimit,
+ int? retainedFileCountLimit,
+ FileLifecycleHooks? hooks,
+ TimeSpan? retainedFileTimeLimit)
+ {
+ 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 < 1) throw new ArgumentException("Invalid value provided; file size limit must be at least 1 byte, or null.", nameof(fileSizeLimitBytes));
+ if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1) throw new ArgumentException("At least one file must be retained.", nameof(retainedFileCountLimit));
+ if (retainedFileTimeLimit.HasValue && retainedFileTimeLimit < TimeSpan.Zero) throw new ArgumentException("Negative value provided; retained file time limit must be non-negative.", nameof(retainedFileTimeLimit));
+ 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;
+ ILogEventSink sink;
- try
+ try
+ {
+ if (rollOnFileSizeLimit || rollingInterval != RollingInterval.Infinite)
+ {
+ sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, rollingInterval, rollOnFileSizeLimit, hooks, retainedFileTimeLimit);
+ }
+ else
{
- if (rollOnFileSizeLimit || rollingInterval != RollingInterval.Infinite)
+ if (shared)
{
- sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, rollingInterval, rollOnFileSizeLimit, hooks, retainedFileTimeLimit);
+#pragma warning disable 618
+ sink = new SharedFileSink(path, formatter, fileSizeLimitBytes, encoding);
+#pragma warning restore 618
}
else
{
- 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);
- }
-
+ sink = new FileSink(path, formatter, fileSizeLimitBytes, encoding, buffered, hooks);
}
+
}
- catch (Exception ex)
- {
- SelfLog.WriteLine("Unable to open file sink for {0}: {1}", path, ex);
+ }
+ catch (Exception ex)
+ {
+ SelfLog.WriteLine("Unable to open file sink for {0}: {1}", path, ex);
- if (propagateExceptions)
- throw;
+ if (propagateExceptions)
+ throw;
- return addSink(new NullSink(), LevelAlias.Maximum, null);
- }
+ return addSink(new NullSink(), LevelAlias.Maximum, null);
+ }
- if (flushToDiskInterval.HasValue)
- {
+ if (flushToDiskInterval.HasValue)
+ {
#pragma warning disable 618
- sink = new PeriodicFlushToDiskSink(sink, flushToDiskInterval.Value);
+ sink = new PeriodicFlushToDiskSink(sink, flushToDiskInterval.Value);
#pragma warning restore 618
- }
-
- return addSink(sink, restrictedToMinimumLevel, levelSwitch);
}
+
+ return addSink(sink, restrictedToMinimumLevel, levelSwitch);
}
}
diff --git a/src/Serilog.Sinks.File/Properties/AssemblyInfo.cs b/src/Serilog.Sinks.File/Properties/AssemblyInfo.cs
index 93017cb..b431c64 100644
--- a/src/Serilog.Sinks.File/Properties/AssemblyInfo.cs
+++ b/src/Serilog.Sinks.File/Properties/AssemblyInfo.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Reflection;
-using System.Runtime.CompilerServices;
+using System.Runtime.CompilerServices;
[assembly: CLSCompliant(true)]
diff --git a/src/Serilog.Sinks.File/RollingInterval.cs b/src/Serilog.Sinks.File/RollingInterval.cs
index 9fac848..55582ec 100644
--- a/src/Serilog.Sinks.File/RollingInterval.cs
+++ b/src/Serilog.Sinks.File/RollingInterval.cs
@@ -12,41 +12,40 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-namespace Serilog
+namespace Serilog;
+
+///
+/// Specifies the frequency at which the log file should roll.
+///
+public enum RollingInterval
{
///
- /// Specifies the frequency at which the log file should roll.
+ /// The log file will never roll; no time period information will be appended to the log file name.
///
- public enum RollingInterval
- {
- ///
- /// The log file will never roll; no time period information will be appended to the log file name.
- ///
- Infinite,
+ Infinite,
- ///
- /// Roll every year. Filenames will have a four-digit year appended in the pattern yyyy
.
- ///
- Year,
+ ///
+ /// Roll every year. Filenames will have a four-digit year appended in the pattern yyyy
.
+ ///
+ Year,
- ///
- /// Roll every calendar month. Filenames will have yyyyMM
appended.
- ///
- Month,
+ ///
+ /// Roll every calendar month. Filenames will have yyyyMM
appended.
+ ///
+ Month,
- ///
- /// Roll every day. Filenames will have yyyyMMdd
appended.
- ///
- Day,
+ ///
+ /// Roll every day. Filenames will have yyyyMMdd
appended.
+ ///
+ Day,
- ///
- /// Roll every hour. Filenames will have yyyyMMddHH
appended.
- ///
- Hour,
+ ///
+ /// Roll every hour. Filenames will have yyyyMMddHH
appended.
+ ///
+ Hour,
- ///
- /// Roll every minute. Filenames will have yyyyMMddHHmm
appended.
- ///
- Minute
- }
+ ///
+ /// Roll every minute. Filenames will have yyyyMMddHHmm
appended.
+ ///
+ Minute
}
diff --git a/src/Serilog.Sinks.File/Serilog.Sinks.File.csproj b/src/Serilog.Sinks.File/Serilog.Sinks.File.csproj
index 3eb3c1e..e9edc97 100644
--- a/src/Serilog.Sinks.File/Serilog.Sinks.File.csproj
+++ b/src/Serilog.Sinks.File/Serilog.Sinks.File.csproj
@@ -5,12 +5,7 @@
5.0.1
Serilog Contributors
net45;netstandard1.3;netstandard2.0;netstandard2.1;net5.0;net6.0
- 8.0
- enable
true
- ../../assets/Serilog.snk
- true
- true
serilog;file
images\icon.png
https://serilog.net/images/serilog-sink-nuget.png
@@ -19,7 +14,6 @@
https://github.com/serilog/serilog-sinks-file
git
Serilog
- true
true
false
true
@@ -29,9 +23,9 @@
-
+
-
+
diff --git a/src/Serilog.Sinks.File/Sinks/File/Clock.cs b/src/Serilog.Sinks.File/Sinks/File/Clock.cs
index b7cf3cc..7624fb4 100644
--- a/src/Serilog.Sinks.File/Sinks/File/Clock.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/Clock.cs
@@ -1,4 +1,4 @@
-// Copyright 2013-2016 Serilog Contributors
+// Copyright 2013-2016 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,27 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
+namespace Serilog.Sinks.File;
-namespace Serilog.Sinks.File
+static class Clock
{
- static class Clock
- {
- static Func _dateTimeNow = () => DateTime.Now;
+ static Func _dateTimeNow = () => DateTime.Now;
- [ThreadStatic]
- static DateTime _testDateTimeNow;
+ [ThreadStatic]
+ static DateTime _testDateTimeNow;
- public static DateTime DateTimeNow => _dateTimeNow();
+ public static DateTime DateTimeNow => _dateTimeNow();
- // Time is set per thread to support parallel
- // If any thread uses the clock in test mode, all threads
- // must use it in test mode; once set to test mode only
- // terminating the application returns it to normal use.
- public static void SetTestDateTimeNow(DateTime now)
- {
- _testDateTimeNow = now;
- _dateTimeNow = () => _testDateTimeNow;
- }
+ // Time is set per thread to support parallel
+ // If any thread uses the clock in test mode, all threads
+ // must use it in test mode; once set to test mode only
+ // terminating the application returns it to normal use.
+ public static void SetTestDateTimeNow(DateTime now)
+ {
+ _testDateTimeNow = now;
+ _dateTimeNow = () => _testDateTimeNow;
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/FileLifeCycleHookChain.cs b/src/Serilog.Sinks.File/Sinks/File/FileLifeCycleHookChain.cs
index cf27bfe..2c3034c 100644
--- a/src/Serilog.Sinks.File/Sinks/File/FileLifeCycleHookChain.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/FileLifeCycleHookChain.cs
@@ -12,35 +12,32 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.IO;
using System.Text;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+class FileLifeCycleHookChain : FileLifecycleHooks
{
- class FileLifeCycleHookChain : FileLifecycleHooks
- {
- private readonly FileLifecycleHooks _first;
- private readonly FileLifecycleHooks _second;
+ private readonly FileLifecycleHooks _first;
+ private readonly FileLifecycleHooks _second;
- public FileLifeCycleHookChain(FileLifecycleHooks first, FileLifecycleHooks second)
- {
- _first = first ?? throw new ArgumentNullException(nameof(first));
- _second = second ?? throw new ArgumentNullException(nameof(second));
- }
+ public FileLifeCycleHookChain(FileLifecycleHooks first, FileLifecycleHooks second)
+ {
+ _first = first ?? throw new ArgumentNullException(nameof(first));
+ _second = second ?? throw new ArgumentNullException(nameof(second));
+ }
- public override Stream OnFileOpened(string path, Stream underlyingStream, Encoding encoding)
- {
- var firstStreamResult = _first.OnFileOpened(path, underlyingStream, encoding);
- var secondStreamResult = _second.OnFileOpened(path, firstStreamResult, encoding);
+ public override Stream OnFileOpened(string path, Stream underlyingStream, Encoding encoding)
+ {
+ var firstStreamResult = _first.OnFileOpened(path, underlyingStream, encoding);
+ var secondStreamResult = _second.OnFileOpened(path, firstStreamResult, encoding);
- return secondStreamResult;
- }
+ return secondStreamResult;
+ }
- public override void OnFileDeleting(string path)
- {
- _first.OnFileDeleting(path);
- _second.OnFileDeleting(path);
- }
+ public override void OnFileDeleting(string path)
+ {
+ _first.OnFileDeleting(path);
+ _second.OnFileDeleting(path);
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/FileLifecycleHooks.cs b/src/Serilog.Sinks.File/Sinks/File/FileLifecycleHooks.cs
index 26fd1e2..ac6df00 100644
--- a/src/Serilog.Sinks.File/Sinks/File/FileLifecycleHooks.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/FileLifecycleHooks.cs
@@ -12,68 +12,66 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System.IO;
using System.Text;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+///
+/// Enables hooking into log file lifecycle events.
+/// Hooks run synchronously and therefore may affect responsiveness of the application if long operations are performed.
+///
+public abstract class FileLifecycleHooks
{
///
- /// Enables hooking into log file lifecycle events.
- /// Hooks run synchronously and therefore may affect responsiveness of the application if long operations are performed.
+ /// Initialize or wrap the opened on the log file. This can be used to write
+ /// file headers, or wrap the stream in another that adds buffering, compression, encryption, etc. The underlying
+ /// file may or may not be empty when this method is called.
///
- public abstract class FileLifecycleHooks
- {
- ///
- /// Initialize or wrap the opened on the log file. This can be used to write
- /// file headers, or wrap the stream in another that adds buffering, compression, encryption, etc. The underlying
- /// file may or may not be empty when this method is called.
- ///
- ///
- /// A value must be returned from overrides of this method. Serilog will flush and/or dispose the returned value, but will not
- /// dispose the stream initially passed in unless it is itself returned.
- ///
- /// The full path to the log file.
- /// The underlying opened on the log file.
- /// The encoding to use when reading/writing to the stream.
- /// The Serilog should use when writing events to the log file.
- public virtual Stream OnFileOpened(string path, Stream underlyingStream, Encoding encoding) => OnFileOpened(underlyingStream, encoding);
+ ///
+ /// A value must be returned from overrides of this method. Serilog will flush and/or dispose the returned value, but will not
+ /// dispose the stream initially passed in unless it is itself returned.
+ ///
+ /// The full path to the log file.
+ /// The underlying opened on the log file.
+ /// The encoding to use when reading/writing to the stream.
+ /// The Serilog should use when writing events to the log file.
+ public virtual Stream OnFileOpened(string path, Stream underlyingStream, Encoding encoding) => OnFileOpened(underlyingStream, encoding);
- ///
- /// Initialize or wrap the opened on the log file. This can be used to write
- /// file headers, or wrap the stream in another that adds buffering, compression, encryption, etc. The underlying
- /// file may or may not be empty when this method is called.
- ///
- ///
- /// A value must be returned from overrides of this method. Serilog will flush and/or dispose the returned value, but will not
- /// dispose the stream initially passed in unless it is itself returned.
- ///
- /// The underlying opened on the log file.
- /// The encoding to use when reading/writing to the stream.
- /// The Serilog should use when writing events to the log file.
- public virtual Stream OnFileOpened(Stream underlyingStream, Encoding encoding) => underlyingStream;
+ ///
+ /// Initialize or wrap the opened on the log file. This can be used to write
+ /// file headers, or wrap the stream in another that adds buffering, compression, encryption, etc. The underlying
+ /// file may or may not be empty when this method is called.
+ ///
+ ///
+ /// A value must be returned from overrides of this method. Serilog will flush and/or dispose the returned value, but will not
+ /// dispose the stream initially passed in unless it is itself returned.
+ ///
+ /// The underlying opened on the log file.
+ /// The encoding to use when reading/writing to the stream.
+ /// The Serilog should use when writing events to the log file.
+ public virtual Stream OnFileOpened(Stream underlyingStream, Encoding encoding) => underlyingStream;
- ///
- /// Called before an obsolete (rolling) log file is deleted.
- /// This can be used to copy old logs to an archive location or send to a backup server.
- ///
- /// The full path to the file being deleted.
- public virtual void OnFileDeleting(string path) {}
+ ///
+ /// Called before an obsolete (rolling) log file is deleted.
+ /// This can be used to copy old logs to an archive location or send to a backup server.
+ ///
+ /// The full path to the file being deleted.
+ public virtual void OnFileDeleting(string path) {}
- ///
- /// Creates a chain of that have their methods called sequentially
- /// Can be used to compose together; e.g. add header information to each log file and
- /// compress it.
- ///
- ///
- ///
- /// var hooks = new GZipHooks().Then(new HeaderWriter("File Header"));
- ///
- ///
- /// The next to have its methods called in the chain
- ///
- public FileLifecycleHooks Then(FileLifecycleHooks next)
- {
- return new FileLifeCycleHookChain(this, next);
- }
+ ///
+ /// Creates a chain of that have their methods called sequentially
+ /// Can be used to compose together; e.g. add header information to each log file and
+ /// compress it.
+ ///
+ ///
+ ///
+ /// var hooks = new GZipHooks().Then(new HeaderWriter("File Header"));
+ ///
+ ///
+ /// The next to have its methods called in the chain
+ ///
+ public FileLifecycleHooks Then(FileLifecycleHooks next)
+ {
+ return new FileLifeCycleHookChain(this, next);
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/FileSink.cs b/src/Serilog.Sinks.File/Sinks/File/FileSink.cs
index 611b45d..9e39892 100644
--- a/src/Serilog.Sinks.File/Sinks/File/FileSink.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/FileSink.cs
@@ -12,140 +12,137 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.IO;
using System.Text;
using Serilog.Events;
using Serilog.Formatting;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+///
+/// Write log events to a disk file.
+///
+public sealed class FileSink : IFileSink, IDisposable
{
- ///
- /// Write log events to a disk file.
- ///
- public sealed class FileSink : IFileSink, IDisposable
+ readonly TextWriter _output;
+ readonly FileStream _underlyingStream;
+ readonly ITextFormatter _textFormatter;
+ readonly long? _fileSizeLimitBytes;
+ readonly bool _buffered;
+ readonly object _syncRoot = new();
+ readonly WriteCountingStream? _countingStreamWrapper;
+
+ /// Construct a .
+ /// Path to the file.
+ /// Formatter used to convert log events to text.
+ /// 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.
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Indicates if flushing to the output file can be buffered or not. The default
+ /// is false.
+ /// Configuration object allowing method chaining.
+ /// This constructor preserves compatibility with early versions of the public API. New code should not depend on this type.
+ /// When is null
+ /// When is null
or less than 0
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ [Obsolete("This type and constructor will be removed from the public API in a future version; use `WriteTo.File()` instead.")]
+ public FileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBytes, Encoding? encoding = null, bool buffered = false)
+ : this(path, textFormatter, fileSizeLimitBytes, encoding, buffered, null)
{
- readonly TextWriter _output;
- readonly FileStream _underlyingStream;
- readonly ITextFormatter _textFormatter;
- readonly long? _fileSizeLimitBytes;
- readonly bool _buffered;
- readonly object _syncRoot = new object();
- readonly WriteCountingStream? _countingStreamWrapper;
-
- /// Construct a .
- /// Path to the file.
- /// Formatter used to convert log events to text.
- /// 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.
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Indicates if flushing to the output file can be buffered or not. The default
- /// is false.
- /// Configuration object allowing method chaining.
- /// This constructor preserves compatibility with early versions of the public API. New code should not depend on this type.
- /// When is null
- /// When is null
or less than 0
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- [Obsolete("This type and constructor will be removed from the public API in a future version; use `WriteTo.File()` instead.")]
- public FileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBytes, Encoding? encoding = null, bool buffered = false)
- : this(path, textFormatter, fileSizeLimitBytes, encoding, buffered, null)
- {
- }
+ }
- // This overload should be used internally; the overload above maintains compatibility with the earlier public API.
- internal FileSink(
- string path,
- ITextFormatter textFormatter,
- long? fileSizeLimitBytes,
- Encoding? encoding,
- bool buffered,
- FileLifecycleHooks? hooks)
+ // This overload should be used internally; the overload above maintains compatibility with the earlier public API.
+ internal FileSink(
+ string path,
+ ITextFormatter textFormatter,
+ long? fileSizeLimitBytes,
+ Encoding? encoding,
+ bool buffered,
+ FileLifecycleHooks? hooks)
+ {
+ if (path == null) throw new ArgumentNullException(nameof(path));
+ if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 1) throw new ArgumentException("Invalid value provided; file size limit must be at least 1 byte, or null.");
+ _textFormatter = textFormatter ?? throw new ArgumentNullException(nameof(textFormatter));
+ _fileSizeLimitBytes = fileSizeLimitBytes;
+ _buffered = buffered;
+
+ var directory = Path.GetDirectoryName(path);
+ if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
{
- if (path == null) throw new ArgumentNullException(nameof(path));
- if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 1) throw new ArgumentException("Invalid value provided; file size limit must be at least 1 byte, or null.");
- _textFormatter = textFormatter ?? throw new ArgumentNullException(nameof(textFormatter));
- _fileSizeLimitBytes = fileSizeLimitBytes;
- _buffered = buffered;
-
- var directory = Path.GetDirectoryName(path);
- if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
- {
- Directory.CreateDirectory(directory);
- }
+ Directory.CreateDirectory(directory);
+ }
- Stream outputStream = _underlyingStream = System.IO.File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
- outputStream.Seek(0, SeekOrigin.End);
+ Stream outputStream = _underlyingStream = System.IO.File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
+ outputStream.Seek(0, SeekOrigin.End);
- if (_fileSizeLimitBytes != null)
- {
- outputStream = _countingStreamWrapper = new WriteCountingStream(_underlyingStream);
- }
-
- // Parameter reassignment.
- encoding = encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
+ if (_fileSizeLimitBytes != null)
+ {
+ outputStream = _countingStreamWrapper = new WriteCountingStream(_underlyingStream);
+ }
- if (hooks != null)
- {
- outputStream = hooks.OnFileOpened(path, outputStream, encoding) ??
- throw new InvalidOperationException($"The file lifecycle hook `{nameof(FileLifecycleHooks.OnFileOpened)}(...)` returned `null`.");
- }
+ // Parameter reassignment.
+ encoding ??= new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
- _output = new StreamWriter(outputStream, encoding);
+ if (hooks != null)
+ {
+ outputStream = hooks.OnFileOpened(path, outputStream, encoding) ??
+ throw new InvalidOperationException($"The file lifecycle hook `{nameof(FileLifecycleHooks.OnFileOpened)}(...)` returned `null`.");
}
- bool IFileSink.EmitOrOverflow(LogEvent logEvent)
+ _output = new StreamWriter(outputStream, encoding);
+ }
+
+ bool IFileSink.EmitOrOverflow(LogEvent logEvent)
+ {
+ if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
+ lock (_syncRoot)
{
- if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
- lock (_syncRoot)
+ if (_fileSizeLimitBytes != null)
{
- if (_fileSizeLimitBytes != null)
- {
- if (_countingStreamWrapper!.CountedLength >= _fileSizeLimitBytes.Value)
- return false;
- }
+ if (_countingStreamWrapper!.CountedLength >= _fileSizeLimitBytes.Value)
+ return false;
+ }
- _textFormatter.Format(logEvent, _output);
- if (!_buffered)
- _output.Flush();
+ _textFormatter.Format(logEvent, _output);
+ if (!_buffered)
+ _output.Flush();
- return true;
- }
+ return true;
}
+ }
- ///
- /// Emit the provided log event to the sink.
- ///
- /// The log event to write.
- /// When is null
- public void Emit(LogEvent logEvent)
- {
- ((IFileSink) this).EmitOrOverflow(logEvent);
- }
+ ///
+ /// Emit the provided log event to the sink.
+ ///
+ /// The log event to write.
+ /// When is null
+ public void Emit(LogEvent logEvent)
+ {
+ ((IFileSink) this).EmitOrOverflow(logEvent);
+ }
- ///
- public void Dispose()
+ ///
+ public void Dispose()
+ {
+ lock (_syncRoot)
{
- lock (_syncRoot)
- {
- _output.Dispose();
- }
+ _output.Dispose();
}
+ }
- ///
- public void FlushToDisk()
+ ///
+ public void FlushToDisk()
+ {
+ lock (_syncRoot)
{
- lock (_syncRoot)
- {
- _output.Flush();
- _underlyingStream.Flush(true);
- }
+ _output.Flush();
+ _underlyingStream.Flush(true);
}
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/IFileSink.cs b/src/Serilog.Sinks.File/Sinks/File/IFileSink.cs
index 89268ab..f1e2d7e 100644
--- a/src/Serilog.Sinks.File/Sinks/File/IFileSink.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/IFileSink.cs
@@ -15,15 +15,14 @@
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+///
+/// Exists only for the convenience of , which
+/// switches implementations based on sharing. Would refactor, but preserving
+/// backwards compatibility.
+///
+interface IFileSink : ILogEventSink, IFlushableFileSink
{
- ///
- /// Exists only for the convenience of , which
- /// switches implementations based on sharing. Would refactor, but preserving
- /// backwards compatibility.
- ///
- interface IFileSink : ILogEventSink, IFlushableFileSink
- {
- bool EmitOrOverflow(LogEvent logEvent);
- }
+ bool EmitOrOverflow(LogEvent logEvent);
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs b/src/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs
index 75d6e52..ad9e407 100644
--- a/src/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs
@@ -12,16 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+///
+/// Supported by (file-based) sinks that can be explicitly flushed.
+///
+public interface IFlushableFileSink
{
///
- /// Supported by (file-based) sinks that can be explicitly flushed.
+ /// Flush buffered contents to disk.
///
- public interface IFlushableFileSink
- {
- ///
- /// Flush buffered contents to disk.
- ///
- void FlushToDisk();
- }
+ void FlushToDisk();
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/IOErrors.cs b/src/Serilog.Sinks.File/Sinks/File/IOErrors.cs
index 36fe8bc..faa121c 100644
--- a/src/Serilog.Sinks.File/Sinks/File/IOErrors.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/IOErrors.cs
@@ -12,20 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System.IO;
+namespace Serilog.Sinks.File;
-namespace Serilog.Sinks.File
+static class IOErrors
{
- static class IOErrors
+ public static bool IsLockedFile(IOException ex)
{
- public static bool IsLockedFile(IOException ex)
- {
#if HRESULTS
- var errorCode = System.Runtime.InteropServices.Marshal.GetHRForException(ex) & ((1 << 16) - 1);
- return errorCode == 32 || errorCode == 33;
+ var errorCode = System.Runtime.InteropServices.Marshal.GetHRForException(ex) & ((1 << 16) - 1);
+ return errorCode == 32 || errorCode == 33;
#else
- return true;
+ return true;
#endif
- }
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/NullSink.cs b/src/Serilog.Sinks.File/Sinks/File/NullSink.cs
index 5e9bb2c..8992197 100644
--- a/src/Serilog.Sinks.File/Sinks/File/NullSink.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/NullSink.cs
@@ -15,16 +15,15 @@
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+///
+/// An instance of this sink may be substituted when an instance of the
+/// is unable to be constructed.
+///
+class NullSink : ILogEventSink
{
- ///
- /// An instance of this sink may be substituted when an instance of the
- /// is unable to be constructed.
- ///
- class NullSink : ILogEventSink
+ public void Emit(LogEvent logEvent)
{
- public void Emit(LogEvent logEvent)
- {
- }
}
}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.File/Sinks/File/PathRoller.cs b/src/Serilog.Sinks.File/Sinks/File/PathRoller.cs
index 79a6915..922682d 100644
--- a/src/Serilog.Sinks.File/Sinks/File/PathRoller.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/PathRoller.cs
@@ -12,106 +12,102 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.IO;
using System.Text.RegularExpressions;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+class PathRoller
{
- class PathRoller
- {
- const string PeriodMatchGroup = "period";
- const string SequenceNumberMatchGroup = "sequence";
+ const string PeriodMatchGroup = "period";
+ const string SequenceNumberMatchGroup = "sequence";
- readonly string _directory;
- readonly string _filenamePrefix;
- readonly string _filenameSuffix;
- readonly Regex _filenameMatcher;
+ readonly string _directory;
+ readonly string _filenamePrefix;
+ readonly string _filenameSuffix;
+ readonly Regex _filenameMatcher;
- readonly RollingInterval _interval;
- readonly string _periodFormat;
+ readonly RollingInterval _interval;
+ readonly string _periodFormat;
- public PathRoller(string path, RollingInterval 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) +
- "$",
- RegexOptions.Compiled);
-
- DirectorySearchPattern = $"{_filenamePrefix}*{_filenameSuffix}";
- }
+ public PathRoller(string path, RollingInterval 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) +
+ "$",
+ RegexOptions.Compiled);
+
+ DirectorySearchPattern = $"{_filenamePrefix}*{_filenameSuffix}";
+ }
- public string LogFileDirectory => _directory;
+ public string LogFileDirectory => _directory;
- public string DirectorySearchPattern { get; }
+ public string DirectorySearchPattern { get; }
- public void GetLogFilePath(DateTime date, int? sequenceNumber, out string path)
- {
- var currentCheckpoint = GetCurrentCheckpoint(date);
+ public void GetLogFilePath(DateTime date, int? sequenceNumber, out string path)
+ {
+ var currentCheckpoint = GetCurrentCheckpoint(date);
- var tok = currentCheckpoint?.ToString(_periodFormat, CultureInfo.InvariantCulture) ?? "";
+ var tok = currentCheckpoint?.ToString(_periodFormat, CultureInfo.InvariantCulture) ?? "";
- if (sequenceNumber != null)
- tok += "_" + sequenceNumber.Value.ToString("000", CultureInfo.InvariantCulture);
+ if (sequenceNumber != null)
+ tok += "_" + sequenceNumber.Value.ToString("000", CultureInfo.InvariantCulture);
- path = Path.Combine(_directory, _filenamePrefix + tok + _filenameSuffix);
- }
+ path = Path.Combine(_directory, _filenamePrefix + tok + _filenameSuffix);
+ }
- public IEnumerable SelectMatches(IEnumerable filenames)
+ public IEnumerable SelectMatches(IEnumerable filenames)
+ {
+ foreach (var filename in filenames)
{
- foreach (var filename in filenames)
- {
- var match = _filenameMatcher.Match(filename);
- if (!match.Success)
- continue;
+ var match = _filenameMatcher.Match(filename);
+ if (!match.Success)
+ continue;
- int? inc = null;
- var incGroup = match.Groups[SequenceNumberMatchGroup];
- if (incGroup.Captures.Count != 0)
- {
- var incPart = incGroup.Captures[0].Value.Substring(1);
- inc = int.Parse(incPart, CultureInfo.InvariantCulture);
- }
+ int? inc = null;
+ var incGroup = match.Groups[SequenceNumberMatchGroup];
+ if (incGroup.Captures.Count != 0)
+ {
+ var incPart = incGroup.Captures[0].Value.Substring(1);
+ inc = int.Parse(incPart, CultureInfo.InvariantCulture);
+ }
- DateTime? period = null;
- var periodGroup = match.Groups[PeriodMatchGroup];
- if (periodGroup.Captures.Count != 0)
+ DateTime? period = null;
+ var periodGroup = match.Groups[PeriodMatchGroup];
+ if (periodGroup.Captures.Count != 0)
+ {
+ var dateTimePart = periodGroup.Captures[0].Value;
+ if (DateTime.TryParseExact(
+ dateTimePart,
+ _periodFormat,
+ CultureInfo.InvariantCulture,
+ DateTimeStyles.None,
+ out var dateTime))
{
- var dateTimePart = periodGroup.Captures[0].Value;
- if (DateTime.TryParseExact(
- dateTimePart,
- _periodFormat,
- CultureInfo.InvariantCulture,
- DateTimeStyles.None,
- out var dateTime))
- {
- period = dateTime;
- }
+ period = dateTime;
}
-
- yield return new RollingLogFile(filename, period, inc);
}
+
+ yield return new RollingLogFile(filename, period, inc);
}
+ }
- public DateTime? GetCurrentCheckpoint(DateTime instant) => _interval.GetCurrentCheckpoint(instant);
+ public DateTime? GetCurrentCheckpoint(DateTime instant) => _interval.GetCurrentCheckpoint(instant);
- public DateTime? GetNextCheckpoint(DateTime instant) => _interval.GetNextCheckpoint(instant);
- }
+ public DateTime? GetNextCheckpoint(DateTime instant) => _interval.GetNextCheckpoint(instant);
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs b/src/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs
index 1b931c9..c4272d9 100644
--- a/src/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs
@@ -12,75 +12,72 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.Threading;
using Serilog.Core;
using Serilog.Debugging;
using Serilog.Events;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+///
+/// A sink wrapper that periodically flushes the wrapped sink to disk.
+///
+[Obsolete("This type will be removed from the public API in a future version; use `WriteTo.File(flushToDiskInterval:)` instead.")]
+public class PeriodicFlushToDiskSink : ILogEventSink, IDisposable
{
+ readonly ILogEventSink _sink;
+ readonly Timer _timer;
+ int _flushRequired;
+
///
- /// A sink wrapper that periodically flushes the wrapped sink to disk.
+ /// Construct a that wraps
+ /// and flushes it at the specified .
///
- [Obsolete("This type will be removed from the public API in a future version; use `WriteTo.File(flushToDiskInterval:)` instead.")]
- public class PeriodicFlushToDiskSink : ILogEventSink, IDisposable
+ /// The sink to wrap.
+ /// The interval at which to flush the underlying sink.
+ /// When is null
+ public PeriodicFlushToDiskSink(ILogEventSink sink, TimeSpan flushInterval)
{
- readonly ILogEventSink _sink;
- readonly Timer _timer;
- int _flushRequired;
+ _sink = sink ?? throw new ArgumentNullException(nameof(sink));
- ///
- /// Construct a that wraps
- /// and flushes it at the specified .
- ///
- /// The sink to wrap.
- /// The interval at which to flush the underlying sink.
- /// When is null
- public PeriodicFlushToDiskSink(ILogEventSink sink, TimeSpan flushInterval)
+ if (sink is IFlushableFileSink flushable)
{
- _sink = sink ?? throw new ArgumentNullException(nameof(sink));
-
- if (sink is IFlushableFileSink flushable)
- {
- _timer = new Timer(_ => FlushToDisk(flushable), null, flushInterval, flushInterval);
- }
- else
- {
- _timer = new Timer(_ => { }, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
- SelfLog.WriteLine("{0} configured to flush {1}, but {2} not implemented", typeof(PeriodicFlushToDiskSink), sink, nameof(IFlushableFileSink));
- }
+ _timer = new Timer(_ => FlushToDisk(flushable), null, flushInterval, flushInterval);
}
-
- ///
- public void Emit(LogEvent logEvent)
+ else
{
- _sink.Emit(logEvent);
- Interlocked.Exchange(ref _flushRequired, 1);
+ _timer = new Timer(_ => { }, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
+ SelfLog.WriteLine("{0} configured to flush {1}, but {2} not implemented", typeof(PeriodicFlushToDiskSink), sink, nameof(IFlushableFileSink));
}
+ }
- ///
- public void Dispose()
- {
- _timer.Dispose();
- (_sink as IDisposable)?.Dispose();
- }
+ ///
+ public void Emit(LogEvent logEvent)
+ {
+ _sink.Emit(logEvent);
+ Interlocked.Exchange(ref _flushRequired, 1);
+ }
+
+ ///
+ public void Dispose()
+ {
+ _timer.Dispose();
+ (_sink as IDisposable)?.Dispose();
+ }
- void FlushToDisk(IFlushableFileSink flushable)
+ void FlushToDisk(IFlushableFileSink flushable)
+ {
+ try
{
- try
- {
- if (Interlocked.CompareExchange(ref _flushRequired, 0, 1) == 1)
- {
- // May throw ObjectDisposedException, since we're not trying to synchronize
- // anything here in the wrapper.
- flushable.FlushToDisk();
- }
- }
- catch (Exception ex)
+ if (Interlocked.CompareExchange(ref _flushRequired, 0, 1) == 1)
{
- SelfLog.WriteLine("{0} could not flush the underlying sink to disk: {1}", typeof(PeriodicFlushToDiskSink), ex);
+ // May throw ObjectDisposedException, since we're not trying to synchronize
+ // anything here in the wrapper.
+ flushable.FlushToDisk();
}
}
+ catch (Exception ex)
+ {
+ SelfLog.WriteLine("{0} could not flush the underlying sink to disk: {1}", typeof(PeriodicFlushToDiskSink), ex);
+ }
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs b/src/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs
index dccb802..373a97e 100644
--- a/src/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs
@@ -1,4 +1,4 @@
-// Copyright 2013-2017 Serilog Contributors
+// Copyright 2013-2017 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,248 +12,244 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.IO;
-using System.Linq;
using System.Text;
using Serilog.Core;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+sealed class RollingFileSink : ILogEventSink, IFlushableFileSink, IDisposable
{
- sealed class RollingFileSink : ILogEventSink, IFlushableFileSink, IDisposable
+ readonly PathRoller _roller;
+ readonly ITextFormatter _textFormatter;
+ readonly long? _fileSizeLimitBytes;
+ readonly int? _retainedFileCountLimit;
+ readonly TimeSpan? _retainedFileTimeLimit;
+ readonly Encoding? _encoding;
+ readonly bool _buffered;
+ readonly bool _shared;
+ readonly bool _rollOnFileSizeLimit;
+ readonly FileLifecycleHooks? _hooks;
+
+ readonly object _syncRoot = new();
+ bool _isDisposed;
+ DateTime? _nextCheckpoint;
+ IFileSink? _currentFile;
+ int? _currentFileSequence;
+
+ public RollingFileSink(string path,
+ ITextFormatter textFormatter,
+ long? fileSizeLimitBytes,
+ int? retainedFileCountLimit,
+ Encoding? encoding,
+ bool buffered,
+ bool shared,
+ RollingInterval rollingInterval,
+ bool rollOnFileSizeLimit,
+ FileLifecycleHooks? hooks,
+ TimeSpan? retainedFileTimeLimit)
{
- readonly PathRoller _roller;
- readonly ITextFormatter _textFormatter;
- readonly long? _fileSizeLimitBytes;
- readonly int? _retainedFileCountLimit;
- readonly TimeSpan? _retainedFileTimeLimit;
- readonly Encoding? _encoding;
- readonly bool _buffered;
- readonly bool _shared;
- readonly bool _rollOnFileSizeLimit;
- readonly FileLifecycleHooks? _hooks;
-
- readonly object _syncRoot = new object();
- bool _isDisposed;
- DateTime? _nextCheckpoint;
- IFileSink? _currentFile;
- int? _currentFileSequence;
-
- public RollingFileSink(string path,
- ITextFormatter textFormatter,
- long? fileSizeLimitBytes,
- int? retainedFileCountLimit,
- Encoding? encoding,
- bool buffered,
- bool shared,
- RollingInterval rollingInterval,
- bool rollOnFileSizeLimit,
- FileLifecycleHooks? hooks,
- TimeSpan? retainedFileTimeLimit)
- {
- if (path == null) throw new ArgumentNullException(nameof(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));
-
- _roller = new PathRoller(path, rollingInterval);
- _textFormatter = textFormatter;
- _fileSizeLimitBytes = fileSizeLimitBytes;
- _retainedFileCountLimit = retainedFileCountLimit;
- _retainedFileTimeLimit = retainedFileTimeLimit;
- _encoding = encoding;
- _buffered = buffered;
- _shared = shared;
- _rollOnFileSizeLimit = rollOnFileSizeLimit;
- _hooks = hooks;
- }
+ if (path == null) throw new ArgumentNullException(nameof(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));
+
+ _roller = new PathRoller(path, rollingInterval);
+ _textFormatter = textFormatter;
+ _fileSizeLimitBytes = fileSizeLimitBytes;
+ _retainedFileCountLimit = retainedFileCountLimit;
+ _retainedFileTimeLimit = retainedFileTimeLimit;
+ _encoding = encoding;
+ _buffered = buffered;
+ _shared = shared;
+ _rollOnFileSizeLimit = rollOnFileSizeLimit;
+ _hooks = hooks;
+ }
- public void Emit(LogEvent logEvent)
- {
- if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
+ public void Emit(LogEvent logEvent)
+ {
+ if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
- lock (_syncRoot)
- {
- if (_isDisposed) throw new ObjectDisposedException("The log file has been disposed.");
+ lock (_syncRoot)
+ {
+ if (_isDisposed) throw new ObjectDisposedException("The log file has been disposed.");
- var now = Clock.DateTimeNow;
- AlignCurrentFileTo(now);
+ var now = Clock.DateTimeNow;
+ AlignCurrentFileTo(now);
- while (_currentFile?.EmitOrOverflow(logEvent) == false && _rollOnFileSizeLimit)
- {
- AlignCurrentFileTo(now, nextSequence: true);
- }
+ while (_currentFile?.EmitOrOverflow(logEvent) == false && _rollOnFileSizeLimit)
+ {
+ AlignCurrentFileTo(now, nextSequence: true);
}
}
+ }
- void AlignCurrentFileTo(DateTime now, bool nextSequence = false)
+ void AlignCurrentFileTo(DateTime now, bool nextSequence = false)
+ {
+ if (!_nextCheckpoint.HasValue)
+ {
+ OpenFile(now);
+ }
+ else if (nextSequence || now >= _nextCheckpoint.Value)
{
- if (!_nextCheckpoint.HasValue)
+ int? minSequence = null;
+ if (nextSequence)
{
- OpenFile(now);
+ if (_currentFileSequence == null)
+ minSequence = 1;
+ else
+ minSequence = _currentFileSequence.Value + 1;
}
- else if (nextSequence || now >= _nextCheckpoint.Value)
- {
- int? minSequence = null;
- if (nextSequence)
- {
- if (_currentFileSequence == null)
- minSequence = 1;
- else
- minSequence = _currentFileSequence.Value + 1;
- }
- CloseFile();
- OpenFile(now, minSequence);
- }
+ CloseFile();
+ OpenFile(now, minSequence);
}
+ }
- void OpenFile(DateTime now, int? minSequence = null)
- {
- var currentCheckpoint = _roller.GetCurrentCheckpoint(now);
+ void OpenFile(DateTime now, int? minSequence = null)
+ {
+ var currentCheckpoint = _roller.GetCurrentCheckpoint(now);
- // We only try periodically because repeated failures
- // to open log files REALLY slow an app down.
- _nextCheckpoint = _roller.GetNextCheckpoint(now) ?? now.AddMinutes(30);
+ // We only try periodically because repeated failures
+ // to open log files REALLY slow an app down.
+ _nextCheckpoint = _roller.GetNextCheckpoint(now) ?? now.AddMinutes(30);
- var existingFiles = Enumerable.Empty();
- try
+ var existingFiles = Enumerable.Empty();
+ try
+ {
+ if (Directory.Exists(_roller.LogFileDirectory))
{
- if (Directory.Exists(_roller.LogFileDirectory))
- {
- existingFiles = Directory.GetFiles(_roller.LogFileDirectory, _roller.DirectorySearchPattern)
- .Select(f => Path.GetFileName(f));
- }
+ existingFiles = Directory.GetFiles(_roller.LogFileDirectory, _roller.DirectorySearchPattern)
+ .Select(f => Path.GetFileName(f));
}
- catch (DirectoryNotFoundException) { }
+ }
+ catch (DirectoryNotFoundException) { }
- var latestForThisCheckpoint = _roller
- .SelectMatches(existingFiles)
- .Where(m => m.DateTime == currentCheckpoint)
- .OrderByDescending(m => m.SequenceNumber)
- .FirstOrDefault();
+ var latestForThisCheckpoint = _roller
+ .SelectMatches(existingFiles)
+ .Where(m => m.DateTime == currentCheckpoint)
+ .OrderByDescending(m => m.SequenceNumber)
+ .FirstOrDefault();
- var sequence = latestForThisCheckpoint?.SequenceNumber;
- if (minSequence != null)
- {
- if (sequence == null || sequence.Value < minSequence.Value)
- sequence = minSequence;
- }
+ var sequence = latestForThisCheckpoint?.SequenceNumber;
+ if (minSequence != null)
+ {
+ if (sequence == null || sequence.Value < minSequence.Value)
+ sequence = minSequence;
+ }
- const int maxAttempts = 3;
- for (var attempt = 0; attempt < maxAttempts; attempt++)
- {
- _roller.GetLogFilePath(now, sequence, out var path);
+ const int maxAttempts = 3;
+ for (var attempt = 0; attempt < maxAttempts; attempt++)
+ {
+ _roller.GetLogFilePath(now, sequence, out var path);
- try
- {
- _currentFile = _shared ?
+ try
+ {
+ _currentFile = _shared ?
#pragma warning disable 618
- (IFileSink)new SharedFileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding) :
+ (IFileSink)new SharedFileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding) :
#pragma warning restore 618
- new FileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding, _buffered, _hooks);
+ new FileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding, _buffered, _hooks);
- _currentFileSequence = sequence;
- }
- catch (IOException ex)
+ _currentFileSequence = sequence;
+ }
+ catch (IOException ex)
+ {
+ if (IOErrors.IsLockedFile(ex))
{
- if (IOErrors.IsLockedFile(ex))
- {
- SelfLog.WriteLine("File target {0} was locked, attempting to open next in sequence (attempt {1})", path, attempt + 1);
- sequence = (sequence ?? 0) + 1;
- continue;
- }
-
- throw;
+ SelfLog.WriteLine("File target {0} was locked, attempting to open next in sequence (attempt {1})", path, attempt + 1);
+ sequence = (sequence ?? 0) + 1;
+ continue;
}
- ApplyRetentionPolicy(path, now);
- return;
+ throw;
}
+
+ ApplyRetentionPolicy(path, now);
+ return;
}
+ }
- void ApplyRetentionPolicy(string currentFilePath, DateTime now)
- {
- if (_retainedFileCountLimit == null && _retainedFileTimeLimit == null) return;
+ void ApplyRetentionPolicy(string currentFilePath, DateTime now)
+ {
+ if (_retainedFileCountLimit == null && _retainedFileTimeLimit == null) return;
- var currentFileName = Path.GetFileName(currentFilePath);
+ var currentFileName = Path.GetFileName(currentFilePath);
- // We consider the current file to exist, even if nothing's been written yet,
- // because files are only opened on response to an event being processed.
- var potentialMatches = Directory.GetFiles(_roller.LogFileDirectory, _roller.DirectorySearchPattern)
- .Select(f => Path.GetFileName(f))
- .Union(new[] { currentFileName });
+ // We consider the current file to exist, even if nothing's been written yet,
+ // because files are only opened on response to an event being processed.
+ var potentialMatches = Directory.GetFiles(_roller.LogFileDirectory, _roller.DirectorySearchPattern)
+ .Select(f => Path.GetFileName(f))
+ .Union(new[] { currentFileName });
- var newestFirst = _roller
- .SelectMatches(potentialMatches)
- .OrderByDescending(m => m.DateTime)
- .ThenByDescending(m => m.SequenceNumber);
+ var newestFirst = _roller
+ .SelectMatches(potentialMatches)
+ .OrderByDescending(m => m.DateTime)
+ .ThenByDescending(m => m.SequenceNumber);
- var toRemove = newestFirst
- .Where(n => StringComparer.OrdinalIgnoreCase.Compare(currentFileName, n.Filename) != 0)
- .SkipWhile((f, i) => ShouldRetainFile(f, i, now))
- .Select(x => x.Filename)
- .ToList();
+ var toRemove = newestFirst
+ .Where(n => StringComparer.OrdinalIgnoreCase.Compare(currentFileName, n.Filename) != 0)
+ .SkipWhile((f, i) => ShouldRetainFile(f, i, now))
+ .Select(x => x.Filename)
+ .ToList();
- foreach (var obsolete in toRemove)
+ foreach (var obsolete in toRemove)
+ {
+ var fullPath = Path.Combine(_roller.LogFileDirectory, obsolete);
+ try
{
- var fullPath = Path.Combine(_roller.LogFileDirectory, obsolete);
- try
- {
- _hooks?.OnFileDeleting(fullPath);
- System.IO.File.Delete(fullPath);
- }
- catch (Exception ex)
- {
- SelfLog.WriteLine("Error {0} while processing obsolete log file {1}", ex, fullPath);
- }
+ _hooks?.OnFileDeleting(fullPath);
+ System.IO.File.Delete(fullPath);
}
- }
-
- bool ShouldRetainFile(RollingLogFile file, int index, DateTime now)
- {
- if (_retainedFileCountLimit.HasValue && index >= _retainedFileCountLimit.Value - 1)
- return false;
-
- if (_retainedFileTimeLimit.HasValue && file.DateTime.HasValue &&
- file.DateTime.Value < now.Subtract(_retainedFileTimeLimit.Value))
+ catch (Exception ex)
{
- return false;
+ SelfLog.WriteLine("Error {0} while processing obsolete log file {1}", ex, fullPath);
}
-
- return true;
}
+ }
- public void Dispose()
+ bool ShouldRetainFile(RollingLogFile file, int index, DateTime now)
+ {
+ if (_retainedFileCountLimit.HasValue && index >= _retainedFileCountLimit.Value - 1)
+ return false;
+
+ if (_retainedFileTimeLimit.HasValue && file.DateTime.HasValue &&
+ file.DateTime.Value < now.Subtract(_retainedFileTimeLimit.Value))
{
- lock (_syncRoot)
- {
- if (_currentFile == null) return;
- CloseFile();
- _isDisposed = true;
- }
+ return false;
}
- void CloseFile()
+ return true;
+ }
+
+ public void Dispose()
+ {
+ lock (_syncRoot)
{
- if (_currentFile != null)
- {
- (_currentFile as IDisposable)?.Dispose();
- _currentFile = null;
- }
+ if (_currentFile == null) return;
+ CloseFile();
+ _isDisposed = true;
+ }
+ }
- _nextCheckpoint = null;
+ void CloseFile()
+ {
+ if (_currentFile != null)
+ {
+ (_currentFile as IDisposable)?.Dispose();
+ _currentFile = null;
}
- public void FlushToDisk()
+ _nextCheckpoint = null;
+ }
+
+ public void FlushToDisk()
+ {
+ lock (_syncRoot)
{
- lock (_syncRoot)
- {
- _currentFile?.FlushToDisk();
- }
+ _currentFile?.FlushToDisk();
}
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs b/src/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs
index 2c9e2fd..98ffb42 100644
--- a/src/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs
@@ -12,75 +12,72 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
+namespace Serilog.Sinks.File;
-namespace Serilog.Sinks.File
+static class RollingIntervalExtensions
{
- static class RollingIntervalExtensions
+ public static string GetFormat(this RollingInterval interval)
{
- public static string GetFormat(this RollingInterval interval)
+ switch (interval)
{
- switch (interval)
- {
- case RollingInterval.Infinite:
- return "";
- case RollingInterval.Year:
- return "yyyy";
- case RollingInterval.Month:
- return "yyyyMM";
- case RollingInterval.Day:
- return "yyyyMMdd";
- case RollingInterval.Hour:
- return "yyyyMMddHH";
- case RollingInterval.Minute:
- return "yyyyMMddHHmm";
- default:
- throw new ArgumentException("Invalid rolling interval");
- }
+ case RollingInterval.Infinite:
+ return "";
+ case RollingInterval.Year:
+ return "yyyy";
+ case RollingInterval.Month:
+ return "yyyyMM";
+ case RollingInterval.Day:
+ return "yyyyMMdd";
+ case RollingInterval.Hour:
+ return "yyyyMMddHH";
+ case RollingInterval.Minute:
+ return "yyyyMMddHHmm";
+ default:
+ throw new ArgumentException("Invalid rolling interval");
}
+ }
- public static DateTime? GetCurrentCheckpoint(this RollingInterval interval, DateTime instant)
+ public static DateTime? GetCurrentCheckpoint(this RollingInterval interval, DateTime instant)
+ {
+ switch (interval)
{
- switch (interval)
- {
- case RollingInterval.Infinite:
- return null;
- case RollingInterval.Year:
- return new DateTime(instant.Year, 1, 1, 0, 0, 0, instant.Kind);
- case RollingInterval.Month:
- return new DateTime(instant.Year, instant.Month, 1, 0, 0, 0, instant.Kind);
- case RollingInterval.Day:
- return new DateTime(instant.Year, instant.Month, instant.Day, 0, 0, 0, instant.Kind);
- case RollingInterval.Hour:
- return new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, 0, 0, instant.Kind);
- case RollingInterval.Minute:
- return new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, instant.Minute, 0, instant.Kind);
- default:
- throw new ArgumentException("Invalid rolling interval");
- }
+ case RollingInterval.Infinite:
+ return null;
+ case RollingInterval.Year:
+ return new DateTime(instant.Year, 1, 1, 0, 0, 0, instant.Kind);
+ case RollingInterval.Month:
+ return new DateTime(instant.Year, instant.Month, 1, 0, 0, 0, instant.Kind);
+ case RollingInterval.Day:
+ return new DateTime(instant.Year, instant.Month, instant.Day, 0, 0, 0, instant.Kind);
+ case RollingInterval.Hour:
+ return new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, 0, 0, instant.Kind);
+ case RollingInterval.Minute:
+ return new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, instant.Minute, 0, instant.Kind);
+ default:
+ throw new ArgumentException("Invalid rolling interval");
}
+ }
- public static DateTime? GetNextCheckpoint(this RollingInterval interval, DateTime instant)
- {
- var current = GetCurrentCheckpoint(interval, instant);
- if (current == null)
- return null;
+ public static DateTime? GetNextCheckpoint(this RollingInterval interval, DateTime instant)
+ {
+ var current = GetCurrentCheckpoint(interval, instant);
+ if (current == null)
+ return null;
- switch (interval)
- {
- case RollingInterval.Year:
- return current.Value.AddYears(1);
- case RollingInterval.Month:
- return current.Value.AddMonths(1);
- case RollingInterval.Day:
- return current.Value.AddDays(1);
- case RollingInterval.Hour:
- return current.Value.AddHours(1);
- case RollingInterval.Minute:
- return current.Value.AddMinutes(1);
- default:
- throw new ArgumentException("Invalid rolling interval");
- }
+ switch (interval)
+ {
+ case RollingInterval.Year:
+ return current.Value.AddYears(1);
+ case RollingInterval.Month:
+ return current.Value.AddMonths(1);
+ case RollingInterval.Day:
+ return current.Value.AddDays(1);
+ case RollingInterval.Hour:
+ return current.Value.AddHours(1);
+ case RollingInterval.Minute:
+ return current.Value.AddMinutes(1);
+ default:
+ throw new ArgumentException("Invalid rolling interval");
}
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs b/src/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs
index be64c4e..6441627 100644
--- a/src/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs
@@ -11,24 +11,23 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-
-using System;
-namespace Serilog.Sinks.File
+
+namespace Serilog.Sinks.File;
+
+class RollingLogFile
{
- class RollingLogFile
+ public RollingLogFile(string filename, DateTime? dateTime, int? sequenceNumber)
{
- public RollingLogFile(string filename, DateTime? dateTime, int? sequenceNumber)
- {
- Filename = filename;
- DateTime = dateTime;
- SequenceNumber = sequenceNumber;
- }
+ Filename = filename;
+ DateTime = dateTime;
+ SequenceNumber = sequenceNumber;
+ }
- public string Filename { get; }
+ public string Filename { get; }
- public DateTime? DateTime { get; }
+ public DateTime? DateTime { get; }
+
+ public int? SequenceNumber { get; }
+}
- public int? SequenceNumber { get; }
- }
-}
diff --git a/src/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs b/src/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs
index b8a07db..0038c6b 100644
--- a/src/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs
@@ -1,4 +1,4 @@
-// Copyright 2013-2019 Serilog Contributors
+// Copyright 2013-2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,152 +22,151 @@
using System.Threading;
using Serilog.Debugging;
-namespace Serilog.Sinks.File
+namespace Serilog.Sinks.File;
+
+///
+/// Write log events to a disk file.
+///
+[Obsolete("This type will be removed from the public API in a future version; use `WriteTo.File(shared: true)` instead.")]
+public sealed class SharedFileSink : IFileSink, IDisposable
{
- ///
- /// Write log events to a disk file.
- ///
- [Obsolete("This type will be removed from the public API in a future version; use `WriteTo.File(shared: true)` instead.")]
- public sealed class SharedFileSink : IFileSink, IDisposable
+ readonly TextWriter _output;
+ readonly FileStream _underlyingStream;
+ readonly ITextFormatter _textFormatter;
+ readonly long? _fileSizeLimitBytes;
+ readonly object _syncRoot = new();
+
+ const string MutexNameSuffix = ".serilog";
+ const int MutexWaitTimeout = 10000;
+ readonly Mutex _mutex;
+
+ /// Construct a .
+ /// Path to the file.
+ /// Formatter used to convert log events to text.
+ /// 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.
+ /// Character encoding used to write the text file. The default is UTF-8 without BOM.
+ /// Configuration object allowing method chaining.
+ /// The file will be written using the UTF-8 character set.
+ /// When is null
+ /// When is null
+ ///
+ ///
+ ///
+ /// When is too long
+ /// The caller does not have the required permission to access the
+ /// Invalid
+ public SharedFileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBytes, Encoding? encoding = null)
{
- readonly TextWriter _output;
- readonly FileStream _underlyingStream;
- readonly ITextFormatter _textFormatter;
- readonly long? _fileSizeLimitBytes;
- readonly object _syncRoot = new object();
-
- const string MutexNameSuffix = ".serilog";
- const int MutexWaitTimeout = 10000;
- readonly Mutex _mutex;
-
- /// Construct a .
- /// Path to the file.
- /// Formatter used to convert log events to text.
- /// 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.
- /// Character encoding used to write the text file. The default is UTF-8 without BOM.
- /// Configuration object allowing method chaining.
- /// The file will be written using the UTF-8 character set.
- /// When is null
- /// When is null
- ///
- ///
- ///
- /// When is too long
- /// The caller does not have the required permission to access the
- /// Invalid
- public SharedFileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBytes, Encoding? encoding = null)
+ if (path == null) throw new ArgumentNullException(nameof(path));
+ if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 1)
+ throw new ArgumentException("Invalid value provided; file size limit must be at least 1 byte, or null.");
+ _textFormatter = textFormatter ?? throw new ArgumentNullException(nameof(textFormatter));
+ _fileSizeLimitBytes = fileSizeLimitBytes;
+
+ var directory = Path.GetDirectoryName(path);
+ if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
{
- if (path == null) throw new ArgumentNullException(nameof(path));
- if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 1)
- throw new ArgumentException("Invalid value provided; file size limit must be at least 1 byte, or null.");
- _textFormatter = textFormatter ?? throw new ArgumentNullException(nameof(textFormatter));
- _fileSizeLimitBytes = fileSizeLimitBytes;
-
- var directory = Path.GetDirectoryName(path);
- if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
- {
- Directory.CreateDirectory(directory);
- }
-
- var mutexName = Path.GetFullPath(path).Replace(Path.DirectorySeparatorChar, ':') + MutexNameSuffix;
- _mutex = new Mutex(false, mutexName);
- _underlyingStream = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
- _output = new StreamWriter(_underlyingStream, encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
+ Directory.CreateDirectory(directory);
}
- bool IFileSink.EmitOrOverflow(LogEvent logEvent)
+ var mutexName = Path.GetFullPath(path).Replace(Path.DirectorySeparatorChar, ':') + MutexNameSuffix;
+ _mutex = new Mutex(false, mutexName);
+ _underlyingStream = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
+ _output = new StreamWriter(_underlyingStream, encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
+ }
+
+ bool IFileSink.EmitOrOverflow(LogEvent logEvent)
+ {
+ if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
+
+ lock (_syncRoot)
{
- if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
+ if (!TryAcquireMutex())
+ return true; // We didn't overflow, but, roll-on-size should not be attempted
- lock (_syncRoot)
+ try
{
- if (!TryAcquireMutex())
- return true; // We didn't overflow, but, roll-on-size should not be attempted
-
- try
+ _underlyingStream.Seek(0, SeekOrigin.End);
+ if (_fileSizeLimitBytes != null)
{
- _underlyingStream.Seek(0, SeekOrigin.End);
- if (_fileSizeLimitBytes != null)
- {
- if (_underlyingStream.Length >= _fileSizeLimitBytes.Value)
- return false;
- }
-
- _textFormatter.Format(logEvent, _output);
- _output.Flush();
- _underlyingStream.Flush();
- return true;
- }
- finally
- {
- ReleaseMutex();
+ if (_underlyingStream.Length >= _fileSizeLimitBytes.Value)
+ return false;
}
+
+ _textFormatter.Format(logEvent, _output);
+ _output.Flush();
+ _underlyingStream.Flush();
+ return true;
+ }
+ finally
+ {
+ ReleaseMutex();
}
}
+ }
+
+ ///
+ /// Emit the provided log event to the sink.
+ ///
+ /// The log event to write.
+ /// When is null
+ public void Emit(LogEvent logEvent)
+ {
+ ((IFileSink)this).EmitOrOverflow(logEvent);
+ }
- ///
- /// Emit the provided log event to the sink.
- ///
- /// The log event to write.
- /// When is null
- public void Emit(LogEvent logEvent)
+ ///
+ public void Dispose()
+ {
+ lock (_syncRoot)
{
- ((IFileSink)this).EmitOrOverflow(logEvent);
+ _output.Dispose();
+ _mutex.Dispose();
}
+ }
- ///
- public void Dispose()
+ ///
+ public void FlushToDisk()
+ {
+ lock (_syncRoot)
{
- lock (_syncRoot)
+ if (!TryAcquireMutex())
+ return;
+
+ try
{
- _output.Dispose();
- _mutex.Dispose();
+ _underlyingStream.Flush(true);
}
- }
-
- ///
- public void FlushToDisk()
- {
- lock (_syncRoot)
+ finally
{
- if (!TryAcquireMutex())
- return;
-
- try
- {
- _underlyingStream.Flush(true);
- }
- finally
- {
- ReleaseMutex();
- }
+ ReleaseMutex();
}
}
+ }
- bool TryAcquireMutex()
+ bool TryAcquireMutex()
+ {
+ try
{
- try
- {
- if (!_mutex.WaitOne(MutexWaitTimeout))
- {
- SelfLog.WriteLine("Shared file mutex could not be acquired within {0} ms", MutexWaitTimeout);
- return false;
- }
- }
- catch (AbandonedMutexException)
+ if (!_mutex.WaitOne(MutexWaitTimeout))
{
- SelfLog.WriteLine("Inherited shared file mutex after abandonment by another process");
+ SelfLog.WriteLine("Shared file mutex could not be acquired within {0} ms", MutexWaitTimeout);
+ return false;
}
-
- return true;
}
-
- void ReleaseMutex()
+ catch (AbandonedMutexException)
{
- _mutex.ReleaseMutex();
+ SelfLog.WriteLine("Inherited shared file mutex after abandonment by another process");
}
+
+ return true;
+ }
+
+ void ReleaseMutex()
+ {
+ _mutex.ReleaseMutex();
}
}
diff --git a/src/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs b/src/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs
index e247144..e95d80f 100644
--- a/src/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs
@@ -12,69 +12,65 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.IO;
+namespace Serilog.Sinks.File;
-namespace Serilog.Sinks.File
+sealed class WriteCountingStream : Stream
{
- sealed class WriteCountingStream : Stream
+ readonly Stream _stream;
+
+ public WriteCountingStream(Stream stream)
{
- readonly Stream _stream;
+ _stream = stream ?? throw new ArgumentNullException(nameof(stream));
+ CountedLength = stream.Length;
+ }
- public WriteCountingStream(Stream stream)
- {
- _stream = stream ?? throw new ArgumentNullException(nameof(stream));
- CountedLength = stream.Length;
- }
+ public long CountedLength { get; private set; }
- public long CountedLength { get; private set; }
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ _stream.Dispose();
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- _stream.Dispose();
+ base.Dispose(disposing);
+ }
- base.Dispose(disposing);
- }
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ _stream.Write(buffer, offset, count);
+ CountedLength += count;
+ }
- public override void Write(byte[] buffer, int offset, int count)
- {
- _stream.Write(buffer, offset, count);
- CountedLength += count;
- }
+ public override void Flush() => _stream.Flush();
+ public override bool CanRead => false;
+ public override bool CanSeek => _stream.CanSeek;
+ public override bool CanWrite => true;
+ public override long Length => _stream.Length;
- public override void Flush() => _stream.Flush();
- public override bool CanRead => false;
- public override bool CanSeek => _stream.CanSeek;
- public override bool CanWrite => true;
- public override long Length => _stream.Length;
+ public override long Position
+ {
+ get => _stream.Position;
+ set => throw new NotSupportedException();
+ }
- public override long Position
- {
- get => _stream.Position;
- set => throw new NotSupportedException();
- }
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new InvalidOperationException($"Seek operations are not available through `{nameof(WriteCountingStream)}`.");
+ }
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new InvalidOperationException($"Seek operations are not available through `{nameof(WriteCountingStream)}`.");
- }
+ public override void SetLength(long value)
+ {
+ _stream.SetLength(value);
- public override void SetLength(long value)
+ if (value < CountedLength)
{
- _stream.SetLength(value);
-
- if (value < CountedLength)
- {
- // File is now shorter and our position has changed to _stream.Length
- CountedLength = _stream.Length;
- }
+ // File is now shorter and our position has changed to _stream.Length
+ CountedLength = _stream.Length;
}
+ }
- public override int Read(byte[] buffer, int offset, int count)
- {
- throw new NotSupportedException();
- }
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException();
}
}
diff --git a/test/Serilog.Sinks.File.Tests/FileLoggerConfigurationExtensionsTests.cs b/test/Serilog.Sinks.File.Tests/FileLoggerConfigurationExtensionsTests.cs
index 3dde37a..9c32200 100644
--- a/test/Serilog.Sinks.File.Tests/FileLoggerConfigurationExtensionsTests.cs
+++ b/test/Serilog.Sinks.File.Tests/FileLoggerConfigurationExtensionsTests.cs
@@ -1,120 +1,116 @@
-using System;
-using System.Threading;
using Serilog.Sinks.File.Tests.Support;
using Serilog.Tests.Support;
using Xunit;
-using System.IO;
using System.Text;
-namespace Serilog.Sinks.File.Tests
+namespace Serilog.Sinks.File.Tests;
+
+public class FileLoggerConfigurationExtensionsTests
{
- public class FileLoggerConfigurationExtensionsTests
+ static readonly string InvalidPath = new(Path.GetInvalidPathChars());
+
+ [Fact]
+ public void WhenWritingCreationExceptionsAreSuppressed()
{
- static readonly string InvalidPath = new string(Path.GetInvalidPathChars());
+ new LoggerConfiguration()
+ .WriteTo.File(InvalidPath)
+ .CreateLogger();
+ }
- [Fact]
- public void WhenWritingCreationExceptionsAreSuppressed()
- {
+ [Fact]
+ public void WhenAuditingCreationExceptionsPropagate()
+ {
+ Assert.Throws(() =>
new LoggerConfiguration()
- .WriteTo.File(InvalidPath)
- .CreateLogger();
- }
+ .AuditTo.File(InvalidPath)
+ .CreateLogger());
+ }
- [Fact]
- public void WhenAuditingCreationExceptionsPropagate()
+ [Fact]
+ public void WhenWritingLoggingExceptionsAreSuppressed()
+ {
+ using (var tmp = TempFolder.ForCaller())
+ using (var log = new LoggerConfiguration()
+ .WriteTo.File(new ThrowingLogEventFormatter(), tmp.AllocateFilename())
+ .CreateLogger())
{
- Assert.Throws(() =>
- new LoggerConfiguration()
- .AuditTo.File(InvalidPath)
- .CreateLogger());
+ log.Information("Hello");
}
+ }
- [Fact]
- public void WhenWritingLoggingExceptionsAreSuppressed()
+ [Fact]
+ public void WhenAuditingLoggingExceptionsPropagate()
+ {
+ using (var tmp = TempFolder.ForCaller())
+ using (var log = new LoggerConfiguration()
+ .AuditTo.File(new ThrowingLogEventFormatter(), tmp.AllocateFilename())
+ .CreateLogger())
{
- using (var tmp = TempFolder.ForCaller())
- using (var log = new LoggerConfiguration()
- .WriteTo.File(new ThrowingLogEventFormatter(), tmp.AllocateFilename())
- .CreateLogger())
- {
- log.Information("Hello");
- }
+ var ex = Assert.Throws(() => log.Information("Hello"));
+ Assert.IsType(ex.GetBaseException());
}
+ }
- [Fact]
- public void WhenAuditingLoggingExceptionsPropagate()
+ [Fact]
+ public void WhenFlushingToDiskReportedFileSinkCanBeCreatedAndDisposed()
+ {
+ using (var tmp = TempFolder.ForCaller())
+ using (var log = new LoggerConfiguration()
+ .WriteTo.File(tmp.AllocateFilename(), flushToDiskInterval: TimeSpan.FromMilliseconds(500))
+ .CreateLogger())
{
- using (var tmp = TempFolder.ForCaller())
- using (var log = new LoggerConfiguration()
- .AuditTo.File(new ThrowingLogEventFormatter(), tmp.AllocateFilename())
- .CreateLogger())
- {
- var ex = Assert.Throws(() => log.Information("Hello"));
- Assert.IsType(ex.GetBaseException());
- }
+ log.Information("Hello");
+ Thread.Sleep(TimeSpan.FromSeconds(1));
}
+ }
- [Fact]
- public void WhenFlushingToDiskReportedFileSinkCanBeCreatedAndDisposed()
+ [Fact]
+ public void WhenFlushingToDiskReportedSharedFileSinkCanBeCreatedAndDisposed()
+ {
+ using (var tmp = TempFolder.ForCaller())
+ using (var log = new LoggerConfiguration()
+ .WriteTo.File(tmp.AllocateFilename(), shared: true, flushToDiskInterval: TimeSpan.FromMilliseconds(500))
+ .CreateLogger())
{
- using (var tmp = TempFolder.ForCaller())
- using (var log = new LoggerConfiguration()
- .WriteTo.File(tmp.AllocateFilename(), flushToDiskInterval: TimeSpan.FromMilliseconds(500))
- .CreateLogger())
- {
- log.Information("Hello");
- Thread.Sleep(TimeSpan.FromSeconds(1));
- }
+ log.Information("Hello");
+ Thread.Sleep(TimeSpan.FromSeconds(1));
}
+ }
- [Fact]
- public void WhenFlushingToDiskReportedSharedFileSinkCanBeCreatedAndDisposed()
- {
- using (var tmp = TempFolder.ForCaller())
- using (var log = new LoggerConfiguration()
- .WriteTo.File(tmp.AllocateFilename(), shared: true, flushToDiskInterval: TimeSpan.FromMilliseconds(500))
- .CreateLogger())
- {
- log.Information("Hello");
- Thread.Sleep(TimeSpan.FromSeconds(1));
- }
- }
+ [Fact]
+ public void BufferingIsNotAvailableWhenSharingEnabled()
+ {
+ Assert.Throws(() =>
+ new LoggerConfiguration()
+ .WriteTo.File("logs", buffered: true, shared: true));
+ }
- [Fact]
- public void BufferingIsNotAvailableWhenSharingEnabled()
- {
- Assert.Throws(() =>
- new LoggerConfiguration()
- .WriteTo.File("logs", buffered: true, shared: true));
- }
+ [Fact]
+ public void HooksAreNotAvailableWhenSharingEnabled()
+ {
+ Assert.Throws(() =>
+ new LoggerConfiguration()
+ .WriteTo.File("logs", shared: true, hooks: new GZipHooks()));
+ }
- [Fact]
- public void HooksAreNotAvailableWhenSharingEnabled()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void SpecifiedEncodingIsPropagated(bool shared)
+ {
+ using (var tmp = TempFolder.ForCaller())
{
- Assert.Throws(() =>
- new LoggerConfiguration()
- .WriteTo.File("logs", shared: true, hooks: new GZipHooks()));
- }
+ var filename = tmp.AllocateFilename("txt");
- [Theory]
- [InlineData(false)]
- [InlineData(true)]
- public void SpecifiedEncodingIsPropagated(bool shared)
- {
- using (var tmp = TempFolder.ForCaller())
+ using (var log = new LoggerConfiguration()
+ .WriteTo.File(filename, outputTemplate: "{Message}", encoding: Encoding.Unicode, shared: shared)
+ .CreateLogger())
{
- var filename = tmp.AllocateFilename("txt");
-
- using (var log = new LoggerConfiguration()
- .WriteTo.File(filename, outputTemplate: "{Message}", encoding: Encoding.Unicode, shared: shared)
- .CreateLogger())
- {
- log.Information("ten chars.");
- }
-
- // Don't forget the two-byte BOM :-)
- Assert.Equal(22, System.IO.File.ReadAllBytes(filename).Length);
+ log.Information("ten chars.");
}
+
+ // Don't forget the two-byte BOM :-)
+ Assert.Equal(22, System.IO.File.ReadAllBytes(filename).Length);
}
}
}
diff --git a/test/Serilog.Sinks.File.Tests/FileSinkTests.cs b/test/Serilog.Sinks.File.Tests/FileSinkTests.cs
index a33261f..af5c8f5 100644
--- a/test/Serilog.Sinks.File.Tests/FileSinkTests.cs
+++ b/test/Serilog.Sinks.File.Tests/FileSinkTests.cs
@@ -1,6 +1,4 @@
-using System.Collections.Generic;
-using System.IO;
-using System.IO.Compression;
+using System.IO.Compression;
using System.Text;
using Xunit;
using Serilog.Formatting.Json;
@@ -9,272 +7,271 @@
#pragma warning disable 618
-namespace Serilog.Sinks.File.Tests
+namespace Serilog.Sinks.File.Tests;
+
+public class FileSinkTests
{
- public class FileSinkTests
+ [Fact]
+ public void FileIsWrittenIfNonexistent()
{
- [Fact]
- public void FileIsWrittenIfNonexistent()
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var nonexistent = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent("Hello, world!");
+ var nonexistent = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent("Hello, world!");
- using (var sink = new FileSink(nonexistent, new JsonFormatter(), null))
- {
- sink.Emit(evt);
- }
-
- var lines = System.IO.File.ReadAllLines(nonexistent);
- Assert.Contains("Hello, world!", lines[0]);
+ using (var sink = new FileSink(nonexistent, new JsonFormatter(), null))
+ {
+ sink.Emit(evt);
}
+
+ var lines = System.IO.File.ReadAllLines(nonexistent);
+ Assert.Contains("Hello, world!", lines[0]);
}
+ }
- [Fact]
- public void FileIsAppendedToWhenAlreadyCreated()
+ [Fact]
+ public void FileIsAppendedToWhenAlreadyCreated()
+ {
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent("Hello, world!");
-
- using (var sink = new FileSink(path, new JsonFormatter(), null))
- {
- sink.Emit(evt);
- }
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent("Hello, world!");
- using (var sink = new FileSink(path, new JsonFormatter(), null))
- {
- sink.Emit(evt);
- }
+ using (var sink = new FileSink(path, new JsonFormatter(), null))
+ {
+ sink.Emit(evt);
+ }
- var lines = System.IO.File.ReadAllLines(path);
- Assert.Contains("Hello, world!", lines[0]);
- Assert.Contains("Hello, world!", lines[1]);
+ using (var sink = new FileSink(path, new JsonFormatter(), null))
+ {
+ sink.Emit(evt);
}
+
+ var lines = System.IO.File.ReadAllLines(path);
+ Assert.Contains("Hello, world!", lines[0]);
+ Assert.Contains("Hello, world!", lines[1]);
}
+ }
+
+ [Fact]
+ public void WhenLimitIsSpecifiedFileSizeIsRestricted()
+ {
+ const int maxBytes = 5000;
+ const int eventsToLimit = 10;
- [Fact]
- public void WhenLimitIsSpecifiedFileSizeIsRestricted()
+ using (var tmp = TempFolder.ForCaller())
{
- const int maxBytes = 5000;
- const int eventsToLimit = 10;
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
- using (var tmp = TempFolder.ForCaller())
+ using (var sink = new FileSink(path, new JsonFormatter(), maxBytes))
{
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
-
- using (var sink = new FileSink(path, new JsonFormatter(), maxBytes))
+ for (var i = 0; i < eventsToLimit * 2; i++)
{
- for (var i = 0; i < eventsToLimit * 2; i++)
- {
- sink.Emit(evt);
- }
+ sink.Emit(evt);
}
-
- var size = new FileInfo(path).Length;
- Assert.True(size > maxBytes);
- Assert.True(size < maxBytes * 2);
}
+
+ var size = new FileInfo(path).Length;
+ Assert.True(size > maxBytes);
+ Assert.True(size < maxBytes * 2);
}
+ }
+
+ [Fact]
+ public void WhenLimitIsNotSpecifiedFileSizeIsNotRestricted()
+ {
+ const int maxBytes = 5000;
+ const int eventsToLimit = 10;
- [Fact]
- public void WhenLimitIsNotSpecifiedFileSizeIsNotRestricted()
+ using (var tmp = TempFolder.ForCaller())
{
- const int maxBytes = 5000;
- const int eventsToLimit = 10;
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
- using (var tmp = TempFolder.ForCaller())
+ using (var sink = new FileSink(path, new JsonFormatter(), null))
{
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
-
- using (var sink = new FileSink(path, new JsonFormatter(), null))
+ for (var i = 0; i < eventsToLimit * 2; i++)
{
- for (var i = 0; i < eventsToLimit * 2; i++)
- {
- sink.Emit(evt);
- }
+ sink.Emit(evt);
}
-
- var size = new FileInfo(path).Length;
- Assert.True(size > maxBytes * 2);
}
+
+ var size = new FileInfo(path).Length;
+ Assert.True(size > maxBytes * 2);
}
+ }
- [Fact]
- public void WhenLimitIsSpecifiedAndEncodingHasPreambleDataIsCorrectlyAppendedToFileSink()
- {
- long? maxBytes = 5000;
- var encoding = Encoding.UTF8;
+ [Fact]
+ public void WhenLimitIsSpecifiedAndEncodingHasPreambleDataIsCorrectlyAppendedToFileSink()
+ {
+ long? maxBytes = 5000;
+ var encoding = Encoding.UTF8;
- Assert.True(encoding.GetPreamble().Length > 0);
- WriteTwoEventsAndCheckOutputFileLength(maxBytes, encoding);
- }
+ Assert.True(encoding.GetPreamble().Length > 0);
+ WriteTwoEventsAndCheckOutputFileLength(maxBytes, encoding);
+ }
- [Fact]
- public void WhenLimitIsNotSpecifiedAndEncodingHasPreambleDataIsCorrectlyAppendedToFileSink()
- {
- var encoding = Encoding.UTF8;
+ [Fact]
+ public void WhenLimitIsNotSpecifiedAndEncodingHasPreambleDataIsCorrectlyAppendedToFileSink()
+ {
+ var encoding = Encoding.UTF8;
- Assert.True(encoding.GetPreamble().Length > 0);
- WriteTwoEventsAndCheckOutputFileLength(null, encoding);
- }
+ Assert.True(encoding.GetPreamble().Length > 0);
+ WriteTwoEventsAndCheckOutputFileLength(null, encoding);
+ }
- [Fact]
- public void WhenLimitIsSpecifiedAndEncodingHasNoPreambleDataIsCorrectlyAppendedToFileSink()
- {
- long? maxBytes = 5000;
- var encoding = new UTF8Encoding(false);
+ [Fact]
+ public void WhenLimitIsSpecifiedAndEncodingHasNoPreambleDataIsCorrectlyAppendedToFileSink()
+ {
+ long? maxBytes = 5000;
+ var encoding = new UTF8Encoding(false);
- Assert.Empty(encoding.GetPreamble());
- WriteTwoEventsAndCheckOutputFileLength(maxBytes, encoding);
- }
+ Assert.Empty(encoding.GetPreamble());
+ WriteTwoEventsAndCheckOutputFileLength(maxBytes, encoding);
+ }
- [Fact]
- public void WhenLimitIsNotSpecifiedAndEncodingHasNoPreambleDataIsCorrectlyAppendedToFileSink()
- {
- var encoding = new UTF8Encoding(false);
+ [Fact]
+ public void WhenLimitIsNotSpecifiedAndEncodingHasNoPreambleDataIsCorrectlyAppendedToFileSink()
+ {
+ var encoding = new UTF8Encoding(false);
- Assert.Empty(encoding.GetPreamble());
- WriteTwoEventsAndCheckOutputFileLength(null, encoding);
- }
+ Assert.Empty(encoding.GetPreamble());
+ WriteTwoEventsAndCheckOutputFileLength(null, encoding);
+ }
+
+ [Fact]
+ public void OnOpenedLifecycleHookCanWrapUnderlyingStream()
+ {
+ var gzipWrapper = new GZipHooks();
- [Fact]
- public void OnOpenedLifecycleHookCanWrapUnderlyingStream()
+ using (var tmp = TempFolder.ForCaller())
{
- var gzipWrapper = new GZipHooks();
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent("Hello, world!");
- using (var tmp = TempFolder.ForCaller())
+ using (var sink = new FileSink(path, new JsonFormatter(), null, null, false, gzipWrapper))
{
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent("Hello, world!");
-
- using (var sink = new FileSink(path, new JsonFormatter(), null, null, false, gzipWrapper))
- {
- sink.Emit(evt);
- sink.Emit(evt);
- }
+ sink.Emit(evt);
+ sink.Emit(evt);
+ }
- // Ensure the data was written through the wrapping GZipStream, by decompressing and comparing against
- // what we wrote
- List lines;
- using (var textStream = new MemoryStream())
+ // Ensure the data was written through the wrapping GZipStream, by decompressing and comparing against
+ // what we wrote
+ List lines;
+ using (var textStream = new MemoryStream())
+ {
+ using (var fs = System.IO.File.OpenRead(path))
+ using (var decompressStream = new GZipStream(fs, CompressionMode.Decompress))
{
- using (var fs = System.IO.File.OpenRead(path))
- using (var decompressStream = new GZipStream(fs, CompressionMode.Decompress))
- {
- decompressStream.CopyTo(textStream);
- }
-
- textStream.Position = 0;
- lines = textStream.ReadAllLines();
+ decompressStream.CopyTo(textStream);
}
- Assert.Equal(2, lines.Count);
- Assert.Contains("Hello, world!", lines[0]);
+ textStream.Position = 0;
+ lines = textStream.ReadAllLines();
}
+
+ Assert.Equal(2, lines.Count);
+ Assert.Contains("Hello, world!", lines[0]);
}
+ }
- [Fact]
- public static void OnOpenedLifecycleHookCanWriteFileHeader()
+ [Fact]
+ public static void OnOpenedLifecycleHookCanWriteFileHeader()
+ {
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var headerWriter = new FileHeaderWriter("This is the file header");
+ var headerWriter = new FileHeaderWriter("This is the file header");
- var path = tmp.AllocateFilename("txt");
- using (new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, headerWriter))
- {
- // Open and write header
- }
+ var path = tmp.AllocateFilename("txt");
+ using (new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, headerWriter))
+ {
+ // Open and write header
+ }
- using (var sink = new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, headerWriter))
- {
- // Length check should prevent duplicate header here
- sink.Emit(Some.LogEvent());
- }
+ using (var sink = new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, headerWriter))
+ {
+ // Length check should prevent duplicate header here
+ sink.Emit(Some.LogEvent());
+ }
- var lines = System.IO.File.ReadAllLines(path);
+ var lines = System.IO.File.ReadAllLines(path);
- Assert.Equal(2, lines.Length);
- Assert.Equal(headerWriter.Header, lines[0]);
- Assert.Equal('{', lines[1][0]);
- }
+ Assert.Equal(2, lines.Length);
+ Assert.Equal(headerWriter.Header, lines[0]);
+ Assert.Equal('{', lines[1][0]);
}
+ }
- [Fact]
- public static void OnOpenedLifecycleHookCanCaptureFilePath()
+ [Fact]
+ public static void OnOpenedLifecycleHookCanCaptureFilePath()
+ {
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var capturePath = new CaptureFilePathHook();
-
- var path = tmp.AllocateFilename("txt");
- using (new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, capturePath))
- {
- // Open and capture the log file path
- }
+ var capturePath = new CaptureFilePathHook();
- Assert.Equal(path, capturePath.Path);
+ var path = tmp.AllocateFilename("txt");
+ using (new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, capturePath))
+ {
+ // Open and capture the log file path
}
+
+ Assert.Equal(path, capturePath.Path);
}
+ }
- [Fact]
- public static void OnOpenedLifecycleHookCanEmptyTheFileContents()
+ [Fact]
+ public static void OnOpenedLifecycleHookCanEmptyTheFileContents()
+ {
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var emptyFileHook = new TruncateFileHook();
+ var emptyFileHook = new TruncateFileHook();
- var path = tmp.AllocateFilename("txt");
- using (var sink = new FileSink(path, new JsonFormatter(), fileSizeLimitBytes: null, encoding: new UTF8Encoding(false), buffered: false))
- {
- sink.Emit(Some.LogEvent());
- }
+ var path = tmp.AllocateFilename("txt");
+ using (var sink = new FileSink(path, new JsonFormatter(), fileSizeLimitBytes: null, encoding: new UTF8Encoding(false), buffered: false))
+ {
+ sink.Emit(Some.LogEvent());
+ }
- using (var sink = new FileSink(path, new JsonFormatter(), fileSizeLimitBytes: null, encoding: new UTF8Encoding(false), buffered: false, hooks: emptyFileHook))
- {
- // Hook will clear the contents of the file before emitting the log events
- sink.Emit(Some.LogEvent());
- }
+ using (var sink = new FileSink(path, new JsonFormatter(), fileSizeLimitBytes: null, encoding: new UTF8Encoding(false), buffered: false, hooks: emptyFileHook))
+ {
+ // Hook will clear the contents of the file before emitting the log events
+ sink.Emit(Some.LogEvent());
+ }
- var lines = System.IO.File.ReadAllLines(path);
+ var lines = System.IO.File.ReadAllLines(path);
- Assert.Single(lines);
- Assert.Equal('{', lines[0][0]);
- }
+ Assert.Single(lines);
+ Assert.Equal('{', lines[0][0]);
}
+ }
- static void WriteTwoEventsAndCheckOutputFileLength(long? maxBytes, Encoding encoding)
+ static void WriteTwoEventsAndCheckOutputFileLength(long? maxBytes, Encoding encoding)
+ {
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent("Irrelevant as it will be replaced by the formatter");
- const string actualEventOutput = "x";
- var formatter = new FixedOutputFormatter(actualEventOutput);
- var eventOuputLength = encoding.GetByteCount(actualEventOutput);
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent("Irrelevant as it will be replaced by the formatter");
+ const string actualEventOutput = "x";
+ var formatter = new FixedOutputFormatter(actualEventOutput);
+ var eventOuputLength = encoding.GetByteCount(actualEventOutput);
- using (var sink = new FileSink(path, formatter, maxBytes, encoding: encoding))
- {
- sink.Emit(evt);
- }
- var size = new FileInfo(path).Length;
- Assert.Equal(encoding.GetPreamble().Length + eventOuputLength, size);
-
- //write a second event to the same file
- using (var sink = new FileSink(path, formatter, maxBytes, encoding: encoding))
- {
- sink.Emit(evt);
- }
+ using (var sink = new FileSink(path, formatter, maxBytes, encoding: encoding))
+ {
+ sink.Emit(evt);
+ }
+ var size = new FileInfo(path).Length;
+ Assert.Equal(encoding.GetPreamble().Length + eventOuputLength, size);
- size = new FileInfo(path).Length;
- Assert.Equal(encoding.GetPreamble().Length + eventOuputLength * 2, size);
+ //write a second event to the same file
+ using (var sink = new FileSink(path, formatter, maxBytes, encoding: encoding))
+ {
+ sink.Emit(evt);
}
+
+ size = new FileInfo(path).Length;
+ Assert.Equal(encoding.GetPreamble().Length + eventOuputLength * 2, size);
}
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Properties/launchSettings.json b/test/Serilog.Sinks.File.Tests/Properties/launchSettings.json
deleted file mode 100644
index 3ab0635..0000000
--- a/test/Serilog.Sinks.File.Tests/Properties/launchSettings.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "profiles": {
- "test": {
- "commandName": "test"
- },
- "test-dnxcore50": {
- "commandName": "test",
- "sdkVersion": "dnx-coreclr-win-x86.1.0.0-rc1-final"
- }
- }
-}
\ No newline at end of file
diff --git a/test/Serilog.Sinks.File.Tests/RollingFileSinkTests.cs b/test/Serilog.Sinks.File.Tests/RollingFileSinkTests.cs
index 9232bde..5739983 100644
--- a/test/Serilog.Sinks.File.Tests/RollingFileSinkTests.cs
+++ b/test/Serilog.Sinks.File.Tests/RollingFileSinkTests.cs
@@ -1,306 +1,295 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
using System.IO.Compression;
-using System.Linq;
using Xunit;
using Serilog.Events;
using Serilog.Sinks.File.Tests.Support;
using Serilog.Configuration;
using Serilog.Core;
-namespace Serilog.Sinks.File.Tests
+namespace Serilog.Sinks.File.Tests;
+
+public class RollingFileSinkTests
{
- public class RollingFileSinkTests
+ [Fact]
+ public void LogEventsAreEmittedToTheFileNamedAccordingToTheEventTimestamp()
{
- [Fact]
- public void LogEventsAreEmittedToTheFileNamedAccordingToTheEventTimestamp()
- {
- TestRollingEventSequence(Some.InformationEvent());
- }
+ TestRollingEventSequence(Some.InformationEvent());
+ }
- [Fact]
- public void EventsAreWrittenWhenSharingIsEnabled()
- {
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, shared: true, rollingInterval: RollingInterval.Day),
- new[] { Some.InformationEvent() });
- }
+ [Fact]
+ public void EventsAreWrittenWhenSharingIsEnabled()
+ {
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, shared: true, rollingInterval: RollingInterval.Day),
+ new[] { Some.InformationEvent() });
+ }
- [Fact]
- public void EventsAreWrittenWhenBufferingIsEnabled()
- {
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, buffered: true, rollingInterval: RollingInterval.Day),
- new[] { Some.InformationEvent() });
- }
+ [Fact]
+ public void EventsAreWrittenWhenBufferingIsEnabled()
+ {
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, buffered: true, rollingInterval: RollingInterval.Day),
+ new[] { Some.InformationEvent() });
+ }
- [Fact]
- public void EventsAreWrittenWhenDiskFlushingIsEnabled()
- {
- // Doesn't test flushing, but ensures we haven't broken basic logging
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, flushToDiskInterval: TimeSpan.FromMilliseconds(50), rollingInterval: RollingInterval.Day),
- new[] { Some.InformationEvent() });
- }
+ [Fact]
+ public void EventsAreWrittenWhenDiskFlushingIsEnabled()
+ {
+ // Doesn't test flushing, but ensures we haven't broken basic logging
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, flushToDiskInterval: TimeSpan.FromMilliseconds(50), rollingInterval: RollingInterval.Day),
+ new[] { Some.InformationEvent() });
+ }
- [Fact]
- public void WhenTheDateChangesTheCorrectFileIsWritten()
- {
- var e1 = Some.InformationEvent();
- var e2 = Some.InformationEvent(e1.Timestamp.AddDays(1));
- TestRollingEventSequence(e1, e2);
- }
+ [Fact]
+ public void WhenTheDateChangesTheCorrectFileIsWritten()
+ {
+ var e1 = Some.InformationEvent();
+ var e2 = Some.InformationEvent(e1.Timestamp.AddDays(1));
+ TestRollingEventSequence(e1, e2);
+ }
- [Fact]
- public void WhenRetentionCountIsSetOldFilesAreDeleted()
- {
- LogEvent e1 = Some.InformationEvent(),
- e2 = Some.InformationEvent(e1.Timestamp.AddDays(1)),
- e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
+ [Fact]
+ public void WhenRetentionCountIsSetOldFilesAreDeleted()
+ {
+ LogEvent e1 = Some.InformationEvent(),
+ e2 = Some.InformationEvent(e1.Timestamp.AddDays(1)),
+ e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
+
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, rollingInterval: RollingInterval.Day),
+ new[] {e1, e2, e3},
+ files =>
+ {
+ Assert.Equal(3, files.Count);
+ Assert.True(!System.IO.File.Exists(files[0]));
+ Assert.True(System.IO.File.Exists(files[1]));
+ Assert.True(System.IO.File.Exists(files[2]));
+ });
+ }
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, rollingInterval: RollingInterval.Day),
- new[] {e1, e2, e3},
- files =>
- {
- Assert.Equal(3, files.Count);
- Assert.True(!System.IO.File.Exists(files[0]));
- Assert.True(System.IO.File.Exists(files[1]));
- Assert.True(System.IO.File.Exists(files[2]));
- });
- }
+ [Fact]
+ public void WhenRetentionTimeIsSetOldFilesAreDeleted()
+ {
+ LogEvent e1 = Some.InformationEvent(DateTime.Today.AddDays(-5)),
+ e2 = Some.InformationEvent(e1.Timestamp.AddDays(2)),
+ e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
+
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, retainedFileTimeLimit: TimeSpan.FromDays(1), rollingInterval: RollingInterval.Day),
+ new[] {e1, e2, e3},
+ files =>
+ {
+ Assert.Equal(3, files.Count);
+ Assert.True(!System.IO.File.Exists(files[0]));
+ Assert.True(!System.IO.File.Exists(files[1]));
+ Assert.True(System.IO.File.Exists(files[2]));
+ });
+ }
- [Fact]
- public void WhenRetentionTimeIsSetOldFilesAreDeleted()
- {
- LogEvent e1 = Some.InformationEvent(DateTime.Today.AddDays(-5)),
- e2 = Some.InformationEvent(e1.Timestamp.AddDays(2)),
- e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
+ [Fact]
+ public void WhenRetentionCountAndTimeIsSetOldFilesAreDeletedByTime()
+ {
+ LogEvent e1 = Some.InformationEvent(DateTime.Today.AddDays(-5)),
+ e2 = Some.InformationEvent(e1.Timestamp.AddDays(2)),
+ e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
+
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, retainedFileTimeLimit: TimeSpan.FromDays(1), rollingInterval: RollingInterval.Day),
+ new[] {e1, e2, e3},
+ files =>
+ {
+ Assert.Equal(3, files.Count);
+ Assert.True(!System.IO.File.Exists(files[0]));
+ Assert.True(!System.IO.File.Exists(files[1]));
+ Assert.True(System.IO.File.Exists(files[2]));
+ });
+ }
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, retainedFileTimeLimit: TimeSpan.FromDays(1), rollingInterval: RollingInterval.Day),
- new[] {e1, e2, e3},
- files =>
- {
- Assert.Equal(3, files.Count);
- Assert.True(!System.IO.File.Exists(files[0]));
- Assert.True(!System.IO.File.Exists(files[1]));
- Assert.True(System.IO.File.Exists(files[2]));
- });
- }
+ [Fact]
+ public void WhenRetentionCountAndTimeIsSetOldFilesAreDeletedByCount()
+ {
+ LogEvent e1 = Some.InformationEvent(DateTime.Today.AddDays(-5)),
+ e2 = Some.InformationEvent(e1.Timestamp.AddDays(2)),
+ e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
+
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, retainedFileTimeLimit: TimeSpan.FromDays(10), rollingInterval: RollingInterval.Day),
+ new[] {e1, e2, e3},
+ files =>
+ {
+ Assert.Equal(3, files.Count);
+ Assert.True(!System.IO.File.Exists(files[0]));
+ Assert.True(System.IO.File.Exists(files[1]));
+ Assert.True(System.IO.File.Exists(files[2]));
+ });
+ }
- [Fact]
- public void WhenRetentionCountAndTimeIsSetOldFilesAreDeletedByTime()
- {
- LogEvent e1 = Some.InformationEvent(DateTime.Today.AddDays(-5)),
- e2 = Some.InformationEvent(e1.Timestamp.AddDays(2)),
+ [Fact]
+ public void WhenRetentionCountAndArchivingHookIsSetOldFilesAreCopiedAndOriginalDeleted()
+ {
+ const string archiveDirectory = "OldLogs";
+ LogEvent e1 = Some.InformationEvent(),
+ e2 = Some.InformationEvent(e1.Timestamp.AddDays(1)),
e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, retainedFileTimeLimit: TimeSpan.FromDays(1), rollingInterval: RollingInterval.Day),
- new[] {e1, e2, e3},
- files =>
- {
- Assert.Equal(3, files.Count);
- Assert.True(!System.IO.File.Exists(files[0]));
- Assert.True(!System.IO.File.Exists(files[1]));
- Assert.True(System.IO.File.Exists(files[2]));
- });
- }
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, rollingInterval: RollingInterval.Day, hooks: new ArchiveOldLogsHook(archiveDirectory)),
+ new[] {e1, e2, e3},
+ files =>
+ {
+ Assert.Equal(3, files.Count);
+ Assert.False(System.IO.File.Exists(files[0]));
+ Assert.True(System.IO.File.Exists(files[1]));
+ Assert.True(System.IO.File.Exists(files[2]));
+ Assert.True(System.IO.File.Exists(ArchiveOldLogsHook.AddTopDirectory(files[0], archiveDirectory)));
+ });
+ }
- [Fact]
- public void WhenRetentionCountAndTimeIsSetOldFilesAreDeletedByCount()
- {
- LogEvent e1 = Some.InformationEvent(DateTime.Today.AddDays(-5)),
- e2 = Some.InformationEvent(e1.Timestamp.AddDays(2)),
- e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
+ [Fact]
+ public void WhenSizeLimitIsBreachedNewFilesCreated()
+ {
+ var fileName = Some.String() + ".txt";
+ using var temp = new TempFolder();
+ using var log = new LoggerConfiguration()
+ .WriteTo.File(Path.Combine(temp.Path, fileName), rollOnFileSizeLimit: true, fileSizeLimitBytes: 1)
+ .CreateLogger();
+ LogEvent e1 = Some.InformationEvent(),
+ e2 = Some.InformationEvent(e1.Timestamp),
+ e3 = Some.InformationEvent(e1.Timestamp);
+
+ log.Write(e1); log.Write(e2); log.Write(e3);
+
+ var files = Directory.GetFiles(temp.Path)
+ .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
+ .ToArray();
+
+ Assert.Equal(3, files.Length);
+ Assert.True(files[0].EndsWith(fileName), files[0]);
+ Assert.True(files[1].EndsWith("_001.txt"), files[1]);
+ Assert.True(files[2].EndsWith("_002.txt"), files[2]);
+ }
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, retainedFileTimeLimit: TimeSpan.FromDays(10), rollingInterval: RollingInterval.Day),
- new[] {e1, e2, e3},
- files =>
- {
- Assert.Equal(3, files.Count);
- Assert.True(!System.IO.File.Exists(files[0]));
- Assert.True(System.IO.File.Exists(files[1]));
- Assert.True(System.IO.File.Exists(files[2]));
- });
- }
+ [Fact]
+ public void WhenStreamWrapperSpecifiedIsUsedForRolledFiles()
+ {
+ var gzipWrapper = new GZipHooks();
+ var fileName = Some.String() + ".txt";
- [Fact]
- public void WhenRetentionCountAndArchivingHookIsSetOldFilesAreCopiedAndOriginalDeleted()
+ using var temp = new TempFolder();
+ string[] files;
+ var logEvents = new[]
{
- const string archiveDirectory = "OldLogs";
- LogEvent e1 = Some.InformationEvent(),
- e2 = Some.InformationEvent(e1.Timestamp.AddDays(1)),
- e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
-
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, retainedFileCountLimit: 2, rollingInterval: RollingInterval.Day, hooks: new ArchiveOldLogsHook(archiveDirectory)),
- new[] {e1, e2, e3},
- files =>
- {
- Assert.Equal(3, files.Count);
- Assert.False(System.IO.File.Exists(files[0]));
- Assert.True(System.IO.File.Exists(files[1]));
- Assert.True(System.IO.File.Exists(files[2]));
- Assert.True(System.IO.File.Exists(ArchiveOldLogsHook.AddTopDirectory(files[0], archiveDirectory)));
- });
- }
-
- [Fact]
- public void WhenSizeLimitIsBreachedNewFilesCreated()
+ Some.InformationEvent(),
+ Some.InformationEvent(),
+ Some.InformationEvent()
+ };
+
+ using (var log = new LoggerConfiguration()
+ .WriteTo.File(Path.Combine(temp.Path, fileName), rollOnFileSizeLimit: true, fileSizeLimitBytes: 1, hooks: gzipWrapper)
+ .CreateLogger())
{
- var fileName = Some.String() + ".txt";
- using (var temp = new TempFolder())
- using (var log = new LoggerConfiguration()
- .WriteTo.File(Path.Combine(temp.Path, fileName), rollOnFileSizeLimit: true, fileSizeLimitBytes: 1)
- .CreateLogger())
- {
- LogEvent e1 = Some.InformationEvent(),
- e2 = Some.InformationEvent(e1.Timestamp),
- e3 = Some.InformationEvent(e1.Timestamp);
- log.Write(e1); log.Write(e2); log.Write(e3);
+ foreach (var logEvent in logEvents)
+ {
+ log.Write(logEvent);
+ }
- var files = Directory.GetFiles(temp.Path)
- .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
- .ToArray();
+ files = Directory.GetFiles(temp.Path)
+ .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
+ .ToArray();
- Assert.Equal(3, files.Length);
- Assert.True(files[0].EndsWith(fileName), files[0]);
- Assert.True(files[1].EndsWith("_001.txt"), files[1]);
- Assert.True(files[2].EndsWith("_002.txt"), files[2]);
- }
+ Assert.Equal(3, files.Length);
+ Assert.True(files[0].EndsWith(fileName), files[0]);
+ Assert.True(files[1].EndsWith("_001.txt"), files[1]);
+ Assert.True(files[2].EndsWith("_002.txt"), files[2]);
}
- [Fact]
- public void WhenStreamWrapperSpecifiedIsUsedForRolledFiles()
+ // Ensure the data was written through the wrapping GZipStream, by decompressing and comparing against
+ // what we wrote
+ for (var i = 0; i < files.Length; i++)
{
- var gzipWrapper = new GZipHooks();
- var fileName = Some.String() + ".txt";
-
- using (var temp = new TempFolder())
+ using var textStream = new MemoryStream();
+ using (var fs = System.IO.File.OpenRead(files[i]))
+ using (var decompressStream = new GZipStream(fs, CompressionMode.Decompress))
{
- string[] files;
- var logEvents = new[]
- {
- Some.InformationEvent(),
- Some.InformationEvent(),
- Some.InformationEvent()
- };
-
- using (var log = new LoggerConfiguration()
- .WriteTo.File(Path.Combine(temp.Path, fileName), rollOnFileSizeLimit: true, fileSizeLimitBytes: 1, hooks: gzipWrapper)
- .CreateLogger())
- {
-
- foreach (var logEvent in logEvents)
- {
- log.Write(logEvent);
- }
-
- files = Directory.GetFiles(temp.Path)
- .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
- .ToArray();
-
- Assert.Equal(3, files.Length);
- Assert.True(files[0].EndsWith(fileName), files[0]);
- Assert.True(files[1].EndsWith("_001.txt"), files[1]);
- Assert.True(files[2].EndsWith("_002.txt"), files[2]);
- }
-
- // Ensure the data was written through the wrapping GZipStream, by decompressing and comparing against
- // what we wrote
- for (var i = 0; i < files.Length; i++)
- {
- using (var textStream = new MemoryStream())
- {
- using (var fs = System.IO.File.OpenRead(files[i]))
- using (var decompressStream = new GZipStream(fs, CompressionMode.Decompress))
- {
- decompressStream.CopyTo(textStream);
- }
-
- textStream.Position = 0;
- var lines = textStream.ReadAllLines();
-
- Assert.Single(lines);
- Assert.EndsWith(logEvents[i].MessageTemplate.Text, lines[0]);
- }
- }
+ decompressStream.CopyTo(textStream);
}
+
+ textStream.Position = 0;
+ var lines = textStream.ReadAllLines();
+
+ Assert.Single(lines);
+ Assert.EndsWith(logEvents[i].MessageTemplate.Text, lines[0]);
}
+ }
- [Fact]
- public void IfTheLogFolderDoesNotExistItWillBeCreated()
- {
- var fileName = Some.String() + "-{Date}.txt";
- var temp = Some.TempFolderPath();
- var folder = Path.Combine(temp, Guid.NewGuid().ToString());
- var pathFormat = Path.Combine(folder, fileName);
+ [Fact]
+ public void IfTheLogFolderDoesNotExistItWillBeCreated()
+ {
+ var fileName = Some.String() + "-{Date}.txt";
+ var temp = Some.TempFolderPath();
+ var folder = Path.Combine(temp, Guid.NewGuid().ToString());
+ var pathFormat = Path.Combine(folder, fileName);
- Logger? log = null;
+ Logger? log = null;
- try
- {
- log = new LoggerConfiguration()
- .WriteTo.File(pathFormat, retainedFileCountLimit: 3, rollingInterval: RollingInterval.Day)
- .CreateLogger();
+ try
+ {
+ log = new LoggerConfiguration()
+ .WriteTo.File(pathFormat, retainedFileCountLimit: 3, rollingInterval: RollingInterval.Day)
+ .CreateLogger();
- log.Write(Some.InformationEvent());
+ log.Write(Some.InformationEvent());
- Assert.True(Directory.Exists(folder));
- }
- finally
- {
- log?.Dispose();
- Directory.Delete(temp, true);
- }
+ Assert.True(Directory.Exists(folder));
}
-
- static void TestRollingEventSequence(params LogEvent[] events)
+ finally
{
- TestRollingEventSequence(
- (pf, wt) => wt.File(pf, retainedFileCountLimit: null, rollingInterval: RollingInterval.Day),
- events);
+ log?.Dispose();
+ Directory.Delete(temp, true);
}
+ }
- static void TestRollingEventSequence(
- Action configureFile,
- IEnumerable events,
- Action>? verifyWritten = null)
- {
- var fileName = Some.String() + "-.txt";
- var folder = Some.TempFolderPath();
- var pathFormat = Path.Combine(folder, fileName);
+ static void TestRollingEventSequence(params LogEvent[] events)
+ {
+ TestRollingEventSequence(
+ (pf, wt) => wt.File(pf, retainedFileCountLimit: null, rollingInterval: RollingInterval.Day),
+ events);
+ }
+
+ static void TestRollingEventSequence(
+ Action configureFile,
+ IEnumerable events,
+ Action>? verifyWritten = null)
+ {
+ var fileName = Some.String() + "-.txt";
+ var folder = Some.TempFolderPath();
+ var pathFormat = Path.Combine(folder, fileName);
- var config = new LoggerConfiguration();
- configureFile(pathFormat, config.WriteTo);
- var log = config.CreateLogger();
+ var config = new LoggerConfiguration();
+ configureFile(pathFormat, config.WriteTo);
+ var log = config.CreateLogger();
- var verified = new List();
+ var verified = new List();
- try
+ try
+ {
+ foreach (var @event in events)
{
- foreach (var @event in events)
- {
- Clock.SetTestDateTimeNow(@event.Timestamp.DateTime);
- log.Write(@event);
+ Clock.SetTestDateTimeNow(@event.Timestamp.DateTime);
+ log.Write(@event);
- var expected = pathFormat.Replace(".txt", @event.Timestamp.ToString("yyyyMMdd") + ".txt");
- Assert.True(System.IO.File.Exists(expected));
+ var expected = pathFormat.Replace(".txt", @event.Timestamp.ToString("yyyyMMdd") + ".txt");
+ Assert.True(System.IO.File.Exists(expected));
- verified.Add(expected);
- }
- }
- finally
- {
- log.Dispose();
- verifyWritten?.Invoke(verified);
- Directory.Delete(folder, true);
+ verified.Add(expected);
}
}
+ finally
+ {
+ log.Dispose();
+ verifyWritten?.Invoke(verified);
+ Directory.Delete(folder, true);
+ }
}
}
diff --git a/test/Serilog.Sinks.File.Tests/RollingIntervalExtensionsTests.cs b/test/Serilog.Sinks.File.Tests/RollingIntervalExtensionsTests.cs
index 404d5b4..a7b307b 100644
--- a/test/Serilog.Sinks.File.Tests/RollingIntervalExtensionsTests.cs
+++ b/test/Serilog.Sinks.File.Tests/RollingIntervalExtensionsTests.cs
@@ -1,34 +1,32 @@
-using System;
-using Xunit;
+using Xunit;
-namespace Serilog.Sinks.File.Tests
+namespace Serilog.Sinks.File.Tests;
+
+public class RollingIntervalExtensionsTests
{
- public class RollingIntervalExtensionsTests
+ public static object?[][] IntervalInstantCurrentNextCheckpoint => new[]
{
- public static object?[][] IntervalInstantCurrentNextCheckpoint => new[]
- {
- new object?[]{ RollingInterval.Infinite, new DateTime(2018, 01, 01), null, null },
- new object?[]{ RollingInterval.Year, new DateTime(2018, 01, 01), new DateTime(2018, 01, 01), new DateTime(2019, 01, 01) },
- new object?[]{ RollingInterval.Year, new DateTime(2018, 06, 01), new DateTime(2018, 01, 01), new DateTime(2019, 01, 01) },
- new object?[]{ RollingInterval.Month, new DateTime(2018, 01, 01), new DateTime(2018, 01, 01), new DateTime(2018, 02, 01) },
- new object?[]{ RollingInterval.Month, new DateTime(2018, 01, 14), new DateTime(2018, 01, 01), new DateTime(2018, 02, 01) },
- new object?[]{ RollingInterval.Day, new DateTime(2018, 01, 01), new DateTime(2018, 01, 01), new DateTime(2018, 01, 02) },
- new object?[]{ RollingInterval.Day, new DateTime(2018, 01, 01, 12, 0, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 02) },
- new object?[]{ RollingInterval.Hour, new DateTime(2018, 01, 01, 0, 0, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 1, 0, 0) },
- new object?[]{ RollingInterval.Hour, new DateTime(2018, 01, 01, 0, 30, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 1, 0, 0) },
- new object?[]{ RollingInterval.Minute, new DateTime(2018, 01, 01, 0, 0, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 0, 1, 0) },
- new object?[]{ RollingInterval.Minute, new DateTime(2018, 01, 01, 0, 0, 30), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 0, 1, 0) }
- };
+ new object?[]{ RollingInterval.Infinite, new DateTime(2018, 01, 01), null, null },
+ new object?[]{ RollingInterval.Year, new DateTime(2018, 01, 01), new DateTime(2018, 01, 01), new DateTime(2019, 01, 01) },
+ new object?[]{ RollingInterval.Year, new DateTime(2018, 06, 01), new DateTime(2018, 01, 01), new DateTime(2019, 01, 01) },
+ new object?[]{ RollingInterval.Month, new DateTime(2018, 01, 01), new DateTime(2018, 01, 01), new DateTime(2018, 02, 01) },
+ new object?[]{ RollingInterval.Month, new DateTime(2018, 01, 14), new DateTime(2018, 01, 01), new DateTime(2018, 02, 01) },
+ new object?[]{ RollingInterval.Day, new DateTime(2018, 01, 01), new DateTime(2018, 01, 01), new DateTime(2018, 01, 02) },
+ new object?[]{ RollingInterval.Day, new DateTime(2018, 01, 01, 12, 0, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 02) },
+ new object?[]{ RollingInterval.Hour, new DateTime(2018, 01, 01, 0, 0, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 1, 0, 0) },
+ new object?[]{ RollingInterval.Hour, new DateTime(2018, 01, 01, 0, 30, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 1, 0, 0) },
+ new object?[]{ RollingInterval.Minute, new DateTime(2018, 01, 01, 0, 0, 0), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 0, 1, 0) },
+ new object?[]{ RollingInterval.Minute, new DateTime(2018, 01, 01, 0, 0, 30), new DateTime(2018, 01, 01), new DateTime(2018, 01, 01, 0, 1, 0) }
+ };
- [Theory]
- [MemberData(nameof(IntervalInstantCurrentNextCheckpoint))]
- public void NextIntervalTests(RollingInterval interval, DateTime instant, DateTime? currentCheckpoint, DateTime? nextCheckpoint)
- {
- var current = interval.GetCurrentCheckpoint(instant);
- Assert.Equal(currentCheckpoint, current);
+ [Theory]
+ [MemberData(nameof(IntervalInstantCurrentNextCheckpoint))]
+ public void NextIntervalTests(RollingInterval 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);
- }
+ var next = interval.GetNextCheckpoint(instant);
+ Assert.Equal(nextCheckpoint, next);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Serilog.Sinks.File.Tests.csproj b/test/Serilog.Sinks.File.Tests/Serilog.Sinks.File.Tests.csproj
index 9fd79c8..5d5af8c 100644
--- a/test/Serilog.Sinks.File.Tests/Serilog.Sinks.File.Tests.csproj
+++ b/test/Serilog.Sinks.File.Tests/Serilog.Sinks.File.Tests.csproj
@@ -1,15 +1,7 @@
-
+
-
net48;net6.0
- 8.0
- enable
- true
- Serilog.Sinks.File.Tests
- ../../assets/Serilog.snk
- true
- true
true
@@ -18,16 +10,12 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
+
diff --git a/test/Serilog.Sinks.File.Tests/SharedFileSinkTests.cs b/test/Serilog.Sinks.File.Tests/SharedFileSinkTests.cs
index 565be9b..ec90f25 100644
--- a/test/Serilog.Sinks.File.Tests/SharedFileSinkTests.cs
+++ b/test/Serilog.Sinks.File.Tests/SharedFileSinkTests.cs
@@ -1,103 +1,101 @@
-using System.IO;
-using Xunit;
+using Xunit;
using Serilog.Formatting.Json;
using Serilog.Sinks.File.Tests.Support;
#pragma warning disable 618
-namespace Serilog.Sinks.File.Tests
+namespace Serilog.Sinks.File.Tests;
+
+public class SharedFileSinkTests
{
- public class SharedFileSinkTests
+ [Fact]
+ public void FileIsWrittenIfNonexistent()
{
- [Fact]
- public void FileIsWrittenIfNonexistent()
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var nonexistent = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent("Hello, world!");
+ var nonexistent = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent("Hello, world!");
- using (var sink = new SharedFileSink(nonexistent, new JsonFormatter(), null))
- {
- sink.Emit(evt);
- }
-
- var lines = System.IO.File.ReadAllLines(nonexistent);
- Assert.Contains("Hello, world!", lines[0]);
+ using (var sink = new SharedFileSink(nonexistent, new JsonFormatter(), null))
+ {
+ sink.Emit(evt);
}
+
+ var lines = System.IO.File.ReadAllLines(nonexistent);
+ Assert.Contains("Hello, world!", lines[0]);
}
+ }
- [Fact]
- public void FileIsAppendedToWhenAlreadyCreated()
+ [Fact]
+ public void FileIsAppendedToWhenAlreadyCreated()
+ {
+ using (var tmp = TempFolder.ForCaller())
{
- using (var tmp = TempFolder.ForCaller())
- {
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent("Hello, world!");
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent("Hello, world!");
- using (var sink = new SharedFileSink(path, new JsonFormatter(), null))
- {
- sink.Emit(evt);
- }
-
- using (var sink = new SharedFileSink(path, new JsonFormatter(), null))
- {
- sink.Emit(evt);
- }
+ using (var sink = new SharedFileSink(path, new JsonFormatter(), null))
+ {
+ sink.Emit(evt);
+ }
- var lines = System.IO.File.ReadAllLines(path);
- Assert.Contains("Hello, world!", lines[0]);
- Assert.Contains("Hello, world!", lines[1]);
+ using (var sink = new SharedFileSink(path, new JsonFormatter(), null))
+ {
+ sink.Emit(evt);
}
+
+ var lines = System.IO.File.ReadAllLines(path);
+ Assert.Contains("Hello, world!", lines[0]);
+ Assert.Contains("Hello, world!", lines[1]);
}
+ }
- [Fact]
- public void WhenLimitIsSpecifiedFileSizeIsRestricted()
+ [Fact]
+ public void WhenLimitIsSpecifiedFileSizeIsRestricted()
+ {
+ const int maxBytes = 5000;
+ const int eventsToLimit = 10;
+
+ using (var tmp = TempFolder.ForCaller())
{
- const int maxBytes = 5000;
- const int eventsToLimit = 10;
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
- using (var tmp = TempFolder.ForCaller())
+ using (var sink = new SharedFileSink(path, new JsonFormatter(), maxBytes))
{
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
-
- using (var sink = new SharedFileSink(path, new JsonFormatter(), maxBytes))
+ for (var i = 0; i < eventsToLimit * 2; i++)
{
- for (var i = 0; i < eventsToLimit * 2; i++)
- {
- sink.Emit(evt);
- }
+ sink.Emit(evt);
}
-
- var size = new FileInfo(path).Length;
- Assert.True(size > maxBytes);
- Assert.True(size < maxBytes * 2);
}
+
+ var size = new FileInfo(path).Length;
+ Assert.True(size > maxBytes);
+ Assert.True(size < maxBytes * 2);
}
+ }
+
+ [Fact]
+ public void WhenLimitIsNotSpecifiedFileSizeIsNotRestricted()
+ {
+ const int maxBytes = 5000;
+ const int eventsToLimit = 10;
- [Fact]
- public void WhenLimitIsNotSpecifiedFileSizeIsNotRestricted()
+ using (var tmp = TempFolder.ForCaller())
{
- const int maxBytes = 5000;
- const int eventsToLimit = 10;
+ var path = tmp.AllocateFilename("txt");
+ var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
- using (var tmp = TempFolder.ForCaller())
+ using (var sink = new SharedFileSink(path, new JsonFormatter(), null))
{
- var path = tmp.AllocateFilename("txt");
- var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
-
- using (var sink = new SharedFileSink(path, new JsonFormatter(), null))
+ for (var i = 0; i < eventsToLimit * 2; i++)
{
- for (var i = 0; i < eventsToLimit * 2; i++)
- {
- sink.Emit(evt);
- }
+ sink.Emit(evt);
}
-
- var size = new FileInfo(path).Length;
- Assert.True(size > maxBytes * 2);
}
+
+ var size = new FileInfo(path).Length;
+ Assert.True(size > maxBytes * 2);
}
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/ArchiveOldLogsHook.cs b/test/Serilog.Sinks.File.Tests/Support/ArchiveOldLogsHook.cs
index 96dcb8c..566b5ba 100644
--- a/test/Serilog.Sinks.File.Tests/Support/ArchiveOldLogsHook.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/ArchiveOldLogsHook.cs
@@ -1,35 +1,30 @@
-using System;
-using System.IO;
-using System.Text;
+namespace Serilog.Sinks.File.Tests.Support;
-namespace Serilog.Sinks.File.Tests.Support
+internal class ArchiveOldLogsHook : FileLifecycleHooks
{
- internal class ArchiveOldLogsHook : FileLifecycleHooks
+ private readonly string _relativeArchiveDir;
+
+ public ArchiveOldLogsHook(string relativeArchiveDir)
{
- private readonly string _relativeArchiveDir;
+ _relativeArchiveDir = relativeArchiveDir;
+ }
- public ArchiveOldLogsHook(string relativeArchiveDir)
- {
- _relativeArchiveDir = relativeArchiveDir;
- }
+ public override void OnFileDeleting(string path)
+ {
+ base.OnFileDeleting(path);
+ var newFile = AddTopDirectory(path, _relativeArchiveDir, true);
+ System.IO.File.Copy(path, newFile, false);
+ }
- public override void OnFileDeleting(string path)
- {
- base.OnFileDeleting(path);
- var newFile = AddTopDirectory(path, _relativeArchiveDir, true);
- System.IO.File.Copy(path, newFile, false);
- }
+ public static string AddTopDirectory(string path, string directoryToAdd, bool createOnNonExist = false)
+ {
+ string file = Path.GetFileName(path);
+ string directory = Path.Combine(Path.GetDirectoryName(path) ?? throw new InvalidOperationException(), directoryToAdd);
- public static string AddTopDirectory(string path, string directoryToAdd, bool createOnNonExist = false)
+ if (createOnNonExist && !Directory.Exists(directory))
{
- string file = Path.GetFileName(path);
- string directory = Path.Combine(Path.GetDirectoryName(path) ?? throw new InvalidOperationException(), directoryToAdd);
-
- if (createOnNonExist && !Directory.Exists(directory))
- {
- Directory.CreateDirectory(directory);
- }
- return Path.Combine(directory, file);
+ Directory.CreateDirectory(directory);
}
+ return Path.Combine(directory, file);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/CaptureFilePathHook.cs b/test/Serilog.Sinks.File.Tests/Support/CaptureFilePathHook.cs
index 65857d1..14fa452 100644
--- a/test/Serilog.Sinks.File.Tests/Support/CaptureFilePathHook.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/CaptureFilePathHook.cs
@@ -1,20 +1,18 @@
-using System.IO;
-using System.Text;
+using System.Text;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+///
+///
+/// Demonstrates the use of , by capturing the log file path
+///
+class CaptureFilePathHook : FileLifecycleHooks
{
- ///
- ///
- /// Demonstrates the use of , by capturing the log file path
- ///
- class CaptureFilePathHook : FileLifecycleHooks
- {
- public string? Path { get; private set; }
+ public string? Path { get; private set; }
- public override Stream OnFileOpened(string path, Stream _, Encoding __)
- {
- Path = path;
- return base.OnFileOpened(path, _, __);
- }
+ public override Stream OnFileOpened(string path, Stream _, Encoding __)
+ {
+ Path = path;
+ return base.OnFileOpened(path, _, __);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/CollectingSink.cs b/test/Serilog.Sinks.File.Tests/Support/CollectingSink.cs
index 244ae5c..323aba8 100644
--- a/test/Serilog.Sinks.File.Tests/Support/CollectingSink.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/CollectingSink.cs
@@ -1,21 +1,18 @@
-using System.Collections.Generic;
-using System.Linq;
-using Serilog.Core;
+using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+class CollectingSink : ILogEventSink
{
- class CollectingSink : ILogEventSink
- {
- readonly List _events = new List();
+ readonly List _events = new();
- public List Events { get { return _events; } }
+ public List Events { get { return _events; } }
- public LogEvent SingleEvent { get { return _events.Single(); } }
-
- public void Emit(LogEvent logEvent)
- {
- _events.Add(logEvent);
- }
+ public LogEvent SingleEvent { get { return _events.Single(); } }
+
+ public void Emit(LogEvent logEvent)
+ {
+ _events.Add(logEvent);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/DelegateDisposable.cs b/test/Serilog.Sinks.File.Tests/Support/DelegateDisposable.cs
index 3ac9974..3386a4f 100644
--- a/test/Serilog.Sinks.File.Tests/Support/DelegateDisposable.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/DelegateDisposable.cs
@@ -1,24 +1,21 @@
-using System;
+namespace Serilog.Sinks.File.Tests.Support;
-namespace Serilog.Sinks.File.Tests.Support
+public class DelegateDisposable : IDisposable
{
- public class DelegateDisposable : IDisposable
- {
- private readonly Action _disposeAction;
- private bool _disposed;
+ private readonly Action _disposeAction;
+ private bool _disposed;
- public DelegateDisposable(Action disposeAction)
- {
- _disposeAction = disposeAction;
- }
+ public DelegateDisposable(Action disposeAction)
+ {
+ _disposeAction = disposeAction;
+ }
- public void Dispose()
- {
- if (_disposed)
- return;
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
- _disposeAction();
- _disposed = true;
- }
+ _disposeAction();
+ _disposed = true;
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/DelegatingEnricher.cs b/test/Serilog.Sinks.File.Tests/Support/DelegatingEnricher.cs
index 0a480fb..67b9758 100644
--- a/test/Serilog.Sinks.File.Tests/Support/DelegatingEnricher.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/DelegatingEnricher.cs
@@ -1,22 +1,20 @@
-using System;
-using Serilog.Core;
+using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+class DelegatingEnricher : ILogEventEnricher
{
- class DelegatingEnricher : ILogEventEnricher
- {
- readonly Action _enrich;
+ readonly Action _enrich;
- public DelegatingEnricher(Action enrich)
- {
- if (enrich == null) throw new ArgumentNullException(nameof(enrich));
- _enrich = enrich;
- }
+ public DelegatingEnricher(Action enrich)
+ {
+ if (enrich == null) throw new ArgumentNullException(nameof(enrich));
+ _enrich = enrich;
+ }
- public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
- {
- _enrich(logEvent, propertyFactory);
- }
+ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
+ {
+ _enrich(logEvent, propertyFactory);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/DelegatingSink.cs b/test/Serilog.Sinks.File.Tests/Support/DelegatingSink.cs
index 12b7f3d..aee1615 100644
--- a/test/Serilog.Sinks.File.Tests/Support/DelegatingSink.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/DelegatingSink.cs
@@ -1,33 +1,31 @@
-using System;
-using Serilog.Core;
+using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+public class DelegatingSink : ILogEventSink
{
- public class DelegatingSink : ILogEventSink
- {
- readonly Action _write;
+ readonly Action _write;
- public DelegatingSink(Action write)
- {
- if (write == null) throw new ArgumentNullException(nameof(write));
- _write = write;
- }
+ public DelegatingSink(Action write)
+ {
+ if (write == null) throw new ArgumentNullException(nameof(write));
+ _write = write;
+ }
- public void Emit(LogEvent logEvent)
- {
- _write(logEvent);
- }
+ public void Emit(LogEvent logEvent)
+ {
+ _write(logEvent);
+ }
- public static LogEvent GetLogEvent(Action writeAction)
- {
- LogEvent? result = null;
- var l = new LoggerConfiguration()
- .WriteTo.Sink(new DelegatingSink(le => result = le))
- .CreateLogger();
+ public static LogEvent GetLogEvent(Action writeAction)
+ {
+ LogEvent? result = null;
+ var l = new LoggerConfiguration()
+ .WriteTo.Sink(new DelegatingSink(le => result = le))
+ .CreateLogger();
- writeAction(l);
- return result!;
- }
+ writeAction(l);
+ return result!;
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/DisposableLogger.cs b/test/Serilog.Sinks.File.Tests/Support/DisposableLogger.cs
index befcbd4..ff8cf35 100644
--- a/test/Serilog.Sinks.File.Tests/Support/DisposableLogger.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/DisposableLogger.cs
@@ -1,422 +1,419 @@
-using System;
-using System.Collections.Generic;
-using Serilog.Core;
+using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+public class DisposableLogger : ILogger, IDisposable
{
- public class DisposableLogger : ILogger, IDisposable
- {
- public bool Disposed { get; set; }
-
- public void Dispose()
- {
- Disposed = true;
- }
-
- public ILogger ForContext(ILogEventEnricher enricher)
- {
- throw new NotImplementedException();
- }
-
- public ILogger ForContext(IEnumerable enrichers)
- {
- throw new NotImplementedException();
- }
-
- public ILogger ForContext(string propertyName, object value, bool destructureObjects = false)
- {
- throw new NotImplementedException();
- }
-
- public ILogger ForContext()
- {
- throw new NotImplementedException();
- }
-
- public ILogger ForContext(Type source)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEvent logEvent)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1, T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public bool IsEnabled(LogEventLevel level)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(Exception exception, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(Exception exception, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(Exception exception, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(Exception exception, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Debug(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Information(string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Information(string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Information(string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Information(Exception exception, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Information(Exception exception, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Information(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(Exception exception, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(Exception exception, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Warning(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Error(string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Error(string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Error(string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Error(Exception exception, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Error(Exception exception, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Error(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(Exception exception, string messageTemplate)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(Exception exception, string messageTemplate, T propertyValue)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- throw new NotImplementedException();
- }
-
- public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- throw new NotImplementedException();
- }
-
- public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate,
- out IEnumerable boundProperties)
- {
- throw new NotImplementedException();
- }
-
- public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property)
- {
- throw new NotImplementedException();
- }
+ public bool Disposed { get; set; }
+
+ public void Dispose()
+ {
+ Disposed = true;
+ }
+
+ public ILogger ForContext(ILogEventEnricher enricher)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ILogger ForContext(IEnumerable enrichers)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ILogger ForContext(string propertyName, object value, bool destructureObjects = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ILogger ForContext()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ILogger ForContext(Type source)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEvent logEvent)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1, T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsEnabled(LogEventLevel level)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(Exception exception, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(Exception exception, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(Exception exception, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(Exception exception, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(Exception exception, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Information(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(Exception exception, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(Exception exception, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warning(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(Exception exception, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(Exception exception, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(Exception exception, string messageTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, T propertyValue)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate,
+ out IEnumerable boundProperties)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property)
+ {
+ throw new NotImplementedException();
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/DisposeTrackingSink.cs b/test/Serilog.Sinks.File.Tests/Support/DisposeTrackingSink.cs
index 29cac56..c4e2559 100644
--- a/test/Serilog.Sinks.File.Tests/Support/DisposeTrackingSink.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/DisposeTrackingSink.cs
@@ -1,20 +1,18 @@
-using System;
-using Serilog.Core;
+using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+class DisposeTrackingSink : ILogEventSink, IDisposable
{
- class DisposeTrackingSink : ILogEventSink, IDisposable
- {
- public bool IsDisposed { get; set; }
+ public bool IsDisposed { get; set; }
- public void Emit(LogEvent logEvent)
- {
- }
+ public void Emit(LogEvent logEvent)
+ {
+ }
- public void Dispose()
- {
- IsDisposed = true;
- }
+ public void Dispose()
+ {
+ IsDisposed = true;
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/Extensions.cs b/test/Serilog.Sinks.File.Tests/Support/Extensions.cs
index a048353..3fd7a15 100644
--- a/test/Serilog.Sinks.File.Tests/Support/Extensions.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/Extensions.cs
@@ -1,30 +1,27 @@
-using System.Collections.Generic;
-using System.IO;
-using Serilog.Events;
+using Serilog.Events;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+public static class Extensions
{
- public static class Extensions
+ public static object LiteralValue(this LogEventPropertyValue @this)
{
- public static object LiteralValue(this LogEventPropertyValue @this)
- {
- return ((ScalarValue)@this).Value;
- }
+ return ((ScalarValue)@this).Value;
+ }
- public static List ReadAllLines(this Stream @this)
- {
- var lines = new List();
+ public static List ReadAllLines(this Stream @this)
+ {
+ var lines = new List();
- using (var reader = new StreamReader(@this))
+ using (var reader = new StreamReader(@this))
+ {
+ string? line;
+ while ((line = reader.ReadLine()) != null)
{
- string? line;
- while ((line = reader.ReadLine()) != null)
- {
- lines.Add(line);
- }
+ lines.Add(line);
}
-
- return lines;
}
+
+ return lines;
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/FileHeaderWriter.cs b/test/Serilog.Sinks.File.Tests/Support/FileHeaderWriter.cs
index ae90604..9e92294 100644
--- a/test/Serilog.Sinks.File.Tests/Support/FileHeaderWriter.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/FileHeaderWriter.cs
@@ -1,28 +1,26 @@
-using System.IO;
-using System.Text;
+using System.Text;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+class FileHeaderWriter : FileLifecycleHooks
{
- class FileHeaderWriter : FileLifecycleHooks
+ public string Header { get; }
+
+ public FileHeaderWriter(string header)
{
- public string Header { get; }
+ Header = header;
+ }
- public FileHeaderWriter(string header)
+ public override Stream OnFileOpened(Stream underlyingStream, Encoding encoding)
+ {
+ if (underlyingStream.Length == 0)
{
- Header = header;
+ var writer = new StreamWriter(underlyingStream, encoding);
+ writer.WriteLine(Header);
+ writer.Flush();
+ underlyingStream.Flush();
}
- public override Stream OnFileOpened(Stream underlyingStream, Encoding encoding)
- {
- if (underlyingStream.Length == 0)
- {
- var writer = new StreamWriter(underlyingStream, encoding);
- writer.WriteLine(Header);
- writer.Flush();
- underlyingStream.Flush();
- }
-
- return base.OnFileOpened(underlyingStream, encoding);
- }
+ return base.OnFileOpened(underlyingStream, encoding);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/FixedOutputFormatter.cs b/test/Serilog.Sinks.File.Tests/Support/FixedOutputFormatter.cs
index 24b70da..650a2e2 100644
--- a/test/Serilog.Sinks.File.Tests/Support/FixedOutputFormatter.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/FixedOutputFormatter.cs
@@ -1,21 +1,19 @@
using Serilog.Formatting;
using Serilog.Events;
-using System.IO;
-namespace Serilog.Tests.Support
+namespace Serilog.Tests.Support;
+
+public class FixedOutputFormatter : ITextFormatter
{
- public class FixedOutputFormatter : ITextFormatter
- {
- string _substitutionText;
+ string _substitutionText;
- public FixedOutputFormatter(string substitutionText)
- {
- _substitutionText = substitutionText;
- }
+ public FixedOutputFormatter(string substitutionText)
+ {
+ _substitutionText = substitutionText;
+ }
- public void Format(LogEvent logEvent, TextWriter output)
- {
- output.Write(_substitutionText);
- }
+ public void Format(LogEvent logEvent, TextWriter output)
+ {
+ output.Write(_substitutionText);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/GZipHooks.cs b/test/Serilog.Sinks.File.Tests/Support/GZipHooks.cs
index 40a77bb..7191db1 100644
--- a/test/Serilog.Sinks.File.Tests/Support/GZipHooks.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/GZipHooks.cs
@@ -1,26 +1,24 @@
-using System.IO;
using System.IO.Compression;
using System.Text;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+///
+///
+/// Demonstrates the use of , by compressing log output using GZip
+///
+public class GZipHooks : FileLifecycleHooks
{
- ///
- ///
- /// Demonstrates the use of , by compressing log output using GZip
- ///
- public class GZipHooks : FileLifecycleHooks
- {
- readonly int _bufferSize;
+ readonly int _bufferSize;
- public GZipHooks(int bufferSize = 1024 * 32)
- {
- _bufferSize = bufferSize;
- }
+ public GZipHooks(int bufferSize = 1024 * 32)
+ {
+ _bufferSize = bufferSize;
+ }
- public override Stream OnFileOpened(Stream underlyingStream, Encoding _)
- {
- var compressStream = new GZipStream(underlyingStream, CompressionMode.Compress);
- return new BufferedStream(compressStream, _bufferSize);
- }
+ public override Stream OnFileOpened(Stream underlyingStream, Encoding _)
+ {
+ var compressStream = new GZipStream(underlyingStream, CompressionMode.Compress);
+ return new BufferedStream(compressStream, _bufferSize);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/Some.cs b/test/Serilog.Sinks.File.Tests/Support/Some.cs
index 4209102..05ddc11 100644
--- a/test/Serilog.Sinks.File.Tests/Support/Some.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/Some.cs
@@ -1,102 +1,97 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using Serilog.Events;
+using Serilog.Events;
using Serilog.Parsing;
using Xunit.Sdk;
// ReSharper disable UnusedMember.Global
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+static class Some
{
- static class Some
- {
- static int _counter;
+ static int _counter;
- public static int Int()
- {
- return Interlocked.Increment(ref _counter);
- }
+ public static int Int()
+ {
+ return Interlocked.Increment(ref _counter);
+ }
- public static decimal Decimal()
- {
- return Int() + 0.123m;
- }
+ public static decimal Decimal()
+ {
+ return Int() + 0.123m;
+ }
- public static string String(string? tag = null)
- {
- return (tag ?? "") + "__" + Int();
- }
+ public static string String(string? tag = null)
+ {
+ return (tag ?? "") + "__" + Int();
+ }
- public static TimeSpan TimeSpan()
- {
- return System.TimeSpan.FromMinutes(Int());
- }
+ public static TimeSpan TimeSpan()
+ {
+ return System.TimeSpan.FromMinutes(Int());
+ }
- public static DateTime Instant()
- {
- return new DateTime(2012, 10, 28) + TimeSpan();
- }
+ public static DateTime Instant()
+ {
+ return new DateTime(2012, 10, 28) + TimeSpan();
+ }
- public static DateTimeOffset OffsetInstant()
- {
- return new DateTimeOffset(Instant());
- }
+ public static DateTimeOffset OffsetInstant()
+ {
+ return new DateTimeOffset(Instant());
+ }
- public static LogEvent LogEvent(string messageTemplate, params object[] propertyValues)
- {
- var log = new LoggerConfiguration().CreateLogger();
+ public static LogEvent LogEvent(string messageTemplate, params object[] propertyValues)
+ {
+ var log = new LoggerConfiguration().CreateLogger();
#pragma warning disable Serilog004 // Constant MessageTemplate verifier
- if (!log.BindMessageTemplate(messageTemplate, propertyValues, out var template, out var properties))
+ if (!log.BindMessageTemplate(messageTemplate, propertyValues, out var template, out var properties))
#pragma warning restore Serilog004 // Constant MessageTemplate verifier
- {
- throw new XunitException("Template could not be bound.");
- }
- return new LogEvent(DateTimeOffset.Now, LogEventLevel.Information, null, template, properties);
- }
-
- public static LogEvent LogEvent(DateTimeOffset? timestamp = null, LogEventLevel level = LogEventLevel.Information)
{
- return new LogEvent(timestamp ?? OffsetInstant(), level,
- null, MessageTemplate(), Enumerable.Empty());
+ throw new XunitException("Template could not be bound.");
}
+ return new LogEvent(DateTimeOffset.Now, LogEventLevel.Information, null, template, properties);
+ }
- public static LogEvent InformationEvent(DateTimeOffset? timestamp = null)
- {
- return LogEvent(timestamp);
- }
+ public static LogEvent LogEvent(DateTimeOffset? timestamp = null, LogEventLevel level = LogEventLevel.Information)
+ {
+ return new LogEvent(timestamp ?? OffsetInstant(), level,
+ null, MessageTemplate(), Enumerable.Empty());
+ }
- public static LogEvent DebugEvent(DateTimeOffset? timestamp = null)
- {
- return LogEvent(timestamp, LogEventLevel.Debug);
- }
+ public static LogEvent InformationEvent(DateTimeOffset? timestamp = null)
+ {
+ return LogEvent(timestamp);
+ }
- public static LogEventProperty LogEventProperty()
- {
- return new LogEventProperty(String(), new ScalarValue(Int()));
- }
+ public static LogEvent DebugEvent(DateTimeOffset? timestamp = null)
+ {
+ return LogEvent(timestamp, LogEventLevel.Debug);
+ }
- public static string NonexistentTempFilePath()
- {
- return Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".txt");
- }
+ public static LogEventProperty LogEventProperty()
+ {
+ return new LogEventProperty(String(), new ScalarValue(Int()));
+ }
- public static string TempFilePath()
- {
- return Path.GetTempFileName();
- }
+ public static string NonexistentTempFilePath()
+ {
+ return Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".txt");
+ }
- public static string TempFolderPath()
- {
- var dir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
- Directory.CreateDirectory(dir);
- return dir;
- }
+ public static string TempFilePath()
+ {
+ return Path.GetTempFileName();
+ }
- public static MessageTemplate MessageTemplate()
- {
- return new MessageTemplateParser().Parse(String());
- }
+ public static string TempFolderPath()
+ {
+ var dir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
+ Directory.CreateDirectory(dir);
+ return dir;
+ }
+
+ public static MessageTemplate MessageTemplate()
+ {
+ return new MessageTemplateParser().Parse(String());
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/TempFolder.cs b/test/Serilog.Sinks.File.Tests/Support/TempFolder.cs
index 29682e0..10d751e 100644
--- a/test/Serilog.Sinks.File.Tests/Support/TempFolder.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/TempFolder.cs
@@ -1,55 +1,52 @@
-using System;
-using System.Diagnostics;
-using System.IO;
+using System.Diagnostics;
using System.Runtime.CompilerServices;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+class TempFolder : IDisposable
{
- class TempFolder : IDisposable
- {
- static readonly Guid Session = Guid.NewGuid();
+ static readonly Guid Session = Guid.NewGuid();
- readonly string _tempFolder;
+ readonly string _tempFolder;
- public TempFolder(string? name = null)
- {
- _tempFolder = System.IO.Path.Combine(
- Environment.GetEnvironmentVariable("TMP") ?? Environment.GetEnvironmentVariable("TMPDIR") ?? "/tmp",
- "Serilog.Sinks.File.Tests",
- Session.ToString("n"),
- name ?? Guid.NewGuid().ToString("n"));
+ public TempFolder(string? name = null)
+ {
+ _tempFolder = System.IO.Path.Combine(
+ Environment.GetEnvironmentVariable("TMP") ?? Environment.GetEnvironmentVariable("TMPDIR") ?? "/tmp",
+ "Serilog.Sinks.File.Tests",
+ Session.ToString("n"),
+ name ?? Guid.NewGuid().ToString("n"));
- Directory.CreateDirectory(_tempFolder);
- }
+ Directory.CreateDirectory(_tempFolder);
+ }
- public string Path => _tempFolder;
+ public string Path => _tempFolder;
- public void Dispose()
+ public void Dispose()
+ {
+ try
{
- try
- {
- if (Directory.Exists(_tempFolder))
- Directory.Delete(_tempFolder, true);
- }
- catch (Exception ex)
- {
- Debug.WriteLine(ex);
- }
+ if (Directory.Exists(_tempFolder))
+ Directory.Delete(_tempFolder, true);
}
-
- public static TempFolder ForCaller([CallerMemberName] string? caller = null, [CallerFilePath] string sourceFileName = "")
+ catch (Exception ex)
{
- if (caller == null) throw new ArgumentNullException(nameof(caller));
- if (sourceFileName == null) throw new ArgumentNullException(nameof(sourceFileName));
-
- var folderName = System.IO.Path.GetFileNameWithoutExtension(sourceFileName) + "_" + caller;
-
- return new TempFolder(folderName);
+ Debug.WriteLine(ex);
}
+ }
- public string AllocateFilename(string? ext = null)
- {
- return System.IO.Path.Combine(Path, Guid.NewGuid().ToString("n") + "." + (ext ?? "tmp"));
- }
+ public static TempFolder ForCaller([CallerMemberName] string? caller = null, [CallerFilePath] string sourceFileName = "")
+ {
+ if (caller == null) throw new ArgumentNullException(nameof(caller));
+ if (sourceFileName == null) throw new ArgumentNullException(nameof(sourceFileName));
+
+ var folderName = System.IO.Path.GetFileNameWithoutExtension(sourceFileName) + "_" + caller;
+
+ return new TempFolder(folderName);
+ }
+
+ public string AllocateFilename(string? ext = null)
+ {
+ return System.IO.Path.Combine(Path, Guid.NewGuid().ToString("n") + "." + (ext ?? "tmp"));
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/ThrowingLogEventFormatter.cs b/test/Serilog.Sinks.File.Tests/Support/ThrowingLogEventFormatter.cs
index 9170ef5..10de763 100644
--- a/test/Serilog.Sinks.File.Tests/Support/ThrowingLogEventFormatter.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/ThrowingLogEventFormatter.cs
@@ -1,15 +1,12 @@
-using System;
-using System.IO;
-using Serilog.Events;
+using Serilog.Events;
using Serilog.Formatting;
-namespace Serilog.Tests.Support
+namespace Serilog.Tests.Support;
+
+public class ThrowingLogEventFormatter : ITextFormatter
{
- public class ThrowingLogEventFormatter : ITextFormatter
+ public void Format(LogEvent logEvent, TextWriter output)
{
- public void Format(LogEvent logEvent, TextWriter output)
- {
- throw new NotImplementedException();
- }
+ throw new NotImplementedException();
}
}
diff --git a/test/Serilog.Sinks.File.Tests/Support/TruncateFileHook.cs b/test/Serilog.Sinks.File.Tests/Support/TruncateFileHook.cs
index 63f8497..aecc413 100644
--- a/test/Serilog.Sinks.File.Tests/Support/TruncateFileHook.cs
+++ b/test/Serilog.Sinks.File.Tests/Support/TruncateFileHook.cs
@@ -1,18 +1,16 @@
-using System.IO;
using System.Text;
-namespace Serilog.Sinks.File.Tests.Support
+namespace Serilog.Sinks.File.Tests.Support;
+
+///
+///
+/// Demonstrates the use of , by emptying the file before it's written to
+///
+public class TruncateFileHook : FileLifecycleHooks
{
- ///
- ///
- /// Demonstrates the use of , by emptying the file before it's written to
- ///
- public class TruncateFileHook : FileLifecycleHooks
+ public override Stream OnFileOpened(Stream underlyingStream, Encoding encoding)
{
- public override Stream OnFileOpened(Stream underlyingStream, Encoding encoding)
- {
- underlyingStream.SetLength(0);
- return base.OnFileOpened(underlyingStream, encoding);
- }
+ underlyingStream.SetLength(0);
+ return base.OnFileOpened(underlyingStream, encoding);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/TemplatedPathRollerTests.cs b/test/Serilog.Sinks.File.Tests/TemplatedPathRollerTests.cs
index 65a974c..e34c335 100644
--- a/test/Serilog.Sinks.File.Tests/TemplatedPathRollerTests.cs
+++ b/test/Serilog.Sinks.File.Tests/TemplatedPathRollerTests.cs
@@ -1,100 +1,96 @@
-using System;
-using System.IO;
-using System.Linq;
-using Xunit;
+using Xunit;
-namespace Serilog.Sinks.File.Tests
+namespace Serilog.Sinks.File.Tests;
+
+public class PathRollerTests
{
- public class PathRollerTests
+ [Fact]
+ public void TheLogFileIncludesDateToken()
{
- [Fact]
- public void TheLogFileIncludesDateToken()
- {
- var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
- 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);
- }
+ var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
+ 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);
+ }
- [Fact]
- public void ANonZeroIncrementIsIncludedAndPadded()
- {
- var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
- 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);
- }
+ [Fact]
+ public void ANonZeroIncrementIsIncludedAndPadded()
+ {
+ var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
+ 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);
+ }
- static void AssertEqualAbsolute(string path1, string path2)
- {
- var abs1 = Path.GetFullPath(path1);
- var abs2 = Path.GetFullPath(path2);
- Assert.Equal(abs1, abs2);
- }
+ static void AssertEqualAbsolute(string path1, string path2)
+ {
+ var abs1 = Path.GetFullPath(path1);
+ var abs2 = Path.GetFullPath(path2);
+ Assert.Equal(abs1, abs2);
+ }
- [Fact]
- public void TheRollerReturnsTheLogFileDirectory()
- {
- var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
- AssertEqualAbsolute("Logs", roller.LogFileDirectory);
- }
+ [Fact]
+ public void TheRollerReturnsTheLogFileDirectory()
+ {
+ var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
+ AssertEqualAbsolute("Logs", roller.LogFileDirectory);
+ }
- [Fact]
- public void TheLogFileIsNotRequiredToIncludeAnExtension()
- {
- var roller = new PathRoller(Path.Combine("Logs", "log-"), RollingInterval.Day);
- 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);
- }
+ [Fact]
+ public void TheLogFileIsNotRequiredToIncludeAnExtension()
+ {
+ var roller = new PathRoller(Path.Combine("Logs", "log-"), RollingInterval.Day);
+ 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);
+ }
- [Fact]
- public void TheLogFileIsNotRequiredToIncludeADirectory()
- {
- var roller = new PathRoller("log-", RollingInterval.Day);
- var now = new DateTime(2013, 7, 14, 3, 24, 9, 980);
- roller.GetLogFilePath(now, null, out var path);
- AssertEqualAbsolute("log-20130714", path);
- }
+ [Fact]
+ public void TheLogFileIsNotRequiredToIncludeADirectory()
+ {
+ var roller = new PathRoller("log-", RollingInterval.Day);
+ var now = new DateTime(2013, 7, 14, 3, 24, 9, 980);
+ roller.GetLogFilePath(now, null, out var path);
+ AssertEqualAbsolute("log-20130714", path);
+ }
- [Fact]
- public void MatchingExcludesSimilarButNonMatchingFiles()
- {
- var roller = new PathRoller("log-.txt", RollingInterval.Day);
- const string similar1 = "log-0.txt";
- const string similar2 = "log-hello.txt";
- var matched = roller.SelectMatches(new[] { similar1, similar2 });
- Assert.Empty(matched);
- }
+ [Fact]
+ public void MatchingExcludesSimilarButNonMatchingFiles()
+ {
+ var roller = new PathRoller("log-.txt", RollingInterval.Day);
+ const string similar1 = "log-0.txt";
+ const string similar2 = "log-hello.txt";
+ var matched = roller.SelectMatches(new[] { similar1, similar2 });
+ Assert.Empty(matched);
+ }
- [Fact]
- public void TheDirectorSearchPatternUsesWildcardInPlaceOfDate()
- {
- var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
- Assert.Equal("log-*.txt", roller.DirectorySearchPattern);
- }
+ [Fact]
+ public void TheDirectorSearchPatternUsesWildcardInPlaceOfDate()
+ {
+ var roller = new PathRoller(Path.Combine("Logs", "log-.txt"), RollingInterval.Day);
+ Assert.Equal("log-*.txt", roller.DirectorySearchPattern);
+ }
- [Theory]
- [InlineData("log-.txt", "log-20131210.txt", "log-20131210_031.txt", RollingInterval.Day)]
- [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 matched = roller.SelectMatches(new[] { zeroth, thirtyFirst }).ToArray();
- Assert.Equal(2, matched.Length);
- Assert.Null(matched[0].SequenceNumber);
- Assert.Equal(31, matched[1].SequenceNumber);
- }
+ [Theory]
+ [InlineData("log-.txt", "log-20131210.txt", "log-20131210_031.txt", RollingInterval.Day)]
+ [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 matched = roller.SelectMatches(new[] { zeroth, thirtyFirst }).ToArray();
+ Assert.Equal(2, matched.Length);
+ Assert.Null(matched[0].SequenceNumber);
+ Assert.Equal(31, matched[1].SequenceNumber);
+ }
- [Theory]
- [InlineData("log-.txt", "log-20150101.txt", "log-20141231.txt", RollingInterval.Day)]
- [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 matched = roller.SelectMatches(new[] { older, newer }).OrderByDescending(m => m.DateTime).Select(m => m.Filename).ToArray();
- Assert.Equal(new[] { newer, older }, matched);
- }
+ [Theory]
+ [InlineData("log-.txt", "log-20150101.txt", "log-20141231.txt", RollingInterval.Day)]
+ [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 matched = roller.SelectMatches(new[] { older, newer }).OrderByDescending(m => m.DateTime).Select(m => m.Filename).ToArray();
+ Assert.Equal(new[] { newer, older }, matched);
}
}
diff --git a/test/Serilog.Sinks.File.Tests/WriteCountingStreamTests.cs b/test/Serilog.Sinks.File.Tests/WriteCountingStreamTests.cs
index 887ffe2..68a8cc8 100644
--- a/test/Serilog.Sinks.File.Tests/WriteCountingStreamTests.cs
+++ b/test/Serilog.Sinks.File.Tests/WriteCountingStreamTests.cs
@@ -1,83 +1,77 @@
-using System.IO;
using System.Text;
using Serilog.Sinks.File.Tests.Support;
using Xunit;
-namespace Serilog.Sinks.File.Tests
+namespace Serilog.Sinks.File.Tests;
+
+public class WriteCountingStreamTests
{
- public class WriteCountingStreamTests
+ [Fact]
+ public void CountedLengthIsResetToStreamLengthIfNewSizeIsSmaller()
{
- [Fact]
- public void CountedLengthIsResetToStreamLengthIfNewSizeIsSmaller()
+ // If we counted 10 bytes written and SetLength was called with a smaller length (e.g. 5)
+ // we adjust the counter to the new byte count of the file to reflect reality
+
+ using var tmp = TempFolder.ForCaller();
+ var path = tmp.AllocateFilename("txt");
+
+ long streamLengthAfterSetLength;
+ long countedLengthAfterSetLength;
+
+ using (var fileStream = System.IO.File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read))
+ using (var countingStream = new WriteCountingStream(fileStream))
+ using (var writer = new StreamWriter(countingStream, new UTF8Encoding(false)))
{
- // If we counted 10 bytes written and SetLength was called with a smaller length (e.g. 5)
- // we adjust the counter to the new byte count of the file to reflect reality
+ writer.WriteLine("Hello, world!");
+ writer.Flush();
- using (var tmp = TempFolder.ForCaller())
- {
- var path = tmp.AllocateFilename("txt");
+ countingStream.SetLength(5);
+ streamLengthAfterSetLength = countingStream.Length;
+ countedLengthAfterSetLength = countingStream.CountedLength;
+ }
- long streamLengthAfterSetLength;
- long countedLengthAfterSetLength;
+ Assert.Equal(5, streamLengthAfterSetLength);
+ Assert.Equal(5, countedLengthAfterSetLength);
- using (var fileStream = System.IO.File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read))
- using (var countingStream = new WriteCountingStream(fileStream))
- using (var writer = new StreamWriter(countingStream, new UTF8Encoding(false)))
- {
- writer.WriteLine("Hello, world!");
- writer.Flush();
+ var lines = System.IO.File.ReadAllLines(path);
- countingStream.SetLength(5);
- streamLengthAfterSetLength = countingStream.Length;
- countedLengthAfterSetLength = countingStream.CountedLength;
- }
+ Assert.Single(lines);
+ Assert.Equal("Hello", lines[0]);
+ }
- Assert.Equal(5, streamLengthAfterSetLength);
- Assert.Equal(5, countedLengthAfterSetLength);
+ [Fact]
+ public void CountedLengthRemainsTheSameIfNewSizeIsLarger()
+ {
+ // If we counted 10 bytes written and SetLength was called with a larger length (e.g. 100)
+ // we leave the counter intact because our position on the stream remains the same... The
+ // file just grew larger in size
- var lines = System.IO.File.ReadAllLines(path);
+ using var tmp = TempFolder.ForCaller();
+ var path = tmp.AllocateFilename("txt");
- Assert.Single(lines);
- Assert.Equal("Hello", lines[0]);
- }
- }
+ long streamLengthBeforeSetLength;
+ long streamLengthAfterSetLength;
+ long countedLengthAfterSetLength;
- [Fact]
- public void CountedLengthRemainsTheSameIfNewSizeIsLarger()
+ using (var fileStream = System.IO.File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read))
+ using (var countingStream = new WriteCountingStream(fileStream))
+ using (var writer = new StreamWriter(countingStream, new UTF8Encoding(false)))
{
- // If we counted 10 bytes written and SetLength was called with a larger length (e.g. 100)
- // we leave the counter intact because our position on the stream remains the same... The
- // file just grew larger in size
-
- using (var tmp = TempFolder.ForCaller())
- {
- var path = tmp.AllocateFilename("txt");
-
- long streamLengthBeforeSetLength;
- long streamLengthAfterSetLength;
- long countedLengthAfterSetLength;
-
- using (var fileStream = System.IO.File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read))
- using (var countingStream = new WriteCountingStream(fileStream))
- using (var writer = new StreamWriter(countingStream, new UTF8Encoding(false)))
- {
- writer.WriteLine("Hello, world!");
- writer.Flush();
-
- streamLengthBeforeSetLength = countingStream.CountedLength;
- countingStream.SetLength(100);
- streamLengthAfterSetLength = countingStream.Length;
- countedLengthAfterSetLength = countingStream.CountedLength;
- }
-
- Assert.Equal(100, streamLengthAfterSetLength);
- Assert.Equal(streamLengthBeforeSetLength, countedLengthAfterSetLength);
-
- var lines = System.IO.File.ReadAllLines(path);
-
- Assert.Equal(2, lines.Length);
- Assert.Equal("Hello, world!", lines[0]);
- }
+ writer.WriteLine("Hello, world!");
+ writer.Flush();
+
+ streamLengthBeforeSetLength = countingStream.CountedLength;
+ countingStream.SetLength(100);
+ streamLengthAfterSetLength = countingStream.Length;
+ countedLengthAfterSetLength = countingStream.CountedLength;
}
+
+ Assert.Equal(100, streamLengthAfterSetLength);
+ Assert.Equal(streamLengthBeforeSetLength, countedLengthAfterSetLength);
+
+ var lines = System.IO.File.ReadAllLines(path);
+
+ Assert.Equal(2, lines.Length);
+ Assert.Equal("Hello, world!", lines[0]);
}
}