系列文章
概述
我們是基於這篇文章: Grafana 系列文章(十二):如何使用 Loki 建立一個用於搜尋日誌的 Grafana 儀表板, 建立一個類似的, 但是基於 ElasticSearch 的日誌快速搜尋儀表板.
最終完整效果如下:
?Notes:
其實我基於 ElasticSearch 做了2個儀表板
- 用於檢索 Applog 的
- 用於檢索 accesslog 的
在下面的講解中會綜合2個儀表板來進行說明.
這次不會講述詳細細節, 只選擇部分關鍵點進行說明.
知識儲備
建立 Query
使用自定義的JSON字串編寫查詢,field 在Elasticsearch索引對映中被對映為一個 keyword。
如果查詢是 multi-field 的 text
和 keyword
型別,使用 "field": "fieldname.keyword"
(有時是fieldname.raw
)來指定你查詢中的關鍵字欄位。
Query
Query | Description |
---|---|
{"find": "fields", "type": "keyword"} |
返回一個索引型別為keyword 的欄位名列表。 |
{"find": "terms", "field": "hostname.keyword", "size": 1000} |
使用 terms 聚合返回一個 keyword 的值列表。查詢將使用當前儀表板的時間範圍作為時間範圍查詢。 |
{"find": "terms", "field": "hostname", "query": '<Lucene query>'} |
使用terms 聚合和指定的Lucene查詢過濾器,返回一個keyword field 的值列表。查詢將使用當前儀表板的時間範圍作為查詢的時間範圍。 |
terms
的查詢預設有500個結果的限制。要設定一個自定義的限制,需要在你的查詢中設定size
屬性。
Variable 語法
皮膚標題和 metric 查詢可以使用多種不同的語法來引用變數:
$varname
, 這種語法很容易閱讀,但它不允許你在詞的中間使用變數。例如:apps.frontend.$server.requests.count
${var_name}
, 當你想在表示式的中間插值一個變數時,請使用這種語法。${var_name:<format>}
這種格式讓你對Grafana如何插值有更多控制。[[varname]]
不建議使用。廢棄的舊語法,將在未來的版本中刪除。
高階變數格式選項
變數插值的格式取決於資料來源,但在有些情況下,你可能想改變預設的格式。
例如,MySql資料來源的預設格式是以逗號分隔的方式連線多個值,並加引號, 如:'server01', 'server02'
.在某些情況下,你可能希望有一個不帶引號的逗號分隔的字串, 如:server01,server02
。你可以用下面列出的高階變數格式化選項來實現這一目的。
通用語法
語法: ${var_name:option}
可以在Grafana Play網站上測試格式化選項。
如果指定了任何無效的格式化選項,那麼 glob
就是預設/回退選項。
CSV
將具有多個值的變數形成一個逗號分隔的字串。
servers = ['test1', 'test2']
String to interpolate: '${servers:csv}'
Interpolation result: 'test1,test2'
分散式 - OpenTSDB
以OpenTSDB的自定義格式對具有多個值的變數進行格式化。
servers = ['test1', 'test2']
String to interpolate: '${servers:distributed}'
Interpolation result: 'test1,servers=test2'
雙引號
將單值和多值變數形成一個逗號分隔的字串,在單個值中用\"
轉義"
,並將每個值用""
引號括起來。
servers = ['test1', 'test2']
String to interpolate: '${servers:doublequote}'
Interpolation result: '"test1","test2"'
Glob - Graphite
將具有多個值的變數組成一個glob(用於Graphite查詢)。
servers = ['test1', 'test2']
String to interpolate: '${servers:glob}'
Interpolation result: '{test1,test2}'
JSON
將具有多個值的變數形成一個逗號分隔的字串。
servers = ['test1', 'test2']
String to interpolate: '${servers:json}'
Interpolation result: '["test1", "test2"]'
Lucene - Elasticsearch
以Lucene格式對Elasticsearch的多值變數進行格式化。
servers = ['test1', 'test2']
String to interpolate: '${servers:lucene}'
Interpolation result: '("test1" OR "test2")'
URL 編碼 (Percentencode)
對單值和多值變數進行格式化,以便在URL引數中使用。
servers = ['foo()bar BAZ', 'test2']
String to interpolate: '${servers:percentencode}'
Interpolation result: 'foo%28%29bar%20BAZ%2Ctest2'
Pipe
將具有多個值的變數形成一個管道分隔的字串。
servers = ['test1.', 'test2']
String to interpolate: '${servers:pipe}'
Interpolation result: 'test1.|test2'
Raw
關閉資料來源特定的格式化,如SQL查詢中的單引號。
servers = ['test.1', 'test2']
String to interpolate: '${var_name:raw}'
Interpolation result: 'test.1,test2'
Regex
將有多個值的變數形成一個regex字串。
servers = ['test1.', 'test2']
String to interpolate: '${servers:regex}'
Interpolation result: '(test1\.|test2)'
單引號
將單值和多值變數形成一個逗號分隔的字串,在單個值中用\'
轉義'
,並將每個值用'
引號括起來。
servers = ['test1', 'test2']
String to interpolate: '${servers:singlequote}'
Interpolation result: "'test1','test2'"
Sqlstring
將單值和多值變數組成一個逗號分隔的字串,每個值中的'
用''
轉義,每個值用'
引號括起來。
servers = ["test'1", "test2"]
String to interpolate: '${servers:sqlstring}'
Interpolation result: "'test''1','test2'"
Text
將單值和多值變數轉換成其文字表示法。對於一個單變數,它將只返回文字表示法。對於多值變數,它將返回與+
相結合的文字表示法。
servers = ["test1", "test2"]
String to interpolate: '${servers:text}'
Interpolation result: "test1 + test2"
查詢引數
將單值和多值變數編入其查詢參數列示法。例如:var-foo=value1&var-foo=value2
servers = ["test1", "test2"]
String to interpolate: '${servers:queryparam}'
Interpolation result: "servers=test1&servers=test2"
配置變數選擇選項
Selection Options 是一個你可以用來管理變數選項選擇的功能。所有的選擇選項都是可選的,它們在預設情況下是關閉的。
Multi-value Variables
內插一個選擇了多個值的變數是很棘手的,因為如何將多個值格式化為一個在使用該變數的給定環境中有效的字串並不直接。Grafana試圖透過允許每個資料來源外掛告知模板插值引擎對多個值使用什麼格式來解決這個問題。
?Notes:
變數上的Custom all value選項必須為空,以便Grafana將所有值格式化為一個字串。如果它留空,那麼Grafana就會把查詢中的所有值連線起來(加在一起)。類似於
value1,value2,value3
。如果使用了一個自定義的所有值,那麼該值將是類似於*
或all
的東西。
帶有Prometheus或InfluxDB資料來源的多值變數
InfluxDB和Prometheus使用regex表示式,所以host1
, host2
, host3
變數會被插值為{host1,host2,host3}
。每個值都會被regex轉義。
使用Elastic資料來源的多值變數
Elasticsearch使用lucene查詢語法,所以同樣的變數會被格式化為("host1" OR "host2" OR "host3")
。在這種情況下,每一個值都必須被轉義,以便該值只包含lucene控制詞和引號。
Include All 選項
Grafana在變數下拉選單中新增了一個 All
選項。如果使用者選擇了這個選項,那麼所有的變數選項都被選中。
自定義 all 的值
這個選項只有在選擇了 Include All option 時才可見。
在Custom all value欄位中可以輸入regex、globs或lucene語法來定義All選項的值。
預設情況下,All
值包括組合表示式中的所有選項。這可能會變得非常長,而且會產生效能問題。有時,指定一個自定義的所有值可能會更好,比如萬用字元。
為了在 Custom all value 選項中擁有自定義的regex、globs或lucene語法,它永遠不會被轉義,所以你將不得不考慮什麼是你的資料來源的有效值。
ElasticSearch Template Variables
選擇一種 Variable 語法
如上文所述, Elasticsearch資料來源支援在查詢欄位中使用多種變數語法.
當啟用 Multi-value 或 Include all value 選項時,Grafana 會將標籤從純文字轉換為與 Lucene 相容的條件。即隱式轉換 $varname
為 ${varname:lucene}
實戰
1. 弄清楚有哪些索引欄位
首先, 最重要的, 就是弄清楚該索引有哪些索引欄位(fields), 以及有哪些keywords, 選擇部分欄位和 keywords 作為 varibles. 可以直接透過 Kibana 介面進行查詢和嘗試.
如本次選擇的有:
app_name
level
request_path
(? 透過多次在 Kibana 上使用發現, 查詢時應該使用request_path.keyword
而不是request_path
)request_method
status_code
2. 建立 Variables
app_name
設定如下:
- Name:
app_name
- Type: Query
- Data source: ES
- Query:
{"find": "terms", "field": "current_app_name"}
, 另外, 如果巢狀使用, 可以類似這樣{"find": "terms", "field": "pod_name", "query": "app_name:$app_name"}
request_path
設定如下:
- Name:
request_path
- Type: Query
- Data source: ES
- Query:
{"find": "terms", "field": "request_path.keyword", "query": "app_name:$app_name"}
- Multi-value: ✔️
- Include All option: ✔️
- Custom all value:
*
? 注意, 這裡使用了 Custom all value, 最終 Query All 的表示式就會變成: request_path.keyword:*
而不是 request_path.keyword:(<path1> OR <path2> ...)
request_method
request_method
常用的就這麼幾個:
- GET
- POST
- DELETE
- HEAD
- PUT
- PATCH
- OPTIONS
所以可以將其設定為 Custom
variable, 設定如下:
- Name:
request_method
- Type: Custom
- Values separated by comma:
GET,POST,DELETE,HEAD, PUT,PATCH,OPTIONS
- Multi-value: ✔️
- Include All option: ✔️
- Custom all value:
*
level
日誌級別可以直接使用 Custom 型別變數. 如下:
- Name:
level
- Type:
Custom
- Values separated by comma:
INFO, WARN, ERROR,FATAL
- Multi-value: ✔️
- Include All option: ✔️
如果只關注錯誤日誌, 那麼 level 變數的預設值可以設定為同時勾選: ERROR
和 FATAL
status_code
這裡會將 status_code
variable 用於 Lucene 的範圍語法 []
(包括開頭和結尾的2個數字), 所以有用到Custom all value
以及 Variable 語法配置.
- Name:
status_code
- Type:
Custom
- Values separated by comma:
200 TO 299, 300 TO 399, 400 TO 499, 500 TO 599
- Include All option: ✔️
- Custom all value:
200 TO 599
(?Note: 即包括所有的 http 狀態碼, 從 200 到 599)
後續要在 Query 中使用, 用法如下:
status_code:[${status_code:raw}]
直接使用 ${status_code:raw}
, 這樣傳入就會變成:
status_code:[200 TO 299]
status_code:[200 TO 599]
按期望完成對 ES 的查詢.
filter
最後, 還新增一個 Ad hoc filters
variable, 方便使用者進行更多自定義的過濾篩選.
- Name: filter
- Type:
Ad hoc filters
- Data source:
${datasource}
後續會在該 Dashboard 的所有 Query 中自動使用. 一個典型使用場景如下:
對於 request_path
, 需要過濾監控/健康檢查等請求(包含info
health
metric
等關鍵詞), 那麼可以將該 filter
儲存為預設的變數值.
3. Panel
Dashboard 只有 2 個皮膚組成:
- 上圖: Time series, 顯示日誌柱狀圖, 並著色,
INFO
日誌為綠色,WARN
日誌為黃色,ERROR
和FATAL
日誌為紅色. - 下日誌
Time series panel
如下圖:
可以透過如下 Query 實現:
app_name:$app_name AND level:($level AND INFO)
app_name:$app_name AND level:($level AND ERROR or FATAL)
$level AND INFO
這種寫法是一個 workaround, 為的是在 level 變數改變時, Time series panel 隨之改變.
另外一個需要注意的點是, Metric
是 Count
(日誌條數) 而不是 Logs
(具體日誌).
還有, 需要配置 Override -> Color, 如下:
最後, 如果柱子太密, 可以透過調整如 3 Colors Time series panel
圖中的 Interval
來調整時間間隔, 本例調整為 1m
Logs panel
在 Logs panel 中, 也可以根據實際情況做一系列調整.
如下圖, 可以對日誌展示方式做調整:
- Time: 是否加時間戳
- Unique labels: 是否每條日誌加 label
- Common labels: 是否對 logs panel 左上角對所有日誌加 common labels
- Wrap lines
- Pretify JSON: JSON 美化
- Enable log details: 啟用檢視日誌詳細資訊
- Deduplication: 日誌去重, 去重方式有:
- None: 不去重
- Exact: 精確去重
- Numbers: 不同數字記為同一類的去重方式
- Signature: 根據計算得出的 Signature 去重
- Order: 排序.
另外, 考慮到 ES 日誌的 log details 會有很多我們不關注的 fields, 如: _source
_id
等, 可以透過 Transform 進行轉換調整. 具體如下圖:
總結
這篇文章算是該系列文章的一個重點了. 包含了非常多的實用細節.
如:
- ES Query
- Variable 語法
- Variable raw 語法
- Lucene - Elasticsearch 語法
- …
- Multi-value Variables
- Include All 選項
- 自定義 all 的值
Ad hoc filters
Variable- ES Metric Type
- Count
- Logs
- …
- 調整Query 時間間隔
- Logs panel 設定
- Panel Transform
希望對你有所幫助.
三人行, 必有我師; 知識共享, 天下為公. 本文由東風微鳴技術部落格 EWhisper.cn 編寫.