// Copyright 2019 github.com. All rights reserved. // Use of this source code is governed by github.com. package httptasker import ( "fmt" "net/http" "time" "github.com/gin-gonic/gin" "git.getensh.com/common/gopkgs/tasker" "go.uber.org/zap" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "git.getensh.com/common/gopkgs/logger" ) // Error 出错时数据结构 type Error struct { Code codes.Code `json:"code"` Message string `json:"message"` } // Task 任务函数 type Task func() error // Exec 执行任务 func Exec(ctx *gin.Context, tasks ...Task) (err error) { // 进程中断中,不再处理任务 if tasker.Interrupted() { return tasker.InterruptError } // 开始时间 startTime := uint64(time.Now().UnixNano()) // 抓异常代码 defer func() { if r := recover(); r != nil { if e, ok := r.(error); ok { err = e } else { err = fmt.Errorf("%+v", r) logger.Error("err", zap.String("system_err", err.Error()), zap.Stack("stacktrace")) } s := status.New(10002, "内部服务错误") if v, ok := status.FromError(err); ok { s = v } ctx.JSON(http.StatusOK, Error{Code: s.Code(), Message: s.Message()}) // 打印到access.log日志中 endTime := uint64(time.Now().UnixNano()) tasker.LogInfo(ctx.Request.Method, zap.String("path", ctx.Request.URL.Path), zap.String("status", "failure"), zap.String("elapsed", fmt.Sprintf("%fms", float64(endTime-startTime)/1000000)), zap.String("remote_addr", ctx.Request.RemoteAddr), // 这里必须要配置nginx正确,否则内网IP zap.String("error", err.Error())) // 具体的错误消息 return // 这里必须返回 } // TODO 需要记录哪些信息 // 打印到access.log日志中 endTime := uint64(time.Now().UnixNano()) tasker.LogInfo(ctx.Request.Method, zap.String("path", ctx.Request.URL.Path), zap.String("status", "success"), zap.String("elapsed", fmt.Sprintf("%fms", float64(endTime-startTime)/1000000)), zap.String("remote_addr", ctx.Request.RemoteAddr)) // 这里必须要配置nginx正确,否则内网IP }() // 按顺序执行任务 for _, task := range tasks { if task != nil { if err = task(); err != nil { panic(err) } } } return }