Skip to content

Commit 00e3e94

Browse files
authored
Merge branch 'dev' into dev
2 parents 1b863ff + 1093c3b commit 00e3e94

File tree

7 files changed

+72
-6
lines changed

7 files changed

+72
-6
lines changed

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ artifacts:
1919
deploy:
2020
- provider: NuGet
2121
api_key:
22-
secure: bd9z4P73oltOXudAjPehwp9iDKsPtC+HbgshOrSgoyQKr5xVK+bxJQngrDJkHdY8
22+
secure: N59tiJECUYpip6tEn0xvdmDAEiP9SIzyLEFLpwiigm/8WhJvBNs13QxzT1/3/JW/
2323
skip_symbols: true
2424
on:
2525
branch: /^(master|dev)$/

src/Serilog.Sinks.File/Serilog.Sinks.File.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<Description>Write Serilog events to text files in plain or JSON format.</Description>
5-
<VersionPrefix>4.1.0</VersionPrefix>
5+
<VersionPrefix>5.0.0</VersionPrefix>
66
<Authors>Serilog Contributors</Authors>
77
<TargetFrameworks>net45;netstandard1.3;netstandard2.0</TargetFrameworks>
88
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -30,7 +30,7 @@
3030
</PropertyGroup>
3131

3232
<ItemGroup>
33-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-63127-02" PrivateAssets="All" />
33+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
3434
<PackageReference Include="Serilog" Version="2.5.0" />
3535
</ItemGroup>
3636

src/Serilog.Sinks.File/Sinks/File/FileLifecycleHooks.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace Serilog.Sinks.File
1919
{
2020
/// <summary>
2121
/// Enables hooking into log file lifecycle events.
22+
/// Hooks run synchronously and therefore may affect responsiveness of the application if long operations are performed.
2223
/// </summary>
2324
public abstract class FileLifecycleHooks
2425
{
@@ -35,5 +36,12 @@ public abstract class FileLifecycleHooks
3536
/// <param name="encoding">The encoding to use when reading/writing to the stream.</param>
3637
/// <returns>The <see cref="Stream"/> Serilog should use when writing events to the log file.</returns>
3738
public virtual Stream OnFileOpened(Stream underlyingStream, Encoding encoding) => underlyingStream;
39+
40+
/// <summary>
41+
/// Called before an obsolete (rolling) log file is deleted.
42+
/// This can be used to copy old logs to an archive location or send to a backup server.
43+
/// </summary>
44+
/// <param name="path">The full path to the file being deleted.</param>
45+
public virtual void OnFileDeleting(string path) {}
3846
}
3947
}

src/Serilog.Sinks.File/Sinks/File/PathRoller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ public PathRoller(string path, RollingInterval interval)
5252
"(?<" + PeriodMatchGroup + ">\\d{" + _periodFormat.Length + "})" +
5353
"(?<" + SequenceNumberMatchGroup + ">_[0-9]{3,}){0,1}" +
5454
Regex.Escape(_filenameSuffix) +
55-
"$");
55+
"$",
56+
RegexOptions.Compiled);
5657

5758
DirectorySearchPattern = $"{_filenamePrefix}*{_filenameSuffix}";
5859
}

src/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,12 @@ void ApplyRetentionPolicy(string currentFilePath, DateTime now)
204204
var fullPath = Path.Combine(_roller.LogFileDirectory, obsolete);
205205
try
206206
{
207+
_hooks?.OnFileDeleting(fullPath);
207208
System.IO.File.Delete(fullPath);
208209
}
209210
catch (Exception ex)
210211
{
211-
SelfLog.WriteLine("Error {0} while removing obsolete log file {1}", ex, fullPath);
212+
SelfLog.WriteLine("Error {0} while processing obsolete log file {1}", ex, fullPath);
212213
}
213214
}
214215
}

test/Serilog.Sinks.File.Tests/RollingFileSinkTests.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.IO;
44
using System.IO.Compression;
@@ -127,6 +127,27 @@ public void WhenRetentionCountAndTimeIsSetOldFilesAreDeletedByCount()
127127
Assert.True(System.IO.File.Exists(files[2]));
128128
});
129129
}
130+
131+
[Fact]
132+
public void WhenRetentionCountAndArchivingHookIsSetOldFilesAreCopiedAndOriginalDeleted()
133+
{
134+
const string archiveDirectory = "OldLogs";
135+
LogEvent e1 = Some.InformationEvent(),
136+
e2 = Some.InformationEvent(e1.Timestamp.AddDays(1)),
137+
e3 = Some.InformationEvent(e2.Timestamp.AddDays(5));
138+
139+
TestRollingEventSequence(
140+
(pf, wt) => wt.File(pf, retainedFileCountLimit: 2, rollingInterval: RollingInterval.Day, hooks: new ArchiveOldLogsHook(archiveDirectory)),
141+
new[] {e1, e2, e3},
142+
files =>
143+
{
144+
Assert.Equal(3, files.Count);
145+
Assert.True(!System.IO.File.Exists(files[0]));
146+
Assert.True(System.IO.File.Exists(files[1]));
147+
Assert.True(System.IO.File.Exists(files[2]));
148+
Assert.True(System.IO.File.Exists(ArchiveOldLogsHook.AddTopDirectory(files[0], archiveDirectory)));
149+
});
150+
}
130151

131152
[Fact]
132153
public void WhenSizeLimitIsBreachedNewFilesCreated()
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.IO;
3+
using System.Text;
4+
5+
namespace Serilog.Sinks.File.Tests.Support
6+
{
7+
internal class ArchiveOldLogsHook : FileLifecycleHooks
8+
{
9+
private readonly string _relativeArchiveDir;
10+
11+
public ArchiveOldLogsHook(string relativeArchiveDir)
12+
{
13+
_relativeArchiveDir = relativeArchiveDir;
14+
}
15+
16+
public override void OnFileDeleting(string path)
17+
{
18+
base.OnFileDeleting(path);
19+
var newFile = AddTopDirectory(path, _relativeArchiveDir, true);
20+
System.IO.File.Copy(path, newFile, false);
21+
}
22+
23+
public static string AddTopDirectory(string path, string directoryToAdd, bool createOnNonExist = false)
24+
{
25+
string file = Path.GetFileName(path);
26+
string directory = Path.Combine(Path.GetDirectoryName(path) ?? throw new InvalidOperationException(), directoryToAdd);
27+
28+
if (createOnNonExist && !Directory.Exists(directory))
29+
{
30+
Directory.CreateDirectory(directory);
31+
}
32+
return Path.Combine(directory, file);
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)