Skip to content

Support for logging from .NET Tracing and ETW / Semantic Logging ApplicationBlock to Splunk.

License

Notifications You must be signed in to change notification settings

ThorTech/splunk-library-dotnetlogging

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Splunk Logging for .NET

Version 1.5

Splunk Logging for .NET enables you to configure [HTTP Event Collector] (http://dev.splunk.com/view/event-collector/SP-CAAAE6M), UDP or TCP logging of events to a Splunk Enterprise instance from within your .NET applications, via a .NET TraceListener or a Semantic Logging Application Block (SLAB) event sink.

Each 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
  • Splunk.Logging.SLAB
  • Splunk.Logging.Common

Advice

Splunk Universal Forwarder vs. Splunk UDP Inputs

If you can, it is better to log to files and monitor them with a Splunk Universal Forwarder. This provides you with the features of the Universal Forwarder, and added robustness from having persistent files. However, there are situations where using a Universal Forwarder is not a possibility. In these cases, writing directly to a UDP input is a reasonable approach.

Data cloning

You can use data cloning by providing multiple instances of your UDP handler in your logging configuration, each instance pointing to different indexers.

Load balancing

Rather than trying to reinvent load balancing across your indexers in your log configuration, set up a Splunk Universal Forwarder with a UDP input. Have all your logging sources write to that UDP input, and use the Universal Forwarder's load balancing features to distribute the data from there to a set of indexers.

Get started

The information in this Readme provides steps to get going quickly, but for more in-depth information be sure to visit Splunk Logging for .NET page on Splunk Developer Portal.

Requirements

Here's what you need to use Splunk Logging for .NET:

  • .NET Framework 4.0 or later: Splunk Logging for .NET require at least .NET 4.0.
  • Splunk Enterprise: If you haven't already installed Splunk Enterprise, download it at http://www.splunk.com/download. For more information about installing and running Splunk Enterprise and system requirements, see the Splunk Installation Manual.

If you want to build the libraries and run the test suite, you will also need:

Install

You have several options for installing Splunk Logging for .NET. The most common method is through NuGet. Add the package you want after searching for "splunk" in the Manage NuGet Packages window in Visual Studio.

For more information, and for information about other ways to install Splunk Logging for .NET, see Install Splunk Logging for .NET

Solution layout

The solution is organized into src and test directories. The src directory contains three libraries: Splunk.Logging.TraceListener (which contains .NET trace listeners that log events to Splunk Enterprise over UDP or TCP), Splunk.Logging.SLAB (which contains Semantic Logging Application Block (SLAB) event sinks that log ETW events to Splunk Enterprise over UDP or TCP), and Splunk.Logging.Common (a common library that contains resources required by both logging libraries). The test directory contains a single project, unit-tests.

Examples and unit tests

Splunk Logging for .NET include full unit tests which run using xunit.

Example code

Add logging to Splunk via a TraceListener

Below is a snippet showing creating a TraceSource and then attaching a UdpTraceListener (or TcpTraceListener) configured to talk to localhost on port 10000. Next an event is generated which is sent to Splunk.

//setup
var traceSource = new TraceSource("TestLogger");
traceSource.Listeners.Remove("Default");
traceSource.Switch.Level = SourceLevels.All;
traceSource.Listeners.Add(new UdpTraceListener(IPAddress.Loopback, 10000));
// or, for TCP:
// traceSource.Listeners.Add(new TcpTraceListener(IPAddress.Loopback, 10000, new ExponentialBackoffTcpReconnectionPolicy()));

//log an event
traceSource.TraceEvent(TraceEventType.Information, 1, "Test event");

Add logging to Splunk via a SLAB event sink

Below is a snippet showing how to create an ObservableEventListener and then subscribe to events with a UdpEventSink (or TcpEventSink) configured to talk to localhost on port 10000. Next a SimpleEventSource is instantiated and a test event is generated.

//setup
var listener = new ObservableEventListener();
listener.Subscribe(new UdpEventSink(IPAddress.Loopback, 10000));
// or, for TCP:
// listener.Subscribe(new TcpEventSink(IPAddress.Loopback, 10000, new ExponentialBackoffReconnectionPolicy()));

var eventSource = new SimpleEventSource();
listener.EnableEvents(eventSource, EventLevel.LogAlways, Keywords.All);

//log an event
eventSource.Message("Test event");

[EventSource(Name = "TestEventSource")]
public class SimpleEventSource : EventSource
{
    public class Keywords { }
    public class Tasks { }

    [Event(1, Message = "{0}", Level = EventLevel.Error)]
    internal void Message(string message)
    {
        this.WriteEvent(1, message);
    }
}

In both the example above, the TCP listeners took an extra argument, which specifies how they should handle dropped TCP sessions. You can specify a custom reconnection policy by defining an implementation of Splunk.Logging.ITcpReconnectionPolicy and passing it to the constructors of the TcpTraceListener or TcpEventSink classes. If you have no particular policy in mind, use the ExponentialBackoffReconnectionPolicy provided by the library, which retries after increasingly long intervals, starting from a delay of one second and going to a plateau of ten minutes.

TcpConnectionPolicy has a single method, Connect, which tries to establish a connection or throws a TcpReconnectFailure if it cannot do so acceptably. Here is annotated source code of the default, exponential backoff policy:

public class ExponentialBackoffTcpReconnectionPolicy : ITcpReconnectionPolicy
{
    private int ceiling = 10 * 60; // 10 minutes in seconds

	// The arguments are:
	//
	//     connect - a function that attempts a TCP connection given a host, port number.
	//     host - the host to connect to
	//     port - the port to connect on
	//     cancellationToken - used by TcpTraceListener and TcpEventSink to cancel this method
	//         when they are disposed.
    public Socket Connect(Func<IPAddress, int, Socket> connect, IPAddress host, int port, CancellationToken cancellationToken)
    {
        int delay = 1; // in seconds
        while (!cancellationToken.IsCancellationRequested)
        {
            try
            {
                return connect(host, port);
            }
            catch (SocketException) { }

            // If this is cancelled via the cancellationToken instead of
            // completing its delay, the next while-loop test will fail,
            // the loop will terminate, and the method will return null
            // with no additional connection attempts.
            Task.Delay(delay * 1000, cancellationToken).Wait();
            // The nth delay is min(10 minutes, 2^n - 1 seconds).
            delay = Math.Min((delay + 1) * 2 - 1, ceiling);
        }

        // cancellationToken has been cancelled.
        return null;
    }
}

Another, simpler policy, would be trying to reconnect once, and then failing:

class TryOnceTcpConnectionPolicy : ITcpReconnectionPolicy
{
    public Socket Connect(Func<System.Net.IPAddress, int, Socket> connect, 
            System.Net.IPAddress host, int port, 
            System.Threading.CancellationToken cancellationToken)
    {
        try
        {
            if (cancellationToken.IsCancellationRequested)
                return null;
            return connect(host, port);
        }
        catch (SocketException e)
        {
            throw new TcpReconnectFailureException("Reconnect failed: " + e.Message);
        }
    }
}

Handling errors from the TCP logging system

It can be difficult to diagnose connection problems in TCP logging without seeing the exceptions that are actually thrown. The exceptions thrown during connection attempts and by the reconnection policy are available by adding a handler to TcpEventSink or TcpTraceListener.

Both TcpEventSink and TcpTraceListener have a method that takes an action to be executed on each exception thrown in the logging system:

public void AddLoggingFailureHandler(Action<Exception> handler)

For example, to write them to a local console, you would write:

TcpTraceListener listener = ...;
listener.AddLoggingFailureHandler((ex) => {
    Console.WriteLine("{0}", ex);
});

Sending events to HTTP Event Collector

This feature requires Splunk 6.3+.

After enabling HTTP Event Collector and creating an application token sending events is very simple:

// TraceListener
var trace = new TraceSource("demo-logger");
trace.Listeners.Add(new HttpEventCollectorTraceListener(
    uri: new Uri("https::/splunk-server:8088"),
    token: "<token-guid>"));
trace.TraceEvent(TraceEventType.Information, 0, "hello world");

// SLAB
var listener = new ObservableEventListener();
var sink = new HttpEventCollectorEventSink(
    uri: new Uri("https://splunk-server:8088"), 
    token: "token-guid",
    formatter: new AppEventFormatter());
listener.Subscribe(sink);
var eventSource = new AppEventSource();
listener.EnableEvents(eventSource, EventLevel.LogAlways, Keywords.All);
eventSource.Message("hello world");

Error Handling

A user application code can register an error handler that is invoked when HTTP Event Collector isn't able to send data.

listener.AddLoggingFailureHandler((sender, HttpEventCollectorException e) =>
{
    // handle the error
});

Changelog

The CHANGELOG.md file in the root of the repository contains a description of changes for each version of Splunk Logging for .NET. You can also find it online at

https://github.com/splunk/splunk-library-dotnetlogging/blob/master/CHANGELOG.md

Branches

The master branch always represents a stable and released version of the Splunk Library for .NET Logging. You can read more about our branching model on our Wiki at

https://github.com/splunk/splunk-sdk-python/wiki/Branching-Model

Documentation and resources

If you need to know more:

Community

Stay connected with other developers building on Splunk.

Email [email protected]
Issues https://github.com/splunk/splunk-library-dotnetlogging
Answers http://splunk-base.splunk.com/tags/csharp/
Blog http://blogs.splunk.com/dev/
Twitter @splunkdev

Contributions

If you want to make a code contribution, go to the Open Source page for more information.

Support

This product is currently in development and officially unsupported. We will be triaging any issues filed by the community however and addressing them as appropriate. Please file issues for any problems that you encounter.

Contact us

You can reach the Dev Platform team at [email protected].

License

Splunk Logging for .NET is licensed under the Apache License 2.0. Details can be found in the LICENSE file.

About

Support for logging from .NET Tracing and ETW / Semantic Logging ApplicationBlock to Splunk.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%