菜单
开源

LogCLI 教程

LogCLI 教程将引导您学习以下概念

  • 查询日志
  • 对 Loki 实例执行元查询
  • 对静态日志文件执行查询

前提条件

在开始之前,您需要具备以下条件

  • Docker
  • Docker-compose
  • LogCLI 已安装在您的机器上(参见 LogCLI 安装

提示

此外,您可以在我们的交互式学习环境中尝试此示例:LogCLI 教程

这是一个已安装所有依赖项的完整配置环境。

Interactive

Grafana Killercoda 仓库中提供反馈、报告错误和提出问题。

场景

您是一家新物流公司的站点经理。该公司使用结构化日志来跟踪发送和接收的每批货物。载荷格式如下所示

json
{"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 中。您的任务是使用 LogCLI 监控日志并生成一份关于货物整体健康状况的报告。

设置

首先,我们需要克隆 Alloy Scenario 仓库并启动 mail-house 示例

  1. 克隆仓库
    bash
    git clone https://github.com/grafana/alloy-scenarios.git
  2. 启动 mail-house 示例
    bash
    docker compose -f alloy-scenarios/mail-house/docker-compose.yml up -d

这将启动 mail-house 示例并将 Loki 实例暴露在 https://:3100。我们还包含了一个 Grafana 实例,用于验证 LogCLI 结果,可通过 https://:3000 访问。

将 LogCLI 连接到 Loki

要将 LogCLI 连接到 Loki 实例,您需要设置 LOKI_ADDR 环境变量

提示

如果您将此示例针对您自己的 Loki 实例运行并已配置身份验证,您还需要设置 LOKI_USERNAMELOKI_PASSWORD 环境变量。

bash
export LOKI_ADDR=https://:3100

现在,让我们通过运行以下命令来验证连接

bash
logcli labels

这应该会返回类似以下的输出

console
https://:3100/loki/api/v1/labels?end=1732282703894072000&start=1732279103894072000
package_size
service_name
state

这确认 LogCLI 已连接到 Loki 实例,我们现在知道日志包含以下标签:package_sizeservice_namestate。让我们对 Loki 运行一些查询,以便更好地了解我们的包裹物流。

查询日志

作为物流公司角色的一部分,我们需要生成一份关于货物整体健康状况的报告。不幸的是,我们只能访问控制台,无法使用 Grafana 来可视化数据。我们可以使用 LogCLI 来查询日志并生成报告。

查找所有关键包裹

要查找最近一小时内的所有关键包裹(默认回溯时间),我们可以运行以下查询

bash
logcli query '{service_name="Delivery World"} | package_status="critical"'

这将返回所有 service_nameDelivery Worldpackage_statuscritical 的日志。输出将类似于以下内容

console
https://:3100/loki/api/v1/query_range?direction=BACKWARD&end=1732617594381712000&limit=30&query=%7Bservice_name%3D%22Delivery+World%22%7D+%7C+package_status%3D%22critical%22&start=1732613994381712000
Common labels: {package_status="critical", service_name="Delivery World"}
2024-11-26T10:39:52Z {package_id="PKG79755", package_size="Small", state="Texas"}       {"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_id="PKG34018", package_size="Large", state="Illinois"}    {"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"}}

假设我们要回溯查看最近 24 小时的日志,我们可以使用 --since 标志来指定时间范围

bash
logcli query --since 24h '{service_name="Delivery World"} | package_status="critical"' 

这将查询最近 24 小时内 package_statuscritical 的所有日志。但它不会返回所有日志,只会返回前 30 条日志。我们可以使用 --limit 标志来指定返回的日志数量

bash
logcli query --since 24h --limit 100 '{service_name="Delivery World"} | package_status="critical"' 

指标查询

我们还可以使用 LogCLI 基于指标来查询日志。例如,作为站点报告的一部分,我们想计算过去 24 小时内每隔 1 小时从加州发出的包裹总数。我们可以使用以下查询

bash
logcli query --since 24h 'sum(count_over_time({state="California"}[1h]))'

这将返回一个 JSON 对象,其中包含时间戳列表(Unix 格式)以及每隔 1 小时从加州发出的包裹数量。由于我们汇总了随时间变化的日志计数,我们将看到日志总数随时间稳定增长。输出将类似于以下内容

console
[
  {
    "metric": {},
    "values": [
      [
        1733913765,
        "46"
      ],
      [
        1733914110,
        "114"
      ],
      [
        1733914455,
        "179"
      ],
      [
        1733914800,
        "250"
      ],
      [
        1733915145,
        "318"
      ],
      [
        1733915490,
        "392"
      ],
      [
        1733915835,
        "396"
      ]
    ]
  }
]

我们可以更进一步,根据 package_type 标签过滤日志。例如,我们可以计算过去 24 小时内每隔 1 小时从加州发出的文档数量

bash
logcli query --since 24h  'sum(count_over_time({state="California"}| json | package_type= "Documents" [1h]))'

这将返回一个与上述类似的 JSON 对象,但仅显示过去 24 小时内每隔 1 小时从加州发出的文档数量趋势。

即时指标查询

即时指标查询是指标查询的一个子集,它返回特定时间点指标的值。这对于快速了解存储日志的聚合状态非常有用。

例如,我们可以使用以下查询来获取过去 5 分钟内从加州发出的包裹数量

bash
logcli instant-query 'sum(count_over_time({state="California"}[5m]))'

这将返回一个类似于以下内容的结果

console
[
  {
    "metric": {},
    "value": [
      1732702998.725,
      "58"
    ]
  }
]

将查询结果写入文件

LogCLI 的另一个有用功能是将查询结果写入文件。这对于下载我们的库存报告结果非常有用。

首先,我们需要创建一个目录来存储日志

bash
mkdir -p ./inventory

接下来,我们可以运行以下查询将日志写入 ./inventory 目录

bash
  logcli query \
     --timezone=UTC \
     --output=jsonl \
     --parallel-duration="12h" \
     --parallel-max-workers="4" \
     --part-path-prefix="./inventory/inv" \
     --since=24h \
     '{service_name="Delivery World"}'

这将把过去 24 小时内 service_nameDelivery World 的所有日志写入 ./inventory 目录。日志将分成两个文件,每个文件包含 12 小时的日志。请注意,我们无需指定 --limit,因为该标志会被 --parallel-duration 标志覆盖。

元查询

作为站点经理,保持良好数据卫生并确保 Loki 高效运行至关重要。理解日志中的标签和日志量在此过程中起着关键作用。除了查询日志,LogCLI 还支持对您的 Loki 实例进行元查询。元查询不返回日志数据,但提供有关日志结构和查询性能的洞察。以下示例演示了我们在内部运行的一些核心元查询,以更好地了解 Loki 实例的运行情况。

检查序列基数

保持 Loki 健康最重要的方面之一是监控序列基数。这是日志中唯一序列的数量。高序列基数可能导致性能问题和存储成本增加。我们可以使用 LogCLI 来检查日志的序列基数。

首先,让我们打印日志中有多少个唯一序列

bash
logcli series '{}'

这将返回日志中所有唯一序列的列表。输出将类似于以下内容

console
{package_size="Small", service_name="Delivery World", state="Florida"}
{package_size="Medium", service_name="Delivery World", state="Florida"}
{package_size="Small", service_name="Delivery World", state="California"}
{package_size="Large", service_name="Delivery World", state="New York"}
{package_size="Small", service_name="Delivery World", state="Illinois"}
{package_size="Large", service_name="Delivery World", state="Florida"}
{package_size="Medium", service_name="Delivery World", state="Illinois"}
{package_size="Large", service_name="Delivery World", state="Texas"}
{package_size="Medium", service_name="Delivery World", state="California"}
{package_size="Medium", service_name="Delivery World", state="Texas"}
{package_size="Small", service_name="Delivery World", state="Texas"}
{package_size="Large", service_name="Delivery World", state="Illinois"}
{package_size="Small", service_name="Delivery World", state="New York"}
{package_size="Medium", service_name="Delivery World", state="New York"}
{package_size="Large", service_name="Delivery World", state="California"}

我们可以通过添加 --analyze-labels 进一步改进此查询

bash
logcli series '{}' --analyze-labels

这将返回日志中每个标签的唯一值摘要。输出将类似于以下内容。

console
Label Name    Unique Values  Found In Streams
state         5              15
package_size  3              15
service_name  1              15

检测到的字段

LogCLI 的另一个有用功能是检测日志中的字段。这对于理解日志结构和存在的键非常有用。这使我们能够检测可以提升为标签或结构化元数据的键。

bash
logcli detected-fields --since 24h '{service_name="Delivery World"}'

这将返回日志中检测到的所有键列表。输出将类似于以下内容。

console
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 基数高,且每个日志条目唯一,这使得它成为结构化元数据的良好候选,因为我们可能需要直接查询它。另一方面,Package size 基数低,这使得它成为标签的良好候选。

检查查询性能

注意

LogCLI 只能返回涉及对象存储的查询统计信息。在此示例中,我们强制 Loki ingesters 每 5 分钟刷新一次 chunk,这不建议用于生产环境。运行此演示时,如果您没有看到任何统计信息返回,请在几分钟后再次尝试运行该命令。

首先,让我们打印日志的查询性能

这将提供一个 JSON 对象,其中包含查询数据量的统计信息。输出将类似于以下内容。

bash
logcli stats --since 24h '{service_name="Delivery World"}'

这将返回查询的总字节数、查询的 chunk 数、查询的 stream 数和查询的条目数。如果我们通过指定次要标签来缩小查询范围,我们可以看到查询的性能

console
https://:3100/loki/api/v1/index/stats?end=1732639430272850000&query=%7Bservice_name%3D%22Delivery+World%22%7D&start=1732553030272850000
{
  bytes: 12MB
  chunks: 63
  streams: 15
  entries: 29529
}

这将返回 service_nameDelivery Worldpackage_sizeLarge 的日志统计信息。输出将类似于以下内容。

bash
logcli stats --since 24h '{service_name="Delivery World", package_size="Large"}'

如您所见,通过缩小查询范围,我们接触到的 stream 和条目少得多。

console
{
  bytes: 4.2MB
  chunks: 22
  streams: 5
  entries: 10198
}

检查日志量

我们可能还想检查日志中的日志量。这对于了解摄取到 Loki 中的数据量非常有用。我们可以使用 LogCLI 来检查日志中的日志量。

这将返回过去 24 小时内标签 Delivery World 的总摄取日志数。输出将类似于以下内容

bash
logcli volume --since 24h '{service_name="Delivery World"}'

结果包括时间戳和总摄取日志数。

console
[
  {
    "metric": {
      "service_name": "Delivery World"
    },
    "value": [
      1732640292.354,
      "11669299"
    ]
  }
]

我们还可以使用 volume_range 返回随时间变化的日志量

这将提供一个 JSON 对象,其中包含过去 24 小时内标签 Delivery World 的日志量。--step 将日志量按 1 小时分桶聚合。请注意,如果特定小时没有日志,则该小时的日志量将不返回任何值。

bash
logcli volume_range --since 24h --step=1h '{service_name="Delivery World"}'

我们甚至可以根据特定标签值将日志量聚合到桶中

这将提供一个类似的 JSON 对象,但会根据 state 标签值将日志量聚合到桶中。

bash
logcli volume_range --since 24h --step=1h --targetLabels='state' '{service_name="Delivery World"}' 

除了从 Loki 查询日志外,LogCLI 还支持查询静态日志文件。这对于查询未存储在 Loki 中的日志非常有用。在本教程前面,我们将日志存储在 ./inventory 目录中。让我们运行一个类似的查询,但将其通过管道输出到日志文件

对静态日志文件执行查询

接下来让我们对静态日志文件运行查询

bash
  logcli query \
     --timezone=UTC \
     --parallel-duration="12h" \
     --parallel-max-workers="4" \
     --part-path-prefix="./inventory/inv" \
     --since=24h \
     --merge-parts \
     --output=raw \
     '{service_name="Delivery World"}' > ./inventory/complete.log

请注意,由于我们查询的是静态日志文件,因此标签不会自动检测

bash
cat ./inventory/complete.log |  logcli --stdin query '{service_name="Delivery World"} | json | package_status="critical"'

{service_name="Delivery World"} 在这种情况下是可选的,但为了清晰起见建议使用。

  • 需要 json 来将日志文件解析为 JSON。这使我们能够提取 package_status 字段。
  • 例如,假设我们尝试不带 json 过滤器的查询日志文件

这将不返回任何结果,因为未检测到 package_status 字段。

bash
cat ./inventory/complete.log | logcli --stdin query '{service_name="Delivery World"} | package_status="critical"'

结论

在本教程中,作为物流公司的站点经理,我们成功使用了 LogCLI 来查询日志并生成了一份关于货物整体健康状况的报告。我们还使用元查询来更好地了解数据卫生和查询性能。LogCLI 是一个强大的工具,可用于理解您的日志以及它们在 Loki 中的存储方式,随着您不断扩展解决方案,请记住利用 LogCLI 来监控基数和查询性能。

此页面是否有帮助?