Windows IoT Core: Logging to Syslog server

Syslog servers are most popular in Linux world. These servers accept logs from different clients and are not opened to external network. There are also Syslog servers available for Windows. This blog post shows how to write messages to Syslog server from WIndows 10 IoT Core background application.

Syslog server

Syslog server is logging server. Usually it is separate box or virtual machine that is configured to accept log messages and not accept any users from external network. If some system or device gets hacked then usually Syslog server is not accessible and logs are there to analyze what happened.

syslog-server
Example of network with Syslog server.
Copyright belongs to Network Management Software

For more information about Syslog server follow these links:

ILogger interface

In my TemperatureStation IoT solution I use ILogger interface to support multiple logger implementations.


internal interface ILogger
{
    void Debug(string message);
    void Info(string message);
    void Warn(string message);
    void Error(string message);
    void Critical(string message);
}

Now let’s get to logger implementation.

Adding support for syslog server

To write logger for Syslog server we need enum with log levels. These doesn’t match completely with ones used in .NET based logging solutions.


public enum SyslogLogLevel
{
    Emergency,
    Alert,
    Critical,
    Error,
    Warn,
    Notice,
    Info,
    Debug
}

And here is the logger class for Syslog. It’s simple and primitive but it works. The most important method in this class is Send() method. All other methods are just shortcuts for it that come in with ILogger interface.


internal class SyslogLogger : ILogger
{
    private const string SyslogClientName = "RPI-001";
    private const string SyslogHost = "192.168.210.2";
    private const int SyslogPort = 514;
    private const int SyslogFacility = 16;
 
    public void Critical(string message)
    {
        Send(SyslogLogLevel.Critical, message);
    }
 
    public void Debug(string message)
    {
        Send(SyslogLogLevel.Debug, message);
    }
 
    public void Error(string message)
    {
        Send(SyslogLogLevel.Error, message);
    }
 
    public void Info(string message)
    {
        Send(SyslogLogLevel.Info, message);
    }
 
    public void Warn(string message)
    {
        Send(SyslogLogLevel.Warn, message);
    }
 
    internal static void Send(SyslogLogLevel logLevel, string message)
    {
        if (string.IsNullOrWhiteSpace(SyslogHost) || SyslogPort <= 0)
        {
            return;
        }
 
        var hostName = Dns.GetHostName();
        var level = SyslogFacility * 8 + (int)logLevel;
        var logMessage = string.Format("<{0}>{1} {2}", level, hostName, message);
        var bytes = Encoding.UTF8.GetBytes(logMessage);
 
        using (var client = new UdpClient())
        {
            client.SendAsync(bytes, bytes.Length, SyslogHost, SyslogPort)
                  .Wait();
        }
    }
}

Here is the fragment of code that shows how loggers based on ILogger interface are used in my TemperatureStation solution.


_logger.Info("Timer callback: reading and reporting sensors");
 
try
{
    var readings = _sensorsClient.ReadSensors();
    await _reportingClient.ReportReadings(readings);
 
    _logger.Info(readings.ToString());
}
catch (Exception ex)
{
    _logger.Critical(ex.ToString());
}
 
_logger.Info("Timer callback: reading and reporting is done");

And here is how Visual Syslog Server monitor is displaying messages sent from my RaspberryPI.

Visual Syslog Server

NB! You can use the same code also with Linux based Syslog servers as they share the same protocol.

Wrapping up

Connecting good things from two worlds may work out as perfect solution. Here we took Syslog server that is popular in Linux world and used it as logging solution for IoT service running on Windows IoT Core and RaspberryPI. We wrote some lines of code to make it work and we were able to send log messages to Syslog server.



See also

Leave a Reply

Your email address will not be published. Required fields are marked *