Makale Özeti

Makale konusu Syslog protokolü için mesaj gönderiminde kullanılacak bir araç olarak Syslog mesaj göndericisi yazmayı öğrenmek.

Makale

Öncelikle Merhabalar;
            Bugüne kadar vakit buldukça yazdığım ingilizce makaleleri artık türkçe olarakta yayınlamaya karar verdim; bu karar doğrultusunda yazdığım ilk makalemi sizlere sunmaktan gayet mutluyum umarım beğenirsiniz.

SysLog Protokolü ve SysLogSender Uygulaması Örneği
Mehmet Akif ÇAKAR; 2006, v1.0

Gerekli Ek Bileşenler :
Örnek Syslog Sunucu Programı : Kiwi SysLog Server Daemon

            Makale konusu Syslog protokolü için mesaj gönderiminde kullanılacak bir araç olarak Syslog mesaj göndericisi yazmayı öğrenmek. Bunu için öncelikle bilmeyen arkadaşlar için SysLog protokolünü tanıtalım.

SysLog İletişim Standardı :
            Syslog standart olarak UDP üzerinden 514 nolu porttan haberleşmeyi sağlayan bir protokoldür. UDP üzerinden yapılan haberleşmede veri kaybı olabileceğinden daha sonraları TCP üzerinden 1468 nolu portu kullanarak haberleşmede sağlanmıştır. Bu port numaralarını SysLog serverlerden değiştirebilmemiz mümkündür fakat tüm sistemlerce standar kabul edilen bilgilerin bunlar olduğunu bilmemiz şu anda yeterli.

SysLog Mesajlaşma Sistemi :
            Syslog mesajları normal text mesajının önüne mesaj başlık (header) bilgisiyle gönderilir. Bu başlık bilgisi temelde 8 seviyeye ayrılmıştır.

Bu seviyeler önem sırasına göre :

  • 0 = Emergency
  • 1 = Alert
  • 2 = Critical
  • 3 = Error
  • 4 = Warning
  • 5 = Notice
  • 6 = Informational
  • 7 = Debug

            Başlık bilgisi taşımayan bir mesaj varsayılan olarak en önemsiz derece olan “Debug” değerini alır. Mesaj başlıkları seviyelerin yanında birde kendilerine ayrılan servis alanlarını kullanırlar.

Bu servis alanları sırasıyla :

  • 0 = Kernel mesajları
  • 1 = Kullanıcı-Seviye Mesajları
  • 2 = Mail sistemi
  • 3 = Sistem  Mesajları
  • 4 = Güvenlik/Tanımlama Mesajları
  • 5 = Syslog sunucularına ayrılmış alan
  • 6 = Çizgi yazıcı alt sistemi mesajları
  • 7 = Ağ haberleri alt sistemi mesajları
  • 8 = UUCP alt sistemi mesajları
  • 9 = Saat mesajları
  • 10 = Güvenlik/Tanımlama Mesajları
  • 11 = FTP mesajları
  • 12 = NTP Mesajları
  • 13 = Geri izleme log mesajları
  • 14 = Alarm log mesajları
  • 15 = Saat mesajları
  • 16, 17, 18, 19, 20, 21, 22, 23  = yerel kullanım için ayrılan servis alanları.

            Temel sıralamayı öğrendikten sonra mesajın başlık bilgisinin hesaplanmasına gelirsek;
Başlık Değeri = Servis Alan Değeri * 8 + Seviye Değeri şeklindedir. Yani mail sisteminden alarm mesajı atmak için gerekli olan başlık değerimiz (2 * 8 + 1) 17 olacaktır. Dolayısıyla başlık değerimizin alabileceği minimum değer 0, maximum değer de (23 * 8 + 7) 191 olacaktır.

Not : Ek olarak başlık bilgileri mesajın önünde “<BaşlıkNumarası>” şeklinde eklenir.

 

            Bu kadar syslog bilgisinin ardından kodlamaya geçelim, kodumuzu standartlara dayalı olarak geliştirelim. (Not kodda niteliklerin açıklama alanlarını ingilizce olarak bıraktım. .Net geliştiriciler olarak pek yabancı kaldığımızı düşünmediğimden türkçeye çevirme gereği duymadım.)

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

namespace SBB.Utilities.SysLog
{
    public class SysLogSender
    {
        #region Private - Public Declerations

        private UdpClient udp;
        private string destinationIpAddress;
        private SysLogMessageFormat messageFormat = SysLogMessageFormat.BodyOnly;
        private int destinationPort = 514, serviceAreaCode = 0;
        private Encoding messageEncoding = Encoding.ASCII;

        /// <summary>
        /// Gets or sets syslog protocol facility code.
        /// </summary>
        public int ServiceAreaCode
        {
            set
            {
                if (value > -1 && value < 24)
                    service AreaCode = value;
                else
                  &nb sp; throw new ArgumentOutOfRangeException();
            }
            get
            {
                return serviceAreaCode;
            }
        }

        /// <summary>
        /// Gets or sets message encoding algorithm.
        /// </summary>
        public Encoding MessageEncoding
        {
            set
            {
                messageEncoding = value;
            }
            get
            {
                return messageEncoding;
            }
        }

        /// <summary>
        /// Gets or sets destination syslog port.
        /// </summary>
        public int DestinationPort
        {
            set
            {
                destinationPort = value;
            }
            get
            {
                return destinationPort;
            }
        }

        /// <summary>
        /// Gets or sets defined syslog message format
        /// </summary>
        public SysLogMessageFormat MessageFormat
        {
            get
            {
                return messageFormat;
            }
            set
            {
                messageFormat = value;
            }
        }

        /// <summary>
        /// Gets or sets syslog receiver(listener) ip address.
        /// </summary>
        public string DestinationIpAddress
        {
            get
            {
                return destinationIpAddress;
            }
            set
            {
                destinationIpAddress = value;
            }
        }

        #endregion

        #region Enumerators

        /// <summary>
        /// Provides syslog standart message priority type.
        /// </summary>
        public enum PriorityType
        {
            Alert = 1,
            Critical = 2,
            Debug = 7,
            Emergency = 0,
            Error = 3,
            Informational = 6,
            Notice = 5,
            Warning = 4
        }

        /// <summary>
        /// Provides syslog message sending format
        /// </summary>
        public enum SysLogMessageFormat
        {
            /// <summary>
            /// Sends only message body
            /// </summary>
            BodyOnly,

            /// <summary>
            /// Sends time and machine name with body message
            /// </summary>
            TimeMachineBody
        }
        #endregion

        #region Public Methods

        public void Send(string messageBody)
        {
            Send(null, messageBody);
        }

        public void Send(string ipAddress, string messageBody)
        {
            Send(ipAddress, PriorityType.Warning, DateTime.Now, messageBody);
        }

        public void Send(PriorityType priority, string messageBody)
        {
            Send(null, priority, DateTime.Now, messageBody);
        }

        public void Send(string ipAddress, PriorityType priority, DateTime time, string messageBody)
        {
            if (String.IsNullOrEmpty(ipAddress) || (ipAddress.Length < 5))
            {
                if (String.IsNullOrEmpty(DestinationIpAddress))
                  &nb sp; DestinationIpAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();
                ipAddress = DestinationIpAddress;
            }
            else
                destinationIpAddress = ipAddress;

            // Syslog standardı olarak udp cilent kullanıyoruz makalenin ileriki sürümünde tcp desteğide eklenebilir.
            udp = new UdpClient(ipAddress, destinationPort);
            try
            {
                byte[] rawMsg = null;
                string[] strParams = null;
                // Söylediğimiz başlık bilgisi bu satırda hesaplanıyor.
                string priorityHeader = String.Format("<{0}>", ServiceAreaCode * 8 + priority.GetHashCode());
                switch (messageFormat)
                {
                    case SysLogMessageFormat.BodyOnly:
                  &nb sp;     strParams = new string[] { priorityHeader, messageBody };
                  &nb sp;     break;
                  &nb sp; case SysLogMessageFormat.TimeMachineBody:
                  &nb sp;     strParams = new string[] { priorityHeader, time.ToString("MMM dd HH:mm:ss"), System.Net.Dns.GetHostName(), messageBody };
                  &nb sp;     break;
                }
                rawMsg = MessageEncoding.GetBytes(String.Concat(strParams));
                udp.Send(rawMsg, rawMsg.Length);
            }
            catch
            {
                throw;
            }
            finally
            {
                udp.Close();
                udp = null;
            }
        }

        #endregion
    }
}

            Görüldüğü gibi kodda kullanıcının değiştirmesine imkan tanınabilecek alanları niteliklere çevirdim. (Encoding, port, mesaj formatı vs..) buraya UDP veya TCP seçeneğide property olarak eklenebilir. Veya ihtiyaçlara göre daha da güzelleştirilebilir. (Bunu makalenin ileriki bir sürümünde de gerçekleştirebiliriz.)

SysLog Sunucu Örneği :
            Kodu denemek için Kiwi SysLog Server Daemon programını önerebilirim. Programı açtığımızda alttaki şekilde bir ekranla karşılaşırız.
Şekil 1-A

Örnek Kullanım :
            Kodumuzun nasıl çalıştığına bir örnek kod vermemiz gerekirse :

protected void SBBButton1_Click(object sender, EventArgs e)
{
        SysLogSender sysLogSender = new SysLogSender();
        // Deneme yaptığımız bilgisayarın yani kendi bilgisayarımızın ip adresi
        sysLogSender.DestinationIpAddress = "127.0.0.1";
        // Mail servisi için gönderilen bir mesaj olsun
        sysLogSender.ServiceAreaCode = 2;
        // Mesaj tipimizde not olsun
        sysLogSender.Send(null, SysLogSender.PriorityType.Notice, DateTime.Now, "Deneme mesaj");
}

Sonuç :
Şekil 1-B

Sonsöz :
            Türkçe yazdığım ilk makalemin sizler için yararlı olabildiğini umarak hepinize başarılar diliyorum. Esenlikle kalın...

Mehmet Akif ÇAKAR;
http://authors.sbbsoftware.com/MehmetAkifCAKAR/