Logstash 日志配置完全指南:log4j2.properties、Logging API 与 Slowlog 慢日志调优

  • 数据工程
  • 后端

【免费下载链接】logstash

Logstash - transport and process your logs, events, or other data

项目地址: https://gitcode.com/gh_mirrors/lo/logstash
点击查看 免费下载

Logstash 在运行过程中会通过内部日志系统记录自身的启动、管道编译、插件执行与关闭全过程,本文以当前仓库的官方日志文档 docs/reference/logging.md 为核心骨架,结合 config/log4j2.properties 出厂配置与 logstash-core 源码,系统讲解 Logstash 日志的存储位置、Log4j2 静态配置与文件滚动策略、通过 Logging API 热更新日志级别,以及如何用 Slowlog 定位管道中的慢事件。读完本文,你将能够熟练排查插件问题、按子系统精准控制日志输出,并快速定位拖慢管道的事件与过滤器。

日志体系概览

Logstash 在运行期间会产生大量内部日志,这些日志默认写入 LS_HOME/logs 目录(DEB/RPM 包安装时位于 /var/log/logstash),默认日志级别为 INFO。其日志框架基于 Apache Log4j 2,且 Log4j2 的大部分能力(logger 分层、appender、滚动策略、PatternLayout、JSONLayout 等)都直接暴露给用户使用,因此你可以针对某个子系统、模块或插件单独配置日志级别。

当需要排查问题(尤其是插件问题)时,将日志级别提升到 DEBUG 能获得更详细的消息。例如排查 Elasticsearch Output 插件问题时,可以只针对 logstash.outputs.elasticsearch 这一个 logger 提高级别,从而避免全局 DEBUG 带来的海量噪音,把注意力集中在出问题的组件上。

Logstash 提供两种日志配置途径,两者特性对比如下:

配置方式生效时机是否持久化适用场景
log4j2.properties 文件需要重启 Logstash重启后依然生效永久性、生产环境基线配置
Logging API(_node/logging)立即生效,无需重启重启后丢失临时调试、线上排障

通过 log4j2.properties 配置日志

Logstash 出厂自带一份 config/log4j2.properties,开箱即用,默认同时输出到控制台与滚动文件。你可以修改该文件来调整滚动策略、输出格式(plain / json)以及其他 Log4j2 配置项。修改后必须重启 Logstash 才能生效,且改动会持久保留。

日志级别通过形如 logger.<name>.level 的方式设置。以下示例针对 Elasticsearch Output 插件单独开启 DEBUG:

logger.elasticsearchoutput.name = logstash.outputs.elasticsearch
logger.elasticsearchoutput.level = debug

logger 的 name 通常是 Java 类名,例如 org.logstash.dissect.Dissector,也可以是部分包路径,如 org.logstash.dissect。对于 Ruby 类(如 LogStash::Outputs::Elasticsearch),logger 名称通过对完整类名小写化、并把双冒号 :: 替换为单个点 . 得到,即 logstash.outputs.elasticsearch。

出厂配置文件解析

当前仓库的 config/log4j2.properties 定义了完整的 appender 集合,比文档示例更丰富,主要包括:

  • 控制台 appender:plain_console(PatternLayout)与 json_console(JSONLayout),由 rootLogger.appenderRef.console.ref 引用;
  • 滚动文件 appender:plain_rolling 写 logstash-plain.log、json_rolling 写 logstash-json.log;
  • 按管道拆分 appender:pipeline_routing_appender(PipelineRouting 类型),当设置 pipeline.separate_logs 时按管道分别写入 pipeline_${ctx:pipeline.id}.log;
  • Slowlog appender:plain_rolling_slowlog、json_rolling_slowlog 等,对应 logger.slowlog(级别 trace,additivity = false);
  • Deprecation 日志:deprecation_plain_rolling 写入 logstash-deprecation.log,由 logger.deprecation(级别 WARN)与 logger.deprecation_root 使用;
  • 根 logger 级别通过系统属性 sys:ls.log.level 注入,实际值来自 logstash.yml 的 log.level(默认 info)。

日志格式中通过 %X{pipeline.id} 与 %X{plugin.id} 两个 MDC 键输出管道与插件 ID,方便多管道场景下追溯日志归属。

滚动(Rollover)策略详解

log4j2.properties 中针对日志文件的 appender 定义了两种机制:**触发策略(triggering policies)**决定"是否"执行滚动,**滚动策略(rollover strategy)**决定"如何"执行滚动。默认定义了两个触发策略——时间与大小:

  • 时间策略:每天生成一个日志文件;
  • 大小策略:文件大小超过 100 MB 时强制创建新文件。

默认滚动策略还基于最大文件数执行滚动:当文件数达到上限 30 个时,最旧的文件被删除,其余文件依次重新编号。每个文件名称包含日期,滚动时还会清理超过 7 天(默认)的文件。

下面是对照 config/log4j2.properties 第 15-34 行的逐项注释版本:

appender.rolling.type = RollingFile                              # 1. appender 类型,用于滚动旧日志
appender.rolling.name = plain_rolling
appender.rolling.fileName = ${sys:ls.logs}/logstash-plain.log    # 2. 当前日志文件名
appender.rolling.filePattern = ${sys:ls.logs}/logstash-plain-%d{yyyy-MM-dd}-%i.log.gz  # 3. 滚动文件名格式:日期+递增序号,默认最多 30 个
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy  # 4. 时间策略:每天结束时触发滚动
appender.rolling.policies.time.interval = 1
appender.rolling.policies.time.modulate = true
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c]%notEmpty{[%X{pipeline.id}]}%notEmpty{[%X{plugin.id}]} %m%n
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy  # 5. 大小策略:纯文本日志达到 100 MB 时触发
appender.rolling.policies.size.size = 100MB
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.max = 30                              # 6. 滚动策略:最多保留 30 个文件
appender.rolling.strategy.action.type = Delete                   # 7. 滚动时执行的动作
appender.rolling.strategy.action.basepath = ${sys:ls.logs}
appender.rolling.strategy.action.condition.type = IfFileName
appender.rolling.strategy.action.condition.glob = logstash-plain-*  # 8. 动作考虑的文件集合
appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified
appender.rolling.strategy.action.condition.nested_condition.age = 7D  # 9. 执行条件:文件修改时间超过 7 天

滚动动作还可以附加磁盘用量限制,删除旧文件以匹配指定条件。例如,按管道拆分日志时,如果所有已压缩的 pipeline_*.log.gz 文件累计超过 5 MB,则删除最旧文件:

appender.rolling.type = RollingFile
...
appender.rolling.strategy.action.condition.glob = pipeline_${ctx:pipeline.id}.*.log.gz
appender.rolling.strategy.action.condition.nested_condition.type = IfAccumulatedFileSize
appender.rolling.strategy.action.condition.nested_condition.exceeds = 5MB  # 压缩文件累计超过 5MB 时删除

建议优先使用 Logstash 出厂自带的默认 log4j2 配置,它针对大多数部署场景做了合理调优。只有在确需调整时才修改上述滚动策略相关参数。

通过 Logging API 动态调整日志级别

如果只是为了临时调整日志级别,修改 log4j2.properties 并重启会产生不必要的停机。Logging API 允许在不重启的情况下动态更新日志级别,设置立即生效。

默认情况下 Logging API 监听 tcp:9600。如果该端口已被其他 Logstash 实例占用,需要使用 --api.http.port 命令行参数指定其他端口,详见 docs/reference/running-logstash-command-line.md。

从源码看,Logging API 由 logstash-core/lib/logstash/api/modules/logging.rb 实现,并在 logstash-core/lib/logstash/api/rack_app.rb 中注册到 /_node/logging 路由。其核心处理逻辑是:把请求体中所有以 logger. 开头的键拆分出 logger 路径,然后调用 LogStash::Logging::Logger::configure_logging(level, path) 完成动态配置;遇到非法日志级别时,底层抛出 IllegalArgumentException,API 返回 HTTP 400。底层 Java 实现见 logstash-core/src/main/java/org/logstash/log/LoggerExt.java 中的 configure_logging 方法(对 CONFIG_LOCK 加锁保证线程安全)。

