news 2026/9/11 20:59:19

Grafana Loki 日志条目删除(Log Entry Deletion)完整指南:配置、API 与底层原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Grafana Loki 日志条目删除(Log Entry Deletion)完整指南:配置、API 与底层原理

Grafana Loki 日志条目删除(Log Entry Deletion)完整指南:配置、API 与底层原理

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

Grafana Loki 支持按流(stream)、按时间窗口、按可选行过滤器删除日志条目,该能力由 compactor 组件统一承载。本文基于当前仓库的官方文档与源码实现,系统讲解删除功能的前置条件、compactor 配置项、三种deletion_mode语义、删除请求的创建/查询/取消 API 参数,以及删除请求在后端的存储、分片与执行机制,帮助你安全、正确地落地日志删除与合规需求。

功能概述:Loki 能删除什么

Grafana Loki 的日志条目删除功能允许你从**指定流(stream)**中删除日志:满足以下条件的日志条目会被删除:

  • 落在指定的时间窗口内;
  • 匹配一个可选的 LogQL 行过滤器(line filter)。

删除请求通过 compactor 组件暴露的 REST 端点提交(端点列表见 reference/loki-http-api 中的 compactor 部分),由请求指定流与时间窗口;日志条目的实际删除动作,则在可配置的**取消期(cancellation period)**过后才会发生。

需要特别注意的是索引存储类型的约束:日志条目删除在TSDB 索引作为索引存储时受支持;过时的 BoltDB Shipper 索引也支持该功能,但 BoltDB Shipper 将在 Loki 4.0 中被移除,因此新部署应使用 TSDB。

日志条目删除依赖自定义日志保留(custom logs retention)工作流——即 compactor 的 retention 机制。compactor 会检查所有未处理且已超过取消期的删除请求,据此判断某个 chunk 是否应该被删除。

开启删除功能的前置条件

日志删除不是开箱即用的,需要同时满足三个条件:

  1. 启用 retention:在 compactor 配置中设置retention_enabled: true(命令行对应-compactor.retention-enabled)。
  2. 配置delete_request_store:指定存储删除请求的对象存储桶;启用 retention 后必须配置,否则 compactor 启动校验会直接失败(见 pkg/compactor/config.go 中Validate()DeleteRequestStore == ""的报错)。
  3. 租户的deletion_modedisabled:默认值为filter-and-delete,因此在未显式修改的情况下,一旦启用 retention 并配置好delete_request_store,删除功能对所有租户即默认生效。

⚠️ 启用 retention 的安全警告

启用 retention 必须非常谨慎。强烈建议同时在对象存储上开启版本控制(versioning),以便在 retention 配置误操作时能够恢复数据。如果你只想启用删除能力、并不想强制执行 retention,请将retention_period设置为0s

从源码看,compactor 的Validate()还做了一些自动化的配置协调(pkg/compactor/config.go):当retention_enabled为 true 且apply_retention_interval为 0 时,它会将apply_retention_interval对齐为compaction_interval的值,并额外增加最多 10 分钟(不超过其一半)的抖动(jitter),以避免 retention 与 compaction 在同一时刻运行。

配置详解:compactor 与 limits_config

deletion_mode:三种模式

deletion_modelimits_config中的全局与按租户设置,其类型定义在 pkg/validation/limits.go:

limits_config: # 全局默认,可选值:disabled | filter-only | filter-and-delete deletion_mode: filter-and-delete

在全局配置文件中设置即为全局默认值;也可以按租户在**运行时配置文件(runtime configuration file)**中覆盖(参见 configure 文档的 runtime-configuration-file 部分)。

deletion_mode支持三种取值(实现见 pkg/compactor/deletionmode/mode.go):

取值语义存储行为
disabled不允许删除,对删除 API 端点的请求返回403 Forbidden不删除
filter-only查询 Loki 时过滤掉匹配删除请求的日志行不从存储中移除
filter-and-delete查询时过滤,且同时从存储中移除从存储删除(默认值)

