业务需求:因为公司内部需要一个读取日志文件的ERROR错误并发送内部邮件
读取文件跟发送邮件的插件Logstash自身就有,但是我的需求是发送内部邮件,需要提供身份跟内部邮箱链接
建议阅读前先了解Logstash的基本使用
一、安装
安装 | Logstash 最佳实践
1.因为Logstash Java Filter需要依赖Logstash的API,我们需要将Logstash源码下载下来并构建
git clone --branch <branch_name> --single-branch https://github.com/elastic/logstash.git <target_folder>
其中<branch_name>需替换为你想要使用的logstash版本,使用7.1之后的GA版本就可以。<target_folder>需替换为你想要下载到的logstash代码父目录,不指定的话就下载到当前目录的logstash文件夹下。我这里使用的是8.4.2版本:
git clone --branch 8.4.2 --single-branch https://github.com/elastic/logstash.git
2.安装编写所需的demo代码
2.1.下载官方demo
官方提供了一个demo,我们可以下载下来基于这个demo做修改。
2.2.指定LOGSTASH_CORE_PATH
下载下来demo后,在项目根目录创建gradle.properties文件,添加一行数据:
LOGSTASH_CORE_PATH=<target_folder>/logstash-core
<target_folder>修改为本地的logstash的路径。
2.3.build.gradle文件可能会有很多报错,除了 FileNameFinder 其他都解决掉
具体太多了,比如拷贝versions.yml
文件,修改路径等,当时整的时候也没详细记录,不过都不难,我是IDEA用的项目确保刷新Gradle刷新没问题就行
3.代码说明
我自己写的插件的不完整代码-业务逻辑每个人都不一样,我就不放了:
package org.logstashplugins;
import co.elastic.logstash.api.*;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.commons.lang3.StringUtils;
import javax.xml.rpc.ParameterMode;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
/**
* @Description 邮箱发送
* @Author 胡桂明
* @Since 2022/9/23 11:16
*/
@LogstashPlugin(name = "send_email_output")
public class SendEmailOutput implements Output {
private final CountDownLatch done = new CountDownLatch(1);
/*
定义一个该Output支持的setting配置。名字是email,默认值为空
可从Output方法中看出是拿 EMAIL_CONFIG 的value值做field 的名称使用的
第一个参数表示配置文件的变量,第二个参数表示默认值,第三个参数表示是否启用,第四个参数表示必须提供
*/
// 收件人
public static final PluginConfigSpec<String> RECEIVERACCOUNTS_CONFIG =
PluginConfigSpec.stringSetting("receiverAccounts", "", false, true);
// 发件人(可以按系统填写)
public static final PluginConfigSpec<String> POSTERNAME_CONFIG =
PluginConfigSpec.stringSetting("posterName", "异常信息发送", false, true);
// 邮件主题
public static final PluginConfigSpec<String> EMAILSUBJECT_CONFIG =
PluginConfigSpec.stringSetting("emailSubject", "【重要提醒】系统出现ERROR异常", false, true);
// OA调接口key(MD5加密后的字符串)
public static final PluginConfigSpec<String> KEY_CONFIG =
PluginConfigSpec.stringSetting("key", "", false, true);
// OA调接口地址
public static final PluginConfigSpec<String> WSDLADDRESS_CONFIG =
PluginConfigSpec.stringSetting("wsdlAddress", "", false, true);
private final String id;
private final String receiverAccounts;
private final String posterName;
private final String key;
private final String wsdlAddress;
private final String emailSubject;
public SendEmailOutput(String id, Configuration config, Context context) {
// 构造函数应该验证配置选项
this.id = id;
// 收件人
this.receiverAccounts = config.get(RECEIVERACCOUNTS_CONFIG);
// 发件人
this.posterName = config.get(POSTERNAME_CONFIG);
// OA调接口key(MD5加密后的字符串)
this.key = config.get(KEY_CONFIG);
// OA调接口地址
this.wsdlAddress = config.get(WSDLADDRESS_CONFIG);
// 邮件主题
this.emailSubject = config.get(EMAILSUBJECT_CONFIG);
}
@Override
public void output(Collection<Event> collection) {
for (Event event : collection) {
System.out.println("-------------Map:" + event.toMap());
Map<String, Object> data = event.getData();
String logLevel = data.get("logLevel") + "";
String message = data.get("message") + "";
// xxx...
}
}
/**
* 停止
*/
@Override
public void stop() {
done.countDown();
}
/**
* 等待停止
*
* @throws InterruptedException 中断异常
*/
@Override
public void awaitStop() throws InterruptedException {
done.await();
}
/**
* 返回配置参数的集合
*
* @return 所有配置选项
*/
@Override
public Collection<PluginConfigSpec<?>> configSchema() {
// 应该返回此插件的所有配置选项的列表
return Arrays.asList(RECEIVERACCOUNTS_CONFIG, POSTERNAME_CONFIG, EMAILSUBJECT_CONFIG, KEY_CONFIG, WSDLADDRESS_CONFIG);
}
@Override
public String getId() {
return id;
}
}
@LogstashPlugin(name = "send_email_output")
// 必须跟类名称保持高度一致。一个驼峰命名,一个下划线命名
implements Output
// 因为我写的是输出插件,这里是Output,如果是输入就是Input,过滤器Filter
// 收件人public static final PluginConfigSpec<String> RECEIVERACCOUNTS_CONFIG =
// 这个是在你写好插件后,从配置文件读取的内容,可以修改数据类型,第一个参数表示配置文件的变量,第二个参数表示默认值,第三个参数表示是否启用,第四个参数表示是否必须提供
PluginConfigSpec.stringSetting("receiverAccounts", "", false, true);
SendEmailOutput
构造类,从配置文件读取值用的,更上面的对应
output
类,这个就是我们需要主要编写逻辑的地方
Collection<Event> collection
从输入插件或者过滤器处理后得到的数据,可以用for遍历获得里面的Event,Map格式
configSchema() { return Arrays.asList(RECEIVERACCOUNTS_CONFIG, POSTERNAME_CONFIG, EMAILSUBJECT_CONFIG, KEY_CONFIG, WSDLADDRESS_CONFIG);
// 应该返回此插件的所有配置选项的列表
添加java依赖
我们自己编写插件的时候,往往需要用到别的jar依赖,添加方式:
打开build.gradle
,在最后添加:
group:依赖的路劲,找个maven仓库就能看到了
name:依赖的名称
version:依赖的版本
dependencies {
implementation group: 'commons-logging',name: 'commons-logging',version: '1.2'
}
然后旁边会有个绿色三角号:
点一下Run运行就添加成功了,在右边就能看到了,没看到的话请自行百度Gradle怎么添加依赖
可以在test写一个测试类来调用程序是否能跑
package org.logstashplugins;
import org.junit.Before;
import org.junit.Test;
import co.elastic.logstash.api.Event;
import org.logstash.plugins.ConfigurationImpl;
import co.elastic.logstash.api.Configuration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @Description 发送邮件测试类
* @Author 胡桂明
* @Since 2022/9/26 15:33
*/
public class SendEmailOutputTest {
String receiverAccounts = "xxx";
String posterName = "异常信息发送";
String logLevel = "ERROR";
String key = "xxx";
// 配置信息
Map<String, Object> configValues = new HashMap<>();
// 初始化配置信息
@Before
public void init(){
configValues.put(SendEmailOutput.RECEIVERACCOUNTS_CONFIG.name(), receiverAccounts);
configValues.put(SendEmailOutput.POSTERNAME_CONFIG.name(), posterName);
configValues.put(SendEmailOutput.KEY_CONFIG.name(), key);
}
// 设置好需要的信息,测试output方法
@Test
public void testJavaOutputExample() {
Configuration config = new ConfigurationImpl(configValues);
SendEmailOutput output = new SendEmailOutput("test-id", config, null);
Collection<Event> events = new ArrayList<>();
output.output(events);
}
}
二、打包插件-安装插件:
在IDEA的最下面的Terminal
清理clean
:
gradlew clean
打包:
在IDEA的Terminal执行 gradlew.bat assemble
如果没用报错,则可以进行打包
打包命令 gradlew.bat gem
打包完成后会在项目根目录出现一个xxx.gem的文件,这个就是我们的插件了
安装:
在logstash根目录下的bin,打开黑窗口输入 logstash-plugin install --no-verify --local C:/Dev/Development/logstash-8.4.2/logstash-output-send_email_output-1.0.0.gem
C:/Dev/Development/logstash-8.4.2/logstash-output-send_email_output-1.0.0.gem
是我放插件的位置
出现 Installation successful
则安装成功
三、编写配置文件启动logstash测试
使用:
解压之后在Logstash的bin下面执行
logstash -e "input { stdin {}} output { stdout {}}"
// input { stdin {} } 输入 - 终端输入
// output { stdin {} } 输出 - 终端输出
编写配置文件:
在根目录新建一个conf文件夹,里面新建一个*.conf
文件,里面输入:
input {
stdin { }
}
output {
stdout { }
}
然后执行命令 logstash -f conf/agent.conf
此外,logstash 还提供一个方便我们规划和书写配置的小功能。你可以直接用 bin/logstash -f /etc/logstash.d/
来运行。logstash 会自动读取 /etc/logstash.d/
目录下所有的文本文件,然后在自己内存里拼接成一个完整的大配置文件,再去执行。
可能写的不是特别详细,有不懂的可以评论或者留言,看到了会及时回复的~