log4net.redis+logstash+kibana+elasticsearch+redis 實現日誌系統

來源:互聯網
上載者:User

標籤:style   blog   http   color   java   使用   os   strong   

前端時間寫了個隨筆 log4net.NoSql +Elasticsearch 實現日誌記錄 ,因項目原因需要把日誌根java平台的同事整合採用logstash+kibana+elasticsearch+redis結構實現日誌統計分析,所以需要一個將log4net日誌輸出到redis的組件。沒有找到現成的,就自己動手了。參考了 log4net.NoSql 的代碼。

redis的C#用戶端使用了 ServiceStackRedis,json序列化使用 RestSharp。代碼結構如下:

 

JsonLayout.cs代碼:

  public class JsonLayout : LayoutSkeleton    {        public readonly string HostName;        private readonly ITextTransform _transform;        public string LogType { get; set; }        public string AppName { get; set; }        public JsonLayout()            : base()        {            HostName = Dns.GetHostName();            _transform = TextTransform.Instance;        }        public override string ContentType        {            get { return "application/json"; }        }        public override void ActivateOptions()        {            //nothing to do here        }        public override void Format(TextWriter writer, LoggingEvent loggingEvent)        {            var info = loggingEvent.LocationInformation;            var loggingEventJson = _transform.Serialize(new JsonLogMessage                {                    class_method = info.MethodName,                    class_name = info.ClassName,                    host_ip = HostName,                    line_number = info.LineNumber,                    log_level = loggingEvent.Level.DisplayName,                    log_message = loggingEvent.MessageObject.ToString(),                    exception = BuildExceptionMessage(loggingEvent),                    log_time = loggingEvent.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss"),                    logger_name = loggingEvent.LoggerName,                    run_time = "0", //目前擷取不到                    thread_name = loggingEvent.ThreadName,                    host = HostName,                    log_type = this.LogType,                    app_name = this.AppName,                    path = ""                });            writer.Write(loggingEventJson);        }        private JsonLogException BuildExceptionMessage(LoggingEvent loggingEvent)        {            if (loggingEvent.ExceptionObject == null)                return new JsonLogException { exception_class = "", exception_message = "", exception_stacktrace = "" };            var exception = loggingEvent.ExceptionObject;            return                new JsonLogException                {                    exception_class = exception.Source,                    exception_message = exception.Message,                    exception_stacktrace = exception.StackTrace                };        }    }
View Code

RedisAppender.cs

 public class RedisAppender : AppenderSkeleton    {        private volatile PooledRedisClient _pooledRedisClient;        private readonly object _padlock = new object();        public string Host { get; set; }        public string Port { get; set; }        public string ListId { get; set; }        public string MaxPoolSize { get; set; }        public RedisAppender()        {        }        private PooledRedisClient Client        {            get            {                if (_pooledRedisClient != null) return _pooledRedisClient;                lock (_padlock)                {                    if (_pooledRedisClient == null)                    {                        _pooledRedisClient = new PooledRedisClient(this.Host, int.Parse(this.Port), int.Parse(this.MaxPoolSize));                    }                }                return _pooledRedisClient;            }        }        protected override void Append(LoggingEvent loggingEvent)        {            var sb = new StringBuilder();            var writer = new StringWriter(sb);            base.Layout.Format(writer, loggingEvent);            this.Client.AddItemToListAsync(ListId, writer.ToString());        }    }
View Code

PooledRedisClient.cs

  public class PooledRedisClient    {        private readonly string _baseUri;        private readonly PooledRedisClientManager _clientManager;        /// <summary>        /// 執行個體化串連池用戶端        /// </summary>        /// <param name="host"></param>        /// <param name="port"></param>        /// <param name="maxPoolSize">預設值10</param>        public PooledRedisClient(string host, int port, int maxPoolSize = 10)        {            _baseUri = string.Format("{0}:{1}", host, port);            var config = new RedisClientManagerConfig();            config.MaxReadPoolSize = maxPoolSize;            config.MaxWritePoolSize = maxPoolSize;            _clientManager = new PooledRedisClientManager(new string[] { _baseUri }, new string[] { _baseUri }, config);        }        /// <summary>        /// 非同步記錄        /// </summary>        /// <param name="listId"></param>        /// <param name="log"></param>        public void AddItemToListAsync(string listId, string log)        {            //使用Task任務非同步執行            var task = new Task(() =>            {                try                {                    using (var clinet = _clientManager.GetClient())                    {                        clinet.AddItemToList(listId, log);                    }                }                catch (Exception ex)                {                    Trace.WriteLine(ex.Message);                }            });            task.Start();        }    }
View Code

在RedisClient串連時用了串連池,寫日誌時用Task做了非同步。這種寫法不知道會不會存在問題?!

設定檔

<?xml version="1.0"?><log4net>  <!--Redis日誌記錄-->  <appender name="redisAppender" type="log4net.Redis.Appender.RedisAppender, log4net.Redis">    <Host value="192.168.0.10" />    <Port value="6379" />    <MaxPoolSize value="500" />    <ListId value="logstash" />    <layout type="log4net.Redis.Layout.JsonLayout,log4net.Redis" >      <LogType value="iis_log" />      <AppName value="Demo" />    </layout>  </appender>  <root>    <level value="ALL" />    <appender-ref ref="redisAppender" />  </root></log4net>
View Code

Layout和Appender裡的屬性配置和代碼裡屬性配置名稱一致,Log4net的架構就可以讀取配置資料反射到實體屬性上。

代碼:

http://download.csdn.net/detail/zbl131/7702673

 

參考文章:

1.用Kibana和logstash快速搭建即時日誌查詢、收集與分析系統

http://storysky.blog.51cto.com/628458/1158707/

2.使用ServiceStackRedis連結Redis簡介

http://www.cnblogs.com/daizhj/archive/2011/02/17/1956860.html

3.ServiceStack.Redis的問題與修正

http://blog.csdn.net/susubuhui/article/details/8930417

4.對ServiceStack.Redis的串連池進行容錯移轉改造

http://www.cnblogs.com/smark/archive/2013/05/24/3096488.html

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.