Skip to content

Add ability to capture path of log file opened, via FileLifecycleHooks #189

New issue

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

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

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Serilog.Sinks.File/Sinks/File/FileLifeCycleHookChain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ public FileLifeCycleHookChain(FileLifecycleHooks first, FileLifecycleHooks secon
_second = second ?? throw new ArgumentNullException(nameof(second));
}

public override Stream OnFileOpened(Stream underlyingStream, Encoding encoding)
public override Stream OnFileOpened(string path, Stream underlyingStream, Encoding encoding)
{
var firstStreamResult = _first.OnFileOpened(underlyingStream, encoding);
var secondStreamResult = _second.OnFileOpened(firstStreamResult, encoding);
var firstStreamResult = _first.OnFileOpened(path, underlyingStream, encoding);
var secondStreamResult = _second.OnFileOpened(path, firstStreamResult, encoding);

return secondStreamResult;
}
Expand Down
15 changes: 15 additions & 0 deletions src/Serilog.Sinks.File/Sinks/File/FileLifecycleHooks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ namespace Serilog.Sinks.File
/// </summary>
public abstract class FileLifecycleHooks
{
/// <summary>
/// Initialize or wrap the <paramref name="underlyingStream"/> 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.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <param name="path">The full path to the log file.</param>
/// <param name="underlyingStream">The underlying <see cref="Stream"/> opened on the log file.</param>
/// <param name="encoding">The encoding to use when reading/writing to the stream.</param>
/// <returns>The <see cref="Stream"/> Serilog should use when writing events to the log file.</returns>
public virtual Stream OnFileOpened(string path, Stream underlyingStream, Encoding encoding) => OnFileOpened(underlyingStream, encoding);

/// <summary>
/// Initialize or wrap the <paramref name="underlyingStream"/> 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
Expand Down
2 changes: 1 addition & 1 deletion src/Serilog.Sinks.File/Sinks/File/FileSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ internal FileSink(

if (hooks != null)
{
outputStream = hooks.OnFileOpened(outputStream, encoding) ??
outputStream = hooks.OnFileOpened(path, outputStream, encoding) ??
throw new InvalidOperationException($"The file lifecycle hook `{nameof(FileLifecycleHooks.OnFileOpened)}(...)` returned `null`.");
}

Expand Down
17 changes: 17 additions & 0 deletions test/Serilog.Sinks.File.Tests/FileSinkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,23 @@ public static void OnOpenedLifecycleHookCanWriteFileHeader()
}
}

[Fact]
public static void OnOpenedLifecycleHookCanCaptureFilePath()
{
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
}

Assert.Equal(path, capturePath.Path);
}
}

static void WriteTwoEventsAndCheckOutputFileLength(long? maxBytes, Encoding encoding)
{
using (var tmp = TempFolder.ForCaller())
Expand Down
20 changes: 20 additions & 0 deletions test/Serilog.Sinks.File.Tests/Support/CaptureFilePathHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.IO;
using System.Text;

namespace Serilog.Sinks.File.Tests.Support
{
/// <inheritdoc />
/// <summary>
/// Demonstrates the use of <seealso cref="T:Serilog.FileLifecycleHooks" />, by capturing the log file path
/// </summary>
class CaptureFilePathHook : FileLifecycleHooks
{
public string Path { get; private set; }

public override Stream OnFileOpened(string path, Stream _, Encoding __)
{
Path = path;
return base.OnFileOpened(path, _, __);
}
}
}