Created
June 2, 2020 08:40
-
-
Save mojocn/4c1196f144a18bd5a9fe20becde33837 to your computer and use it in GitHub Desktop.
logrus email hook
This file contains hidden or 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 common | |
import ( | |
"bytes" | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"net" | |
"net/mail" | |
"net/smtp" | |
"strconv" | |
"time" | |
"github.com/sirupsen/logrus" | |
) | |
//Logger 可以使用这个logger 也可直接使用logrus | |
var Logger = logrus.New() | |
//SetLogger 初始化logrus 同时把logrus的logger var 引用到这个common.Logger | |
func SetLogger(cfg Config, verbose bool) error { | |
//logFileName := fmt.Sprintf("app.gin.%s.%s.log", cfg.Web.Name, time.Now().Format("20060102T15")) | |
// | |
//f, err := os.Create(logFileName) | |
//if err != nil { | |
// return err | |
//} | |
logLvl, err := logrus.ParseLevel(cfg.LogLevel) | |
if err != nil { | |
return err | |
} | |
logrus.SetLevel(logLvl) | |
logrus.SetReportCaller(true) | |
//logrus.SetFormatter(&logrus.JSONFormatter{}) | |
//使用console默认输出 | |
if (cfg.Env == "dev" || cfg.Env == "test") && cfg.Mail.Host != "" { | |
hook, err := newMailAuthHook(cfg.Web.Name, cfg.Mail.Host, cfg.Mail.Port, cfg.Mail.Limit, cfg.Mail.User, cfg.Mail.User, cfg.Mail.Password, cfg.Mail.Receivers) | |
if err != nil { | |
return err | |
} | |
logrus.AddHook(hook) | |
} | |
//logrus.SetOutput(f) | |
//logrus.SetReportCaller(verbose) | |
Logger = logrus.StandardLogger() | |
return nil | |
} | |
const ( | |
format = "20060102 15:04:05" | |
) | |
// mailHook to sends logs by email with authentication. | |
type mailHook struct { | |
appName string | |
emailHost string | |
emailPort int | |
emailFrom *mail.Address | |
emailTos []string | |
emailUserName string | |
emailPassword string | |
buff *bytes.Buffer | |
count int | |
limit int | |
} | |
// newMailAuthHook creates a hook to be added to an instance of logger. | |
func newMailAuthHook(app string, host string, port, limit int, from string, username string, password string, to []string) (*mailHook, error) { | |
// Check if server listens on that port. | |
conn, err := net.DialTimeout("tcp", host+":"+strconv.Itoa(port), 3*time.Second) | |
if err != nil { | |
return nil, err | |
} | |
defer conn.Close() | |
// Validate sender and recipient | |
sender, err := mail.ParseAddress(from) | |
if err != nil { | |
return nil, err | |
} | |
for _, v := range to { | |
_, err := mail.ParseAddress(v) | |
if err != nil { | |
return nil, fmt.Errorf("%s 不是有效的邮箱:%s", v, err) | |
} | |
} | |
return &mailHook{ | |
appName: app, | |
emailHost: host, | |
emailPort: port, | |
emailFrom: sender, | |
emailTos: to, | |
emailUserName: username, | |
emailPassword: password, | |
buff: bytes.NewBufferString(""), | |
limit: limit, | |
count: 0, | |
}, nil | |
} | |
// Fire is called when a log event is fired. | |
func (hook *mailHook) Fire(entry *logrus.Entry) error { | |
if hook.count < hook.limit { | |
hook.storeError(entry) | |
return nil | |
} | |
return hook.sendEmail() | |
} | |
// Levels returns the available logging levels. | |
func (hook *mailHook) Levels() []logrus.Level { | |
return []logrus.Level{ | |
logrus.PanicLevel, | |
logrus.FatalLevel, | |
logrus.ErrorLevel, | |
} | |
} | |
func (hook *mailHook) storeError(entry *logrus.Entry) { | |
body := entry.Time.Format(format) + " - " + entry.Message | |
hook.buff.WriteString(body) | |
fields, _ := json.MarshalIndent(entry.Data, "", "\t") | |
hook.buff.Write(fields) | |
hook.buff.Write([]byte("\r\n")) | |
callers, _ := json.MarshalIndent(entry.Caller, "", "\t") | |
hook.buff.Write(callers) | |
hook.buff.Write([]byte("\r\n")) | |
hook.count++ | |
} | |
func (hook *mailHook) sendEmail() error { | |
auth := smtp.PlainAuth("", hook.emailUserName, hook.emailPassword, hook.emailHost) | |
subject := hook.appName + " - " + time.Now().Format(format) | |
body, _ := ioutil.ReadAll(hook.buff) | |
hook.buff.Reset() | |
contents := fmt.Sprintf("Subject: %s\r\n\r\n%s", subject, body) | |
hook.count = 0 | |
// Connect to the server, authenticate, set the sender and recipient, | |
// and send the email all in one step. | |
err := smtp.SendMail( | |
hook.emailHost+":"+strconv.Itoa(hook.emailPort), | |
auth, | |
hook.emailFrom.Address, | |
hook.emailTos, | |
[]byte(contents), | |
) | |
if err != nil { | |
return err | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment