Serilog.Sinks.GitHubIssues 0.1.0

dotnet add package Serilog.Sinks.GitHubIssues --version 0.1.0
                    
NuGet\Install-Package Serilog.Sinks.GitHubIssues -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Serilog.Sinks.GitHubIssues" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Serilog.Sinks.GitHubIssues" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Serilog.Sinks.GitHubIssues" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Serilog.Sinks.GitHubIssues --version 0.1.0
                    
#r "nuget: Serilog.Sinks.GitHubIssues, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Serilog.Sinks.GitHubIssues@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Serilog.Sinks.GitHubIssues&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Serilog.Sinks.GitHubIssues&version=0.1.0
                    
Install as a Cake Tool

Serilog.Sinks.GitHubIssues

Serilog.Sinks.GitHubIssues is a reusable Serilog sink for promoting carefully selected high-severity log events into GitHub Issues. It is intended for escalation and operational tracking of exceptional failures, not for general log storage.

The sink targets net10.0, enables nullable reference types, and uses GitHub's REST API through HttpClient. It does not use Octokit, background job frameworks, persistence dependencies, or application-specific code.

What this sink is for

Use this sink when a small number of severe events should create or update an issue in a configured GitHub repository, for example:

  • fatal production exceptions that need triage;
  • carefully filtered error events that represent a tracked operational incident;
  • repeat occurrences of the same fingerprinted error, added as comments to the existing issue.

What this sink is not for

GitHub Issues should not be used as a high-volume log store. Use normal logging sinks and observability platforms for full log retention, querying, dashboards, metrics, traces, and bulk diagnostics. This sink is only for escalation and tracking.

Recommended usage is Fatal only, or Error only after careful filtering. Avoid routing noisy events to GitHub because GitHub API rate limits and secondary rate limits may delay or reject issue creation.

GitHub authentication and permissions

Configure a fine-grained GitHub Personal Access Token (PAT) with least privilege:

  • Repository access: only the target repository.
  • Issues: read and write.
  • Metadata: read.
  • Contents permission is not required.

If CreateLabelIfMissing is enabled, ensure the token has the GitHub permission required to create labels in the selected repository.

Do not put real secrets in source code or committed configuration. Use environment variables, secret stores, or deployment configuration.

Using it across different projects

The intended reuse model is to build this repository as a normal NuGet package and reference that package from each application that should promote fatal events to GitHub Issues. Do not copy the sink source into each application and do not add application-specific dependencies to this project.

For local development, you have two practical options:

  1. Project reference while iterating

    dotnet add path/to/YourApp/YourApp.csproj reference path/to/Serilog.Sinks.GitHubIssues/src/Serilog.Sinks.GitHubIssues/Serilog.Sinks.GitHubIssues.csproj
    

    This is convenient while changing the sink itself, but it couples the application checkout to this repository.

  2. Local or private NuGet package

    dotnet pack src/Serilog.Sinks.GitHubIssues/Serilog.Sinks.GitHubIssues.csproj -c Release -o ./artifacts/packages
    dotnet nuget add source ./artifacts/packages --name local-serilog-github-issues
    dotnet add path/to/YourApp/YourApp.csproj package Serilog.Sinks.GitHubIssues --version 0.1.0 --source ./artifacts/packages
    

    For real reuse across unrelated projects, publish the .nupkg to your organization's private NuGet feed, GitHub Packages feed, Azure Artifacts feed, or another internal package registry. Then each consuming project only needs a normal package reference:

    <PackageReference Include="Serilog.Sinks.GitHubIssues" Version="0.1.0" />
    

Source drop-in option

You can copy the sink source files directly into an application project folder and reference them by namespace, but this should be treated as a short-term or single-application convenience rather than the preferred reuse model. A NuGet package or project reference is easier to version, update, test, and share across multiple unrelated projects.

If you do choose a source drop-in:

  1. Copy the production .cs files from src/Serilog.Sinks.GitHubIssues into a folder in your application, for example Logging/GitHubIssuesSink/. For a simple application drop-in, copy FingerprintHelper.cs, GitHubIssuesRestClient.cs, GitHubIssuesSink.cs, GitHubIssuesSinkOptions.cs, LoggerSinkConfigurationGitHubIssuesExtensions.cs, and RedactionService.cs.

  2. Do not copy the test project, package project file, solution file, or AssemblyInfo.cs into the application. AssemblyInfo.cs only exists to expose internals to the test project.

  3. Ensure the application project references Serilog; SDK-style projects include copied .cs files automatically.

  4. Keep the namespace as Serilog.Sinks.GitHubIssues, then add this using directive where you configure Serilog:

    using Serilog.Sinks.GitHubIssues;
    
  5. Configure the sink exactly the same way from code:

    Log.Logger = new LoggerConfiguration()
        .WriteTo.GitHubIssues(options =>
        {
            options.Owner = "your-org";
            options.Repository = "your-repo";
            options.Token = "<github-fine-grained-pat>";
        })
        .CreateLogger();
    

