- 7 minutes to read

Logging using SeriLog

Use one of Nodinite's SeriLog sinks with your full framework and .NET Core applications to enable end to end tracking. This feature also includes Microsoft Azure functions built with .NET (usually csharp).

The following Serilog sinks are available:

Sink Reliable GitHub Nuget
Log API GitHub NuGet Version
File (SMB) GitHub NuGet Version
Azure Service Bus GitHub NuGet Version
Azure Event Hub GitHub NuGet Version

Configuration

You must add configuration either in code (explicit) or the configuration file appsettings.json (implicit)

  1. Code
  2. Appsettings.json

1. Code

string nodiniteApiUrl = "https://yourenv/nodinite/logapi/";

var settings = new NodiniteLogEventSettings()
{
    LogAgentValueId = 503,
    EndPointDirection = 0,
    EndPointTypeId = 0,
    EndPointUri = "Nodinite.Serilog.ApiSink.Tests.Serilog",
    EndPointName = "Nodinite.Serilog.ApiSink.Tests",
    ProcessingUser = "NODINITE",
    ProcessName = "Nodinite.Serilog.LogApiSink.Tests",
    ProcessingMachineName = "NODINITE-DEV",
    ProcessingModuleName = "DOTNETCORE.TESTS",
    ProcessingModuleType = "DOTNETCORE.TESTPROJECT"
};

ILogger log = new LoggerConfiguration()
   .WriteTo.NodiniteApiSink(nodiniteApiUrl, settings)
   .CreateLogger();

2. Appsettings.json

{
  "Serilog": {
    "Using": [ "Nodinite.Serilog.Apisink" ],
    "WriteTo": [
      {
        "Name": "NodiniteApiSink",
        "Args": {
          "NodiniteApiUrl": "",
          "Settings": {
            "LogAgentValueId": 503,
            "EndPointName": "Nodinite.Serilog.ApiSink.Tests",
            "EndPointUri": "Nodinite.Serilog.ApiSink.Tests.Serilog",
            "EndPointDirection": 0,
            "EndPointTypeId": 0,
            "OriginalMessageTypeName": "Serilog.LogEvent",
            "ProcessingUser": "NODINITE",
            "ProcessName": "Nodinite.Serilog.ApiSink.Tests",
            "ProcessingMachineName": "NODINITE-DEV",
            "ProcessingModuleName": "DOTNETCORE.TESTS",
            "ProcessingModuleType": "DOTNETCORE.TESTPROJECT"
          }
        }
      }
    ]
  }
}
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

Logger log = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

1. Code

var folder = "{Your Folder}";

var settings = new NodiniteLogEventSettings()
{
    LogAgentValueId = 503,
    EndPointDirection = 0,
    EndPointTypeId = 0,
    EndPointUri = "Nodinite.Serilog.FileSink.Tests.Serilog",
    EndPointName = "Nodinite.Serilog.FileSink.Tests",
    ProcessingUser = "NODINITE",
    ProcessName = "Nodinite.Serilog.FileSink.Tests",
    ProcessingMachineName = "NODINITE-DEV",
    ProcessingModuleName = "DOTNETCORE.TESTS",
    ProcessingModuleType = "DOTNETCORE.TESTPROJECT"
};

ILogger log = new LoggerConfiguration()
    .WriteTo.NodiniteFileSink(folder, settings)
    .CreateLogger();

2. Appsettings.json

{
  "Serilog": {
    "Using": [ "Nodinite.Serilog.FileSink" ],
    "WriteTo": [
      {
        "Name": "NodiniteFileSink",
        "Args": {
          "Folder": "",
          "Settings": {
            "LogAgentValueId": 503,
            "EndPointName": "Nodinite.Serilog.FileSink.Tests",
            "EndPointUri": "Nodinite.Serilog.FileSink.Tests.Serilog",
            "EndPointDirection": 0,
            "EndPointTypeId": 0,
            "OriginalMessageTypeName": "Serilog.LogEvent",
            "ProcessingUser": "NODINITE",
            "ProcessName": "Nodinite.Serilog.FileSink.Tests",
            "ProcessingMachineName": "NODINITE-DEV",
            "ProcessingModuleName": "DOTNETCORE.TESTS",
            "ProcessingModuleType": "DOTNETCORE.TESTPROJECT"
          }
        }
      }
    ]
  }
}
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

