Skip to content

Commit 01b0d10

Browse files
authored
Merge pull request #216 from sungam3r/cache
Cache trimmed keys for @ and $
2 parents 3f63b63 + 04a36b0 commit 01b0d10

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,24 @@
77
using FrameworkLogger = Microsoft.Extensions.Logging.ILogger;
88
using System.Reflection;
99
using Serilog.Debugging;
10+
using System.Collections.Concurrent;
1011

1112
namespace Serilog.Extensions.Logging;
1213

1314
class SerilogLogger : FrameworkLogger
1415
{
16+
internal static readonly ConcurrentDictionary<string, string> DestructureDictionary = new();
17+
internal static readonly ConcurrentDictionary<string, string> StringifyDictionary = new();
18+
19+
internal static string GetKeyWithoutFirstSymbol(ConcurrentDictionary<string, string> source, string key)
20+
{
21+
if (source.TryGetValue(key, out var value))
22+
return value;
23+
if (source.Count < 1000)
24+
return source.GetOrAdd(key, k => k.Substring(1));
25+
return key.Substring(1);
26+
}
27+
1528
readonly SerilogLoggerProvider _provider;
1629
readonly ILogger _logger;
1730

@@ -88,12 +101,12 @@ void Write<TState>(LogEventLevel level, EventId eventId, TState state, Exception
88101
}
89102
else if (property.Key.StartsWith("@"))
90103
{
91-
if (logger.BindProperty(property.Key.Substring(1), property.Value, true, out var destructured))
104+
if (logger.BindProperty(GetKeyWithoutFirstSymbol(DestructureDictionary, property.Key), property.Value, true, out var destructured))
92105
properties.Add(destructured);
93106
}
94107
else if (property.Key.StartsWith("$"))
95108
{
96-
if (logger.BindProperty(property.Key.Substring(1), property.Value?.ToString(), true, out var stringified))
109+
if (logger.BindProperty(GetKeyWithoutFirstSymbol(StringifyDictionary, property.Key), property.Value?.ToString(), true, out var stringified))
97110
properties.Add(stringified);
98111
}
99112
else

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
5+
using System.Collections.Generic;
46
using Serilog.Core;
57
using Serilog.Events;
68

@@ -57,13 +59,12 @@ void AddProperty(KeyValuePair<string, object> stateProperty)
5759

5860
if (key.StartsWith("@"))
5961
{
60-
key = key.Substring(1);
62+
key = SerilogLogger.GetKeyWithoutFirstSymbol(SerilogLogger.DestructureDictionary, key);
6163
destructureObject = true;
6264
}
63-
64-
if (key.StartsWith("$"))
65+
else if (key.StartsWith("$"))
6566
{
66-
key = key.Substring(1);
67+
key = SerilogLogger.GetKeyWithoutFirstSymbol(SerilogLogger.StringifyDictionary, key);
6768
value = value?.ToString();
6869
}
6970

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

0 commit comments

Comments
 (0)