Raycoon.Serilog.Sinks.SQLite 1.0.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package Raycoon.Serilog.Sinks.SQLite --version 1.0.4
                    
NuGet\Install-Package Raycoon.Serilog.Sinks.SQLite -Version 1.0.4
                    
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="Raycoon.Serilog.Sinks.SQLite" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Raycoon.Serilog.Sinks.SQLite" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Raycoon.Serilog.Sinks.SQLite" />
                    
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 Raycoon.Serilog.Sinks.SQLite --version 1.0.4
                    
#r "nuget: Raycoon.Serilog.Sinks.SQLite, 1.0.4"
                    
#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 Raycoon.Serilog.Sinks.SQLite@1.0.4
                    
#: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=Raycoon.Serilog.Sinks.SQLite&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Raycoon.Serilog.Sinks.SQLite&version=1.0.4
                    
Install as a Cake Tool

Raycoon.Serilog.Sinks.SQLite

NuGet License .NET

A modern, high-performance Serilog sink for SQLite databases. Developed for .NET 8+ with full AnyCPU support.

Features

  • AnyCPU compatible - Uses Microsoft.Data.Sqlite (no native SQLite required)
  • .NET 8.0, .NET 9.0 & .NET 10.0 support
  • Asynchronous batching - Optimal performance through batch writing
  • Automatic retention - By time, count, or database size
  • Custom columns - Store structured data in dedicated columns
  • WAL mode - Optimized for high write load
  • Thread-safe - Fully suitable for parallel logging
  • Configurable - Extensive options for every use case

Installation

dotnet add package Raycoon.Serilog.Sinks.SQLite

Quick Start

Basic Usage

using Serilog;

var logger = new LoggerConfiguration()
    .WriteTo.SQLite("logs/app.db")
    .CreateLogger();

logger.Information("Hello, SQLite!");
logger.Error(new Exception("Oops!"), "An error occurred");

// Important: Dispose the logger at the end
await Log.CloseAndFlushAsync();

Advanced Configuration

using Serilog;
using Serilog.Events;
using Raycoon.Serilog.Sinks.SQLite.Options;

var logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .Enrich.FromLogContext()
    .Enrich.WithThreadId()
    .WriteTo.SQLite("logs/app.db", options =>
    {
        // Table name
        options.TableName = "ApplicationLogs";

        // Retention: Delete logs older than 30 days
        options.RetentionPeriod = TimeSpan.FromDays(30);

        // Retention: Keep maximum 100,000 entries
        options.RetentionCount = 100_000;

        // Retention: Database max. 100 MB
        options.MaxDatabaseSize = 100 * 1024 * 1024;

        // Performance tuning
        options.BatchSizeLimit = 200;
        options.BatchPeriod = TimeSpan.FromSeconds(1);
        options.QueueLimit = 50000;

        // SQLite optimizations
        options.JournalMode = SQLiteJournalMode.Wal;
        options.SynchronousMode = SQLiteSynchronousMode.Normal;

        // Store timestamps in UTC
        options.StoreTimestampInUtc = true;

        // Minimum log level for this sink
        options.RestrictedToMinimumLevel = LogEventLevel.Information;
    })
    .CreateLogger();

Custom Columns

Store structured data in dedicated columns for better queries:

var logger = new LoggerConfiguration()
    .WriteTo.SQLite("logs/app.db", options =>
    {
        options.CustomColumns.Add(new CustomColumn
        {
            ColumnName = "UserId",
            DataType = "TEXT",
            PropertyName = "UserId",
            CreateIndex = true // Index for fast searches
        });

        options.CustomColumns.Add(new CustomColumn
        {
            ColumnName = "RequestId",
            DataType = "TEXT",
            PropertyName = "RequestId"
        });

        options.CustomColumns.Add(new CustomColumn
        {
            ColumnName = "Duration",
            DataType = "REAL",
            PropertyName = "DurationMs"
        });
    })
    .CreateLogger();

// Usage
logger
    .ForContext("UserId", "user123")
    .ForContext("RequestId", Guid.NewGuid())
    .ForContext("DurationMs", 42.5)
    .Information("Request processed");

