【免费下载链接】logstash
Logstash - transport and process your logs, events, or other data
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
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



