Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
augustoproiete committed May 22, 2020
1 parent 4a45880 commit a95785b
Show file tree
Hide file tree
Showing 19 changed files with 870 additions and 0 deletions.
152 changes: 152 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Serilog.Sinks.Notepad [![NuGet Version](http://img.shields.io/nuget/v/Serilog.Sinks.Notepad.svg?style=flat)](https://www.nuget.org/packages/Serilog.Sinks.Notepad) [![Help](https://img.shields.io/badge/stackoverflow-serilog-orange.svg)](http://stackoverflow.com/questions/tagged/serilog)

A [Serilog](https://serilog.net) sink that writes log events to Notepad (_Yes, you've read it right!_). The default output is plain text; JSON formatting can be plugged in using a package such as [_Serilog.Formatting.Compact_](https://github.com/serilog/serilog-formatting-compact).

![Screenshot of Serilog.Sinks.Notepad in action](assets/serilog-sinks-notepad-screenshot.png)

## Give a Star! :star:

If you like or are using this project please give it a star. Thanks!

## Getting started

Install the [Serilog.Sinks.Notepad](https://www.nuget.org/packages/Serilog.Sinks.Notepad) package from NuGet:

```powershell
Install-Package Serilog.Sinks.Notepad
```

To configure the sink in C# code, call `WriteTo.Notepad()` during logger configuration:

```csharp
Log.Logger = new LoggerConfiguration()
.WriteTo.Notepad()
.CreateLogger();

Log.Information("Hello, world!");
```

Open Notepad, and you should see the logs appear in that Notepad window. By default, `Serilog.Sinks.Notepad` writes messages to the most recent `notepad.exe` started on the machine. This behavior can be changed in the sink configuration.

## Background

I created this sink just for fun, after reading [this comment on Reddit](https://www.reddit.com/r/programming/comments/gnazif/ray_tracing_in_notepadexe_at_30_fps/fr8uy2l/):

![Screenshot of Serilog.Sinks.Notepad in action](assets/reddit-comment-note-ad-as-debug-console.png)

I thought that's a clever idea to be able to simply open a Notepad instance and immediately start receiving logs from your application, and I can imagine this actually being useful for troubleshooting issues with applications.

## Configuration

### Output templates

The format of events written to Notepad can be modified using the `outputTemplate` configuration parameter:

```csharp
.WriteTo.Notepad(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
```

The default template, shown in the example above, uses built-in properties like `Timestamp` and `Level`. Properties from events, including those attached using [enrichers](https://github.com/serilog/serilog/wiki/Enrichment), can also appear in the output template.

### JSON output

The sink can write JSON output instead of plain text. `CompactJsonFormatter` or `RenderedCompactJsonFormatter` from [Serilog.Formatting.Compact](https://github.com/serilog/serilog-formatting-compact) is recommended:

```powershell
Install-Package Serilog.Formatting.Compact
```

Pass a formatter to the `Notepad()` configuration method:

```csharp
.WriteTo.Notepad(new RenderedCompactJsonFormatter())
```

Output theming is not available when custom formatters are used.

### XML `<appSettings>` configuration

To use the Notepad sink with the [Serilog.Settings.AppSettings](https://github.com/serilog/serilog-settings-appsettings) package, first install that package if you haven't already done so:

```powershell
Install-Package Serilog.Settings.AppSettings
```

Instead of configuring the logger in code, call `ReadFrom.AppSettings()`:

```csharp
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.CreateLogger();
```

In your application's `App.config` or `Web.config` file, specify the Notepad sink assembly under the `<appSettings>` node:

```xml
<configuration>
<appSettings>
<add key="serilog:using:Notepad" value="Serilog.Sinks.Notepad" />
<add key="serilog:write-to:Notepad" />
```

To configure the Notepad sink and include the `SourceContext` in the output, change your `App.config`/`Web.config` to:
```xml
<configuration>
<appSettings>
<add key="serilog:using:Notepad" value="Serilog.Sinks.Notepad" />
<add key="serilog:write-to:Notepad.outputTemplate" value="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} &lt;s:{SourceContext}&gt;{NewLine}{Exception}" />
```

### JSON `appsettings.json` configuration

To use the Notepad sink with _Microsoft.Extensions.Configuration_, for example with ASP.NET Core or .NET Core, use the [Serilog.Settings.Configuration](https://github.com/serilog/serilog-settings-configuration) package. First install that package if you have not already done so:

```powershell
Install-Package Serilog.Settings.Configuration
```

Instead of configuring the sink directly in code, call `ReadFrom.Configuration()`:

```csharp
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();

Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
```

In your `appsettings.json` file, under the `Serilog` node, :
```json
{
"Serilog": {
"WriteTo": [{"Name": "Notepad"}]
}
}
```

To configure the Notepad sink and include the `SourceContext` in the output, change your `appsettings.json` to:
```json
{
"Serilog": {
"WriteTo": [
{
"Name": "Notepad",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}"
}
}
]
}
}
```

## Release History

Click on the [Releases](https://github.com/augustoproiete/serilog-sinks-notepad/releases) tab on GitHub.

---

_Copyright &copy; 2020 C. Augusto Proiete & Contributors - Provided under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0.html)._
Binary file added assets/Serilog.snk
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/serilog-sinks-notepad-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"sdk": {
"version": "3.1.*"
}
}
17 changes: 17 additions & 0 deletions sample/ConsoleDemo/ConsoleDemo.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net45;netcoreapp3.1</TargetFrameworks>
<LangVersion>8.0</LangVersion>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Serilog.Sinks.Notepad\Serilog.Sinks.Notepad.csproj" />
</ItemGroup>

<ItemGroup>
<None Remove="*.DotSettings" />
</ItemGroup>

</Project>
54 changes: 54 additions & 0 deletions sample/ConsoleDemo/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Threading;
using Serilog;

namespace ConsoleDemo
{
internal class Program
{
private static void Main(string[] args)
{
Serilog.Debugging.SelfLog.Enable(s => Console.WriteLine($"Internal Error with Serilog: {s}"));

Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.Notepad()
.CreateLogger();

try
{
Console.WriteLine("Open a `notepad.exe` instance and press <enter> to continue...");
Console.ReadLine();

Console.WriteLine("Writing messages to the most recent Notepad you opened...");

Log.Debug("Getting started");

Log.Information("Hello {Name} from thread {ThreadId}", Environment.GetEnvironmentVariable("USERNAME"),
Thread.CurrentThread.ManagedThreadId);

Log.Warning("No coins remain at position {@Position}", new { Lat = 25, Long = 134 });

try
{
Fail();
}
catch (Exception ex)
{
Log.Error(ex, "Oops... Something went wrong");
}

Console.WriteLine("Done.");
}
finally
{
Log.CloseAndFlush();
}
}

private static void Fail()
{
throw new DivideByZeroException();
}
}
}
59 changes: 59 additions & 0 deletions serilog-sinks-notepad.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30104.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{98FECEDE-5590-406F-A327-AA7F6CBE07A7}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitattributes = .gitattributes
.gitignore = .gitignore
CHANGES.md = CHANGES.md
CODEOWNERS = CODEOWNERS
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A788D7A8-C32F-4EFC-ADD0-2A1791595225}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.Notepad", "src\Serilog.Sinks.Notepad\Serilog.Sinks.Notepad.csproj", "{CC7EBF80-9141-489F-A7BC-D59D18971279}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{C73ACC17-798C-44E7-BC96-4BEADBD4085D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleDemo", "sample\ConsoleDemo\ConsoleDemo.csproj", "{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{1E653E10-F79F-4BFF-9A49-30F4B7DCF851}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.Notepad.Tests", "test\Serilog.Sinks.Notepad.Tests\Serilog.Sinks.Notepad.Tests.csproj", "{FC1DB800-0FD6-489A-96B6-B4C880EC409B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Release|Any CPU.Build.0 = Release|Any CPU
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Release|Any CPU.Build.0 = Release|Any CPU
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CC7EBF80-9141-489F-A7BC-D59D18971279} = {A788D7A8-C32F-4EFC-ADD0-2A1791595225}
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7} = {C73ACC17-798C-44E7-BC96-4BEADBD4085D}
{FC1DB800-0FD6-489A-96B6-B4C880EC409B} = {1E653E10-F79F-4BFF-9A49-30F4B7DCF851}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {53FA8B3B-657E-4173-B3F9-EA434D5D5BB0}
EndGlobalSection
EndGlobal
16 changes: 16 additions & 0 deletions serilog-sinks-notepad.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002EIfThenThrowPattern/@EntryIndexedValue">1000</s:Int64>
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002EPatternMatchingIfThenThrowPattern/@EntryIndexedValue">3000</s:Int64>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArgumentsStyleLiteral/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArgumentsStyleNamedExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToUsingDeclaration/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=LocalizableElement/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MarkupAttributeTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MarkupTextTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInInitializer/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantExtendsListEntry/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary>
Loading

0 comments on commit a95785b

Please sign in to comment.