Logger log = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

1. Code

var connectionString = "{Your ServiceBus Connection String";
var queueName = "{Your ServiceBus Queue Name}";

var settings = new NodiniteLogEventSettings()
{
    LogAgentValueId = 503,
    EndPointDirection = 0,
    EndPointTypeId = 0,
    EndPointUri = "Nodinite.Serilog.ServiceBusSink.Tests.Serilog",
    EndPointName = "Nodinite.Serilog.ServiceBusSink.Tests",
    ProcessingUser = "NODINITE",
    ProcessName = "Nodinite.Serilog.ServiceBusSink.Tests",
    ProcessingMachineName = "NODINITE-DEV",
    ProcessingModuleName = "DOTNETCORE.TESTS",
    ProcessingModuleType = "DOTNETCORE.TESTPROJECT"
};

ILogger log = new LoggerConfiguration()
    .WriteTo.NodiniteServiceBusSink(connectionString, queueName, settings)
    .CreateLogger();

2. Appsettings.json

{
  "Serilog": {
    "Using": [ "Nodinite.Serilog.ServiceBusSink" ],
    "WriteTo": [
      {
        "Name": "NodiniteServiceBusSink",
        "Args": {
          "ConnectionString": "",
          "QueueName":  "",
          "Settings": {
            "LogAgentValueId": 503,
            "EndPointName": "Nodinite.Serilog.ServiceBusSink.Tests",
            "EndPointUri": "Nodinite.Serilog.ServiceBusSink.Tests.Serilog",
            "EndPointDirection": 0,
            "EndPointTypeId": 0,
            "OriginalMessageTypeName": "Serilog.LogEvent",
            "ProcessingUser": "NODINITE",
            "ProcessName": "Nodinite.Serilog.ServiceBusSink.Tests",
            "ProcessingMachineName": "NODINITE-DEV",
            "ProcessingModuleName": "DOTNETCORE.TESTS",
            "ProcessingModuleType": "DOTNETCORE.TESTPROJECT"
          }
        }
      }
    ]
  }
}
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

Logger log = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

1. Code

var connectionString = "{Your EventHub Connection String";

var settings = new NodiniteLogEventSettings()
{
    LogAgentValueId = 503,
    EndPointDirection = 0,
    EndPointTypeId = 0,
    EndPointUri = "Nodinite.Serilog.EventHubSink.Tests.Serilog",
    EndPointName = "Nodinite.Serilog.EventHubSink.Tests",
    ProcessingUser = "NODINITE",
    ProcessName = "Nodinite.Serilog.EventHubSink.Tests",
    ProcessingMachineName = "NODINITE-DEV",
    ProcessingModuleName = "DOTNETCORE.TESTS",
    ProcessingModuleType = "DOTNETCORE.TESTPROJECT"
};

ILogger log = new LoggerConfiguration()
    .WriteTo.NodiniteEventHubSink(connectionString, settings)
    .CreateLogger();

2. Appsettings.json

{
  "Serilog": {
    "Using": [ "Nodinite.Serilog.EventHubSink" ],
    "WriteTo": [
      {
        "Name": "NodiniteEventHubSink",
        "Args": {
          "ConnectionString": "",
          "Settings": {
            "LogAgentValueId": 503,
            "EndPointName": "Nodinite.Serilog.EventHubSink.Tests",
            "EndPointUri": "Nodinite.Serilog.EventHubSink.Tests.Serilog",
            "EndPointDirection": 0,
            "EndPointTypeId": 0,
            "OriginalMessageTypeName": "Serilog.LogEvent",
            "ProcessingUser": "NODINITE",
            "ProcessName": "Nodinite.Serilog.EventHubSink.Tests",
            "ProcessingMachineName": "NODINITE-DEV",
            "ProcessingModuleName": "DOTNETCORE.TESTS",
            "ProcessingModuleType": "DOTNETCORE.TESTPROJECT"
          }
        }
      }
    ]
  }
}
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

