Skip to content

Latest commit

 

History

History
245 lines (181 loc) · 9.87 KB

File metadata and controls

245 lines (181 loc) · 9.87 KB

New Relic .NET Logging Extensions for Serilog

The .NET Extensions for Serilog will add contextual information from the .NET Agent to Application Log Messages, output them in the New Relic's expected JSON format, and send them to the New Relic Logging endpoint.

Minimum Requirements

Recommended Components

Overview

When application code logs a message, Serilog creates a LogEvent. Serilog can add additional information to Log Events using Enrichers. Sinks and Formatters format and output Log Events for downstream consumption and/or viewing. The New Relic Log Forwarder monitors an output folder and incrementally sends log information to New Relic.

Architecture Diagram

New Relic Enricher

The NewRelicEnricher adds contextual information from the .NET Agent (using the API) to the Log Events generated by the application. This contextual information, known as Linking Metadata, is used by New Relic to link log messages to the transactions and spans from which they were created.

New Relic Formatter and Sink

The NewRelicFormatter translates enriched Log Events into the JSON format expected by New Relic. A Sink instructs Serilog to output the JSON to a file in the location that the Log Forwarder expects.

New Relic Log Forwarder

The Log Forwarder monitors an output folder and incrementally sends New Relic formatted Log information to the New Relic Logging Endpoint. There are many log-forwarders available. For our examples, we will use fluentd.

Configuration

Configuring the New Relic Enricher

Configure the NewRelicEnricher by adding the NewRelicEnricher to the Serilog configuration as described below. There are no configuration options for the NewRelicEnricher.

    var loggerConfig = new LoggerConfiguration()
        
    loggerConfig
        .Enrich.WithNewRelicLogsInContext();

It is common to have multiple enrichers adding information to log messages. In this example, two additional enrichers append Thread Id and Name to the Log Events generated by the application code. When adding additional enrichers, it is recommended to configure the NewRelicEnricher as the last enricher.

    var loggerConfig = new LoggerConfiguration()
        
    loggerConfig
        .Enrich.WithThreadName()
        .Enrich.WithThreadId()    
        .Enrich.WithNewRelicLogsInContext();
        

Configuring the New Relic Formatter and Serilog Output Sink

Below is an example configuration using a basic Serilog File Output Sink with the NewRelicFormatter.

    var loggerConfig = new LoggerConfiguration()
        
    loggerConfig
        .Enrich.WithThreadName()
        .Enrich.WithThreadId()    
        .Enrich.WithNewRelicLogsInContext()
        .WriteTo.File(
            formatter: new NewRelicFormatter(), 
            path: @"C:\logs\SerilogExample.log.json");

    var log = loggerConfig.CreateLogger();

Since the JSON files are written to disk, some of these configuration options may be useful in managing the amount of disk space used and/or the performance of the Sink.

  • restrictedToMinimumLevel
  • buffered
  • rollingInterval
  • rollOnFileSizeLimit
  • retainedFileCountLimit

Though not required, using the Serilog Asynchronous Sink Wrapper may help improve the performance by performing formatting and output of log files to a different thread.

Configuring the fluentd Log Forwarder

Based on the Fornatter and Sink Configuration described above, the following Fluentd configuration can be used to send logs to New Relic.

<!--NewRelicLoggingExample.conf-->
<source> 
    @type tail 
    path C:\logs\SerilogExample.log.json
    pos_file C:\logs\SerilogExample.log.json.pos 
    tag logfile.*
 <parse> 
    @type json 
</parse>
</source>
<match **> 
    @type newrelic 
    license_key <YOUR NEW_RELIC_LICENSE_KEY>
    base_uri https://log-api.newrelic.com/log/v1
</match>

Applying Context to Log Events

Automatic Properties

In addition to the linking metadata obtained from the .NET Agent, the NewRelicFormatter automatically adds the following properties, if applicable, to each LogEvent.

  • Timestamp
  • Error Message
  • Error Class
  • Error Stack Trace
  • Message Text
  • Message Template
  • Log Level

Other Common Properties

Other enrichers may be used to provide additional contextual information. For enrichers that provide the following fields, the New Relic Formatter should be configured to identify these properties.

  • Thread Id
  • Thread Name
  • File Name
  • Namespace
  • Class Name
  • Method Name
  • Line Number

In this example configuration, the ThreadId and ThreadName enrichers add the additional properties ThreadId and ThreadName to each LogEvent. Correspondingly, the NewRelicFormatter is configured to identify these fields.

    var loggerConfig = new LoggerConfiguration()
        
    loggerConfig
        .Enrich.WithThreadName()                                                            //Captures the Thread Id and adds it as the "ThreadId" property to the LogEvent
        .Enrich.WithThreadId()                                                              //Captures the Thread Name and adds it as the "ThreadName" property to the LogEvent
        .Enrich.WithNewRelicLogsInContext()
        .WriteTo.File(
            path: @"C:\logs\SerilogExample.log.json",
            formatter: new NewRelicFormatter()
                .WithPropertyMapping("ThreadId", NewRelicLoggingProperty.ThreadId)          //Identifies the "ThreadId" Property on the Log Event as the Thread Id
                .WithPropertyMapping("ThreadName", NewRelicLoggingProperty.ThreadName)      //Identifies the "ThreadName" Property on the Log Event as the Thread Name
        );

    var log = loggerConfig.CreateLogger();

Custom Message Properties

The NewRelicFormatter automatically adds all custom properties to Log Events. These properties are visible in New Relic Logging under the "Message Properties" section. There are two methods of adding custom properties: (1) a custom enricher; or (2) a message template.

For exmple, the following log message template will result in the custom properties of FirstName and nbr

    log.Debug("Hello {FirstName}, you are number {nbr} on my list", "Bob", 32);

File-based Configuration

Configuration of the New Relic extensions for Serilog may be accomplished with file based configuration providers.

AppSettings Based Configuration

The example code below creates a logger based on settings contained in an appSettings.json file.

The following NuGet Packages are required:

Sample Code
var builder = new ConfigurationBuilder()
        .AddJsonFile("appsettings.json");
        
var configuration = builder.Build();

var logger = new LoggerConfiguration()
        .ReadFrom.Configuration(configuration)
        .CreateLogger();
Sample AppSettings.Json
{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console","Serilog.Sinks.File","NewRelic.LogEnrichers.Serilog" ],
    "MinimumLevel": "Debug",
    "Enrich": [ "WithNewRelicLogsInContext" ],
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "C:\\Logs\\SerilogExample.log.json",
          "formatter": "NewRelic.LogEnrichers.Serilog.NewRelicFormatter, NewRelic.LogEnrichers.Serilog"
          }
      }
    ],
    
    "Properties": {
      "Application": "NewRelic Logging Serilog Example"
    }
  }
}

.Config file Based Configuration

The example code below creates a logger based on settings contained in a .config file.

The following NuGet Package is required:

var logger = new LoggerConfiguration()
    .ReadFrom.AppSettings()
    .CreateLogger();
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="serilog:using:NewRelic" value="NewRelic.LogEnrichers.Serilog" />
    <add key="serilog:using:File" value="Serilog.Sinks.File" />
    <!--Add other enrichers here-->
    <add key="serilog:enrich:WithNewRelicLogsInContext" />
    <add key="serilog:write-to:File.path" value="C:\logs\SerilogExample.log.json" />
    <add key="serilog:write-to:File.formatter" value="NewRelic.LogEnrichers.Serilog.NewRelicFormatter, NewRelic.LogEnrichers.Serilog" />
  </appSettings>