提交 92ed6521 编写于 作者: cdy816's avatar cdy816

DotNetty Log目录被忽略

上级 aa1b2d4e
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 8:45:22.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
//
// 摘要:
// Represents a type used to perform logging.
//
// 言论:
// Aggregates most logging patterns to a single method.
public interface ILogger
{
//
// 摘要:
// Begins a logical operation scope.
//
// 参数:
// state:
// The identifier for the scope.
//
// 返回结果:
// An IDisposable that ends the logical operation scope on dispose.
IDisposable BeginScope<TState>(TState state);
//
// 摘要:
// Checks if the given logLevel is enabled.
//
// 参数:
// logLevel:
// level to be checked.
//
// 返回结果:
// true if enabled.
bool IsEnabled(LogLevel logLevel);
//
// 摘要:
// Writes a log entry.
//
// 参数:
// logLevel:
// Entry will be written on this level.
//
// eventId:
// Id of the event.
//
// state:
// The entry to be written. Can be also an object.
//
// exception:
// The exception related to this entry.
//
// formatter:
// Function to create a string message of the state and exception.
void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 8:59:22.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
//
// 摘要:
// Represents a type used to configure the logging system and create instances of
// Microsoft.Extensions.Logging.ILogger from the registered Microsoft.Extensions.Logging.ILoggerProviders.
public interface ILoggerFactory : IDisposable
{
//
// 摘要:
// Adds an Microsoft.Extensions.Logging.ILoggerProvider to the logging system.
//
// 参数:
// provider:
// The Microsoft.Extensions.Logging.ILoggerProvider.
void AddProvider(ILoggerProvider provider);
//
// 摘要:
// Creates a new Microsoft.Extensions.Logging.ILogger instance.
//
// 参数:
// categoryName:
// The category name for messages produced by the logger.
//
// 返回结果:
// The Microsoft.Extensions.Logging.ILogger.
ILogger CreateLogger(string categoryName);
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 8:52:25.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
//
// 摘要:
// Represents a type that can create instances of Microsoft.Extensions.Logging.ILogger.
public interface ILoggerProvider : IDisposable
{
//
// 摘要:
// Creates a new Microsoft.Extensions.Logging.ILogger instance.
//
// 参数:
// categoryName:
// The category name for messages produced by the logger.
ILogger CreateLogger(string categoryName);
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:30:54.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
/// <summary>
/// Used for notifications when <typeparamref name="TOptions"/> instances change.
/// </summary>
/// <typeparam name="TOptions">The options type.</typeparam>
public interface IOptionsMonitor<out TOptions>
{
/// <summary>
/// Returns the current <typeparamref name="TOptions"/> instance with the <see cref="Options.DefaultName"/>.
/// </summary>
TOptions CurrentValue { get; }
/// <summary>
/// Returns a configured <typeparamref name="TOptions"/> instance with the given name.
/// </summary>
TOptions Get(string name);
/// <summary>
/// Registers a listener to be called whenever a named <typeparamref name="TOptions"/> changes.
/// </summary>
/// <param name="listener">The action to be invoked when <typeparamref name="TOptions"/> has changed.</param>
/// <returns>An <see cref="IDisposable"/> which should be disposed to stop listening for changes.</returns>
IDisposable OnChange(Action<TOptions, string> listener);
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 8:44:10.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
//
// 摘要:
// Defines logging severity levels.
public enum LogLevel
{
//
// 摘要:
// Logs that contain the most detailed messages. These messages may contain sensitive
// application data. These messages are disabled by default and should never be
// enabled in a production environment.
Trace = 0,
//
// 摘要:
// Logs that are used for interactive investigation during development. These logs
// should primarily contain information useful for debugging and have no long-term
// value.
Debug = 1,
//
// 摘要:
// Logs that track the general flow of the application. These logs should have long-term
// value.
Information = 2,
//
// 摘要:
// Logs that highlight an abnormal or unexpected event in the application flow,
// but do not otherwise cause the application execution to stop.
Warning = 3,
//
// 摘要:
// Logs that highlight when the current flow of execution is stopped due to a failure.
// These should indicate a failure in the current activity, not an application-wide
// failure.
Error = 4,
//
// 摘要:
// Logs that describe an unrecoverable application or system crash, or a catastrophic
// failure that requires immediate attention.
Critical = 5,
//
// 摘要:
// Not used for writing log messages. Specifies that a logging category should not
// write any messages.
None = 6
}
public struct EventId
{
public EventId(int id, string name = null)
{
Id = id;
Name = name;
}
public int Id { get; }
public string Name { get; }
public override string ToString()
{
return Id + "" + Name;
}
public static implicit operator EventId(int i)
{
return new EventId(i);
}
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:22:38.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
internal class Logger : ILogger
{
public LoggerInformation[] Loggers { get; set; }
public MessageLogger[] MessageLoggers { get; set; }
public ScopeLogger[] ScopeLoggers { get; set; }
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var loggers = MessageLoggers;
if (loggers == null)
{
return;
}
List<Exception> exceptions = null;
for (var i = 0; i < loggers.Length; i++)
{
ref readonly var loggerInfo = ref loggers[i];
if (!loggerInfo.IsEnabled(logLevel))
{
continue;
}
LoggerLog(logLevel, eventId, loggerInfo.Logger, exception, formatter, ref exceptions, state);
}
if (exceptions != null && exceptions.Count > 0)
{
ThrowLoggingError(exceptions);
}
static void LoggerLog(LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func<TState, Exception, string> formatter, ref List<Exception> exceptions, in TState state)
{
try
{
logger.Log(logLevel, eventId, state, exception, formatter);
}
catch (Exception ex)
{
if (exceptions == null)
{
exceptions = new List<Exception>();
}
exceptions.Add(ex);
}
}
}
public bool IsEnabled(LogLevel logLevel)
{
var loggers = MessageLoggers;
if (loggers == null)
{
return false;
}
List<Exception> exceptions = null;
var i = 0;
for (; i < loggers.Length; i++)
{
ref readonly var loggerInfo = ref loggers[i];
if (!loggerInfo.IsEnabled(logLevel))
{
continue;
}
if (LoggerIsEnabled(logLevel, loggerInfo.Logger, ref exceptions))
{
break;
}
}
if (exceptions != null && exceptions.Count > 0)
{
ThrowLoggingError(exceptions);
}
return i < loggers.Length ? true : false;
static bool LoggerIsEnabled(LogLevel logLevel, ILogger logger, ref List<Exception> exceptions)
{
try
{
if (logger.IsEnabled(logLevel))
{
return true;
}
}
catch (Exception ex)
{
if (exceptions == null)
{
exceptions = new List<Exception>();
}
exceptions.Add(ex);
}
return false;
}
}
public IDisposable BeginScope<TState>(TState state)
{
var loggers = ScopeLoggers;
//if (loggers == null)
//{
// return NullScope.Instance;
//}
if (loggers.Length == 1)
{
return loggers[0].CreateScope(state);
}
var scope = new Scope(loggers.Length);
List<Exception> exceptions = null;
for (var i = 0; i < loggers.Length; i++)
{
ref readonly var scopeLogger = ref loggers[i];
try
{
scope.SetDisposable(i, scopeLogger.CreateScope(state));
}
catch (Exception ex)
{
if (exceptions == null)
{
exceptions = new List<Exception>();
}
exceptions.Add(ex);
}
}
if (exceptions != null && exceptions.Count > 0)
{
ThrowLoggingError(exceptions);
}
return scope;
}
private static void ThrowLoggingError(List<Exception> exceptions)
{
throw new AggregateException(
message: "An error occurred while writing to logger(s).", innerExceptions: exceptions);
}
private class Scope : IDisposable
{
private bool _isDisposed;
private IDisposable _disposable0;
private IDisposable _disposable1;
private readonly IDisposable[] _disposable;
public Scope(int count)
{
if (count > 2)
{
_disposable = new IDisposable[count - 2];
}
}
public void SetDisposable(int index, IDisposable disposable)
{
switch (index)
{
case 0:
_disposable0 = disposable;
break;
case 1:
_disposable1 = disposable;
break;
default:
_disposable[index - 2] = disposable;
break;
}
}
public void Dispose()
{
if (!_isDisposed)
{
_disposable0?.Dispose();
_disposable1?.Dispose();
if (_disposable != null)
{
var count = _disposable.Length;
for (var index = 0; index != count; ++index)
{
if (_disposable[index] != null)
{
_disposable[index].Dispose();
}
}
}
_isDisposed = true;
}
}
}
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:29:23.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace DotNetty.Common
{
/// <summary>
/// Default implementation of <see cref="IExternalScopeProvider"/>
/// </summary>
public class LoggerExternalScopeProvider : IExternalScopeProvider
{
private readonly AsyncLocal<Scope> _currentScope = new AsyncLocal<Scope>();
/// <summary>
/// Creates a new <see cref="LoggerExternalScopeProvider"/>.
/// </summary>
public LoggerExternalScopeProvider()
{ }
/// <inheritdoc />
public void ForEachScope<TState>(Action<object, TState> callback, TState state)
{
void Report(Scope current)
{
if (current == null)
{
return;
}
Report(current.Parent);
callback(current.State, state);
}
Report(_currentScope.Value);
}
/// <inheritdoc />
public IDisposable Push(object state)
{
var parent = _currentScope.Value;
var newScope = new Scope(this, state, parent);
_currentScope.Value = newScope;
return newScope;
}
private class Scope : IDisposable
{
private readonly LoggerExternalScopeProvider _provider;
private bool _isDisposed;
internal Scope(LoggerExternalScopeProvider provider, object state, Scope parent)
{
_provider = provider;
State = state;
Parent = parent;
}
public Scope Parent { get; }
public object State { get; }
public override string ToString()
{
return State?.ToString();
}
public void Dispose()
{
if (!_isDisposed)
{
_provider._currentScope.Value = Parent;
_isDisposed = true;
}
}
}
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:19:06.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
/// <summary>
/// The options for a LoggerFilter.
/// </summary>
public class LoggerFilterOptions
{
/// <summary>
/// Creates a new <see cref="LoggerFilterOptions"/> instance.
/// </summary>
public LoggerFilterOptions() { }
/// <summary>
/// Gets or sets value indicating whether logging scopes are being captured. Defaults to <c>true</c>
/// </summary>
public bool CaptureScopes { get; set; } = true;
/// <summary>
/// Gets or sets the minimum level of log messages if none of the rules match.
/// </summary>
public LogLevel MinLevel { get; set; }
/// <summary>
/// Gets the collection of <see cref="LoggerFilterRule"/> used for filtering log messages.
/// </summary>
public IList<LoggerFilterRule> Rules { get; } = new List<LoggerFilterRule>();
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:19:47.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
/// <summary>
/// Defines a rule used to filter log messages
/// </summary>
public class LoggerFilterRule
{
/// <summary>
/// Creates a new <see cref="LoggerFilterRule"/> instance.
/// </summary>
/// <param name="providerName">The provider name to use in this filter rule.</param>
/// <param name="categoryName">The category name to use in this filter rule.</param>
/// <param name="logLevel">The <see cref="LogLevel"/> to use in this filter rule.</param>
/// <param name="filter">The filter to apply.</param>
public LoggerFilterRule(string providerName, string categoryName, LogLevel? logLevel, Func<string, string, LogLevel, bool> filter)
{
ProviderName = providerName;
CategoryName = categoryName;
LogLevel = logLevel;
Filter = filter;
}
/// <summary>
/// Gets the logger provider type or alias this rule applies to.
/// </summary>
public string ProviderName { get; }
/// <summary>
/// Gets the logger category this rule applies to.
/// </summary>
public string CategoryName { get; }
/// <summary>
/// Gets the minimum <see cref="LogLevel"/> of messages.
/// </summary>
public LogLevel? LogLevel { get; }
/// <summary>
/// Gets the filter delegate that would be applied to messages that passed the <see cref="LogLevel"/>.
/// </summary>
public Func<string, string, LogLevel, bool> Filter { get; }
/// <inheritdoc/>
public override string ToString()
{
return $"{nameof(ProviderName)}: '{ProviderName}', {nameof(CategoryName)}: '{CategoryName}', {nameof(LogLevel)}: '{LogLevel}', {nameof(Filter)}: '{Filter}'";
}
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:24:05.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
internal readonly struct MessageLogger
{
public MessageLogger(ILogger logger, string category, string providerTypeFullName, LogLevel? minLevel, Func<string, string, LogLevel, bool> filter)
{
Logger = logger;
Category = category;
ProviderTypeFullName = providerTypeFullName;
MinLevel = minLevel;
Filter = filter;
}
public ILogger Logger { get; }
public string Category { get; }
private string ProviderTypeFullName { get; }
public LogLevel? MinLevel { get; }
public Func<string, string, LogLevel, bool> Filter { get; }
public bool IsEnabled(LogLevel level)
{
if (MinLevel != null && level < MinLevel)
{
return false;
}
if (Filter != null)
{
return Filter(ProviderTypeFullName, Category, level);
}
return true;
}
}
internal readonly struct ScopeLogger
{
public ScopeLogger(ILogger logger, IExternalScopeProvider externalScopeProvider)
{
Logger = logger;
ExternalScopeProvider = externalScopeProvider;
}
public ILogger Logger { get; }
public IExternalScopeProvider ExternalScopeProvider { get; }
public IDisposable CreateScope<TState>(TState state)
{
if (ExternalScopeProvider != null)
{
return ExternalScopeProvider.Push(state);
}
return Logger.BeginScope<TState>(state);
}
}
/// <summary>
/// Represents a storage of common scope data.
/// </summary>
public interface IExternalScopeProvider
{
/// <summary>
/// Executes callback for each currently active scope objects in order of creation.
/// All callbacks are guaranteed to be called inline from this method.
/// </summary>
/// <param name="callback">The callback to be executed for every scope object</param>
/// <param name="state">The state object to be passed into the callback</param>
/// <typeparam name="TState">The type of state to accept.</typeparam>
void ForEachScope<TState>(Action<object, TState> callback, TState state);
/// <summary>
/// Adds scope object to the list
/// </summary>
/// <param name="state">The scope object</param>
/// <returns>The <see cref="IDisposable"/> token that removes scope on dispose.</returns>
IDisposable Push(object state);
}
/// <summary>
/// Represents a <see cref="ILoggerProvider"/> that is able to consume external scope information.
/// </summary>
public interface ISupportExternalScope
{
/// <summary>
/// Sets external scope information source for logger provider.
/// </summary>
/// <param name="scopeProvider">The provider of scope data.</param>
void SetScopeProvider(IExternalScopeProvider scopeProvider);
}
internal readonly struct LoggerInformation
{
public LoggerInformation(ILoggerProvider provider, string category) : this()
{
ProviderType = provider.GetType();
Logger = provider.CreateLogger(category);
Category = category;
ExternalScope = provider is ISupportExternalScope;
}
public ILogger Logger { get; }
public string Category { get; }
public Type ProviderType { get; }
public bool ExternalScope { get; }
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:18:17.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
internal class LoggerRuleSelector
{
private static readonly char[] WildcardChar = { '*' };
public void Select(LoggerFilterOptions options, Type providerType, string category, out LogLevel? minLevel, out Func<string, string, LogLevel, bool> filter)
{
filter = null;
minLevel = options.MinLevel;
// Filter rule selection:
// 1. Select rules for current logger type, if there is none, select ones without logger type specified
// 2. Select rules with longest matching categories
// 3. If there nothing matched by category take all rules without category
// 3. If there is only one rule use it's level and filter
// 4. If there are multiple rules use last
// 5. If there are no applicable rules use global minimal level
//var providerAlias = ProviderAliasUtilities.GetAlias(providerType);
//LoggerFilterRule current = null;
//foreach (var rule in options.Rules)
//{
// if (IsBetter(rule, current, providerType.FullName, category)
// || (!string.IsNullOrEmpty(providerAlias) && IsBetter(rule, current, providerAlias, category)))
// {
// current = rule;
// }
//}
//if (current != null)
//{
// filter = current.Filter;
// minLevel = current.LogLevel;
//}
}
private static bool IsBetter(LoggerFilterRule rule, LoggerFilterRule current, string logger, string category)
{
// Skip rules with inapplicable type or category
if (rule.ProviderName != null && rule.ProviderName != logger)
{
return false;
}
if (rule.CategoryName != null)
{
var categoryParts = rule.CategoryName.Split(WildcardChar);
if (categoryParts.Length > 2)
{
throw new InvalidOperationException("Only one wildcard character is allowed in category name.");
}
var prefix = categoryParts[0];
var suffix = categoryParts.Length > 1 ? categoryParts[1] : string.Empty;
if (!category.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) ||
!category.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
if (current?.ProviderName != null)
{
if (rule.ProviderName == null)
{
return false;
}
}
else
{
// We want to skip category check when going from no provider to having provider
if (rule.ProviderName != null)
{
return true;
}
}
if (current?.CategoryName != null)
{
if (rule.CategoryName == null)
{
return false;
}
if (current.CategoryName.Length > rule.CategoryName.Length)
{
return false;
}
}
return true;
}
}
}
//==============================================================
// Copyright (C) 2020 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2020/5/12 9:31:46.
// Version 1.0
// 种道洋
//==============================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetty.Common
{
internal class StaticFilterOptionsMonitor : IOptionsMonitor<LoggerFilterOptions>
{
public StaticFilterOptionsMonitor(LoggerFilterOptions currentValue)
{
CurrentValue = currentValue;
}
public IDisposable OnChange(Action<LoggerFilterOptions, string> listener) => null;
public LoggerFilterOptions Get(string name) => CurrentValue;
public LoggerFilterOptions CurrentValue { get; }
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册