kra/internal/server/middleware/email.go

79 lines
1.9 KiB
Go

package middleware
import (
"bytes"
"context"
"fmt"
"io"
"time"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware"
"github.com/go-kratos/kratos/v2/transport"
kratoshttp "github.com/go-kratos/kratos/v2/transport/http"
)
// EmailSender 邮件发送接口
type EmailSender interface {
SendError(subject, body string) error
}
// ErrorToEmail 错误邮件通知中间件
func ErrorToEmail(sender EmailSender, logger log.Logger) middleware.Middleware {
helper := log.NewHelper(logger)
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (interface{}, error) {
var (
username string
body string
method string
path string
ip string
)
// 获取用户信息
if claims, ok := GetClaims(ctx); ok {
username = claims.Username
}
if username == "" {
username = "Unknown"
}
if tr, ok := transport.FromServerContext(ctx); ok {
path = tr.Operation()
if header := tr.RequestHeader(); header != nil {
method = header.Get(":method")
}
if ht, ok := tr.(kratoshttp.Transporter); ok {
r := ht.Request()
ip = getClientIP(r)
// 读取body
bodyBytes, _ := io.ReadAll(r.Body)
r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
body = string(bodyBytes)
}
}
start := time.Now()
reply, err := handler(ctx, req)
latency := time.Since(start)
// 如果有错误,发送邮件
if err != nil && sender != nil {
subject := fmt.Sprintf("%s %s调用了%s报错了", username, ip, path)
content := fmt.Sprintf(
"接收到的请求为%s\n请求方式为%s\n报错信息如下%s\n耗时%s\n",
body, method, err.Error(), latency.String(),
)
if sendErr := sender.SendError(subject, content); sendErr != nil {
helper.Error("ErrorToEmail Failed, err:", sendErr)
}
}
return reply, err
}
}
}