Skip to content

Commit 6b6af9c

Browse files
committed
Cache trimmed keys for @ and $
1 parent da7b61b commit 6b6af9c

File tree

3 files changed

+73
-6
lines changed

3 files changed

+73
-6
lines changed

src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@
1010
using FrameworkLogger = Microsoft.Extensions.Logging.ILogger;
1111
using System.Reflection;
1212
using Serilog.Debugging;
13+
using System.Collections.Concurrent;
1314

1415
namespace Serilog.Extensions.Logging
1516
{
1617
class SerilogLogger : FrameworkLogger
1718
{
19+
internal static readonly ConcurrentDictionary<string, string> DestructureDictionary = new ConcurrentDictionary<string, string>();
20+
internal static readonly ConcurrentDictionary<string, string> StringifyDictionary = new ConcurrentDictionary<string, string>();
21+
1822
readonly SerilogLoggerProvider _provider;
1923
readonly ILogger _logger;
2024

@@ -91,12 +95,12 @@ void Write<TState>(LogEventLevel level, EventId eventId, TState state, Exception
9195
}
9296
else if (property.Key.StartsWith("@"))
9397
{
94-
if (logger.BindProperty(property.Key.Substring(1), property.Value, true, out var destructured))
98+
if (logger.BindProperty(DestructureDictionary.GetOrAdd(property.Key, k => k.Substring(1)), property.Value, true, out var destructured))
9599
properties.Add(destructured);
96100
}
97101
else if (property.Key.StartsWith("$"))
98102
{
99-
if (logger.BindProperty(property.Key.Substring(1), property.Value?.ToString(), true, out var stringified))
103+
if (logger.BindProperty(StringifyDictionary.GetOrAdd(property.Key, k => k.Substring(1)), property.Value?.ToString(), true, out var stringified))
100104
properties.Add(stringified);
101105
}
102106
else

src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Collections.Concurrent;
56
using System.Collections.Generic;
67
using Serilog.Core;
78
using Serilog.Events;
@@ -59,13 +60,12 @@ void AddProperty(KeyValuePair<string, object> stateProperty)
5960

6061
if (key.StartsWith("@"))
6162
{
62-
key = key.Substring(1);
63+
key = SerilogLogger.DestructureDictionary.GetOrAdd(key, k => k.Substring(1));
6364
destructureObject = true;
6465
}
65-
66-
if (key.StartsWith("$"))
66+
else if (key.StartsWith("$"))
6767
{
68-
key = key.Substring(1);
68+
key = SerilogLogger.StringifyDictionary.GetOrAdd(key, k => k.Substring(1));
6969
value = value?.ToString();
7070
}
7171

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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 BenchmarkDotNet.Attributes;
16+
using BenchmarkDotNet.Running;
17+
using Microsoft.Extensions.Logging;
18+
using Xunit;
19+
using IMelLogger = Microsoft.Extensions.Logging.ILogger;
20+
21+
namespace Serilog.Extensions.Logging.Benchmarks
22+
{
23+
[MemoryDiagnoser]
24+
public class LogEventBenchmark
25+
{
26+
private class Person
27+
{
28+
public string Name { get; set; }
29+
public int Age { get; set; }
30+
public override string ToString() => "Fixed text";
31+
}
32+
33+
readonly IMelLogger _melLogger;
34+
readonly Person _bob, _alice;
35+
36+
public LogEventBenchmark()
37+
{
38+
var underlyingLogger = new LoggerConfiguration().CreateLogger();
39+
_melLogger = new SerilogLoggerProvider(underlyingLogger).CreateLogger(GetType().FullName);
40+
_bob = new Person { Name = "Bob", Age = 42 };
41+
_alice = new Person { Name = "Alice", Age = 42 };
42+
}
43+
44+
[Fact]
45+
public void Benchmark()
46+
{
47+
BenchmarkRunner.Run<LogEventBenchmark>();
48+
}
49+
50+
[Benchmark]
51+
public void LogInformation()
52+
{
53+
_melLogger.LogInformation("Hi {@User} from {$Me}", _bob, _alice);
54+
}
55+
56+
[Benchmark]
57+
public void LogInformationScoped()
58+
{
59+
using (var scope = _melLogger.BeginScope("Hi {@User} from {$Me}", _bob, _alice))
60+
_melLogger.LogInformation("Hi");
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)