Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2bc0ea5

Browse files
Make EventIdPropertyCache non-static; Create unit tests.
1 parent 29b94f3 commit 2bc0ea5

File tree

3 files changed

+154
-73
lines changed

3 files changed

+154
-73
lines changed

‎src/Serilog.Extensions.Logging/Extensions/Logging/EventIdPropertyCache.cs

Lines changed: 59 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,75 +12,86 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
namespace Serilog.Extensions.Logging
15+
namespace Serilog.Extensions.Logging;
16+
17+
using System.Collections.Concurrent;
18+
using Microsoft.Extensions.Logging;
19+
using Serilog.Events;
20+
21+
class EventIdPropertyCache
1622
{
17-
using System.Collections.Concurrent;
18-
using Microsoft.Extensions.Logging;
19-
using Serilog.Events;
23+
readonly int _maxCachedProperties;
24+
readonly ConcurrentDictionary<EventKey, LogEventProperty> _propertyCache = new();
2025

21-
static class EventIdPropertyCache
22-
{
23-
const int MaxCachedProperties = 1024;
26+
int _count;
2427

25-
static readonly ConcurrentDictionary<EventKey, LogEventProperty> s_propertyCache = new();
26-
static int s_count;
28+
public EventIdPropertyCache(int maxCachedProperties = 1024)
29+
{
30+
_maxCachedProperties = maxCachedProperties;
31+
}
2732

28-
publicstatic LogEventProperty GetOrCreateProperty(in EventId eventId)
29-
{
30-
var eventKey = new EventKey(eventId);
33+
public LogEventProperty GetOrCreateProperty(in EventId eventId)
34+
{
35+
var eventKey = new EventKey(eventId);
3136

32-
LogEventProperty? property;
37+
LogEventProperty? property;
3338

34-
if (s_count >= MaxCachedProperties)
39+
if (_count >= _maxCachedProperties)
40+
{
41+
if (!_propertyCache.TryGetValue(eventKey, out property))
3542
{
36-
if (!s_propertyCache.TryGetValue(eventKey, out property))
37-
{
38-
property = CreateCore(in eventKey);
39-
}
43+
property = CreateProperty(in eventKey);
4044
}
41-
else
45+
}
46+
else
47+
{
48+
if (!_propertyCache.TryGetValue(eventKey, out property))
4249
{
43-
property = s_propertyCache.GetOrAdd(
44-
eventKey,
45-
static key =>
46-
{
47-
Interlocked.Increment(ref s_count);
48-
49-
return CreateCore(in key);
50-
});
50+
// GetOrAdd is moved to a separate method to prevent closure allocation
51+
property = GetOrAddCore(in eventKey);
5152
}
53+
}
5254

53-
return property;
55+
return property;
56+
}
57+
58+
static LogEventProperty CreateProperty(in EventKey eventKey)
59+
{
60+
var properties = new List<LogEventProperty>(2);
61+
62+
if (eventKey.Id != 0)
63+
{
64+
properties.Add(new LogEventProperty("Id", new ScalarValue(eventKey.Id)));
5465
}
5566

56-
staticLogEventPropertyCreateCore(inEventKeyeventKey)
67+
if(eventKey.Name!=null)
5768
{
58-
var properties = new List<LogEventProperty>(2);
69+
properties.Add(new LogEventProperty("Name", new ScalarValue(eventKey.Name)));
70+
}
5971

60-
if (eventKey.Id != 0)
61-
{
62-
properties.Add(new LogEventProperty("Id", new ScalarValue(eventKey.Id)));
63-
}
72+
return new LogEventProperty("EventId", new StructureValue(properties));
73+
}
6474

65-
if (eventKey.Name != null)
75+
LogEventProperty GetOrAddCore(in EventKey eventKey) =>
76+
_propertyCache.GetOrAdd(
77+
eventKey,
78+
key =>
6679
{
67-
properties.Add(new LogEventProperty("Name", new ScalarValue(eventKey.Name)));
68-
}
80+
Interlocked.Increment(ref _count);
6981

70-
returnnewLogEventProperty("EventId",newStructureValue(properties));
71-
}
82+
returnCreateProperty(inkey);
83+
});
7284

73-
readonly record struct EventKey
85+
readonly record struct EventKey
86+
{
87+
public EventKey(EventId eventId)
7488
{
75-
public EventKey(EventId eventId)
76-
{
77-
Id = eventId.Id;
78-
Name = eventId.Name;
79-
}
89+
Id = eventId.Id;
90+
Name = eventId.Name;
91+
}
8092

81-
public int Id { get; }
93+
public int Id { get; }
8294

83-
public string? Name { get; }
84-
}
95+
public string? Name { get; }
8596
}
8697
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ internal static string GetKeyWithoutFirstSymbol(ConcurrentDictionary<string, str
2828

2929
readonly SerilogLoggerProvider _provider;
3030
readonly ILogger _logger;
31+
readonly EventIdPropertyCache _eventIdPropertyCache = new();
3132

32-
static readonly CachingMessageTemplateParser MessageTemplateParser = new();
33+
static readonly CachingMessageTemplateParser MessageTemplateParser = new();
3334

3435
public SerilogLogger(
3536
SerilogLoggerProvider provider,
@@ -150,7 +151,7 @@ LogEvent PrepareWrite<TState>(LogEventLevel level, EventId eventId, TState state
150151
}
151152

152153
if (eventId.Id != 0 || eventId.Name != null)
153-
properties.Add(EventIdPropertyCache.GetOrCreateProperty(in eventId));
154+
properties.Add(_eventIdPropertyCache.GetOrCreateProperty(in eventId));
154155

155156
var (traceId, spanId) = Activity.Current is { } activity ?
156157
(activity.TraceId, activity.SpanId) :

‎test/Serilog.Extensions.Logging.Tests/EventIdPropertyCacheTests.cs

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,99 @@
1616
using Serilog.Events;
1717
using Xunit;
1818

19-
namespace Serilog.Extensions.Logging.Tests
19+
namespace Serilog.Extensions.Logging.Tests;
20+
21+
public class EventIdPropertyCacheTests
2022
{
21-
public class EventIdPropertyCacheTests
23+
[Fact]
24+
public void CreatesPropertyWithCorrectIdAndName()
25+
{
26+
// Arrange
27+
const int id = 101;
28+
const string name = "TestEvent";
29+
var eventId = new EventId(id, name);
30+
31+
var cache = new EventIdPropertyCache();
32+
33+
// Act
34+
var eventProperty = cache.GetOrCreateProperty(eventId);
35+
36+
// Assert
37+
var value = Assert.IsType<StructureValue>(eventProperty.Value);
38+
39+
Assert.Equal(2, value.Properties.Count);
40+
41+
var idValue = value.Properties.Single(property => property.Name == "Id").Value;
42+
var nameValue = value.Properties.Single(property => property.Name == "Name").Value;
43+
44+
var scalarId = Assert.IsType<ScalarValue>(idValue);
45+
var scalarName = Assert.IsType<ScalarValue>(nameValue);
46+
47+
Assert.Equal(id, scalarId.Value);
48+
Assert.Equal(name, scalarName.Value);
49+
}
50+
51+
[Fact]
52+
public void EventsWithDSameKeysHaveSameReferences()
53+
{
54+
// Arrange
55+
var cache = new EventIdPropertyCache();
56+
57+
// Act
58+
var property1 = cache.GetOrCreateProperty(new EventId(1, "Name1"));
59+
var property2 = cache.GetOrCreateProperty(new EventId(1, "Name1"));
60+
61+
// Assert
62+
Assert.Same(property1, property2);
63+
}
64+
65+
[Theory]
66+
[InlineData(1, "SomeName", 1, "AnotherName")]
67+
[InlineData(1, "SomeName", 2, "SomeName")]
68+
[InlineData(1, "SomeName", 2, "AnotherName")]
69+
public void EventsWithDifferentKeysHaveDifferentReferences(int firstId, string firstName, int secondId, string secondName)
70+
{
71+
// Arrange
72+
var cache = new EventIdPropertyCache();
73+
74+
// Act
75+
var property1 = cache.GetOrCreateProperty(new EventId(firstId, firstName));
76+
var property2 = cache.GetOrCreateProperty(new EventId(secondId, secondName));
77+
78+
// Assert
79+
Assert.NotSame(property1, property2);
80+
}
81+
82+
83+
[Fact]
84+
public void WhenLimitIsNotOverSameEventsHaveSameReferences()
2285
{
23-
[Theory]
24-
[InlineData(1)]
25-
[InlineData(10)]
26-
[InlineData(48)]
27-
[InlineData(100)]
28-
public void LowAndHighNumberedEventIdsAreMapped(int id)
29-
{
30-
// Arrange
31-
var eventId = new EventId(id, "test");
32-
33-
// Act
34-
var mapped = EventIdPropertyCache.GetOrCreateProperty(eventId);
35-
36-
// Assert
37-
var value = Assert.IsType<StructureValue>(mapped.Value);
38-
Assert.Equal(2, value.Properties.Count);
39-
40-
var idValue = value.Properties.Single(p => p.Name == "Id").Value;
41-
var scalar = Assert.IsType<ScalarValue>(idValue);
42-
Assert.Equal(id, scalar.Value);
43-
}
86+
// Arrange
87+
var eventId = new EventId(101, "test");
88+
var cache = new EventIdPropertyCache();
89+
90+
// Act
91+
var property1 = cache.GetOrCreateProperty(eventId);
92+
var property2 = cache.GetOrCreateProperty(eventId);
93+
94+
// Assert
95+
Assert.Same(property1, property2);
96+
}
97+
98+
[Fact]
99+
public void WhenLimitIsOverSameEventsHaveDifferentReferences()
100+
{
101+
// Arrange
102+
var cache = new EventIdPropertyCache(maxCachedProperties: 1);
103+
cache.GetOrCreateProperty(new EventId(1, "InitialEvent"));
104+
105+
var eventId = new EventId(101, "DifferentEvent");
106+
107+
// Act
108+
var property1 = cache.GetOrCreateProperty(eventId);
109+
var property2 = cache.GetOrCreateProperty(eventId);
110+
111+
// Assert
112+
Assert.NotSame(property1, property2);
44113
}
45114
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /