[料理佳餚] ELK 搭檔 NXLog 收集 IIS Log

IIS Log 是記錄 HTTP Request 的重要記錄檔,我們可以從 IIS Log 中得知 Client 端對 Server 端的所有 HTTP 要求,IIS Log 一般以檔案的型式儲存在磁碟中,因此要收 IIS Log 就用監看檔案的方式,只要檔案有異動就把異動的部分往 Elasticsearch 送,這樣不僅每次傳輸的資料量不大,而且快又即時,接下來我們來看看 ELK 怎麼來達成這件事情。

挑選 W3C 記錄欄位

IIS Log 預設並沒有勾選全部的欄位,為了統一及方便起見我這邊把 IIS Log 的欄位全部打勾。

產生 Logstash 設定檔

雖然說 ELK 是一整套的,但是大部分要調整的都是 Logstash,收集 IIS Log 的 Logstash 設定檔如下,其中的參數我在下面做說明。

input {
    tcp {
        port => 1304
    }
}
filter {
    grok {
        match => {
            "message" => "%{TIMESTAMP_ISO8601:logTime} %{WORD:serviceName} %{NOTSPACE:computerName} %{IP:siteIP} %{WORD:httpMethod} %{URIPATH:relativePath} %{NOTSPACE:queryString} %{NUMBER:port} %{NOTSPACE:userName} %{IPORHOST:clientHost} %{NOTSPACE:httpVersion} %{NOTSPACE:userAgent} %{NOTSPACE:cookie} %{NOTSPACE:referer} %{HOSTNAME:siteHost} %{NUMBER:httpStatus} %{NUMBER:httpSubtatus} %{NUMBER:win32Status} %{NUMBER:sentBytes} %{NUMBER:receivedBytes} %{NUMBER:timeTaken}"
        }
    }
    date {
        match => ["logTime", "YYYY-MM-dd HH:mm:ss"]
        timezone => "Etc/UCT"
    }
    mutate {
        remove_field => ["logTime"]
        convert => {
            "port" => "integer"
            "sentBytes" => "integer"
            "receivedBytes" => "integer"
            "timeTaken" => "integer"
        }
    }
}
output {
    elasticsearch {
        hosts => ["elasticsearch1", "elasticsearch2", "elasticsearch3"]
        document_type => "iislog"
    }
}

input { tcp {} }

tcp 插件會幫我們監聽一個 port 等待訊息輸入。

filter { grok {} }

grok 插件是 Logstash 中非常重要的一個插件,它允許我們寫 Regular Expression 來過濾輸入的訊息,並且把符合條件的訊息指定到一個變數中,撰寫的格式就像這樣 (?<serviceName>\b\w+\b),它的意思代表只要符合 \b\w+\b 這個正則表達式的訊息就填入到 serviceName 這個變數之中。

grok 也允許我們宣告一個正則表達式指定成一個常數值,就像這樣 WORD \b\w+\b,宣告完之後我們就可以不用再寫標準的正則表達式,直接這樣使用 %{WORD:serviceName} 也有一樣的效果,grok 預設有幫我們宣告一些常用的正則表達式,我們可以直接拿來用,至於有哪些正則表達式可以提供使用,請參考這裡 logstash-patterns-core/patterns/grok-patterns

grok 官網也提供了一個 Grok Debugger 的工具,讓我們可以在上面直接線上除錯,讓我們看看收到的訊息是不是符合我們宣告的正則表達式,超方便的。

match 這個參數值可以是一個或多個,差別就在於輸入進來的訊息是否有多種不同的拆解方式,如果是,就多設定幾組正則表達式來拆解,如果不是設定一組就可以了。

一個我們就這樣宣告:

filter {
    grok {
        match => {
            "message" => "…"
        }
    }
}

多個我們就這樣宣告:

filter {
    grok {
        match => [
            "message", "…",
            "message", "…"
        ]
    }
}

filter { date {} }

date 插件可以用來轉換訊息中的時間字串,轉存到 @timestamp 這個欄位之中,@timestamp 這個欄位是固定會有的,如果我們不指定的話,預設就是 Logstash 處理訊息當下的時間,如果我們想要指定 @timestamp 為訊息內容裡面所帶的時間資訊,就用 date 插件來轉換。

filter { mutate {} }

mutate 插件是另一個 Logstash 中重要的插件,它提供資料類型轉換、字串處理、欄位處理的功能,像如果我要移除掉一個欄位就這樣寫。

filter {
    mutate {
        remove_field => ["欄位名稱1","欄位名稱2",…]
    }
}

儲存 Logstash 設定檔

我們要的 input、filter、output 都設定完成之後,就把它儲存下來,設定檔我就命名為 iislog_tcp_to_elasticsearch.conf 存放在 /etc/logstash/conf.d 資料夾,Logstash 在背景啟動時會從這個資料夾裡面載入所有的 *.conf 檔案,然後開始執行所載入的訊息轉入作業,如果還有其他設定檔需要在背景執行,必須要把副檔名命名為 *.conf 放到 /etc/logstash/conf.d。

安裝及設定 NXLog

接著,我們要在 IIS 伺服器上安裝 NXLog,而為什麼我們需要安裝 NXLog?目的是要去監看 IIS Log 檔,將檔案內容有異動的部分往 Logstash 傳送,其實 Logstash 本身有 file 插件可以提供我們相同的功能,只是某些 Logstash 的版本在 Windows 上不靠譜,所以我們選用其他軟體來 cover 掉這一個部分,不一定要用 NXLog,也可以選用其他的軟體,只要達到相同的目的就行了。

我們安裝的是 NXLog Community Edition,安裝好之後我們要去修改設定檔,設定檔是 C:\Program Files (x86)\nxlog\conf\nxlog.conf,內容如下。

## This is a sample configuration file. See the nxlog reference manual about the
## configuration options. It should be installed locally and is also available
## online at http://nxlog.org/docs/

## Please set the ROOT to the folder your nxlog was installed into,
## otherwise it will not start.

#define ROOT C:\Program Files\nxlog
define ROOT C:\Program Files (x86)\nxlog

Moduledir %ROOT%\modules
CacheDir %ROOT%\data
Pidfile %ROOT%\data\nxlog.pid
SpoolDir %ROOT%\data
LogFile %ROOT%\data\nxlog.log

<Extension _syslog>
    Module      xm_syslog
</Extension>

<Input iislog>
    Module      im_file
    File      "C:\\inetpub\\logs\\LogFiles\\W3SVC1\\u_ex*"
    SavePos      TRUE
</Input>

<Output logstash>
    Module      om_tcp
    Host        LogstashServer
    Port        1304
</Output>

<Route 1>
    Path        iislog => logstash
</Route>

我們這邊需要關注的三個 tag:<Input><Output><Route>

<Input>

我們先給 Input 標籤一個自定義的名字 iislog,我們要在標籤裡面去設定一組輸入的來源。

  • Module:設定 為im_file
  • File:設定 IIS Log 檔案的儲存位置
  • SavePos:設定為 TRUE,用來記住上次的讀檔位置。

<Output>

我們一樣給 Output 檔籤一個自定義的名字 logstash,我們在標籤裡面去設定一組輸出的目的。

  • Module:設定 為om_tcp
  • Host:設定為 Logstash 伺服器的名稱或位址
  • Port:設定為 Logstash 伺服器開啟監聽的埠號

<Route>

Route 是告訴 NXLog 哪一個 Input 要對應到哪一個 Output,Input 及 Output 可以用逗號隔開設定多組,例如這樣:

<Route 1>
    Path        iislog1,iislog2,… => logstash1,logstash2,…
</Route>

但是如果我們想指定 iislog1 只輸出給 logstash1、iislog2 則輸出給 logstash1 及 logstash2,這個時候就要設定第二組 Route 去另外指定,像這樣:

<Route 1>
    Path        iislog1 => logstash1
</Route>

<Route 2>
    Path        iislog2 => logstash1,logstash2
</Route>

啟動 NXLog 服務

一切就緖之後我們在「服務」裡面找到 nxlog,並且把它啟動。

啟動之後我們可以查看記錄檔 C:\Program Files (x86)\nxlog\data\nxlog.log,看看服務有沒有正常啟動、連線 Logstash 伺服器有沒有正常。

這樣就大功告成了,只要 IIS 有發生 HTTP Request 事件,我們就可以在 Kibana 上看得到。

參考資料