Browse Source

Merge pull request #283 from SliverHorn/sliverhorn_dev

gorm日志收集进log功能
main
奇淼(piexlmax 4 years ago
committed by GitHub
parent
commit
52f5e831cc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      server/config.yaml
  2. 1
      server/config/gorm.go
  3. 2
      server/core/server.go
  4. 6
      server/initialize/gorm.go
  5. 150
      server/initialize/logger.go
  6. 2
      server/initialize/router.go
  7. 12
      server/middleware/operation.go
  8. 3
      server/router/exp_customer.go
  9. 3
      server/router/sys_api.go
  10. 3
      server/router/sys_authority.go
  11. 3
      server/router/sys_casbin.go
  12. 3
      server/router/sys_dictionary.go
  13. 3
      server/router/sys_dictionary_detail.go
  14. 3
      server/router/sys_email.go
  15. 3
      server/router/sys_jwt.go
  16. 3
      server/router/sys_menu.go
  17. 11
      server/router/sys_operation_record.go
  18. 3
      server/router/sys_system.go
  19. 3
      server/router/sys_user.go
  20. 3
      server/router/sys_workflow.go
  21. 10
      server/service/sys_auto_code.go
  22. 2
      web/src/main.js

3
server/config.yaml

@ -56,10 +56,11 @@ mysql:
config: 'charset=utf8mb4&parseTime=True&loc=Local'
db-name: 'qmPlus'
username: 'root'
password: 'root123'
password: 'Aa@6447985'
max-idle-conns: 10
max-open-conns: 100
log-mode: false
log-zap: false
# local configuration
local:

1
server/config/gorm.go

@ -9,4 +9,5 @@ type Mysql struct {
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"`
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"`
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
LogZap bool `mapstructure:"log-zap" json:"logZap" yaml:"log-zap"`
}

2
server/core/server.go

@ -29,7 +29,7 @@ func RunWindowsServer() {
fmt.Printf(`
欢迎使用 Gin-Vue-Admin
当前版本:V2.3.6
当前版本:V2.3.7
默认自动化文档地址:http://127.0.0.1%s/swagger/index.html
默认前端文件运行地址:http://127.0.0.1:8080
如果项目让您获得了收益希望您能请团队喝杯可乐:https://www.gin-vue-admin.com/docs/coffee

6
server/initialize/gorm.go

@ -73,6 +73,12 @@ func GormMysql() *gorm.DB {
// gormConfig 根据配置决定是否开启日志
func gormConfig(mod bool) *gorm.Config {
if global.GVA_CONFIG.Mysql.LogZap {
return &gorm.Config{
Logger: Default.LogMode(logger.Info),
DisableForeignKeyConstraintWhenMigrating: true,
}
}
if mod {
return &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),

150
server/initialize/logger.go

@ -0,0 +1,150 @@
package initialize
import (
"context"
"fmt"
"gin-vue-admin/global"
"go.uber.org/zap"
"gorm.io/gorm/logger"
"gorm.io/gorm/utils"
"io/ioutil"
"log"
"os"
"time"
)
var (
Discard = New(log.New(ioutil.Discard, "", log.LstdFlags), GormConfig{})
Default = New(log.New(os.Stdout, "\r\n", log.LstdFlags), GormConfig{
SlowThreshold: 200 * time.Millisecond,
LogLevel: logger.Warn,
Colorful: true,
})
Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()}
)
type traceRecorder struct {
logger.Interface
BeginAt time.Time
SQL string
RowsAffected int64
Err error
}
func New(writer Writer, config GormConfig) logger.Interface {
var (
infoStr = "%s\n[info] "
warnStr = "%s\n[warn] "
errStr = "%s\n[error] "
traceStr = "%s\n[%.3fms] [rows:%v] %s"
traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s"
traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s"
)
if config.Colorful {
infoStr = logger.Green + "%s\n" + logger.Reset + logger.Green + "[info] " + logger.Reset
warnStr = logger.BlueBold + "%s\n" + logger.Reset + logger.Magenta + "[warn] " + logger.Reset
errStr = logger.Magenta + "%s\n" + logger.Reset + logger.Red + "[error] " + logger.Reset
traceStr = logger.Green + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
traceWarnStr = logger.Green + "%s " + logger.Yellow + "%s\n" + logger.Reset + logger.RedBold + "[%.3fms] " + logger.Yellow + "[rows:%v]" + logger.Magenta + " %s" + logger.Reset
traceErrStr = logger.RedBold + "%s " + logger.MagentaBold + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
}
return &GormLogger{
Writer: writer,
GormConfig: config,
infoStr: infoStr,
warnStr: warnStr,
errStr: errStr,
traceStr: traceStr,
traceWarnStr: traceWarnStr,
traceErrStr: traceErrStr,
}
}
// Writer log writer interface
type Writer interface {
Printf(string, ...interface{})
}
type GormConfig struct {
SlowThreshold time.Duration
Colorful bool
LogLevel logger.LogLevel
}
type GormLogger struct {
Writer
GormConfig
infoStr, warnStr, errStr string
traceStr, traceErrStr, traceWarnStr string
}
func (g *GormLogger) LogMode(level logger.LogLevel) logger.Interface {
newLogger := *g
newLogger.LogLevel = level
return &newLogger
}
func (g *GormLogger) Info(ctx context.Context, message string, data ...interface{}) {
if g.LogLevel >= logger.Info {
g.Printf(g.infoStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
}
}
func (g *GormLogger) Warn(ctx context.Context, message string, data ...interface{}) {
if g.LogLevel >= logger.Warn {
g.Printf(g.warnStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
}
}
func (g *GormLogger) Error(ctx context.Context, message string, data ...interface{}) {
if g.LogLevel >= logger.Error {
g.Printf(g.errStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
}
}
func (g *GormLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
if g.LogLevel > 0 {
elapsed := time.Since(begin)
switch {
case err != nil && g.LogLevel >= logger.Error:
sql, rows := fc()
if rows == -1 {
g.Printf(g.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
g.Printf(g.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
}
case elapsed > g.SlowThreshold && g.SlowThreshold != 0 && g.LogLevel >= logger.Warn:
sql, rows := fc()
slowLog := fmt.Sprintf("SLOW SQL >= %v", g.SlowThreshold)
if rows == -1 {
g.Printf(g.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
g.Printf(g.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
}
case g.LogLevel >= logger.Info:
sql, rows := fc()
if rows == -1 {
g.Printf(g.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
g.Printf(g.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
}
}
}
}
func (g *GormLogger) Printf(message string, data ...interface{}) {
switch len(data) {
case 0:
global.GVA_LOG.Info(message)
case 1:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]))
case 2:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]))
case 3:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]))
case 4:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]), zap.Any("sql", data[3]))
}
}

2
server/initialize/router.go

@ -29,7 +29,7 @@ func Routers() *gin.Engine {
router.InitBaseRouter(PublicGroup) // 注册基础功能路由 不做鉴权
}
PrivateGroup := Router.Group("")
PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()).Use(middleware.OperationRecord())
PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
{
router.InitApiRouter(PrivateGroup) // 注册功能api路由
router.InitJwtRouter(PrivateGroup) // jwt相关路由

12
server/middleware/operation.go

@ -11,7 +11,6 @@ import (
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
@ -31,7 +30,7 @@ func OperationRecord() gin.HandlerFunc {
if claims, ok := c.Get("claims"); ok {
waitUse := claims.(*request.CustomClaims)
userId = int(waitUse.ID)
}else {
} else {
id, err := strconv.Atoi(c.Request.Header.Get("x-user-id"))
if err != nil {
userId = 0
@ -46,10 +45,11 @@ func OperationRecord() gin.HandlerFunc {
Body: string(body),
UserID: userId,
}
values := c.Request.Header.Values("content-type")
if len(values) >0 && strings.Contains(values[0], "boundary") {
record.Body = "file"
}
// 存在某些未知错误 TODO
//values := c.Request.Header.Values("content-type")
//if len(values) >0 && strings.Contains(values[0], "boundary") {
// record.Body = "file"
//}
writer := responseBodyWriter{
ResponseWriter: c.Writer,
body: &bytes.Buffer{},

3
server/router/exp_customer.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitCustomerRouter(Router *gin.RouterGroup) {
ApiRouter := Router.Group("customer")
ApiRouter := Router.Group("customer").Use(middleware.OperationRecord())
{
ApiRouter.POST("customer", v1.CreateExaCustomer) // 创建客户
ApiRouter.PUT("customer", v1.UpdateExaCustomer) // 更新客户

3
server/router/sys_api.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitApiRouter(Router *gin.RouterGroup) {
ApiRouter := Router.Group("api")
ApiRouter := Router.Group("api").Use(middleware.OperationRecord())
{
ApiRouter.POST("createApi", v1.CreateApi) // 创建Api
ApiRouter.POST("deleteApi", v1.DeleteApi) // 删除Api

3
server/router/sys_authority.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitAuthorityRouter(Router *gin.RouterGroup) {
AuthorityRouter := Router.Group("authority")
AuthorityRouter := Router.Group("authority").Use(middleware.OperationRecord())
{
AuthorityRouter.POST("createAuthority", v1.CreateAuthority) // 创建角色
AuthorityRouter.POST("deleteAuthority", v1.DeleteAuthority) // 删除角色

3
server/router/sys_casbin.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitCasbinRouter(Router *gin.RouterGroup) {
CasbinRouter := Router.Group("casbin")
CasbinRouter := Router.Group("casbin").Use(middleware.OperationRecord())
{
CasbinRouter.POST("updateCasbin", v1.UpdateCasbin)
CasbinRouter.POST("getPolicyPathByAuthorityId", v1.GetPolicyPathByAuthorityId)

3
server/router/sys_dictionary.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitSysDictionaryRouter(Router *gin.RouterGroup) {
SysDictionaryRouter := Router.Group("sysDictionary")
SysDictionaryRouter := Router.Group("sysDictionary").Use(middleware.OperationRecord())
{
SysDictionaryRouter.POST("createSysDictionary", v1.CreateSysDictionary) // 新建SysDictionary
SysDictionaryRouter.DELETE("deleteSysDictionary", v1.DeleteSysDictionary) // 删除SysDictionary

3
server/router/sys_dictionary_detail.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitSysDictionaryDetailRouter(Router *gin.RouterGroup) {
SysDictionaryDetailRouter := Router.Group("sysDictionaryDetail")
SysDictionaryDetailRouter := Router.Group("sysDictionaryDetail").Use(middleware.OperationRecord())
{
SysDictionaryDetailRouter.POST("createSysDictionaryDetail", v1.CreateSysDictionaryDetail) // 新建SysDictionaryDetail
SysDictionaryDetailRouter.DELETE("deleteSysDictionaryDetail", v1.DeleteSysDictionaryDetail) // 删除SysDictionaryDetail

3
server/router/sys_email.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitEmailRouter(Router *gin.RouterGroup) {
UserRouter := Router.Group("email")
UserRouter := Router.Group("email").Use(middleware.OperationRecord())
{
UserRouter.POST("emailTest", v1.EmailTest) // 发送测试邮件
}

3
server/router/sys_jwt.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitJwtRouter(Router *gin.RouterGroup) {
ApiRouter := Router.Group("jwt")
ApiRouter := Router.Group("jwt").Use(middleware.OperationRecord())
{
ApiRouter.POST("jsonInBlacklist", v1.JsonInBlacklist) // jwt加入黑名单
}

3
server/router/sys_menu.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitMenuRouter(Router *gin.RouterGroup) (R gin.IRoutes) {
MenuRouter := Router.Group("menu")
MenuRouter := Router.Group("menu").Use(middleware.OperationRecord())
{
MenuRouter.POST("getMenu", v1.GetMenu) // 获取菜单树
MenuRouter.POST("getMenuList", v1.GetMenuList) // 分页获取基础menu列表

11
server/router/sys_operation_record.go

@ -2,17 +2,18 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitSysOperationRecordRouter(Router *gin.RouterGroup) {
SysOperationRecordRouter := Router.Group("sysOperationRecord")
SysOperationRecordRouter := Router.Group("sysOperationRecord").Use(middleware.OperationRecord())
{
SysOperationRecordRouter.POST("createSysOperationRecord", v1.CreateSysOperationRecord) // 新建SysOperationRecord
SysOperationRecordRouter.DELETE("deleteSysOperationRecord", v1.DeleteSysOperationRecord) // 删除SysOperationRecord
SysOperationRecordRouter.POST("createSysOperationRecord", v1.CreateSysOperationRecord) // 新建SysOperationRecord
SysOperationRecordRouter.DELETE("deleteSysOperationRecord", v1.DeleteSysOperationRecord) // 删除SysOperationRecord
SysOperationRecordRouter.DELETE("deleteSysOperationRecordByIds", v1.DeleteSysOperationRecordByIds) // 批量删除SysOperationRecord
SysOperationRecordRouter.GET("findSysOperationRecord", v1.FindSysOperationRecord) // 根据ID获取SysOperationRecord
SysOperationRecordRouter.GET("getSysOperationRecordList", v1.GetSysOperationRecordList) // 获取SysOperationRecord列表
SysOperationRecordRouter.GET("findSysOperationRecord", v1.FindSysOperationRecord) // 根据ID获取SysOperationRecord
SysOperationRecordRouter.GET("getSysOperationRecordList", v1.GetSysOperationRecordList) // 获取SysOperationRecord列表
}
}

3
server/router/sys_system.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitSystemRouter(Router *gin.RouterGroup) {
SystemRouter := Router.Group("system")
SystemRouter := Router.Group("system").Use(middleware.OperationRecord())
{
SystemRouter.POST("getSystemConfig", v1.GetSystemConfig) // 获取配置文件内容
SystemRouter.POST("setSystemConfig", v1.SetSystemConfig) // 设置配置文件内容

3
server/router/sys_user.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitUserRouter(Router *gin.RouterGroup) {
UserRouter := Router.Group("user")
UserRouter := Router.Group("user").Use(middleware.OperationRecord())
{
UserRouter.POST("register", v1.Register)
UserRouter.POST("changePassword", v1.ChangePassword) // 修改密码

3
server/router/sys_workflow.go

@ -2,11 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitWorkflowRouter(Router *gin.RouterGroup) {
WorkflowRouter := Router.Group("workflow")
WorkflowRouter := Router.Group("workflow").Use(middleware.OperationRecord())
{
WorkflowRouter.POST("createWorkFlow", v1.CreateWorkFlow) // 创建工作流
}

10
server/service/sys_auto_code.go

@ -209,7 +209,6 @@ func addAutoMoveFile(data *tplData) {
}
}
//@author: [piexlmax](https://github.com/piexlmax)
//@author: [SliverHorn](https://github.com/SliverHorn)
//@function: CreateApi
@ -259,11 +258,10 @@ func AutoCreateApi(a *model.AutoCodeStruct) (err error) {
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
for _, v := range apiList {
var api model.SysApi
if err := tx.Where("path = ? AND method = ?", v.Path, v.Method).First(&api).Error; err != nil {
return err
}
if err := tx.Create(&v).Error; err != nil { // 遇到错误时回滚事务
return err
if errors.Is(tx.Where("path = ? AND method = ?", v.Path, v.Method).First(&api).Error, gorm.ErrRecordNotFound) {
if err := tx.Create(&v).Error; err != nil { // 遇到错误时回滚事务
return err
}
}
}
return nil

2
web/src/main.js

@ -66,7 +66,7 @@ Vue.prototype.$echarts = echarts;
console.log(`
欢迎使用 Gin-Vue-Admin
当前版本:V2.3.6
当前版本:V2.3.7
默认自动化文档地址:http://127.0.0.1%s/swagger/index.html
默认前端文件运行地址:http://127.0.0.1:8080
如果项目让您获得了收益希望您能请团队喝杯可乐:https://www.gin-vue-admin.com/docs/coffee
Loading…
Cancel
Save