diff --git a/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs b/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs
index d31acb4..9e77cbb 100644
--- a/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs
+++ b/src/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs
@@ -94,27 +94,97 @@ public static LoggerConfiguration File(
long? fileSizeLimitBytes = DefaultFileSizeLimitBytes,
LoggingLevelSwitch levelSwitch = null,
bool buffered = false)
+ {
+ return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch, buffered);
+ }
+
+ ///
+ /// 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} [{Level}] {Message}{NewLine}{Exception}".
+ /// Configuration object allowing method chaining.
+ /// The file will be written using the UTF-8 character set.
+ public static LoggerConfiguration File(
+ this LoggerAuditSinkConfiguration sinkConfiguration,
+ string path,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ string outputTemplate = DefaultOutputTemplate,
+ IFormatProvider formatProvider = null,
+ LoggingLevelSwitch levelSwitch = 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);
+ }
+
+ ///
+ /// 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.
+ public static LoggerConfiguration File(
+ this LoggerAuditSinkConfiguration sinkConfiguration,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ LoggingLevelSwitch levelSwitch = null)
+ {
+ return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, null, levelSwitch, false, true);
+ }
+
+ static LoggerConfiguration ConfigureFile(
+ this Func addSink,
+ ITextFormatter formatter,
+ string path,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ long? fileSizeLimitBytes = DefaultFileSizeLimitBytes,
+ LoggingLevelSwitch levelSwitch = null,
+ bool buffered = false,
+ bool propagateExceptions = false)
+ {
+ if (addSink == null) throw new ArgumentNullException(nameof(addSink));
if (formatter == null) throw new ArgumentNullException(nameof(formatter));
if (path == null) throw new ArgumentNullException(nameof(path));
+ if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) throw new ArgumentException("Negative value provided; file size limit must be non-negative");
FileSink sink;
try
{
sink = new FileSink(path, formatter, fileSizeLimitBytes, buffered: buffered);
}
- catch (ArgumentException)
- {
- throw;
- }
catch (Exception ex)
{
SelfLog.WriteLine("Unable to open file sink for {0}: {1}", path, ex);
- return sinkConfiguration.Sink(new NullSink());
+
+ if (propagateExceptions)
+ throw;
+
+ return addSink(new NullSink(), LevelAlias.Maximum, null);
}
- return sinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);
+ return addSink(sink, restrictedToMinimumLevel, levelSwitch);
}
}
}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.File/Sinks/File/FileSink.cs b/src/Serilog.Sinks.File/Sinks/File/FileSink.cs
index 8268654..088b5bd 100644
--- a/src/Serilog.Sinks.File/Sinks/File/FileSink.cs
+++ b/src/Serilog.Sinks.File/Sinks/File/FileSink.cs
@@ -16,7 +16,6 @@
using System.IO;
using System.Text;
using Serilog.Core;
-using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting;
@@ -53,7 +52,11 @@ public FileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBy
_textFormatter = textFormatter;
_buffered = buffered;
- TryCreateDirectory(path);
+ var directory = Path.GetDirectoryName(path);
+ if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
var file = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read);
var outputWriter = new StreamWriter(file, encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
@@ -69,22 +72,6 @@ public FileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBy
}
}
- static void TryCreateDirectory(string path)
- {
- try
- {
- var directory = Path.GetDirectoryName(path);
- if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
- {
- Directory.CreateDirectory(directory);
- }
- }
- catch (Exception ex)
- {
- SelfLog.WriteLine("Failed to create directory {0}: {1}", path, ex);
- }
- }
-
///
/// Emit the provided log event to the sink.
///
diff --git a/src/Serilog.Sinks.File/project.json b/src/Serilog.Sinks.File/project.json
index 6acdfb7..bb17847 100644
--- a/src/Serilog.Sinks.File/project.json
+++ b/src/Serilog.Sinks.File/project.json
@@ -9,7 +9,7 @@
"iconUrl": "http://serilog.net/images/serilog-sink-nuget.png"
},
"dependencies": {
- "Serilog": "2.0.0"
+ "Serilog": "2.2.0-dev-00688"
},
"buildOptions": {
"keyFile": "../../assets/Serilog.snk",
diff --git a/test/Serilog.Sinks.File.Tests/FileLoggerConfigurationExtensionsTests.cs b/test/Serilog.Sinks.File.Tests/FileLoggerConfigurationExtensionsTests.cs
new file mode 100644
index 0000000..8dbbdbc
--- /dev/null
+++ b/test/Serilog.Sinks.File.Tests/FileLoggerConfigurationExtensionsTests.cs
@@ -0,0 +1,55 @@
+using System;
+using Serilog;
+using Serilog.Sinks.File.Tests.Support;
+using Serilog.Tests.Support;
+using Xunit;
+
+namespace Serilog.Tests
+{
+ public class FileLoggerConfigurationExtensionsTests
+ {
+ const string InvalidPath = "/\\";
+
+ [Fact]
+ public void WhenWritingCreationExceptionsAreSuppressed()
+ {
+ new LoggerConfiguration()
+ .WriteTo.File(InvalidPath)
+ .CreateLogger();
+ }
+
+ [Fact]
+ public void WhenAuditingCreationExceptionsPropagate()
+ {
+ Assert.Throws(() =>
+ new LoggerConfiguration()
+ .AuditTo.File(InvalidPath)
+ .CreateLogger());
+ }
+
+ [Fact]
+ public void WhenWritingLoggingExceptionsAreSuppressed()
+ {
+ using (var tmp = TempFolder.ForCaller())
+ using (var log = new LoggerConfiguration()
+ .WriteTo.File(new ThrowingLogEventFormatter(), tmp.AllocateFilename())
+ .CreateLogger())
+ {
+ log.Information("Hello");
+ }
+ }
+
+ [Fact]
+ public void WhenAuditingLoggingExceptionsPropagate()
+ {
+ 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());
+ }
+ }
+ }
+}
diff --git a/test/Serilog.Sinks.File.Tests/Sinks/File/FileSinkTests.cs b/test/Serilog.Sinks.File.Tests/FileSinkTests.cs
similarity index 98%
rename from test/Serilog.Sinks.File.Tests/Sinks/File/FileSinkTests.cs
rename to test/Serilog.Sinks.File.Tests/FileSinkTests.cs
index e71cac3..f553494 100644
--- a/test/Serilog.Sinks.File.Tests/Sinks/File/FileSinkTests.cs
+++ b/test/Serilog.Sinks.File.Tests/FileSinkTests.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System;
+using System.IO;
using Xunit;
using Serilog.Formatting.Json;
using Serilog.Sinks.File.Tests.Support;
diff --git a/test/Serilog.Sinks.File.Tests/Support/ThrowingLogEventFormatter.cs b/test/Serilog.Sinks.File.Tests/Support/ThrowingLogEventFormatter.cs
new file mode 100644
index 0000000..9170ef5
--- /dev/null
+++ b/test/Serilog.Sinks.File.Tests/Support/ThrowingLogEventFormatter.cs
@@ -0,0 +1,15 @@
+using System;
+using System.IO;
+using Serilog.Events;
+using Serilog.Formatting;
+
+namespace Serilog.Tests.Support
+{
+ public class ThrowingLogEventFormatter : ITextFormatter
+ {
+ public void Format(LogEvent logEvent, TextWriter output)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}