зеркало из https://github.com/aspnet/Logging.git
Decrease logging overhead (#917)
This commit is contained in:
Родитель
03970f7104
Коммит
cc90113f45
|
@ -29,3 +29,4 @@ project.lock.json
|
|||
.build/
|
||||
.testPublish/
|
||||
global.json
|
||||
BenchmarkDotNet.Artifacts/
|
|
@ -60,6 +60,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Loggin
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Analyzer.Test", "test\Microsoft.Extensions.Logging.Analyzer.Test\Microsoft.Extensions.Logging.Analyzer.Test.csproj", "{C0391E46-FD04-4D52-BE40-1F21CE83E037}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{0BE8FABE-0FE7-4DF1-ABDE-27BB0D86F881}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Logging.Performance", "benchmarks\Logging.Performance\Logging.Performance.csproj", "{67B77ED1-8827-4088-8724-4A0AF4351FB7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -134,6 +138,10 @@ Global
|
|||
{C0391E46-FD04-4D52-BE40-1F21CE83E037}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0391E46-FD04-4D52-BE40-1F21CE83E037}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C0391E46-FD04-4D52-BE40-1F21CE83E037}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{67B77ED1-8827-4088-8724-4A0AF4351FB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67B77ED1-8827-4088-8724-4A0AF4351FB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67B77ED1-8827-4088-8724-4A0AF4351FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67B77ED1-8827-4088-8724-4A0AF4351FB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -156,6 +164,7 @@ Global
|
|||
{6D921637-507E-4CDC-8C5F-C3D6B62D118C} = {699DB330-0095-4266-B7B0-3EAB3710CA49}
|
||||
{99DF369F-40A4-4088-8308-1C361B59DF4E} = {699DB330-0095-4266-B7B0-3EAB3710CA49}
|
||||
{C0391E46-FD04-4D52-BE40-1F21CE83E037} = {09920C51-6220-4D8D-94DC-E70C13446187}
|
||||
{67B77ED1-8827-4088-8724-4A0AF4351FB7} = {0BE8FABE-0FE7-4DF1-ABDE-27BB0D86F881}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BA58E3CA-3A01-46A7-B57F-FD7A188EDC79}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// 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;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Performance
|
||||
{
|
||||
[AspNetCoreBenchmark]
|
||||
public class FormattingBenchmarks : LoggingBenchmarkBase
|
||||
{
|
||||
private ILogger _logger;
|
||||
|
||||
[Benchmark]
|
||||
public void TwoArguments()
|
||||
{
|
||||
TwoArgumentErrorMessage(_logger, 1, "string", Exception);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void NoArguments()
|
||||
{
|
||||
NoArgumentErrorMessage(_logger, Exception);
|
||||
}
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
services.AddSingleton<ILoggerProvider, LoggerProvider<MessageFormattingLogger>>();
|
||||
|
||||
_logger = services.BuildServiceProvider().GetService<ILoggerFactory>().CreateLogger("Logger");
|
||||
}
|
||||
|
||||
public class MessageFormattingLogger: ILogger
|
||||
{
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||
{
|
||||
formatter(state, exception);
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public IDisposable BeginScope<TState>(TState state)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<RootNamespace>Microsoft.Extensions.Logging.Performance</RootNamespace>
|
||||
<OutputType>Exe</OutputType>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Extensions.Logging\Microsoft.Extensions.Logging.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,40 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Performance
|
||||
{
|
||||
public class LoggingBenchmarkBase
|
||||
{
|
||||
protected static readonly Action<ILogger, Exception> NoArgumentTraceMessage = LoggerMessage.Define(LogLevel.Trace, 0, "Message");
|
||||
protected static readonly Action<ILogger, Exception> NoArgumentErrorMessage = LoggerMessage.Define(LogLevel.Error, 0, "Message");
|
||||
|
||||
protected static readonly Action<ILogger, int, string, Exception> TwoArgumentTraceMessage = LoggerMessage.Define<int, string>(LogLevel.Trace, 0, "Message {Argument1} {Argument2}");
|
||||
protected static readonly Action<ILogger, int, string, Exception> TwoArgumentErrorMessage = LoggerMessage.Define<int, string>(LogLevel.Error, 0, "Message {Argument1} {Argument2}");
|
||||
|
||||
protected static Exception Exception = ((Func<Exception>)(() => {
|
||||
try
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ex;
|
||||
}
|
||||
}))();
|
||||
|
||||
public class LoggerProvider<T>: ILoggerProvider
|
||||
where T: ILogger, new()
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
// 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;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Performance
|
||||
{
|
||||
[AspNetCoreBenchmark]
|
||||
public class LoggingOverheadBenchmark: LoggingBenchmarkBase
|
||||
{
|
||||
private ILogger _logger;
|
||||
|
||||
[Benchmark]
|
||||
public void NoArguments_FilteredByLevel()
|
||||
{
|
||||
_logger.LogTrace(Exception, "Message");
|
||||
}
|
||||
|
||||
// Baseline as this is the fastest way to do nothing
|
||||
[Benchmark(Baseline = true)]
|
||||
public void NoArguments_DefineMessage_FilteredByLevel()
|
||||
{
|
||||
NoArgumentTraceMessage(_logger, Exception);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void NoArguments()
|
||||
{
|
||||
_logger.LogError(Exception, "Message");
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void NoArguments_DefineMessage()
|
||||
{
|
||||
NoArgumentErrorMessage(_logger, Exception);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TwoArguments()
|
||||
{
|
||||
_logger.LogError(Exception, "Message {Argument1} {Argument2}", 1, "string");
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TwoArguments_FilteredByLevel()
|
||||
{
|
||||
_logger.LogTrace(Exception, "Message {Argument1} {Argument2}", 1, "string");
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TwoArguments_DefineMessage()
|
||||
{
|
||||
TwoArgumentErrorMessage(_logger, 1, "string", Exception);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TwoArguments_DefineMessage_FilteredByLevel()
|
||||
{
|
||||
TwoArgumentTraceMessage(_logger, 1, "string", Exception);
|
||||
}
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
services.AddSingleton<ILoggerProvider, LoggerProvider<NoopLogger>>();
|
||||
_logger = services.BuildServiceProvider().GetService<ILoggerFactory>().CreateLogger("Logger");
|
||||
}
|
||||
}
|
||||
|
||||
public class NoopLogger : ILogger
|
||||
{
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public IDisposable BeginScope<TState>(TState state)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// 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 BenchmarkDotNet.Attributes;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Performance
|
||||
{
|
||||
[AspNetCoreBenchmark]
|
||||
public class ScopesOverheadBenchmark: LoggingBenchmarkBase
|
||||
{
|
||||
private ILogger _logger;
|
||||
|
||||
[Params(true, false)]
|
||||
public bool HasISupportLoggingScopeLogger { get; set; } = false;
|
||||
|
||||
// Baseline as this is the fastest way to do nothing
|
||||
[Benchmark(Baseline = true)]
|
||||
public void FilteredByLevel()
|
||||
{
|
||||
TwoArgumentTraceMessage(_logger, 1, "string", Exception);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void FilteredByLevel_InsideScope()
|
||||
{
|
||||
using (_logger.BeginScope("string"))
|
||||
{
|
||||
TwoArgumentTraceMessage(_logger, 1, "string", Exception);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void NotFiltered()
|
||||
{
|
||||
TwoArgumentErrorMessage(_logger, 1, "string", Exception);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void NotFiltered_InsideScope()
|
||||
{
|
||||
using (_logger.BeginScope("string"))
|
||||
{
|
||||
TwoArgumentErrorMessage(_logger, 1, "string", Exception);
|
||||
}
|
||||
}
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
if (HasISupportLoggingScopeLogger)
|
||||
{
|
||||
services.AddSingleton<ILoggerProvider, LoggerProviderWithISupportExternalScope>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<ILoggerProvider, LoggerProvider<NoopLogger>>();
|
||||
}
|
||||
|
||||
_logger = services.BuildServiceProvider().GetService<ILoggerFactory>().CreateLogger("Logger");
|
||||
}
|
||||
|
||||
class LoggerProviderWithISupportExternalScope: LoggerProvider<NoopLogger>, ISupportExternalScope
|
||||
{
|
||||
public void SetScopeProvider(IExternalScopeProvider scopeProvider)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,8 +3,10 @@
|
|||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Package Versions">
|
||||
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
|
||||
<InternalAspNetCoreSdkPackageVersion>3.0.0-alpha1-20181004.7</InternalAspNetCoreSdkPackageVersion>
|
||||
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-alpha1-10584</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-alpha1-10584</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-alpha1-10584</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-alpha1-10584</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Microsoft.Extensions.Logging.Internal
|
|||
/// LogValues to enable formatting options supported by <see cref="M:string.Format"/>.
|
||||
/// This also enables using {NamedformatItem} in the format string.
|
||||
/// </summary>
|
||||
public class FormattedLogValues : IReadOnlyList<KeyValuePair<string, object>>
|
||||
public readonly struct FormattedLogValues : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
internal const int MaxCachedFormatters = 1024;
|
||||
private const string NullFormat = "[null]";
|
||||
|
@ -46,6 +46,10 @@ namespace Microsoft.Extensions.Logging.Internal
|
|||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_formatter = null;
|
||||
}
|
||||
|
||||
_originalMessage = format ?? NullFormat;
|
||||
_values = values;
|
||||
|
|
|
@ -119,32 +119,33 @@ namespace Microsoft.Extensions.Logging.Internal
|
|||
{
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
var value = values[i];
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
values[i] = NullValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
// since 'string' implements IEnumerable, special case it
|
||||
if (value is string)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the value implements IEnumerable, build a comma separated string.
|
||||
var enumerable = value as IEnumerable;
|
||||
if (enumerable != null)
|
||||
{
|
||||
values[i] = string.Join(", ", enumerable.Cast<object>().Select(o => o ?? NullValue));
|
||||
}
|
||||
values[i] = FormatArgument(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return string.Format(CultureInfo.InvariantCulture, _format, values ?? EmptyArray);
|
||||
}
|
||||
|
||||
internal string Format()
|
||||
{
|
||||
return _format;
|
||||
}
|
||||
|
||||
internal string Format(object arg0)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0));
|
||||
}
|
||||
|
||||
internal string Format(object arg0, object arg1)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0), FormatArgument(arg1));
|
||||
}
|
||||
|
||||
internal string Format(object arg0, object arg1, object arg2)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0), FormatArgument(arg1), FormatArgument(arg2));
|
||||
}
|
||||
|
||||
public KeyValuePair<string, object> GetValue(object[] values, int index)
|
||||
{
|
||||
if (index < 0 || index > _valueNames.Count)
|
||||
|
@ -171,5 +172,29 @@ namespace Microsoft.Extensions.Logging.Internal
|
|||
valueArray[valueArray.Length - 1] = new KeyValuePair<string, object>("{OriginalFormat}", OriginalFormat);
|
||||
return valueArray;
|
||||
}
|
||||
|
||||
private object FormatArgument(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return NullValue;
|
||||
}
|
||||
|
||||
// since 'string' implements IEnumerable, special case it
|
||||
if (value is string)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// if the value implements IEnumerable, build a comma separated string.
|
||||
var enumerable = value as IEnumerable;
|
||||
if (enumerable != null)
|
||||
{
|
||||
return string.Join(", ", enumerable.Cast<object>().Select(o => o ?? NullValue));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Microsoft.Extensions.Logging
|
|||
/// </summary>
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
private static readonly Func<object, Exception, string> _messageFormatter = MessageFormatter;
|
||||
private static readonly Func<FormattedLogValues, Exception, string> _messageFormatter = MessageFormatter;
|
||||
|
||||
//------------------------------------------DEBUG------------------------------------------//
|
||||
|
||||
|
@ -425,7 +425,7 @@ namespace Microsoft.Extensions.Logging
|
|||
|
||||
//------------------------------------------HELPERS------------------------------------------//
|
||||
|
||||
private static string MessageFormatter(object state, Exception error)
|
||||
private static string MessageFormatter(FormattedLogValues state, Exception error)
|
||||
{
|
||||
return state.ToString();
|
||||
}
|
||||
|
|
|
@ -102,11 +102,16 @@ namespace Microsoft.Extensions.Logging
|
|||
{
|
||||
var formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 1);
|
||||
|
||||
void Log(ILogger logger, T1 arg1, Exception exception)
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1>(formatter, arg1), exception, LogValues<T1>.Callback);
|
||||
}
|
||||
|
||||
return (logger, arg1, exception) =>
|
||||
{
|
||||
if (logger.IsEnabled(logLevel))
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1>(formatter, arg1), exception, LogValues<T1>.Callback);
|
||||
Log(logger, arg1, exception);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -124,11 +129,16 @@ namespace Microsoft.Extensions.Logging
|
|||
{
|
||||
var formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 2);
|
||||
|
||||
void Log(ILogger logger, T1 arg1, T2 arg2, Exception exception)
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1, T2>(formatter, arg1, arg2), exception, LogValues<T1, T2>.Callback);
|
||||
}
|
||||
|
||||
return (logger, arg1, arg2, exception) =>
|
||||
{
|
||||
if (logger.IsEnabled(logLevel))
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1, T2>(formatter, arg1, arg2), exception, LogValues<T1, T2>.Callback);
|
||||
Log(logger, arg1, arg2, exception);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -147,11 +157,16 @@ namespace Microsoft.Extensions.Logging
|
|||
{
|
||||
var formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 3);
|
||||
|
||||
void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, Exception exception)
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1, T2, T3>(formatter, arg1, arg2, arg3), exception, LogValues<T1, T2, T3>.Callback);
|
||||
}
|
||||
|
||||
return (logger, arg1, arg2, arg3, exception) =>
|
||||
{
|
||||
if (logger.IsEnabled(logLevel))
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1, T2, T3>(formatter, arg1, arg2, arg3), exception, LogValues<T1, T2, T3>.Callback);
|
||||
Log(logger, arg1, arg2, arg3, exception);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -171,11 +186,16 @@ namespace Microsoft.Extensions.Logging
|
|||
{
|
||||
var formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 4);
|
||||
|
||||
void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, Exception exception)
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1, T2, T3, T4>(formatter, arg1, arg2, arg3, arg4), exception, LogValues<T1, T2, T3, T4>.Callback);
|
||||
}
|
||||
|
||||
return (logger, arg1, arg2, arg3, arg4, exception) =>
|
||||
{
|
||||
if (logger.IsEnabled(logLevel))
|
||||
{
|
||||
logger.Log(logLevel, eventId, new LogValues<T1, T2, T3, T4>(formatter, arg1, arg2, arg3, arg4), exception, LogValues<T1, T2, T3, T4>.Callback);
|
||||
Log(logger, arg1, arg2, arg3, arg4, exception);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -245,11 +265,9 @@ namespace Microsoft.Extensions.Logging
|
|||
return logValuesFormatter;
|
||||
}
|
||||
|
||||
private class LogValues : IReadOnlyList<KeyValuePair<string, object>>
|
||||
private readonly struct LogValues : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues)state)._formatter.Format(((LogValues)state).ToArray());
|
||||
|
||||
private static object[] _valueArray = new object[0];
|
||||
public static readonly Func<LogValues, Exception, string> Callback = (state, exception) => state.ToString();
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
|
||||
|
@ -270,22 +288,14 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
public int Count => 1;
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
yield return this[0];
|
||||
}
|
||||
|
||||
public object[] ToArray() => _valueArray;
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
public override string ToString() => _formatter.Format();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
|
@ -293,9 +303,9 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
private class LogValues<T0> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
private readonly struct LogValues<T0> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues<T0>)state)._formatter.Format(((LogValues<T0>)state).ToArray());
|
||||
public static readonly Func<LogValues<T0>, Exception, string> Callback = (state, exception) => state.ToString();
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
private readonly T0 _value0;
|
||||
|
@ -310,25 +320,19 @@ namespace Microsoft.Extensions.Logging
|
|||
{
|
||||
get
|
||||
{
|
||||
if (index == 0)
|
||||
switch (index)
|
||||
{
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0);
|
||||
case 0:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0);
|
||||
case 1:
|
||||
return new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat);
|
||||
default:
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
}
|
||||
else if (index == 1)
|
||||
{
|
||||
return new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat);
|
||||
}
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
public int Count => 2;
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
|
@ -338,9 +342,8 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
public object[] ToArray() => new object[] { _value0 };
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
public override string ToString() => _formatter.Format(_value0);
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
|
@ -348,9 +351,9 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
private class LogValues<T0, T1> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
private readonly struct LogValues<T0, T1> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues<T0, T1>)state)._formatter.Format(((LogValues<T0, T1>)state).ToArray());
|
||||
public static readonly Func<LogValues<T0, T1>, Exception, string> Callback = (state, exception) => state.ToString();
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
private readonly T0 _value0;
|
||||
|
@ -381,13 +384,7 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
public int Count => 3;
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
|
@ -397,9 +394,7 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
public object[] ToArray() => new object[] { _value0, _value1 };
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
public override string ToString() => _formatter.Format(_value0, _value1);
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
|
@ -407,22 +402,16 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
private class LogValues<T0, T1, T2> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
private readonly struct LogValues<T0, T1, T2> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues<T0, T1, T2>)state)._formatter.Format(((LogValues<T0, T1, T2>)state).ToArray());
|
||||
public static readonly Func<LogValues<T0, T1, T2>, Exception, string> Callback = (state, exception) => state.ToString();
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
public T0 _value0;
|
||||
public T1 _value1;
|
||||
public T2 _value2;
|
||||
private readonly T0 _value0;
|
||||
private readonly T1 _value1;
|
||||
private readonly T2 _value2;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
public int Count => 4;
|
||||
|
||||
public KeyValuePair<string, object> this[int index]
|
||||
{
|
||||
|
@ -452,9 +441,7 @@ namespace Microsoft.Extensions.Logging
|
|||
_value2 = value2;
|
||||
}
|
||||
|
||||
public object[] ToArray() => new object[] { _value0, _value1, _value2 };
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
public override string ToString() => _formatter.Format(_value0, _value1, _value2);
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
|
@ -470,23 +457,17 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
private class LogValues<T0, T1, T2, T3> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
private readonly struct LogValues<T0, T1, T2, T3> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues<T0, T1, T2, T3>)state)._formatter.Format(((LogValues<T0, T1, T2, T3>)state).ToArray());
|
||||
public static readonly Func<LogValues<T0, T1, T2, T3>, Exception, string> Callback = (state, exception) => state.ToString();
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
public T0 _value0;
|
||||
public T1 _value1;
|
||||
public T2 _value2;
|
||||
public T3 _value3;
|
||||
private readonly T0 _value0;
|
||||
private readonly T1 _value1;
|
||||
private readonly T2 _value2;
|
||||
private readonly T3 _value3;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
public int Count => 5;
|
||||
|
||||
public KeyValuePair<string, object> this[int index]
|
||||
{
|
||||
|
@ -519,7 +500,7 @@ namespace Microsoft.Extensions.Logging
|
|||
_value3 = value3;
|
||||
}
|
||||
|
||||
public object[] ToArray() => new object[] { _value0, _value1, _value2, _value3 };
|
||||
private object[] ToArray() => new object[] { _value0, _value1, _value2, _value3 };
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
|
||||
|
@ -537,24 +518,18 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
private class LogValues<T0, T1, T2, T3, T4> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
private readonly struct LogValues<T0, T1, T2, T3, T4> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues<T0, T1, T2, T3, T4>)state)._formatter.Format(((LogValues<T0, T1, T2, T3, T4>)state).ToArray());
|
||||
public static readonly Func<LogValues<T0, T1, T2, T3, T4>, Exception, string> Callback = (state, exception) => state.ToString();
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
public T0 _value0;
|
||||
public T1 _value1;
|
||||
public T2 _value2;
|
||||
public T3 _value3;
|
||||
public T4 _value4;
|
||||
private readonly T0 _value0;
|
||||
private readonly T1 _value1;
|
||||
private readonly T2 _value2;
|
||||
private readonly T3 _value3;
|
||||
private readonly T4 _value4;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
public int Count => 6;
|
||||
|
||||
public KeyValuePair<string, object> this[int index]
|
||||
{
|
||||
|
@ -590,7 +565,7 @@ namespace Microsoft.Extensions.Logging
|
|||
_value4 = value4;
|
||||
}
|
||||
|
||||
public object[] ToArray() => new object[] { _value0, _value1, _value2, _value3, _value4 };
|
||||
private object[] ToArray() => new object[] { _value0, _value1, _value2, _value3, _value4 };
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
|
||||
|
@ -608,25 +583,19 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
|
||||
private class LogValues<T0, T1, T2, T3, T4, T5> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
private readonly struct LogValues<T0, T1, T2, T3, T4, T5> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues<T0, T1, T2, T3, T4, T5>)state)._formatter.Format(((LogValues<T0, T1, T2, T3, T4, T5>)state).ToArray());
|
||||
public static readonly Func<LogValues<T0, T1, T2, T3, T4, T5>, Exception, string> Callback = (state, exception) => state.ToString();
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
public T0 _value0;
|
||||
public T1 _value1;
|
||||
public T2 _value2;
|
||||
public T3 _value3;
|
||||
public T4 _value4;
|
||||
public T5 _value5;
|
||||
private readonly T0 _value0;
|
||||
private readonly T1 _value1;
|
||||
private readonly T2 _value2;
|
||||
private readonly T3 _value3;
|
||||
private readonly T4 _value4;
|
||||
private readonly T5 _value5;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
public int Count => 7;
|
||||
|
||||
public KeyValuePair<string, object> this[int index]
|
||||
{
|
||||
|
@ -665,86 +634,7 @@ namespace Microsoft.Extensions.Logging
|
|||
_value5 = value5;
|
||||
}
|
||||
|
||||
public object[] ToArray() => new object[] { _value0, _value1, _value2, _value3, _value4, _value5 };
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
private class LogValues<T0, T1, T2, T3, T4, T5, T6> : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
public static Func<object, Exception, string> Callback = (state, exception) => ((LogValues<T0, T1, T2, T3, T4, T5, T6>)state)._formatter.Format(((LogValues<T0, T1, T2, T3, T4, T5, T6>)state).ToArray());
|
||||
|
||||
private readonly LogValuesFormatter _formatter;
|
||||
public T0 _value0;
|
||||
public T1 _value1;
|
||||
public T2 _value2;
|
||||
public T3 _value3;
|
||||
public T4 _value4;
|
||||
public T5 _value5;
|
||||
public T6 _value6;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValuePair<string, object> this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0);
|
||||
case 1:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[1], _value1);
|
||||
case 2:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[2], _value2);
|
||||
case 3:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[3], _value3);
|
||||
case 4:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[4], _value4);
|
||||
case 5:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[5], _value5);
|
||||
case 6:
|
||||
return new KeyValuePair<string, object>(_formatter.ValueNames[6], _value6);
|
||||
case 7:
|
||||
return new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat);
|
||||
default:
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LogValues(LogValuesFormatter formatter, T0 value0, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6)
|
||||
{
|
||||
_formatter = formatter;
|
||||
_value0 = value0;
|
||||
_value1 = value1;
|
||||
_value2 = value2;
|
||||
_value3 = value3;
|
||||
_value4 = value4;
|
||||
_value5 = value5;
|
||||
_value6 = value6;
|
||||
}
|
||||
|
||||
public object[] ToArray() => new object[] { _value0, _value1, _value2, _value3, _value4, _value5, _value6 };
|
||||
private object[] ToArray() => new object[] { _value0, _value1, _value2, _value3, _value4, _value5 };
|
||||
|
||||
public override string ToString() => _formatter.Format(ToArray());
|
||||
|
||||
|
@ -763,4 +653,3 @@ namespace Microsoft.Extensions.Logging
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче