Skip to content

Commit 6846f43

Browse files
committed
SerilogLogValues to clean up provision of TState; re-version as 3.0.0-* and limit dependencies
1 parent ad31fe8 commit 6846f43

File tree

7 files changed

+139
-52
lines changed

7 files changed

+139
-52
lines changed

samples/Sample/Sample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
55
<AssemblyName>Sample</AssemblyName>
66
<OutputType>Exe</OutputType>
77
<PackageId>Sample</PackageId>

src/Serilog.Extensions.Logging/Extensions/Logging/LevelMapping.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
using Microsoft.Extensions.Logging;
1+
// Copyright 2019 Serilog Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using Microsoft.Extensions.Logging;
216
using Serilog.Events;
317

418
namespace Serilog.Extensions.Logging

src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,8 @@
1313
// limitations under the License.
1414

1515
using System;
16-
using System.Linq;
17-
using Microsoft.Extensions.Logging;
18-
using Microsoft.Extensions.Logging.Internal;
1916
using Serilog.Core;
2017
using Serilog.Events;
21-
using Serilog.Parsing;
2218

2319
namespace Serilog.Extensions.Logging
2420
{
@@ -42,29 +38,17 @@ sourceContextProperty is ScalarValue sourceContextValue &&
4238
categoryName = sourceContext;
4339
}
4440

45-
// Allocates like mad, but first make it work, then make it work fast ;-)
46-
var flv = new FormattedLogValues(
47-
logEvent.MessageTemplate.Text,
48-
logEvent.MessageTemplate.Tokens
49-
.OfType<PropertyToken>()
50-
.Select(p =>
51-
{
52-
if (!logEvent.Properties.TryGetValue(p.PropertyName, out var value))
53-
return null;
54-
if (value is ScalarValue sv)
55-
return sv.Value;
56-
return value;
57-
})
58-
.ToArray());
41+
var level = LevelMapping.ToExtensionsLevel(logEvent.Level);
42+
var slv = new SerilogLogValues(logEvent.MessageTemplate, logEvent.Properties);
5943