获取当前日志配置列表

通过 GET 请求 _node/logging 可以列出运行时可用的日志子系统及其当前级别:

curl -XGET 'localhost:9600/_node/logging?pretty'

示例响应(节选):

{
  ...
  "loggers" : {
    "logstash.agent" : "INFO",
    "logstash.api.service" : "INFO",
    "logstash.basepipeline" : "INFO",
    "logstash.codecs.plain" : "INFO",
    "logstash.codecs.rubydebug" : "INFO",
    "logstash.filters.grok" : "INFO",
    "logstash.inputs.beats" : "INFO",
    "logstash.instrument.periodicpoller.jvm" : "INFO",
    "logstash.instrument.periodicpoller.os" : "INFO",
    "logstash.instrument.periodicpoller.persistentqueue" : "INFO",
    "logstash.outputs.stdout" : "INFO",
    "logstash.pipeline" : "INFO",
    "logstash.plugins.registry" : "INFO",
    "logstash.runner" : "INFO",
    "logstash.shutdownwatcher" : "INFO",
    "org.logstash.Event" : "INFO",
    "slowlog.logstash.codecs.plain" : "TRACE",
    "slowlog.logstash.codecs.rubydebug" : "TRACE",
    "slowlog.logstash.filters.grok" : "TRACE",
    "slowlog.logstash.inputs.beats" : "TRACE",
    "slowlog.logstash.outputs.stdout" : "TRACE"
  }
}

注意 slowlog.* 前缀的 logger 对应 Slowlog 专用通道,级别固定为 TRACE(见 config/log4j2.properties 中 logger.slowlog 的定义)。响应中根 logger(名称为空)的级别也会被包含(对应 rootLogger.level)。

更新日志级别

在子系统、模块或插件名称前加上 logger. 前缀即可。以 outputs.elasticsearch 为例:

curl -XPUT 'localhost:9600/_node/logging?pretty' -H 'Content-Type: application/json' -d'
{
    "logger.logstash.outputs.elasticsearch" : "DEBUG"
}
'

该设置在生效期间,Logstash 会为配置中所有 Elasticsearch Output 输出 DEBUG 级日志。此设置是临时性的,重启后不保留。

如果希望日志修改在重启后仍然生效,请把配置写入 log4j2.properties。

重置动态日志级别

要恢复被 Logging API 动态修改过的所有级别,发送 PUT 请求到 _node/logging/reset,所有 logger 将回退到 log4j2.properties 中定义的值:

curl -XPUT 'localhost:9600/_node/logging/reset?pretty'

从 logging.rb 的实现看,PUT /reset 通过 get_logging_context 获取 Log4j2 的 LoggerContext 并调用 context.reconfigure 重新加载配置;若日志上下文未正确初始化则返回 HTTP 500。

日志文件位置

日志文件位置通过 --path.logs 设置指定(DEB/RPM 安装默认在 /var/log/logstash,源码/压缩包运行默认在 LS_HOME/logs)。在 config/logstash.yml 中对应 path.logs 配置项。启动后日志目录下会产生 logstash-plain.log(或 logstash-json.log,取决于 log.format)、logstash-slowlog-plain.log、logstash-deprecation.log 以及按管道拆分的 pipeline_<pipeline-id>.log 等文件。

另外,与日志直接相关的还有 log.level 与 log.format 两个配置项(config/logstash.yml 第 368-384 行):

# Options for log.level:
#   * fatal
#   * error
#   * warn
#   * info (default)
#   * debug
#   * trace
# log.level: info
#
# Options for log.format:
#   * plain (default)
#   * json
# log.format: plain

log.level 会被注入为系统属性 ls.log.level,供 log4j2.properties 的 rootLogger.level = ${sys:ls.log.level} 使用;log.format 同理注入 ls.log.format,用于在 plain / json 控制台与滚动 appender 之间切换。