源码中Mode.DeleteEnabled()仅对FilterOnlyFilterAndDelete返回 true(mode.go),而删除 API 的请求处理会先调用validDeletionLimit检查租户模式是否允许删除(pkg/compactor/deletion/util.go)。注意ParseMode对未知值会返回ErrUnknownMode,因此配置拼写错误会直接导致请求校验失败。

端点注册与 retention 的强绑定

删除 API 端点仅在compactor.retention_enabled为 true 时注册。当 retention 未启用时,无论deletion_mode取什么值,所有租户都无法访问删除端点(此时请求处理器的 handler 为 nil,会直接返回400 Retention is not enabled,见 pkg/compactor/deletion/request_handler.go)。

当 retention 启用后,再通过deletion_mode的按租户覆盖(override)来控制哪些租户可以使用删除 API。

其他关键 compactor 配置项

以下是当前仓库中与删除相关的完整配置项(默认值与含义来自 pkg/compactor/config.go):

compactor: # 启用按流/按租户的自定义 retention(删除功能的前提) retention_enabled: true # 存储删除请求的对象存储桶,启用 retention 后必填 delete_request_store: loki-delete-requests # 删除请求在桶中的路径前缀,默认 "index/" delete_request_store_key_prefix: index/ # 存储删除请求所用的数据库类型:boltdb(默认)或 sqlite delete_request_store_db_type: boltdb # 迁移数据库类型时的备份库类型,例如 boltdb backup_delete_request_store_db_type: "" # 允许在创建后多长时间内取消删除请求,默认 24h delete_request_cancel_period: 24h # 带行过滤器的删除请求最大分片跨度,默认 24h delete_max_interval: 24h # 每个压缩周期最多处理的删除请求数,默认 70 delete_batch_size: 70 # retention 生效周期:0 表示与 compaction 周期一致(源码会自动加抖动) apply_retention_interval: 0s # 删除请求开始真正删除数据前的延迟,默认 2h retention_delete_delay: 2h # 删除 chunk 的工作协程数,默认 150 retention_delete_worker_count: 150

对应的命令行 Flag(前缀均为-compactor.):

Flag默认值
-compactor.retention-enabledfalse
-compactor.delete-request-store
-compactor.delete-request-store.key-prefixindex/
-compactor.delete-request-store.db-typeboltdb
-compactor.delete-request-store.backup-db-type
-compactor.delete-request-cancel-period24h
-compactor.delete-max-interval24h
-compactor.delete-batch-size70
-compactor.retention-delete-delay2h
-compactor.retention-delete-worker-count150

源码中delete_request_cancel_period的 Flag 注释建议至少设为 24h(config.go);retention_delete_delay则是在取消期之后、chunk 真正被删除之前的额外缓冲。

一个最小可用配置示例

limits_config: retention_period: 744h # 如不想强制 retention,可设为 0s deletion_mode: filter-and-delete compactor: working_directory: /var/loki/compactor retention_enabled: true delete_request_store: gcs://bucket_for_delete_requests # 按你的对象存储类型填写 delete_request_store_db_type: boltdb delete_request_cancel_period: 24h delete_max_interval: 24h

删除请求的生命周期与 HTTP API 使用

提交删除请求(Add)

通过 compactor 的删除端点提交删除请求。核心参数在 request_handler.go 中解析:

  • query(必填):LogQL 流选择器表达式,如{cluster="prod"},可带行过滤器如{cluster="prod"} |= "ERROR"。源码中parseDeletionQuery会先syntax.ParseLogSelector再构建 Pipeline,非法表达式(如错误的 regex 或ip()模式)会在提交时就返回 400,而不是等到执行期失败(pkg/compactor/deletion/util.go)。
  • start(必填):起始时间,支持Unix 秒RFC3339格式。
  • end(必填):结束时间,同样支持两种格式。校验规则包括:不允许删除未来时间的数据(deletes in the future are not allowed),且 start 必须小于 end(request_handler.go)。
  • max_interval(可选):单请求的分片跨度,不能大于delete_max_interval,也不能大于待删除时间窗口本身;最小 1 秒,合法单位为smh(request_handler.go)。
