Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
github: vonhoff
ko_fi: vonhoff
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- Summarize your changes in the title -->

**Motivation and Context**
**Context**

<!-- Why is this change needed? Link any relevant issues. -->

Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,29 @@ on:
jobs:
build-and-test:
runs-on: windows-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup .NET 8.0
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v5
with:
dotnet-version: 8.0.x

- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --no-restore --configuration Release --framework net8.0-windows

- name: Test with Coverage
run: dotnet test --no-build --configuration Release --framework net8.0-windows --collect:"XPlat Code Coverage" --results-directory ./coverage

- name: Generate coverage report
uses: danielpalme/ReportGenerator-GitHub-Action@5.1.4
uses: danielpalme/ReportGenerator-GitHub-Action@v5
with:
reports: './coverage/**/coverage.cobertura.xml'
targetdir: './coverage/report'
Expand All @@ -50,7 +50,7 @@ jobs:
$coverage = Select-Xml -Path "./coverage/**/coverage.cobertura.xml" -XPath "//coverage/@line-rate" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty Value
$coveragePercent = [math]::Round([double]$coverage * 100, 2)
Write-Host "Current line coverage: $coveragePercent%"
if ($coveragePercent -lt 75) {
Write-Error "Code coverage ($coveragePercent%) is below the required threshold of 75%"
if ($coveragePercent -lt 80) {
Write-Error "Code coverage ($coveragePercent%) is below the required threshold of 80%"
exit 1
}
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ a project may be further defined and clarified by project maintainers.
## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at `simon.vonhoff[at]outlook.com`. All
reported by contacting the project team at `simon.vonhoff@outlook.com`. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Expand Down
61 changes: 57 additions & 4 deletions Demo/Form1.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 50 additions & 1 deletion Demo/Form1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public partial class Form1 : Form
private RichTextBoxSinkOptions? _options;
private RichTextBoxSink? _sink;
private bool _toolbarsVisible = true;
private bool _prettyPrintJson = false;
private int _spacesPerIndent = 2;
private bool _updatingIndent = false;

public Form1()
{
Expand All @@ -47,7 +50,9 @@ private void Initialize()
_options = new RichTextBoxSinkOptions(
theme: ThemePresets.Literate,
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:l}{NewLine}{Exception}",
formatProvider: new CultureInfo("en-US"));
formatProvider: new CultureInfo("en-US"),
prettyPrintJson: _prettyPrintJson,
spacesPerIndent: _spacesPerIndent);

_sink = new RichTextBoxSink(richTextBox1, _options);
Log.Logger = new LoggerConfiguration()
Expand Down Expand Up @@ -77,6 +82,15 @@ private void Initialize()

Log.Debug("Started logger.");
btnDispose.Enabled = true;
btnPrettyPrint.Text = _prettyPrintJson ? "Disable Pretty Print" : "Enable Pretty Print";

// Update the numeric up/down control without triggering events
_updatingIndent = true;
if (numericUpDownSpacesPerIndent.Value != _spacesPerIndent)
{
numericUpDownSpacesPerIndent.Value = _spacesPerIndent;
}
_updatingIndent = false;
}

private void Form1_Load(object sender, EventArgs e)
Expand Down Expand Up @@ -350,6 +364,41 @@ private void btnAutoScroll_Click(object sender, EventArgs e)
btnAutoScroll.Text = _options.AutoScroll ? "Disable Auto Scroll" : "Enable Auto Scroll";
}

private void btnPrettyPrint_Click(object sender, EventArgs e)
{
_prettyPrintJson = !_prettyPrintJson;
btnPrettyPrint.Text = _prettyPrintJson ? "Disable Pretty Print" : "Enable Pretty Print";

// Recreate the sink and logger with new pretty print setting
CloseAndFlush();
Initialize();

Log.Information("Pretty print JSON: {PrettyPrint}", _prettyPrintJson);
}

