* [#886] Feature: 提供一种go plugin 告警通知方式 * fix: 移除下层并发
This commit is contained in:
parent
46c60a32fd
commit
302cebbbec
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
.phony: all
|
||||||
|
all: plugin
|
||||||
|
|
||||||
|
.phony: plugin
|
||||||
|
plugin:
|
||||||
|
export GOPROXY=http://goproxy.cn,direct
|
||||||
|
go build -buildmode=plugin -o notify.so notify.go
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
通过go plugin模式处理告警通知
|
||||||
|
---
|
||||||
|
|
||||||
|
相比于调用py脚本方式,该方式一般无需考虑依赖问题
|
||||||
|
|
||||||
|
### (1) 编写动态链接库逻辑
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
type inter interface {
|
||||||
|
Descript() string
|
||||||
|
Notify([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0、Descript 可用于该插件在 server 中的描述
|
||||||
|
// 1、在 Notify 方法中实现要处理的自定义逻辑
|
||||||
|
```
|
||||||
|
|
||||||
|
实现以上接口的 `struct` 实例即为合法 `plugin`
|
||||||
|
|
||||||
|
### (2) 构建链接库
|
||||||
|
|
||||||
|
参考 `notify.go` 实现方式,执行 `make` 后可以看到生成一个 `notify.so` 链接文件,放到 n9e 对应项目位置即可
|
||||||
|
|
||||||
|
### (3) 更新 n9e 配置
|
||||||
|
|
||||||
|
```text
|
||||||
|
[Alerting.CallPlugin]
|
||||||
|
Enable = false
|
||||||
|
PluginPath = "./etc/script/notify.so"
|
||||||
|
# 注意此处caller必须在notify.so中作为变量暴露
|
||||||
|
Caller = "n9eCaller"
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// the caller can be called for alerting notify by complete this interface
|
||||||
|
type inter interface {
|
||||||
|
Descript() string
|
||||||
|
Notify([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// N9E complete
|
||||||
|
type N9EPlugin struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
BuildAt string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *N9EPlugin) Descript() string {
|
||||||
|
return fmt.Sprintf("%s: %s", n.Name, n.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *N9EPlugin) Notify(bs []byte) {
|
||||||
|
var channels = []string{
|
||||||
|
"dingtalk_robot_token",
|
||||||
|
"wecom_robot_token",
|
||||||
|
"feishu_robot_token",
|
||||||
|
}
|
||||||
|
for _, ch := range channels {
|
||||||
|
if ret := gjson.GetBytes(bs, ch); ret.Exists() {
|
||||||
|
fmt.Printf("do something...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// will be loaded for alertingCall
|
||||||
|
var n9eCaller = N9EPlugin{
|
||||||
|
Name: "n9e",
|
||||||
|
Description: "演示告警通过动态链接库方式通知",
|
||||||
|
BuildAt: time.Now().Local().Format("2006/01/02 15:04:05"),
|
||||||
|
}
|
|
@ -75,6 +75,12 @@ NotifyBuiltinEnable = true
|
||||||
Enable = false
|
Enable = false
|
||||||
ScriptPath = "./etc/script/notify.py"
|
ScriptPath = "./etc/script/notify.py"
|
||||||
|
|
||||||
|
[Alerting.CallPlugin]
|
||||||
|
Enable = false
|
||||||
|
# use a plugin via `go build -buildmode=plugin -o notify.so`
|
||||||
|
PluginPath = "./etc/script/notify.so"
|
||||||
|
Caller = "n9eCaller"
|
||||||
|
|
||||||
[Alerting.RedisPub]
|
[Alerting.RedisPub]
|
||||||
Enable = false
|
Enable = false
|
||||||
# complete redis key: ${ChannelPrefix} + ${Cluster}
|
# complete redis key: ${ChannelPrefix} + ${Cluster}
|
||||||
|
@ -211,4 +217,4 @@ MaxIdleConnsPerHost = 100
|
||||||
# KeepAlive = 30000
|
# KeepAlive = 30000
|
||||||
# MaxConnsPerHost = 0
|
# MaxConnsPerHost = 0
|
||||||
# MaxIdleConns = 100
|
# MaxIdleConns = 100
|
||||||
# MaxIdleConnsPerHost = 100
|
# MaxIdleConnsPerHost = 100
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -23,7 +23,7 @@ require (
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
github.com/prometheus/common v0.26.0
|
github.com/prometheus/common v0.26.0
|
||||||
github.com/prometheus/prometheus v2.5.0+incompatible
|
github.com/prometheus/prometheus v2.5.0+incompatible
|
||||||
github.com/tidwall/gjson v1.14.0 // indirect
|
github.com/tidwall/gjson v1.14.0
|
||||||
github.com/toolkits/pkg v1.2.9
|
github.com/toolkits/pkg v1.2.9
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
|
||||||
|
@ -31,7 +31,7 @@ require (
|
||||||
google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4 // indirect
|
google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4 // indirect
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
google.golang.org/grpc v1.41.0 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gorm.io/driver/mysql v1.1.2
|
gorm.io/driver/mysql v1.1.2
|
||||||
gorm.io/driver/postgres v1.1.1
|
gorm.io/driver/postgres v1.1.1
|
||||||
gorm.io/gorm v1.21.15
|
gorm.io/gorm v1.21.15
|
||||||
|
|
|
@ -139,6 +139,7 @@ type Alerting struct {
|
||||||
NotifyConcurrency int
|
NotifyConcurrency int
|
||||||
NotifyBuiltinEnable bool
|
NotifyBuiltinEnable bool
|
||||||
CallScript CallScript
|
CallScript CallScript
|
||||||
|
CallPlugin CallPlugin
|
||||||
RedisPub RedisPub
|
RedisPub RedisPub
|
||||||
Webhook Webhook
|
Webhook Webhook
|
||||||
}
|
}
|
||||||
|
@ -148,6 +149,12 @@ type CallScript struct {
|
||||||
ScriptPath string
|
ScriptPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CallPlugin struct {
|
||||||
|
Enable bool
|
||||||
|
PluginPath string
|
||||||
|
Caller string
|
||||||
|
}
|
||||||
|
|
||||||
type RedisPub struct {
|
type RedisPub struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
ChannelPrefix string
|
ChannelPrefix string
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"plugin"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -119,6 +121,8 @@ func alertingRedisPub(bs []byte) {
|
||||||
func handleNotice(notice Notice, bs []byte) {
|
func handleNotice(notice Notice, bs []byte) {
|
||||||
alertingCallScript(bs)
|
alertingCallScript(bs)
|
||||||
|
|
||||||
|
alertingCallPlugin(bs)
|
||||||
|
|
||||||
if !config.C.Alerting.NotifyBuiltinEnable {
|
if !config.C.Alerting.NotifyBuiltinEnable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -396,3 +400,37 @@ func alertingCallScript(stdinBytes []byte) {
|
||||||
|
|
||||||
logger.Infof("event_notify: exec %s output: %s", fpath, buf.String())
|
logger.Infof("event_notify: exec %s output: %s", fpath, buf.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Notifier interface {
|
||||||
|
Descript() string
|
||||||
|
Notify([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// call notify.so via golang plugin build
|
||||||
|
// ig. etc/script/notify/notify.so
|
||||||
|
func alertingCallPlugin(stdinBytes []byte) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
logger.Errorf("call notify plugin on unsupported os: %s", runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !config.C.Alerting.CallPlugin.Enable {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p, err := plugin.Open(config.C.Alerting.CallPlugin.PluginPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("failed to open notify plugin: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
caller, err := p.Lookup(config.C.Alerting.CallPlugin.Caller)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("failed to load caller: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
notifier, ok := caller.(Notifier)
|
||||||
|
if !ok {
|
||||||
|
logger.Errorf("notifier interface not implemented): %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
notifier.Notify(stdinBytes)
|
||||||
|
logger.Debugf("alertingCallPlugin done. %s", notifier.Descript())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue