Nlog、elasticsearch、Kibana以及logstash在項目中的應用(二)

上一篇說如何搭建elk的環境(不清楚的能夠看個人上一篇博客http://www.cnblogs.com/never-give-up-1015/p/5715904.html),如今來講一下如何用Nlog將日誌經過logstash寫入elasticsearch。html

 新建一個項目,用nuget引入Nlog,隨便寫幾行打日誌的代碼(寫成循環是爲了方便測試)數據庫

 1             var log = LogManager.GetCurrentClassLogger();
 2             while (true)
 3             {
 4                 log.Info("high Hkaos one");
 5                 log.Debug("high Hkaos two");
 6                 log.Warn("high Hkaos three");
 7                 log.Error("high Hkaos four");
 8                 Console.WriteLine("success");
 9                 Console.ReadKey();
10             }

我是採用udp的方式傳輸,因此在配置Nlog的時候須要設置type爲Network,至於message的格式能夠在layout中配置(網上一大堆,一搜就出來了),下面是個人配置文件json

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
      <target name="network" xsi:type="Network" address="udp://192.168.4.12:4561" layout="${message}"/>
    </targets>
    <rules>
          <logger name="*" minlevel="Debug" writeTo="network" />
    </rules>
  </nlog>
</configuration>

一開始沒有寫configSections和rules,因此一直沒有打日誌,暈死。數組

配置完畢以後,在配置logstash。因爲Nlog是經過udp一直向配置的地址端口發送日誌,因此在配置文件(這個配置就是本身手動建的文件,不懂的看上一篇博客)中的input要監聽Nlog中配置的地址。logstash的input中能夠寫多種蒐集日誌的方式,有興趣的能夠去官網地址看看(https://www.elastic.co/guide/en/logstash/current/input-plugins.html)。app

input { 
    udp{
        host=>"192.168.4.12"
        port=>4561
    }    
}

  output {
    stdout{

    }
}elasticsearch

 

input下面能夠寫多個蒐集方式,好比ide

input { 
    stdin{
    
    }
    udp{
        host=>"192.168.4.12"
        port=>4561
    }    
}

配置完成以後就能夠測試一下。運行程序以前記得啓動logstash,elasticsearch和kibana暫時不用能夠不用啓動。工具

同時觀察啓動logstash的窗口佈局

出現了剛剛打印的日誌,yes! 成功了。測試

那咱們先看看如何把日誌寫到elasticsearch裏面而且經過kibana查看。很簡單,咱們在output中把原先輸入到屏幕上的信息同時也輸入到elasticsearch中就Ok了。同時呢,output的輸出方式也有不少,能夠去看看(https://www.elastic.co/guide/en/logstash/current/output-plugins.html),elasticsearch的選項有不少,這裏有詳細的介紹(https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html),下面是個人配置

output {
        stdout{
        }
        elasticsearch {
        hosts => ["127.0.0.1:9200"]
        index => "logstash-%{+YYYY.MM.dd}"
        document_type => "logs"
        }
}

hosts就是elasticsearch的地址,能夠配置多個,是個數組,index是索引的名稱,至關於數據庫的庫名字,這裏就是命名就是logstash-當天日期,天天都會新建一個庫,document_type是類型的名稱,至關於數據庫中的表,老版本是index_type,新版本不讓用了,若是用的話就會報錯,告訴你這個方法被棄用了,讓你用document_type。配置好以後須要從新啓動logstash,首先要先啓動elasticsearch和kibana。(Tip:重啓logstash的話能夠用Ctrl+C重啓,連續按,能輸入爲止)。走起!

界面是沒啥變化,這時候要登陸kibana看看,地址在啓動kibana的時候被被打印出來

界面以下:

剛剛的日誌被打印了出來,bingo!右邊的字段能夠本身選擇添加是否顯示在右邊,右上角有個last 15 minutes,表示查看最新15分鐘的,點擊以後你能夠任意選擇你想查看的時間段。

同時呢,elasticsearch也自帶了查詢的插件,不過須要安裝,方法也簡單,cmd進入elasticsearch的目錄 運行plugin -install mobz/elasticsearch-head,就會自動安裝了,成功以後地址爲http://localhost:9200/_plugin/head/,能夠直接訪問,下面是界面

在基本查詢裏面你能夠查詢打印的日誌,還有執行的查詢語句和原始的json。

可是這些只能打印出message,好比我要打印其餘的東西怎麼辦,好比方法名,hash值,是debug仍是info仍是error以及其餘自定義的字段,這時候會有人說那就所有打印在message裏面,那爲啥還要這麼麻煩用這個工具呢,直接打印到文件裏面直接Ctrl+F就行了。因此咱們要經過Nlog打印自定義的字段。這就要本身在Nlog裏面定義了。

這也是在網上查找了資料才找到的方法,須要繼承Nlog的LayoutRenderer,重寫Append方法

    [LayoutRenderer("json")]
    public class JsonLayoutRenderer : LayoutRenderer
    {
        protected override void Append(StringBuilder builder, LogEventInfo loggingEvent)
        {
            var msg = loggingEvent.FormattedMessage.AsJson<JsonLogMessage>();

            msg.priority = loggingEvent.Level.ToString();
            msg.logger_name = loggingEvent.LoggerName;
            msg.thread = loggingEvent.SequenceID.ToString();
            msg.application = "TestApplication";
            var json = msg.AsJsonString();
            builder.Append(json);
        }
    }

原本是經過賦值的方法在LogEventInfo中取我想要的值好比Method,file,class等等,Log4net中是直接能夠取獲得的,可是Nlog不行,唉,蛋疼,因此只能吧數據寫到json序列化以後寫到message裏面,而後在這個方法裏面反序列化回來。大神們有什麼好方法但願給解惑啊!

這是對象信息

  public class JsonLogMessage
    {
        public string @class { get; set; }
        public string file { get; set; }
        public string host { get; set; }
        public string logger_name { get; set; }
        public string path { get; set; }
        public string priority { get; set; }
        public string thread { get; set; }
        public string application { get; set; }
        public string message { get; set; }
        public string addUser { get; set; }
        public string addUserName { get; set; }
        public string objName { get; set; }
        public string objId { get; set; }
        public int hash { get; set; }
        public string method { get; set; }
        public DateTime timestamp { get; set; }
    }

原本timestamp字段不想寫上去的,可是後來經過代碼取不到時間,也是一個蛋疼的問題。

那message的格式修改了,因此打日誌的方法也就要變了,因爲Append的方式改變了,因此佈局方式須要從新修改,只要在程序運行前加一段代碼就好,代碼裏面用的AsJosn和AsJosnString是封裝好的json序列化和反序列化的方法,因此你們要用的話就直接用json原生的方法就行了。另外在配置文件中須要改變layout的佈局方式,將layout="${message}修改爲layout="${json}

private static void Main(string[] args)
        {
            ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("json", typeof(JsonLayoutRenderer));

            var log = LogManager.GetCurrentClassLogger();
            while (true)
            {
                var josn1 = new JsonLogMessage("Main", -1, "high Hkaos one", "tester", "testName", "objName", "objId");
                var josn2 = new JsonLogMessage("Main", -1, "high Hkaos two", "tester", "testName", "objName", "objId");
                var josn3 = new JsonLogMessage("Main", -1, "high Hkaos three", "tester", "testName", "objName", "objId");
                var josn4 = new JsonLogMessage("Main", -1, "high Hkaos four", "tester", "testName", "objName", "objId");

                log.Info(josn1.AsJsonString());
                log.Debug(josn2.AsJsonString());
                log.Warn(josn3.AsJsonString());
                log.Error(josn4.AsJsonString());
                Console.WriteLine("success");
                Console.ReadKey();
            }
        }

運行!

完蛋了,看到這個我就知道有錯了,雖然日誌出來了,可是咱們在head插件或者kibana中看看(我用的是head插件)

日誌的信息所有打印到message裏面,操蛋了。我要的不是這樣子的。去Google了一下,發現要是用json的話,須要在input裏面加codec=>"json",好了,那就修改一下input

input { 
    stdin{

    }
    udp{
        host=>"192.168.4.12"
        port=>4561
        codec=>"json"
    }    
}

重啓一下logstash,再來一遍

此次明顯打印的不同了,再看看head裏面數據

yes!要的就是這個效果。

以後我吧Nlog的配置改爲了代碼寫的,使用配置文件總有一些不方便的地方,好比說地址。下面是代碼

 private static void Main(string[] args)
        {
            ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("json", typeof(JsonLayoutRenderer));

            var log = LogManager.GetCurrentClassLogger();
            var udpTarget = new NetworkTarget()
            {
                Address = "udp://192.168.4.12:4561",
                Encoding = Encoding.UTF8,
                Layout = "${json}",
                NewLine = true,
            };

            var config = new LoggingConfiguration();
            config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, udpTarget));
            LogManager.Configuration = config;

            while (true)
            {
                var josn1 = new JsonLogMessage("Main", -1, "high Hkaos one", "tester", "testName", "objName", "objId");
                var josn2 = new JsonLogMessage("Main", -1, "high Hkaos two", "tester", "testName", "objName", "objId");
                var josn3 = new JsonLogMessage("Main", -1, "high Hkaos three", "tester", "testName", "objName", "objId");
                var josn4 = new JsonLogMessage("Main", -1, "high Hkaos four", "tester", "testName", "objName", "objId");

                log.Info(josn1.AsJsonString());
                log.Debug(josn2.AsJsonString());
                log.Warn(josn3.AsJsonString());
                log.Error(josn4.AsJsonString());
                Console.WriteLine("success");
                Console.ReadKey();
            }
        }

配置文件裏面直接刪除原來添加的東西就行了。

就寫到這裏吧,下一篇準備些一下如何用C#連接日誌服務,根據條件查詢日誌,如何配置模板和映射等。

相關文章
相關標籤/搜索