Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Commit

Permalink
Limit cached format values size
Browse files Browse the repository at this point in the history
  • Loading branch information
BrennanConroy committed Mar 16, 2017
1 parent 5c3239f commit cc503aa
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;

namespace Microsoft.Extensions.Logging.Internal
{
Expand All @@ -14,17 +15,36 @@ namespace Microsoft.Extensions.Logging.Internal
/// </summary>
public class FormattedLogValues : IReadOnlyList<KeyValuePair<string, object>>
{
internal const int MaxCachedFormatters = 1024;
private const string NullFormat = "[null]";
private static int _count;
private static ConcurrentDictionary<string, LogValuesFormatter> _formatters = new ConcurrentDictionary<string, LogValuesFormatter>();
private readonly LogValuesFormatter _formatter;
private readonly object[] _values;
private readonly string _originalMessage;

// for testing purposes
internal LogValuesFormatter Formatter => _formatter;

public FormattedLogValues(string format, params object[] values)
{
if (values?.Length != 0 && format != null)
{
_formatter = _formatters.GetOrAdd(format, f => new LogValuesFormatter(f));
if (_count >= MaxCachedFormatters)
{
if (!_formatters.TryGetValue(format, out _formatter))
{
_formatter = new LogValuesFormatter(format);
}
}
else
{
_formatter = _formatters.GetOrAdd(format, f =>
{
Interlocked.Increment(ref _count);
return new LogValuesFormatter(f);
});
}
}

_originalMessage = format ?? NullFormat;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Microsoft.Extensions.Logging.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
17 changes: 17 additions & 0 deletions test/Microsoft.Extensions.Logging.Test/FormattedLogValuesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,23 @@ public void LogValues_With_UnbalancedBraces(string format)
});
}

[Fact]
public void CachedFormattersAreCapped()
{
for (var i = 0; i < FormattedLogValues.MaxCachedFormatters; ++i)
{
var ignore = new FormattedLogValues($"{i}{{i}}", i);
}

// check cached formatter
var formatter = new FormattedLogValues("0{i}", 0).Formatter;
Assert.Same(formatter, new FormattedLogValues("0{i}", 0).Formatter);

// check non-cached formatter
formatter = new FormattedLogValues("test {}", 0).Formatter;
Assert.NotSame(formatter, new FormattedLogValues("test {}", 0).Formatter);
}

// message format, format arguments, expected message
public static TheoryData<string, object[], string> FormatsEnumerableValuesData
{
Expand Down

0 comments on commit cc503aa

Please sign in to comment.