diff --git a/src/Serilog.Sinks.RollingFile/RollingFileLoggerConfigurationExtensions.cs b/src/Serilog.Sinks.RollingFile/RollingFileLoggerConfigurationExtensions.cs
index 672e4ef..41975e9 100644
--- a/src/Serilog.Sinks.RollingFile/RollingFileLoggerConfigurationExtensions.cs
+++ b/src/Serilog.Sinks.RollingFile/RollingFileLoggerConfigurationExtensions.cs
@@ -53,8 +53,9 @@ public static class RollingFileLoggerConfigurationExtensions
/// including the current log file. For unlimited retention, pass null. The default is 31.
/// Indicates if flushing to the output file can be buffered or not. The default
/// is false.
+ /// Allow the log files to be shared by multiple processes. The default is false.
/// Configuration object allowing method chaining.
- /// The file will be written using the UTF-8 character set.
+ /// The file will be written using the UTF-8 encoding without a byte-order mark.
public static LoggerConfiguration RollingFile(
this LoggerSinkConfiguration sinkConfiguration,
string pathFormat,
@@ -64,11 +65,12 @@ public static LoggerConfiguration RollingFile(
long? fileSizeLimitBytes = DefaultFileSizeLimitBytes,
int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
LoggingLevelSwitch levelSwitch = null,
- bool buffered = false)
+ bool buffered = false,
+ bool shared = false)
{
var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
return RollingFile(sinkConfiguration, formatter, pathFormat, restrictedToMinimumLevel, fileSizeLimitBytes,
- retainedFileCountLimit, levelSwitch, buffered);
+ retainedFileCountLimit, levelSwitch, buffered, shared);
}
///
@@ -92,8 +94,9 @@ public static LoggerConfiguration RollingFile(
/// including the current log file. For unlimited retention, pass null. The default is 31.
/// Indicates if flushing to the output file can be buffered or not. The default
/// is false.
+ /// Allow the log files to be shared by multiple processes. The default is false.
/// Configuration object allowing method chaining.
- /// The file will be written using the UTF-8 character set.
+ /// The file will be written using the UTF-8 encoding without a byte-order mark.
public static LoggerConfiguration RollingFile(
this LoggerSinkConfiguration sinkConfiguration,
ITextFormatter formatter,
@@ -102,11 +105,16 @@ public static LoggerConfiguration RollingFile(
long? fileSizeLimitBytes = DefaultFileSizeLimitBytes,
int? retainedFileCountLimit = DefaultRetainedFileCountLimit,
LoggingLevelSwitch levelSwitch = null,
- bool buffered = false)
+ bool buffered = false,
+ bool shared = false)
{
if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
if (formatter == null) throw new ArgumentNullException(nameof(formatter));
- var sink = new RollingFileSink(pathFormat, formatter, fileSizeLimitBytes, retainedFileCountLimit, buffered: buffered);
+
+ if (shared && buffered)
+ throw new ArgumentException("Buffered writes are not available when file sharing is enabled.", nameof(buffered));
+
+ var sink = new RollingFileSink(pathFormat, formatter, fileSizeLimitBytes, retainedFileCountLimit, buffered: buffered, shared: shared);
return sinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);
}
}
diff --git a/src/Serilog.Sinks.RollingFile/Sinks/RollingFile/RollingFileSink.cs b/src/Serilog.Sinks.RollingFile/Sinks/RollingFile/RollingFileSink.cs
index 0644672..9e5d745 100644
--- a/src/Serilog.Sinks.RollingFile/Sinks/RollingFile/RollingFileSink.cs
+++ b/src/Serilog.Sinks.RollingFile/Sinks/RollingFile/RollingFileSink.cs
@@ -39,11 +39,12 @@ public sealed class RollingFileSink : ILogEventSink, IDisposable
readonly int? _retainedFileCountLimit;
readonly Encoding _encoding;
readonly bool _buffered;
+ readonly bool _shared;
readonly object _syncRoot = new object();
bool _isDisposed;
DateTime? _nextCheckpoint;
- FileSink _currentFile;
+ ILogEventSink _currentFile;
/// Construct a .
/// String describing the location of the log files,
@@ -54,9 +55,10 @@ public sealed class RollingFileSink : ILogEventSink, IDisposable
/// For unrestricted growth, pass null. The default is 1 GB.
/// 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.
+ /// 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.
+ /// Allow the log files to be shared by multiple processes. The default is false.
/// Configuration object allowing method chaining.
/// The file will be written using the UTF-8 character set.
public RollingFileSink(string pathFormat,
@@ -64,18 +66,25 @@ public RollingFileSink(string pathFormat,
long? fileSizeLimitBytes,
int? retainedFileCountLimit,
Encoding encoding = null,
- bool buffered = false)
+ bool buffered = false,
+ bool shared = false)
{
if (pathFormat == null) throw new ArgumentNullException(nameof(pathFormat));
if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) throw new ArgumentException("Negative value provided; file size limit must be non-negative");
if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1) throw new ArgumentException("Zero or negative value provided; retained file count limit must be at least 1");
+#if !SHARING
+ if (shared)
+ throw new NotSupportedException("File sharing is not supported on this platform.");
+#endif
+
_roller = new TemplatedPathRoller(pathFormat);
_textFormatter = textFormatter;
_fileSizeLimitBytes = fileSizeLimitBytes;
_retainedFileCountLimit = retainedFileCountLimit;
- _encoding = encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
+ _encoding = encoding;
_buffered = buffered;
+ _shared = shared;
}
///
@@ -98,8 +107,7 @@ public void Emit(LogEvent logEvent)
// If the file was unable to be opened on the last attempt, it will remain
// null until the next checkpoint passes, at which time another attempt will be made to
// open it.
- if (_currentFile != null)
- _currentFile.Emit(logEvent);
+ _currentFile?.Emit(logEvent);
}
}
@@ -148,7 +156,13 @@ void OpenFile(DateTime now)
try
{
+#if SHARING
+ _currentFile = _shared ?
+ (ILogEventSink)new SharedFileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding) :
+ new FileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding, _buffered);
+#else
_currentFile = new FileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding, _buffered);
+#endif
}
catch (IOException ex)
{
@@ -223,7 +237,7 @@ void CloseFile()
{
if (_currentFile != null)
{
- _currentFile.Dispose();
+ (_currentFile as IDisposable)?.Dispose();
_currentFile = null;
}
diff --git a/src/Serilog.Sinks.RollingFile/project.json b/src/Serilog.Sinks.RollingFile/project.json
index b1fc93c..2651010 100644
--- a/src/Serilog.Sinks.RollingFile/project.json
+++ b/src/Serilog.Sinks.RollingFile/project.json
@@ -1,5 +1,5 @@
{
- "version": "2.3.0-*",
+ "version": "3.0.0-*",
"description": "The rolling file sink for Serilog - Simple .NET logging with fully-structured events",
"authors": [ "Serilog Contributors" ],
"packOptions": {
@@ -9,8 +9,7 @@
"iconUrl": "http://serilog.net/images/serilog-sink-nuget.png"
},
"dependencies": {
- "Serilog": "2.0.0",
- "Serilog.Sinks.File": "2.0.0"
+ "Serilog.Sinks.File": "3.0.0-dev-00735"
},
"buildOptions": {
"keyFile": "../../assets/Serilog.snk",
@@ -18,7 +17,9 @@
"warningsAsErrors": true
},
"frameworks": {
- "net4.5": {},
+ "net4.5": {
+ "buildOptions": {"define": ["SHARING"]}
+ },
"netstandard1.3": {
"dependencies": {
"System.IO": "4.1.0",
diff --git a/test/Serilog.Sinks.RollingFile.Tests/RollingFileLoggerConfigurationExtensionsTests.cs b/test/Serilog.Sinks.RollingFile.Tests/RollingFileLoggerConfigurationExtensionsTests.cs
new file mode 100644
index 0000000..e5ac302
--- /dev/null
+++ b/test/Serilog.Sinks.RollingFile.Tests/RollingFileLoggerConfigurationExtensionsTests.cs
@@ -0,0 +1,16 @@
+using System;
+using Xunit;
+
+namespace Serilog.Tests
+{
+ public class RollingFileLoggerConfigurationExtensionsTests
+ {
+ [Fact]
+ public void BuffferingIsNotAvailableWhenSharingEnabled()
+ {
+ Assert.Throws(() =>
+ new LoggerConfiguration()
+ .WriteTo.RollingFile("logs", buffered: true, shared: true));
+ }
+ }
+}
diff --git a/test/Serilog.Sinks.RollingFile.Tests/project.json b/test/Serilog.Sinks.RollingFile.Tests/project.json
index 1f84c3e..2e868cc 100644
--- a/test/Serilog.Sinks.RollingFile.Tests/project.json
+++ b/test/Serilog.Sinks.RollingFile.Tests/project.json
@@ -1,11 +1,9 @@
{
- "version": "2.0.0",
"testRunner": "xunit",
"dependencies": {
"Serilog.Sinks.RollingFile": { "target": "project" },
"xunit": "2.1.0",
- "dotnet-test-xunit": "1.0.0-rc2-build10025",
- "Serilog.Sinks.File": "2.0.0"
+ "dotnet-test-xunit": "1.0.0-rc2-build10025"
},
"buildOptions": {
"keyFile": "../../assets/Serilog.snk",