Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
15 changes: 6 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ jobs:
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
Expand All @@ -29,28 +29,25 @@ jobs:

- 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'
reporttypes: 'Html;HtmlSummary'
title: 'Code Coverage Report'

- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: './coverage/report'
continue-on-error: true

- name: Check coverage threshold
run: |
$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
14 changes: 13 additions & 1 deletion Demo/Form1.Designer.cs

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

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

public Form1()
{
Expand All @@ -47,7 +48,8 @@ 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);

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

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

private void Form1_Load(object sender, EventArgs e)
Expand Down Expand Up @@ -350,6 +353,18 @@ 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 Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.T)
Expand Down
28 changes: 18 additions & 10 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 @@ -67,23 +68,30 @@ The themes based on the original sinks are slightly adjusted to be [WCAG complia

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
## FAQ

### Why is the package name so long?

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.
Shorter alternatives were already reserved in NuGet. The descriptive name helps people find it more easily.

### Why use a WinForms RichTextBox instead of a WPF RichTextBox?
### Why a WinForms RichTextBox and not WPF?

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.
This sink is designed for WinForms apps to avoid pulling in the WPF framework and its dependencies.

## Support and Contribute
## Support the Project 💖

If you find value in this project, there are several ways you can contribute:
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:

- 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))
* [GitHub Sponsors](https://github.com/sponsors/vonhoff)
* [Ko-fi](https://ko-fi.com/vonhoff)

Every contribution of any size helps sustain ongoing development.

## Contributing

Contributions are welcome! Report issues, improve documentation, or submit pull requests.

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.

Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,40 @@ public class ConcurrentCircularBufferTests
[Fact]
public void TakeSnapshot_WithItemsLessThanCapacity_ReturnsAllItemsInOrder()
{
// Arrange
var buffer = new ConcurrentCircularBuffer<int>(3);
buffer.Add(1);
buffer.Add(2);

// Act
var snapshot = new List<int>();
buffer.TakeSnapshot(snapshot);

// Assert
Assert.Equal(new[] { 1, 2 }, snapshot);
}

[Fact]
public void AddBeyondCapacity_OverwritesOldestItemsAndMaintainsOrder()
{
// Arrange
var buffer = new ConcurrentCircularBuffer<int>(3);
buffer.Add(1);
buffer.Add(2);
buffer.Add(3);
buffer.Add(4); // Should overwrite the oldest item (1)

// Act
var snapshot = new List<int>();
buffer.TakeSnapshot(snapshot);

// Assert
Assert.Equal(new[] { 2, 3, 4 }, snapshot);
}

[Fact]
public void Clear_FollowedByAdds_SnapshotContainsOnlyNewItems()
{
// Arrange
var buffer = new ConcurrentCircularBuffer<int>(3);
buffer.Add(1);
buffer.Add(2);
buffer.Add(3);

// Act & Assert - After clear, snapshot should be empty
// After clear, snapshot should be empty
buffer.Clear();
var snapshotAfterClear = new List<int>();
buffer.TakeSnapshot(snapshotAfterClear);
Expand All @@ -71,7 +64,6 @@ public void Clear_FollowedByAdds_SnapshotContainsOnlyNewItems()
[Fact]
public void Restore_AfterClear_ReturnsAllItemsAgain()
{
// Arrange
var buffer = new ConcurrentCircularBuffer<int>(3);
buffer.Add(1);
buffer.Add(2);
Expand All @@ -82,12 +74,11 @@ public void Restore_AfterClear_ReturnsAllItemsAgain()
buffer.Add(4);
buffer.Add(5);

// Act - Restore should make all items visible again
// Restore should make all items visible again
buffer.Restore();
var snapshot = new List<int>();
buffer.TakeSnapshot(snapshot);

// Assert
Assert.Equal(new[] { 3, 4, 5 }, snapshot);
}
}
Expand Down
Loading
Loading