Slowlog:定位管道中的慢事件

Slowlog 让 Logstash 能够在某个事件在管道中耗时异常时输出日志,日志同样落在 --path.logs 目录下(logstash-slowlog-plain.log 等)。Slowlog 通过 logstash.yml 中的以下选项配置:

slowlog.threshold.warn (default: -1)
slowlog.threshold.info (default: -1)
slowlog.threshold.debug (default: -1)
slowlog.threshold.trace (default: -1)

Slowlog 默认关闭:四个阈值默认值均为 -1nanos,代表无限阈值,即永不触发慢日志。

从源码看,四个阈值在 logstash-core/lib/logstash/environment.rb 中以 TimeValueSetting 注册为 Logstash 全局设置;每个插件初始化时(logstash-core/lib/logstash/plugin.rb)会读取这四个值并转为纳秒,构造慢日志器;过滤器的计时发生在 logstash-core/lib/logstash/filters/base.rb 的 do_filter 中——用 System.nanoTime 记录过滤前后耗时,再调用 @slow_logger.on_event 判断是否超阈值。底层判定逻辑位于 logstash-core/src/main/java/org/logstash/log/SlowLoggerExt.java:从 warn 到 trace 依次比较耗时与阈值,事件耗时会附带 plugin_params、took_in_nanos、took_in_millis 以及事件 JSON 一起写入日志。

启用 Slowlog

slowlog.threshold 系列字段使用时间值格式,支持多种时间单位:nanos(纳秒)、micros(微秒)、ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)。日志级别越高,Slowlog 越敏感、记录的慢事件越多。

示例配置:

slowlog.threshold.warn: 2s
slowlog.threshold.info: 1s
slowlog.threshold.debug: 500ms
slowlog.threshold.trace: 100ms

各级别的含义:

  • 日志级别为 warn 时,只记录处理耗时超过 2s 的事件;
  • 日志级别为 info 时,记录耗时超过 1s 的事件;
  • 日志级别为 debug 时,记录耗时超过 500ms 的事件;
  • 日志级别为 trace 时,记录耗时超过 100ms 的事件。

Slowlog 日志中包含完整的 event 内容以及造成慢速的过滤器配置(plugin_params),便于直接复现和定位是哪个过滤器、哪条配置导致的延迟。配合 log4j2.properties 中 logger.slowlog(slowlog logger,级别 trace,additivity = false,独立输出到 slowlog 专用文件)的设计,慢日志不会混入主日志,便于单独收集与分析。

排障实践建议

  • 局部开启 DEBUG:优先针对出问题的插件单独设置级别(如 logstash.outputs.elasticsearch),避免全量 DEBUG 淹没关键信息;
  • 线上临时调试用 API:先用 PUT _node/logging 热更新级别,排障结束后用 PUT _node/logging/reset 恢复,全程无需重启;
  • 永久调整写文件:需要长期保留的级别或滚动策略改动写入 config/log4j2.properties,重启生效;
  • 慢管道查 Slowlog:先按 warn → info → debug 逐步收紧 slowlog.threshold.*,从 logstash-slowlog-plain.log 中找出耗时事件及其过滤器配置,再针对性优化过滤器顺序或替换低效正则;
  • 注意端口冲突:Logging API 默认 9600,多实例部署时用 --api.http.port 区分。

以上内容均可在当前仓库对应路径中进一步验证:出厂日志配置见 config/log4j2.properties,API 实现见 logstash-core/lib/logstash/api/modules/logging.rb 与 logstash-core/src/main/java/org/logstash/log/LoggerExt.java,Slowlog 实现见 logstash-core/src/main/java/org/logstash/log/SlowLoggerExt.java。

  • 数据工程
  • 后端

【免费下载链接】logstash

Logstash - transport and process your logs, events, or other data

项目地址: https://gitcode.com/gh_mirrors/lo/logstash
点击查看 免费下载

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

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值