forked from akkadotnet/Akka.Logger.Serilog
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MessageTemplateCache.cs
62 lines (49 loc) · 2.25 KB
/
MessageTemplateCache.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using System;
using System.Collections;
using Serilog.Events;
using Serilog.Parsing;
#nullable enable
namespace Akka.Logger.Serilog
{
/// <summary>
/// Taken directly from Serilog as the cache was internal.
/// https://github.com/serilog/serilog/blob/master/src/Serilog/Core/Pipeline/MessageTemplateCache.cs
/// </summary>
internal class MessageTemplateCache
{
private readonly MessageTemplateParser _innerParser;
private readonly object _templatesLock = new();
private readonly Hashtable _templates = new();
private const int MaxCacheItems = 1000;
private const int MaxCachedTemplateLength = 1024;
public MessageTemplateCache(MessageTemplateParser innerParser)
{
_innerParser = innerParser ?? throw new ArgumentNullException(nameof(innerParser));
}
public MessageTemplate Parse(string messageTemplate)
{
if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate));
if (messageTemplate.Length > MaxCachedTemplateLength)
return _innerParser.Parse(messageTemplate);
// ReSharper disable once InconsistentlySynchronizedField
// ignored warning because this is by design
var result = (MessageTemplate?)_templates[messageTemplate];
if (result != null)
return result;
result = _innerParser.Parse(messageTemplate);
lock (_templatesLock)
{
// Exceeding MaxCacheItems is *not* the sunny day scenario; all we're doing here is preventing out-of-memory
// conditions when the library is used incorrectly. Correct use (templates, rather than
// direct message strings) should barely, if ever, overflow this cache.
// Changing workloads through the lifecycle of an app instance mean we can gain some ground by
// potentially dropping templates generated only in startup, or only during specific infrequent
// activities.
if (_templates.Count == MaxCacheItems)
_templates.Clear();
_templates[messageTemplate] = result;
}
return result;
}
}
}