6044
foreach (var provider in _providers.Providers)
6145
{
6246
var logger = provider.CreateLogger(categoryName);
6347

6448
logger.Log(
65-
LevelMapping.ToExtensionsLevel(logEvent.Level),
66-
default(EventId),
67-
flv,
49+
level,
50+
default,
51+
slv,
6852
logEvent.Exception,
6953
(s, e) => s.ToString());
7054
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2019 Serilog Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using Serilog.Events;
16+
using System;
17+
using System.Collections;
18+
using System.Collections.Generic;
19+
20+
namespace Serilog.Extensions.Logging
21+
{
22+
readonly struct SerilogLogValues : IReadOnlyList<KeyValuePair<string, object>>
23+
{
24+
// Note, this struct is only used in a very limited context internally, so we ignore
25+
// the possibility of fields being null via the default struct initialization.
26+
27+
private readonly MessageTemplate _messageTemplate;
28+
private readonly IReadOnlyDictionary<string, LogEventPropertyValue> _properties;
29+
private readonly KeyValuePair<string, object>[] _values;
30+
31+
public SerilogLogValues(MessageTemplate messageTemplate, IReadOnlyDictionary<string, LogEventPropertyValue> properties)
32+
{
33+
_messageTemplate = messageTemplate ?? throw new ArgumentNullException(nameof(messageTemplate));
34+
35+
// The dictionary is needed for rendering through the message template
36+
_properties = properties ?? throw new ArgumentNullException(nameof(properties));
37+
38+
// The array is needed because the IReadOnlyList<T> interface expects indexed access
39+
_values = new KeyValuePair<string, object>[_properties.Count + 1];
40+
var i = 0;
41+
foreach (var p in properties)
42+
{
43+
_values[i] = new KeyValuePair<string, object>(p.Key, (p.Value is ScalarValue sv) ? sv.Value : p.Value);
44+
++i;
45+
}
46+
_values[i] = new KeyValuePair<string, object>("{OriginalFormat}", _messageTemplate.Text);
47+
}
48+
49+
public KeyValuePair<string, object> this[int index]
50+
{
51+
get => _values[index];
52+
}
53+
54+
public int Count => _properties.Count + 1;
55+
56+
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => ((IEnumerable<KeyValuePair<string, object>>)_values).GetEnumerator();
57+
58+
public override string ToString() => _messageTemplate.Render(_properties);
59+
60+
IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator();
61+
}
62+
}

src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj

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

33
<PropertyGroup>
44
<Description>Low-level Serilog provider for Microsoft.Extensions.Logging</Description>
5-
<VersionPrefix>2.0.5</VersionPrefix>
5+
<VersionPrefix>3.0.0</VersionPrefix>
66
<Authors>Microsoft;Serilog Contributors</Authors>
7-
<TargetFrameworks>net45;net46;net461;netstandard1.3;netstandard2.0</TargetFrameworks>
7+
<TargetFrameworks>netstandard2.0</TargetFrameworks>
88
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
99
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1010
<AssemblyName>Serilog.Extensions.Logging</AssemblyName>
@@ -24,28 +24,9 @@
2424

2525
<ItemGroup>
2626
<PackageReference Include="Serilog" Version="2.8.0" />
27-
</ItemGroup>
28-
29-
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'netstandard1.3' ">
30-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.0" />
31-
</ItemGroup>
32-
33-
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' or '$(TargetFramework)' == 'netstandard2.0' ">
3427
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
3528
</ItemGroup>
3629

37-
<PropertyGroup Condition=" '$(TargetFramework)' == 'net46' ">
38-
<DefineConstants>$(DefineConstants);ASYNCLOCAL</DefineConstants>
39-
</PropertyGroup>
40-
41-
<PropertyGroup Condition=" '$(TargetFramework)' == 'net461' ">
42-
<DefineConstants>$(DefineConstants);ASYNCLOCAL;LOGGING_BUILDER</DefineConstants>
43-
</PropertyGroup>
44-
45-
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
46-
<DefineConstants>$(DefineConstants);ASYNCLOCAL</DefineConstants>
47-
</PropertyGroup>
48-
4930
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
5031
<DefineConstants>$(DefineConstants);ASYNCLOCAL;LOGGING_BUILDER</DefineConstants>
5132
</PropertyGroup>
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netcoreapp1.1;netcoreapp2.0;net46;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp2.0;net472</TargetFrameworks>
55
<AssemblyName>Serilog.Extensions.Logging.Tests</AssemblyName>
66
<AssemblyOriginatorKeyFile>../../assets/Serilog.snk</AssemblyOriginatorKeyFile>
77
<SignAssembly>true</SignAssembly>
88
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
99
<PackageId>Serilog.Extensions.Logging.Tests</PackageId>
1010
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
11-
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dnxcore50;portable-net45+win8</PackageTargetFallback>
12-
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">1.0.4</RuntimeFrameworkVersion>
1311
</PropertyGroup>
1412

1513
<ItemGroup>
@@ -22,9 +20,4 @@
2220
<PackageReference Include="xunit" Version="2.2.0" />
2321
</ItemGroup>
2422

25-
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
26-
<Reference Include="System" />
27-
<Reference Include="Microsoft.CSharp" />
28-
</ItemGroup>
29-
3023
</Project>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Serilog.Events;
2+
using Serilog.Parsing;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using Xunit;
6+
7+
namespace Serilog.Extensions.Logging.Tests
8+
{
9+
public class SerilogLogValuesTests
10+
{
11+
[Fact]
12+
public void OriginalFormatIsExposed()
13+
{
14+
const string format = "Hello, {Name}!";
15+
var mt = new MessageTemplateParser().Parse(format);
16+
var lv = new SerilogLogValues(mt, new Dictionary<string, LogEventPropertyValue>());
17+
var kvp = lv.Single();
18+
Assert.Equal("{OriginalFormat}", kvp.Key);
19+
Assert.Equal(format, kvp.Value);
20+
}
21+
22+
[Fact]
23+
public void ScalarPropertiesAreSimplfied()
24+
{
25+
const string name = "Scalar";
26+
var scalar = 15;
27+
var lv = new SerilogLogValues(MessageTemplate.Empty, new Dictionary<string, LogEventPropertyValue> { [name] = new ScalarValue(scalar) });
28+
var kvp = lv.Single(p => p.Key == name);
29+
var sv = Assert.IsType<int>(kvp.Value);
30+
Assert.Equal(scalar, sv);
31+
}
32+
33+
[Fact]
34+
public void NonscalarPropertiesAreWrapped()
35+
{
36+
const string name = "Sequence";
37+
var seq = new SequenceValue(Enumerable.Empty<LogEventPropertyValue>());
38+
var lv = new SerilogLogValues(MessageTemplate.Empty, new Dictionary<string, LogEventPropertyValue> { [name] = seq });
39+
var kvp = lv.Single(p => p.Key == name);
40+
var sv = Assert.IsType<SequenceValue>(kvp.Value);
41+
Assert.Equal(seq, sv);
42+
}
43+
44+
[Fact]
45+
public void MessageTemplatesAreRendered()
46+
{
47+
const string format = "Hello, {Name}!";
48+
var mt = new MessageTemplateParser().Parse(format);
49+
var lv = new SerilogLogValues(mt, new Dictionary<string, LogEventPropertyValue> { ["Name"] = new ScalarValue("World") });
50+
Assert.Equal("Hello, \"World\"!", lv.ToString());
51+
}
52+
}
53+
}

0 commit comments

Comments
 (0)