Created
May 3, 2023 17:43
-
-
Save womchik/910d2dc5667c9aca41d01c2f599d47c3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/json" | |
"fmt" | |
log "github.com/sirupsen/logrus" | |
"github.com/spf13/viper" | |
"io" | |
"net/http" | |
"net/url" | |
"os" | |
"strconv" | |
"strings" | |
"time" | |
"unicode/utf8" | |
) | |
const ( | |
defaultDelay = 100 | |
defaultLimit = "100" | |
defaultQuery = "{namespace=~\"firecore.+\"} |~ \"PANIC\"" | |
defaultLokiUrl = "http://localhost:3100" | |
fakeSend = false | |
maxLen = 4000 | |
) | |
var ( | |
chatID int64 | |
apiToken string | |
delay int | |
query string | |
limit string | |
lokiUrl string | |
) | |
type Message struct { | |
ChatID int64 `json:"chat_id"` | |
Text string `json:"text"` | |
ParseMode string `json:"parse_mode"` | |
} | |
type Response struct { | |
Status string `json:"status"` | |
Data struct { | |
ResultType string `json:"resultType"` | |
Result []QueryResult | |
} `json:"data"` | |
} | |
type QueryResult struct { | |
Stream interface{} `json:"stream"` | |
Values [][]string `json:"values"` | |
} | |
type TelegramResponse struct { | |
Ok bool `json:"ok"` | |
ErrorCode int `json:"error_code"` | |
Description string `json:"description"` | |
} | |
func SplitHeader(longString string) []string { | |
splits := []string{} | |
var l, r int | |
for l, r = 0, maxLen; r < len(longString); l, r = r, r+maxLen { | |
for !utf8.RuneStart(longString[r]) { | |
r-- | |
} | |
splits = append(splits, longString[l:r]) | |
} | |
splits = append(splits, longString[l:]) | |
return splits | |
} | |
func GetToken(configPath string) error { | |
viper.AutomaticEnv() | |
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) | |
viper.SetDefault("LOGLEVEL", "debug") | |
viper.SetDefault("QUERY", defaultQuery) | |
viper.SetDefault("DELAY", defaultDelay) | |
viper.SetDefault("LIMIT", defaultLimit) | |
viper.SetDefault("LOKI_URL", defaultLokiUrl) | |
if configPath != "" { | |
log.Infof("Parsing config: %s", configPath) | |
viper.SetConfigFile(configPath) | |
err := viper.ReadInConfig() | |
if err != nil { | |
log.Warnf("Unable to read config file: %s", err) | |
} | |
} else { | |
log.Warnf("Config file is not specified.") | |
} | |
logLevelString := viper.GetString("loglevel") | |
logLevel, err := log.ParseLevel(logLevelString) | |
if err != nil { | |
log.Errorf("Unable to parse loglevel: %s", logLevelString) | |
} | |
log.SetLevel(logLevel) | |
apiToken = viper.GetString("BOT_TOKEN") | |
if apiToken == "" { | |
log.Errorf("Bot token error") | |
os.Exit(2) | |
} | |
delay = viper.GetInt("DELAY") | |
limit = viper.GetString("LIMIT") | |
chatID = viper.GetInt64("CHAT_ID") | |
apiToken = viper.GetString("BOT_TOKEN") | |
query = viper.GetString("QUERY") | |
lokiUrl = viper.GetString("LOKI_URL") | |
log.Infof("%s", apiToken) | |
log.Infof("%v", chatID) | |
log.Infof("%v", delay) | |
log.Infof("%v", query) | |
return nil | |
} | |
func SendMessage(url string, message *Message) error { | |
if fakeSend { | |
return nil | |
} | |
payload, err := json.Marshal(message) | |
if err != nil { | |
return err | |
} | |
response, err := http.Post(url, "application/json", bytes.NewBuffer(payload)) | |
if err != nil { | |
return err | |
} | |
resp, _ := io.ReadAll(response.Body) | |
defer func(body io.ReadCloser) { | |
if err := body.Close(); err != nil { | |
log.Println("failed to close response body") | |
} | |
}(response.Body) | |
if response.StatusCode != http.StatusOK { | |
var tgResp TelegramResponse | |
if err := json.Unmarshal(resp, &tgResp); err != nil { | |
log.Errorf("SendMessage UnMarshal error") | |
} | |
return fmt.Errorf("failed to send successful request. Status was %d, text %s", tgResp.ErrorCode, tgResp.Description) | |
} | |
return nil | |
} | |
func main() { | |
customFormatter := new(log.TextFormatter) | |
customFormatter.TimestampFormat = "2006-01-02 15:04:05" | |
customFormatter.FullTimestamp = true | |
customFormatter.DisableLevelTruncation = false | |
log.SetFormatter(customFormatter) | |
err := GetToken(".env") | |
if err != nil { | |
log.Panicf("GetEnv error") | |
} | |
tgUrl := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", apiToken) | |
log.Infof(tgUrl) | |
now := time.Now() | |
endNano := strconv.FormatInt(now.UnixNano(), 10) | |
startNano := strconv.FormatInt(now.Add(-time.Minute*10).UnixNano(), 10) | |
//query = "{namespace=~\"firecore-.+\"} |~ \"ERROR|CRITICAL\" !~ \"401 error\" !~ \"paid has been failed\" !~ \"paid is failed\" !~ \"no more reserve\" !~ \"onlineCommission\" !~ \"apple\"" | |
params := url.Values{} | |
params.Add("direction", "BACKWARD") | |
params.Add("limit", limit) | |
params.Add("query", query) | |
params.Add("start", startNano) | |
params.Add("end", endNano) | |
params.Add("step", "2") | |
lokiFullUrl := fmt.Sprintf("%s/loki/api/v1/query_range?%s", strings.TrimSuffix(lokiUrl, "/"), params.Encode()) | |
log.Infoln(lokiFullUrl) | |
req, err := http.NewRequest(http.MethodGet, lokiFullUrl, nil) | |
if err != nil { | |
log.Errorln(err) | |
os.Exit(2) | |
} | |
resp, err := http.DefaultClient.Do(req) | |
if err != nil { | |
log.Errorln(err) | |
os.Exit(3) | |
} | |
defer func() { | |
err := resp.Body.Close() | |
if err != nil { | |
log.Fatal(err) | |
} | |
}() | |
if resp.StatusCode != 200 { | |
log.Errorln("The requested URL was not found.") | |
} | |
body, err := io.ReadAll(resp.Body) | |
if err != nil { | |
log.Errorln(err) | |
os.Exit(3) | |
} | |
var f Response | |
if err := json.Unmarshal([]byte(body), &f); err != nil { | |
log.Errorln("Can't unmarshal JSON") | |
} | |
var str strings.Builder | |
for _, r := range f.Data.Result { | |
//str.Reset() | |
ErrorLine := r.Stream.(map[string]interface{}) | |
pre := fmt.Sprintf("<b>%s/%s:</b> ", ErrorLine["namespace"], ErrorLine["container"]) | |
str.WriteString(pre) | |
//str.WriteString("```") | |
for _, v := range r.Values { | |
str.WriteString(v[1]) | |
} | |
str.WriteString("\n") | |
//str.WriteString("```\n") | |
//msg := Message{chatID, str.String(), "Markdown"} | |
//Messages = append(Messages, msg) | |
} | |
MessagesCount := 0 | |
for _, s := range SplitHeader(str.String()) { | |
msg := Message{chatID, s, "HTML"} | |
log.Infof("%d: %s\n", len(s), s) | |
if len(s) > 0 { | |
err = SendMessage(tgUrl, &msg) | |
MessagesCount += 1 | |
if err != nil { | |
log.Errorln(err) | |
} | |
} | |
} | |
log.Infof(strconv.Itoa(MessagesCount)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment