Skip to content

Commit 290a7bb

Browse files
authored
Merge pull request #13 from vonhoff/v1.2.3
Version update to 2.0.0
2 parents b257725 + 945a908 commit 290a7bb

File tree

15 files changed

+189
-114
lines changed

15 files changed

+189
-114
lines changed

README.md

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
11
# Serilog.Sinks.RichTextBox.WinForms.Colored
2+
23
[![NuGet Downloads](https://img.shields.io/nuget/dt/Serilog.Sinks.RichTextBox.WinForms.Colored.svg)](https://www.nuget.org/packages/Serilog.Sinks.RichTextBox.WinForms.Colored)
34
[![Latest version](https://img.shields.io/nuget/v/Serilog.Sinks.RichTextBox.WinForms.Colored.svg)](https://www.nuget.org/packages/Serilog.Sinks.RichTextBox.WinForms.Colored)
45
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
56

6-
A [Serilog](https://serilog.net) sink that writes log events to any WinForms [RichTextBox](https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/richtextbox-control-overview-windows-forms) control with coloring and custom theme support.
7+
A [Serilog](https://github.com/serilog/serilog) sink that writes log events to
8+
a [WinForms RichTextBox](https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/richtextbox-control-overview-windows-forms)
9+
with support for coloring and custom themes.
10+
11+
![Screenshot of Serilog.Sinks.RichTextBox.WinForms.Colored in action](https://raw.githubusercontent.com/vonhoff/Serilog.Sinks.RichTextBox.WinForms.Colored/main/Assets/screenshot.png)
12+
13+
## Features
714

8-
![Screenshot of Serilog.Sinks.RichTextBox.WinForms.Colored in action](Assets/screenshot.png)
15+
- Write log events to a WinForms RichTextBox control
16+
- Customizable themes (Dark and Light presets available)
17+
- Configurable output templates
18+
- Auto-scrolling option
19+
- Line limit control
920

10-
## Getting started
21+
## Installation
1122

12-
Install the [Serilog.Sinks.RichTextBox.WinForms.Colored](https://www.nuget.org/packages/Serilog.Sinks.RichTextBox.WinForms.Colored) package from NuGet:
23+
Install the package from NuGet:
1324

1425
```powershell
1526
Install-Package Serilog.Sinks.RichTextBox.WinForms.Colored
1627
```
1728

18-
Declare your [RichTextBox](https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/richtextbox-control-overview-windows-forms) control and give it a name that you can reference it from the code-behind. e.g.:
29+
## Usage
30+
31+
### Basic Setup
32+
33+
Declare your RichTextBox control:
1934

2035
```csharp
2136
private System.Windows.Forms.RichTextBox richTextBox1;
37+
2238
private void InitializeComponent()
2339
{
2440
this.richTextBox1.BackColor = System.Drawing.SystemColors.Window;
@@ -29,60 +45,52 @@ private void InitializeComponent()
2945
}
3046
```
3147

32-
Then enable the sink using the following snippet:
48+
Configure the logger:
3349

3450
```csharp
35-
var options = new RichTextBoxSinkOptions(ThemePresets.Dark, 200, 5, true);
36-
var sink = new RichTextBoxSink(richTextBox1, _options);
3751
Log.Logger = new LoggerConfiguration()
38-
.MinimumLevel.Verbose()
39-
.WriteTo.Sink(sink, LogEventLevel.Verbose)
40-
.Enrich.WithThreadId()
52+
.WriteTo.RichTextBox(richTextBox1)
4153
.CreateLogger();
4254

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

46-
Log events will be written to the `RichTextBox` control:
47-
48-
```
49-
[11:54:36 INF] Hello, world!
50-
```
51-
52-
### Themes
53-
54-
The following built-in themes are available at this time:
55-
56-
| Theme | Description
57-
| ----------------------------------- | ----------------------------------------------------------------- |
58-
| `ThemePresets.Dark` | Styled to replicate the default theme of _Serilog.Sinks.Console_ |
59-
| `ThemePresets.Light` | A theme with a light background and contrasting colors. |
60-
61-
### Output templates
58+
### Advanced Configuration
6259

63-
The format of events to the RichTextBox can be modified by providing a template renderer to the sink.
60+
You can customize the sink using various parameters from the RichTextBox extension method:
6461

6562
```csharp
66-
var options = new RichTextBoxSinkOptions(ThemePresets.Dark, 200, 5, true);
67-
var renderer = new TemplateRenderer(ThemePresets.Dark, "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}");
68-
var sink = new RichTextBoxSink(richTextBox1, _options, renderer);
6963
Log.Logger = new LoggerConfiguration()
70-
.MinimumLevel.Verbose()
71-
.WriteTo.Sink(sink, LogEventLevel.Verbose)
72-
.Enrich.WithThreadId()
64+
.WriteTo.RichTextBox(
65+
richTextBoxControl: richTextBox1,
66+
minimumLogEventLevel: LogEventLevel.Debug,
67+
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}",
68+
theme: ThemePresets.Light,
69+
messageBatchSize: 100,
70+
messagePendingInterval: 10,
71+
autoScroll: true,
72+
maxLogLines: 1000)
7373
.CreateLogger();
7474

75-
Log.Information("Hello, world!");
7675
```
7776

78-
## Acknowledgments
77+
### Themes
78+
79+
Available built-in themes:
80+
81+
| Theme | Description |
82+
|----------------------|---------------------------------------------------------|
83+
| `ThemePresets.Dark` | Similar to the default theme of _Serilog.Sinks.Console_ |
84+
| `ThemePresets.Light` | Light background with contrasting colors |
7985

80-
If you find this sink useful in your projects, consider leaving a star! ⭐
86+
## Support and Contribute
8187

82-
## Contribution
88+
If you find value in this project, there are several ways you can contribute:
8389

84-
If you want to contribute to this project, you are welcome to submit pull requests or report issues on GitHub.
90+
- **Become a Sponsor:** Support the project through [GitHub Sponsors](https://github.com/sponsors/vonhoff).
91+
- **Show Your Appreciation:** Give the [project](https://github.com/vonhoff/Serilog.Sinks.RichTextBox.WinForms.Colored) a star on GitHub.
92+
- **Contribute:** Improve documentation, report bugs, or submit pull requests.
8593

8694
## License
8795

88-
This project is licensed under the terms of the [Apache License, Version 2.0](LICENSE).
96+
This project is licensed under the [Apache License, Version 2.0](LICENSE).

SampleForm/Form1.cs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace SampleForm
3131
{
3232
public partial class Form1 : Form
3333
{
34-
private RichTextBoxSinkOptions _options = null!;
34+
private RichTextBoxSinkOptions? _options;
3535

3636
private void Initialize()
3737
{
@@ -102,17 +102,17 @@ private void BtnInformation_Click(object sender, EventArgs e)
102102

103103
private void BtnParallelFor_Click(object sender, EventArgs e)
104104
{
105-
Parallel.For(1, 101, stepNumber =>
105+
for (var stepNumber = 1; stepNumber <= 100; stepNumber++)
106106
{
107-
var stepName = FormattableString.Invariant($"Step {stepNumber:000}");
108-
109-
Log.Verbose("Hello from Parallel.For({StepName}) Verbose", stepName);
110-
Log.Debug("Hello from Parallel.For({StepName}) Debug", stepName);
111-
Log.Information("Hello from Parallel.For({StepName}) Information", stepName);
112-
Log.Warning("Hello from Parallel.For({StepName}) Warning", stepName);
113-
Log.Error("Hello from Parallel.For({StepName}) Error", stepName);
114-
Log.Fatal("Hello from Parallel.For({StepName}) Fatal", stepName);
115-
});
107+
var stepName = $"Step {stepNumber:000}";
108+
109+
Log.Verbose("Hello from For({StepName}) Verbose", stepName);
110+
Log.Debug("Hello from For({StepName}) Debug", stepName);
111+
Log.Information("Hello from For({StepName}) Information", stepName);
112+
Log.Warning("Hello from For({StepName}) Warning", stepName);
113+
Log.Error("Hello from For({StepName}) Error", stepName);
114+
Log.Fatal("Hello from For({StepName}) Fatal", stepName);
115+
}
116116
}
117117

118118
private async void BtnTaskRun_Click(object sender, EventArgs e)
@@ -124,7 +124,7 @@ private async void BtnTaskRun_Click(object sender, EventArgs e)
124124
var stepNumber = i;
125125
var task = Task.Run(() =>
126126
{
127-
var stepName = FormattableString.Invariant($"Step {stepNumber:000}");
127+
var stepName = $"Step {stepNumber:000}";
128128

129129
Log.Verbose("Hello from Task.Run({StepName}) Verbose", stepName);
130130
Log.Debug("Hello from Task.Run({StepName}) Debug", stepName);
@@ -181,16 +181,26 @@ private void BtnReset_Click(object sender, EventArgs e)
181181

182182
private void BtnAutoScroll_Click(object sender, EventArgs e)
183183
{
184+
if (_options == null)
185+
{
186+
return;
187+
}
188+
184189
_options.AutoScroll = !_options.AutoScroll;
185190
btnAutoScroll.Text = _options.AutoScroll ? "Disable Auto Scroll" : "Enable Auto Scroll";
186191
}
187192

188193
private void BtnLogLimit_Click(object sender, EventArgs e)
189194
{
190-
bool limitEnabled = _options.MaxLogLines != int.MaxValue;
195+
if (_options == null)
196+
{
197+
return;
198+
}
199+
200+
var limitEnabled = _options.MaxLogLines != int.MaxValue;
191201
_options.MaxLogLines = limitEnabled ? 0 : 35;
192202
btnLogLimit.Text = limitEnabled ? "Enable Line Limit" : "Disable Line Limit";
193-
Log.Information("Log line limit set to {lineLimit}", _options.MaxLogLines == int.MaxValue ? "Maximum" : _options.MaxLogLines);
203+
Log.Information("Log line limit set to {lineLimit}", _options.MaxLogLines == int.MaxValue ? "Maximum" : _options.MaxLogLines.ToString());
194204
}
195205
}
196-
}
206+
}

SampleForm/Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ internal static class Program
2626
[STAThread]
2727
private static void Main()
2828
{
29-
Application.SetHighDpiMode(HighDpiMode.SystemAware);
3029
Application.EnableVisualStyles();
3130
Application.SetCompatibleTextRenderingDefault(false);
3231
Application.Run(new Form1());

SampleForm/SampleForm.csproj

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,12 @@
22

33
<PropertyGroup>
44
<OutputType>WinExe</OutputType>
5-
<TargetFramework>net6.0-windows</TargetFramework>
5+
<TargetFrameworks>net452</TargetFrameworks>
66
<Nullable>enable</Nullable>
77
<UseWindowsForms>true</UseWindowsForms>
8+
<LangVersion>9.0</LangVersion>
89
</PropertyGroup>
910

10-
<ItemGroup>
11-
<PackageReference Include="Serilog" Version="3.0.1" />
12-
</ItemGroup>
13-
1411
<ItemGroup>
1512
<ProjectReference Include="..\Serilog.Sinks.RichTextBox.WinForms\Serilog.Sinks.RichTextBox.WinForms.Colored.csproj" />
1613
</ItemGroup>

Serilog.Sinks.RichTextBox.WinForms/Serilog.Sinks.RichTextBox.WinForms.Colored.csproj

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<Authors>Simon Vonhoff</Authors>
@@ -21,15 +21,34 @@
2121
<RepositoryUrl>https://github.com/vonhoff/serilog-sinks-richtextbox-winforms.git</RepositoryUrl>
2222
<RootNamespace>Serilog</RootNamespace>
2323
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
24-
<TargetFramework>net6.0-windows7.0</TargetFramework>
24+
<TargetFrameworks>net452;net6.0-windows;net8.0-windows</TargetFrameworks>
2525
<UseWindowsForms>true</UseWindowsForms>
26-
<Version>1.2.2</Version>
27-
<PackageReleaseNotes>- Fixed bug with autoscrolling and line limit.
26+
<Version>2.0.0</Version>
27+
<PackageReleaseNotes>- Added support for .NET 8
28+
- Added support for .NET Framework 4.5.2
29+
- Added outputTemplate and formatProvider to options
2830

2931
See repository for more information:
3032
https://github.com/vonhoff/Serilog.Sinks.RichTextBox.WinForms.Colored</PackageReleaseNotes>
3133
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
3234
<NeutralLanguage>en-US</NeutralLanguage>
35+
<LangVersion>9.0</LangVersion>
36+
</PropertyGroup>
37+
38+
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-windows|AnyCPU'">
39+
<WarningLevel>6</WarningLevel>
40+
</PropertyGroup>
41+
42+
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-windows|AnyCPU'">
43+
<WarningLevel>6</WarningLevel>
44+
</PropertyGroup>
45+
46+
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net452|AnyCPU'">
47+
<WarningLevel>5</WarningLevel>
48+
</PropertyGroup>
49+
50+
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net452|AnyCPU'">
51+
<WarningLevel>5</WarningLevel>
3352
</PropertyGroup>
3453

3554
<ItemGroup>
@@ -44,7 +63,7 @@ https://github.com/vonhoff/Serilog.Sinks.RichTextBox.WinForms.Colored</PackageRe
4463
</ItemGroup>
4564

4665
<ItemGroup>
47-
<PackageReference Include="Serilog" Version="3.0.1" />
66+
<PackageReference Include="Serilog" Version="2.10.0" />
4867
</ItemGroup>
4968

50-
</Project>
69+
</Project>

Serilog.Sinks.RichTextBox.WinForms/Sinks/RichTextBoxForms/Extensions/ControlExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static void Suspend(this Control control)
6262
private static void InvokeWindowProcedure(in Control control, ref Message message)
6363
{
6464
var window = NativeWindow.FromHandle(control.Handle);
65-
window.DefWndProc(ref message);
65+
window?.DefWndProc(ref message);
6666
}
6767
}
6868
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
3+
namespace Serilog.Sinks.RichTextBoxForms.Extensions
4+
{
5+
internal static class KeyValuePairExtensions
6+
{
7+
public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value)
8+
{
9+
key = tuple.Key;
10+
value = tuple.Value;
11+
}
12+
}
13+
}

Serilog.Sinks.RichTextBox.WinForms/Sinks/RichTextBoxForms/Extensions/RichTextBoxExtensions.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
using System;
2020
using System.Drawing;
21-
using System.Linq;
2221
using System.Runtime.InteropServices;
2322
using System.Windows.Forms;
2423

@@ -46,7 +45,7 @@ public static void AppendRtf(this RichTextBox richTextBox, string rtf, bool auto
4645
{
4746
if (richTextBox.InvokeRequired)
4847
{
49-
richTextBox.Invoke(() => AppendRtf(richTextBox, rtf, autoScroll, maxLogLines));
48+
richTextBox.Invoke(new Action(() => AppendRtf(richTextBox, rtf, autoScroll, maxLogLines)));
5049
return;
5150
}
5251

@@ -77,8 +76,16 @@ public static void AppendRtf(this RichTextBox richTextBox, string rtf, bool auto
7776

7877
if (richTextBox.Lines.Length > maxLogLines)
7978
{
79+
var linesToRemove = richTextBox.Lines.Length - maxLogLines;
80+
var charsToRemove = 0;
81+
82+
for (var i = 0; i < linesToRemove; i++)
83+
{
84+
charsToRemove += richTextBox.Lines[i].Length + 1;
85+
}
86+
8087
richTextBox.SelectionStart = 0;
81-
richTextBox.SelectionLength = richTextBox.Lines[..^maxLogLines].Sum(line => line.Length + 1);
88+
richTextBox.SelectionLength = charsToRemove;
8289
richTextBox.SelectedText = NullCharacter;
8390
previousSelection = 0;
8491
previousLength = 0;

Serilog.Sinks.RichTextBox.WinForms/Sinks/RichTextBoxForms/Formatting/DisplayValueFormatter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using System.IO;
2121
using System.Windows.Forms;
2222
using Serilog.Events;
23+
using Serilog.Sinks.RichTextBoxForms.Extensions;
2324
using Serilog.Sinks.RichTextBoxForms.Themes;
2425

2526
namespace Serilog.Sinks.RichTextBoxForms.Formatting

Serilog.Sinks.RichTextBox.WinForms/Sinks/RichTextBoxForms/Formatting/JsonValueFormatter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using System.IO;
2222
using System.Windows.Forms;
2323
using Serilog.Events;
24+
using Serilog.Sinks.RichTextBoxForms.Extensions;
2425
using Serilog.Sinks.RichTextBoxForms.Themes;
2526

2627
namespace Serilog.Sinks.RichTextBoxForms.Formatting
@@ -233,7 +234,7 @@ public static string GetQuotedJsonString(string str)
233234
{
234235
anyEscaped = true;
235236

236-
output.Write(str[cleanSegmentStart..i]);
237+
output.Write(str.Substring(cleanSegmentStart, i - cleanSegmentStart));
237238
cleanSegmentStart = i + 1;
238239

239240
switch (c)
@@ -282,7 +283,7 @@ public static string GetQuotedJsonString(string str)
282283
{
283284
if (cleanSegmentStart != str.Length)
284285
{
285-
output.Write(str[cleanSegmentStart..]);
286+
output.Write(str.Substring(cleanSegmentStart));
286287
}
287288
}
288289
else

0 commit comments

Comments
 (0)