Logger log = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

Logging

log.ForContext("ApplicationInterchangeId", Guid.NewGuid())
   .ForContext("body", "{\"Order\": {...");
log.Information("Order '12' has been imported.");

simple code example

If you want to log the payload (body) then please add it as plain text in the context property ("body")

The provided example logs directly to the Nodinite Log API. You should consider changing the code to log to the Azure EventHub or ServiceBus or any other supported destination to achieve Asynchronous Logging. Please review the Pickup Service for additional information.

Log Event

The sink produces Nodinite Log Events.

The Log Event has three distinct parts:

  1. Event details (also named Additional field values within Nodinite)
  2. Payload (Body, 0 or more)
  3. Context properties (Key/Value)
graph TD subgraph "Log Event" subgraph "1. Details" roED[fal:fa-bolt Event Details
LogDateTime = 2018-05-03 13:37:00+02:00
EndPointName = https://api.nodinite.com/...
MessageType=Invoice
...] end subgraph "2. Payload" ro[fal:fa-envelope Message
Body=base64EncodedMessage] end subgraph "3. Context Properties" roKey[fal:fa-key Key Values
InvoiceNo = 123
CorrelationId=456
...] end end

Additional field values

The following mandatory fields must be set on the Nodinite class either in configuration or with code:

Nodinite Field Example Description
LogAgentValueId 503 Who (Log Agents) sent the data
EndPointName "Nodinite.Serilog.ApiSink.Tests" Name of Endpoint transport
EndPointUri "Nodinite.Serilog.Apisink.Tests.Serilog" URI for Endpoint transport
EndPointDirection 0 Direction for Endpoint transport
EndPointTypeId 0 Type of Endpoint transport

The following properties are optional and can be set on the Nodinite class either in configuration or with code:

Nodinite Field Example Description
ProcessingUser "Nodinite" Log Identity
ProcessName "My customer import process" Name of process
ProcessingMachineName "localhost" Name of server where log event originated
ProcessingModuleName "INT101-HelloHappyCustomers-Application" Name of module
ProcessingModuleType "FileImport" Type of module, exe, dll, service

Context Properties

The following optional coded context properties are mapped if present to the following Nodinite "additional field values":

Context Key Description
body Plain text
OriginalMessageTypeName Name of MessageType, if not set, the default value is Serilog.LogEvent
ApplicationInterchangeId Please re-use if possible a scenario wide id, for example the x-ms-client-tracking-id in Azure

Automatically assigned

The following properties are automatically set internally by the Nodinite SeriLog sink:

Field Description Example
ServiceInstanceActivityId A guid unique for each log event ee2daba2-4807-4ad8-1337-620e2b9c0052
LocalInterchangeId A unique re-used guid set on all logged events within one class instance ff2daba2-4807-4ad8-1337-620e2b9c0053
LogDateTime UTC 2020-05-17T13:37:42.001+01:00
LogText The text to log Hello World
Log Status Code The log status for event See 'Log Status Code translation table' below

Log Status Code translation table

The Nodinite Log Status Codes are translated as described in the table below from the following SeriLog Log Levels:

SeriLog Log Level Nodinite Log Status Code Nodinite Log Status Code example
Debug 0 None log.Debug
Info 0 None log.Information
Verbose 0 None log.Verbose
Error -1 Error log.Error
Fatal -2 Fatal log.Fatal
Warning 1 Warning log.Warning

Next Step

Log Events
JSON Log Event

Logging