Skip to content

Commit a95785b

Browse files
Initial version
1 parent 4a45880 commit a95785b

19 files changed

+870
-0
lines changed

README.md

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# 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)
2+
3+
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).
4+
5+
![Screenshot of Serilog.Sinks.Notepad in action](assets/serilog-sinks-notepad-screenshot.png)
6+
7+
## Give a Star! :star:
8+
9+
If you like or are using this project please give it a star. Thanks!
10+
11+
## Getting started
12+
13+
Install the [Serilog.Sinks.Notepad](https://www.nuget.org/packages/Serilog.Sinks.Notepad) package from NuGet:
14+
15+
```powershell
16+
Install-Package Serilog.Sinks.Notepad
17+
```
18+
19+
To configure the sink in C# code, call `WriteTo.Notepad()` during logger configuration:
20+
21+
```csharp
22+
Log.Logger = new LoggerConfiguration()
23+
.WriteTo.Notepad()
24+
.CreateLogger();
25+
26+
Log.Information("Hello, world!");
27+
```
28+
29+
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.
30+
31+
## Background
32+
33+
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/):
34+
35+
![Screenshot of Serilog.Sinks.Notepad in action](assets/reddit-comment-note-ad-as-debug-console.png)
36+
37+
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.
38+
39+
## Configuration
40+
41+
### Output templates
42+
43+
The format of events written to Notepad can be modified using the `outputTemplate` configuration parameter:
44+
45+
```csharp
46+
.WriteTo.Notepad(
47+
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
48+
```
49+
50+
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.
51+
52+
### JSON output
53+
54+
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:
55+
56+
```powershell
57+
Install-Package Serilog.Formatting.Compact
58+
```
59+
60+
Pass a formatter to the `Notepad()` configuration method:
61+
62+
```csharp
63+
.WriteTo.Notepad(new RenderedCompactJsonFormatter())
64+
```
65+
66+
Output theming is not available when custom formatters are used.
67+
68+
### XML `<appSettings>` configuration
69+
70+
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:
71+
72+
```powershell
73+
Install-Package Serilog.Settings.AppSettings
74+
```
75+
76+
Instead of configuring the logger in code, call `ReadFrom.AppSettings()`:
77+
78+
```csharp
79+
Log.Logger = new LoggerConfiguration()
80+
.ReadFrom.AppSettings()
81+
.CreateLogger();
82+
```
83+
84+
In your application's `App.config` or `Web.config` file, specify the Notepad sink assembly under the `<appSettings>` node:
85+
86+
```xml
87+
<configuration>
88+
<appSettings>
89+
<add key="serilog:using:Notepad" value="Serilog.Sinks.Notepad" />
90+
<add key="serilog:write-to:Notepad" />
91+
```
92+
93+
To configure the Notepad sink and include the `SourceContext` in the output, change your `App.config`/`Web.config` to:
94+
```xml
95+
<configuration>
96+
<appSettings>
97+
<add key="serilog:using:Notepad" value="Serilog.Sinks.Notepad" />
98+
<add key="serilog:write-to:Notepad.outputTemplate" value="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} &lt;s:{SourceContext}&gt;{NewLine}{Exception}" />
99+
```
100+
101+
### JSON `appsettings.json` configuration
102+
103+
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:
104+
105+
```powershell
106+
Install-Package Serilog.Settings.Configuration
107+
```
108+
109+
Instead of configuring the sink directly in code, call `ReadFrom.Configuration()`:
110+
111+
```csharp
112+
var configuration = new ConfigurationBuilder()
113+
.AddJsonFile("appsettings.json")
114+
.Build();
115+
116+
Log.Logger = new LoggerConfiguration()
117+
.ReadFrom.Configuration(configuration)
118+
.CreateLogger();
119+
```
120+
121+
In your `appsettings.json` file, under the `Serilog` node, :
122+
```json
123+
{
124+
"Serilog": {
125+
"WriteTo": [{"Name": "Notepad"}]
126+
}
127+
}
128+
```
129+
130+
To configure the Notepad sink and include the `SourceContext` in the output, change your `appsettings.json` to:
131+
```json
132+
{
133+
"Serilog": {
134+
"WriteTo": [
135+
{
136+
"Name": "Notepad",
137+
"Args": {
138+
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}"
139+
}
140+
}
141+
]
142+
}
143+
}
144+
```
145+
146+
## Release History
147+
148+
Click on the [Releases](https://github.com/augustoproiete/serilog-sinks-notepad/releases) tab on GitHub.
149+
150+
---
151+
152+
_Copyright &copy; 2020 C. Augusto Proiete & Contributors - Provided under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0.html)._

assets/Serilog.snk

596 Bytes
Binary file not shown.
Loading
28.7 KB
Loading

global.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"sdk": {
3+
"version": "3.1.*"
4+
}
5+
}

sample/ConsoleDemo/ConsoleDemo.csproj

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFrameworks>net45;netcoreapp3.1</TargetFrameworks>
6+
<LangVersion>8.0</LangVersion>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<ProjectReference Include="..\..\src\Serilog.Sinks.Notepad\Serilog.Sinks.Notepad.csproj" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<None Remove="*.DotSettings" />
15+
</ItemGroup>
16+
17+
</Project>

