Overview of Splunk logging for .NET

Welcome to Splunk® logging for .NET!

Splunk logging for .NET enables you to configure logging to HTTP Event Collector in Splunk Enterprise 6.3 and later or Splunk Cloud, as well as UDP or TCP logging of events from within your .NET applications, via a .NET TraceListener or a SLAB event sink.

Choosing a logging destination

HTTP Event Collector is ideal if you want to log data from your .NET application in any of the following scenarios:

  • You want to send events directly to Splunk Enterprise rather than requiring writing to disk and installing a forwarder.
  • You want to send data securely to Splunk Enterprise, with the option of an HTTPS connection and a unique token.
  • You expect to send data at a high volume and frequency.

For more information about HTTP Event Collector, see Introduction to HTTP Event Collector.

Alternately, you can log to a TCP or UDP input either directly or by first logging to a file and then using a Splunk Universal Forwarder to monitor the file and send data any time the file is updated. Doing so gives you the features of the Universal Forwarder, plus added robustness from having persistent files.

Architecture

Each logging library consists of several extensions for existing .NET logging frameworks. Specifically, there are two libraries available, along with a third common library that is required by both main libraries:

  • Splunk.Logging.TraceListener contains .NET trace listeners that log events to Splunk Enterprise over UDP or TCP. Popular logging frameworks support appending to the trace infrastructure, including Apache log4net, NLog, and Microsoft Enterprise Library. .NET trace listeners are cross-platform. The library defines the following trace listeners:
    • HttpEventCollectorTraceListener
    • UdpTraceListener
    • TcpTraceListener
  • Splunk.Logging.SLAB contains event sinks, which are Semantic Logging Application Block (SLAB) sinks that log Event Tracing for Windows (ETW) events to Splunk Enterprise over UDP or TCP. SLAB sinks are for Windows only. The library defines the following sinks:
    • HttpEventCollectorSink
    • UdpEventSink
    • TcpEventSink
  • Splunk.Logging.Common is a common library that contains resources required by both logging libraries. You must include the Splunk.Logging.Common library when you're using either of the other two libraries. The common library defines:
    • Policy for how TCP logging should behave (reconnect intervals, when to throw an exception) when there is a socket error.
    • A TCP socket writer that maintains a queue of strings to be sent.

HttpEventCollectorTraceListener

The HttpEventCollectorTraceListener class is a subclass of TraceListener. HttpEventCollectorTraceListener implementations must implement the Write, WriteLine, and Close methods. The logging infrastructure creates a log entry with successive calls to Write, followed by a call to WriteLine at the end of the event. When the logging is shut down, the infrastructure calls Close on each of the configured TraceListener objects.

public class HttpEventCollectorTraceListener : TraceListener
    {
        /// HttpEventCollectorTraceListener constructor.
        ///
        /// "uri": Splunk server uri, for example https://localhost:8088.
        /// "token": HTTP event collector authorization token.
        /// "metadata": Logger metadata.
        /// "sendMode": Send mode of the events.
        /// "batchInterval": Batch interval in milliseconds.
        /// "batchSizeBytes": Batch max size.
        /// "batchSizeCount": MNax number of individual events in batch.
        /// "middleware": HTTP client middleware. This allows to plug an HttpClient 
        ///     handler that intercepts logging HTTP traffic.
        public HttpEventCollectorTraceListener(
            Uri uri, string token,
            HttpEventCollectorEventInfo.Metadata metadata = null,
            HttpEventCollectorSender.SendMode sendMode = HttpEventCollectorSender.SendMode.Sequential,
            int batchInterval = HttpEventCollectorSender.DefaultBatchInterval,
            int batchSizeBytes = HttpEventCollectorSender.DefaultBatchSize,
            int batchSizeCount = HttpEventCollectorSender.DefaultBatchCount,
            HttpEventCollectorSender.HttpEventCollectorMiddleware middleware = null)

        /// HttpEventCollectorTraceListener constructor. Instantiates
        /// HttpEventCollectorTraceListener when retriesOnError parameter is specified.
        /// 
        /// "uri": Splunk server uri, for example https://localhost:8088.
        /// "token": HTTP event collector authorization token.
        /// "retriesOnError": Number of retries when network problem is detected
        /// "metadata": Logger metadata.
        /// "sendMode": Send mode of the events.
        /// "batchInterval": Batch interval in milliseconds.
        /// "batchSizeBytes": Batch max size.
        /// "batchSizeCount": MNax number of individual events in batch.
        public HttpEventCollectorTraceListener(
            Uri uri, string token,
            int retriesOnError,
            HttpEventCollectorEventInfo.Metadata metadata = null,
            HttpEventCollectorSender.SendMode sendMode = HttpEventCollectorSender.SendMode.Sequential,
            int batchInterval = HttpEventCollectorSender.DefaultBatchInterval,
            int batchSizeBytes = HttpEventCollectorSender.DefaultBatchSize,
            int batchSizeCount = HttpEventCollectorSender.DefaultBatchCount)
            : this(uri, token, metadata, 
                   sendMode,
                   batchInterval, batchSizeBytes, batchSizeCount,
                   (new HttpEventCollectorResendMiddleware(retriesOnError)).Plugin)

        /// Add a handler to be invoked when some problem is detected during the 
        /// operation of HTTP event collector and it cannot be fixed by resending the data.
        /// 
        /// "handler": A function to handle the exception.
        public void AddLoggingFailureHandler(Action<HttpEventCollectorException> handler)

        #region TraceListener output callbacks
        
        public override void Write(string message) 
        public override void WriteLine(string message) 

        public override void TraceData(
            TraceEventCache eventCache, 
            string source, 
            TraceEventType eventType, 
            int id, 
            params object[] data)

        public override void TraceEvent(
            TraceEventCache eventCache, 
            string source, 
            TraceEventType eventType, 
            int id)

        public override void TraceEvent(
            TraceEventCache eventCache, 
            string source, 
            TraceEventType eventType, 
            int id, 
            string message)

        public override void TraceEvent(
            TraceEventCache eventCache, 
            string source, 
            TraceEventType eventType, 
            int id, 
            string format, 
            params object[] args)

        public override void TraceTransfer(
            TraceEventCache eventCache, 
            string source, 
            int id, 
            string message, 
            Guid relatedActivityId)

        /// Flush all events.
        public Task FlushAsync()

        public override void Close()
    }

