mirror of
https://github.com/hmaxnl/DotBased.git
synced 2024-11-09 23:04:20 +01:00
Initial commit
This commit is contained in:
parent
36c89e6048
commit
1785433a67
53
.gitignore
vendored
53
.gitignore
vendored
|
@ -1,7 +1,10 @@
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
##
|
##
|
||||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# JetBrains ide
|
||||||
|
.idea/
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.rsuser
|
*.rsuser
|
||||||
|
@ -23,7 +26,6 @@ mono_crash.*
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
x64/
|
||||||
x86/
|
x86/
|
||||||
[Ww][Ii][Nn]32/
|
|
||||||
[Aa][Rr][Mm]/
|
[Aa][Rr][Mm]/
|
||||||
[Aa][Rr][Mm]64/
|
[Aa][Rr][Mm]64/
|
||||||
bld/
|
bld/
|
||||||
|
@ -62,9 +64,6 @@ project.lock.json
|
||||||
project.fragment.lock.json
|
project.fragment.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
|
|
||||||
# ASP.NET Scaffolding
|
|
||||||
ScaffoldingReadMe.txt
|
|
||||||
|
|
||||||
# StyleCop
|
# StyleCop
|
||||||
StyleCopReport.xml
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
@ -90,7 +89,6 @@ StyleCopReport.xml
|
||||||
*.tmp_proj
|
*.tmp_proj
|
||||||
*_wpftmp.csproj
|
*_wpftmp.csproj
|
||||||
*.log
|
*.log
|
||||||
*.tlog
|
|
||||||
*.vspscc
|
*.vspscc
|
||||||
*.vssscc
|
*.vssscc
|
||||||
.builds
|
.builds
|
||||||
|
@ -142,11 +140,6 @@ _TeamCity*
|
||||||
.axoCover/*
|
.axoCover/*
|
||||||
!.axoCover/settings.json
|
!.axoCover/settings.json
|
||||||
|
|
||||||
# Coverlet is a free, cross platform Code Coverage Tool
|
|
||||||
coverage*.json
|
|
||||||
coverage*.xml
|
|
||||||
coverage*.info
|
|
||||||
|
|
||||||
# Visual Studio code coverage results
|
# Visual Studio code coverage results
|
||||||
*.coverage
|
*.coverage
|
||||||
*.coveragexml
|
*.coveragexml
|
||||||
|
@ -294,17 +287,6 @@ node_modules/
|
||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
*.vbw
|
*.vbw
|
||||||
|
|
||||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
|
|
||||||
*.vbp
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
|
||||||
*.dsw
|
|
||||||
*.dsp
|
|
||||||
|
|
||||||
# Visual Studio 6 technical files
|
|
||||||
*.ncb
|
|
||||||
*.aps
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
# Visual Studio LightSwitch build output
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
@ -361,9 +343,6 @@ ASALocalRun/
|
||||||
# Local History for Visual Studio
|
# Local History for Visual Studio
|
||||||
.localhistory/
|
.localhistory/
|
||||||
|
|
||||||
# Visual Studio History (VSHistory) files
|
|
||||||
.vshistory/
|
|
||||||
|
|
||||||
# BeatPulse healthcheck temp database
|
# BeatPulse healthcheck temp database
|
||||||
healthchecksdb
|
healthchecksdb
|
||||||
|
|
||||||
|
@ -372,27 +351,3 @@ MigrationBackup/
|
||||||
|
|
||||||
# Ionide (cross platform F# VS Code tools) working folder
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
.ionide/
|
.ionide/
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
|
||||||
FodyWeavers.xsd
|
|
||||||
|
|
||||||
# VS Code files for those working on multiple tools
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/settings.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/extensions.json
|
|
||||||
*.code-workspace
|
|
||||||
|
|
||||||
# Local History for Visual Studio Code
|
|
||||||
.history/
|
|
||||||
|
|
||||||
# Windows Installer files from build outputs
|
|
||||||
*.cab
|
|
||||||
*.msi
|
|
||||||
*.msix
|
|
||||||
*.msm
|
|
||||||
*.msp
|
|
||||||
|
|
||||||
# JetBrains Rider
|
|
||||||
*.sln.iml
|
|
||||||
|
|
21
CLI/CLI.csproj
Normal file
21
CLI/CLI.csproj
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DotBased.Log.Serilog\DotBased.Log.Serilog.csproj" />
|
||||||
|
<ProjectReference Include="..\DotBased\DotBased.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
30
CLI/Program.cs
Normal file
30
CLI/Program.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// See https://aka.ms/new-console-template for more information
|
||||||
|
|
||||||
|
using DotBased.Log.Serilog;
|
||||||
|
using DotBased.Logging;
|
||||||
|
using Serilog;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
var serilogLogger = SetupSerilog();
|
||||||
|
|
||||||
|
LogService.AddLogAdapter(new SerilogAdapter(serilogLogger));
|
||||||
|
|
||||||
|
var logger = LogService.RegisterLogger(nameof(Program));
|
||||||
|
|
||||||
|
logger.Trace("Test TRACE log! {StringValue} {AnotherValue}", "WOW", "W0W");
|
||||||
|
logger.Debug("Test DEBUG log! {IntVal}", 69);
|
||||||
|
logger.Information("Test INFO log! {DoubVal}", 4.20);
|
||||||
|
logger.Warning("Test WARNING log! {StrVal} {IntVAl} {StrChar}", "Over", 9000, '!');
|
||||||
|
logger.Error(new NullReferenceException("Test exception"),"Test ERROR log!");
|
||||||
|
logger.Fatal(new NullReferenceException("Test exception"),"Test FATAL log!");
|
||||||
|
|
||||||
|
Console.ReadKey();
|
||||||
|
|
||||||
|
|
||||||
|
ILogger SetupSerilog()
|
||||||
|
{
|
||||||
|
LoggerConfiguration logConfig = new LoggerConfiguration()
|
||||||
|
.MinimumLevel.Verbose()
|
||||||
|
.WriteTo.Console(outputTemplate: SerilogAdapter.SampleTemplate);
|
||||||
|
return logConfig.CreateLogger();
|
||||||
|
}
|
17
DotBased.Log.Serilog/DotBased.Log.Serilog.csproj
Normal file
17
DotBased.Log.Serilog/DotBased.Log.Serilog.csproj
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DotBased\DotBased.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
62
DotBased.Log.Serilog/SerilogAdapter.cs
Normal file
62
DotBased.Log.Serilog/SerilogAdapter.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using DotBased.Logging;
|
||||||
|
using Serilog.Events;
|
||||||
|
using Serilog.Parsing;
|
||||||
|
|
||||||
|
namespace DotBased.Log.Serilog;
|
||||||
|
|
||||||
|
public class SerilogAdapter : LogAdapterBase
|
||||||
|
{
|
||||||
|
public SerilogAdapter(global::Serilog.ILogger serilogLogger) : base("Serilog adapter")
|
||||||
|
{
|
||||||
|
_serilogLogger = serilogLogger;
|
||||||
|
_messageTemplateParser = new MessageTemplateParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public const string SampleTemplate = "[{Timestamp:HH:mm:ss} - {Caller} -> {AsmCaller}] | {Level:u3}] {Message:lj}{NewLine}{Exception}";
|
||||||
|
|
||||||
|
private readonly global::Serilog.ILogger _serilogLogger;
|
||||||
|
private readonly MessageTemplateParser _messageTemplateParser;
|
||||||
|
|
||||||
|
public override void HandleLog(object? sender, LogCapsule? capsule)
|
||||||
|
{
|
||||||
|
if (capsule == null)
|
||||||
|
return;
|
||||||
|
var baseLogger = capsule.Logger as Logger;
|
||||||
|
var logger = _serilogLogger
|
||||||
|
.ForContext("AsmCaller", baseLogger?.CallingAsmInfo.AssemblyName ?? "Static")
|
||||||
|
.ForContext("Caller", baseLogger?.Identifier);
|
||||||
|
|
||||||
|
var template = _messageTemplateParser.Parse(capsule.Message);
|
||||||
|
IEnumerable<LogEventProperty>? properties = null;
|
||||||
|
if (capsule.Parameters != null && capsule.Parameters.Length != 0)
|
||||||
|
{
|
||||||
|
var tokenList = template.Tokens.OfType<PropertyToken>().ToList();
|
||||||
|
properties = capsule.Parameters.Zip(tokenList, (p, t) => new LogEventProperty(t.PropertyName, new ScalarValue(p)));
|
||||||
|
}
|
||||||
|
switch (capsule.Severity)
|
||||||
|
{
|
||||||
|
case LogSeverity.Trace:
|
||||||
|
logger.Write(new LogEvent(capsule.TimeStamp, LogEventLevel.Verbose, null, template, properties ?? ArraySegment<LogEventProperty>.Empty, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()));
|
||||||
|
break;
|
||||||
|
case LogSeverity.Debug:
|
||||||
|
logger.Write(new LogEvent(capsule.TimeStamp, LogEventLevel.Debug, null, template, properties ?? ArraySegment<LogEventProperty>.Empty, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()));
|
||||||
|
break;
|
||||||
|
case LogSeverity.Info:
|
||||||
|
logger.Write(new LogEvent(capsule.TimeStamp, LogEventLevel.Information, null, template, properties ?? ArraySegment<LogEventProperty>.Empty, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()));
|
||||||
|
break;
|
||||||
|
case LogSeverity.Warning:
|
||||||
|
logger.Write(new LogEvent(capsule.TimeStamp, LogEventLevel.Warning, null, template, properties ?? ArraySegment<LogEventProperty>.Empty, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()));
|
||||||
|
break;
|
||||||
|
case LogSeverity.Error:
|
||||||
|
logger.Write(new LogEvent(capsule.TimeStamp, LogEventLevel.Error, capsule.Exception, template, properties ?? ArraySegment<LogEventProperty>.Empty, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()));
|
||||||
|
break;
|
||||||
|
case LogSeverity.Fatal:
|
||||||
|
logger.Write(new LogEvent(capsule.TimeStamp, LogEventLevel.Fatal, capsule.Exception, template, properties ?? ArraySegment<LogEventProperty>.Empty, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
DotBased.sln
Normal file
28
DotBased.sln
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased", "DotBased\DotBased.csproj", "{7FCF823B-D468-4C07-A4BB-192CD2C7EF57}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLI", "CLI\CLI.csproj", "{BAC347B8-42D9-42E1-999A-8CDBE73E9A49}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.Log.Serilog", "DotBased.Log.Serilog\DotBased.Log.Serilog.csproj", "{EBBDAF9A-BFC7-4BDC-8C51-0501B59A1DDC}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{7FCF823B-D468-4C07-A4BB-192CD2C7EF57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7FCF823B-D468-4C07-A4BB-192CD2C7EF57}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7FCF823B-D468-4C07-A4BB-192CD2C7EF57}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7FCF823B-D468-4C07-A4BB-192CD2C7EF57}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BAC347B8-42D9-42E1-999A-8CDBE73E9A49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BAC347B8-42D9-42E1-999A-8CDBE73E9A49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BAC347B8-42D9-42E1-999A-8CDBE73E9A49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BAC347B8-42D9-42E1-999A-8CDBE73E9A49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EBBDAF9A-BFC7-4BDC-8C51-0501B59A1DDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EBBDAF9A-BFC7-4BDC-8C51-0501B59A1DDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EBBDAF9A-BFC7-4BDC-8C51-0501B59A1DDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EBBDAF9A-BFC7-4BDC-8C51-0501B59A1DDC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
9
DotBased/Based.cs
Normal file
9
DotBased/Based.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace DotBased;
|
||||||
|
|
||||||
|
public class Based
|
||||||
|
{
|
||||||
|
void Test()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
14
DotBased/DotBased.csproj
Normal file
14
DotBased/DotBased.csproj
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Utilities\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
16
DotBased/Logging/ILogger.cs
Normal file
16
DotBased/Logging/ILogger.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public interface ILogger
|
||||||
|
{
|
||||||
|
public void Trace(string message, params object?[]? parameters);
|
||||||
|
|
||||||
|
public void Debug(string message, params object?[]? parameters);
|
||||||
|
|
||||||
|
public void Information(string message, params object?[]? parameters);
|
||||||
|
|
||||||
|
public void Warning(string message, params object?[]? parameters);
|
||||||
|
|
||||||
|
public void Error(Exception exception, string message, params object?[]? parameters);
|
||||||
|
|
||||||
|
public void Fatal(Exception exception, string message, params object?[]? parameters);
|
||||||
|
}
|
30
DotBased/Logging/LogAdapterBase.cs
Normal file
30
DotBased/Logging/LogAdapterBase.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public abstract class LogAdapterBase
|
||||||
|
{
|
||||||
|
public LogAdapterBase(string adapterName)
|
||||||
|
{
|
||||||
|
AdapterName = adapterName;
|
||||||
|
HandleLogEvent += HandleLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly EventHandler<LogCapsule> HandleLogEvent;
|
||||||
|
public string Id { get; } = Guid.NewGuid().ToString();
|
||||||
|
public string AdapterName { get; }
|
||||||
|
|
||||||
|
/*private string[] GetMessageProperties(string message)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public abstract void HandleLog(object? sender, LogCapsule? capsule);
|
||||||
|
|
||||||
|
public override int GetHashCode() => HashCode.Combine(Id, AdapterName);
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (obj is LogAdapterBase adapter)
|
||||||
|
return adapter.Id == Id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
17
DotBased/Logging/LogCapsule.cs
Normal file
17
DotBased/Logging/LogCapsule.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public class LogCapsule
|
||||||
|
{
|
||||||
|
public LogSeverity Severity { get; set; }
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
public Exception? Exception { get; set; }
|
||||||
|
public object?[]? Parameters { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Time stamp on when this event happend
|
||||||
|
/// </summary>
|
||||||
|
public DateTime TimeStamp { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The logger that generated this capsule
|
||||||
|
/// </summary>
|
||||||
|
public ILogger Logger { get; set; }
|
||||||
|
}
|
9
DotBased/Logging/LogOptions.cs
Normal file
9
DotBased/Logging/LogOptions.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public class LogOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The severty the logger will log
|
||||||
|
/// </summary>
|
||||||
|
public LogSeverity Severity { get; set; } = LogSeverity.Trace;
|
||||||
|
}
|
85
DotBased/Logging/LogProcessor.cs
Normal file
85
DotBased/Logging/LogProcessor.cs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public class LogProcessor : IDisposable
|
||||||
|
{
|
||||||
|
public LogProcessor()
|
||||||
|
{
|
||||||
|
_processorQueue = new Queue<LogCapsule>();
|
||||||
|
IncommingLogHandlerEvent = IncommingLogHandler;
|
||||||
|
_processorThread = new Thread(ProcessLog)
|
||||||
|
{
|
||||||
|
IsBackground = true,
|
||||||
|
Name = "Log processor thread (DotBased)"
|
||||||
|
};
|
||||||
|
_processorThread.Start();
|
||||||
|
}
|
||||||
|
public readonly Action<LogCapsule> IncommingLogHandlerEvent;
|
||||||
|
public event EventHandler<LogCapsule>? LogProcessed;
|
||||||
|
private readonly Queue<LogCapsule> _processorQueue;
|
||||||
|
private readonly Thread _processorThread;
|
||||||
|
private readonly ManualResetEvent _threadSuspendEvent = new ManualResetEvent(false);
|
||||||
|
private readonly ManualResetEvent _threadShutdownEvent = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop the LogProcessor, the processor cannot be resumed after stopped!
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
_threadShutdownEvent.Set();
|
||||||
|
_threadSuspendEvent.Set();
|
||||||
|
_processorThread.Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IncommingLogHandler(LogCapsule e)
|
||||||
|
{
|
||||||
|
_processorQueue.Enqueue(e);
|
||||||
|
// Check is the thread is running, if not wake up the thread.
|
||||||
|
if (!_threadSuspendEvent.WaitOne(0))
|
||||||
|
_threadSuspendEvent.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessLog()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
_threadSuspendEvent.WaitOne(Timeout.Infinite);
|
||||||
|
|
||||||
|
if (_threadShutdownEvent.WaitOne(0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (_processorQueue.Any())
|
||||||
|
{
|
||||||
|
var capsule = _processorQueue.Dequeue();
|
||||||
|
if (LogService.ShouldLog(LogService.Options.Severity, capsule.Severity))
|
||||||
|
LogProcessed?.Invoke(this, capsule);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_threadSuspendEvent.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// Write exception to the output
|
||||||
|
var oldColor = Console.ForegroundColor;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine("==================================================================================");
|
||||||
|
Console.ForegroundColor = ConsoleColor.Blue;
|
||||||
|
Console.Write($"[{DateTime.Now}] ");
|
||||||
|
Console.ForegroundColor = oldColor;
|
||||||
|
Console.WriteLine($"[{nameof(LogProcessor)} (DotBased)] Log processor thread failed! No logs are being processed!");
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine(e);
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine("==================================================================================");
|
||||||
|
Console.ForegroundColor = oldColor;
|
||||||
|
//TODO: Write info to disk.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
DotBased/Logging/LogService.cs
Normal file
51
DotBased/Logging/LogService.cs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public static class LogService
|
||||||
|
{
|
||||||
|
static LogService()
|
||||||
|
{
|
||||||
|
Options = new LogOptions();
|
||||||
|
_loggerSendEvent = LogProcessor.IncommingLogHandlerEvent;
|
||||||
|
}
|
||||||
|
public static bool ShouldLog(LogSeverity maxSeverity, LogSeverity severity) => maxSeverity <= severity;
|
||||||
|
public static LogOptions Options { get; private set; }
|
||||||
|
public static LogProcessor LogProcessor { get; private set; } = new LogProcessor();
|
||||||
|
|
||||||
|
private static HashSet<LogAdapterBase> Adapters { get; } = new HashSet<LogAdapterBase>();
|
||||||
|
private static HashSet<ILogger> Loggers { get; } = new HashSet<ILogger>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal communication between loggers and processor
|
||||||
|
/// </summary>
|
||||||
|
private static Action<LogCapsule> _loggerSendEvent;
|
||||||
|
|
||||||
|
public static void AddLogAdapter(LogAdapterBase logAdapter)
|
||||||
|
{
|
||||||
|
LogProcessor.LogProcessed += logAdapter.HandleLogEvent;
|
||||||
|
Adapters.Add(logAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ILogger RegisterLogger(string identifier)
|
||||||
|
{
|
||||||
|
var asm = Assembly.GetCallingAssembly();
|
||||||
|
var logger = new Logger(identifier, CallingAssemblyInfo.LoadFromAsm(asm), ref _loggerSendEvent);
|
||||||
|
Loggers.Add(logger);
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct CallingAssemblyInfo
|
||||||
|
{
|
||||||
|
private CallingAssemblyInfo(Assembly asm)
|
||||||
|
{
|
||||||
|
var asmName = asm.GetName();
|
||||||
|
AssemblyName = asmName.Name ?? "Unknown";
|
||||||
|
AssemblyFullName = asmName.FullName;
|
||||||
|
}
|
||||||
|
public static CallingAssemblyInfo LoadFromAsm(Assembly asm) => new CallingAssemblyInfo(asm);
|
||||||
|
|
||||||
|
public string AssemblyName { get; }
|
||||||
|
public string AssemblyFullName { get; set; }
|
||||||
|
}
|
11
DotBased/Logging/LogSeverity.cs
Normal file
11
DotBased/Logging/LogSeverity.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public enum LogSeverity
|
||||||
|
{
|
||||||
|
Trace = 0,
|
||||||
|
Debug = 1,
|
||||||
|
Info = 2,
|
||||||
|
Warning = 3,
|
||||||
|
Error = 4,
|
||||||
|
Fatal = 5
|
||||||
|
}
|
97
DotBased/Logging/Logger.cs
Normal file
97
DotBased/Logging/Logger.cs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public class Logger : ILogger
|
||||||
|
{
|
||||||
|
public Logger(string identifier, CallingAssemblyInfo asmInfo, ref Action<LogCapsule> logProcessorHandler)
|
||||||
|
{
|
||||||
|
Identifier = identifier;
|
||||||
|
CallingAsmInfo = asmInfo;
|
||||||
|
_processLog = logProcessorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Identifier { get; }
|
||||||
|
public CallingAssemblyInfo CallingAsmInfo { get; }
|
||||||
|
|
||||||
|
private readonly Action<LogCapsule> _processLog;
|
||||||
|
|
||||||
|
public void Log(LogCapsule capsule)
|
||||||
|
{
|
||||||
|
_processLog(capsule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trace(string message, params object?[]? parameters)
|
||||||
|
{
|
||||||
|
Log(new LogCapsule()
|
||||||
|
{
|
||||||
|
Logger = this,
|
||||||
|
Message = message,
|
||||||
|
Parameters = parameters,
|
||||||
|
Severity = LogSeverity.Trace,
|
||||||
|
TimeStamp = DateTime.Now
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Debug(string message, params object?[]? parameters)
|
||||||
|
{
|
||||||
|
Log(new LogCapsule()
|
||||||
|
{
|
||||||
|
Logger = this,
|
||||||
|
Message = message,
|
||||||
|
Parameters = parameters,
|
||||||
|
Severity = LogSeverity.Debug,
|
||||||
|
TimeStamp = DateTime.Now
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Information(string message, params object?[]? parameters)
|
||||||
|
{
|
||||||
|
Log(new LogCapsule()
|
||||||
|
{
|
||||||
|
Logger = this,
|
||||||
|
Message = message,
|
||||||
|
Parameters = parameters,
|
||||||
|
Severity = LogSeverity.Info,
|
||||||
|
TimeStamp = DateTime.Now
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning(string message, params object?[]? parameters)
|
||||||
|
{
|
||||||
|
Log(new LogCapsule()
|
||||||
|
{
|
||||||
|
Logger = this,
|
||||||
|
Message = message,
|
||||||
|
Parameters = parameters,
|
||||||
|
Severity = LogSeverity.Warning,
|
||||||
|
TimeStamp = DateTime.Now
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Error(Exception exception, string message, params object?[]? parameters)
|
||||||
|
{
|
||||||
|
Log(new LogCapsule()
|
||||||
|
{
|
||||||
|
Logger = this,
|
||||||
|
Message = message,
|
||||||
|
Parameters = parameters,
|
||||||
|
Severity = LogSeverity.Error,
|
||||||
|
TimeStamp = DateTime.Now,
|
||||||
|
Exception = exception
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fatal(Exception exception, string message, params object?[]? parameters)
|
||||||
|
{
|
||||||
|
Log(new LogCapsule()
|
||||||
|
{
|
||||||
|
Logger = this,
|
||||||
|
Message = message,
|
||||||
|
Parameters = parameters,
|
||||||
|
Severity = LogSeverity.Fatal,
|
||||||
|
TimeStamp = DateTime.Now,
|
||||||
|
Exception = exception
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => HashCode.Combine(Identifier, CallingAsmInfo.AssemblyFullName);
|
||||||
|
}
|
91
DotBased/Logging/SimpleConsoleLogAdapter.cs
Normal file
91
DotBased/Logging/SimpleConsoleLogAdapter.cs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DotBased.Logging;
|
||||||
|
|
||||||
|
public class SimpleConsoleLogAdapter : LogAdapterBase
|
||||||
|
{
|
||||||
|
public SimpleConsoleLogAdapter(string adapterName) : base(adapterName)
|
||||||
|
{
|
||||||
|
Console.OutputEncoding = Encoding.UTF8;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ConsoleColor _defaultColor = Console.ForegroundColor;
|
||||||
|
private const ConsoleColor TimestampColor = ConsoleColor.DarkBlue;
|
||||||
|
private const ConsoleColor BrackedColor = ConsoleColor.Gray;
|
||||||
|
private const ConsoleColor MessageColor = ConsoleColor.DarkGray;
|
||||||
|
private ConsoleColor _severityColor = ConsoleColor.Cyan;
|
||||||
|
|
||||||
|
public override void HandleLog(object? sender, LogCapsule? capsule)
|
||||||
|
{
|
||||||
|
if (capsule == null) return;
|
||||||
|
|
||||||
|
Console.ForegroundColor = BrackedColor;
|
||||||
|
Console.Write("[");
|
||||||
|
Console.ForegroundColor = TimestampColor;
|
||||||
|
Console.Write($"{capsule.TimeStamp}");
|
||||||
|
Console.ForegroundColor = BrackedColor;
|
||||||
|
Console.Write("] ");
|
||||||
|
|
||||||
|
_severityColor = capsule.Severity.ToConsoleColor();
|
||||||
|
WriteSeverity(capsule.Severity);
|
||||||
|
|
||||||
|
if (capsule.Severity is LogSeverity.Error or LogSeverity.Fatal)
|
||||||
|
WriteException(capsule);
|
||||||
|
else
|
||||||
|
WriteMessage(capsule);
|
||||||
|
Console.ForegroundColor = _defaultColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteSeverity(LogSeverity severity)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = BrackedColor;
|
||||||
|
Console.Write("[");
|
||||||
|
Console.ForegroundColor = _severityColor;
|
||||||
|
Console.Write($"{severity}");
|
||||||
|
Console.ForegroundColor = BrackedColor;
|
||||||
|
Console.Write("] ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteMessage(LogCapsule capsule)
|
||||||
|
{
|
||||||
|
if (capsule.Parameters == null || !capsule.Parameters.Any())
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = MessageColor;
|
||||||
|
Console.WriteLine($"{capsule.Message}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteException(LogCapsule capsule)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Blue;
|
||||||
|
Console.WriteLine("\u23F7");
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine("==============================================================================================");
|
||||||
|
WriteMessage(capsule);
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine(capsule.Exception);
|
||||||
|
Console.WriteLine("==============================================================================================");
|
||||||
|
Console.ForegroundColor = _defaultColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LogSeverityExt
|
||||||
|
{
|
||||||
|
public static ConsoleColor ToConsoleColor(this LogSeverity severity)
|
||||||
|
{
|
||||||
|
var color = severity switch
|
||||||
|
{
|
||||||
|
LogSeverity.Trace or LogSeverity.Info => ConsoleColor.White,
|
||||||
|
LogSeverity.Debug => ConsoleColor.Magenta,
|
||||||
|
LogSeverity.Warning => ConsoleColor.Yellow,
|
||||||
|
LogSeverity.Error => ConsoleColor.Red,
|
||||||
|
LogSeverity.Fatal => ConsoleColor.DarkRed,
|
||||||
|
_ => ConsoleColor.White
|
||||||
|
};
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
34
DotBased/doc.md
Normal file
34
DotBased/doc.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# DotBased info
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
In most logging frameworks you will encounter all or some of the following log levels:
|
||||||
|
|
||||||
|
- TRACE
|
||||||
|
- DEBUG
|
||||||
|
- INFO
|
||||||
|
- WARN
|
||||||
|
- ERROR
|
||||||
|
- FATAL
|
||||||
|
|
||||||
|
The names of some of those give you a hint on what they are about. However, let’s discuss each of them in greater detail.
|
||||||
|
|
||||||
|
TRACE – the most fine-grained information only used in rare cases where you need the full visibility of what is happening in your application and inside the third-party libraries that you use. You can expect the TRACE logging level to be very verbose. You can use it for example to annotate each step in the algorithm or each individual query with parameters in your code.
|
||||||
|
|
||||||
|
DEBUG – less granular compared to the TRACE level, but it is more than you will need in everyday use. The DEBUG log level should be used for information that may be needed for diagnosing issues and troubleshooting or when running application in the test environment for the purpose of making sure everything is running correctly
|
||||||
|
|
||||||
|
INFO – the standard log level indicating that something happened, the application entered a certain state, etc. For example, a controller of your authorization API may include an INFO log level with information on which user requested authorization if the authorization was successful or not. The information logged using the INFO log level should be purely informative and not looking into them on a regular basis shouldn’t result in missing any important information.
|
||||||
|
|
||||||
|
WARN – the log level that indicates that something unexpected happened in the application, a problem, or a situation that might disturb one of the processes. But that doesn’t mean that the application failed. The WARN level should be used in situations that are unexpected, but the code can continue the work. For example, a parsing error occurred that resulted in a certain document not being processed.
|
||||||
|
|
||||||
|
ERROR – the log level that should be used when the application hits an issue preventing one or more functionalities from properly functioning. The ERROR log level can be used when one of the payment systems is not available, but there is still the option to check out the basket in the e-commerce application or when your social media logging option is not working for some reason.
|
||||||
|
|
||||||
|
FATAL – the log level that tells that the application encountered an event or entered a state in which one of the crucial business functionality is no longer working. A FATAL log level may be used when the application is not able to connect to a crucial data store like a database or all the payment systems are not available and users can’t checkout their baskets in your e-commerce.
|
||||||
|
|
||||||
|
To summarize what we know about each of the logging level:
|
||||||
|
Log Level Importance
|
||||||
|
- Fatal One or more key business functionalities are not working and the whole system doesn’t fulfill the business functionalities.
|
||||||
|
- Error One or more functionalities are not working, preventing some functionalities from working correctly.
|
||||||
|
- Warn Unexpected behavior happened inside the application, but it is continuing its work and the key business features are operating as expected.
|
||||||
|
- Info An event happened, the event is purely informative and can be ignored during normal operations.
|
||||||
|
- Debug A log level used for events considered to be useful during software debugging when more granular information is needed.
|
||||||
|
- Trace A log level describing events showing step by step execution of your code that can be ignored during the standard operation, but may be useful during extended debugging sessions.
|
Loading…
Reference in New Issue
Block a user