sample/ConsoleDemo/Program.cs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Threading;
3+
using Serilog;
4+
5+
namespace ConsoleDemo
6+
{
7+
internal class Program
8+
{
9+
private static void Main(string[] args)
10+
{
11+
Serilog.Debugging.SelfLog.Enable(s => Console.WriteLine($"Internal Error with Serilog: {s}"));
12+
13+
Log.Logger = new LoggerConfiguration()
14+
.MinimumLevel.Verbose()
15+
.WriteTo.Notepad()
16+
.CreateLogger();
17+
18+
try
19+
{
20+
Console.WriteLine("Open a `notepad.exe` instance and press <enter> to continue...");
21+
Console.ReadLine();
22+
23+
Console.WriteLine("Writing messages to the most recent Notepad you opened...");
24+
25+
Log.Debug("Getting started");
26+
27+
Log.Information("Hello {Name} from thread {ThreadId}", Environment.GetEnvironmentVariable("USERNAME"),
28+
Thread.CurrentThread.ManagedThreadId);
29+
30+
Log.Warning("No coins remain at position {@Position}", new { Lat = 25, Long = 134 });
31+
32+
try
33+
{
34+
Fail();
35+
}
36+
catch (Exception ex)
37+
{
38+
Log.Error(ex, "Oops... Something went wrong");
39+
}
40+
41+
Console.WriteLine("Done.");
42+
}
43+
finally
44+
{
45+
Log.CloseAndFlush();
46+
}
47+
}
48+
49+
private static void Fail()
50+
{
51+
throw new DivideByZeroException();
52+
}
53+
}
54+
}

serilog-sinks-notepad.sln

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30104.148
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{98FECEDE-5590-406F-A327-AA7F6CBE07A7}"
7+
ProjectSection(SolutionItems) = preProject
8+
.editorconfig = .editorconfig
9+
.gitattributes = .gitattributes
10+
.gitignore = .gitignore
11+
CHANGES.md = CHANGES.md
12+
CODEOWNERS = CODEOWNERS
13+
LICENSE = LICENSE
14+
README.md = README.md
15+
EndProjectSection
16+
EndProject
17+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A788D7A8-C32F-4EFC-ADD0-2A1791595225}"
18+
EndProject
19+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.Notepad", "src\Serilog.Sinks.Notepad\Serilog.Sinks.Notepad.csproj", "{CC7EBF80-9141-489F-A7BC-D59D18971279}"
20+
EndProject
21+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{C73ACC17-798C-44E7-BC96-4BEADBD4085D}"
22+
EndProject
23+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleDemo", "sample\ConsoleDemo\ConsoleDemo.csproj", "{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}"
24+
EndProject
25+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{1E653E10-F79F-4BFF-9A49-30F4B7DCF851}"
26+
EndProject
27+
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}"
28+
EndProject
29+
Global
30+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
31+
Debug|Any CPU = Debug|Any CPU
32+
Release|Any CPU = Release|Any CPU
33+
EndGlobalSection
34+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
35+
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36+
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Debug|Any CPU.Build.0 = Debug|Any CPU
37+
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Release|Any CPU.ActiveCfg = Release|Any CPU
38+
{CC7EBF80-9141-489F-A7BC-D59D18971279}.Release|Any CPU.Build.0 = Release|Any CPU
39+
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40+
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
41+
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
42+
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7}.Release|Any CPU.Build.0 = Release|Any CPU
43+
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44+
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Debug|Any CPU.Build.0 = Debug|Any CPU
45+
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Release|Any CPU.ActiveCfg = Release|Any CPU
46+
{FC1DB800-0FD6-489A-96B6-B4C880EC409B}.Release|Any CPU.Build.0 = Release|Any CPU
47+
EndGlobalSection
48+
GlobalSection(SolutionProperties) = preSolution
49+
HideSolutionNode = FALSE
50+
EndGlobalSection
51+
GlobalSection(NestedProjects) = preSolution
52+
{CC7EBF80-9141-489F-A7BC-D59D18971279} = {A788D7A8-C32F-4EFC-ADD0-2A1791595225}
53+
{B3DD36B1-EEFA-4E7C-82B8-60728AFACCF7} = {C73ACC17-798C-44E7-BC96-4BEADBD4085D}
54+
{FC1DB800-0FD6-489A-96B6-B4C880EC409B} = {1E653E10-F79F-4BFF-9A49-30F4B7DCF851}
55+
EndGlobalSection
56+
GlobalSection(ExtensibilityGlobals) = postSolution
57+
SolutionGuid = {53FA8B3B-657E-4173-B3F9-EA434D5D5BB0}
58+
EndGlobalSection
59+
EndGlobal

serilog-sinks-notepad.sln.DotSettings

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<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">
2+
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002EIfThenThrowPattern/@EntryIndexedValue">1000</s:Int64>
3+
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002EPatternMatchingIfThenThrowPattern/@EntryIndexedValue">3000</s:Int64>
4+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArgumentsStyleLiteral/@EntryIndexedValue">DO_NOT_SHOW</s:String>
5+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArgumentsStyleNamedExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
6+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
7+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToUsingDeclaration/@EntryIndexedValue">DO_NOT_SHOW</s:String>
8+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
9+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=LocalizableElement/@EntryIndexedValue">DO_NOT_SHOW</s:String>
10+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MarkupAttributeTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
11+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MarkupTextTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
12+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInInitializer/@EntryIndexedValue">DO_NOT_SHOW</s:String>
13+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantExtendsListEntry/@EntryIndexedValue">DO_NOT_SHOW</s:String>
14+
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue">DO_NOT_SHOW</s:String>
15+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
16+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary>

0 commit comments

Comments
 (0)