Files
EonaCat.Logger/EonaCat.Logger/Managers/LogManager.cs
2023-10-18 12:58:32 +02:00

261 lines
10 KiB
C#

using EonaCat.Logger.Syslog;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using EonaCat.Logger.EonaCatCoreLogger;
using EonaCat.Logger.EonaCatCoreLogger.Extensions;
using EonaCat.Logger.EonaCatCoreLogger.Models;
using EonaCat.Logger.Extensions;
namespace EonaCat.Logger.Managers
{
// 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.
public partial class LogManager : ILogManager, IDisposable
{
public event EventHandler<ErrorMessage> OnException;
private DateTime CurrentDateTme => Settings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;
private DateTime _logDate;
public ILoggerProvider LoggerProvider { get; private set; }
public ILoggerFactory LoggerFactory { get; private set; }
public ILogger Logger { get; private set; }
public string CurrentLogFile => LoggerProvider is FileLoggerProvider fileLoggerProvider ? fileLoggerProvider.LogFile : string.Empty;
public bool IsRunning { get; private set; }
private static LogManager _instance;
private readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
public static LogManager Instance => InstanceInit();
public LoggerSettings Settings { get; set; } = CreateDefaultSettings();
private static LogManager InstanceInit()
{
if (_instance == null)
{
_instance = new LogManager(CreateDefaultSettings());
}
return _instance;
}
private static LoggerSettings CreateDefaultSettings()
{
var settings = new LoggerSettings();
settings.Id = "EonaCatLogger";
settings.MaxLogType = ELogType.TRACE;
return settings;
}
protected virtual async Task DisposeAsync(bool disposing)
{
if (disposing)
{
await StopLoggingAsync().ConfigureAwait(false);
}
}
public async Task StartNewLogAsync()
{
if (_tokenSource.IsCancellationRequested)
return;
if (IsRunning && CurrentDateTme.Date > _logDate.Date)
await StopLoggingAsync().ConfigureAwait(false);
IsRunning = true;
CreateLogger();
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
_logDate = CurrentDateTme;
}
private void CreateLogger()
{
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(builder => builder.SetMinimumLevel(Settings.MaxLogType.ToLogLevel()).AddEonaCatFileLogger(configuration =>
{
var fileLoggerOptions = Settings.FileLoggerOptions;
configuration.MaxWriteTries = fileLoggerOptions.MaxWriteTries;
configuration.RetainedFileCountLimit = fileLoggerOptions.RetainedFileCountLimit;
configuration.FlushPeriod = fileLoggerOptions.FlushPeriod;
configuration.IsEnabled = fileLoggerOptions.IsEnabled;
configuration.BatchSize = fileLoggerOptions.BatchSize;
configuration.FileSizeLimit = fileLoggerOptions.FileSizeLimit;
configuration.LogDirectory = fileLoggerOptions.LogDirectory;
configuration.FileNamePrefix = fileLoggerOptions.FileNamePrefix;
configuration.MaxRolloverFiles = fileLoggerOptions.MaxRolloverFiles;
configuration.UseLocalTime = Settings.UseLocalTime;
}));
var serviceProvider = serviceCollection.BuildServiceProvider();
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
Logger = LoggerFactory.CreateLogger(Settings.Id);
}
private void InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null, bool? sendToSyslogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null, string grayLogVersion = "1.1")
{
if (string.IsNullOrEmpty(message) || logType == ELogType.NONE || (int)logType >= (int)Settings.MaxLogType)
return;
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime);
writeToConsole ??= Settings.EnableConsole;
if (writeToConsole.Value)
{
LogHelper.SendToConsole(Settings, logType, messageWithHeader, true);
}
Task.Run(() => { LogHelper.SendToFile(Logger, Settings, logType, message); });
sendToSyslogServers ??= Settings.SendToSyslogServers;
if (sendToSyslogServers.Value)
{
Task.Run(async () =>
{
await LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader, true);
});
}
sendToSplunkServers ??= Settings.SendToSplunkServers;
if (sendToSplunkServers.Value)
{
Task.Run(async () =>
{
await LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(), messageWithHeader, true);
});
}
sendToGrayLogServers ??= Settings.SendToGrayLogServers;
if (sendToGrayLogServers.Value)
{
Task.Run(async () =>
{
await LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility, grayLogSource, true, grayLogVersion);
});
}
var logMessage = new EonaCatLogMessage
{
DateTime = dateTime,
Message = message,
LogType = logType,
Origin = string.IsNullOrWhiteSpace(Settings.LogOrigin) ? "LogManager" : Settings.LogOrigin
};
Settings.OnLogEvent(logMessage);
}
public void Reset() => Settings.ResetLogEvent();
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
{
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>
{
new SyslogServer(serverIp, serverPort)
};
Settings = settings;
SetupLogManager();
}
public LogManager(LoggerSettings settings)
{
Settings = settings;
SetupFileLogger(settings, null, true);
SetupLogManager();
LogHelper.OnException += LogHelper_OnException;
}
private void LogHelper_OnException(object sender, ErrorMessage e)
{
OnException?.Invoke(sender, e);
}
private void SetupFileLogger(LoggerSettings settings = null, string logFolder = null, bool defaultPrefix = true)
{
if (settings == null)
settings = Settings;
if (!settings.EnableFileLogging)
return;
if (logFolder != null)
settings.FileLoggerOptions.LogDirectory = logFolder;
if (string.IsNullOrWhiteSpace(settings.FileLoggerOptions.FileNamePrefix))
settings.FileLoggerOptions.FileNamePrefix = defaultPrefix ? "EonaCat" : string.Empty;
}
private void SetupLogManager()
{
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
Console.CancelKeyPress += Console_CancelKeyPress;
_logDate = CurrentDateTme;
}
private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Dispose();
}
private void ProcessExit(object sender, EventArgs e)
{
Dispose();
}
private Task StopLoggingAsync()
{
IsRunning = false;
InternalWriteAsync(CurrentDateTme, $"{DllInfo.ApplicationName} stopped.");
return Task.Delay(500);
}
public void DeleteCurrentLogFile()
{
if (CurrentLogFile != null)
File.Delete(CurrentLogFile);
}
public void Dispose()
{
DisposeAsync(true).GetAwaiter().GetResult();
GC.SuppressFinalize(this);
}
public void Write(Exception exception, string module = null, string method = null, bool criticalException = false, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null, string grayLogVersion = "1.1")
{
if (exception == null)
return;
Write(exception.FormatExceptionToMessage(module, method), criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion);
}
public void Write(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null, string grayLogVersion = "1.1")
{
if (logType == ELogType.NONE)
return;
if (!IsRunning)
StartNewLogAsync().ConfigureAwait(false);
InternalWriteAsync(CurrentDateTme, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion);
}
}
}