A Serilog sink that writes to PostgreSQL
Package - Serilog.Sinks.PostgreSQL | Platforms - .NET 4.5, .NET Standard 2.0
string connectionstring = "User ID=serilog;Password=serilog;Host=localhost;Port=5432;Database=logs";
string tableName = "logs";
//Used columns (Key is a column name)
//Column type is writer's constructor parameter
IDictionary<string, ColumnWriterBase> columnWriters = new Dictionary<string, ColumnWriterBase>
{
{"message", new RenderedMessageColumnWriter(NpgsqlDbType.Text) },
{"message_template", new MessageTemplateColumnWriter(NpgsqlDbType.Text) },
{"level", new LevelColumnWriter(true, NpgsqlDbType.Varchar) },
{"raise_date", new TimestampColumnWriter(NpgsqlDbType.Timestamp) },
{"exception", new ExceptionColumnWriter(NpgsqlDbType.Text) },
{"properties", new LogEventSerializedColumnWriter(NpgsqlDbType.Jsonb) },
{"props_test", new PropertiesColumnWriter(NpgsqlDbType.Jsonb) },
{"machine_name", new SinglePropertyColumnWriter("MachineName", PropertyWriteMethod.ToString, NpgsqlDbType.Text, "l") }
};
var logger = new LoggerConfiguration()
.WriteTo.PostgreSQL(connectionstring, tableName, columnWriters)
.CreateLogger();
If you set parameter needAutoCreateTable
to true
sink automatically create table.
You can change column sizes by setting values in TableCreator
class:
//Sets size of all BIT and BIT VARYING columns to 20
TableCreator.DefaultBitColumnsLength = 20;
//Sets size of all CHAR columns to 30
TableCreator.DefaultCharColumnsLength = 30;
//Sets size of all VARCHAR columns to 50
TableCreator.DefaultVarcharColumnsLength = 50;
or set column size individually by providing columnLength
parameter to ColumnWriter
int columnLength = 100;
new LevelColumnWriter(true, NpgsqlDbType.Varchar, columnLength)
If your schema, table or column names is in mixed case, you should set parameter respectCase
to true
.
Sink support configuration from json file via separate package Serilog.Sinks.PostgreSQL.Configuration
Example of config
"Serilog": {
"Using": [ "Serilog.Sinks.PostgreSQL.Configuration" ],
"MinimumLevel": "Debug",
"Enrich": [ "WithMachineName" ],
"WriteTo": [
{
"Name": "PostgreSQL",
"Args": {
"connectionString": "LogsDb",
"tableName": "table_name",
"needAutoCreateTable": true
}
}
]
},
"ConnectionStrings": {
"LogsDb": "User ID=serilog;Password=serilog;Host=localhost;Port=55432;Database=serilog_logs"
},
"Columns": {
"message": "RenderedMessageColumnWriter",
"message_template": "MessageTemplateColumnWriter",
"level": {
"Name": "LevelColumnWriter",
"Args": {
"renderAsText": true,
"dbType": "Varchar"
}
},
"raise_date": "TimestampColumnWriter",
"exception": "ExceptionColumnWriter",
"properties": "LogEventSerializedColumnWriter",
"props_test": {
"Name": "PropertiesColumnWriter",
"Args": { "dbType": "Json" }
},
"machine_name": {
"Name": "SinglePropertyColumnWriter",
"Args": {
"propertyName": "MachineName",
"writeMethod": "Raw"
}
}
}
}
You should add Serilog.Sinks.PostgreSQL.Configuration
into Using
section array
connectionString
can be either connection string itself or the name of connection string in ConnectionStrings
section
If Columns
section is a subsection of other you should provide a path to it in a configurationPath
parameter e.g.
"Serilog": {
"Using": [ "Serilog.Sinks.PostgreSQL.Configuration" ],
"MinimumLevel": "Debug",
"Enrich": [ "WithMachineName" ],
"WriteTo": [
{
"Name": "PostgreSQL",
"Args": {
"connectionString": "User ID=serilog;Password=serilog;Host=localhost;Port=55432;Database=serilog_logs",
"tableName": "table_name",
"configurationPath": "ColumnsSectionHolder:AnotherSubSection"
"needAutoCreateTable": true
}
}
]
},
"ColumnsSectionHolder": {
"AnotherSubSection" : {
"Columns": {
"message": "RenderedMessageColumnWriter",
"level": {
"Name": "LevelColumnWriter",
"Args": {
"renderAsText": true,
"dbType": "Varchar"
}
},
"raise_date": "TimestampColumnWriter",
"exception": "ExceptionColumnWriter"
}
}
}
In columns section key is a column name and value is a column writer. Writer can be written in two ways:
- As string value - this mean a parameterless constructor invocation e.g. this lines in config
"Columns" : {
"message": "RenderedMessageColumnWriter"
}
is similar to this code
IDictionary<string, ColumnWriterBase> columnWriters = new Dictionary<string, ColumnWriterBase>
{
{"message", new RenderedMessageColumnWriter() }
};
- As object - then writer's class name is located by the
Name
key and constructor arguments by theArgs
key. e.g.
"Columns" : {
"level": {
"Name": "LevelColumnWriter",
"Args": {
"renderAsText": true,
"dbType": "Varchar"
}
}
}
is similar to this code
IDictionary<string, ColumnWriterBase> columnWriters = new Dictionary<string, ColumnWriterBase>
{
{"level", new LevelColumnWriter(true, NpgsqlDbType.Varchar) }
};
At the moment package supports non bultin column writers only from executing asembly.