Error Handling

var logger = new LoggerConfiguration()
    .WriteTo.SQLite("logs/app.db", options =>
    {
        options.OnError = ex =>
        {
            Console.WriteLine($"SQLite Error: {ex.Message}");
            // Or: Use a fallback logger
        };

        // Throw exception on critical errors
        options.ThrowOnError = false; // Default: false
    })
    .CreateLogger();

JSON Configuration (appsettings.json)

The sink supports full configuration via appsettings.json using Serilog.Settings.Configuration:

dotnet add package Serilog.Settings.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
Basic JSON Configuration
{
  "Serilog": {
    "Using": ["Raycoon.Serilog.Sinks.SQLite"],
    "MinimumLevel": "Information",
    "WriteTo": [
      {
        "Name": "SQLite",
        "Args": {
          "databasePath": "logs/app.db"
        }
      }
    ]
  }
}
Full JSON Configuration
{
  "Serilog": {
    "Using": ["Raycoon.Serilog.Sinks.SQLite"],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "SQLite",
        "Args": {
          "databasePath": "logs/app.db",
          "tableName": "ApplicationLogs",
          "restrictedToMinimumLevel": "Information",
          "storeTimestampInUtc": true,
          "autoCreateDatabase": true,
          "storePropertiesAsJson": true,
          "storeExceptionDetails": true,
          "maxMessageLength": 10000,
          "maxExceptionLength": 20000,
          "maxPropertiesLength": 10000,
          "batchSizeLimit": 200,
          "batchPeriod": "00:00:01",
          "queueLimit": 50000,
          "retentionPeriod": "30.00:00:00",
          "retentionCount": 100000,
          "maxDatabaseSize": 104857600,
          "cleanupInterval": "01:00:00",
          "journalMode": "Wal",
          "synchronousMode": "Normal",
          "throwOnError": false,
          "customColumns": [
            {
              "columnName": "UserId",
              "dataType": "TEXT",
              "propertyName": "UserId",
              "allowNull": true,
              "createIndex": true
            },
            {
              "columnName": "RequestId",
              "dataType": "TEXT",
              "propertyName": "RequestId",
              "allowNull": true,
              "createIndex": false
            },
            {
              "columnName": "Duration",
              "dataType": "REAL",
              "propertyName": "DurationMs",
              "allowNull": true,
              "createIndex": false
            }
          ]
        }
      }
    ],
    "Enrich": ["FromLogContext"]
  }
}
C# Setup for JSON Configuration
using Microsoft.Extensions.Configuration;
using Serilog;

var configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json")
    .Build();

var logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();
TimeSpan Format in JSON
Format Example Description
hh:mm:ss "00:00:02" 2 seconds
hh:mm:ss.fff "00:00:00.500" 500 milliseconds
d.hh:mm:ss "7.00:00:00" 7 days
d.hh:mm:ss "30.00:00:00" 30 days
Enum Values in JSON
Property Valid Values
journalMode "Delete", "Truncate", "Persist", "Memory", "Wal", "Off"
synchronousMode "Off", "Normal", "Full", "Extra"
restrictedToMinimumLevel "Verbose", "Debug", "Information", "Warning", "Error", "Fatal"
Limitations

The following options are not available via JSON configuration:

  • OnError callback (delegates cannot be serialized)
  • AdditionalConnectionParameters (dictionary binding is complex)

Use programmatic configuration for these features.

Database Schema

The sink automatically creates the following table:

Column Type Description
Id INTEGER Primary key (auto-increment)
Timestamp TEXT ISO 8601 timestamp
Level INTEGER Log level (0-5)
LevelName TEXT Log level name
Message TEXT Rendered message
MessageTemplate TEXT Original message template
Exception TEXT Exception details (if present)
Properties TEXT Properties as JSON
SourceContext TEXT Logger name / source
MachineName TEXT Computer name
ThreadId INTEGER Thread ID

Plus all configured custom columns.

Querying Logs