curl -X POST -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete?query=%7Bcluster%3D%22prod%22%7D&start=1704067200&end=1704153600"

成功时返回204 No Content,响应头X-Delete-Request-ID携带删除请求 ID。请求只影响查询层时(filter-only),删除记录同样会持久化,查询时由查询路径按需过滤。

分片(sharding)机制

删除请求如果带行过滤器,会被拆分成多个较小的子请求,每个子请求覆盖不超过delete_max_interval(默认 24h)的时间跨度。单个请求可以用max_interval参数请求更小的分片,但不能大于delete_max_interval不带行过滤器的删除请求不会被拆分(request_handler.go 中仅当parsedExpr.HasFilter()时才计算分片间隔)。

源码中的buildRequests展示了分片的实现细节(request_handler.go):分片时子请求之间刻意保留少量时间重叠(而不是精确衔接),以避免因边界 1ms 的间隙漏删日志。

查询删除请求(Get)

curl -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete"

该接口按创建时间排序返回该租户的全部删除请求(JSON 数组),并隐藏内部的UserIDSequenceNum字段。它还支持两个可选参数:

  • for_querytime_filtering=true:仅返回与查询时过滤相关的删除请求;
  • start+end:可选的时间范围重叠过滤,只返回与给定范围有交集的删除请求(request_handler.go)。

被拆分出的同一请求的多个子请求,在查询时会被mergeDeletes合并展示为一条,状态根据已完成子请求的比例计算为ReceivedProcessedN% Complete(request_handler.go)。

取消删除请求(Cancel)

删除请求在可配置的取消期内可以取消:

curl -X PUT -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete?request_id=<REQUEST_ID>"
  • 取消期的长度由delete_request_cancel_period决定,默认24h
  • 一旦请求进入处理中或已完成(状态为Processed),默认不允许取消(返回 400);
  • 已开始处理已超过创建后取消期的请求,仍可传入force=true查询参数强制取消(request_handler.go):
    curl -X PUT -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete?request_id=<REQUEST_ID>&force=true"

缓存失效辅助端点

compactor 还暴露了缓存代数(cache generation number)相关端点:GET /loki/api/v1/cache_generation_number用于获取某租户的缓存代数;POST(更新)端点用于在回放历史数据等场景下手动递增缓存代数,使该租户的查询结果缓存失效(request_handler.go)。删除处理完成后缓存代数会自动更新,从而保证查询不会命中已删除数据的缓存。

删除请求的存储:boltdb 与 sqlite,以及迁移

删除请求本身使用delete_request_store_db_type指定的数据库类型存储,默认为boltdb,也可改用sqlite

  • 从一种数据库类型迁移到另一种时,可以设置backup_delete_request_store_db_type: boltdb,使删除请求同时写入备份数据库,迁移期间不丢请求(当前仓库中备份库仅支持 boltdb,见 config.go)。
  • 底层实现分别位于 pkg/compactor/deletion/delete_requests_db_boltdb.go 与 pkg/compactor/deletion/delete_requests_db_sqlite.go,并配套完整的单元测试(delete_requests_db_boltdb_test.godelete_requests_db_sqlite_test.go),可作为实现参考。

注意:delete_request_storedelete_request_store_db_type是两个不同维度的配置——前者是对象存储位置(存放删除请求数据文件),后者是本地数据库引擎。二者的组合决定了删除请求的持久化方式。

删除的实际执行机制

