Skip to content

Commit

Permalink
Add telegram alert channel
Browse files Browse the repository at this point in the history
  • Loading branch information
wanliqun committed May 6, 2024
1 parent 57bf8df commit cd85a3c
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 16 deletions.
1 change: 1 addition & 0 deletions alert/alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type ChannelType string

const (
ChannelTypeDingTalk ChannelType = "dingtalk"
ChannelTypeTelegram ChannelType = "telegram"
)

// Notification channel interface.
Expand Down
3 changes: 1 addition & 2 deletions alert/dingtalk.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ var (
)

type DingTalkConfig struct {
Platform string // notify platform
AtMobiles []string // mobiles for @ members
IsAtAll bool // whether to @ all members
Webhook string // webhook url
Expand All @@ -33,7 +32,7 @@ func (dtc *DingTalkChannel) Name() string {
}

func (dtc *DingTalkChannel) Type() ChannelType {
return ChannelType(dtc.Config.Platform)
return ChannelTypeDingTalk
}

func (dtc *DingTalkChannel) Send(note *Notification) error {
Expand Down
60 changes: 60 additions & 0 deletions alert/telegram.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package alert

import (
"context"

"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
"github.com/pkg/errors"
)

var (
_ Channel = (*TelegramChannel)(nil)
)

type TelegramConfig struct {
ApiToken string // Api token
ChatId string // Chat ID
}

// TelegramChannel Telegram notification channel
type TelegramChannel struct {
Formatter Formatter // message formatter
ID string // channel id
Config TelegramConfig // channel config

bot *bot.Bot
}

func NewTelegramChannel(chID string, fmt Formatter, conf TelegramConfig) (*TelegramChannel, error) {
bot, err := bot.New(conf.ApiToken)
if err != nil {
return nil, err
}

tc := &TelegramChannel{ID: chID, Formatter: fmt, Config: conf, bot: bot}
return tc, nil
}

func (tc *TelegramChannel) Name() string {
return tc.ID
}

func (tc *TelegramChannel) Type() ChannelType {
return ChannelTypeTelegram
}

func (tc *TelegramChannel) Send(note *Notification) error {
msg, err := tc.Formatter.Format(note)
if err != nil {
return errors.WithMessage(err, "failed to format alert msg")
}

_, err = tc.bot.SendMessage(context.Background(), &bot.SendMessageParams{
ChatID: tc.Config.ChatId,
Text: msg,
ParseMode: models.ParseModeHTML,
})

return err
}
8 changes: 8 additions & 0 deletions alert/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ func parseAlertChannel(chID string, chmap map[string]interface{}, fmt Formatter)
}

return NewDingTalkChannel(chID, fmt, dtconf), nil
case ChannelTypeTelegram:
var tgconf TelegramConfig
if err := decodeChannelConfig(chmap, &tgconf); err != nil {
return nil, err
}

return NewTelegramChannel(chID, fmt, tgconf)

// NOTE: add more channel types support here if needed
default:
return nil, ErrChannelTypeNotSupported(cht)
Expand Down
5 changes: 5 additions & 0 deletions config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
# secret: ${your_access_secret}
# atMobiles: []
# isAtAll: false
# tgrobot:
# platform: telegram
# apiToken: ${your_api_token}
# chatId: ${your_chat_id}


# REST API Configurations
# api:
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.7.7
github.com/go-playground/validator/v10 v10.4.1
github.com/go-telegram/bot v1.2.2
github.com/mcuadros/go-defaults v1.2.0
github.com/mitchellh/mapstructure v1.4.3
github.com/pkg/errors v0.9.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-telegram/bot v1.2.2 h1:LwGbSzjcSi0w4Ke8JUpgbBhJwwYTl2ITmhubeM2WvN8=
github.com/go-telegram/bot v1.2.2/go.mod h1:i2TRs7fXWIeaceF3z7KzsMt/he0TwkVC680mvdTFYeM=
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
Expand Down
43 changes: 29 additions & 14 deletions log/hook/hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,50 @@ import (
)

var (
dingrobot *alert.DingTalkChannel
channels []alert.Channel
)

// Please set the following enviroments before running tests:
// `TEST_DINGTALK_WEBHOOK`: DingTalk webhook;
// `TEST_DINGTALK_SECRET`: DingTalk secret.

// `TEST_DINGTALK_SECRET`: DingTalk secret;
// `TEST_TELEGRAM_API_TOKEN`: Telegram API token;
// `TEST_TELEGRAM_CHAT_ID`: Telegram chat ID.
func TestMain(m *testing.M) {
webhook := os.Getenv("TEST_DINGTALK_WEBHOOK")
secret := os.Getenv("TEST_DINGTALK_SECRET")
fmtter := alert.NewSimpleTextFormatter([]string{"log", "hook", "test"})

if len(webhook) == 0 || len(secret) == 0 {
return
dtWebhook := os.Getenv("TEST_DINGTALK_WEBHOOK")
dtSecret := os.Getenv("TEST_DINGTALK_SECRET")
if len(dtWebhook) > 0 && len(dtSecret) > 0 {
dingrobot := alert.NewDingTalkChannel("dingrobot", fmtter, alert.DingTalkConfig{
Webhook: dtWebhook, Secret: dtSecret,
})
channels = append(channels, dingrobot)
}

fmtter := alert.NewSimpleTextFormatter([]string{"log", "hook", "test"})
dingrobot = alert.NewDingTalkChannel("dingrobot", fmtter, alert.DingTalkConfig{
Platform: string(alert.ChannelTypeDingTalk),
Webhook: webhook,
Secret: secret,
})
tgApiToken := os.Getenv("TEST_TELEGRAM_API_TOKEN")
tgChatId := os.Getenv("TEST_TELEGRAM_API_TOKEN")
if len(tgApiToken) > 0 && len(tgChatId) > 0 {
tgrobot, err := alert.NewTelegramChannel("tgrobot", fmtter, alert.TelegramConfig{
ApiToken: tgApiToken, ChatId: tgChatId,
})
if err != nil {
logrus.WithError(err).Fatal("Failed to new telegram channel")
}

channels = append(channels, tgrobot)
}

os.Exit(m.Run())
}

func TestLogrusAddHooks(t *testing.T) {
if len(channels) == 0 {
return
}

// Add alert hook for logrus fatal/warn/error level
hookLevels := []logrus.Level{logrus.FatalLevel, logrus.WarnLevel, logrus.ErrorLevel}
logrus.AddHook(NewAlertHook(hookLevels, []alert.Channel{dingrobot}))
logrus.AddHook(NewAlertHook(hookLevels, channels))

// Need to manually check if message sent to dingtalk group chat
logrus.Warn("Test logrus add hooks warns")
Expand Down

0 comments on commit cd85a3c

Please sign in to comment.