Logstash - 插件开发JAVA版 - 自己编写输出插件

业务需求:因为公司内部需要一个读取日志文件的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/ 目录下所有的文本文件,然后在自己内存里拼接成一个完整的大配置文件,再去执行。

可能写的不是特别详细,有不懂的可以评论或者留言,看到了会及时回复的~

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值