瀏覽代碼

add std logger

fancl 2 年之前
父節點
當前提交
f41e79149b
共有 4 個文件被更改,包括 233 次插入133 次删除
  1. 140 0
      api.go
  2. 12 132
      crud.go
  3. 1 1
      instance.go
  4. 80 0
      logger/logger.go

+ 140 - 0
api.go

@@ -0,0 +1,140 @@
+package rest
+
+import (
+	"fmt"
+	"git.nspix.com/golang/micro/gateway/http"
+	"gorm.io/gorm"
+)
+
+type Api struct {
+	crud *CRUD
+}
+
+func (api *Api) handleListSchema(httpCtx *http.Context) (err error) {
+	var (
+		schemas []*Schema
+	)
+	ns := httpCtx.FormValue(NamespaceVariable)
+	if ns == "" {
+		ns = DefaultNamespace
+	}
+	if schemas, err = api.crud.GetSchemas(httpCtx.Request().Context(), ns, httpCtx.ParamValue("module"), httpCtx.ParamValue("table")); err == nil {
+		return httpCtx.Success(schemas)
+	} else {
+		return httpCtx.Error(HttpDatabaseQueryFailed, err.Error())
+	}
+}
+
+func (api *Api) handleSaveSchema(httpCtx *http.Context) (err error) {
+	var (
+		rest *Restful
+	)
+	ns := httpCtx.FormValue(NamespaceVariable)
+	if ns == "" {
+		ns = DefaultNamespace
+	}
+	moduleName := httpCtx.ParamValue("module")
+	tableName := httpCtx.ParamValue("table")
+	for _, row := range api.crud.modules {
+		if row.model.ModuleName() == moduleName && row.model.TableName() == tableName {
+			rest = row
+			break
+		}
+	}
+	if rest == nil {
+		return httpCtx.Error(HTTPUnknownFailed, fmt.Sprintf("module %s table %s schema not found", moduleName, tableName))
+	}
+	schemas := make([]*Schema, 0)
+	if err = httpCtx.Bind(&schemas); err != nil {
+		return httpCtx.Error(HttpInvalidPayload, err.Error())
+	}
+	if err = api.crud.db.Transaction(func(tx *gorm.DB) error {
+		var (
+			errTx error
+		)
+		for _, scm := range schemas {
+			if errTx = tx.Save(scm).Error; errTx != nil {
+				return errTx
+			}
+		}
+		return nil
+	}); err == nil {
+		return httpCtx.Success(map[string]interface{}{
+			"count": len(schemas),
+			"state": "success",
+		})
+	} else {
+		return httpCtx.Error(HTTPUnknownFailed, err.Error())
+	}
+}
+
+func (api *Api) handleListSchemas(httpCtx *http.Context) (err error) {
+	var (
+		moduleLabel string
+	)
+	ts := make([]*treeValue, 0)
+	isHandled := false
+	for _, e := range api.crud.modules {
+		isHandled = false
+		for _, tv := range ts {
+			if tv.Value == e.model.ModuleName() {
+				tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
+				isHandled = true
+				break
+			}
+		}
+		if isHandled {
+			continue
+		}
+		moduleLabel = e.model.ModuleName()
+		tv := &treeValue{Label: moduleLabel, Value: e.model.ModuleName(), Type: TypeModule}
+		tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
+		ts = append(ts, tv)
+	}
+	return httpCtx.Success(ts)
+}
+
+func (api *Api) handleDeleteSchema(httpCtx *http.Context) (err error) {
+	id := httpCtx.ParamValue("id")
+	model := &Schema{}
+	if err = api.crud.db.Where("id=?", id).First(model).Error; err == nil {
+		if err = api.crud.db.Where("id=?", id).Delete(&Schema{}).Error; err == nil {
+			return httpCtx.Success(map[string]string{
+				"id":    id,
+				"state": "success",
+			})
+		} else {
+			return httpCtx.Error(HttpDatabaseDeleteFailed, err.Error())
+		}
+	} else {
+		return httpCtx.Error(HttpDatabaseFindFailed, err.Error())
+	}
+}
+
+func (api *Api) Router(svr *http.Server, ms ...http.Middleware) {
+	svr.Handle("GET", "/rest/schemas", api.handleListSchemas, ms...)
+	svr.Handle("GET", "/rest/schema/:module/:table", api.handleListSchema, ms...)
+	svr.Handle("PUT", "/rest/schema/:module/:table", api.handleSaveSchema, ms...)
+	svr.Handle("DELETE", "/rest/schema/:id", api.handleDeleteSchema, ms...)
+
+	for _, rest := range api.crud.modules {
+		if rest.hasScenario(ScenarioList) {
+			svr.Handle("GET", rest.getScenarioUrl(ScenarioList), rest.getScenarioHandle(ScenarioList), ms...)
+		}
+		if rest.hasScenario(ScenarioCreate) {
+			svr.Handle("POST", rest.getScenarioUrl(ScenarioCreate), rest.getScenarioHandle(ScenarioCreate), ms...)
+		}
+		if rest.hasScenario(ScenarioUpdate) {
+			svr.Handle("PUT", rest.getScenarioUrl(ScenarioUpdate), rest.getScenarioHandle(ScenarioUpdate), ms...)
+		}
+		if rest.hasScenario(ScenarioDelete) {
+			svr.Handle("DELETE", rest.getScenarioUrl(ScenarioDelete), rest.getScenarioHandle(ScenarioDelete), ms...)
+		}
+		if rest.hasScenario(ScenarioExport) {
+			svr.Handle("GET", rest.getScenarioUrl(ScenarioExport), rest.getScenarioHandle(ScenarioExport), ms...)
+		}
+		if rest.hasScenario(ScenarioView) {
+			svr.Handle("GET", rest.getScenarioUrl(ScenarioView), rest.getScenarioHandle(ScenarioView), ms...)
+		}
+	}
+}