For Serilog.Settings.Configuration with a source drop-in, the extension method is compiled into your application assembly rather than a separate Serilog.Sinks.GitHubIssues package assembly. If you use the Using array, list your application assembly name instead of Serilog.Sinks.GitHubIssues, or prefer code configuration for the source-drop-in approach.

Packaging as a NuGet package

Yes. The project is configured as a NuGet-style SDK project with package metadata, symbol package generation, and README packing enabled. Build a package with:

dotnet pack src/Serilog.Sinks.GitHubIssues/Serilog.Sinks.GitHubIssues.csproj -c Release -o ./artifacts/packages

The package output is suitable for publishing to a private feed or NuGet.org. Before publishing publicly, confirm the package version, release notes, and repository URL in the project file.

A typical private-feed publish command looks like this:

dotnet nuget push ./artifacts/packages/Serilog.Sinks.GitHubIssues.0.1.0.nupkg --source <your-feed-name-or-url> --api-key <feed-api-key>

For NuGet.org, use the NuGet.org source name or URL:

dotnet nuget push ./artifacts/packages/Serilog.Sinks.GitHubIssues.0.1.0.nupkg --source https://api.nuget.org/v3/index.json --api-key <nuget-api-key>

Use placeholders, environment variables, or secret-store values for feed API keys. Do not commit package feed credentials or GitHub PATs.

Code configuration

using Serilog;

Log.Logger = new LoggerConfiguration()
    .WriteTo.GitHubIssues(options =>
    {
        options.Owner = "your-org";
        options.Repository = "your-repo";
        options.Token = "<github-fine-grained-pat>";
        options.EnvironmentName = "Live";
        options.ServiceName = "OptimiseBP.WebApi";
        options.Label = "FatalError";
    })
    .CreateLogger();

You can also use the direct overload:

using Serilog;
using Serilog.Events;

Log.Logger = new LoggerConfiguration()
    .WriteTo.GitHubIssues(
        owner: "your-org",
        repository: "your-repo",
        token: "<github-fine-grained-pat>",
        label: "FatalError",
        restrictedToMinimumLevel: LogEventLevel.Fatal)
    .CreateLogger();

appsettings.json configuration

When using Serilog.Settings.Configuration, include this package in Using and configure the GitHubIssues sink by name:

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.GitHubIssues" ],
    "MinimumLevel": "Information",
    "WriteTo": [
      {
        "Name": "GitHubIssues",
        "Args": {
          "owner": "your-org",
          "repository": "your-repo",
          "token": "%GITHUB_ISSUES_PAT%",
          "label": "FatalError",
          "restrictedToMinimumLevel": "Fatal",
          "environmentName": "Live",
          "serviceName": "OptimiseBP.WebApi"
        }
      }
    ]
  }
}

Behaviour

By default, the sink:

  • promotes only Fatal events;
  • attaches the FatalError label;
  • computes a deterministic fingerprint from stable event data;
  • searches open issues in the configured repository for the fingerprint marker;
  • creates a new issue if no open issue is found;
  • optionally comments on an existing issue when the same fingerprint recurs;
  • uses a bounded in-memory queue and drops promotions safely when the queue is full;
  • processes GitHub writes serially on a single background worker;
  • uses Serilog.Debugging.SelfLog for internal diagnostics and never logs recursively through Serilog.

Created issue bodies include an HTML fingerprint marker:


Duplicate searches use the GitHub Issues search API with a query equivalent to:

repo:{owner}/{repo} is:issue is:open label:{label} "serilog-github-issues:fingerprint:{fingerprint}"

Operational cautions

  • GitHub REST API rate limits and secondary rate limits can delay or reject writes.
  • The sink honors Retry-After and x-ratelimit-reset headers where available, otherwise it backs off before retrying.
  • Do not log secrets, patient data, request bodies, or full HTTP headers.
  • The sink redacts common sensitive property names, bearer tokens, obvious connection strings, email addresses, and long digit sequences, but redaction is a last line of defense and is not a substitute for safe logging practices.
  • Use regular logging sinks for full retention and forensic detail.
  • Prefer requiring the configured label to already exist. If CreateLabelIfMissing is false and GitHub rejects issue creation because the label is missing, the promotion is dropped and the failure is written to SelfLog.

Key options

Option Default Description
Owner required GitHub repository owner or organization.
Repository required GitHub repository name.
Token required Fine-grained GitHub PAT.
Label FatalError Label attached to new issues and used for duplicate searches.
RestrictedToMinimumLevel Fatal Minimum event level promoted to GitHub Issues.
MaxQueueSize 1000 Maximum pending promotions retained in memory.
MinSecondsBetweenGitHubWrites 1 Minimum delay between mutating GitHub requests.
CommentOnExistingIssue true Add recurrence comments to existing issues.
CreateLabelIfMissing false Attempt to create the label and retry once if issue creation fails due to a missing label.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 119 5/17/2026

Initial preview release.