mirror of
https://github.com/yaakov-h/Notepad.Extensions.Logging.git
synced 2024-11-22 03:04:48 +00:00
Initial version
This commit is contained in:
commit
aecb3421c7
9 changed files with 257 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.vs/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.4" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Notepad.Extensions.Logging\Notepad.Extensions.Logging.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
38
Notepad.Extensions.Logging.FunctionalTest/Program.cs
Normal file
38
Notepad.Extensions.Logging.FunctionalTest/Program.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Notepad.Extensions.Logging.FunctionalTest
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var sc = new ServiceCollection();
|
||||||
|
sc.AddLogging(lb =>
|
||||||
|
{
|
||||||
|
lb.AddConsole();
|
||||||
|
lb.AddNotepad();
|
||||||
|
});
|
||||||
|
|
||||||
|
var sp = sc.BuildServiceProvider();
|
||||||
|
var logger = sp.GetRequiredService<ILogger<Program>>();
|
||||||
|
|
||||||
|
logger.LogWarning("Here is a warning.");
|
||||||
|
logger.LogError(GetException(), "oh no!.");
|
||||||
|
logger.LogInformation("Here is some info.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static Exception GetException()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Wheeeeeeee");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
Notepad.Extensions.Logging.sln
Normal file
31
Notepad.Extensions.Logging.sln
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30114.105
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notepad.Extensions.Logging", "Notepad.Extensions.Logging\Notepad.Extensions.Logging.csproj", "{859E3EAB-04EB-42EE-86B2-A6FE90D71731}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notepad.Extensions.Logging.FunctionalTest", "Notepad.Extensions.Logging.FunctionalTest\Notepad.Extensions.Logging.FunctionalTest.csproj", "{82E1E9EF-9284-4E7B-B350-0318F9B7B411}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{859E3EAB-04EB-42EE-86B2-A6FE90D71731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{859E3EAB-04EB-42EE-86B2-A6FE90D71731}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{859E3EAB-04EB-42EE-86B2-A6FE90D71731}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{859E3EAB-04EB-42EE-86B2-A6FE90D71731}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{82E1E9EF-9284-4E7B-B350-0318F9B7B411}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{82E1E9EF-9284-4E7B-B350-0318F9B7B411}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{82E1E9EF-9284-4E7B-B350-0318F9B7B411}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{82E1E9EF-9284-4E7B-B350-0318F9B7B411}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {4F5721FB-D38E-487C-9851-8A268DE891CC}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
11
Notepad.Extensions.Logging/LoggingBuilderExtensions.cs
Normal file
11
Notepad.Extensions.Logging/LoggingBuilderExtensions.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Microsoft.Extensions.Logging
|
||||||
|
{
|
||||||
|
public static class LoggingBuilderExtensions
|
||||||
|
{
|
||||||
|
public static ILoggingBuilder AddNotepad(this ILoggingBuilder builder)
|
||||||
|
{
|
||||||
|
builder.AddProvider(NotepadLoggerProvider.Instance);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
Notepad.Extensions.Logging/Notepad.Extensions.Logging.csproj
Normal file
13
Notepad.Extensions.Logging/Notepad.Extensions.Logging.csproj
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<LangVersion>8.0</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.4" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="3.1.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
107
Notepad.Extensions.Logging/NotepadLogger.cs
Normal file
107
Notepad.Extensions.Logging/NotepadLogger.cs
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.Logging
|
||||||
|
{
|
||||||
|
class NotepadLogger : ILogger
|
||||||
|
{
|
||||||
|
public NotepadLogger(ObjectPool<StringBuilder> stringBuilderPool, string categoryName)
|
||||||
|
{
|
||||||
|
this.stringBuilderPool = stringBuilderPool;
|
||||||
|
this.categoryName = categoryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly ObjectPool<StringBuilder> stringBuilderPool;
|
||||||
|
readonly string categoryName;
|
||||||
|
|
||||||
|
public IDisposable BeginScope<TState>(TState state) => NullDisposable.Instance;
|
||||||
|
|
||||||
|
public bool IsEnabled(LogLevel logLevel) => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||||
|
|
||||||
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
|
{
|
||||||
|
if (!IsEnabled(logLevel))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formatter is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(formatter));
|
||||||
|
}
|
||||||
|
|
||||||
|
var message = formatter(state, exception);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(message) && exception is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteMessage(logLevel, eventId.Id, message, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMessage(LogLevel logLevel, int eventId, string message, Exception ex)
|
||||||
|
{
|
||||||
|
var builder = stringBuilderPool.Get();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.Append('[')
|
||||||
|
.Append(GetLogLevelString(logLevel))
|
||||||
|
.Append("] ")
|
||||||
|
.Append(categoryName)
|
||||||
|
.Append(" (")
|
||||||
|
.Append(eventId)
|
||||||
|
.Append(") ")
|
||||||
|
.AppendLine(message);
|
||||||
|
|
||||||
|
if (ex is { })
|
||||||
|
{
|
||||||
|
builder.Append(" ");
|
||||||
|
builder.AppendLine(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteToNotepad(builder.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stringBuilderPool.Return(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetLogLevelString(LogLevel logLevel) => logLevel switch
|
||||||
|
{
|
||||||
|
LogLevel.Trace => "trce",
|
||||||
|
LogLevel.Debug => "dbug",
|
||||||
|
LogLevel.Information => "info",
|
||||||
|
LogLevel.Warning => "warn",
|
||||||
|
LogLevel.Error => "fail",
|
||||||
|
LogLevel.Critical => "crit",
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(logLevel)),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void WriteToNotepad(string message)
|
||||||
|
{
|
||||||
|
IntPtr hwnd = NativeMethods.FindWindow(null, "Untitled - Notepad");
|
||||||
|
IntPtr edit = NativeMethods.FindWindowEx(hwnd, IntPtr.Zero, "EDIT", null);
|
||||||
|
NativeMethods.SendMessage(edit, NativeMethods.EM_REPLACESEL, (IntPtr)1, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class NativeMethods
|
||||||
|
{
|
||||||
|
[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||||
|
|
||||||
|
[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);
|
||||||
|
|
||||||
|
public const int EM_REPLACESEL = 0x00C2;
|
||||||
|
|
||||||
|
[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
|
||||||
|
}
|
||||||
|
}
|
24
Notepad.Extensions.Logging/NotepadLoggerProvider.cs
Normal file
24
Notepad.Extensions.Logging/NotepadLoggerProvider.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.Logging
|
||||||
|
{
|
||||||
|
class NotepadLoggerProvider : ILoggerProvider
|
||||||
|
{
|
||||||
|
NotepadLoggerProvider()
|
||||||
|
{
|
||||||
|
var poolProvider = new DefaultObjectPoolProvider();
|
||||||
|
stringBuilderPool = poolProvider.CreateStringBuilderPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ILoggerProvider Instance { get; } = new NotepadLoggerProvider();
|
||||||
|
|
||||||
|
readonly ObjectPool<StringBuilder> stringBuilderPool;
|
||||||
|
|
||||||
|
public ILogger CreateLogger(string categoryName) => new NotepadLogger(stringBuilderPool, categoryName);
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
Notepad.Extensions.Logging/NullDisposable.cs
Normal file
13
Notepad.Extensions.Logging/NullDisposable.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.Logging
|
||||||
|
{
|
||||||
|
class NullDisposable : IDisposable
|
||||||
|
{
|
||||||
|
public static IDisposable Instance { get; } = new NullDisposable();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue