如何编写自定义 Logstash 插件?(详细教程 + 实战示例)
Logstash 虽然提供了 200+ 官方和社区插件,但在某些特殊场景下(如对接内部系统、私有协议、定制化处理逻辑),仍需要开发 自定义插件。
本文将带你从零开始,手把手编写一个 自定义 Filter 插件(也可扩展为 Input/Output),并介绍插件结构、开发环境、调试与打包发布全流程。
一、Logstash 插件类型
| 类型 | 说明 | 示例 |
|---|---|---|
input | 数据输入源 | 读取自定义 API、消息队列 |
filter | 数据处理过滤器 | 解析私有日志格式、调用外部服务 |
output | 数据输出目标 | 写入内部数据库、调用 Webhook |
本文以 Filter 插件 为例,但结构通用。
二、开发准备
2.1 环境要求
| 工具 | 版本要求 |
|---|---|
| Ruby | ≥ 2.7(Logstash 基于 JRuby) |
| Java | ≥ 8(Logstash 运行在 JVM 上) |
| Logstash | 下载对应版本(如 8.11.3) |
| gem | Ruby 包管理器 |
💡 提示:Logstash 自带 JRuby,推荐使用其内置 Ruby 环境。
2.2 安装 Plugin Generator(官方工具)
Logstash 提供了插件生成器,可快速创建模板:
# 进入 Logstash 目录
cd /usr/share/logstash
# 安装生成器(首次)
bin/logstash-plugin generate --type filter --name my_custom_filter
这会生成一个名为
logstash-filter-my_custom_filter的插件项目。
三、插件项目结构
执行上述命令后,生成目录:
logstash-filter-my_custom_filter/
├── lib/
│ └── logstash/
│ └── filters/
│ └── my_custom_filter.rb # 核心逻辑
├── spec/
│ └── logstash/
│ └── filters/
│ └── my_custom_filter_spec.rb # 单元测试
├── logstash-filter-my_custom_filter.gemspec # Gem 包描述文件
└── CHANGELOG.md
四、实战:编写一个“添加时间戳偏移”的 Filter 插件
需求:
创建一个 filter 插件,将事件中的 @timestamp 增加指定秒数(用于测试或模拟数据)。
例如:offset => 3600 表示时间加 1 小时。
4.1 编辑 my_custom_filter.rb
路径:lib/logstash/filters/my_custom_filter.rb
# encoding: utf-8
require "logstash/filters/base"
require "logstash/namespace"
class LogStash::Filters::MyCustomFilter < LogStash::Filters::Base
# 插件名称(必须与文件名一致)
config_name "my_custom_filter"
# 定义配置参数
config :offset, :validate => :number, :default => 0
config :target, :validate => :string, :default => "@timestamp"
public
def register
# 插件初始化时调用
@logger.info("MyCustomFilter 已注册", :offset => @offset, :target => @target)
end
public
def filter(event)
# 跳过已标记为“丢弃”的事件
return unless filter_include?(event)
begin
if @target == "@timestamp"
# 处理时间戳
new_timestamp = event.timestamp.time + @offset
event.timestamp = LogStash::Timestamp.new(new_timestamp)
else
# 处理普通字段(假设是时间字符串)
old_value = event.get(@target)
if old_value.is_a?(String)
time = Time.parse(old_value)
new_time = (time + @offset).iso8601
event.set(@target, new_time)
end
end
# 标记事件已处理
filter_matched(event)
rescue => e
@logger.warn("MyCustomFilter 处理失败", :exception => e.message, :event => event)
# 可选:丢弃错误事件
# event.tag("_my_custom_filter_error")
end
end
end
4.2 编辑 .gemspec 文件
确保 logstash-filter-my_custom_filter.gemspec 内容正确:
Gem::Specification.new do |s|
s.name = "logstash-filter-my_custom_filter"
s.version = "1.0.0"
s.licenses = ["Apache-2.0"]
s.summary = "Adds a time offset to @timestamp or a field"
s.description = "This plugin adds a specified number of seconds to the @timestamp or a custom field."
s.homepage = "https://github.com/yourname/logstash-filter-my_custom_filter"
s.authors = ["Your Name"]
s.email = "you@example.com"
# 依赖 Logstash 核心
s.require_paths = ["lib"]
# 指定 Logstash 版本兼容性
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
end
五、测试插件
5.1 本地安装插件
cd logstash-filter-my_custom_filter
# 打包
gem build logstash-filter-my_custom_filter.gemspec
# 安装到 Logstash
/usr/share/logstash/bin/logstash-plugin install ./logstash-filter-my_custom_filter-1.0.0.gem
✅ 安装成功后,Logstash 启动时会加载该插件。
5.2 编写测试配置文件 test.conf
input {
generator {
message => "test event"
count => 1
}
}
filter {
my_custom_filter {
offset => 3600
target => "@timestamp"
}
}
output {
stdout {
codec => rubydebug
}
}
5.3 运行测试
/usr/share/logstash/bin/logstash -f test.conf
你应该看到输出的 @timestamp 比当前时间 快了 1 小时。
六、编写单元测试(可选但推荐)
编辑 spec/logstash/filters/my_custom_filter_spec.rb
require "logstash/devutils/rspec/spec_helper"
require "logstash/filters/my_custom_filter"
describe LogStash::Filters::MyCustomFilter do
let(:config) { { "offset" => 3600 } }
context "当 offset 为 3600" do
sample({}) do
expect(subject.get("@timestamp").time.to_i).to be > (Time.now.to_i + 3500)
end
end
end
运行测试:
rake test
七、支持 Input 或 Output 插件
Input 示例骨架
class LogStash::Inputs::MyInput < LogStash::Inputs::Base
config_name "my_input"
def register; end
def run(queue)
while !stop?
event = LogStash::Event.new("message" => "hello from custom input")
queue << event
sleep 5
end
end
def stop; end
end
Output 示例骨架
class LogStash::Outputs::MyOutput < LogStash::Outputs::Base
config_name "my_output"
def register; end
def receive(event)
puts "Output: #{event.to_json}"
end
def close; end
end
生成命令:
bin/logstash-plugin generate --type input --name my_input
bin/logstash-plugin generate --type output --name my_output
八、插件发布与管理
8.1 发布到 RubyGems(可选)
gem push logstash-filter-my_custom_filter-1.0.0.gem
8.2 内部私有仓库(企业推荐)
使用 Gem in a Box、Artifactory 或 Nexus 搭建私有 gem 仓库。
九、调试技巧
| 技巧 | 方法 |
|---|---|
| 查看日志 | --log.level debug |
| 打印调试信息 | @logger.info("debug", :var => value) |
使用 stdout { codec => rubydebug } | 查看事件结构 |
启用 --config.test_and_exit | 验证配置语法 |
bin/logstash -f test.conf --config.test_and_exit
十、最佳实践
- 命名规范:
- Filter 插件:
logstash-filter-<name> - 使用小写字母+下划线
- Filter 插件:
- 错误处理:
- 捕获异常,记录日志,避免崩溃
- 使用
event.tag("_error")标记失败事件
- 性能优化:
- 避免在
filter中做耗时网络请求(可异步) - 缓存外部资源(如 lookup 表)
- 避免在
- 文档化:
- 在 README 中说明配置参数和用途
- 版本管理:
- 遵循语义化版本(SemVer)
十一、常见问题
❓ 插件未加载?
- 检查插件名称是否与
config_name一致 - 查看 Logstash 启动日志是否有
Load custom plugin信息 - 确保
.gem安装成功:bin/logstash-plugin list | grep my_custom_filter
❓ 报错 undefined method?
- 检查类继承是否正确:
< LogStash::Filters::Base - 确保文件路径和命名规范
❓ 如何调用外部 API?
require "net/http"
uri = URI("https://api.example.com/lookup")
response = Net::HTTP.get(uri)
注意:建议加缓存,避免性能瓶颈。
十二、参考资源
-
官方插件开发指南:
👉 https://www.elastic.co/guide/en/logstash/current/plugin-development.html -
插件生成器源码:
👉 https://github.com/logstash-plugins/generator-logstash-plugin -
社区插件仓库:
👉 https://github.com/logstash-plugins
结语
编写自定义 Logstash 插件,让你能够:
- 对接内部系统
- 实现复杂业务逻辑
- 扩展 Logstash 能力边界
虽然需要一定的 Ruby 基础,但模板化开发 + 丰富的 API,使得开发过程非常高效。
🎁 附:完整插件模板下载
你可以克隆这个仓库作为起点:
git clone https://github.com/logstash-plugins/logstash-filter-example.git
替换内容即可快速开发。
1688

被折叠的 条评论
为什么被折叠?



