作者 yangfu

edit config

@@ -19,7 +19,7 @@ FROM alpine:latest @@ -19,7 +19,7 @@ FROM alpine:latest
19 # Define the project name | 定义项目名称 19 # Define the project name | 定义项目名称
20 ARG PROJECT=core 20 ARG PROJECT=core
21 # Define the config file name | 定义配置文件名 21 # Define the config file name | 定义配置文件名
22 -ARG CONFIG_FILE=core.yaml 22 +ARG CONFIG_FILE=core-dev.yaml
23 # Define the author | 定义作者 23 # Define the author | 定义作者
24 ARG AUTHOR=785409885@qq.com 24 ARG AUTHOR=785409885@qq.com
25 25
@@ -2,7 +2,7 @@ package main @@ -2,7 +2,7 @@ package main
2 2
3 import ( 3 import (
4 "flag" 4 "flag"
5 - "fmt" 5 + "github.com/zeromicro/go-zero/core/logx"
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db" 6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain" 7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
8 "net/http" 8 "net/http"
@@ -57,6 +57,6 @@ func main() { @@ -57,6 +57,6 @@ func main() {
57 57
58 db.Migrate(ctx.DB) 58 db.Migrate(ctx.DB)
59 59
60 - fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) 60 + logx.Infof("Starting server at %s:%d...\n", c.Host, c.Port)
61 server.Start() 61 server.Start()
62 } 62 }
  1 +Name: chart
  2 +Host: 0.0.0.0
  3 +Port: 8080
  4 +Verbose: true
  5 +
  6 +Log:
  7 + Mode: file
  8 + Encoding: plain
  9 + Level: debug # info
  10 +
  11 +JwtAuth:
  12 + AccessSecret: digital-platform
  13 + Expire: 360000
  14 +
  15 +Redis:
  16 + Host: 192.168.0.243:6379
  17 + Type: node
  18 + Pass:
  19 +DB:
  20 + DataSource: host=114.55.200.59 user=postgres password=eagle1010 dbname=sumifcc-bchart-dev port=31543 sslmode=disable TimeZone=Asia/Shanghai
  21 +
  22 +ByteMetadata:
  23 + Name: ApiByteMetadata
  24 + Host: http://character-library-metadata-bastion-test.fjmaimaimai.com
  25 + Timeout: 0s
1 Name: chart 1 Name: chart
2 Host: 0.0.0.0 2 Host: 0.0.0.0
3 -Port: 8080 3 +Port: 8081
4 Verbose: true 4 Verbose: true
5 5
  6 +Log:
  7 + Mode: file
  8 + Encoding: plain
  9 + Level: debug # info
  10 + MaxSize: 1 # 2MB
  11 + TimeFormat: 2006-01-02 15:04:05.000
  12 +
6 JwtAuth: 13 JwtAuth:
7 AccessSecret: digital-platform 14 AccessSecret: digital-platform
8 Expire: 360000 15 Expire: 360000
  1 +package log
  2 +
  3 +import (
  4 + "net/http"
  5 + "path/filepath"
  6 + "strings"
  7 +
  8 + "github.com/zeromicro/go-zero/rest/httpx"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
  11 +)
  12 +
  13 +func GetLogHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  14 + return func(w http.ResponseWriter, r *http.Request) {
  15 + var req types.LogGetRequest
  16 + if err := httpx.Parse(r, &req); err != nil {
  17 + httpx.ErrorCtx(r.Context(), w, err)
  18 + return
  19 + }
  20 + path := svcCtx.Config.Log.Path
  21 + if svcCtx.Config.Log.Mode != "file" {
  22 + return
  23 + }
  24 + if path == "" {
  25 + path = "logs"
  26 + }
  27 + if !strings.HasSuffix(req.Module, ".log") {
  28 + req.Module += ".log"
  29 + }
  30 + handler := http.FileServer(http.Dir(path))
  31 + r.URL.Path = filepath.Join(req.Module)
  32 + handler.ServeHTTP(w, r)
  33 + }
  34 +}
