Grafana Loki LogCLI 实战教程:用命令行查询日志、执行元查询与分析静态日志文件

Grafana Loki LogCLI 实战教程:用命令行查询日志、执行元查询与分析静态日志文件 Grafana Loki LogCLI 实战教程用命令行查询日志、执行元查询与分析静态日志文件【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki本篇教程以 Grafana Loki 的官方 LogCLI 教程docs/sources/query/logcli/logcli-tutorial.md为骨架结合 LogCLI 源码与入门参考文档进行深度扩充。LogCLI 是 Loki 的命令行客户端可以运行 LogQL 查询、对 Loki 实例执行元查询series、stats、volume、detected-fields 等甚至可以直接查询静态日志文件——非常适合在只有控制台、没有 Grafana 可视化面板的环境中完成日志检索、基线与容量评估、数据卫生检查等管理任务。读完本文你将掌握 LogCLI 的安装与连接配置、日志查询与指标查询、基线与性能分析以及离线日志文件查询等完整实战技能。场景设定一家物流公司的包裹日志假设你是一家新成立的物流公司的站点管理员。公司使用结构化日志记录每一件包裹的发出与接收情况日志负载格式如下{timestamp: 2024-11-22T13:22:56.377884, state: New York, city: Buffalo, package_id: PKG34245, package_type: Documents, package_size: Medium, package_status: error, note: Out for delivery, sender: {name: Sender27, address: 144 Elm St, Buffalo, New York}, receiver: {name: Receiver4, address: 260 Cedar Blvd, New York City, New York}}这些日志由 Grafana Alloy 处理在写入 Loki 之前会先抽取标签labels和结构化元数据structured metadata。你的任务是用 LogCLI 监控这些日志并产出一份关于包裹整体健康状况的报告——全程只有一台控制台无法使用 Grafana 可视化。前置条件与环境搭建开始之前你需要准备DockerDocker-compose本机已安装 LogCLI安装方式见下文安装 LogCLI从 Loki releases 页面 中定义了logcli构建目标git clone https://github.com/grafana/loki.git cd loki make logcli可选地把二进制放入$PATHcp cmd/logcli/logcli /usr/local/bin/logcli从源码结构看LogCLI 的入口是 cmd/logcli/main.go它基于 kingpin 框架注册了query、instant-query、labels、series、fmt、stats、volume、volume_range、detected-fields、delete等子命令核心查询逻辑分布在 pkg/logcli 下的query、client、output、print等子包中。启动演示环境克隆 Alloy 场景仓库并启动 mail-house 示例git clone https://github.com/grafana/alloy-scenarios.git docker compose -f alloy-scenarios/mail-house/docker-compose.yml up -d启动后Loki 实例暴露在http://localhost:3100附带一个 Grafana 实例http://localhost:3000用于交叉验证 LogCLI 的结果该示例的 Loki 配置刻意让 ingester 每 5 分钟 flush 一次 chunk生产环境不推荐这样做目的是让stats等统计命令能够命中对象存储稍后你会看到它的影响。连接 LogCLI 与 Loki设置LOKI_ADDR环境变量指向 Loki 实例export LOKI_ADDRhttp://localhost:3100如果连接的是你自己的、配置了认证的 Loki 实例还需要设置LOKI_USERNAME和LOKI_PASSWORDGrafana Cloud 用户则设置为对应的云实例地址与凭据。验证连接logcli labels预期输出类似http://localhost:3100/loki/api/v1/labels?end1732282703894072000start1732279103894072000 package_size service_name state从源码看这些连接参数在 cmd/logcli/main.go#L574-L619 中注册--addr默认http://localhost:3100、--username、--password、--org-id对应X-Scope-OrgID请求头用于绕过认证网关直接请求指定租户数据、--bearer-token、--ca-cert、--tls-skip-verify、--proxy-url、--retries/--min-backoff/--max-backoff等每一项都有对应的LOKI_*环境变量且环境变量优先于命令行参数。labels命令的输出第一行是实际请求的 API URL其余行是该时间窗口内的标签名列表。日志中目前有 3 个标签package_size、service_name、state。下面开始真正的查询。查询日志从筛选关键包裹到趋势统计找出所有关键包裹默认回看窗口是最近 1 小时对应--since1h的默认值见 cmd/logcli/main.go#L711查询service_name为Delivery World且package_status为critical的日志logcli query {service_nameDelivery World} | package_statuscritical输出类似http://localhost:3100/loki/api/v1/query_range?directionBACKWARDend1732617594381712000limit30query%7Bservice_name%3D%22DeliveryWorld%22%7D%7Cpackage_status%3D%22critical%22start1732613994381712000 Common labels: {package_statuscritical, service_nameDelivery World} 2024-11-26T10:39:52Z {package_idPKG79755, package_sizeSmall, stateTexas} {timestamp: 2024-11-26T10:39:52.521602Z, state: Texas, city: Dallas, package_id: PKG79755, package_type: Clothing, package_size: Small, package_status: critical, note: In transit, sender: {name: Sender38, address: 906 Maple Ave, Dallas, Texas}, receiver: {name: Receiver41, address: 455 Pine Rd, Dallas, Texas}} 2024-11-26T10:39:50Z {package_idPKG34018, package_sizeLarge, stateIllinois} {timestamp: 2024-11-26T10:39:50.510841Z, state: Illinois, city: Chicago, package_id: PKG34018, package_type: Clothing, package_size: Large, package_status: critical, note: Delayed due to weather, sender: {name: Sender22, address: 758 Elm St, Chicago, Illinois}, receiver: {name: Receiver10, address: 441 Cedar Blvd, Naperville, Illinois}}要点默认输出模式default为时间戳 该流的标签 原始日志行并附带Common labels所有结果共有的标签等查询元信息可用--quiet/-q抑制--outputraw只输出日志行--outputjsonl输出 Loki API 的 JSON 响应。默认只返回前 30 条--limit30。回看 24 小时logcli query --since 24h {service_nameDelivery World} | package_statuscritical增加返回条数上限logcli query --since 24h --limit 100 {service_nameDelivery World} | package_statuscritical其余常用时间参数--from/--to指定绝对时间范围RFC3339Nano 格式、不带时区后缀--step用于指标查询的分辨率步长--batch控制直到达到 limit 前的每批大小默认 1000在 cmd/logcli/main.go#L716 注册。query命令还支持--tail/-t--follow/-f为别名实时跟踪日志、--forward正向扫描、--no-labels、--exclude-label/--include-label、--colored-output等输出控制。从实现看范围查询会在 pkg/logcli/query/query.go#L139-L211 中按--batch分批循环调用QueryRange以上一批最后一条日志的时间戳作为下一批的起点/终点并处理同时间戳重复条目带来的重叠直到达到 limit每次请求后打印统计信息配合--stats标志。指标查询按 1 小时粒度统计包裹数统计最近 24 小时加州发出的包裹总数按 1 小时间隔logcli query --since 24h sum(count_over_time({stateCalifornia}[1h]))返回一个 JSON 对象包含一组 Unix 时间戳与对应区间的包裹计数。由于是对日志计数做累计求和总数会随时间单调增长[ { metric: {}, values: [ [1733913765, 46], [1733914110, 114], [1733914455, 179], [1733914800, 250], [1733915145, 318], [1733915490, 392], [1733915835, 396] ] } ]query命令支持指标查询但输出的是时间段内的多个数据点类似 Grafana Explore 的 graph 视图。再进一步用json解析器抽取package_type字段并过滤出 Documentslogcli query --since 24h sum(count_over_time({stateCalifornia}| json | package_typeDocuments [1h]))返回结构类似但只展示加州发出 Documents 包裹的 1 小时间隔趋势。即时指标查询只看当前时刻的聚合值即时指标查询instant metric query返回某个特定时间点上指标的值适合快速了解日志的聚合状态。查询最近 5 分钟加州发出的包裹数logcli instant-query sum(count_over_time({stateCalifornia}[5m]))[ { metric: {}, value: [ 1732702998.725, 58 ] } ]注意instant-query相当于 Grafana Explore 的 table 视图只返回最新数据点查询日志行时它没有实用输出应该始终用query命令。即时查询可通过--now指定执行时刻见 cmd/logcli/main.go#L708。把查询结果写入文件并行下载全量日志LogCLI 可以把查询结果写入文件适合下载库存报告等全量数据。先创建目录mkdir -p ./inventory然后使用并行下载参数把Delivery World最近 24 小时的全部日志写入./inventory目录logcli query \ --timezoneUTC \ --outputjsonl \ --parallel-duration12h \ --parallel-max-workers4 \ --part-path-prefix./inventory/inv \ --since24h \ {service_nameDelivery World}日志会被拆成两个文件每个文件包含 12 小时数据。注意指定了--parallel-duration后--limit会被忽略cmd/logcli/main.go#L464-L467 中并行模式下强制把Limit置 0。并行下载的实现要点见 pkg/logcli/query/query.go--parallel-duration把时间范围切分成若干长度相同的 job。以 24 小时、12h 为例会生成 2 个 job。--parallel-max-workers并行 worker 数量为 1 时不启动并行走普通路径。每个 job 通过DoQuery独立执行startWorkers用带缓冲的 channel 分发任务。--part-path-prefix每个 job 的结果保存为前缀_UTC起始_UTC结束.part格式的 part 文件下载过程中文件名带.part后缀完成后去掉。默认情况下已完成 part 文件会跳过不再下载可用--overwrite-completed-parts覆盖。默认按时间倒序BACKWARD下载 part可用--forward改为正向。--merge-parts按顺序读取 part 文件并输出到 stdout边下载边输出读完后默认删除 part 文件--keep-parts可保留它们。元查询理解数据卫生与查询性能作为站点管理员保持数据卫生并确保 Loki 高效运行至关重要。元查询不返回日志数据而是揭示日志的结构与查询性能。以下示例是官方运维中常用的核心元查询。检查序列基数series cardinality序列series是标签组合的集合高序列基数会导致性能下降和存储成本上升。列出日志中全部唯一序列logcli series {}{package_sizeSmall, service_nameDelivery World, stateFlorida} {package_sizeMedium, service_nameDelivery World, stateFlorida} {package_sizeSmall, service_nameDelivery World, stateCalifornia} {package_sizeLarge, service_nameDelivery World, stateNew York} {package_sizeSmall, service_nameDelivery World, stateIllinois} {package_sizeLarge, service_nameDelivery World, stateFlorida} {package_sizeMedium, service_nameDelivery World, stateIllinois} {package_sizeLarge, service_nameDelivery World, stateTexas} {package_sizeMedium, service_nameDelivery World, stateCalifornia} {package_sizeMedium, service_nameDelivery World, stateTexas} {package_sizeSmall, service_nameDelivery World, stateTexas} {package_sizeLarge, service_nameDelivery World, stateIllinois} {package_sizeSmall, service_nameDelivery World, stateNew York} {package_sizeMedium, service_nameDelivery World, stateNew York} {package_sizeLarge, service_nameDelivery World, stateCalifornia}空匹配器{}返回所有流。加上--analyze-labels汇总每个标签的唯一值数量logcli series {} --analyze-labelsLabel Name Unique Values Found In Streams state 5 15 package_size 3 15 service_name 1 15从实现看pkg/logcli/seriesquery/series.go#L36-L71--analyze-labels会遍历每个流统计每个标签名出现的流数量与唯一值集合按唯一值数量降序用 tabwriter 打印表格并额外输出Total Streams与Unique Labels。这是定位高基数标签的利器。检测字段Detected fields判断标签 vs 结构化元数据detected-fields用json或logfmt解析器对日志行做字段检测帮你了解日志中存在哪些键从而决定哪些键适合提升为标签、哪些适合保留在结构化元数据中logcli detected-fields --since 24h {service_nameDelivery World}label: city type: string cardinality: 15 label: detected_level type: string cardinality: 3 label: note type: string cardinality: 7 label: package_id type: string cardinality: 994 label: package_size_extracted type: string cardinality: 3 label: package_status type: string cardinality: 4 label: package_type type: string cardinality: 5 label: receiver_address type: string cardinality: 991 label: receiver_name type: string cardinality: 100 label: sender_address type: string cardinality: 991 label: sender_name type: string cardinality: 100 label: state_extracted type: string cardinality: 5 label: timestamp type: string cardinality: 1000现在你能理解为什么package_id放在结构化元数据中、而package_size做成标签了package_id基数高达 994几乎每个日志条目都不同将来可能需要按它精确查询适合作为结构化元数据package_size基数只有 3天然适合做标签。detected-fields默认最多返回 100 个字段--limit、每个子查询处理 1000 行--line-limit可传可选的第二个参数指定单个字段名默认步长--step10s见 cmd/logcli/main.go#L825-L865。检查查询性能stats保持 Loki 健康还要关注查询性能。stats返回查询所触及的数据量统计logcli stats --since 24h {service_nameDelivery World}http://localhost:3100/loki/api/v1/index/stats?end1732639430272850000query%7Bservice_name%3D%22DeliveryWorld%22%7Dstart1732553030272850000 { bytes: 12MB chunks: 63 streams: 15 entries: 29529 }包括查询的字节数、chunk 数、流数与条目数。缩小查询范围追加第二个标签可以对比性能logcli stats --since 24h {service_nameDelivery World, package_sizeLarge}{ bytes: 4.2MB chunks: 22 streams: 5 entries: 10198 }可见收窄标签后触及的流与条目大幅减少。从实现看pkg/logcli/index/stats.go、pkg/logcli/client/client.go#L193-L204stats请求的是 Loki 的/loki/api/v1/index/stats接口返回的IndexStatsResponse包含 bytes、chunks、streams、entries 四个维度。注意stats/volume仅对使用 TSDB 索引格式的 Loki 实例有效且 LogCLI 只能返回触及对象存储的查询统计。本演示为了让统计可见而把 ingester 的 flush 间隔压到 5 分钟生产环境不推荐。如果运行演示时没有看到统计数据等几分钟再执行一次。检查日志量volume 与 volume_range了解正在写入 Loki 的数据量有助于容量规划。查询Delivery World最近 24 小时的日志总量logcli volume --since 24h {service_nameDelivery World}[ { metric: { service_name: Delivery World }, value: [ 1732640292.354, 11669299 ] } ]结果包含时间戳与日志摄入总数。用volume_range查看日志量随时间的变化logcli volume_range --since 24h --step1h {service_nameDelivery World}--step把日志量按 1 小时桶聚合注意某小时如果没有日志该小时不会返回值。还可以按特定标签值分桶聚合logcli volume_range --since 24h --step1h --targetLabelsstate {service_nameDelivery World}volume/volume_range的实现位于 pkg/logcli/index/volume.go底层请求 Loki 的/loki/api/v1/index/volume与/loki/api/v1/index/volume_range接口--targetLabels指定按哪些标签分组聚合cmd/logcli/main.go#L815volume_range的默认--step1hcmd/logcli/main.go#L819。查询静态日志文件LogCLI 还支持直接查询不在 Loki 中的静态日志文件。上一节我们把Delivery World的日志存到了./inventory目录现在用类似命令把结果合并输出到单个文件logcli query \ --timezoneUTC \ --parallel-duration12h \ --parallel-max-workers4 \ --part-path-prefix./inventory/inv \ --since24h \ --merge-parts \ --outputraw \ {service_nameDelivery World} ./inventory/complete.log--merge-parts会按顺序读取 part 文件并输出到 stdout原始日志行模式raw然后通过 shell 重定向写入complete.log。接着对静态文件执行查询cat ./inventory/complete.log | logcli --stdin query {service_nameDelivery World} | json | package_statuscritical注意查询静态日志文件时标签不会自动识别因此{service_nameDelivery World}在这种情况下是可选的前缀为了表达清晰建议保留json是必须的——它把日志行按 JSON 解析从而提取package_status字段。例如省略json过滤器再试cat ./inventory/complete.log | logcli --stdin query {service_nameDelivery World} | package_statuscritical由于没有解析 JSONpackage_status字段无法被检测到查询返回空结果。从实现看--stdin标志会把客户端切换为client.NewFileClient(os.Stdin)cmd/logcli/main.go#L393-L417。其核心机制在 pkg/logcli/client/file.goFileClient为输入注入一个固定的虚拟标签sourcelogcli并用本地logql.Engine直接对文件内容执行 LogQL最大读取 20MB见defaultMaxFileSize。如果查询以|或!开头即省略了流选择器main.go 会自动注入{sourcelogcli}作为流选择器使|error这类省略式查询也能工作。FileClient的SelectLogs会把每行日志按时间顺序BACKWARD 为逆序逐条送入日志管道pipeline匹配处理命中则归入对应流。stats、volume、detected-fields、delete等在文件客户端上返回ErrNotSupported——它们依赖 Loki 的索引能力。常见连接配置速查下表汇总 LogCLI 与 Loki 连接相关的常用参数与对应环境变量全部注册于 cmd/logcli/main.go#L574-L619参数环境变量说明--addrLOKI_ADDRLoki 服务地址默认http://localhost:3100--username/--passwordLOKI_USERNAME/LOKI_PASSWORDHTTP 基本认证凭据--org-idLOKI_ORG_ID为请求添加X-Scope-OrgID头用于指定租户--bearer-token/--bearer-token-fileLOKI_BEARER_TOKEN/LOKI_BEARER_TOKEN_FILEBearer Token 认证--ca-cert/--tls-skip-verifyLOKI_CA_CERT_PATH/LOKI_TLS_SKIP_VERIFYTLS 服务端证书校验--cert/--keyLOKI_CLIENT_CERT_PATH/LOKI_CLIENT_KEY_PATH客户端 mTLS 证书--retries/--min-backoff/--max-backoffLOKI_CLIENT_RETRIES/LOKI_CLIENT_MIN_BACKOFF/LOKI_CLIENT_MAX_BACKOFF查询失败重试策略--proxy-url/--envproxyLOKI_HTTP_PROXY_URL/LOKI_ENV_PROXYHTTP 代理--compressLOKI_HTTP_COMPRESSION请求传输压缩--nocacheLOKI_NO_CACHE添加Cache-Control: no-cache请求头结论在本次教程中作为物流公司的站点管理员我们使用 LogCLI 完成了三件事查询日志并构建包裹健康报告通过元查询理解数据卫生基数、检测字段与查询性能stats、volume以及直接查询静态日志文件。LogCLI 是理解日志内容及其在 Loki 中存储方式的强大工具。随着你的解决方案规模扩大请记得用 LogCLI 持续监控序列基数与查询性能——这往往是 Loki 长期健康运行的关键。更多命令细节可查阅 LogCLI 入门与命令参考命令的全部参数可通过logcli help、logcli help query等查看。【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考