<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Grafana Loki 查詢語言 LogQL 使用

          共 15085字,需瀏覽 31分鐘

           ·

          2022-06-28 21:55

          受 PromQL 的啟發(fā),Loki 也有自己的查詢語言,稱為 LogQL,它就像一個分布式的 grep,可以聚合查看日志。和 PromQL 一樣,LogQL 也是使用標簽和運算符進行過濾的,主要有兩種類型的查詢功能:

          • 查詢返回日志行內(nèi)容
          • 通過過濾規(guī)則在日志流中計算相關(guān)的度量指標

          日志查詢

          一個基本的日志查詢由兩部分組成。

          • log stream selector(日志流選擇器)
          • log pipeline(日志管道)

          由于 Loki 的設(shè)計,所有 LogQL 查詢必須包含一個日志流選擇器。一個 Log Stream 代表了具有相同元數(shù)據(jù)(Label 集)的日志條目。

          日志流選擇器決定了有多少日志將被搜索到,一個更細粒度的日志流選擇器將搜索到流的數(shù)量減少到一個可管理的數(shù)量,通過精細的匹配日志流,可以大幅減少查詢期間帶來資源消耗。

          而日志流選擇器后面的日志管道是可選的,用于進一步處理和過濾日志流信息,它由一組表達式組成,每個表達式都以從左到右的順序為每個日志行執(zhí)行相關(guān)過濾,每個表達式都可以過濾、解析和改變?nèi)罩拘袃?nèi)容以及各自的標簽。

          下面的例子顯示了一個完整的日志查詢的操作:

          {container="query-frontend",namespace="loki-dev"} |= "metrics.go" | logfmt | duration > 10s and throughput_mb < 500

          該查詢語句由以下幾個部分組成:

          • 一個日志流選擇器 {container="query-frontend",namespace="loki-dev"},用于過濾 loki-dev 命名空間下面的 query-frontend 容器的日志
          • 然后后面跟著一個日志管道 |= "metrics.go" | logfmt | duration > 10s and throughput_mb < 500,該管道表示將篩選出包含 metrics.go 這個詞的日志,然后解析每一行日志提取更多的表達式并進行過濾

          為了避免轉(zhuǎn)義特色字符,你可以在引用字符串的時候使用單引號,而不是雙引號,比如 `\w+1` 與 "\w+" 是相同的。

          Log Stream Selector

          日志流選擇器決定了哪些日志流應(yīng)該被包含在你的查詢結(jié)果中,選擇器由一個或多個鍵值對組成,其中每個鍵是一個日志標簽,每個值是該標簽的值。

          日志流選擇器是通過將鍵值對包裹在一對大括號中編寫的,比如:

          {app="mysql", name="mysql-backup"}

          上面這個示例表示,所有標簽為 app 且其值為 mysql 和標簽為 name 且其值為 mysql-backup 的日志流將被包括在查詢結(jié)果中。

          其中標簽名后面的 = 運算符是一個標簽匹配運算符,LogQL 中一共支持以下幾種標簽匹配運算符:

          • =: 完全匹配
          • !=: 不相等
          • =~: 正則表達式匹配
          • !~: 正則表達式不匹配

          例如:

          • {name=~"mysql.+"}
          • {name!~"mysql.+"}
          • {name!~"mysql-\\d+"}

          適用于 Prometheus 標簽選擇器的規(guī)則同樣適用于 Loki 日志流選擇器。

          Log Pipeline

          日志管道可以附加到日志流選擇器上,以進一步處理和過濾日志流。它通常由一個或多個表達式組成,每個表達式針對每個日志行依次執(zhí)行。如果一個表達式過濾掉了日志行,則管道將在此處停止并開始處理下一行。一些表達式可以改變?nèi)罩緝?nèi)容和各自的標簽,然后可用于進一步過濾和處理后續(xù)表達式或指標查詢。

          一個日志管道可以由以下部分組成。

          • 日志行過濾表達式
          • 解析器表達式
          • 標簽過濾表達式
          • 日志行格式化表達式
          • 標簽格式化表達式
          • Unwrap 表達式

          其中 unwrap 表達式是一個特殊的表達式,只能在度量查詢中使用。

          日志行過濾表達式

          日志行過濾表達式用于對匹配日志流中的聚合日志進行分布式 grep。

          編寫入日志流選擇器后,可以使用一個搜索表達式進一步過濾得到的日志數(shù)據(jù)集,搜索表達式可以是文本或正則表達式,比如:

          • {job="mysql"} |= "error"
          • {name="kafka"} |~ "tsdb-ops.*io:2003"
          • {name="cassandra"} |~ "error=\\w+"
          • {instance=~"kafka-[23]",name="kafka"} != "kafka.server:type=ReplicaManager"

          上面示例中的 |=|~!=過濾運算符,支持下面幾種:

          • |=:日志行包含的字符串
          • !=:日志行不包含的字符串
          • |~:日志行匹配正則表達式
          • !~:日志行與正則表達式不匹配

          過濾運算符可以是鏈式的,并將按順序過濾表達式,產(chǎn)生的日志行必須滿足每個過濾器。當使用 |~!~ 時,可以使用 Golang 的 RE2 語法的正則表達式,默認情況下,匹配是區(qū)分大小寫的,可以用 (?i) 作為正則表達式的前綴,切換為不區(qū)分大小寫。

          雖然日志行過濾表達式可以放在管道的任何地方,但最好把它們放在開頭,這樣可以提高查詢的性能,當某一行匹配時才做進一步的后續(xù)處理。例如,雖然結(jié)果是一樣的,但下面的查詢 {job="mysql"} |= "error" |json | line_format "{{.err}}" 會比 {job="mysql"} | json | line_format "{{.message}}" |= "error" 更快,日志行過濾表達式是繼日志流選擇器之后過濾日志的最快方式

          解析器表達式

          解析器表達式可以解析和提取日志內(nèi)容中的標簽,這些提取的標簽可以用于標簽過濾表達式進行過濾,或者用于指標聚合。

          提取的標簽鍵將由解析器進行自動格式化,以遵循 Prometheus 指標名稱的約定(它們只能包含 ASCII 字母和數(shù)字,以及下劃線和冒號,不能以數(shù)字開頭)。

          例如下面的日志經(jīng)過管道 | json 將產(chǎn)生以下 Map 數(shù)據(jù):

          "a.b": { "c""d" }, "e""f" }

          ->

          {a_b_c="d", e="f"}

          在出現(xiàn)錯誤的情況下,例如,如果該行不是預(yù)期的格式,該日志行不會被過濾,而是會被添加一個新的 __error__ 標簽。

          需要注意的是如果一個提取的標簽鍵名已經(jīng)存在于原始日志流中,那么提取的標簽鍵將以 _extracted 作為后綴,以區(qū)分兩個標簽,你可以使用一個標簽格式化表達式來強行覆蓋原始標簽,但是如果一個提取的鍵出現(xiàn)了兩次,那么只有最新的標簽值會被保留。

          目前支持 jsonlogfmtpatternregexpunpack 這幾種解析器。

          我們應(yīng)該盡可能使用 jsonlogfmt 等預(yù)定義的解析器,這會更加容易,而當日志行結(jié)構(gòu)異常時,可以使用 regexp,可以在同一日志管道中使用多個解析器,這在你解析復(fù)雜日志時很有用。

          JSON

          json 解析器有兩種模式運行。

          • 如果日志行是一個有效的 json 文檔,在你的管道中添加 | json 將提取所有 json 屬性作為標簽,嵌套的屬性會使用 _ 分隔符被平鋪到標簽鍵中。

            注意:數(shù)組會被忽略。

            例如,使用 json 解析器從以下文件內(nèi)容中提取標簽。

            {
              "protocol""HTTP/2.0",
              "servers": ["129.0.1.1""10.2.1.3"],
              "request": {
                "time""6.032",
                "method""GET",
                "host""foo.grafana.net",
                "size""55",
                "headers": {
                  "Accept""*/*",
                  "User-Agent""curl/7.68.0"
                }
              },
              "response": {
                "status"401,
                "size""228",
                "latency_seconds""6.031"
              }
            }

            可以得到如下所示的標簽列表:

            "protocol" => "HTTP/2.0"
            "request_time" => "6.032"
            "request_method" => "GET"
            "request_host" => "foo.grafana.net"
            "request_size" => "55"
            "response_status" => "401"
            "response_size" => "228"
            "response_latency_seconds" => "6.031"
            1. 沒有參數(shù)。
          • 在你的管道中使用 |json label="expression", another="expression" 將只提取指定的 json 字段為標簽,你可以用這種方式指定一個或多個表達式,與 label_format 相同,所有表達式必須加引號。

            當前僅支持字段訪問(my.field, my["field"])和數(shù)組訪問(list[0]),以及任何級別嵌套中的這些組合(my.list[0]["field"])。

            例如,|json first_server="servers[0]", ua="request.headers[\"User-Agent\"] 將從以下日志文件中提取標簽:

            {
              "protocol""HTTP/2.0",
              "servers": ["129.0.1.1""10.2.1.3"],
              "request": {
                "time""6.032",
                "method""GET",
                "host""foo.grafana.net",
                "size""55",
                "headers": {
                  "Accept""*/*",
                  "User-Agent""curl/7.68.0"
                }
              },
              "response": {
                "status"401,
                "size""228",
                "latency_seconds""6.031"
              }
            }

            提取的標簽列表為:

            "first_server" => "129.0.1.1"
            "ua" => "curl/7.68.0"

            如果表達式返回一個數(shù)組或?qū)ο螅鼘⒁?json 格式分配給標簽。例如,|json server_list="services", headers="request.headers 將提取到如下標簽:

            "server_list" => `["129.0.1.1","10.2.1.3"]`
            "headers" => `{"Accept": "*/*", "User-Agent": "curl/7.68.0"}`
            1. 帶參數(shù)的

          logfmt

          logfmt 解析器可以通過使用 | logfmt 來添加,它將從 logfmt 格式的日志行中提前所有的鍵和值。

          例如,下面的日志行數(shù)據(jù):

          at=info method=GET path=/ host=grafana.net fwd="124.133.124.161" service=8ms status=200

          將提取得到如下所示的標簽:

          "at" => "info"
          "method" => "GET"
          "path" => "/"
          "host" => "grafana.net"
          "fwd" => "124.133.124.161"
          "service" => "8ms"
          "status" => "200"

          regexp

          logfmtjson(它們隱式提取所有值且不需要參數(shù))不同,regexp 解析器采用單個參數(shù) | regexp "<re>" 的格式,其參數(shù)是使用 Golang RE2 語法的正則表達式。

          正則表達式必須包含至少一個命名的子匹配(例如(?P<name>re)),每個子匹配項都會提取一個不同的標簽。

          例如,解析器 | regexp "(?P<method>\\w+) (?P<path>[\\w|/]+) \\((?P<status>\\d+?)\\) (?P<duration>.*)" 將從以下行中提取標簽:

          POST /api/prom/api/v1/query_range (200) 1.5s

          提取的標簽為:

          "method" => "POST"
          "path" => "/api/prom/api/v1/query_range"
          "status" => "200"
          "duration" => "1.5s"

          pattern

          模式解析器允許通過定義模式表達式(| pattern "<pattern-expression>")從日志行中顯式提取字段,該表達式與日志行的結(jié)構(gòu)相匹配。

          比如我們來考慮下面的 NGINX 日志行數(shù)據(jù):

          0.191.12.2 - - [10/Jun/2021:09:14:29 +0000] "GET /api/plugins/versioncheck HTTP/1.1" 200 2 "-" "Go-http-client/2.0" "13.76.247.102, 34.120.177.193" "TLSv1.2" "US" ""

          該日志行可以用下面的表達式來解析:

          <ip> - - <_> "<method> <uri> <_>" <status> <size> <_> "<agent>" <_>

          解析后可以提取出下面的這些屬性:

          "ip" => "0.191.12.2"
          "method" => "GET"
          "uri" => "/api/plugins/versioncheck"
          "status" => "200"
          "size" => "2"
          "agent" => "Go-http-client/2.0"

          模式表達式的捕獲是由 <> 字符分隔的字段名稱,比如 <example> 定義了字段名稱為 example,未命名的 capture 顯示為 <_>,未命名的 capture 會跳過匹配的內(nèi)容。默認情況下,模式表達式錨定在日志行的開頭,可以在表達式的開頭使用 <_> 將表達式錨定在開頭。

          比如我們查看下面的日志行數(shù)據(jù):

          level=debug ts=2021-06-10T09:24:13.472094048Z caller=logging.go:66 traceID=0568b66ad2d9294c msg="POST /loki/api/v1/push (204) 16.652862ms"

          我們?nèi)绻幌Mテヅ?msg=" 的內(nèi)容,我們可以使用下面的表達式來進行匹配:

          <_> msg="<method> <path> (<status>) <latency>"

          前面大部分日志數(shù)據(jù)我們不需要,只需要使用 <_> 進行占位即可,明顯可以看出這種方式比正則表達式要簡單得多。

          unpack

          unpack 解析器將解析 json 日志行,并通過打包階段解開所有嵌入的標簽,一個特殊的屬性 _entry 也將被用來替換原來的日志行。

          例如,使用 | unpack 解析器,可以得到如下所示的標簽:

          {
            "container""myapp",
            "pod""pod-3223f",
            "_entry""original log message"
          }

          允許提取 containerpod 標簽以及原始日志信息作為新的日志行。

          如果原始嵌入的日志行是特定的格式,你可以將 unpack 與 json 解析器(或其他解析器)相結(jié)合使用。

          標簽過濾表達式

          標簽過濾表達式允許使用其原始和提取的標簽來過濾日志行,它可以包含多個謂詞。

          一個謂詞包含一個標簽標識符、操作符和用于比較標簽的值。

          例如 cluster="namespace" 其中的 cluster 是標簽標識符,操作符是 =,值是"namespace"

          LogQL 支持從查詢輸入中自動推斷出的多種值類型:

          • String(字符串)用雙引號或反引號引起來,例如"200"或`us-central1`。
          • Duration(時間)是一串十進制數(shù)字,每個數(shù)字都有可選的數(shù)和單位后綴,如 "300ms""1.5h""2h45m",有效的時間單位是 "ns""us"(或 "μs")、"ms""s""m""h"
          • Number(數(shù)字)是浮點數(shù)(64 位),如 250、89.923。
          • Bytes(字節(jié))是一串十進制數(shù)字,每個數(shù)字都有可選的數(shù)和單位后綴,如 "42MB""1.5Kib""20b",有效的字節(jié)單位是 "b""kib""kb""mib""mb""gib""gb""tib""tb""pib""bb""eb"

          字符串類型的工作方式與 Prometheus 標簽匹配器在日志流選擇器中使用的方式完全一樣,這意味著你可以使用同樣的操作符(=!==~!~)。

          使用 Duration、Number 和 Bytes 將在比較前轉(zhuǎn)換標簽值,并支持以下比較器。

          • === 相等比較
          • != 不等于比較
          • >>= 用于大于或大于等于比較
          • <<= 用于小于或小于等于比較

          例如 logfmt | duration > 1m and bytes_consumed > 20MB 過濾表達式。

          如果標簽值的轉(zhuǎn)換失敗,日志行就不會被過濾,而會添加一個 __error__ 標簽。你可以使用 andor 來連接多個謂詞,它們分別表示的二進制操作,and 可以用逗號、空格或其他管道來表示,標簽過濾器可以放在日志管道的任何地方。

          以下所有的表達式都是等價的:

          | duration >= 20ms or size == 20kb and method!~"2.."
          | duration >= 20ms or size == 20kb | method!~"2.."
          | duration >= 20ms or size == 20kb,method!~"2.."
          | duration >= 20ms or size == 20kb method!~"2.."

          默認情況下,多個謂詞的優(yōu)先級是從右到左,你可以用圓括號包裝謂詞,強制使用從左到右的不同優(yōu)先級。

          例如,以下內(nèi)容是等價的:

          | duration >= 20ms or method="GET" and size <= 20KB
          | ((duration >= 20ms or method="GET") and size <= 20KB)

          它將首先評估 duration>=20ms or method="GET",要首先評估 method="GET" and size<=20KB,請確保使用適當?shù)睦ㄌ枺缦滤尽?/p>

          | duration >= 20ms or (method="GET" and size <= 20KB)

          日志行格式表達式

          日志行格式化表達式可以通過使用 Golang 的 text/template 模板格式重寫日志行的內(nèi)容,它需要一個字符串參數(shù) | line_format "{{.label_name}}" 作為模板格式,所有的標簽都是注入模板的變量,可以用 {{.label_name}} 的符號來使用。

          例如,下面的表達式:

          {container="frontend"} | logfmt | line_format "{{.query}} {{.duration}}"

          將提取并重寫日志行,只包含 query 和請求的 duration。你可以為模板使用雙引號字符串或反引號 `{{.label_name}}` 來避免轉(zhuǎn)義特殊字符。

          此外 line_format 也支持數(shù)學(xué)函數(shù),例如:

          如果我們有以下標簽 ip=1.1.1.1, status=200duration=3000(ms), 我們可以用 duration 除以 1000 得到以秒為單位的值:

          {container="frontend"} | logfmt | line_format "{{.ip}} {{.status}} {{div .duration 1000}}"

          上面的查詢將得到的日志行內(nèi)容為1.1.1.1 200 3

          標簽格式表達式

          | label_format 表達式可以重命名、修改或添加標簽,它以逗號分隔的操作列表作為參數(shù),可以同時進行多個操作。

          當兩邊都是標簽標識符時,例如 dst=src,該操作將把 src 標簽重命名為 dst

          左邊也可以是一個模板字符串,例如 dst="{{.status}} {{.query}}",在這種情況下,dst 標簽值會被 Golang 模板執(zhí)行結(jié)果所取代,這與 | line_format 表達式是同一個模板引擎,這意味著標簽可以作為變量使用,也可以使用同樣的函數(shù)列表。

          在上面兩種情況下,如果目標標簽不存在,那么就會創(chuàng)建一個新的標簽。

          重命名形式 dst=src 會在將 src 標簽重新映射到 dst 標簽后將其刪除,然而,模板形式將保留引用的標簽,例如 dst="{{.src}}" 的結(jié)果是 dstsrc 都有相同的值。

          一個標簽名稱在每個表達式中只能出現(xiàn)一次,這意味著 | label_format foo=bar,foo="new" 是不允許的,但你可以使用兩個表達式來達到預(yù)期效果,比如 | label_format foo=bar | label_format foo="new"

          日志度量

          LogQL 同樣支持通過函數(shù)方式將日志流進行度量,通常我們可以用它來計算消息的錯誤率或者排序一段時間內(nèi)的應(yīng)用日志輸出 Top N。

          區(qū)間向量

          LogQL 同樣也支持有限的區(qū)間向量度量語句,使用方式和 PromQL 類似,常用函數(shù)主要是如下 4 個:

          • rate: 計算每秒的日志條目
          • count_over_time: 對指定范圍內(nèi)的每個日志流的條目進行計數(shù)
          • bytes_rate: 計算日志流每秒的字節(jié)數(shù)
          • bytes_over_time: 對指定范圍內(nèi)的每個日志流的使用的字節(jié)數(shù)

          比如計算 nginx 的 qps:

          rate({filename="/var/log/nginx/access.log"}[5m]))

          計算 kernel 過去 5 分鐘發(fā)生 oom 的次數(shù):

          count_over_time({filename="/var/log/message"} |~ "oom_kill_process" [5m]))

          聚合函數(shù)

          LogQL 也支持聚合運算,我們可用它來聚合單個向量內(nèi)的元素,從而產(chǎn)生一個具有較少元素的新向量,當前支持的聚合函數(shù)如下:

          • sum:求和
          • min:最小值
          • max:最大值
          • avg:平均值
          • stddev:標準差
          • stdvar:標準方差
          • count:計數(shù)
          • bottomk:最小的 k 個元素
          • topk:最大的 k 個元素

          聚合函數(shù)我們可以用如下表達式描述:

          <aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]

          對于需要對標簽進行分組時,我們可以用 without 或者 by 來區(qū)分。比如計算 nginx 的 qps,并按照 pod 來分組:

          sum(rate({filename="/var/log/nginx/access.log"}[5m])) by (pod)

          只有在使用 bottomktopk 函數(shù)時,我們可以對函數(shù)輸入相關(guān)的參數(shù)。比如計算 nginx 的 qps 最大的前 5 個,并按照 pod 來分組:

          topk(5,sum(rate({filename="/var/log/nginx/access.log"}[5m])) by (pod)))

          二元運算

          數(shù)學(xué)計算

          Loki 存的是日志,都是文本,怎么計算呢?顯然 LogQL 中的數(shù)學(xué)運算是面向區(qū)間向量操作的,LogQL 中的支持的二進制運算符如下:

          • +:加法
          • -:減法
          • *:乘法
          • /:除法
          • %:求模
          • ^:求冪

          比如我們要找到某個業(yè)務(wù)日志里面的錯誤率,就可以按照如下方式計算:

          sum(rate({app="foo", level="error"}[1m])) / sum(rate({app="foo"}[1m]))

          邏輯運算

          集合運算僅在區(qū)間向量范圍內(nèi)有效,當前支持

          • and:并且
          • or:或者
          • unless:排除

          比如:

          rate({app=~"foo|bar"}[1m]) and rate({app="bar"}[1m])

          比較運算

          LogQL 支持的比較運算符和 PromQL 一樣,包括:

          • ==:等于
          • !=:不等于
          • >:大于
          • >=: 大于或等于
          • <:小于
          • <=: 小于或等于

          通常我們使用區(qū)間向量計算后會做一個閾值的比較,這對應(yīng)告警是非常有用的,比如統(tǒng)計 5 分鐘內(nèi) error 級別日志條目大于 10 的情況:

          count_over_time({app="foo", level="error"}[5m]) > 10

          我們也可以通過布爾計算來表達,比如統(tǒng)計 5 分鐘內(nèi) error 級別日志條目大于 10 為真,反正則為假:

          count_over_time({app="foo", level="error"}[5m]) > bool 10

          注釋

          LogQL 查詢可以使用 # 字符進行注釋,例如:

          {app="foo"} # anything that comes after will not be interpreted in your query

          對于多行 LogQL 查詢,可以使用 # 排除整個或部分行:

          {app="foo"}
          | json
          # this line will be ignored
          | bar="baz" # this checks if bar = "baz"

          查詢示例

          這里我們部署一個示例應(yīng)用,該應(yīng)用程序是一個偽造的記錄器,它的日志具有 debug、info 和 warning 輸出到 stdout。error 級別的日志將被寫入 stderr,實際的日志消息以 JSON 格式生成,每 500 毫秒將創(chuàng)建一條新的日志消息。日志消息格式如下所示:

          {
              "app":"The fanciest app of mankind",
              "executable":"fake-logger",
              "is_even"true,
              "level":"debug",
              "msg":"This is a debug message. Hope you'll catch the bug",
              "time":"2022-04-04T13:41:50+02:00",
              "version":"1.0.0"
          }

          使用下面的命令來創(chuàng)建示例應(yīng)用:

          cat <<EOF | kubectl apply -f -
          apiVersion: apps/v1
          kind: Deployment
          metadata:
           labels:
            app: fake-logger
            environment: development
           name: fake-logger
          spec:
           selector:
            matchLabels:
             app: fake-logger
             environment: development
           template:
            metadata:
             labels:
              app: fake-logger
              environment: development
            spec:
             containers:
             - image: thorstenhans/fake-logger:0.0.2
               name: fake-logger
               resources:
                requests:
                 cpu: 10m
                 memory: 32Mi
                limits:
                 cpu: 10m
                 memory: 32Mi
          EOF

          我們可以使用 {app="fake-logger"} 在 Grafana 中查詢到該應(yīng)用的日志流數(shù)據(jù)。

          由于我們該示例應(yīng)用的日志是 JSON 形式的,我們可以采用 JSON 解析器來解析日志,表達式為 {app="fake-logger"} | json,如下所示。

          使用 JSON 解析器解析日志后可以看到 Grafana 提供的面板會根據(jù) level 的值使用不同的顏色進行區(qū)分,而且現(xiàn)在我們?nèi)罩镜膶傩砸脖惶砑拥搅?Log 的標簽中去了。

          現(xiàn)在 JSON 中的數(shù)據(jù)變成了日志標簽我們自然就可以使用這些標簽來過濾日志數(shù)據(jù)了,比如我們要過濾 level=error 的日志,只使用表達式 {app="fake-logger"} | json | level="error" 即可實現(xiàn)。

          此外我們還可以根據(jù)我們的需求去格式化輸出日志,使用 line_format 即可實現(xiàn),比如我們這里使用查詢語句 {app="fake-logger"} | json |is_even="true" | line_format "在 {{.time}} 于 {{.level}}@{{.pod}} Pod中產(chǎn)生了日志 {{.msg}}" 來格式化日志輸出

          監(jiān)控大盤

          這里我們以監(jiān)控 Kubernetes 的事件為例進行說明。首先需要安裝 [kubernetes-event-exporter],地址  https://github.com/opsgenie/kubernetes-event-exporter/tree/master/deploy,kubernetes-event-exporter 日志會打印到 stdout,然后我們的 promtail 會將日志上傳到 Loki。

          然后導(dǎo)入 https://grafana.com/grafana/dashboards/14003 這個 Dashboard 即可,不過需要注意修改每個圖表中的過濾標簽為 job="monitoring/event-exporter"

          修改后正常就可以在 Dashboard 中看到集群中的相關(guān)事件信息了,不過建議用記錄規(guī)則去替換面板中的查詢語句。

          建議

          1. 盡量使用靜態(tài)標簽,開銷更小,通常日志在發(fā)送到 Loki 之前注入 label,推薦的靜態(tài)標簽包含:
          • 宿主機:kubernetes/hosts
          • 應(yīng)用名:kubernetes/labels/app_kubernetes_io/name
          • 組件名:kubernetes/labels/name
          • 命名空間:kubernetes/namespace
          • 其他靜態(tài)標簽,如環(huán)境、版本等
          1. 謹慎使用動態(tài)標簽。過多的標簽組合會造成大量的流,它會讓 Loki 存儲大量的索引和小塊的對象文件。這些都會顯著消耗 Loki 的查詢性能。為避免這些問題,在你知道需要之前不要添加標簽。Loki 的優(yōu)勢在于并行查詢,使用過濾器表達式(label="text", |~ "regex", ...)來查詢?nèi)罩緯行В⑶宜俣纫埠芸臁?img class="rich_pages wxw-img" data-ratio="0.4899095337508699" src="https://filescdn.proginn.com/8123cc340e0640e7569a7d80b02c128b/cb17a1b1e59b10b67effd07c2a9ed739.webp" data-type="png" data-w="2874" style="display: block;margin: 0 auto;max-width: 100%;border-radius: 4px;margin-bottom: 5px;">
          2. 有界的標簽值范圍,作為 Loki 的用戶或操作員,我們的目標應(yīng)該是使用盡可能少的標簽來存儲你的日志。這意味著,更少的標簽帶來更小的索引,從而導(dǎo)致更好的性能,所以我們在添加標簽之前一定要三思而行。
          3. 配置緩存,Loki 可以為多個組件配置緩存, 可以選擇 redis 或者 memcached,這可以顯著提高性能。
          4. 合理使用 LogQL 語法,可大幅提高查詢效率。Label matchers(標簽匹配器)是你的第一道防線,是大幅減少你搜索的日志數(shù)量(例如,從100TB到1TB)的最好方法。當然,這意味著你需要在日志采集端上有良好的標簽定義規(guī)范。


          瀏覽 90
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉之大香蕉之国产沙发 | 日本乱伦A片| aaa国产免费 | 久久久久久久久久久熟女爽 | 国产精品国产精品国产 |