@@ -5,6 +5,7 @@ import ( @@ -5,6 +5,7 @@ import (
5 "net/http" 5 "net/http"
6 6
7 chart "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler/chart" 7 chart "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler/chart"
  8 + log "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler/log"
8 page "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler/page" 9 page "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler/page"
9 table "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler/table" 10 table "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler/table"
10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc" 11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
@@ -161,4 +162,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { @@ -161,4 +162,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
161 }, 162 },
162 rest.WithPrefix("/v1"), 163 rest.WithPrefix("/v1"),
163 ) 164 )
  165 +
  166 + server.AddRoutes(
  167 + []rest.Route{
  168 + {
  169 + Method: http.MethodGet,
  170 + Path: "/log/:module",
  171 + Handler: log.GetLogHandler(serverCtx),
  172 + },
  173 + },
  174 + rest.WithPrefix("/v1"),
  175 + )
164 } 176 }
@@ -76,6 +76,7 @@ func (l *SaveChartLogic) SaveChart(req *types.ChartSaveRequest) (resp *types.Cha @@ -76,6 +76,7 @@ func (l *SaveChartLogic) SaveChart(req *types.ChartSaveRequest) (resp *types.Cha
76 Title: chartProperty.Title, 76 Title: chartProperty.Title,
77 TableAbility: chartProperty.TableAbility, 77 TableAbility: chartProperty.TableAbility,
78 Series: chartProperty.Series, 78 Series: chartProperty.Series,
  79 + Other: chartProperty.Other,
79 TenantId: chart.TenantId, 80 TenantId: chart.TenantId,
80 } 81 }
81 if chartSetting, err = l.svcCtx.ChartSettingRepository.Insert(l.ctx, conn, chartSetting); err != nil { 82 if chartSetting, err = l.svcCtx.ChartSettingRepository.Insert(l.ctx, conn, chartSetting); err != nil {
  1 +package log
  2 +
  3 +import (
  4 + "context"
  5 +
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
  8 +
  9 + "github.com/zeromicro/go-zero/core/logx"
  10 +)
  11 +
  12 +type GetLogLogic struct {
  13 + logx.Logger
  14 + ctx context.Context
  15 + svcCtx *svc.ServiceContext
  16 +}
  17 +
  18 +func NewGetLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLogLogic {
  19 + return &GetLogLogic{
  20 + Logger: logx.WithContext(ctx),
  21 + ctx: ctx,
  22 + svcCtx: svcCtx,
  23 + }
  24 +}
  25 +
  26 +func (l *GetLogLogic) GetLog(req *types.LogGetRequest) (resp *types.LogGetResponse, err error) {
  27 + // todo: add your logic here and delete this line
  28 +
  29 + return
  30 +}
@@ -27,7 +27,7 @@ type ServiceContext struct { @@ -27,7 +27,7 @@ type ServiceContext struct {
27 } 27 }
28 28
29 func NewServiceContext(c config.Config) *ServiceContext { 29 func NewServiceContext(c config.Config) *ServiceContext {
30 - db := database.OpenGormPGDB(c.DB.DataSource) 30 + db := database.OpenGormPGDB(c.DB.DataSource, c.Log.Mode)
31 mlCache := cache.NewMultiLevelCache([]string{c.Redis.Host}, c.Redis.Pass) 31 mlCache := cache.NewMultiLevelCache([]string{c.Redis.Host}, c.Redis.Pass)
32 redisCache := gzcache.NewClusterCache([]string{c.Redis.Host}, c.Redis.Pass) 32 redisCache := gzcache.NewClusterCache([]string{c.Redis.Host}, c.Redis.Pass)
33 redis, _ := redis.NewRedis(redis.RedisConf{Host: c.Redis.Host, Pass: c.Redis.Pass, Type: "node"}) 33 redis, _ := redis.NewRedis(redis.RedisConf{Host: c.Redis.Host, Pass: c.Redis.Pass, Type: "node"})
@@ -298,3 +298,10 @@ type GetAppPageShareDetailRequest struct { @@ -298,3 +298,10 @@ type GetAppPageShareDetailRequest struct {
298 type GetAppPageShareDetailResponse struct { 298 type GetAppPageShareDetailResponse struct {
299 AppPage AppPageItem `json:"page"` 299 AppPage AppPageItem `json:"page"`
300 } 300 }
  301 +
  302 +type LogGetRequest struct {
  303 + Module string `path:"module"`
  304 +}
  305 +
  306 +type LogGetResponse struct {
  307 +}
  1 +#!/bin/bash
  2 +export PATH=/root/local/bin:$PATH
  3 +kubectl -n mmm-suplus-dev get pods | grep -q sumifcc-bchart
  4 +if [ "$?" == "1" ];then
  5 + kubectl create -f /tmp/dev/sumifcc-bchart/sumifcc-bchart.yaml --record
  6 + kubectl -n mmm-suplus-dev get svc | grep -q sumifcc-bchart
  7 + if [ "$?" == "0" ];then
  8 + echo "sumifcc-bchart service install success!"
  9 + else
  10 + echo "sumifcc-bchart service install fail!"
  11 + fi
  12 + kubectl -n mmm-suplus-dev get pods | grep -q sumifcc-bchart
  13 + if [ "$?" == "0" ];then
  14 + echo "sumifcc-bchart deployment install success!"
  15 + else
  16 + echo "sumifcc-bchart deployment install fail!"
  17 + fi
  18 +else
  19 + kubectl delete -f /tmp/dev/sumifcc-bchart/sumifcc-bchart.yaml
  20 + kubectl -n mmm-suplus-dev get svc | grep -q sumifcc-bchart
  21 + while [ "$?" == "0" ]
  22 + do
  23 + kubectl -n mmm-suplus-dev get svc | grep -q sumifcc-bchart
  24 + done
  25 + kubectl -n mmm-suplus-dev get pods | grep -q sumifcc-bchart
  26 + while [ "$?" == "0" ]
  27 + do
  28 + kubectl -n mmm-suplus-dev get pods | grep -q sumifcc-bchart
  29 + done
  30 + kubectl create -f /tmp/dev/sumifcc-bchart/sumifcc-bchart.yaml --record
  31 + kubectl -n mmm-suplus-dev get svc | grep -q sumifcc-bchart
  32 + if [ "$?" == "0" ];then
  33 + echo "sumifcc-bchart service update success!"
  34 + else
  35 + echo "sumifcc-bchart service update fail!"
  36 + fi
  37 + kubectl -n mmm-suplus-dev get pods | grep -q sumifcc-bchart
  38 + if [ "$?" == "0" ];then
  39 + echo "sumifcc-bchart deployment update success!"
  40 + else
  41 + echo "sumifcc-bchart deployment update fail!"
  42 + fi
  43 +fi
  1 +apiVersion: v1
  2 +kind: Service
  3 +metadata:
  4 + name: sumifcc-bchart
  5 + namespace: mmm-suplus-dev
  6 + labels:
  7 + k8s-app: sumifcc-bchart
  8 +spec:
  9 + ports:
  10 + - name: "http"
  11 + port: 80
  12 + targetPort: 8080
  13 + selector:
  14 + k8s-app: sumifcc-bchart
  15 +---
  16 +apiVersion: extensions/v1beta1
  17 +kind: Deployment
  18 +metadata:
  19 + name: sumifcc-bchart
  20 + namespace: mmm-suplus-dev
  21 + labels:
  22 + k8s-app: sumifcc-bchart
  23 +spec:
  24 + replicas: 1
  25 + template:
  26 + metadata:
  27 + labels:
  28 + k8s-app: sumifcc-bchart
  29 + spec:
  30 + affinity:
  31 + nodeAffinity:
  32 + preferredDuringSchedulingIgnoredDuringExecution:
  33 + - preference: {}
  34 + weight: 100
  35 + requiredDuringSchedulingIgnoredDuringExecution:
  36 + nodeSelectorTerms:
  37 + - matchExpressions:
  38 + - key: kubernetes.io/hostname
  39 + operator: In
  40 + values:
  41 + - cn-hangzhou.i-bp1djh1xn7taumbue1zd
  42 + containers:
  43 + - name: sumifcc-bchart
  44 + image: 192.168.0.243:5000/mmm/sumifcc-bchart:dev
  45 + imagePullPolicy: Always
  46 + ports:
  47 + - containerPort: 8080
  48 + volumeMounts:
  49 + - mountPath: /opt/logs
  50 + name: accesslogs
  51 + env:
  52 + - name: LOG_LEVEL
  53 + value: "debug"
  54 + - name: ERROR_BASE_CODE
  55 + value: "1"
  56 + - name: ERROR_BASE_CODE_MULTIPLE
  57 + value: "1000"
  58 + volumes:
  59 + - name: accesslogs
  60 + emptyDir: {}
  1 +#!/bin/bash
  2 +export PATH=/root/local/bin:$PATH
  3 +kubectl -n <replace-your-k8s-namespace> get pods | grep -q sumifcc-survey-server
  4 +if [ "$?" == "1" ];then
  5 + kubectl create -f /tmp/dev/sumifcc-survey-server/sumifcc-survey-server.yaml --record
  6 + kubectl -n <replace-your-k8s-namespace> get svc | grep -q sumifcc-survey-server
  7 + if [ "$?" == "0" ];then
  8 + echo "sumifcc-survey-server service install success!"
  9 + else
  10 + echo "sumifcc-survey-server service install fail!"
  11 + fi
  12 + kubectl -n <replace-your-k8s-namespace> get pods | grep -q sumifcc-survey-server
  13 + if [ "$?" == "0" ];then
  14 + echo "sumifcc-survey-server deployment install success!"
  15 + else
  16 + echo "sumifcc-survey-server deployment install fail!"
  17 + fi
  18 +else
  19 + kubectl delete -f /tmp/dev/sumifcc-survey-server/sumifcc-survey-server.yaml
  20 + kubectl -n <replace-your-k8s-namespace> get svc | grep -q sumifcc-survey-server
  21 + while [ "$?" == "0" ]
  22 + do
  23 + kubectl -n <replace-your-k8s-namespace> get svc | grep -q sumifcc-survey-server
  24 + done
  25 + kubectl -n <replace-your-k8s-namespace> get pods | grep -q sumifcc-survey-server
  26 + while [ "$?" == "0" ]
  27 + do
  28 + kubectl -n <replace-your-k8s-namespace> get pods | grep -q sumifcc-survey-server
  29 + done
  30 + kubectl create -f /tmp/dev/sumifcc-survey-server/sumifcc-survey-server.yaml --record
  31 + kubectl -n <replace-your-k8s-namespace> get svc | grep -q sumifcc-survey-server
  32 + if [ "$?" == "0" ];then
  33 + echo "sumifcc-survey-server service update success!"
  34 + else
  35 + echo "sumifcc-survey-server service update fail!"
  36 + fi
  37 + kubectl -n <replace-your-k8s-namespace> get pods | grep -q sumifcc-survey-server
  38 + if [ "$?" == "0" ];then
  39 + echo "sumifcc-survey-server deployment update success!"
  40 + else
  41 + echo "sumifcc-survey-server deployment update fail!"
  42 + fi
  43 +fi
  1 +apiVersion: v1
  2 +kind: Service
  3 +metadata:
  4 + name: sumifcc-survey-server
  5 + namespace: <replace-your-k8s-namespace>
  6 + labels:
  7 + k8s-app: sumifcc-survey-server
  8 +spec:
  9 + ports:
  10 + - name: "http"
  11 + port: 80
  12 + targetPort: 8082
  13 + selector:
  14 + k8s-app: sumifcc-survey-server
  15 +---
  16 +apiVersion: extensions/v1beta1
  17 +kind: Deployment
  18 +metadata:
  19 + name: sumifcc-survey-server
  20 + namespace: <replace-your-k8s-namespace>
  21 + labels:
  22 + k8s-app: sumifcc-survey-server
  23 +spec:
  24 + replicas: 1
  25 + template:
  26 + metadata:
  27 + labels:
  28 + k8s-app: sumifcc-survey-server
  29 + spec:
  30 + affinity:
  31 + nodeAffinity:
  32 + preferredDuringSchedulingIgnoredDuringExecution:
  33 + - preference: {}
  34 + weight: 100
  35 + requiredDuringSchedulingIgnoredDuringExecution:
  36 + nodeSelectorTerms:
  37 + - matchExpressions:
  38 + - key: kubernetes.io/hostname
  39 + operator: In
  40 + values:
  41 + - cn-hangzhou.i-bp1djh1xn7taumbue1ze
  42 + - cn-hangzhou.i-bp1djh1xn7taumbue1zd
  43 + - cn-hangzhou.i-bp1euf5u1ph9kbhtndhb
  44 + - cn-hangzhou.i-bp1hyp5oips9cdwxxgxy
  45 + containers:
  46 + - name: sumifcc-survey-server
  47 + image: 192.168.0.243:5000/mmm/sumifcc-survey-server:dev
  48 + imagePullPolicy: Always
  49 + ports:
  50 + - containerPort: 8082
  51 + volumeMounts:
  52 + - mountPath: /opt/logs
  53 + name: accesslogs
  54 + env:
  55 + - name: LOG_LEVEL
  56 + value: "debug"
  57 + - name: ERROR_BASE_CODE
  58 + value: "1"
  59 + - name: ERROR_BASE_CODE_MULTIPLE
  60 + value: "1000"
  61 + volumes:
  62 + - name: accesslogs
  63 + emptyDir: {}
1 import "core/chart.api" 1 import "core/chart.api"
2 import "core/table.api" 2 import "core/table.api"
3 import "core/app_page.api" 3 import "core/app_page.api"
  4 +import "core/log.api"
4 // import "./core/chart_stting.api" 5 // import "./core/chart_stting.api"
  1 +syntax = "v1"
  2 +
  3 +info(
  4 + title: "天联字库图表模板"
  5 + desc: "图表模板"
  6 + author: "小火箭"
  7 + email: "email"
  8 + version: "v1"
  9 +)
  10 +
  11 +@server(
  12 + prefix: v1
  13 + group: log
  14 +)
  15 +
  16 +service Core {
  17 + @doc "获取图表详情"
  18 + @handler getLog
  19 + get /log/:module (LogGetRequest) returns (LogGetResponse)
  20 +}
  21 +
  22 +type(
  23 + LogGetRequest struct{
  24 + Module string `path:"module"`
  25 + }
  26 + LogGetResponse struct{
  27 +
  28 + }
  29 +)
1 package cache 1 package cache
2 2
3 import ( 3 import (
4 - "fmt"  
5 "github.com/tiptok/gocomm/pkg/cache" 4 "github.com/tiptok/gocomm/pkg/cache"
6 "github.com/tiptok/gocomm/pkg/cache/gzcache" 5 "github.com/tiptok/gocomm/pkg/cache/gzcache"
7 "github.com/tiptok/gocomm/pkg/log" 6 "github.com/tiptok/gocomm/pkg/log"
  7 + "github.com/zeromicro/go-zero/core/logx"
8 ) 8 )
9 9
10 func NewMultiLevelCache(hosts []string, password string) *cache.MultiLevelCache { 10 func NewMultiLevelCache(hosts []string, password string) *cache.MultiLevelCache {
11 - fmt.Println("starting multi level cache...") 11 + logx.Infof("starting multi level cache...")
12 mlCache := cache.NewMultiLevelCacheNew(cache.WithDebugLog(true, func() log.Log { 12 mlCache := cache.NewMultiLevelCacheNew(cache.WithDebugLog(true, func() log.Log {
13 return log.DefaultLog 13 return log.DefaultLog
14 })) 14 }))
1 package database 1 package database
2 2
3 import ( 3 import (
  4 + "context"
4 "fmt" 5 "fmt"
  6 + "github.com/zeromicro/go-zero/core/logx"
5 "gorm.io/driver/mysql" 7 "gorm.io/driver/mysql"
6 "gorm.io/driver/postgres" 8 "gorm.io/driver/postgres"
7 "gorm.io/gorm" 9 "gorm.io/gorm"
@@ -31,28 +33,52 @@ func OpenGormDB(source string) *gorm.DB { @@ -31,28 +33,52 @@ func OpenGormDB(source string) *gorm.DB {
31 return db 33 return db
32 } 34 }
33 35
34 -func OpenGormPGDB(source string) *gorm.DB {  
35 - newLogger := logger.New(  
36 - log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer  
37 - logger.Config{  
38 - SlowThreshold: time.Second, // Slow SQL threshold  
39 - LogLevel: logger.Info, // Log level  
40 - IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger  
41 - Colorful: false, // Disable color  
42 - },  
43 - )  
44 - fmt.Println("starting db...")  
45 - //db, err := gorm.Open(postgres.Open(source), &gorm.Config{  
46 - // Logger: newLogger,  
47 - //}) 36 +func OpenGormPGDB(source string, logMode string) *gorm.DB {
  37 + logx.Infof("starting db...")
48 db, err := gorm.Open(postgres.New(postgres.Config{ 38 db, err := gorm.Open(postgres.New(postgres.Config{
49 DSN: source, 39 DSN: source,
50 PreferSimpleProtocol: true, // disables implicit prepared statement usage 40 PreferSimpleProtocol: true, // disables implicit prepared statement usage
51 }), &gorm.Config{ 41 }), &gorm.Config{
52 - Logger: newLogger, 42 + Logger: NewLogger(logMode), //newLogger,
53 }) 43 })
54 if err != nil { 44 if err != nil {
55 panic(err) 45 panic(err)
56 } 46 }
57 return db 47 return db
58 } 48 }
  49 +
  50 +func NewLogger(logType string) logger.Interface {
  51 + if logType == "console" {
  52 + return logger.New(
  53 + log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
  54 + logger.Config{
  55 + SlowThreshold: time.Second, // Slow SQL threshold
  56 + LogLevel: logger.Info, // Log level
  57 + IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
  58 + Colorful: false, // Disable color
  59 + },
  60 + )
  61 + }
  62 + return ZeroLog{}
  63 +}
  64 +
  65 +type ZeroLog struct {
  66 +}
  67 +
  68 +func (l ZeroLog) LogMode(logger.LogLevel) logger.Interface {
  69 + return l
  70 +}
  71 +func (l ZeroLog) Info(ctx context.Context, s string, values ...interface{}) {
  72 + logx.Infof(s, values...)
  73 +}
  74 +func (l ZeroLog) Warn(ctx context.Context, s string, values ...interface{}) {
  75 + logx.Errorf(s, values...)
  76 +}
  77 +func (l ZeroLog) Error(ctx context.Context, s string, values ...interface{}) {
  78 + logx.Errorf(s, values...)
  79 +}
  80 +func (l ZeroLog) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
  81 + now := time.Now()
  82 + sql, rows := fc()
  83 + logx.Infof("[%v] [rows:%v] %s", now.Sub(begin).String(), rows, sql)
  84 +}