diff --git a/Abstractions/Configuration.go b/Abstractions/Configuration.go index 6ef53527..c6bf746f 100644 --- a/Abstractions/Configuration.go +++ b/Abstractions/Configuration.go @@ -14,21 +14,23 @@ type Configuration struct { } func NewConfiguration(configContext *ConfigurationContext) *Configuration { + defaultConfig := viper.New() + flag.String("port", "", "application port") flag.String("profile", configContext.profile, "application profile") pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() - _ = viper.BindPFlags(pflag.CommandLine) - - configContext.profile = viper.GetString("profile") + _ = defaultConfig.BindPFlags(pflag.CommandLine) + if pf := defaultConfig.GetString("profile"); pf != "" { + configContext.profile = pf + } configName := configContext.configName + "_" + configContext.profile exists, _ := Utils.PathExists("./" + configName + "." + configContext.configType) if !exists { configName = configContext.configName } - defaultConfig := viper.New() defaultConfig.AddConfigPath(".") defaultConfig.SetConfigName(configName) defaultConfig.SetConfigType(configContext.configType) diff --git a/Abstractions/HostBuilder.go b/Abstractions/HostBuilder.go index 59545782..c139a0be 100644 --- a/Abstractions/HostBuilder.go +++ b/Abstractions/HostBuilder.go @@ -41,6 +41,10 @@ func (host *HostBuilder) UseConfiguration(configuration IConfiguration) *HostBui if section != nil { config := &Configs.HostConfig{} section.Unmarshal(config) + portInterface := configuration.Get("port") + if portInterface != nil && portInterface.(string) != "" { + config.Server.Address = ":" + portInterface.(string) + } host.Context.HostConfiguration = config } return host diff --git a/Abstractions/XLog/XLogger.go b/Abstractions/XLog/DefaultLogger.go similarity index 100% rename from Abstractions/XLog/XLogger.go rename to Abstractions/XLog/DefaultLogger.go diff --git a/Abstractions/XLog/LogrusLogger.go b/Abstractions/XLog/LogrusLogger.go new file mode 100644 index 00000000..17e5bce1 --- /dev/null +++ b/Abstractions/XLog/LogrusLogger.go @@ -0,0 +1,67 @@ +package XLog + +import ( + "fmt" + logrus "github.com/sirupsen/logrus" + "os" + "time" +) + +type LogrusLogger struct { + logger *logrus.Logger + dateFormat string + class string +} + +func NewLogger() ILogger { + logger := logrus.New() + return &LogrusLogger{logger: logger, dateFormat: LoggerDefaultDateFormat} +} + +func GetClassLogger(class string) ILogger { + logger := logrus.New() + return &LogrusLogger{logger: logger, class: class, dateFormat: LoggerDefaultDateFormat} +} + +func (log *LogrusLogger) log(level LogLevel, fiedls map[string]interface{}, format string, a ...interface{}) *logrus.Entry { + hostName, _ := os.Hostname() + message := format + message = fmt.Sprintf(format, a...) + start := time.Now() + + fieldsMap := make(map[string]interface{}) + if fiedls != nil { + fieldsMap = fiedls + } + fieldsMap["StartTime"] = start.Format(log.dateFormat) + fieldsMap["Level"] = LevelString[level] + fieldsMap["Class"] = log.class + fieldsMap["Host"] = hostName + fieldsMap["Message"] = message + + return logrus.WithFields(fieldsMap) +} + +func (l LogrusLogger) Debug(format string, a ...interface{}) { + panic("implement me") +} + +func (l LogrusLogger) Info(format string, a ...interface{}) { + panic("implement me") +} + +func (l LogrusLogger) Warning(format string, a ...interface{}) { + panic("implement me") +} + +func (l LogrusLogger) Error(format string, a ...interface{}) { + panic("implement me") +} + +func (l LogrusLogger) SetCustomLogFormat(logFormatterFunc func(logInfo LogInfo) string) { + panic("implement me") +} + +func (l LogrusLogger) SetDateFormat(format string) { + panic("implement me") +} diff --git a/Abstractions/XLog/logInfo.go b/Abstractions/XLog/logInfo.go index 8a21940e..80b71c2f 100644 --- a/Abstractions/XLog/logInfo.go +++ b/Abstractions/XLog/logInfo.go @@ -6,4 +6,5 @@ type LogInfo struct { Class string Host string Message string + Extend map[string]interface{} } diff --git a/Examples/GrafanaAlertWebHook/WechatRequests/GrafanaAlertRequest.go b/Examples/GrafanaAlertWebHook/WechatRequests/GrafanaAlertRequest.go new file mode 100644 index 00000000..7d1aad8f --- /dev/null +++ b/Examples/GrafanaAlertWebHook/WechatRequests/GrafanaAlertRequest.go @@ -0,0 +1,35 @@ +package WechatRequests + +import "strconv" + +type GrafanaAlertRequest struct { + PanelID int `json:"panelId" gorm:"column:panelId"` + DashboardID int `json:"dashboardId" gorm:"column:dashboardId"` + ImageUrl string `json:"imageUrl" gorm:"column:imageUrl"` + RuleName string `json:"ruleName" gorm:"column:ruleName"` + State string `json:"state" gorm:"column:state"` + Message string `json:"message" gorm:"column:message"` + RuleID int `json:"ruleId" gorm:"column:ruleId"` + Title string `json:"title" gorm:"column:title"` + RuleUrl string `json:"ruleUrl" gorm:"column:ruleUrl"` + OrgID int `json:"orgId" gorm:"column:orgId"` + + EvalMatches []struct { + Metric string `json:"metric" gorm:"column:metric"` + Value int `json:"value" gorm:"column:value"` + Tags struct{} `json:"tags" gorm:"column:tags"` + } `json:"evalMatches" gorm:"column:evalMatches"` + + Tags map[string]string `json:"tags" gorm:"column:tags"` +} + +func (request GrafanaAlertRequest) GetMetricValue() string { + if len(request.EvalMatches) > 0 { + return strconv.Itoa(request.EvalMatches[0].Value) + } + return "0" +} + +func (request GrafanaAlertRequest) GetTag() string { + return request.Tags["alert"] +} diff --git a/Examples/GrafanaAlertWebHook/WechatRequests/MarkdownMessage.go b/Examples/GrafanaAlertWebHook/WechatRequests/MarkdownMessage.go new file mode 100644 index 00000000..343e3a05 --- /dev/null +++ b/Examples/GrafanaAlertWebHook/WechatRequests/MarkdownMessage.go @@ -0,0 +1,8 @@ +package WechatRequests + +type MarkdownMessage struct { + Markdown struct { + Content string `json:"content" gorm:"column:content"` + } `json:"markdown" gorm:"column:markdown"` + Msgtype string `json:"msgtype" gorm:"column:msgtype"` +} diff --git a/Examples/GrafanaAlertWebHook/WechatRequests/QiyeWechat.go b/Examples/GrafanaAlertWebHook/WechatRequests/QiyeWechat.go new file mode 100644 index 00000000..aa0859bf --- /dev/null +++ b/Examples/GrafanaAlertWebHook/WechatRequests/QiyeWechat.go @@ -0,0 +1,59 @@ +package WechatRequests + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/yoyofx/yoyogo/Abstractions" + "github.com/yoyofx/yoyogo/Abstractions/XLog" + "io/ioutil" + "net/http" +) + +func postWechatMessage(sendUrl, msg string) string { + client := &http.Client{} + req, _ := http.NewRequest("POST", sendUrl, bytes.NewBuffer([]byte(msg))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("charset", "UTF-8") + resp, err := client.Do(req) + if err != nil { + panic(err) + } + defer resp.Body.Close() + fmt.Println("response Status:", resp.Status) + body, _ := ioutil.ReadAll(resp.Body) + strBody := string(body) + fmt.Println("response Body:", strBody) + return strBody +} + +func SendTxtMessage(request GrafanaAlertRequest, config Abstractions.IConfiguration) string { + tag := request.GetTag() + logger := XLog.GetXLogger("wechat") + js, _ := json.Marshal(request) + logger.Info(string(js)) + if tag == "" { + logger.Info("no send") + return "" + } + sendUrl := config.Get("alert.webhook_url").(string) + linkUrl := config.Get(fmt.Sprintf("alert.%s.link_url", tag)).(string) + var message *MarkdownMessage + if request.State == "alerting" && len(request.EvalMatches) > 0 { + message = &MarkdownMessage{ + Markdown: struct { + Content string `json:"content" gorm:"column:content"` + }{ + Content: request.RuleName + ",请相关同事注意。\n" + + " > [报警次数]:" + request.GetMetricValue() + "次" + "\n" + + " > [报警明细](" + linkUrl + ")\n", + }, + Msgtype: "markdown", + } + } + msg, _ := json.Marshal(message) + msgStr := string(msg) + logger.Info("send message:%s", msgStr) + + return postWechatMessage(sendUrl, msgStr) +} diff --git a/Examples/GrafanaAlertWebHook/config.yml b/Examples/GrafanaAlertWebHook/config.yml new file mode 100644 index 00000000..a9dacbd4 --- /dev/null +++ b/Examples/GrafanaAlertWebHook/config.yml @@ -0,0 +1,16 @@ +yoyogo: + application: + name: Alert + metadata: "" + server: + type: "fasthttp" + address: ":8089" + max_request_size: 2096157 + +# alert通过 tag识别节点值 +alert: + webhook_url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=014f19d9-929e-4349-9b0f-ee57d868da9e + jishi: + link_url: http://jcenter-main.easypass.cn/jiankong/d/trpHG7FGk/che-hou-ye-wu-ri-zhi-cha-xun?orgId=1&from=now-1h&to=now&var-app=jishi*&var-level=error&var-host=All&var-msg=* + znbk: + link_url: http://jcenter-main.easypass.cn/jiankong/d/trpHG7FGk/che-hou-ye-wu-ri-zhi-cha-xun?orgId=1&from=now-1h&to=now&var-app=zhineng*&var-level=error&var-host=All&var-msg=* diff --git a/Examples/GrafanaAlertWebHook/controller.go b/Examples/GrafanaAlertWebHook/controller.go new file mode 100644 index 00000000..1e727ad3 --- /dev/null +++ b/Examples/GrafanaAlertWebHook/controller.go @@ -0,0 +1,43 @@ +package main + +import ( + "GrafanaAlertWebHook/WechatRequests" + "github.com/yoyofx/yoyogo/Abstractions" + "github.com/yoyofx/yoyogo/WebFramework/Context" +) + +func PostAlert(ctx *Context.HttpContext) { + var request WechatRequests.GrafanaAlertRequest + _ = ctx.Bind(&request) + var config Abstractions.IConfiguration + _ = ctx.RequiredServices.GetService(&config) + + ctx.JSON(200, Context.H{ + "Message": WechatRequests.SendTxtMessage(request, config), + }) + + //var message WechatRequests.MarkdownMessage + //if request.State == "alerting" && len(request.EvalMatches) > 0 { + // message = WechatRequests.MarkdownMessage{ + // Markdown: struct { + // Content string `json:"content" gorm:"column:content"` + // }{ + // Content: request.RuleName + ",请相关同事注意。\n" + + // " > [报警次数]:" + strconv.Itoa(request.EvalMatches[0].Value) + "次" + "\n" + + // " > [报警明细](http://jcenter-main.easypass.cn/jiankong/d/trpHG7FGk/che-hou-ye-wu-ri-zhi-cha-xun?orgId=1&from=now-1h&to=now&var-app=jishi*&var-level=error&var-host=All&var-msg=*)\n", + // }, + // Msgtype: "markdown", + // } + // //msg, _ := json.Marshal(message) + // //sendUrl := "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=efaebe93-7b21-4bc3-888f-260744f397ac" + // //ctx.JSON(200, Context.H{ + // // "Message": postWechatMessage(sendUrl,string(msg)), + // //}) + // ctx.JSON(200, message) + //} + //msg, _ := json.Marshal(message) + // + //ctx.JSON(200,Context.H{ + // "Message":postWechatMessage(string(msg)) , + //}) +} diff --git a/Examples/GrafanaAlertWebHook/go.mod b/Examples/GrafanaAlertWebHook/go.mod new file mode 100644 index 00000000..9f301256 --- /dev/null +++ b/Examples/GrafanaAlertWebHook/go.mod @@ -0,0 +1,9 @@ +module GrafanaAlertWebHook + +go 1.15 + +require github.com/yoyofx/yoyogo v0.0.0 + +replace ( + github.com/yoyofx/yoyogo => ../../ +) \ No newline at end of file diff --git a/Examples/GrafanaAlertWebHook/main.go b/Examples/GrafanaAlertWebHook/main.go new file mode 100644 index 00000000..cbf3b1f7 --- /dev/null +++ b/Examples/GrafanaAlertWebHook/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/yoyofx/yoyogo/Abstractions" + "github.com/yoyofx/yoyogo/WebFramework" + "github.com/yoyofx/yoyogo/WebFramework/Router" +) + +func main() { + configuration := Abstractions.NewConfigurationBuilder().AddYamlFile("config").Build() + // --profile=prod , to read , config.yml + YoyoGo.NewWebHostBuilder(). + UseConfiguration(configuration). + Configure(func(app *YoyoGo.WebApplicationBuilder) { + app.UseEndpoints(func(router Router.IRouterBuilder) { + router.POST("/alert", PostAlert) + }) + }).Build().Run() +} diff --git a/Examples/SimpleWeb/config_dev.yml b/Examples/SimpleWeb/config_dev.yml index 548b130d..3c3e7f1e 100644 --- a/Examples/SimpleWeb/config_dev.yml +++ b/Examples/SimpleWeb/config_dev.yml @@ -4,7 +4,7 @@ yoyogo: metadata: "develop" server: type: "fasthttp" - address: ":8081" + address: ":8082" max_request_size: 2096157 static: patten: "/" diff --git a/Version.go b/Version.go index 9d47c1c4..2dc237cb 100644 --- a/Version.go +++ b/Version.go @@ -2,7 +2,7 @@ package YoyoGo const ( //Application Version, such as v1.x.x pre-release - Version = "v1.5.3.release" + Version = "v1.5.5.release" //Application logo Logo = "IF8gICAgIF8gICAgICAgICAgICAgICAgICAgIF9fXyAgICAgICAgICAKKCApICAgKCApICAgICAgICAgICAgICAgICAgKCAgX2BcICAgICAgICAKYFxgXF8vJy8nXyAgICBfICAgXyAgICBfICAgfCAoIChfKSAgIF8gICAKICBgXCAvJy8nX2BcICggKSAoICkgLydfYFwgfCB8X19fICAvJ19gXCAKICAgfCB8KCAoXykgKXwgKF8pIHwoIChfKSApfCAoXywgKSggKF8pICkKICAgKF8pYFxfX18vJ2BcX18sIHxgXF9fXy8nKF9fX18vJ2BcX19fLycKICAgICAgICAgICAgICggKV98IHwgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgIGBcX19fLycgICAgICAgICAgICBMaWdodCBhbmQgZmFzdC4gIA==" ) diff --git a/go.mod b/go.mod index b6c4710d..e36c4069 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v0.9.3 + github.com/sirupsen/logrus v1.2.0 github.com/spf13/pflag v1.0.3 github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.6.1 diff --git a/go.sum b/go.sum index 5a3c8001..19e90d55 100644 --- a/go.sum +++ b/go.sum @@ -172,6 +172,7 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc= github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -254,6 +255,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=