Added sysLogServer functionality
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
namespace EonaCat.Logger
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace EonaCat.Logger
|
||||||
{
|
{
|
||||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||||
@@ -14,4 +16,84 @@
|
|||||||
CRITICAL = 6,
|
CRITICAL = 6,
|
||||||
TRACE = 7
|
TRACE = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LogTypeConverter
|
||||||
|
{
|
||||||
|
public static ELogType FromLogLevel(this LogLevel logLevel)
|
||||||
|
{
|
||||||
|
switch (logLevel)
|
||||||
|
{
|
||||||
|
case LogLevel.None:
|
||||||
|
return ELogType.NONE;
|
||||||
|
case LogLevel.Error:
|
||||||
|
return ELogType.ERROR;
|
||||||
|
case LogLevel.Debug:
|
||||||
|
return ELogType.DEBUG;
|
||||||
|
case LogLevel.Critical:
|
||||||
|
return ELogType.CRITICAL;
|
||||||
|
case LogLevel.Warning:
|
||||||
|
return ELogType.WARNING;
|
||||||
|
case LogLevel.Trace:
|
||||||
|
return ELogType.TRACE;
|
||||||
|
default:
|
||||||
|
return ELogType.INFO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ELogType FromSeverity(this ESeverity logLevel)
|
||||||
|
{
|
||||||
|
switch (logLevel)
|
||||||
|
{
|
||||||
|
case ESeverity.Debug:
|
||||||
|
return ELogType.DEBUG;
|
||||||
|
case ESeverity.Warn:
|
||||||
|
return ELogType.WARNING;
|
||||||
|
case ESeverity.Emergency:
|
||||||
|
return ELogType.CRITICAL;
|
||||||
|
case ESeverity.Critical:
|
||||||
|
return ELogType.CRITICAL;
|
||||||
|
case ESeverity.Alert:
|
||||||
|
return ELogType.ERROR;
|
||||||
|
case ESeverity.Error:
|
||||||
|
return ELogType.ERROR;
|
||||||
|
default:
|
||||||
|
return ELogType.INFO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message severity.
|
||||||
|
/// </summary>
|
||||||
|
public enum ESeverity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Debug messages.
|
||||||
|
/// </summary>
|
||||||
|
Debug = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Informational messages.
|
||||||
|
/// </summary>
|
||||||
|
Info = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Warning messages.
|
||||||
|
/// </summary>
|
||||||
|
Warn = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Error messages.
|
||||||
|
/// </summary>
|
||||||
|
Error = 3,
|
||||||
|
/// <summary>
|
||||||
|
/// Alert messages.
|
||||||
|
/// </summary>
|
||||||
|
Alert = 4,
|
||||||
|
/// <summary>
|
||||||
|
/// Critical messages.
|
||||||
|
/// </summary>
|
||||||
|
Critical = 5,
|
||||||
|
/// <summary>
|
||||||
|
/// Emergency messages.
|
||||||
|
/// </summary>
|
||||||
|
Emergency = 6
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
net6.0;
|
net6.0;
|
||||||
</TargetFrameworks>
|
</TargetFrameworks>
|
||||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.1</Version>
|
||||||
<Authors>EonaCat (Jeroen Saey)</Authors>
|
<Authors>EonaCat (Jeroen Saey)</Authors>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Company>EonaCat (Jeroen Saey)</Company>
|
<Company>EonaCat (Jeroen Saey)</Company>
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<Title>EonaCat.Logger</Title>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -16,20 +16,20 @@ namespace EonaCat.Logger.Extensions
|
|||||||
/// Adds a file logger named 'File' to the factory.
|
/// Adds a file logger named 'File' to the factory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||||
public static ILoggingBuilder AddFile(this ILoggingBuilder builder)
|
public static ILoggingBuilder AddEonaCatFileLogger(this ILoggingBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
|
builder.Services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a file logger named 'File' to the factory.
|
/// Adds the EonaCat File Logger named 'EonaCatFileLogger' to the factory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||||
/// <param name="filenamePrefix">Sets the filename prefix to use for log files</param>
|
/// <param name="filenamePrefix">Sets the filename prefix to use for log files</param>
|
||||||
public static ILoggingBuilder AddFile(this ILoggingBuilder builder, string filenamePrefix)
|
public static ILoggingBuilder AddEonaCatFileLogger(this ILoggingBuilder builder, string filenamePrefix)
|
||||||
{
|
{
|
||||||
builder.AddFile(options => options.FileNamePrefix = filenamePrefix);
|
builder.AddEonaCatFileLogger(options => options.FileNamePrefix = filenamePrefix);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,13 +38,13 @@ namespace EonaCat.Logger.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||||
/// <param name="configure">Configure an instance of the <see cref="FileLoggerOptions" /> to set logging options</param>
|
/// <param name="configure">Configure an instance of the <see cref="FileLoggerOptions" /> to set logging options</param>
|
||||||
public static ILoggingBuilder AddFile(this ILoggingBuilder builder, Action<FileLoggerOptions> configure)
|
public static ILoggingBuilder AddEonaCatFileLogger(this ILoggingBuilder builder, Action<FileLoggerOptions> configure)
|
||||||
{
|
{
|
||||||
if (configure == null)
|
if (configure == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(configure));
|
throw new ArgumentNullException(nameof(configure));
|
||||||
}
|
}
|
||||||
builder.AddFile();
|
builder.AddEonaCatFileLogger();
|
||||||
builder.Services.Configure(configure);
|
builder.Services.Configure(configure);
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace EonaCat.Logger
|
|||||||
private int _fileSizeLimit = 200 * 1024 * 1024;
|
private int _fileSizeLimit = 200 * 1024 * 1024;
|
||||||
private int _retainedFileCountLimit = 50;
|
private int _retainedFileCountLimit = 50;
|
||||||
private int _maxRolloverFiles = 10;
|
private int _maxRolloverFiles = 10;
|
||||||
|
private int _maxTries = 3;
|
||||||
|
|
||||||
public static string DefaultPath => AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
|
public static string DefaultPath => AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
|
||||||
@@ -55,6 +56,20 @@ namespace EonaCat.Logger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the max times to try to write to the file.
|
||||||
|
/// Defaults 3.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxWriteTries
|
||||||
|
{
|
||||||
|
get => _maxTries;
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_maxTries = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a strictly positive value representing the maximum retained file rollovers or null for no limit.
|
/// Gets or sets a strictly positive value representing the maximum retained file rollovers or null for no limit.
|
||||||
/// Defaults to <c>10</c>.
|
/// Defaults to <c>10</c>.
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using EonaCat.Logger.Internal;
|
using EonaCat.Logger.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -23,9 +25,37 @@ namespace EonaCat.Logger
|
|||||||
private readonly int _maxFileSize;
|
private readonly int _maxFileSize;
|
||||||
private readonly int _maxRetainedFiles;
|
private readonly int _maxRetainedFiles;
|
||||||
private readonly int _maxRolloverFiles;
|
private readonly int _maxRolloverFiles;
|
||||||
|
private readonly int _maxTries;
|
||||||
private int _rollOverCount = 0;
|
private int _rollOverCount = 0;
|
||||||
|
private static readonly object _writeLock = new object();
|
||||||
|
private string _logFile;
|
||||||
|
|
||||||
public string LogFile { get; private set; }
|
/// <summary>
|
||||||
|
/// The file to which log messages should be appended.
|
||||||
|
/// </summary>
|
||||||
|
public string LogFile
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _logFile;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_logFile = value;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_logFile))
|
||||||
|
{
|
||||||
|
string dir = Path.GetDirectoryName(_logFile);
|
||||||
|
if (!string.IsNullOrEmpty(dir))
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an instance of the <see cref="FileLoggerProvider" />
|
/// Creates an instance of the <see cref="FileLoggerProvider" />
|
||||||
@@ -39,6 +69,7 @@ namespace EonaCat.Logger
|
|||||||
_maxFileSize = loggerOptions.FileSizeLimit;
|
_maxFileSize = loggerOptions.FileSizeLimit;
|
||||||
_maxRetainedFiles = loggerOptions.RetainedFileCountLimit;
|
_maxRetainedFiles = loggerOptions.RetainedFileCountLimit;
|
||||||
_maxRolloverFiles = loggerOptions.MaxRolloverFiles;
|
_maxRolloverFiles = loggerOptions.MaxRolloverFiles;
|
||||||
|
_maxTries = loggerOptions.MaxWriteTries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -77,11 +108,31 @@ namespace EonaCat.Logger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (StreamWriter streamWriter = File.AppendText(LogFile))
|
lock (_writeLock)
|
||||||
{
|
{
|
||||||
foreach (LogMessage item in group)
|
int tries = 0;
|
||||||
|
bool completed = false;
|
||||||
|
|
||||||
|
while (!completed)
|
||||||
{
|
{
|
||||||
await streamWriter.WriteAsync(item.Message);
|
try
|
||||||
|
{
|
||||||
|
System.IO.StreamWriter file = new System.IO.StreamWriter(LogFile, true);
|
||||||
|
foreach (LogMessage item in group)
|
||||||
|
{
|
||||||
|
file.WriteAsync(item.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Close();
|
||||||
|
completed = true;
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
tries++;
|
||||||
|
Task.Delay(100);
|
||||||
|
if (tries >= _maxTries)
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using EonaCat.logger.Managers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -25,35 +26,21 @@ namespace EonaCat.Logger.Internal
|
|||||||
|
|
||||||
public bool IsEnabled(LogLevel logLevel)
|
public bool IsEnabled(LogLevel logLevel)
|
||||||
{
|
{
|
||||||
if (logLevel == LogLevel.None)
|
return logLevel != LogLevel.None;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log<TState>(DateTimeOffset timestamp, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
public void Log<TState>(DateTimeOffset timestamp, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
{
|
{
|
||||||
if (!IsEnabled(logLevel))
|
if (!IsEnabled(logLevel)) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
var message = LogHelper.FormatMessageWithHeader(new Managers.LoggerSettings(), logLevel.FromLogLevel(), formatter(state, exception)) + Environment.NewLine;
|
||||||
builder.Append(timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff zzz"));
|
|
||||||
builder.Append(" [");
|
|
||||||
builder.Append(logLevel.ToString());
|
|
||||||
builder.Append("] ");
|
|
||||||
builder.Append(_category);
|
|
||||||
builder.Append(": ");
|
|
||||||
builder.AppendLine(formatter(state, exception));
|
|
||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
{
|
{
|
||||||
builder.AppendLine(exception.ToString());
|
message = exception.FormatExceptionToMessage() + Environment.NewLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
_provider.AddMessage(timestamp, builder.ToString());
|
_provider.AddMessage(timestamp, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ namespace EonaCat.Logger.Internal
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
//cancellation token canceled or CompleteAdding called
|
// cancellation token canceled or CompleteAdding called
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,6 +128,12 @@ namespace EonaCat.Logger.Internal
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~BatchingLoggerProvider()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILogger CreateLogger(string categoryName)
|
public ILogger CreateLogger(string categoryName)
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ namespace EonaCatLogger.EonaCatCoreLogger.Models
|
|||||||
|
|
||||||
public class EonaCatLogMessage
|
public class EonaCatLogMessage
|
||||||
{
|
{
|
||||||
public DateTime DateTime { get; internal set; }
|
public DateTime DateTime { get; set; }
|
||||||
public string Message { get; internal set; }
|
public string Message { get; set; }
|
||||||
public ELogType LogType { get; internal set; }
|
public ELogType LogType { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"[{EnumHelper<ELogType>.ToString(LogType)}] [{DateTime.ToString(Constants.DateTimeFormats.LOGGING)}] {Message}";
|
return $"[{DateTime.ToString(Constants.DateTimeFormats.LOGGING)}] [{EnumHelper<ELogType>.ToString(LogType)}] {Message}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace EonaCat.Logger.Exceptions
|
||||||
|
{
|
||||||
|
public class EonaCatLoggerAssertionException : Exception
|
||||||
|
{
|
||||||
|
public EonaCatLoggerAssertionException(string message) : base(message) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
74
EonaCat.Logger/Managers/ColorSchema.cs
Normal file
74
EonaCat.Logger/Managers/ColorSchema.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace EonaCat.Logger.Managers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Colors to use when writing to the console.
|
||||||
|
/// </summary>
|
||||||
|
public class ColorSchema
|
||||||
|
{
|
||||||
|
private ConsoleColor currentForeground = Console.ForegroundColor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color to use for debug messages. Default is dark gray on black.
|
||||||
|
/// </summary>
|
||||||
|
public ColorScheme Debug = new ColorScheme(ConsoleColor.DarkGray, ConsoleColor.Black);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color to use for informational messages. Default is gray on black.
|
||||||
|
/// </summary>
|
||||||
|
public ColorScheme Info = new ColorScheme(ConsoleColor.Gray, ConsoleColor.Black);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color to use for warning messages. Default is dark red on black.
|
||||||
|
/// </summary>
|
||||||
|
public ColorScheme Warning = new ColorScheme(ConsoleColor.DarkRed, ConsoleColor.Black);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color to use for error messages. Default is red on black.
|
||||||
|
/// </summary>
|
||||||
|
public ColorScheme Error = new ColorScheme(ConsoleColor.Red, ConsoleColor.Black);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color to use for alert messages. Default is dark yellow on black.
|
||||||
|
/// </summary>
|
||||||
|
public ColorScheme Traffic = new ColorScheme(ConsoleColor.DarkYellow, ConsoleColor.Black);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color to use for critical messages. Default is yellow on black.
|
||||||
|
/// </summary>
|
||||||
|
public ColorScheme Critical = new ColorScheme(ConsoleColor.Yellow, ConsoleColor.Black);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color to use for emergency messages. Default is white on red.
|
||||||
|
/// </summary>
|
||||||
|
public ColorScheme Trace = new ColorScheme(ConsoleColor.White, ConsoleColor.Red);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Color scheme for logging messages.
|
||||||
|
/// </summary>
|
||||||
|
public class ColorScheme
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Foreground color.
|
||||||
|
/// </summary>
|
||||||
|
public ConsoleColor Foreground = Console.ForegroundColor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Background color.
|
||||||
|
/// </summary>
|
||||||
|
public ConsoleColor Background = Console.BackgroundColor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a new color scheme.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="foreground">Foreground color.</param>
|
||||||
|
/// <param name="background">Background color.</param>
|
||||||
|
public ColorScheme(ConsoleColor foreground, ConsoleColor background)
|
||||||
|
{
|
||||||
|
Foreground = foreground;
|
||||||
|
Background = background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
EonaCat.Logger/Managers/EFileLoggingMode.cs
Normal file
8
EonaCat.Logger/Managers/EFileLoggingMode.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace EonaCat.Logger.Managers
|
||||||
|
{
|
||||||
|
public enum EFileLoggingMode
|
||||||
|
{
|
||||||
|
Enabled = 0,
|
||||||
|
Disabled = 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
7
EonaCat.Logger/Managers/ILogManager.cs
Normal file
7
EonaCat.Logger/Managers/ILogManager.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace EonaCat.Logger.Managers
|
||||||
|
{
|
||||||
|
public interface ILogManager
|
||||||
|
{
|
||||||
|
void Write(string message, ELogType logType = ELogType.INFO, ELogType? logLevel = null);
|
||||||
|
}
|
||||||
|
}
|
||||||
292
EonaCat.Logger/Managers/LogHelper.cs
Normal file
292
EonaCat.Logger/Managers/LogHelper.cs
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
using EonaCat.Logger;
|
||||||
|
using EonaCat.Logger.Managers;
|
||||||
|
using EonaCat.Logger.Syslog;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace EonaCat.logger.Managers
|
||||||
|
{
|
||||||
|
public static class LogHelper
|
||||||
|
{
|
||||||
|
private static readonly object _fileLock = new object();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format a message with the specified header
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settings">Logger settings</param>
|
||||||
|
/// <param name="logType">logtype for the formatted message</param>
|
||||||
|
/// <param name="currentMessage">The actual message to format with the header</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(currentMessage))
|
||||||
|
{
|
||||||
|
return currentMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings == null)
|
||||||
|
{
|
||||||
|
return "[EonaCatLogger]" + " " + currentMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
string header = settings.HeaderFormat;
|
||||||
|
if (header.Contains("{ts}"))
|
||||||
|
{
|
||||||
|
header = header.Replace("{ts}", DateTime.Now.ToUniversalTime().ToString(settings.TimestampFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.Contains("{host}"))
|
||||||
|
{
|
||||||
|
header = header.Replace("{host}", Dns.GetHostName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.Contains("{thread}"))
|
||||||
|
{
|
||||||
|
header = header.Replace("{thread}", Thread.CurrentThread.ManagedThreadId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.Contains("{sev}"))
|
||||||
|
{
|
||||||
|
header = header.Replace("{sev}", logType.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
string fullMessage = "[EonaCatLogger]" + " " + header + " " + currentMessage;
|
||||||
|
return fullMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a given exception as a string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">exception</param>
|
||||||
|
/// <param name="module">The name of the module which called the code (optional)</param>
|
||||||
|
/// <param name="method">The name of the method which waws called in code (optional)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
|
||||||
|
{
|
||||||
|
if (exception == null) return string.Empty;
|
||||||
|
var st = new StackTrace(exception, true);
|
||||||
|
var frame = st.GetFrame(0);
|
||||||
|
int fileLine = frame.GetFileLineNumber();
|
||||||
|
string filename = frame.GetFileName();
|
||||||
|
|
||||||
|
string message =
|
||||||
|
Environment.NewLine +
|
||||||
|
"--- [EonaCatLogger] Exception details ---" + Environment.NewLine +
|
||||||
|
(!string.IsNullOrEmpty(module) ? " Module : " + module + Environment.NewLine : "") +
|
||||||
|
(!string.IsNullOrEmpty(method) ? " Method : " + method + Environment.NewLine : "") +
|
||||||
|
" Type : " + exception.GetType().ToString() + Environment.NewLine;
|
||||||
|
|
||||||
|
if (exception.Data != null && exception.Data.Count > 0)
|
||||||
|
{
|
||||||
|
message += " Data : " + Environment.NewLine;
|
||||||
|
foreach (DictionaryEntry curr in exception.Data)
|
||||||
|
{
|
||||||
|
message += " | " + curr.Key + ": " + curr.Value + Environment.NewLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message += " Data : (none)" + Environment.NewLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
message +=
|
||||||
|
" Inner : ";
|
||||||
|
|
||||||
|
if (exception.InnerException == null) message += "(null)" + Environment.NewLine;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message += exception.InnerException.GetType().ToString() + Environment.NewLine;
|
||||||
|
message +=
|
||||||
|
" Message : " + exception.InnerException.Message + Environment.NewLine +
|
||||||
|
" Source : " + exception.InnerException.Source + Environment.NewLine +
|
||||||
|
" StackTrace : " + exception.InnerException.StackTrace + Environment.NewLine +
|
||||||
|
" ToString : " + exception.InnerException.ToString() + Environment.NewLine;
|
||||||
|
|
||||||
|
if (exception.InnerException.Data != null && exception.InnerException.Data.Count > 0)
|
||||||
|
{
|
||||||
|
message += " Data : " + Environment.NewLine;
|
||||||
|
foreach (DictionaryEntry curr in exception.Data)
|
||||||
|
{
|
||||||
|
message += " | " + curr.Key + ": " + curr.Value + Environment.NewLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message += " Data : (none)" + Environment.NewLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message +=
|
||||||
|
" Message : " + exception.Message + Environment.NewLine +
|
||||||
|
" Source : " + exception.Source + Environment.NewLine +
|
||||||
|
" StackTrace : " + exception.StackTrace + Environment.NewLine +
|
||||||
|
" Line : " + fileLine + Environment.NewLine +
|
||||||
|
" File : " + filename + Environment.NewLine +
|
||||||
|
" ToString : " + exception.ToString() + Environment.NewLine +
|
||||||
|
"---";
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SendConsole(LoggerSettings settings, ELogType logType, string message)
|
||||||
|
{
|
||||||
|
if (settings == null) return;
|
||||||
|
if (!settings.EnableConsole) return;
|
||||||
|
if (string.IsNullOrWhiteSpace(message)) return;
|
||||||
|
|
||||||
|
if (settings.EnableColors)
|
||||||
|
{
|
||||||
|
ConsoleColor prevForeground = Console.ForegroundColor;
|
||||||
|
ConsoleColor prevBackground = Console.BackgroundColor;
|
||||||
|
|
||||||
|
if (settings.Colors != null)
|
||||||
|
{
|
||||||
|
switch (logType)
|
||||||
|
{
|
||||||
|
case ELogType.DEBUG:
|
||||||
|
Console.ForegroundColor = settings.Colors.Debug.Foreground;
|
||||||
|
Console.BackgroundColor = settings.Colors.Debug.Background;
|
||||||
|
break;
|
||||||
|
case ELogType.INFO:
|
||||||
|
Console.ForegroundColor = settings.Colors.Info.Foreground;
|
||||||
|
Console.BackgroundColor = settings.Colors.Info.Background;
|
||||||
|
break;
|
||||||
|
case ELogType.WARNING:
|
||||||
|
Console.ForegroundColor = settings.Colors.Warning.Foreground;
|
||||||
|
Console.BackgroundColor = settings.Colors.Warning.Background;
|
||||||
|
break;
|
||||||
|
case ELogType.ERROR:
|
||||||
|
Console.ForegroundColor = settings.Colors.Error.Foreground;
|
||||||
|
Console.BackgroundColor = settings.Colors.Error.Background;
|
||||||
|
break;
|
||||||
|
case ELogType.TRAFFIC:
|
||||||
|
Console.ForegroundColor = settings.Colors.Traffic.Foreground;
|
||||||
|
Console.BackgroundColor = settings.Colors.Traffic.Background;
|
||||||
|
break;
|
||||||
|
case ELogType.CRITICAL:
|
||||||
|
Console.ForegroundColor = settings.Colors.Critical.Foreground;
|
||||||
|
Console.BackgroundColor = settings.Colors.Critical.Background;
|
||||||
|
break;
|
||||||
|
case ELogType.TRACE:
|
||||||
|
Console.ForegroundColor = settings.Colors.Trace.Foreground;
|
||||||
|
Console.BackgroundColor = settings.Colors.Trace.Background;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(message);
|
||||||
|
Console.ForegroundColor = prevForeground;
|
||||||
|
Console.BackgroundColor = prevBackground;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SendFile(ILogger logger, LoggerSettings settings, ELogType logType, string message, int maxTries = 3)
|
||||||
|
{
|
||||||
|
lock (_fileLock)
|
||||||
|
{
|
||||||
|
if (logger == null) return;
|
||||||
|
if (settings == null) return;
|
||||||
|
if (!settings.EnableFileLogging) return;
|
||||||
|
if (string.IsNullOrWhiteSpace(message)) return;
|
||||||
|
//logger.LogInformation(message);
|
||||||
|
|
||||||
|
int tries = 0;
|
||||||
|
bool completed = false;
|
||||||
|
while (!completed)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.IO.StreamWriter file = new System.IO.StreamWriter($"{settings.FileLoggerOptions.LogDirectory}{Path.DirectorySeparatorChar}{settings.FileLoggerOptions.FileNamePrefix}_{DateTime.Now.ToString("yyyyMMdd")}.log", true);
|
||||||
|
file.Write(message + Environment.NewLine);
|
||||||
|
file.Close();
|
||||||
|
completed = true;
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
tries++;
|
||||||
|
Task.Delay(100);
|
||||||
|
if (tries >= maxTries)
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (logType == ELogType.CRITICAL)
|
||||||
|
{
|
||||||
|
logger.LogCritical(message);
|
||||||
|
}
|
||||||
|
else if (logType == ELogType.DEBUG)
|
||||||
|
{
|
||||||
|
logger.LogDebug(message);
|
||||||
|
}
|
||||||
|
else if (logType == ELogType.ERROR)
|
||||||
|
{
|
||||||
|
logger.LogError(message);
|
||||||
|
}
|
||||||
|
else if (logType == ELogType.INFO)
|
||||||
|
{
|
||||||
|
logger.LogInformation(message);
|
||||||
|
}
|
||||||
|
else if (logType == ELogType.TRACE)
|
||||||
|
{
|
||||||
|
logger.LogTrace(message);
|
||||||
|
}
|
||||||
|
else if (logType == ELogType.TRAFFIC)
|
||||||
|
{
|
||||||
|
logger.LogTrace($"[TRAFFIC] {message}");
|
||||||
|
}
|
||||||
|
else if (logType == ELogType.WARNING)
|
||||||
|
{
|
||||||
|
logger.LogWarning(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SendToSysLogServers(LoggerSettings settings, string message)
|
||||||
|
{
|
||||||
|
if (settings == null) return;
|
||||||
|
if (!settings.SendToSyslogServers) return;
|
||||||
|
if (settings.SysLogServers == null) return;
|
||||||
|
if (!settings.SysLogServers.Any()) return;
|
||||||
|
if (string.IsNullOrWhiteSpace(message)) return;
|
||||||
|
|
||||||
|
byte[] data = Encoding.UTF8.GetBytes(message);
|
||||||
|
|
||||||
|
var sysLogServers = settings.SysLogServers.ToList();
|
||||||
|
foreach (SyslogServer server in sysLogServers)
|
||||||
|
{
|
||||||
|
lock (server.SendLock)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(server.Hostname))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Server hostname not specified, skipping syslog server");
|
||||||
|
}
|
||||||
|
if (server.Port < 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Server port must be zero or greater, skipping syslog server");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
server.Udp.Send(data, data.Length);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
using EonaCat.Extensions;
|
using EonaCat.logger.Managers;
|
||||||
|
using EonaCat.Logger.Exceptions;
|
||||||
using EonaCat.Logger.Extensions;
|
using EonaCat.Logger.Extensions;
|
||||||
using EonaCat.Logger.Helpers;
|
using EonaCat.Logger.Helpers;
|
||||||
|
using EonaCat.Logger.Syslog;
|
||||||
using EonaCatLogger.EonaCatCoreLogger.Models;
|
using EonaCatLogger.EonaCatCoreLogger.Models;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -16,11 +20,15 @@ namespace EonaCat.Logger.Managers
|
|||||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||||
|
|
||||||
public class LogManager : IDisposable
|
public partial class LogManager : ILogManager, IDisposable
|
||||||
{
|
{
|
||||||
private readonly object _batton = new object();
|
private readonly object _batton = new object();
|
||||||
private DateTime _logDate;
|
private DateTime _logDate;
|
||||||
|
public event LogDelegate OnLog;
|
||||||
|
public delegate void LogDelegate(LogManager logger, ELogType logLevel, EonaCatLogMessage message);
|
||||||
|
|
||||||
|
|
||||||
|
public ELogType LogType;
|
||||||
private ILoggerProvider LoggerProvider { get; set; }
|
private ILoggerProvider LoggerProvider { get; set; }
|
||||||
private ILoggerFactory LoggerFactory { get; set; }
|
private ILoggerFactory LoggerFactory { get; set; }
|
||||||
private ILogger Logger { get; set; }
|
private ILogger Logger { get; set; }
|
||||||
@@ -29,13 +37,50 @@ namespace EonaCat.Logger.Managers
|
|||||||
public bool IsRunning { get; private set; }
|
public bool IsRunning { get; private set; }
|
||||||
|
|
||||||
public StreamWriter Output { get; private set; }
|
public StreamWriter Output { get; private set; }
|
||||||
public string LogFolderPath { get; set; } = "logs";
|
|
||||||
public FileLoggerOptions FileLoggerOptions { get; private set; }
|
|
||||||
public int FileSizeLimit { get; set; } = 200 * 1024 * 1024;
|
|
||||||
public string CategoryName { get; set; }
|
public string CategoryName { get; set; }
|
||||||
private LogManager Instance { get; set; }
|
|
||||||
|
public readonly string Id;
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
private static LogManager _instance;
|
||||||
|
private LoggerSettings _settings;
|
||||||
|
private CancellationTokenSource _TokenSource = new CancellationTokenSource();
|
||||||
|
private CancellationToken _Token;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default Logger Instance with it's default configuration
|
||||||
|
/// </summary>
|
||||||
|
public static LogManager Instance => InstanceInit();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logging settings.
|
||||||
|
/// </summary>
|
||||||
|
public LoggerSettings Settings
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_settings == null)
|
||||||
|
{
|
||||||
|
_settings = new LoggerSettings();
|
||||||
|
}
|
||||||
|
return _settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_settings = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LogManager InstanceInit()
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
_instance = new LogManager(null, id: "EonaCat");
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
@@ -49,47 +94,20 @@ namespace EonaCat.Logger.Managers
|
|||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
StopLogging();
|
StopLogging();
|
||||||
|
_TokenSource.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task DownloadLogAsync(HttpResponse response, string logFile, long limit)
|
|
||||||
{
|
|
||||||
using (FileStream fileStream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
||||||
{
|
|
||||||
response.ContentType = "text/plain";
|
|
||||||
response.Headers.Add("Content-Disposition", "attachment;filename=" + Path.GetFileName(logFile));
|
|
||||||
|
|
||||||
if (limit > fileStream.Length)
|
|
||||||
{
|
|
||||||
limit = fileStream.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (OffsetStream offsetStream = new OffsetStream(fileStream, 0, limit))
|
|
||||||
{
|
|
||||||
using (Stream stream = response.Body)
|
|
||||||
{
|
|
||||||
offsetStream.CopyTo(stream);
|
|
||||||
|
|
||||||
if (fileStream.Length > limit)
|
|
||||||
{
|
|
||||||
byte[] buffer = Encoding.UTF8.GetBytes("####___EonaCatLogger_TRUNCATED___####");
|
|
||||||
await stream.WriteAsync(buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartNewLog()
|
private void StartNewLog()
|
||||||
{
|
{
|
||||||
|
if (_TokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.Now;
|
||||||
|
|
||||||
if (IsRunning && now.Date > _logDate.Date)
|
if (IsRunning && now.Date > _logDate.Date)
|
||||||
@@ -99,143 +117,157 @@ namespace EonaCat.Logger.Managers
|
|||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
|
|
||||||
IServiceCollection serviceCollection = new ServiceCollection();
|
IServiceCollection serviceCollection = new ServiceCollection();
|
||||||
CreateDefaultFileLoggerOptions();
|
serviceCollection.AddLogging(builder => builder.AddEonaCatFileLogger(configuration =>
|
||||||
|
|
||||||
serviceCollection.AddLogging(builder => builder.AddFile(configuration =>
|
|
||||||
{
|
{
|
||||||
configuration.BackgroundQueueSize = FileLoggerOptions.BackgroundQueueSize;
|
configuration = Settings.FileLoggerOptions;
|
||||||
configuration.BatchSize = FileLoggerOptions.BatchSize;
|
|
||||||
configuration.FileNamePrefix = FileLoggerOptions.FileNamePrefix;
|
|
||||||
configuration.FileSizeLimit = FileLoggerOptions.FileSizeLimit;
|
|
||||||
configuration.FlushPeriod = FileLoggerOptions.FlushPeriod;
|
|
||||||
configuration.IsEnabled = FileLoggerOptions.IsEnabled;
|
|
||||||
configuration.LogDirectory = FileLoggerOptions.LogDirectory;
|
|
||||||
configuration.RetainedFileCountLimit = FileLoggerOptions.RetainedFileCountLimit;
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||||
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
||||||
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
||||||
|
|
||||||
CategoryName = CategoryName ?? string.Empty;
|
CategoryName = CategoryName ?? string.Empty;
|
||||||
Logger = LoggerFactory.CreateLogger(CategoryName);
|
Logger = LoggerFactory.CreateLogger(CategoryName);
|
||||||
|
|
||||||
if (!Directory.Exists(FileLoggerOptions.LogDirectory))
|
if (!Directory.Exists(Settings.FileLoggerOptions.LogDirectory))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(FileLoggerOptions.LogDirectory);
|
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logDate = now;
|
_logDate = now;
|
||||||
|
|
||||||
Write(now, "EonaCatLogger started.");
|
Write(now, $"{DllInfo.ApplicationName} started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateDefaultFileLoggerOptions()
|
public void Assert(bool condition, string message)
|
||||||
{
|
{
|
||||||
if (FileLoggerOptions == null)
|
if (!condition)
|
||||||
{
|
{
|
||||||
FileLoggerOptions = new FileLoggerOptions
|
throw new EonaCatLoggerAssertionException(message);
|
||||||
{
|
|
||||||
LogDirectory = LogFolderPath,
|
|
||||||
FileSizeLimit = FileSizeLimit
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteToFile(EonaCatLogMessage EonaCatLogMessage)
|
|
||||||
{
|
|
||||||
if (EonaCatLogMessage.LogType == ELogType.CRITICAL)
|
|
||||||
{
|
|
||||||
Instance.Logger.LogCritical(EonaCatLogMessage.Message);
|
|
||||||
}
|
|
||||||
else if (EonaCatLogMessage.LogType == ELogType.DEBUG)
|
|
||||||
{
|
|
||||||
Instance.Logger.LogDebug(EonaCatLogMessage.Message);
|
|
||||||
}
|
|
||||||
else if (EonaCatLogMessage.LogType == ELogType.ERROR)
|
|
||||||
{
|
|
||||||
Instance.Logger.LogError(EonaCatLogMessage.Message);
|
|
||||||
}
|
|
||||||
else if (EonaCatLogMessage.LogType == ELogType.INFO)
|
|
||||||
{
|
|
||||||
Instance.Logger.LogInformation(EonaCatLogMessage.Message);
|
|
||||||
}
|
|
||||||
else if (EonaCatLogMessage.LogType == ELogType.TRACE)
|
|
||||||
{
|
|
||||||
Instance.Logger.LogTrace(EonaCatLogMessage.Message);
|
|
||||||
}
|
|
||||||
else if (EonaCatLogMessage.LogType == ELogType.TRAFFIC)
|
|
||||||
{
|
|
||||||
Instance.Logger.LogTrace($"[TRAFFIC] {EonaCatLogMessage.Message}");
|
|
||||||
}
|
|
||||||
else if (EonaCatLogMessage.LogType == ELogType.WARNING)
|
|
||||||
{
|
|
||||||
Instance.Logger.LogWarning(EonaCatLogMessage.Message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Write(DateTime dateTime, string message, ELogType logType = ELogType.INFO)
|
private void Write(DateTime dateTime, string message, ELogType logType = ELogType.INFO)
|
||||||
{
|
{
|
||||||
var EonaCatMessage = new EonaCatLogMessage { DateTime = dateTime, Message = message, LogType = logType };
|
if (string.IsNullOrWhiteSpace(message)) return;
|
||||||
WriteToFile(EonaCatMessage);
|
if (logType < ELogType.INFO) return;
|
||||||
|
|
||||||
|
string remainder = "";
|
||||||
|
string currentMessage;
|
||||||
|
|
||||||
|
if (message.Length > _settings.MaxMessageLength)
|
||||||
|
{
|
||||||
|
currentMessage = message.Substring(0, _settings.MaxMessageLength);
|
||||||
|
remainder = message.Substring(_settings.MaxMessageLength, (message.Length - _settings.MaxMessageLength));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentMessage = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullMessage = LogHelper.FormatMessageWithHeader(_settings, logType, currentMessage);
|
||||||
|
|
||||||
|
LogHelper.SendConsole(_settings, logType, fullMessage);
|
||||||
|
|
||||||
|
LogHelper.SendFile(Logger, _settings, logType, fullMessage);
|
||||||
|
|
||||||
|
LogHelper.SendToSysLogServers(_settings, fullMessage);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(remainder))
|
||||||
|
{
|
||||||
|
Write(dateTime, remainder, logType);
|
||||||
|
}
|
||||||
|
|
||||||
|
var EonaCatMessage = new EonaCatLogMessage { DateTime = dateTime, Message = currentMessage, LogType = logType };
|
||||||
|
OnLog?.Invoke(this, logType, EonaCatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LogManager()
|
public void Reset() => OnLog = null;
|
||||||
{
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogManager(FileLoggerOptions fileLoggerOptions)
|
public LogManager(LoggerSettings settings, string serverIp, int serverPort, string id = "EonaCatLogger")
|
||||||
{
|
{
|
||||||
FileLoggerOptions = fileLoggerOptions;
|
if (string.IsNullOrEmpty(serverIp)) throw new ArgumentNullException(nameof(serverIp));
|
||||||
|
if (serverPort < 0) throw new ArgumentException("Server port must be zero or greater.");
|
||||||
|
|
||||||
|
settings.SysLogServers = new List<SyslogServer>();
|
||||||
|
settings.SysLogServers.Add(new SyslogServer(serverIp, serverPort));
|
||||||
|
|
||||||
|
Id = id;
|
||||||
|
Settings = settings;
|
||||||
SetupLogManager();
|
SetupLogManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupLogManager()
|
public LogManager(LoggerSettings settings, string id = "EonaCatLogger")
|
||||||
{
|
{
|
||||||
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
Id = id;
|
||||||
|
Settings = settings;
|
||||||
Instance = this;
|
SetupFileLogger(settings, null, true);
|
||||||
|
SetupLogManager();
|
||||||
_logDate = DateTime.Now;
|
|
||||||
|
|
||||||
StartNewLog();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessExit(object sender, EventArgs e)
|
private void SetupFileLogger(LoggerSettings settings = null, string logFolder = null, bool defaultPrefix = true)
|
||||||
{
|
{
|
||||||
Instance?.StopLogging();
|
if (settings == null)
|
||||||
Thread.Sleep(1000);
|
{
|
||||||
}
|
// Create default loggingSettings
|
||||||
|
Settings = settings;
|
||||||
|
settings = Settings;
|
||||||
|
}
|
||||||
|
|
||||||
private void StopLogging()
|
if (!settings.EnableFileLogging) return;
|
||||||
{
|
|
||||||
Write(DateTime.Now, "EonaCatLogger stopped.");
|
|
||||||
IsRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogManager(string logFolder = null, bool defaultPrefix = true)
|
|
||||||
{
|
|
||||||
CreateDefaultFileLoggerOptions();
|
|
||||||
if (logFolder != null)
|
if (logFolder != null)
|
||||||
{
|
{
|
||||||
FileLoggerOptions.LogDirectory = logFolder;
|
Settings.FileLoggerOptions.LogDirectory = logFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultPrefix)
|
if (defaultPrefix)
|
||||||
{
|
{
|
||||||
FileLoggerOptions.FileNamePrefix = "EonaCat";
|
Settings.FileLoggerOptions.FileNamePrefix = "EonaCat";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileLoggerOptions.FileNamePrefix = string.Empty;
|
Settings.FileLoggerOptions.FileNamePrefix = string.Empty;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupLogManager()
|
||||||
|
{
|
||||||
|
_Token = _TokenSource.Token;
|
||||||
|
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
||||||
|
|
||||||
|
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
|
||||||
|
|
||||||
|
_logDate = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessExit(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopLogging()
|
||||||
|
{
|
||||||
|
IsRunning = false;
|
||||||
|
Write(DateTime.Now, $"{DllInfo.ApplicationName} stopped.");
|
||||||
|
Task.Delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogManager(string logFolder = null, bool defaultPrefix = true)
|
||||||
|
{
|
||||||
|
SetupFileLogger(null, logFolder, defaultPrefix);
|
||||||
SetupLogManager();
|
SetupLogManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(Exception exception)
|
public void Write(Exception exception, string module = null, string method = null, bool criticalException = false)
|
||||||
{
|
{
|
||||||
Write(exception.ToString());
|
if (exception != null) return;
|
||||||
|
Write(exception.FormatExceptionToMessage(module, method), criticalException ? ELogType.CRITICAL : ELogType.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(string message, ELogType logType = ELogType.INFO, ELogType? logLevel = null)
|
public void Write(string message, ELogType logType = ELogType.INFO, ELogType? logLevel = null)
|
||||||
@@ -256,7 +288,7 @@ namespace EonaCat.Logger.Managers
|
|||||||
StartNewLog();
|
StartNewLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
Write(now, $"{DllInfo.ApplicationName}: {message}", logType);
|
Write(now, message, logType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,8 +301,12 @@ namespace EonaCat.Logger.Managers
|
|||||||
{
|
{
|
||||||
File.Delete(CurrentLogFile);
|
File.Delete(CurrentLogFile);
|
||||||
}
|
}
|
||||||
StartNewLog();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
173
EonaCat.Logger/Managers/LoggerSettings.cs
Normal file
173
EonaCat.Logger/Managers/LoggerSettings.cs
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using EonaCat.Logger.Syslog;
|
||||||
|
using System.Runtime;
|
||||||
|
|
||||||
|
namespace EonaCat.Logger.Managers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logger settings.
|
||||||
|
/// </summary>
|
||||||
|
public class LoggerSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Header format. Provide a string that specifies how the preamble of each message should be structured. You can use variables including:
|
||||||
|
/// {ts}: UTC timestamp
|
||||||
|
/// {host}: Hostname
|
||||||
|
/// {thread}: Thread ID
|
||||||
|
/// {sev}: Severity
|
||||||
|
/// Default: {ts} {host} {thread} {sev}
|
||||||
|
/// A space will be inserted between the header and the message.
|
||||||
|
/// </summary>
|
||||||
|
public string HeaderFormat
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _HeaderFormat;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value)) _HeaderFormat = "";
|
||||||
|
else _HeaderFormat = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Timestamp format.
|
||||||
|
/// </summary>
|
||||||
|
public string TimestampFormat
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _TimestampFormat;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(HeaderFormat));
|
||||||
|
_TimestampFormat = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable or disable console logging.
|
||||||
|
/// Settings this to true will first validate if a console exists.
|
||||||
|
/// If a console is not available, it will be set to false.
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableConsole
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _EnableConsole;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value) _EnableConsole = ConsoleExists();
|
||||||
|
else _EnableConsole = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum severity required to send a message.
|
||||||
|
/// </summary>
|
||||||
|
public ESeverity MinimumSeverity { get; set; } = ESeverity.Debug;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable or disable use of color for console messages.
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableColors { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colors to use for console messages based on message severity.
|
||||||
|
/// </summary>
|
||||||
|
public ColorSchema Colors
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _colors;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(Colors));
|
||||||
|
}
|
||||||
|
_colors = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SendToSyslogServers { get; set; }
|
||||||
|
|
||||||
|
public List<SyslogServer> SysLogServers { get; set; } = new List<SyslogServer> { new SyslogServer("127.0.0.1", 514) };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the fileLogging is enabled
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableFileLogging { get; set; } = true;
|
||||||
|
|
||||||
|
private FileLoggerOptions _fileLoggerOptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FileLogger settings.
|
||||||
|
/// </summary>
|
||||||
|
public FileLoggerOptions FileLoggerOptions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_fileLoggerOptions == null)
|
||||||
|
{
|
||||||
|
_fileLoggerOptions = CreateDefaultFileLoggerOptions();
|
||||||
|
}
|
||||||
|
return _fileLoggerOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_fileLoggerOptions = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileLoggerOptions CreateDefaultFileLoggerOptions()
|
||||||
|
{
|
||||||
|
return new FileLoggerOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum message length. Must be greater than or equal to 32. Default is 1024.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxMessageLength
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _MaxMessageLength;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 32) throw new ArgumentException("Maximum message length must be at least 32.");
|
||||||
|
_MaxMessageLength = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _HeaderFormat = "{ts} {host} {thread} {sev}";
|
||||||
|
private string _TimestampFormat = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
private bool _EnableConsole = true;
|
||||||
|
private int _MaxMessageLength = 1024;
|
||||||
|
private ColorSchema _colors = new ColorSchema();
|
||||||
|
|
||||||
|
|
||||||
|
private bool ConsoleExists()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool test1 = Environment.UserInteractive;
|
||||||
|
bool test2 = Console.WindowHeight > 0;
|
||||||
|
return test1 && test2;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
89
EonaCat.Logger/Syslog/SyslogServer.cs
Normal file
89
EonaCat.Logger/Syslog/SyslogServer.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace EonaCat.Logger.Syslog
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Syslog server.
|
||||||
|
/// </summary>
|
||||||
|
public class SyslogServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Hostname.
|
||||||
|
/// </summary>
|
||||||
|
public string Hostname
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _Hostname;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(Hostname));
|
||||||
|
_Hostname = value;
|
||||||
|
|
||||||
|
SetUdp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UDP port.
|
||||||
|
/// </summary>
|
||||||
|
public int Port
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _Port;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0) throw new ArgumentException("Port must be zero or greater.");
|
||||||
|
_Port = value;
|
||||||
|
|
||||||
|
SetUdp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IP:port of the server.
|
||||||
|
/// </summary>
|
||||||
|
public string IpPort
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _Hostname + ":" + _Port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly object SendLock = new object();
|
||||||
|
internal UdpClient Udp = null;
|
||||||
|
private string _Hostname = "127.0.0.1";
|
||||||
|
private int _Port = 514;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiate the object.
|
||||||
|
/// </summary>
|
||||||
|
public SyslogServer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiate the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hostname">Hostname.</param>
|
||||||
|
/// <param name="port">Port.</param>
|
||||||
|
public SyslogServer(string hostname = "127.0.0.1", int port = 514)
|
||||||
|
{
|
||||||
|
Hostname = hostname;
|
||||||
|
Port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetUdp()
|
||||||
|
{
|
||||||
|
Udp = null;
|
||||||
|
Udp = new UdpClient(_Hostname, _Port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
README.md
10
README.md
@@ -2,4 +2,12 @@
|
|||||||
|
|
||||||
EonaCat Logger
|
EonaCat Logger
|
||||||
|
|
||||||
Log application information to log files
|
Log application information to log files
|
||||||
|
|
||||||
|
|
||||||
|
Be sure the following dependencies are added:
|
||||||
|
|
||||||
|
Microsoft.Extensions.Logging.Abstractions
|
||||||
|
Microsoft.Extensions.DependencyInjection.Abstractions
|
||||||
|
Microsoft.Extensions.DependencyInjection
|
||||||
|
Microsoft.Extensions.Logging
|
||||||
Reference in New Issue
Block a user