-- All errors from the last 24 hours
SELECT * FROM Logs
WHERE Level >= 4
AND Timestamp > datetime('now', '-1 day')
ORDER BY Timestamp DESC;

-- Logs by UserId (if custom column configured)
SELECT * FROM Logs
WHERE UserId = 'user123'
ORDER BY Timestamp DESC
LIMIT 100;

-- Aggregation by level
SELECT LevelName, COUNT(*) as Count
FROM Logs
GROUP BY Level;

-- Search through properties (JSON)
SELECT * FROM Logs
WHERE json_extract(Properties, '$.RequestId') = 'abc123';

Performance Tips

1. Optimize Batch Size

options.BatchSizeLimit = 500;  // For high-volume
options.BatchPeriod = TimeSpan.FromMilliseconds(100);

2. Use WAL Mode (Default)

options.JournalMode = SQLiteJournalMode.Wal;

3. Adjust Synchronous Mode

// Faster, but less safe in case of power failure
options.SynchronousMode = SQLiteSynchronousMode.Normal;

// Or for maximum performance (only if data loss is acceptable)
options.SynchronousMode = SQLiteSynchronousMode.Off;

4. Set Queue Limit

// Prevents memory overflow during burst traffic
options.QueueLimit = 100000;

Comparison to Other SQLite Sinks

Feature Raycoon.Serilog.Sinks.SQLite Serilog.Sinks.SQLite
AnyCPU Support Yes (Microsoft.Data.Sqlite) No (System.Data.SQLite)
.NET 8/9/10 Yes Partial (.NET 7 only)
Async Batching Yes Yes
Retention Policies Yes (time, count, size) No
Custom Columns Yes No
WAL Mode Yes Yes

API Reference

SQLiteSinkOptions

Database
Property Type Default Description
DatabasePath string "logs.db" Path to the SQLite database file
TableName string "Logs" Name of the log table
AutoCreateDatabase bool true Auto-create database file if not exists
Logging Behavior
Property Type Default Description
RestrictedToMinimumLevel LogEventLevel Verbose Minimum log level to capture
StoreTimestampInUtc bool true Store timestamps in UTC (false = local time)
StorePropertiesAsJson bool true Store log event properties as JSON
StoreExceptionDetails bool true Store exception details in separate column
Data Limits
Property Type Default Description
MaxMessageLength int? null Max rendered message length (null = unlimited)
MaxExceptionLength int? null Max exception text length (null = unlimited)
MaxPropertiesLength int? null Max properties JSON length (null = unlimited)
Batching & Performance
Property Type Default Description
BatchSizeLimit int 100 Max events per batch write
BatchPeriod TimeSpan 2s Interval between batch writes
QueueLimit int? 10000 Max events in memory queue (null = unlimited)
Retention Policy
Property Type Default Description
RetentionPeriod TimeSpan? null Delete logs older than this (null = disabled)
RetentionCount long? null Keep only this many logs (null = disabled)
MaxDatabaseSize long? null Max database size in bytes (null = disabled)
CleanupInterval TimeSpan 1h Interval for retention cleanup checks
SQLite Configuration
Property Type Default Description
JournalMode SQLiteJournalMode Wal SQLite journal mode (Wal recommended)
SynchronousMode SQLiteSynchronousMode Normal SQLite synchronous mode
AdditionalConnectionParameters Dictionary {} Extra SQLite connection string parameters

License

Apache 2.0 - See LICENSE for details.

Contributing

Pull requests are welcome! Please open an issue first to discuss proposed changes.

Changelog

1.0.0

  • Initial Release
  • .NET 8.0, .NET 9.0 and .NET 10.0 support
  • AnyCPU compatibility with Microsoft.Data.Sqlite
  • Async batching
  • Retention policies (time, count, size)
  • Custom columns
  • WAL mode support
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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
1.1.1 95 2/15/2026
1.0.8 100 1/29/2026
1.0.7 94 1/29/2026
1.0.4 92 1/29/2026
1.0.3 102 1/28/2026
1.0.2 93 1/28/2026
1.0.0 90 1/28/2026

Add JSON configuration support