UdpTraceListener and TcpTraceListener

The UdpTraceListener and TcpTraceListener classes are subclasses of TraceListener. TraceListener implementations must implement the Write, WriteLine, and Close methods. The logging infrastructure creates a log entry with successive calls to Write, followed by a call to WriteLine at the end of the event. When the logging is shut down, the infrastructure calls Close on each of the configured TraceListener objects.

UdpTraceListener has the following form:

class UdpTraceListener : TraceListener
{
    // Constructors that specify the host:port to write events to. A host passed as a
    // string will be DNS resolved to an IPAddress.
    public UdpTraceListener(IPAddress host, int port)
    public UdpTraceListener(string host, int port)
 
    // Methods to write chunks of events to this TraceListener. WriteLine is called
    // for the last chunk of an event, Write for incremental chunks of an event.
    public void Write(string message)
    public void WriteLine(string message)
 
    // Called when TraceListeners are shut down by the logging infrastructure.
    // Calls TraceListener.Close(), and then cleans up the UDP socket.
    public void Close()
}

TcpTraceListener has the following form:

class TcpTraceListener : TraceListener
{
    // Constructors that specify the host:port to write events to.
    public TcpTraceListener(IPAddress host, int port, 
            TcpConnectionPolicy policy = null, 
            int maxQueueSize = 10000)

    // Methods to write chunks of events to this TraceListener. WriteLine is called
    // for the last chunk of an event, Write for incremental chunks of an event.
    public void Write(string message)
    public void WriteLine(string message)

    // Called when TraceListeners are shut down by the logging infrastructure.
    // Calls TraceListener.Close(), and then cleans up the TCP socket.
    public void Close()
}

For an example, see Add logging using a .NET trace listener.

UdpEventSink and TcpEventSink

The Semantic Logging Application Block (SLAB) is part of the Microsoft Enterprise Library. Splunk logging for .NET implements Observer<EventEntry>. The logging library's implementations of Observer<EventEntry> are called UdpEventSink and TcpEventSink, both of which take EventEntry objects, convert them to text, and write them to a UDP or TCP port to be logged to Splunk Enterprise. The OnCompleted and OnError methods of UdpEventSink or TcpEventSink clean up the resources used by the event sink. The OnNext method serializes and writes the event.

UdpEventSink has the following form:

class UdpEventSink : IObserver<EventEntry>
{
    // Open a logger to host:port (or a socket) and optionally specify a 
    // formatter. The default format is: 
    // {timestamp} EventId={...} EventName={...} Level={...} "FormattedMessage={...}" 
    public UdpEventSink(ISocket socket, IEventTextFormatter formatter = null)
    public UdpEventSink(IPAddress host, int port, IEventTextFormatter formatter = null)
 
    // Write value to a UDP port.
    public void OnNext(EventEntry value)
 
    // The stream has ended, either correctly or with an error. Either way,
    // dispose of all the resources and clean up.
    public void OnCompleted()
    public void OnError(Exception error)
}

TcpEventSink has the following form:

class TcpEventSink : IObserver<EventEntry>
{
    // Open a logger to host:port and optionally specify a formatter. The default 
    // format is: 
    // {timestamp} EventId={...} EventName={...} Level={...} "FormattedMessage={...}" 
    // A host passed as a string will be DNS resolved to an IPAddress.
    public TcpEventSink(IPAddress host, int port, IEventTextFormatter formatter = null,
        TcpConnectionPolicy policy = null, int maxQueueSize = 10000)
    public TcpEventSink(string host, int port, IEventTextFormatter formatter = null,
        TcpConnectionPolicy policy = null, int maxQueueSize = 10000)

    // Write value to a TCP port.
    public void OnNext(EventEntry value)

    // The stream has ended, either correctly or with an error. Either way,
    // dispose of all the resources and clean up.
    public void OnCompleted()
    public void OnError(Exception error)
}

For an example, see Add logging using a SLAB sink.