1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Grafana Loki 查詢語言 LogQL 使用

        共 15085字,需瀏覽 31分鐘

         ·

        2022-06-28 21:55

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

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

        日志查詢

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

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

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

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

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

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

        {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 這個詞的日志,然后解析每一行日志提取更多的表達式并進行過濾

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

        Log Stream Selector

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

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

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

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

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

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

        例如:

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

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

        Log Pipeline

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

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

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

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

        日志行過濾表達式

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

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

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

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

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

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

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

        解析器表達式

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

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

        例如下面的日志經過管道 | json 將產生以下 Map 數據:

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

        ->

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

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

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

        目前支持 json、logfmt、pattern、regexpunpack 這幾種解析器。

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

        JSON

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

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

          注意:數組會被忽略。

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

          {
            "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. 沒有參數。
        • 在你的管道中使用 |json label="expression", another="expression" 將只提取指定的 json 字段為標簽,你可以用這種方式指定一個或多個表達式,與 label_format 相同,所有表達式必須加引號。

          當前僅支持字段訪問(my.field, my["field"])和數組訪問(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"

          如果表達式返回一個數組或對象,它將以 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. 帶參數的

        logfmt

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

        例如,下面的日志行數據:

        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(它們隱式提取所有值且不需要參數)不同,regexp 解析器采用單個參數 | regexp "<re>" 的格式,其參數是使用 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>")從日志行中顯式提取字段,該表達式與日志行的結構相匹配。

        比如我們來考慮下面的 NGINX 日志行數據:

        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 會跳過匹配的內容。默認情況下,模式表達式錨定在日志行的開頭,可以在表達式的開頭使用 <_> 將表達式錨定在開頭。

        比如我們查看下面的日志行數據:

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

        我們如果只希望去匹配 msg=" 的內容,我們可以使用下面的表達式來進行匹配:

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

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

        unpack

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

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

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

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

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

        標簽過濾表達式

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

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

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

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

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

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

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

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

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

        如果標簽值的轉換失敗,日志行就不會被過濾,而會添加一個 __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)先級。

        例如,以下內容是等價的:

        | 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,請確保使用適當的括號,如下所示。

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

        日志行格式表達式

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

        例如,下面的表達式:

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

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

        此外 line_format 也支持數學函數,例如:

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

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

        上面的查詢將得到的日志行內容為1.1.1.1 200 3。

        標簽格式表達式

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

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

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

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

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

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

        日志度量

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

        區(qū)間向量

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

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

        比如計算 nginx 的 qps:

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

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

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

        聚合函數

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

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

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

        <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 函數時,我們可以對函數輸入相關的參數。比如計算 nginx 的 qps 最大的前 5 個,并按照 pod 來分組:

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

        二元運算

        數學計算

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

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

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

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

        邏輯運算

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

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

        比如:

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

        比較運算

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

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

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

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

        我們也可以通過布爾計算來表達,比如統(tǒng)計 5 分鐘內 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"

        查詢示例

        這里我們部署一個示例應用,該應用程序是一個偽造的記錄器,它的日志具有 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)建示例應用:

        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 中查詢到該應用的日志流數據。

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

        使用 JSON 解析器解析日志后可以看到 Grafana 提供的面板會根據 level 的值使用不同的顏色進行區(qū)分,而且現(xiàn)在我們日志的屬性也被添加到了 Log 的標簽中去了。

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

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

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

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

        建議

        1. 盡量使用靜態(tài)標簽,開銷更小,通常日志在發(fā)送到 Loki 之前注入 label,推薦的靜態(tài)標簽包含:
        • 宿主機:kubernetes/hosts
        • 應用名: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", ...)來查詢日志會更有效,并且速度也很快。
        2. 有界的標簽值范圍,作為 Loki 的用戶或操作員,我們的目標應該是使用盡可能少的標簽來存儲你的日志。這意味著,更少的標簽帶來更小的索引,從而導致更好的性能,所以我們在添加標簽之前一定要三思而行。
        3. 配置緩存,Loki 可以為多個組件配置緩存, 可以選擇 redis 或者 memcached,這可以顯著提高性能。
        4. 合理使用 LogQL 語法,可大幅提高查詢效率。Label matchers(標簽匹配器)是你的第一道防線,是大幅減少你搜索的日志數量(例如,從100TB到1TB)的最好方法。當然,這意味著你需要在日志采集端上有良好的標簽定義規(guī)范。


        瀏覽 90
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            青草久久久久 | 成人电影999 | 亚洲无码 家庭乱伦 | 大香蕉天天日 | 国产91精品高清一区二区三区 | 色欲插插插 | 国产免费淫秽视频 | 美国三级日本三级人妇www | 国产十大尺度真做无删减电影 | 91无码人妻精品一区二区帝霸网 |