private void numericUpDownSpacesPerIndent_ValueChanged(object sender, EventArgs e)
{
// Prevent recursive calls when we're updating the value programmatically
if (_updatingIndent)
{
return;
}

var newValue = (int)numericUpDownSpacesPerIndent.Value;
if (newValue == _spacesPerIndent)
{
return;
}

_spacesPerIndent = newValue;

// Recreate the sink and logger with new indent size
CloseAndFlush();
Initialize();

Log.Information("Spaces per indent changed to: {SpacesPerIndent}", _spacesPerIndent);
}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.T)
Expand Down
46 changes: 28 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ A [Serilog](https://github.com/serilog/serilog) sink that writes log events to a
- Multiple theme presets with customization options
- High-performance asynchronous processing
- Line limit to control memory usage
- Support for pretty-printing of JSON objects
- WCAG compliant color schemes based on the [Serilog WPF RichTextBox](https://github.com/serilog-contrib/serilog-sinks-richtextbox) sink.

## Get Started
## Getting Started

Install the package from NuGet:

Expand Down Expand Up @@ -52,38 +53,47 @@ Log.Information("Hello, world!");

See the [Extension Method](Serilog.Sinks.RichTextBox.WinForms.Colored/RichTextBoxSinkLoggerConfigurationExtensions.cs) for more configuration options.

## Configuration Options

| Option | Description | Default Value |
|-------------------|------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|
| `theme` | The color theme applied when rendering individual message tokens. | `ThemePresets.Literate` |
| `autoScroll` | When `true` (default) the target control scrolls automatically to the most recent log line. | `true` |
| `maxLogLines` | Maximum number of log events retained in the in-memory circular buffer and rendered in the control. | `256` |
| `outputTemplate` | Serilog output template that controls textual formatting of each log event. | `[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}` |
| `formatProvider` | Optional culture-specific or custom formatting provider used when rendering scalar values; `null` for the invariant culture. | `CultureInfo.InvariantCulture` |
| `prettyPrintJson` | When `true`, formats JSON values with indentation and line breaks for better readability. | `false` |
| `spacesPerIndent` | Number of spaces per indentation level when pretty printing JSON. | `2` |

## Themes

Available built-in themes:

| Theme | Description |
|-----------------------------|------------------------------------------------------------------------------|
| `ThemePresets.Literate` | Styled to replicate the default theme of Serilog.Sinks.Console __(default)__ |
| `ThemePresets.Grayscale` | A theme using only shades of gray, white, and black |
| `ThemePresets.Colored` | A theme based on the original Serilog.Sinks.ColoredConsole sink |
| `ThemePresets.Luminous` | A light theme with high contrast for accessibility |
| Theme | Description |
|--------------------------|------------------------------------------------------------------------------|
| `ThemePresets.Literate` | Styled to replicate the default theme of Serilog.Sinks.Console __(default)__ |
| `ThemePresets.Grayscale` | A theme using only shades of gray, white, and black |
| `ThemePresets.Colored` | A theme based on the original Serilog.Sinks.ColoredConsole sink |
| `ThemePresets.Luminous` | A light theme with high contrast for accessibility |

The themes based on the original sinks are slightly adjusted to be [WCAG compliant](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum), ensuring that the contrast ratio between text and background colors is at least 4.5:1.

You can create your own custom themes by creating a new instance of the [Theme](Serilog.Sinks.RichTextBox.WinForms.Colored/Sinks/RichTextBoxForms/Themes/Theme.cs) class and passing it to the `RichTextBox` extension method. Look at the [existing themes](Serilog.Sinks.RichTextBox.WinForms.Colored/Sinks/RichTextBoxForms/Themes/ThemePresets.cs) for examples.

## Frequently Asked Questions

### Why is the package name so long?
## Support the Project 💖

Shorter alternatives were already reserved in the NuGet registry, so a more descriptive name was needed for this implementation. The name is a bit long, but it makes it easier to find the package in the NuGet registry.
This project has been maintained since 2022 and is still under active development. If you find it useful, please consider supporting it. Your support will help keep the project alive and allow me to dedicate more time to making improvements. You can support it through:

### Why use a WinForms RichTextBox instead of a WPF RichTextBox?
* [GitHub Sponsors](https://github.com/sponsors/vonhoff)
* [Ko-fi](https://ko-fi.com/vonhoff)

This sink is specifically designed for WinForms applications to avoid the WPF framework. Using a WPF-based logging component would require adding the entire WPF framework with all its dependencies, greatly increasing the size of the application.
Every contribution of any size helps sustain ongoing development.

## Support and Contribute
## Contributing

If you find value in this project, there are several ways you can contribute:
Contributions are welcome! Report issues, improve documentation, or submit pull requests.

- Give the [project](https://github.com/vonhoff/Serilog.Sinks.RichTextBox.WinForms.Colored) a star on GitHub ⭐
- Support the project through [GitHub Sponsors](https://github.com/sponsors/vonhoff)
- Improve docs, report bugs, or submit PRs (see [CONTRIBUTING.md](CONTRIBUTING.md))
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## License

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Reporting a Vulnerability

If you find a security issue, please email `simon.vonhoff[at]outlook.com` with a description. Include a suggested fix if you have one.
If you find a security issue, please email `simon.vonhoff@outlook.com` with a description. Include a suggested fix if you have one.

We will review the report, release a fix or mitigation if needed, and credit you. Do **not** disclose the issue publicly until a fix is released. Once addressed, public disclosure is allowed.

Loading