+ 12 - 132
crud.go

@@ -2,10 +2,10 @@ package rest
 
 import (
 	"context"
-	"fmt"
-	"git.nspix.com/golang/micro/gateway/http"
+	loggerpkg "git.nspix.com/golang/rest/v3/logger"
 	"gorm.io/gorm"
 	"gorm.io/gorm/clause"
+	"gorm.io/gorm/logger"
 	"strings"
 )
 
@@ -30,6 +30,7 @@ const (
 
 type (
 	CRUD struct {
+		api      *Api
 		db       *gorm.DB
 		modules  []*Restful
 		delegate *delegate
@@ -60,6 +61,13 @@ func (r *CRUD) createStatement(db *gorm.DB) *gorm.Statement {
 	}
 }
 
+//WithDebug 开启调试
+func (r *CRUD) WithDebug() *CRUD {
+	r.db.Logger = r.db.Logger.LogMode(logger.Info)
+	return r
+}
+
+//RegisterDelegate 注册一个旁观者
 func (r *CRUD) RegisterDelegate(d Delegate) {
 	r.delegate.Register(d)
 }
@@ -186,135 +194,6 @@ func (r *CRUD) VisibleSchemas(ctx context.Context, ns, moduleName, tableName, sc
 	return
 }
 
-func (r *CRUD) handleListSchema(httpCtx *http.Context) (err error) {
-	var (
-		schemas []*Schema
-	)
-	ns := httpCtx.FormValue(NamespaceVariable)
-	if ns == "" {
-		ns = DefaultNamespace
-	}
-	if schemas, err = r.GetSchemas(httpCtx.Request().Context(), ns, httpCtx.ParamValue("module"), httpCtx.ParamValue("table")); err == nil {
-		return httpCtx.Success(schemas)
-	} else {
-		return httpCtx.Error(HttpDatabaseQueryFailed, err.Error())
-	}
-}
-
-func (r *CRUD) handleSaveSchema(httpCtx *http.Context) (err error) {
-	var (
-		rest *Restful
-	)
-	ns := httpCtx.FormValue(NamespaceVariable)
-	if ns == "" {
-		ns = DefaultNamespace
-	}
-	moduleName := httpCtx.ParamValue("module")
-	tableName := httpCtx.ParamValue("table")
-	for _, row := range r.modules {
-		if row.model.ModuleName() == moduleName && row.model.TableName() == tableName {
-			rest = row
-			break
-		}
-	}
-	if rest == nil {
-		return httpCtx.Error(HTTPUnknownFailed, fmt.Sprintf("module %s table %s schema not found", moduleName, tableName))
-	}
-	schemas := make([]*Schema, 0)
-	if err = httpCtx.Bind(&schemas); err != nil {
-		return httpCtx.Error(HttpInvalidPayload, err.Error())
-	}
-	if err = r.db.Transaction(func(tx *gorm.DB) error {
-		var (
-			errTx error
-		)
-		for _, scm := range schemas {
-			if errTx = tx.Save(scm).Error; errTx != nil {
-				return errTx
-			}
-		}
-		return nil
-	}); err == nil {
-		return httpCtx.Success(map[string]interface{}{
-			"count": len(schemas),
-			"state": "success",
-		})
-	} else {
-		return httpCtx.Error(HTTPUnknownFailed, err.Error())
-	}
-}
-
-func (r *CRUD) handleListSchemas(httpCtx *http.Context) (err error) {
-	var (
-		moduleLabel string
-	)
-	ts := make([]*treeValue, 0)
-	isHandled := false
-	for _, e := range r.modules {
-		isHandled = false
-		for _, tv := range ts {
-			if tv.Value == e.model.ModuleName() {
-				tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
-				isHandled = true
-				break
-			}
-		}
-		if isHandled {
-			continue
-		}
-		moduleLabel = e.model.ModuleName()
-		tv := &treeValue{Label: moduleLabel, Value: e.model.ModuleName(), Type: TypeModule}
-		tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
-		ts = append(ts, tv)
-	}
-	return httpCtx.Success(ts)
-}
-
-func (r *CRUD) handleDeleteSchema(httpCtx *http.Context) (err error) {
-	id := httpCtx.ParamValue("id")
-	model := &Schema{}
-	if err = r.db.Where("id=?", id).First(model).Error; err == nil {
-		if err = r.db.Where("id=?", id).Delete(&Schema{}).Error; err == nil {
-			return httpCtx.Success(map[string]string{
-				"id":    id,
-				"state": "success",
-			})
-		} else {
-			return httpCtx.Error(HttpDatabaseDeleteFailed, err.Error())
-		}
-	} else {
-		return httpCtx.Error(HttpDatabaseFindFailed, err.Error())
-	}
-}
-
-func (r *CRUD) Router(svr *http.Server, ms ...http.Middleware) {
-	svr.Handle("GET", "/rest/schemas", r.handleListSchemas, ms...)
-	svr.Handle("GET", "/rest/schema/:module/:table", r.handleListSchema, ms...)
-	svr.Handle("PUT", "/rest/schema/:module/:table", r.handleSaveSchema, ms...)
-	svr.Handle("DELETE", "/rest/schema/:id", r.handleDeleteSchema, ms...)
-
-	for _, rest := range r.modules {
-		if rest.hasScenario(ScenarioList) {
-			svr.Handle("GET", rest.getScenarioUrl(ScenarioList), rest.getScenarioHandle(ScenarioList), ms...)
-		}
-		if rest.hasScenario(ScenarioCreate) {
-			svr.Handle("POST", rest.getScenarioUrl(ScenarioCreate), rest.getScenarioHandle(ScenarioCreate), ms...)
-		}
-		if rest.hasScenario(ScenarioUpdate) {
-			svr.Handle("PUT", rest.getScenarioUrl(ScenarioUpdate), rest.getScenarioHandle(ScenarioUpdate), ms...)
-		}
-		if rest.hasScenario(ScenarioDelete) {
-			svr.Handle("DELETE", rest.getScenarioUrl(ScenarioDelete), rest.getScenarioHandle(ScenarioDelete), ms...)
-		}
-		if rest.hasScenario(ScenarioExport) {
-			svr.Handle("GET", rest.getScenarioUrl(ScenarioExport), rest.getScenarioHandle(ScenarioExport), ms...)
-		}
-		if rest.hasScenario(ScenarioView) {
-			svr.Handle("GET", rest.getScenarioUrl(ScenarioView), rest.getScenarioHandle(ScenarioView), ms...)
-		}
-	}
-}
-
 //New  create new restful
 func New(dialer gorm.Dialector) (r *CRUD, err error) {
 	r = &CRUD{
@@ -323,7 +202,8 @@ func New(dialer gorm.Dialector) (r *CRUD, err error) {
 	if r.db, err = gorm.Open(dialer); err != nil {
 		return
 	}
-	r.db = r.db.Debug()
+	r.api = &Api{crud: r}
+	r.db.Logger = loggerpkg.New()
 	err = r.db.AutoMigrate(&Schema{})
 	return
 }

+ 1 - 1
instance.go

@@ -49,6 +49,6 @@ func Router(hs *http.Server, ms ...http.Middleware) (err error) {
 	if std == nil {
 		return ErrUninitializedComponent
 	}
-	std.Router(hs, ms...)
+	std.api.Router(hs, ms...)
 	return
 }

+ 80 - 0
logger/logger.go

@@ -0,0 +1,80 @@
+package logger
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"git.nspix.com/golang/micro/log"
+	"gorm.io/gorm/logger"
+	"gorm.io/gorm/utils"
+	"time"
+)
+
+type Logger struct {
+	LogLevel      logger.LogLevel
+	SlowThreshold time.Duration
+	traceStr      string
+	traceErrStr   string
+}
+
+func (lg *Logger) LogMode(level logger.LogLevel) logger.Interface {
+	lg.LogLevel = level
+	return lg
+}
+
+func (lg *Logger) Info(ctx context.Context, s string, i ...interface{}) {
+	if lg.LogLevel >= logger.Info {
+		log.Infof(s, i...)
+	}
+}
+
+func (lg *Logger) Warn(ctx context.Context, s string, i ...interface{}) {
+	if lg.LogLevel >= logger.Warn {
+		log.Warnf(s, i...)
+	}
+}
+
+func (lg *Logger) Error(ctx context.Context, s string, i ...interface{}) {
+	if lg.LogLevel >= logger.Error {
+		log.Errorf(s, i...)
+	}
+}
+
+func (lg *Logger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
+	if lg.LogLevel <= logger.Silent {
+		return
+	}
+	elapsed := time.Since(begin)
+	switch {
+	case err != nil && lg.LogLevel >= logger.Error && (!errors.Is(err, logger.ErrRecordNotFound)):
+		sql, rows := fc()
+		if rows == -1 {
+			lg.Warn(ctx, lg.traceErrStr, sql, err, float64(elapsed.Nanoseconds())/1e6, "-", utils.FileWithLineNum())
+		} else {
+			lg.Warn(ctx, lg.traceErrStr, sql, err, float64(elapsed.Nanoseconds())/1e6, rows, utils.FileWithLineNum())
+		}
+	case elapsed > lg.SlowThreshold && lg.SlowThreshold != 0 && lg.LogLevel >= logger.Warn:
+		sql, rows := fc()
+		slowLog := fmt.Sprintf("SLOW SQL >= %v", lg.SlowThreshold)
+		if rows == -1 {
+			lg.Warn(ctx, lg.traceErrStr, sql, slowLog, float64(elapsed.Nanoseconds())/1e6, "-", utils.FileWithLineNum())
+		} else {
+			lg.Warn(ctx, lg.traceErrStr, sql, slowLog, float64(elapsed.Nanoseconds())/1e6, rows, utils.FileWithLineNum())
+		}
+	case lg.LogLevel == logger.Info:
+		sql, rows := fc()
+		if rows == -1 {
+			lg.Info(ctx, lg.traceStr, sql, float64(elapsed.Nanoseconds())/1e6, "-", utils.FileWithLineNum())
+		} else {
+			lg.Info(ctx, lg.traceStr, sql, float64(elapsed.Nanoseconds())/1e6, rows, utils.FileWithLineNum())
+		}
+	}
+}
+
+func New() *Logger {
+	return &Logger{
+		SlowThreshold: time.Second * 10,
+		traceStr:      "%s [%.3fms] [rows:%v] in %s",
+		traceErrStr:   "%s [%s] [%.3fms] [rows:%v] in %s",
+	}
+}