Skip to content

Commit

Permalink
Add UTF-8 SpanFormattable support (#83)
Browse files Browse the repository at this point in the history
* Add UTF-8 SpanFormattable support

* Fix default timespan format

* Bump net48 to net481 for tests and benchmarks

* Update benchmark
  • Loading branch information
alexaka1 authored Aug 26, 2024
1 parent 8b8bf08 commit ee9314c
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/new-seas-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"alexaka1.serilog.extensions.formatting": minor
---

Add IUtf8SpanFormattable support as fallback option
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@
<DefineConstants>$(DefineConstants);FEATURE_SPAN;FEATURE_DATE_AND_TIME_ONLY;FEATURE_ISPANFORMATTABLE;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<DefineConstants>$(DefineConstants);FEATURE_SPAN;FEATURE_DATE_AND_TIME_ONLY;FEATURE_ISPANFORMATTABLE;FEATURE_JSON_NAMING_POLICY;</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_SPAN;FEATURE_DATE_AND_TIME_ONLY;FEATURE_ISPANFORMATTABLE;FEATURE_JSON_NAMING_POLICY;FEATURE_IUTF8SPANFORMATTABLE;</DefineConstants>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## Utf8JsonFormatter

A simple JSON formatter for Serilog that uses the `System.Text.Json.Utf8JsonWriter` to write the log events to the output stream.
A simple JSON formatter for Serilog that uses the `System.Text.Json.Utf8JsonWriter` to write the log events to the output stream. As the name suggests, it is entirely built around UTF-8, with all the [.NET optimizations for UTF-8](https://github.com/dotnet/runtime/issues/81500), so using other encodings will most likely result in invalid characters. The default for the File sink is UTF-8.

### Usage

Expand Down
40 changes: 37 additions & 3 deletions src/Serilog.Extensions.Formatting/Utf8JsonFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class Utf8JsonFormatter : ITextFormatter, IDisposable, IAsyncDisposable
private readonly StringWriter _sw;
private readonly Utf8JsonWriter _writer;
private const string TimeFormat = "O";
private const string TimeSpanFormat = "c";
#if FEATURE_DATE_AND_TIME_ONLY
private const string DateOnlyFormat = "O";
#endif
Expand Down Expand Up @@ -339,15 +340,23 @@ private void VisitScalarValue(ScalarValue value)
break;
case TimeSpan timeSpan:
{
#if FEATURE_ISPANFORMATTABLE
#if FEATURE_IUTF8SPANFORMATTABLE
Span<byte> buffer = stackalloc byte[_spanBufferSize];
if (timeSpan.TryFormat(buffer, out int written, formatProvider: _formatProvider,
format: TimeSpanFormat))
{
// fallback to string
_writer.WriteStringValue(Encoding.UTF8.GetString(buffer.Slice(0, written)));
}
#elif FEATURE_ISPANFORMATTABLE
Span<char> buffer = stackalloc char[_spanBufferSize];
if (timeSpan.TryFormat(buffer, out int written, formatProvider: _formatProvider,
format: "c"))
format: TimeSpanFormat))
{
_writer.WriteStringValue(buffer.Slice(0, written));
}
#else
_writer.WriteStringValue(timeSpan.ToString("c", _formatProvider));
_writer.WriteStringValue(timeSpan.ToString(TimeSpanFormat, _formatProvider));
#endif

break;
Expand Down Expand Up @@ -387,6 +396,18 @@ private void VisitScalarValue(ScalarValue value)
{
_writer.WriteStringValue(vt.ToString());
}
#if FEATURE_IUTF8SPANFORMATTABLE
else if (vt is IUtf8SpanFormattable utf8Span)
{
Span<byte> buffer = stackalloc byte[_spanBufferSize * 2];
if (utf8Span.TryFormat(buffer, out int written, provider: _formatProvider,
format: default))
{
// fallback to string
_writer.WriteStringValue(Encoding.UTF8.GetString(buffer.Slice(0, written)));
}
}
#endif
#if FEATURE_ISPANFORMATTABLE
else if (vt is ISpanFormattable span)
{
Expand All @@ -404,6 +425,19 @@ private void VisitScalarValue(ScalarValue value)
}

break;
#if FEATURE_IUTF8SPANFORMATTABLE
case IUtf8SpanFormattable span:
{
Span<byte> buffer = stackalloc byte[_spanBufferSize * 4];
if (span.TryFormat(buffer, out int written, provider: _formatProvider, format: default))
{
// fallback to string
_writer.WriteStringValue(buffer.Slice(0, written));
}

break;
}
#endif
#if FEATURE_ISPANFORMATTABLE
case ISpanFormattable span:
{
Expand Down
6 changes: 5 additions & 1 deletion test/Serilog.Extensions.Formatting.Benchmark/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```shell
dotnet run -c Release -f net8.0 -- -f * --r net8.0 net6.0 net48
dotnet run -c Release -f net8.0 -- -f * -r net481 net6.0 --join
```

```shell
dotnet run -c Release -f net481 -- -f * -r net481 --join
```
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net6.0;net48;net472</TargetFrameworks>
<TargetFrameworks>net8.0;net6.0;net481;net472</TargetFrameworks>
<OutputType>Exe</OutputType>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@
}
}
},
".NETFramework,Version=v4.8": {
".NETFramework,Version=v4.8.1": {
"BenchmarkDotNet": {
"type": "Direct",
"requested": "[0.14.0, )",
Expand Down Expand Up @@ -890,7 +890,7 @@
}
}
},
".NETFramework,Version=v4.8/win7-x86": {
".NETFramework,Version=v4.8.1/win7-x86": {
"Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.3.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net6.0;net48;net472</TargetFrameworks>
<TargetFrameworks>net8.0;net6.0;net481;net472</TargetFrameworks>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ public void AnISpanFormattablePropertySerializesAsStringValue()
public void AnISpanFormattablePropertySerializesAsStringValueNet6()
{
string name = Some.String();
var value = Version.Parse("1.2.3.4");
var value = new Uri("https://www.google.com");
var @event = Some.InformationEvent();
@event.AddOrUpdateProperty(new LogEventProperty(name, new ScalarValue(value)));

Expand Down
2 changes: 1 addition & 1 deletion test/Serilog.Extensions.Formatting.Test/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
}
}
},
".NETFramework,Version=v4.8": {
".NETFramework,Version=v4.8.1": {
"coverlet.collector": {
"type": "Direct",
"requested": "[6.0.2, )",
Expand Down

0 comments on commit ee9314c

Please sign in to comment.