Skip to content

Commit d4f59ab

Browse files
committed
Merge branch 'dev' of https://github.com/datalust/serilog-sinks-seq into default-unnest
2 parents a4e6e3b + ae06392 commit d4f59ab

File tree

8 files changed

+105
-282
lines changed

8 files changed

+105
-282
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ A Serilog sink that writes events to the [Seq](https://datalust.co/seq) structur
55
[<img alt="Package Logo" src="https://datalust.co/images/seq-nuget.png" width="128px">](https://nuget.org/packages/serilog.sinks.seq)
66

77
> [!TIP]
8-
> If you would like to see timing and dependency information in Seq, [SerilogTracing](https://github.com/serilog-tracing/serilog-tracing) is a Serilog extension that supports both logs and traces.
8+
> If you would like to see timing and dependency information in Seq, [SerilogTracing](https://github.com/serilog-tracing/serilog-tracing) is a Serilog extension that can send both logs and traces through this sink.
99
1010

1111
### Getting started

src/Serilog.Sinks.Seq/Sinks/Seq/Durable/BookmarkFile.cs

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ sealed class BookmarkFile : IDisposable
2424

2525
public BookmarkFile(string bookmarkFilename)
2626
{
27+
var directory = Path.GetDirectoryName(bookmarkFilename);
28+
if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
29+
{
30+
Directory.CreateDirectory(directory);
31+
}
32+
2733
_bookmark = System.IO.File.Open(bookmarkFilename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
2834
}
2935

src/Serilog.Sinks.Seq/Sinks/Seq/Formatting/CleanMessageTemplateFormatter.cs

-146
This file was deleted.

src/Serilog.Sinks.Seq/Sinks/Seq/Formatting/Padding.cs

-54
This file was deleted.

src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs

+11-51
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
using Serilog.Formatting.Json;
2323
using Serilog.Parsing;
2424
using Serilog.Sinks.Seq.Conventions;
25-
using Serilog.Sinks.Seq.Formatting;
26-
2725
// ReSharper disable MemberCanBePrivate.Global
2826
// ReSharper disable PossibleMultipleEnumeration
2927

@@ -36,82 +34,43 @@ namespace Serilog.Sinks.Seq;
3634
/// implicit SerilogTracing span support.</remarks>
3735
public sealed class SeqCompactJsonFormatter: ITextFormatter
3836
{
39-
static readonly IDottedPropertyNameConvention DefaultDottedPropertyNameConvention =
40-
new UnflattenDottedPropertyNames();
41-
42-
readonly JsonValueFormatter _valueFormatter = new("$type");
37+
readonly JsonValueFormatter _valueFormatter;
4338
readonly IFormatProvider _formatProvider;
4439
readonly IDottedPropertyNameConvention _dottedPropertyNameConvention;
4540

4641
/// <summary>
47-
/// Create a <see cref="SeqCompactJsonFormatter"/>.
48-
/// </summary>
49-
/// <param name="formatProvider">An <see cref="IFormatProvider"/> that will be used to render log event tokens.</param>
50-
public SeqCompactJsonFormatter(IFormatProvider? formatProvider = null)
51-
: this(formatProvider, false)
52-
{
53-
}
54-
55-
/// <summary>
56-
/// Create a <see cref="SeqCompactJsonFormatter"/>.
42+
/// Construct a <see cref="SeqCompactJsonFormatter"/>.
5743
/// </summary>
44+
/// <param name="valueFormatter">A value formatter for <see cref="LogEventPropertyValue"/>s on the event.</param>
5845
/// <param name="formatProvider">An <see cref="IFormatProvider"/> that will be used to render log event tokens.</param>
5946
/// <param name="preserveDottedPropertyNames">If <c langword="true"/>, log event property names that
6047
/// contain <c>.</c> will be sent to Seq as-is. Otherwise, properties with dotted names will be converted
6148
/// into nested objects.</param>
62-
public SeqCompactJsonFormatter(IFormatProvider? formatProvider, bool preserveDottedPropertyNames)
49+
public SeqCompactJsonFormatter(IFormatProvider? formatProvider = null, JsonValueFormatter? valueFormatter = null, bool preserveDottedPropertyNames = false)
6350
{
6451
_formatProvider = formatProvider ?? CultureInfo.InvariantCulture;
52+
_valueFormatter = valueFormatter ?? new("$type");
6553
_dottedPropertyNameConvention = preserveDottedPropertyNames
6654
? new PreserveDottedPropertyNames()
6755
: new UnflattenDottedPropertyNames();
6856
}
6957

7058
/// <summary>
71-
/// Format the log event into the output. Subsequent events will be newline-delimited.
59+
/// Format the log event into the output. Successive events will be newline-delimited.
7260
/// </summary>
7361
/// <param name="logEvent">The event to format.</param>
7462
/// <param name="output">The output.</param>
7563
public void Format(LogEvent logEvent, TextWriter output)
76-
{
77-
FormatEvent(logEvent, output, _valueFormatter, _formatProvider, _dottedPropertyNameConvention);
78-
output.WriteLine();
79-
}
80-
81-
/// <summary>
82-
/// Format the log event into the output.
83-
/// </summary>
84-
/// <param name="logEvent">The event to format.</param>
85-
/// <param name="output">The output.</param>
86-
/// <param name="valueFormatter">A value formatter for <see cref="LogEventPropertyValue"/>s on the event.</param>
87-
/// <param name="formatProvider">An <see cref="IFormatProvider"/> that will be used to render log event tokens.</param>
88-
public static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFormatter valueFormatter, IFormatProvider formatProvider)
89-
{
90-
FormatEvent(logEvent, output, valueFormatter, formatProvider, DefaultDottedPropertyNameConvention);
91-
}
92-
93-
static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFormatter valueFormatter, IFormatProvider formatProvider, IDottedPropertyNameConvention dottedPropertyNameConvention)
9464
{
9565
if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
9666
if (output == null) throw new ArgumentNullException(nameof(output));
97-
if (valueFormatter == null) throw new ArgumentNullException(nameof(valueFormatter));
9867

9968
output.Write("{\"@t\":\"");
10069
output.Write(logEvent.Timestamp.UtcDateTime.ToString("O"));
10170

10271
output.Write("\",\"@mt\":");
10372
JsonValueFormatter.WriteQuotedJsonString(logEvent.MessageTemplate.Text, output);
10473

105-
if (!formatProvider.Equals(CultureInfo.InvariantCulture))
106-
{
107-
// `@m` is normally created during ingestion, however, it must be sent from the client
108-
// to honour non-default IFormatProviders
109-
output.Write(",\"@m\":");
110-
JsonValueFormatter.WriteQuotedJsonString(
111-
CleanMessageTemplateFormatter.Format(logEvent.MessageTemplate, logEvent.Properties, formatProvider),
112-
output);
113-
}
114-
11574
var tokensWithFormat = logEvent.MessageTemplate.Tokens
11675
.OfType<PropertyToken>()
11776
.Where(pt => pt.Format != null);
@@ -127,9 +86,10 @@ static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFormatter
12786
output.Write(delim);
12887
delim = ",";
12988
var space = new StringWriter();
130-
r.Render(logEvent.Properties, space, formatProvider);
89+
r.Render(logEvent.Properties, space, _formatProvider);
13190
JsonValueFormatter.WriteQuotedJsonString(space.ToString(), output);
13291
}
92+
13393
output.Write(']');
13494
}
13595

@@ -189,7 +149,7 @@ static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFormatter
189149
}
190150
}
191151

192-
var properties = dottedPropertyNameConvention.ProcessDottedPropertyNames(logEvent.Properties);
152+
var properties = _dottedPropertyNameConvention.ProcessDottedPropertyNames(logEvent.Properties);
193153
foreach (var property in properties)
194154
{
195155
var name = property.Key;
@@ -206,9 +166,9 @@ static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFormatter
206166
output.Write(',');
207167
JsonValueFormatter.WriteQuotedJsonString(name, output);
208168
output.Write(':');
209-
valueFormatter.Format(property.Value, output);
169+
_valueFormatter.Format(property.Value, output);
210170
}
211171

212172
output.Write('}');
213173
}
214-
}
174+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.IO;
3+
using System.Net;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Serilog.Sinks.Seq.Durable;
7+
using Serilog.Sinks.Seq.Http;
8+
using Serilog.Sinks.Seq.Tests.Support;
9+
using Xunit;
10+
11+
namespace Serilog.Sinks.Seq.Tests.Durable;
12+
13+
public class DurableSeqSinkTests
14+
{
15+
[Fact]
16+
public void SinkCanBeDisposedCleanlyWhenUnused()
17+
{
18+
var path = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("n"), "buffer");
19+
var sink = new DurableSeqSink(
20+
new TestIngestionApi(_ => Task.FromResult(new IngestionResult(true, HttpStatusCode.Accepted, null))),
21+
new SeqCompactJsonFormatter(),
22+
path,
23+
100,
24+
TimeSpan.FromSeconds(1),
25+
null,
26+
null,
27+
new ControlledLevelSwitch(),
28+
null);
29+
30+
// No events written, so files/paths should not exist;
31+
Assert.False(Directory.Exists(path));
32+
33+
using var collector = new SelfLogCollector();
34+
sink.Dispose();
35+
Assert.Empty(collector.Messages);
36+
}
37+
}

0 commit comments

Comments
 (0)