删除不是提交请求后立即发生的,其执行链路如下:

  1. compactor 周期性扫描:compactor 在每个 retention 周期(apply_retention_interval,默认与 compaction 周期一致并带抖动)检查未处理的删除请求。
  2. 只处理已过取消期的请求:只有创建时间超过delete_request_cancel_period(默认 24h)的请求才会进入实际删除阶段,这是给用户留出取消窗口。
  3. 批量执行:每个周期最多处理delete_batch_size(默认 70)个删除请求。
  4. 真正的数据删除:对于filter-and-delete模式,涉及删除的 chunk 需要按删除请求重建(去除被删除的行),再写回对象存储并更新索引;删除动作还会受到retention_delete_delay(默认 2h)的进一步延迟缓冲。

从源码看,delete_requests_manager.go 中的DeleteRequestsManager负责加载待处理的删除请求(loadDeleteRequestsToProcess),并以chunksSelectedTotaldeletedLinesTotaldeleteRequestsProcessedTotaldeletionFailures等指标持续上报进度(metrics.go)。带行过滤器的删除请求重建 chunk 的过程由 deletion_manifest_builder.go 生成删除清单(deletion manifest)驱动。

⚠️ 性能注意事项

带行过滤器的日志删除是 compactor 最消耗资源的操作之一。因为带过滤器的删除需要把每个相关 chunk 读出来、剔除匹配行、再重写并写回对象存储,属于 CPU 与 IO 密集任务。如果需要在多个租户/流上删除大批量带行过滤器的数据,请参考 Horizontal scaling of Compactor,将删除工作分布到多个 compactor 实例上执行。

排查与运维建议

  • 对象存储务必开启版本控制,防止误删后无法恢复;
  • 先以filter-only模式观察删除查询的实际命中范围,再切换到filter-and-delete落地物理删除;
  • 提交带行过滤器的删除请求时,合理利用max_interval参数控制单次分片规模,避免单个请求跨度过大导致执行时间过长;
  • 监控 compactor 的删除相关指标(loki_compactor_deletion_*),观察请求积压与执行失败情况,必要时通过横向扩展 compactor 分散负载。

总结

Loki 的日志条目删除能力以 compactor 的 retention 工作流为底座,通过retention_enabled+delete_request_store+deletion_mode三个要素即可开启;删除请求经 REST API 提交后,先经历可取消的保护期,再由 compactor 周期性地完成过滤、chunk 重建与物理删除。理解filter-onlyfilter-and-delete的差异、分片与取消机制、以及 boltdb/sqlite 两种请求存储的迁移方式,是安全使用这一强操作能力的关键。

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 20:58:14

mise Conda Backend 完全指南:免安装 Conda 直接解析依赖与安装包

mise Conda Backend 完全指南&#xff1a;免安装 Conda 直接解析依赖与安装包 【免费下载链接】mise dev tools, env vars, task runner 项目地址: https://gitcode.com/GitHub_Trending/mi/mise mise 的 conda 后端让你无需安装 conda、mamba 或 micromamba&#xff0c…

作者头像 李华
网站建设 2026/9/11 20:55:04

军用级振动传感器接口技术与应用解析

1. 军用级振动监测的核心组件解析在工业振动监测和军用设备健康管理领域&#xff0c;传感器接口的可靠性直接决定数据采集的成败。MIL-C-5015标准连接器搭配5/8-24UNF螺纹的振动加速度传感器&#xff0c;正是针对极端环境设计的经典解决方案。这类传感器在直升机旋翼监测、装甲…

作者头像 李华
网站建设 2026/9/11 20:52:30

IPD研发流程管控体系:提升产品开发效率与质量

1. 项目概述&#xff1a;IPD研发流程管控体系的核心价值 第一次接触IPD&#xff08;Integrated Product Development&#xff0c;集成产品开发&#xff09;这个概念是在2015年&#xff0c;当时我所在的一家智能硬件公司正面临产品延期交付的困境。市场部门抱怨研发周期太长错过…

作者头像 李华
网站建设 2026/9/11 20:51:05

Parquet转JSONL实战:Python生产级转换方案与踩坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华