* [#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
|
||||
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]
|
||||
Enable = false
|
||||
# complete redis key: ${ChannelPrefix} + ${Cluster}
|
||||
|
@ -211,4 +217,4 @@ MaxIdleConnsPerHost = 100
|
|||
# KeepAlive = 30000
|
||||
# MaxConnsPerHost = 0
|
||||
# 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/common v0.26.0
|
||||
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/urfave/cli/v2 v2.3.0
|
||||
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/grpc v1.41.0 // 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/postgres v1.1.1
|
||||
gorm.io/gorm v1.21.15
|
||||
|
|
|
@ -139,6 +139,7 @@ type Alerting struct {
|
|||
NotifyConcurrency int
|
||||
NotifyBuiltinEnable bool
|
||||
CallScript CallScript
|
||||
CallPlugin CallPlugin
|
||||
RedisPub RedisPub
|
||||
Webhook Webhook
|
||||
}
|
||||
|
@ -148,6 +149,12 @@ type CallScript struct {
|
|||
ScriptPath string
|
||||
}
|
||||
|
||||
type CallPlugin struct {
|
||||
Enable bool
|
||||
PluginPath string
|
||||
Caller string
|
||||
}
|
||||
|
||||
type RedisPub struct {
|
||||
Enable bool
|
||||
ChannelPrefix string
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"net/http"
|
||||
"os/exec"
|
||||
"path"
|
||||
"plugin"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -119,6 +121,8 @@ func alertingRedisPub(bs []byte) {
|
|||
func handleNotice(notice Notice, bs []byte) {
|
||||
alertingCallScript(bs)
|
||||
|
||||
alertingCallPlugin(bs)
|
||||
|
||||
if !config.C.Alerting.NotifyBuiltinEnable {
|
||||
return
|
||||
}
|
||||
|
@ -396,3 +400,37 @@ func alertingCallScript(stdinBytes []byte) {
|
|||
|
||||
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