Simple .NET logging with fully-structured events
ReusableStringWriter
with large renderings (@nblumhardt)This is a bugfix for release 3.1.0.
CHANGES.md
(@sungam3r)README.md
updates (@nblumhardt)GetTypeInfo()
calls (@SimonCropp)Logger.Write()
(@epeshk)Activity.Current.TraceId
and SpanId
automatically in Logger.Write()
(@nblumhardt)README.md
updates (@bartelink)This release adds two new first-class properties to LogEvent
: TraceId
and SpanId
. These are set automatically in Logger.Write()
to the corresponding property values from System.Diagnostics.Activity.Current
.
The major benefit of this change is that sinks, once updated, can reliably propagate trace and span ids through to back-ends that support them (in much the same way that first-class timestamps, messages, levels, and exceptions are used today).
The sinks maintained under serilog/serilog
, along with formatting helpers such as Serilog.Formatting.Compact and Serilog.Expressions, are already compatible with this change or have pending releases that add compatibility.
On .NET Core 2.1 and 3.0, projects targeting Serilog 3.1+ will fail to build, with:
/project/packages/system.runtime.compilerservices.unsafe/6.0.0/buildTransitive/netcoreapp2.0
/System.Runtime.CompilerServices.Unsafe.targets(4,5): error : System.Runtime.CompilerServices.Unsafe
doesn't support netcoreapp2.1. Consider updating your TargetFramework to netcoreapp3.1 or later.
Affected consumers should continue to use Serilog 3.0 or earlier. See https://github.com/serilog/serilog/issues/1983 for a discussion of this issue.
Trace and span id collection includes support for {TraceId}
and {SpanId}
placeholders in output templates (commonly used when formatting text log files). Where previously these names resolved to user-defined properties, they now resolve to the built-in LogEvent.TraceId
and LogEvent.SpanId
values, respectively.
Impact is expected to be low/zero, because the trace and span id values in any user-added properties are almost certainly identical to the built-in ones.
JsonFormatter
output for renderMessage = true
(@nblumhardt)Target framework changes - Serilog no longer targets netstandard1.x
or .NET Framework versions earlier than .NET 4.6.2. Users on affected frameworks should continue to target Serilog 2.12.x.
Removed obsolete APIs - Many deprecated/obsolete types and functions have been removed. Notably, JsonFormatter
can no longer be subclassed (either port to JsonValueFormatter
, use Serilog.Expressions, or copy the original JsonFormatter
code into your project).
Added APIs - LevelAlias.Off
is now provided as an equivalent to Microsoft.Extensions.Logging's LogLevel.Off
; Destructure.AsDictionary<T>()
can now be used to mark dictionary types.
Fewer allocations on many hot paths - A lot of work has gone into avoiding heap allocations wherever possible.
IEnumerator
allocation (#1769) by @igor84 in https://github.com/serilog/serilog/pull/1770
ScalarValue.Null
by @sungam3r in https://github.com/serilog/serilog/pull/1774
Tokens
-> TokenArray
by @sungam3r in https://github.com/serilog/serilog/pull/1778
netstandard1.3
and netstandard1.0
support by @SimonCropp in https://github.com/serilog/serilog/pull/1807
JsonFormatter.Escape
by @SimonCropp in https://github.com/serilog/serilog/pull/1804
WriteLine(char)
by @SimonCropp in https://github.com/serilog/serilog/pull/1803
JsonFormatter
by subclassing by @SimonCropp in https://github.com/serilog/serilog/pull/1801
LoggerSinkConfiguration
by @SimonCropp in https://github.com/serilog/serilog/pull/1800
StringWriter.ToString()
calls by @sungam3r in https://github.com/serilog/serilog/pull/1782
RawFormatter
type by @nblumhardt in https://github.com/serilog/serilog/pull/1808
OutputProperties.GetOutputProperties()
by @SimonCropp in https://github.com/serilog/serilog/pull/1805
Where()
calls in FindConfigurationMethods()
by @SimonCropp in https://github.com/serilog/serilog/pull/1812
net45
support by @SimonCropp in https://github.com/serilog/serilog/pull/1811
GetTypeInfo()
in LoadConfigurationAssemblies
by @SimonCropp in https://github.com/serilog/serilog/pull/1817
GetTypeInfo()
from FindConfigurationMethods(()
by @SimonCropp in https://github.com/serilog/serilog/pull/1815
GetTypeInfo()
in EnumScalarConversionPolicy
by @SimonCropp in https://github.com/serilog/serilog/pull/1816
PropertyToken
constructor by @SimonCropp in https://github.com/serilog/serilog/pull/1819
switch
expressions by @SimonCropp in https://github.com/serilog/serilog/pull/1818
TextWriter.Write()
by @sungam3r in https://github.com/serilog/serilog/pull/1775
SettingValueConversions
by @SimonCropp in https://github.com/serilog/serilog/pull/1814
GetPropertiesRecursive()
performance by @SimonCropp in https://github.com/serilog/serilog/pull/1813
Convert.ToHexString()
in ByteArrayScalarConversionPolicy()
by @sungam3r in https://github.com/serilog/serilog/pull/1776
FEATURE_ASYNCLOCAL
by @SimonCropp in https://github.com/serilog/serilog/pull/1822
FEATURE_HASHTABLE
by @SimonCropp in https://github.com/serilog/serilog/pull/1823
IsEnum
for enum check in EnumScalarConversionPolicy
by @SimonCropp in https://github.com/serilog/serilog/pull/1825
Hashtable
use in MessageTemplateCache
by @SimonCropp in https://github.com/serilog/serilog/pull/1828
GetTypeInfo()
from PropertyValueConverter
by @SimonCropp in https://github.com/serilog/serilog/pull/1824
GetType()
in PropertyValueConverter
by @SimonCropp in https://github.com/serilog/serilog/pull/1832
TryAdd()
and items constructor by @SimonCropp in https://github.com/serilog/serilog/pull/1830
PropertyValueConverter
by @SimonCropp in https://github.com/serilog/serilog/pull/1831
net46
target to net461
by @SimonCropp in https://github.com/serilog/serilog/pull/1827
JsonValueFormatter
by @SimonCropp in https://github.com/serilog/serilog/pull/1835
var
in JsonFormatter
by @SimonCropp in https://github.com/serilog/serilog/pull/1838
SelfLog.Out
by @SimonCropp in https://github.com/serilog/serilog/pull/1837
JsonFormatter
omitEnclosingObject
overload by @SimonCropp in https://github.com/serilog/serilog/pull/1834
PushProperties()
by @SimonCropp in https://github.com/serilog/serilog/pull/1836
_minimumLevel
and _levelSwitch
on stack by @SimonCropp in https://github.com/serilog/serilog/pull/1840
int
where possible by @SimonCropp in https://github.com/serilog/serilog/pull/1841
JsonFormatter
by @SimonCropp in https://github.com/serilog/serilog/pull/1839
char
in JsonFormatter
by @sungam3r in https://github.com/serilog/serilog/pull/1842
net471
DisableImplicitFrameworkReferences
by @SimonCropp in https://github.com/serilog/serilog/pull/1846
TargetFramework
constants in tests by @SimonCropp in https://github.com/serilog/serilog/pull/1847
net471
supports ITuple
by @SimonCropp in https://github.com/serilog/serilog/pull/1849
FEATURE_GETCURRENTMETHOD
const by @SimonCropp in https://github.com/serilog/serilog/pull/1851
PublicApi_Should_Not_Change_Unintentionally()
test by @SimonCropp in https://github.com/serilog/serilog/pull/1864
net461
to net462
by @SimonCropp in https://github.com/serilog/serilog/pull/1863
GetPackagingOutputs
by @SimonCropp in https://github.com/serilog/serilog/pull/1867
ReusableStringWriter
by @igor84 in https://github.com/serilog/serilog/pull/1771
langword
in XML comments by @sungam3r in https://github.com/serilog/serilog/pull/1871
SafeAggregateSink
wrapper around empty list by @sungam3r in https://github.com/serilog/serilog/pull/1878
Alignment
and LevelOverrides
readonly by @sungam3r in https://github.com/serilog/serilog/pull/1884
CallerArgumentExpressionAttribute
by @SimonCropp in https://github.com/serilog/serilog/pull/1886
MessageTemplateToken.StartIndex
by @SimonCropp in https://github.com/serilog/serilog/pull/1882
LoggerSinkConfiguration.Sink(ILogEventSink, LogEventLevel)
by @nblumhardt in https://github.com/serilog/serilog/pull/1889
Array.Empty
by @SimonCropp in https://github.com/serilog/serilog/pull/1898
ReadOnlyDictionary
as Dictionary
by @sungam3r in https://github.com/serilog/serilog/pull/1897
IDictionary
cast by @SimonCropp in https://github.com/serilog/serilog/pull/1900
WriteTo.Logger()
by @srogovtsev in https://github.com/serilog/serilog/pull/1890
AddPropertyIfAbsent
by @sungam3r in https://github.com/serilog/serilog/pull/1872
levelSwitch
option in WriteTo.Logger()
by @nblumhardt in https://github.com/serilog/serilog/pull/1902
net47
target by @SimonCropp in https://github.com/serilog/serilog/pull/1905
WithProperty()
by @sungam3r in https://github.com/serilog/serilog/pull/1907
LoggingLevelSwitch.MinimumLevelChanged
by @sungam3r in https://github.com/serilog/serilog/pull/1908
Destructure.AsDictionary<T>()
by @sungam3r in https://github.com/serilog/serilog/pull/1906
LevelAlias.Off
; fixes #1684 by @nblumhardt in https://github.com/serilog/serilog/pull/1910
JsonValueFormatter
to implement classic JsonFormatter
by @nblumhardt in https://github.com/serilog/serilog/pull/1911
README.md
in the NuGet package for display on nuget.org by @nblumhardt in https://github.com/serilog/serilog/pull/1916
<Nullable>enable</Nullable>
supportA huge number of commits have gone into completing and refining non-null reference type annotations, which now cover the entire public Serilog API. The Serilog project itself now builds with non-null reference type checking globally enabled :tada:
IAsyncDisposable
supportSinks that need to flush changes using asynchronous APIs can now implement IAsyncDisposable
and prevent the possibility of deadlocking while waiting for tasks to complete.
To drive this, Logger
can now be disposed via using async
:
await using var log = new LoggerConfiguration().CreateLogger();
and the Log
class provides Log.CloseAndFlushAsync()
:
await Log.CloseAndFlushAsync();
DateOnly
and TimeOnly
supportThe DateOnly
and TimeOnly
types introduced in .NET 6 are now correctly handled as scalar values when capturing.
DateOnly
and TimeOnly
support (@SimonCropp)IAsyncDisposable
support for Logger
and sinks (@nblumhardt)!
operator from null
in conditions (@sungam3r)ValueTuple
(@SimonCropp)static
to avoid scope capture (@SimonCropp)string[]
to key-value settings (@stochmal)net5.0
target (@nblumhardt)MessageTemplateFormatMethod
(@JinsPeter)Memory<T>
/ReadOnlyMemory<T>
and non-reflection-compatible properties e.g. of type Span<T>
(@skomis-mm)ILogger
documentation (@erichiller)ToString()
throws an exception (@rafaelsc)netstandard2.1
support and default implementations for ILogger
methods (@skomis-mm)MinimumLevel.Override()
runtime optimizations (@skomis-mm)LoggerSinkConfiguration.Wrap()
ToString()
on a logged object returns null
, serialize as ""
(@rafaelsc, @nblumhardt)snupkg
symbol packages (@teo-tsirpanis)MessageTemplateTextFormatter
(@bender2k14)netstandard2.0
target (@WeihanLi)INFLUENCES.md
(@nblumhardt)+
(@martinh2011)Destructure.AsScalar(type)
in key-value settings (@tsimbalar)Destructure.Xxx()
in key-value settings (@tsimbalar)Destructure.With(policy)
in key-value settings (@tsimbalar)Logger.Instance
with Logger.None
(@ie-zero)*.With(...)
and AuditTo.Sink(sink)
/WriteTo.Sink(sink)
in key-value settings (@tsimbalar)repositoryUrl
in the NuGet package (@MaximRouiller)netcoreapp2.0
(@merbla)IFormatProvider
support (@tsimbalar)ForContext()
to destructure some generated proxy types (@balayoglu)netstandard2.0
target to shrink dependency graph on compatible platforms (@nblumhardt)