[Series] go-gin-api routing middleware - catch exceptions (four)

Outline

First synchronization under the project:

Share on articles, and routing middleware - logging, share this article: routing middleware - catch the exception. When an exception occurs the system, suggesting that "abnormalities, please contact the administrator!", And at the same time send a panic alarm messages.

What is abnormal?

Go exception is in panic, it is when the program runs thrown, when panic is thrown, if not added any protective measures in the program, then the console will print out the details of panic, and then terminates .

We can panic divided into two types:

One is intentionally thrown, for example,

panic("自定义的 panic 信息")

Output:

2019/09/10 20:25:27 http: panic serving [::1]:61547: 自定义的 panic 信息
goroutine 8 [running]:
...

One is inadvertently thrown, resulting in sloppy writing program, for example,

var slice = [] int {1, 2, 3, 4, 5}

slice[6] = 6

Output:

2019/09/10 15:27:05 http: panic serving [::1]:61616: runtime error: index out of range
goroutine 6 [running]:
...

Imagine if the online environment has panic, command line output, because we can not capture it can not locate the problem, think about all the terrible, so the question is, how to catch the exception?

How to catch exceptions?

When the program occurs panic, inside the defer (delay function) call can recover capture.

Not much to say, directly on the code:

defer func() {
    if err := recover(); err != nil {
        fmt.Println(err)
    }
}()

In the run about "unintentional thrown panic", output:

runtime error: index out of range

OK, error capture, and then we can make a fuss.

Zuosa article, we should all know by now:

  • Gets called runtime stack (debug.Stack ())
  • Request data acquired at the time of
  • Assembling data, e-mail

So, Go how mail it, there is no open source package it?

Of course there is, please read on.

The method of packaging mail

Use package:gopkg.in/gomail.v2

Directly on the code:

func SendMail(mailTo string, subject string, body string) error {
    
    if config.ErrorNotifyOpen != 1 {
        return nil
    }

    m := gomail.NewMessage()

    //设置发件人
    m.SetHeader("From", config.SystemEmailUser)

    //设置发送给多个用户
    mailArrTo := strings.Split(mailTo, ",")
    m.SetHeader("To", mailArrTo...)

    //设置邮件主题
    m.SetHeader("Subject", subject)

    //设置邮件正文
    m.SetBody("text/html", body)

    d := gomail.NewDialer(config.SystemEmailHost, config.SystemEmailPort, config.SystemEmailUser, config.SystemEmailPass)

    err := d.DialAndSend(m)
    if err != nil {
        fmt.Println(err)
    }
    return err
}

In this piece I added a switch, would like to open want to turn off, you are free.

Now send mail, and then the entire message template is perfect.

Custom Mail Templates

Figure:

This is the template warning messages, it is not bad, what you want to record, you can customize to modify.

One intermediate package

Finally, look at the package.

Directly on the code:

func SetUp() gin.HandlerFunc {

    return func(c *gin.Context) {
        defer func() {
            if err := recover(); err != nil {

                DebugStack := ""
                for _, v := range strings.Split(string(debug.Stack()), "\n") {
                    DebugStack += v + "<br>"
                }

                subject := fmt.Sprintf("【重要错误】%s 项目出错了!", config.AppName)

                body := strings.ReplaceAll(MailTemplate, "{ErrorMsg}", fmt.Sprintf("%s", err))
                body  = strings.ReplaceAll(body, "{RequestTime}", util.GetCurrentDate())
                body  = strings.ReplaceAll(body, "{RequestURL}", c.Request.Method + "  " + c.Request.Host + c.Request.RequestURI)
                body  = strings.ReplaceAll(body, "{RequestUA}", c.Request.UserAgent())
                body  = strings.ReplaceAll(body, "{RequestIP}", c.ClientIP())
                body  = strings.ReplaceAll(body, "{DebugStack}", DebugStack)

                _ = util.SendMail(config.ErrorNotifyUser, subject, body)

                utilGin := util.Gin{Ctx: c}
                utilGin.Response(500, "系统异常,请联系管理员!", nil)
            }
        }()
        c.Next()
    }
}

When a panic abnormality occurs, output:

{
    "code": 500,
    "msg": "系统异常,请联系管理员!",
    "data": null
}

Meanwhile, the panic alarm will also receive an e-mail.

Easy shots, DebugStack deletion of some information.

With this, it is over.

Remark

  • Mail place, it can adjust sent asynchronously.
  • Article posted only part of the code, please refer to the relevant code github.
  • When the test mail, be sure to configure the mailbox information.

Source Address

https://github.com/xinliangnote/go-gin-api

go-gin-api series

Guess you like

Origin www.cnblogs.com/xinliangcoder/p/11505645.html