Log4net自定義實現httpAppender


Log4net內置了很多Appender但似乎找不到基於Http.在應用希望在本地保存日志的同時也可以把日志提交到一個Http服務中用於統一跟蹤管理.如果每記錄一次日志都提交給Http服務那對於應用端來說連接的創建是件很損耗性能的事情.由於日志不需要實時同步性,在設計上可以通過定時或當內存日志到達一定數量的時候才進行提交,這樣就不會出現頻繁提交日志帶來的性能問題.

功能定義

Log4net實現一個Appender是一件比較簡單的工作,只需要實IAppender接口即可以,當然Log4net也會提供一些基類方便我們實現.接下來我們實現一個httpAppender.在實現之前需制定一些參數用於內部實現用.

Host     日志提交的URL,如:http://localhost:30532/logupload.aspx

ServerTag  提交日志的服務器標記,如:192.168.0.1

AppName  應用程序的名稱,如:Game

MaxRecords  內存保存的最大記錄數,當日志數量超過些值是進行數據提交

Timer    定時提交時間

制定消息存儲結構

    public class LogEvent
    {
        public LogEvent()
        {
            Errors = new List<EventMessage>();
        }
        public string EventType
        {
            get;
            set;
        }
        public string ServerTag
        {
            get;
            set;
        }
        public string Message
        {
            get;
            set;
        }
        public string AppName
        {
            get;
            set;
        }
        public DateTime ErrorTime
        {
            get;
            set;
        }
        public List<EventMessage> Errors
        {
            get;
            set;
        }

    }
    public class EventMessage
    {
        public string Message { get; set; }
        public string StackTrace { get; set; }
    }

Appender實現

    /// <summary>
    /// <code>
    /// <appender name="HttpAppender" type="log4netUTS.HttpAppender,log4netUTS">
    ///  <param name="Host" value="http://localhost:30532/WEBFORM1.ASPX"/>
    ///  <param name="ServerTag" value="192.168.0.1"/>
    ///  <param name="AppName" value="test"/>
    ///  <param name="Timer" value="10000"/>
    ///  <param name="MaxRecords" value="1000"/>
    /// </appender>
    /// </code>
    /// </summary>
    public class HttpAppender : log4net.Appender.AppenderSkeleton
    {
        public HttpAppender()
        {
            Timer = 5000;
            MaxRecords = 300;
        }

        private System.Threading.Timer mTimer;

        private void CreateTime()
        {
            lock (this)
            {
                if (mTimer == null)
                    mTimer = new System.Threading.Timer(Upload, null, Timer, Timer);
            }
        }

        private readonly static Type declaringType = typeof(HttpAppender);

        private Queue<LogEvent> mEvents = new Queue<LogEvent>(1000);

        private void Add(LogEvent item)
        {
            CreateTime();
            lock (mEvents)
            {
                mEvents.Enqueue(item);
                if (mEvents.Count > MaxRecords)
                    Upload(null);
            }
        }

        private void Upload(object state)
        {
            List<LogEvent> items = new List<LogEvent>();
            lock (mEvents)
            {
                while (mEvents.Count > 0)
                {
                    items.Add(mEvents.Dequeue());
                }
            }
            if (items.Count > 0)
            {
                OnUpload(items);
            }
        }

        private void OnUpload(object state)
        {
            try
            {
                List<LogEvent> items = (List<LogEvent>)state;
                string param = "LogData=" + Newtonsoft.Json.JsonConvert.SerializeObject(items);
                byte[] data = Encoding.UTF8.GetBytes(param);
                HttpWebRequest req =
                (HttpWebRequest)HttpWebRequest.Create(Host);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = data.Length;
                using (Stream reqStream = req.GetRequestStream())
                {
                    reqStream.Write(data, 0, data.Length);
                }
                using (WebResponse wr = req.GetResponse())
                {

                }
            }
            catch (Exception e_)
            {
                LogLog.Error(declaringType, e_.Message);
            }
        }

        public string Host
        {
            get;
            set;
        }

        public string ServerTag
        {
            get;
            set;
        }

        public string AppName
        {
            get;
            set;
        }

        public int MaxRecords
        {
            get;
            set;
        }

        public int Timer
        {
            get;
            set;
        }

        protected override void Append(log4net.Core.LoggingEvent loggingEvent)
        {
            try
            {
                LogEvent le = new LogEvent();
                le.ErrorTime = loggingEvent.TimeStamp;
                le.EventType = loggingEvent.Level.ToString();
                le.Message = loggingEvent.RenderedMessage;
                le.AppName = AppName;
                le.ServerTag = ServerTag;
                AddError(le, loggingEvent.ExceptionObject);
                Add(le);


            }
            catch (Exception e_)
            {
                LogLog.Error(declaringType, e_.Message);
            }
        }

        private void AddError(LogEvent e, Exception err)
        {
            if (err != null)
            {
                e.Errors.Add(new EventMessage { Message = err.Message, StackTrace = err.StackTrace });
                err = err.InnerException;
                while (err != null)
                {
                    e.Errors.Add(new EventMessage { Message = err.Message, StackTrace = err.StackTrace });
                    err = err.InnerException;
                }
            }

        }
    }

實現代碼相對比較簡單,就是把隊列中的數據打包成json格式上傳到相關http服務.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM