A Low-Overhead SysLog Message Sender Class
by Peter A. Bromberg, Ph.D.

Peter Bromberg

Most developers that come from the UNIX /BSD space are familiar with (and usually swear by) SysLog. In short, SysLog is a compact UDP-based informational messaging protocol that typically talks on port 514. There are various "Service" (aka Windows Service) and non-service client applications to read and display these messages. Probably the best known and certainly most popular is the freeware Kiwi SysLog Daemon.

If you develop and work with any type of product that uses IP-based networking or messaging, you will find the need for a real-time messaging protocol that will enable your application to send messages of varying debug levels and logging priorities so that users and testers can see in real time what your app is doing and where in the app it is happening. With a properly constructed config file, all you need to specify are the SysLog IP address and perhaps a "logging level" - simple, debug, verbose, whatever you want - to specify how much of this messaging your app actually does while it is running. The nice thing about UDP is that it is lightweight and connectionless, which means that you app doesn't get slowed down very much by sending out these messages.



You can read more about SysLog by searching our newly indexed IETF RFC database here.

What I present here is a very simple, very lightweight SysLog Sender class that will send out syslog messages, and is easy to "drop in" to any project. It only has one static method, "Send", making it elegantly simple to use. If you don't specify an IP address by only sending an empty string in the Send method, my class assumes you mean "Send this to the local machine" and that's exactly what it does.

First, let's look at the Sender Class, which is extremely simple:

using System;
using System.Collections;
using System.Net.Sockets;
using System.Text;
using System.Net;

namespace Utils.SysLogSender
{ 
 public class Sender
 {
  public  enum PriorityType
  {
   Emergency,
   Alert,
   Critical,
   Error,
   Warning,
   Notice,
   Informational,
   Debug
  }
  private static UdpClient udp;
  private static ASCIIEncoding ascii= new ASCIIEncoding();
  private static string machine= System.Net.Dns.GetHostName() + " ";
  private static string sysLogIpAddress ;
  private  Sender()
  {
     Sender.sysLogIpAddress=Dns.Resolve(Dns.GetHostName()).AddressList[0].ToString();
  }
  public static string SysLogIpAddress
  {
   get
   {
    return sysLogIpAddress;
   }
   
   set
   {
    sysLogIpAddress=value;
   }
  }

  public static void Send(string ipAddress,  string body)
  {  
   if(ipAddress==null || (ipAddress.Length<5)) ipAddress=Dns.Resolve(Dns.GetHostName()).AddressList[0].ToString();
    Send(ipAddress,Sender.PriorityType.Warning,DateTime.Now,body);
  }

  public static void Send(string ipAddress, PriorityType priority, DateTime time, string body)
  { 
   if(ipAddress==null || (ipAddress.Length<5)) ipAddress=Dns.Resolve(Dns.GetHostName()).AddressList[0].ToString();
   udp = new UdpClient(ipAddress, 514);
   byte[] rawMsg;
   string[] strParams = { priority.ToString()+": ", time.ToString("MMM dd HH:mm:ss "),
          machine,
          body };
   rawMsg = ascii.GetBytes(string.Concat(strParams));
   udp.Send(rawMsg, rawMsg.Length);
   udp.Close();
   udp=null;    
  }
 }
}

As can be seen above, there is a PriorityType enumeration which corresponds to the RFC for SysLog messages, and two overloads of a static Send method.

To illustrate how this can be used, I've added a Windows Form test harness, whose main code looks like so:

private void button1_Click(object sender, System.EventArgs e)
  {
   if(this.cboPriority.SelectedIndex==-1)
    
   {
    MessageBox.Show("please choose a messagepriority, Captain!");
    this.cboPriority.Focus();
   }
   Utils.SysLogSender.Sender.PriorityType t = (Utils.SysLogSender.Sender.PriorityType)this.cboPriority.SelectedIndex;
   Utils.SysLogSender.Sender.Send("",t,DateTime.Now,this.txtMessage.Text);
   this.txtMessage.Text="";
  }

This one line of code:

Utils.SysLogSender.Sender.Send("",t,DateTime.Now,this.txtMessage.Text);

is really all you need. The result you will see if this is run while the Kiwi client is on the desktop will look like the following two images:

This little arrangement has been invaluable to me in checking out what's going on with my apps in real time. Feel free to modify the code in the downloadable solution below.

N.B. Reader John Hirbour, who obviously knows quite a bit about Syslog, and whose posts you can view below, has kindly posted an enhanced version of this code that includes the Priority msg bits that many Syslog servers / clients understand. You can view his code here.

Download the Visual Studio.NET Solution that accompanies this article

 



Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.
Article Discussion: