From 3f0ab29c100447b994c5454b076c5b2558680233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=85=89=E6=98=A5?= Date: Mon, 19 Sep 2022 09:33:33 +0800 Subject: [PATCH] - update gorm --- api.go | 102 ++---- api_gorm.go | 152 +++++---- api_gorm_model_json.go | 31 ++ api_gorm_model_string.go | 28 ++ api_mongo.go | 330 ------------------ const.go | 2 +- gin.go | 113 ++----- gin_gorm.go | 261 +++++++++------ gin_gorm_model_json.go | 42 +++ gin_gorm_model_string.go | 39 +++ gin_mongo.go | 481 --------------------------- go.mod | 5 +- go.sum | 27 ++ vendor/gorm.io/datatypes/License | 21 ++ vendor/gorm.io/datatypes/README.md | 94 ++++++ vendor/gorm.io/datatypes/date.go | 42 +++ vendor/gorm.io/datatypes/json.go | 280 ++++++++++++++++ vendor/gorm.io/datatypes/json_map.go | 96 ++++++ vendor/gorm.io/datatypes/test_all.sh | 10 + vendor/gorm.io/datatypes/time.go | 123 +++++++ vendor/gorm.io/datatypes/url.go | 66 ++++ vendor/modules.txt | 3 + 22 files changed, 1194 insertions(+), 1154 deletions(-) create mode 100644 api_gorm_model_json.go create mode 100644 api_gorm_model_string.go delete mode 100644 api_mongo.go create mode 100644 gin_gorm_model_json.go create mode 100644 gin_gorm_model_string.go delete mode 100644 gin_mongo.go create mode 100644 vendor/gorm.io/datatypes/License create mode 100644 vendor/gorm.io/datatypes/README.md create mode 100644 vendor/gorm.io/datatypes/date.go create mode 100644 vendor/gorm.io/datatypes/json.go create mode 100644 vendor/gorm.io/datatypes/json_map.go create mode 100644 vendor/gorm.io/datatypes/test_all.sh create mode 100644 vendor/gorm.io/datatypes/time.go create mode 100644 vendor/gorm.io/datatypes/url.go diff --git a/api.go b/api.go index d24e022..a1a9fe6 100644 --- a/api.go +++ b/api.go @@ -12,32 +12,20 @@ import ( // ApiClient 接口 type ApiClient struct { - gormClient *dorm.GormClient // 数据库驱动 - mongoClient *dorm.MongoClient // 数据库驱动 - zapLog *ZapLog // 日志服务 - logDebug bool // 日志开关 - currentIp string // 当前ip - gormConfig struct { + gormClient *dorm.GormClient // 数据库驱动 + zapLog *ZapLog // 日志服务 + logDebug bool // 日志开关 + currentIp string // 当前ip + gormConfig struct { tableName string // 表名 insideIp string // 内网ip hostname string // 主机名 goVersion string // go版本 } - mongoConfig struct { - databaseName string // 库名 - collectionName string // 表名 - insideIp string // 内网ip - hostname string // 主机名 - goVersion string // go版本 - } - log struct { - gorm bool // 日志开关 - mongo bool // 日志开关 - } config struct { - os string // 系统类型 - arch string // 系统架构 - maxProCs int // CPU核数 + os string // 系统类型 + arch string // 系统架构 + jsonStatus bool // json状态 } } @@ -45,23 +33,16 @@ type ApiClient struct { // string 表名 type apiGormClientFun func() (*dorm.GormClient, string) -// client 数据库服务 -// string 库名 -// string 表名 -type apiMongoClientFun func() (*dorm.MongoClient, string, string) - // ApiClientConfig 接口实例配置 type ApiClientConfig struct { - GormClientFun apiGormClientFun // 日志配置 - MongoClientFun apiMongoClientFun // 日志配置 - Debug bool // 日志开关 - ZapLog *ZapLog // 日志服务 - CurrentIp string // 当前ip + GormClientFun apiGormClientFun // 日志配置 + Debug bool // 日志开关 + ZapLog *ZapLog // 日志服务 + CurrentIp string // 当前ip + JsonStatus bool // json状态 } // NewApiClient 创建接口实例化 -// client 数据库服务 -// tableName 表名 func NewApiClient(config *ApiClientConfig) (*ApiClient, error) { var ctx = context.Background() @@ -72,6 +53,8 @@ func NewApiClient(config *ApiClientConfig) (*ApiClient, error) { c.logDebug = config.Debug + c.config.jsonStatus = config.JsonStatus + if config.CurrentIp == "" { config.CurrentIp = goip.GetOutsideIp(ctx) } @@ -81,12 +64,10 @@ func NewApiClient(config *ApiClientConfig) (*ApiClient, error) { c.config.os = runtime.GOOS c.config.arch = runtime.GOARCH - c.config.maxProCs = runtime.GOMAXPROCS(0) gormClient, gormTableName := config.GormClientFun() - mongoClient, mongoDatabaseName, mongoCollectionName := config.MongoClientFun() - if (gormClient == nil || gormClient.Db == nil) || (mongoClient == nil || mongoClient.Db == nil) { + if gormClient == nil || gormClient.Db == nil { return nil, errors.New("没有设置驱动") } @@ -110,36 +91,6 @@ func NewApiClient(config *ApiClientConfig) (*ApiClient, error) { c.gormConfig.insideIp = goip.GetInsideIp(ctx) c.gormConfig.goVersion = runtime.Version() - c.log.gorm = true - - } - - if mongoClient != nil || mongoClient.Db != nil { - - c.mongoClient = mongoClient - - if mongoDatabaseName == "" { - return nil, errors.New("没有设置库名") - } - c.mongoConfig.databaseName = mongoDatabaseName - - if mongoCollectionName == "" { - return nil, errors.New("没有设置表名") - } - c.mongoConfig.collectionName = mongoCollectionName - - c.mongoConfig.hostname = hostname - c.mongoConfig.insideIp = goip.GetInsideIp(ctx) - c.mongoConfig.goVersion = runtime.Version() - - c.log.mongo = true - - // 创建时间序列集合 - c.mongoCreateCollection(ctx) - - // 创建索引 - c.mongoCreateIndexes(ctx) - } return c, nil @@ -147,30 +98,15 @@ func NewApiClient(config *ApiClientConfig) (*ApiClient, error) { // Middleware 中间件 func (c *ApiClient) Middleware(ctx context.Context, request gorequest.Response, sdkVersion string) { - if c.log.gorm { - c.GormMiddleware(ctx, request, sdkVersion) - } - if c.log.mongo { - c.MongoMiddleware(ctx, request, sdkVersion) - } + c.GormMiddleware(ctx, request, sdkVersion) } // MiddlewareXml 中间件 func (c *ApiClient) MiddlewareXml(ctx context.Context, request gorequest.Response, sdkVersion string) { - if c.log.gorm { - c.GormMiddlewareXml(ctx, request, sdkVersion) - } - if c.log.mongo { - c.MongoMiddlewareXml(ctx, request, sdkVersion) - } + c.GormMiddlewareXml(ctx, request, sdkVersion) } // MiddlewareCustom 中间件 func (c *ApiClient) MiddlewareCustom(ctx context.Context, api string, request gorequest.Response, sdkVersion string) { - if c.log.gorm { - c.GormMiddlewareCustom(ctx, api, request, sdkVersion) - } - if c.log.mongo { - c.MongoMiddlewareCustom(ctx, api, request, sdkVersion) - } + c.GormMiddlewareCustom(ctx, api, request, sdkVersion) } diff --git a/api_gorm.go b/api_gorm.go index a0fbbc8..83f699f 100644 --- a/api_gorm.go +++ b/api_gorm.go @@ -9,50 +9,22 @@ import ( "go.dtapp.net/gotime" "go.dtapp.net/gotrace_id" "go.dtapp.net/gourl" - "gorm.io/gorm" + "gorm.io/datatypes" "os" "runtime" - "time" "unicode/utf8" ) -// 模型结构体 -type apiPostgresqlLog struct { - LogId uint `gorm:"primaryKey;comment:【记录】编号" json:"log_id,omitempty"` //【记录】编号 - TraceId string `gorm:"index;comment:【系统】跟踪编号" json:"trace_id,omitempty"` //【系统】跟踪编号 - RequestTime time.Time `gorm:"index;comment:【请求】时间" json:"request_time,omitempty"` //【请求】时间 - RequestUri string `gorm:"comment:【请求】链接" json:"request_uri,omitempty"` //【请求】链接 - RequestUrl string `gorm:"comment:【请求】链接" json:"request_url,omitempty"` //【请求】链接 - RequestApi string `gorm:"index;comment:【请求】接口" json:"request_api,omitempty"` //【请求】接口 - RequestMethod string `gorm:"index;comment:【请求】方式" json:"request_method,omitempty"` //【请求】方式 - RequestParams string `gorm:"comment:【请求】参数" json:"request_params,omitempty"` //【请求】参数 - RequestHeader string `gorm:"comment:【请求】头部" json:"request_header,omitempty"` //【请求】头部 - RequestIp string `gorm:"index;comment:【请求】请求Ip" json:"request_ip,omitempty"` //【请求】请求Ip - ResponseHeader string `gorm:"comment:【返回】头部" json:"response_header,omitempty"` //【返回】头部 - ResponseStatusCode int `gorm:"index;comment:【返回】状态码" json:"response_status_code,omitempty"` //【返回】状态码 - ResponseBody string `gorm:"comment:【返回】数据" json:"response_content,omitempty"` //【返回】数据 - ResponseContentLength int64 `gorm:"comment:【返回】大小" json:"response_content_length,omitempty"` //【返回】大小 - ResponseTime time.Time `gorm:"index;comment:【返回】时间" json:"response_time,omitempty"` //【返回】时间 - SystemHostName string `gorm:"index;comment:【系统】主机名" json:"system_host_name,omitempty"` //【系统】主机名 - SystemInsideIp string `gorm:"index;comment:【系统】内网ip" json:"system_inside_ip,omitempty"` //【系统】内网ip - SystemOs string `gorm:"index;comment:【系统】系统类型" json:"system_os,omitempty"` //【系统】系统类型 - SystemArch string `gorm:"index;comment:【系统】系统架构" json:"system_arch,omitempty"` //【系统】系统架构 - SystemCpuQuantity int `gorm:"index;comment:【系统】CPU核数" json:"system_cpu_quantity,omitempty"` //【系统】CPU核数 - GoVersion string `gorm:"index;comment:【程序】Go版本" json:"go_version,omitempty"` //【程序】Go版本 - SdkVersion string `gorm:"index;comment:【程序】Sdk版本" json:"sdk_version,omitempty"` //【程序】Sdk版本 -} - // ApiGormClientConfig 接口实例配置 type ApiGormClientConfig struct { GormClientFun apiGormClientFun // 日志配置 Debug bool // 日志开关 ZapLog *ZapLog // 日志服务 CurrentIp string // 当前ip + JsonStatus bool // json状态 } // NewApiGormClient 创建接口实例化 -// client 数据库服务 -// tableName 表名 func NewApiGormClient(config *ApiGormClientConfig) (*ApiClient, error) { var ctx = context.Background() @@ -63,6 +35,8 @@ func NewApiGormClient(config *ApiGormClientConfig) (*ApiClient, error) { c.logDebug = config.Debug + c.config.jsonStatus = config.JsonStatus + if config.CurrentIp == "" { config.CurrentIp = goip.GetOutsideIp(ctx) } @@ -94,60 +68,112 @@ func NewApiGormClient(config *ApiGormClientConfig) (*ApiClient, error) { c.gormConfig.insideIp = goip.GetInsideIp(ctx) c.gormConfig.goVersion = runtime.Version() - c.log.gorm = true - return c, nil } // 创建模型 func (c *ApiClient) gormAutoMigrate() (err error) { - err = c.gormClient.Db.Table(c.gormConfig.tableName).AutoMigrate(&apiPostgresqlLog{}) - if err != nil { - c.zapLog.WithLogger().Sugar().Infof("[golog.api.gormAutoMigrate]:%s", err) + if c.config.jsonStatus { + err = c.gormClient.Db.Table(c.gormConfig.tableName).AutoMigrate(&apiPostgresqlLogJson{}) + if err != nil { + c.zapLog.WithLogger().Sugar().Errorf("创建模型:%s", err) + } + } else { + err = c.gormClient.Db.Table(c.gormConfig.tableName).AutoMigrate(&apiPostgresqlLogString{}) + if err != nil { + c.zapLog.WithLogger().Sugar().Errorf("创建模型:%s", err) + } } - return + return nil } // 记录日志 -func (c *ApiClient) gormRecord(ctx context.Context, postgresqlLog apiPostgresqlLog) (err error) { +func (c *ApiClient) gormRecord(ctx context.Context, data apiPostgresqlLogString) (err error) { - if utf8.ValidString(postgresqlLog.ResponseBody) == false { - postgresqlLog.ResponseBody = "" + if utf8.ValidString(data.ResponseBody) == false { + data.ResponseBody = "" } - postgresqlLog.SystemHostName = c.gormConfig.hostname - postgresqlLog.SystemInsideIp = c.gormConfig.insideIp - postgresqlLog.GoVersion = c.gormConfig.goVersion - - postgresqlLog.TraceId = gotrace_id.GetTraceIdContext(ctx) - - postgresqlLog.RequestIp = c.currentIp - - postgresqlLog.SystemOs = c.config.os - postgresqlLog.SystemArch = c.config.arch - postgresqlLog.SystemCpuQuantity = c.config.maxProCs - - err = c.gormClient.Db.Table(c.gormConfig.tableName).Create(&postgresqlLog).Error - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("[golog.api.gormRecord]:%s", err) + data.SystemHostName = c.gormConfig.hostname + data.SystemInsideIp = c.gormConfig.insideIp + data.GoVersion = c.gormConfig.goVersion + + data.TraceId = gotrace_id.GetTraceIdContext(ctx) + + data.RequestIp = c.currentIp + + data.SystemOs = c.config.os + data.SystemArch = c.config.arch + + if c.config.jsonStatus { + err = c.gormClient.Db.Table(c.gormConfig.tableName).Create(&apiPostgresqlLogJson{ + TraceId: data.TraceId, + RequestTime: data.RequestTime, + RequestUri: data.RequestUri, + RequestUrl: data.RequestUrl, + RequestApi: data.RequestApi, + RequestMethod: data.RequestMethod, + RequestParams: datatypes.JSON(data.RequestParams), + RequestHeader: datatypes.JSON(data.RequestHeader), + RequestIp: data.RequestIp, + ResponseHeader: datatypes.JSON(data.ResponseHeader), + ResponseStatusCode: data.ResponseStatusCode, + ResponseBody: datatypes.JSON(data.ResponseBody), + ResponseContentLength: data.ResponseContentLength, + ResponseTime: data.ResponseTime, + SystemHostName: data.SystemHostName, + SystemInsideIp: data.SystemInsideIp, + SystemOs: data.SystemOs, + SystemArch: data.SystemArch, + GoVersion: data.GoVersion, + SdkVersion: data.SdkVersion, + }).Error + if err != nil { + c.zapLog.WithTraceId(ctx).Sugar().Errorf("记录日志失败:%s", err) + } + } else { + err = c.gormClient.Db.Table(c.gormConfig.tableName).Create(&apiPostgresqlLogString{ + TraceId: data.TraceId, + RequestTime: data.RequestTime, + RequestUri: data.RequestUri, + RequestUrl: data.RequestUrl, + RequestApi: data.RequestApi, + RequestMethod: data.RequestMethod, + RequestParams: data.RequestParams, + RequestHeader: data.RequestHeader, + RequestIp: data.RequestIp, + ResponseHeader: data.ResponseHeader, + ResponseStatusCode: data.ResponseStatusCode, + ResponseBody: data.ResponseBody, + ResponseContentLength: data.ResponseContentLength, + ResponseTime: data.ResponseTime, + SystemHostName: data.SystemHostName, + SystemInsideIp: data.SystemInsideIp, + SystemOs: data.SystemOs, + SystemArch: data.SystemArch, + GoVersion: data.GoVersion, + SdkVersion: data.SdkVersion, + }).Error + if err != nil { + c.zapLog.WithTraceId(ctx).Sugar().Errorf("记录日志失败:%s", err) + } } return } -// GormQuery 查询 -func (c *ApiClient) GormQuery(ctx context.Context) *gorm.DB { - return c.gormClient.Db.Table(c.gormConfig.tableName) -} - // GormDelete 删除 func (c *ApiClient) GormDelete(ctx context.Context, hour int64) error { - return c.gormClient.Db.Table(c.gormConfig.tableName).Where("request_time < ?", gotime.Current().BeforeHour(hour).Format()).Delete(&apiPostgresqlLog{}).Error + if c.config.jsonStatus { + return c.gormClient.Db.Table(c.gormConfig.tableName).Where("request_time < ?", gotime.Current().BeforeHour(hour).Format()).Delete(&apiPostgresqlLogJson{}).Error + } else { + return c.gormClient.Db.Table(c.gormConfig.tableName).Where("request_time < ?", gotime.Current().BeforeHour(hour).Format()).Delete(&apiPostgresqlLogString{}).Error + } } // GormMiddleware 中间件 func (c *ApiClient) GormMiddleware(ctx context.Context, request gorequest.Response, sdkVersion string) { - data := apiPostgresqlLog{ + data := apiPostgresqlLogString{ RequestTime: request.RequestTime, //【请求】时间 RequestUri: request.RequestUri, //【请求】链接 RequestUrl: gourl.UriParse(request.RequestUri).Url, //【请求】链接 @@ -185,7 +211,7 @@ func (c *ApiClient) GormMiddleware(ctx context.Context, request gorequest.Respon // GormMiddlewareXml 中间件 func (c *ApiClient) GormMiddlewareXml(ctx context.Context, request gorequest.Response, sdkVersion string) { - data := apiPostgresqlLog{ + data := apiPostgresqlLogString{ RequestTime: request.RequestTime, //【请求】时间 RequestUri: request.RequestUri, //【请求】链接 RequestUrl: gourl.UriParse(request.RequestUri).Url, //【请求】链接 @@ -223,7 +249,7 @@ func (c *ApiClient) GormMiddlewareXml(ctx context.Context, request gorequest.Res // GormMiddlewareCustom 中间件 func (c *ApiClient) GormMiddlewareCustom(ctx context.Context, api string, request gorequest.Response, sdkVersion string) { - data := apiPostgresqlLog{ + data := apiPostgresqlLogString{ RequestTime: request.RequestTime, //【请求】时间 RequestUri: request.RequestUri, //【请求】链接 RequestUrl: gourl.UriParse(request.RequestUri).Url, //【请求】链接 diff --git a/api_gorm_model_json.go b/api_gorm_model_json.go new file mode 100644 index 0000000..ee9b29f --- /dev/null +++ b/api_gorm_model_json.go @@ -0,0 +1,31 @@ +package golog + +import ( + "gorm.io/datatypes" + "time" +) + +// 模型 +type apiPostgresqlLogJson struct { + LogId uint `gorm:"primaryKey;comment:【记录】编号" json:"log_id,omitempty"` //【记录】编号 + TraceId string `gorm:"index;comment:【系统】跟踪编号" json:"trace_id,omitempty"` //【系统】跟踪编号 + RequestTime time.Time `gorm:"index;comment:【请求】时间" json:"request_time,omitempty"` //【请求】时间 + RequestUri string `gorm:"comment:【请求】链接" json:"request_uri,omitempty"` //【请求】链接 + RequestUrl string `gorm:"comment:【请求】链接" json:"request_url,omitempty"` //【请求】链接 + RequestApi string `gorm:"index;comment:【请求】接口" json:"request_api,omitempty"` //【请求】接口 + RequestMethod string `gorm:"index;comment:【请求】方式" json:"request_method,omitempty"` //【请求】方式 + RequestParams datatypes.JSON `gorm:"type:jsonb;comment:【请求】参数" json:"request_params,omitempty"` //【请求】参数 + RequestHeader datatypes.JSON `gorm:"type:jsonb;comment:【请求】头部" json:"request_header,omitempty"` //【请求】头部 + RequestIp string `gorm:"index;comment:【请求】请求Ip" json:"request_ip,omitempty"` //【请求】请求Ip + ResponseHeader datatypes.JSON `gorm:"type:jsonb;comment:【返回】头部" json:"response_header,omitempty"` //【返回】头部 + ResponseStatusCode int `gorm:"index;comment:【返回】状态码" json:"response_status_code,omitempty"` //【返回】状态码 + ResponseBody datatypes.JSON `gorm:"type:jsonb;comment:【返回】数据" json:"response_content,omitempty"` //【返回】数据 + ResponseContentLength int64 `gorm:"comment:【返回】大小" json:"response_content_length,omitempty"` //【返回】大小 + ResponseTime time.Time `gorm:"index;comment:【返回】时间" json:"response_time,omitempty"` //【返回】时间 + SystemHostName string `gorm:"index;comment:【系统】主机名" json:"system_host_name,omitempty"` //【系统】主机名 + SystemInsideIp string `gorm:"index;comment:【系统】内网ip" json:"system_inside_ip,omitempty"` //【系统】内网ip + SystemOs string `gorm:"index;comment:【系统】系统类型" json:"system_os,omitempty"` //【系统】系统类型 + SystemArch string `gorm:"index;comment:【系统】系统架构" json:"system_arch,omitempty"` //【系统】系统架构 + GoVersion string `gorm:"comment:【程序】Go版本" json:"go_version,omitempty"` //【程序】Go版本 + SdkVersion string `gorm:"comment:【程序】Sdk版本" json:"sdk_version,omitempty"` //【程序】Sdk版本 +} diff --git a/api_gorm_model_string.go b/api_gorm_model_string.go new file mode 100644 index 0000000..4feae6b --- /dev/null +++ b/api_gorm_model_string.go @@ -0,0 +1,28 @@ +package golog + +import "time" + +// 模型 +type apiPostgresqlLogString struct { + LogId uint `gorm:"primaryKey;comment:【记录】编号" json:"log_id,omitempty"` //【记录】编号 + TraceId string `gorm:"index;comment:【系统】跟踪编号" json:"trace_id,omitempty"` //【系统】跟踪编号 + RequestTime time.Time `gorm:"index;comment:【请求】时间" json:"request_time,omitempty"` //【请求】时间 + RequestUri string `gorm:"comment:【请求】链接" json:"request_uri,omitempty"` //【请求】链接 + RequestUrl string `gorm:"comment:【请求】链接" json:"request_url,omitempty"` //【请求】链接 + RequestApi string `gorm:"index;comment:【请求】接口" json:"request_api,omitempty"` //【请求】接口 + RequestMethod string `gorm:"index;comment:【请求】方式" json:"request_method,omitempty"` //【请求】方式 + RequestParams string `gorm:"comment:【请求】参数" json:"request_params,omitempty"` //【请求】参数 + RequestHeader string `gorm:"comment:【请求】头部" json:"request_header,omitempty"` //【请求】头部 + RequestIp string `gorm:"index;comment:【请求】请求Ip" json:"request_ip,omitempty"` //【请求】请求Ip + ResponseHeader string `gorm:"comment:【返回】头部" json:"response_header,omitempty"` //【返回】头部 + ResponseStatusCode int `gorm:"index;comment:【返回】状态码" json:"response_status_code,omitempty"` //【返回】状态码 + ResponseBody string `gorm:"comment:【返回】数据" json:"response_content,omitempty"` //【返回】数据 + ResponseContentLength int64 `gorm:"comment:【返回】大小" json:"response_content_length,omitempty"` //【返回】大小 + ResponseTime time.Time `gorm:"index;comment:【返回】时间" json:"response_time,omitempty"` //【返回】时间 + SystemHostName string `gorm:"index;comment:【系统】主机名" json:"system_host_name,omitempty"` //【系统】主机名 + SystemInsideIp string `gorm:"index;comment:【系统】内网ip" json:"system_inside_ip,omitempty"` //【系统】内网ip + SystemOs string `gorm:"index;comment:【系统】系统类型" json:"system_os,omitempty"` //【系统】系统类型 + SystemArch string `gorm:"index;comment:【系统】系统架构" json:"system_arch,omitempty"` //【系统】系统架构 + GoVersion string `gorm:"comment:【程序】Go版本" json:"go_version,omitempty"` //【程序】Go版本 + SdkVersion string `gorm:"comment:【程序】Sdk版本" json:"sdk_version,omitempty"` //【程序】Sdk版本 +} diff --git a/api_mongo.go b/api_mongo.go deleted file mode 100644 index f5dacba..0000000 --- a/api_mongo.go +++ /dev/null @@ -1,330 +0,0 @@ -package golog - -import ( - "context" - "errors" - "go.dtapp.net/dorm" - "go.dtapp.net/goip" - "go.dtapp.net/gorequest" - "go.dtapp.net/gotime" - "go.dtapp.net/gotrace_id" - "go.dtapp.net/gourl" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "os" - "runtime" -) - -// 模型结构体 -type apiMongolLog struct { - LogId primitive.ObjectID `json:"log_id,omitempty" bson:"_id,omitempty"` //【记录】编号 - LogTime primitive.DateTime `json:"log_time,omitempty" bson:"log_time,omitempty"` //【记录】时间 - TraceId string `json:"trace_id,omitempty" bson:"trace_id,omitempty"` //【记录】跟踪编号 - RequestTime dorm.BsonTime `json:"request_time,omitempty" bson:"request_time,omitempty"` //【请求】时间 - RequestUri string `json:"request_uri,omitempty" bson:"request_uri,omitempty"` //【请求】链接 - RequestUrl string `json:"request_url,omitempty" bson:"request_url,omitempty"` //【请求】链接 - RequestApi string `json:"request_api,omitempty" bson:"request_api,omitempty"` //【请求】接口 - RequestMethod string `json:"request_method,omitempty" bson:"request_method,omitempty"` //【请求】方式 - RequestParams interface{} `json:"request_params,omitempty" bson:"request_params,omitempty"` //【请求】参数 - RequestHeader interface{} `json:"request_header,omitempty" bson:"request_header,omitempty"` //【请求】头部 - RequestIp string `json:"request_ip,omitempty" bson:"request_ip,omitempty"` //【请求】请求Ip - ResponseHeader interface{} `json:"response_header,omitempty" bson:"response_header,omitempty"` //【返回】头部 - ResponseStatusCode int `json:"response_status_code,omitempty" bson:"response_status_code,omitempty"` //【返回】状态码 - ResponseBody interface{} `json:"response_body,omitempty" bson:"response_body,omitempty"` //【返回】内容 - ResponseContentLength int64 `json:"response_content_length,omitempty" bson:"response_content_length,omitempty"` //【返回】大小 - ResponseTime dorm.BsonTime `json:"response_time,omitempty" bson:"response_time,omitempty"` //【返回】时间 - SystemHostName string `json:"system_host_name,omitempty" bson:"system_host_name,omitempty"` //【系统】主机名 - SystemInsideIp string `json:"system_inside_ip,omitempty" bson:"system_inside_ip,omitempty"` //【系统】内网ip - SystemOs string `json:"system_os,omitempty" bson:"system_os,omitempty"` //【系统】系统类型 - SystemArch string `json:"system_arch,omitempty" bson:"system_arch,omitempty"` //【系统】系统架构 - SystemCpuQuantity int `json:"system_cpu_quantity,omitempty" bson:"system_cpu_quantity,omitempty"` //【系统】CPU核数 - GoVersion string `json:"go_version,omitempty" bson:"go_version,omitempty"` //【程序】Go版本 - SdkVersion string `json:"sdk_version,omitempty" bson:"sdk_version,omitempty"` //【程序】Sdk版本 -} - -// ApiMongoClientConfig 接口实例配置 -type ApiMongoClientConfig struct { - MongoClientFun apiMongoClientFun // 日志配置 - Debug bool // 日志开关 - ZapLog *ZapLog // 日志服务 - CurrentIp string // 当前ip -} - -// NewApiMongoClient 创建接口实例化 -// client 数据库服务 -// databaseName 库名 -// collectionName 表名 -func NewApiMongoClient(config *ApiMongoClientConfig) (*ApiClient, error) { - - var ctx = context.Background() - - c := &ApiClient{} - - c.zapLog = config.ZapLog - - c.logDebug = config.Debug - - if config.CurrentIp == "" { - config.CurrentIp = goip.GetOutsideIp(ctx) - } - if config.CurrentIp != "" && config.CurrentIp != "0.0.0.0" { - c.currentIp = config.CurrentIp - } - - client, databaseName, collectionName := config.MongoClientFun() - - if client == nil || client.Db == nil { - return nil, errors.New("没有设置驱动") - } - - c.mongoClient = client - - if databaseName == "" { - return nil, errors.New("没有设置库名") - } - c.mongoConfig.databaseName = databaseName - - if collectionName == "" { - return nil, errors.New("没有设置表名") - } - c.mongoConfig.collectionName = collectionName - - hostname, _ := os.Hostname() - - c.mongoConfig.hostname = hostname - c.mongoConfig.insideIp = goip.GetInsideIp(ctx) - c.mongoConfig.goVersion = runtime.Version() - - c.log.mongo = true - - // 创建时间序列集合 - c.mongoCreateCollection(ctx) - - // 创建索引 - c.mongoCreateIndexes(ctx) - - return c, nil -} - -// 创建时间序列集合 -func (c *ApiClient) mongoCreateCollection(ctx context.Context) { - var commandResult bson.M - commandErr := c.mongoClient.Db.Database(c.mongoConfig.databaseName).RunCommand(ctx, bson.D{{ - "listCollections", 1, - }}).Decode(&commandResult) - if commandErr != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("检查时间序列集合:%s", commandErr) - } else { - err := c.mongoClient.Db.Database(c.mongoConfig.databaseName).CreateCollection(ctx, c.mongoConfig.collectionName, options.CreateCollection().SetTimeSeriesOptions(options.TimeSeries().SetTimeField("log_time"))) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("创建时间序列集合:%s", err) - } - } -} - -// 创建索引 -func (c *ApiClient) mongoCreateIndexes(ctx context.Context) { - indexes, err := c.mongoClient.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName).CreateManyIndexes(ctx, []mongo.IndexModel{ - { - Keys: bson.D{{ - Key: "trace_id", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "request_time", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "request_method", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "response_status_code", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "response_time", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "system_os", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "system_arch", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "go_version", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "sdk_version", - Value: -1, - }}, - }, - }) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("创建索引:%s", err) - } - c.zapLog.WithTraceId(ctx).Sugar().Infof("创建索引:%s", indexes) -} - -// 记录日志 -func (c *ApiClient) mongoRecord(ctx context.Context, mongoLog apiMongolLog) (err error) { - - mongoLog.SystemHostName = c.mongoConfig.hostname //【系统】主机名 - mongoLog.SystemInsideIp = c.mongoConfig.insideIp //【系统】内网ip - mongoLog.GoVersion = c.mongoConfig.goVersion //【程序】Go版本 - mongoLog.TraceId = gotrace_id.GetTraceIdContext(ctx) //【记录】跟踪编号 - mongoLog.RequestIp = c.currentIp //【请求】请求Ip - mongoLog.SystemOs = c.config.os //【系统】系统类型 - mongoLog.SystemArch = c.config.arch //【系统】系统架构 - mongoLog.SystemCpuQuantity = c.config.maxProCs //【系统】CPU核数 - mongoLog.LogId = primitive.NewObjectID() //【记录】编号 - - _, err = c.mongoClient.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName).InsertOne(ctx, mongoLog) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("[golog.api.mongoRecord]:%s", err) - } - - return err -} - -// MongoQuery 查询 -func (c *ApiClient) MongoQuery(ctx context.Context) *mongo.Collection { - return c.mongoClient.Db.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName) -} - -// MongoDelete 删除 -func (c *ApiClient) MongoDelete(ctx context.Context, hour int64) (*mongo.DeleteResult, error) { - filter := bson.D{{"log_time", bson.D{{"$lt", primitive.NewDateTimeFromTime(gotime.Current().BeforeHour(hour).Time)}}}} - return c.mongoClient.Db.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName).DeleteMany(ctx, filter) -} - -// MongoMiddleware 中间件 -func (c *ApiClient) MongoMiddleware(ctx context.Context, request gorequest.Response, sdkVersion string) { - data := apiMongolLog{ - LogTime: primitive.NewDateTimeFromTime(request.RequestTime), //【记录】时间 - RequestTime: dorm.NewBsonTimeFromTime(request.RequestTime), //【请求】时间 - RequestUri: request.RequestUri, //【请求】链接 - RequestUrl: gourl.UriParse(request.RequestUri).Url, //【请求】链接 - RequestApi: gourl.UriParse(request.RequestUri).Path, //【请求】接口 - RequestMethod: request.RequestMethod, //【请求】方式 - RequestParams: request.RequestParams, //【请求】参数 - RequestHeader: request.RequestHeader, //【请求】头部 - ResponseHeader: request.ResponseHeader, //【返回】头部 - ResponseStatusCode: request.ResponseStatusCode, //【返回】状态码 - ResponseContentLength: request.ResponseContentLength, //【返回】大小 - ResponseTime: dorm.NewBsonTimeFromTime(request.ResponseTime), //【返回】时间 - SdkVersion: sdkVersion, //【程序】Sdk版本 - } - if request.ResponseHeader.Get("Content-Type") == "image/jpeg" || request.ResponseHeader.Get("Content-Type") == "image/png" || request.ResponseHeader.Get("Content-Type") == "image/jpg" { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddleware.type]:%s %s", data.RequestUri, request.ResponseHeader.Get("Content-Type")) - } else { - if len(request.ResponseBody) > 0 { - data.ResponseBody = dorm.JsonDecodeNoError(request.ResponseBody) //【返回】内容 - } else { - if c.logDebug { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddleware.len]:%s %s", data.RequestUri, request.ResponseBody) - } - } - } - - if c.logDebug { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddleware.data]:%+v", data) - } - - err := c.mongoRecord(ctx, data) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("[golog.api.MongoMiddleware]:%s", err.Error()) - } -} - -// MongoMiddlewareXml 中间件 -func (c *ApiClient) MongoMiddlewareXml(ctx context.Context, request gorequest.Response, sdkVersion string) { - data := apiMongolLog{ - LogTime: primitive.NewDateTimeFromTime(request.RequestTime), //【记录】时间 - RequestTime: dorm.NewBsonTimeFromTime(request.RequestTime), //【请求】时间 - RequestUri: request.RequestUri, //【请求】链接 - RequestUrl: gourl.UriParse(request.RequestUri).Url, //【请求】链接 - RequestApi: gourl.UriParse(request.RequestUri).Path, //【请求】接口 - RequestMethod: request.RequestMethod, //【请求】方式 - RequestParams: request.RequestParams, //【请求】参数 - RequestHeader: request.RequestHeader, //【请求】头部 - ResponseHeader: request.ResponseHeader, //【返回】头部 - ResponseStatusCode: request.ResponseStatusCode, //【返回】状态码 - ResponseContentLength: request.ResponseContentLength, //【返回】大小 - ResponseTime: dorm.NewBsonTimeFromTime(request.ResponseTime), //【返回】时间 - SdkVersion: sdkVersion, //【程序】Sdk版本 - } - if request.ResponseHeader.Get("Content-Type") == "image/jpeg" || request.ResponseHeader.Get("Content-Type") == "image/png" || request.ResponseHeader.Get("Content-Type") == "image/jpg" { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddlewareXml.type]:%s %s", data.RequestUri, request.ResponseHeader.Get("Content-Type")) - } else { - if len(request.ResponseBody) > 0 { - data.ResponseBody = dorm.XmlDecodeNoError(request.ResponseBody) //【返回】内容 - } else { - if c.logDebug { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddlewareXml]:%s %s", data.RequestUri, request.ResponseBody) - } - } - } - - if c.logDebug { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddlewareXml.data]:%+v", data) - } - - err := c.mongoRecord(ctx, data) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("[golog.api.MongoMiddlewareXml]:%s", err.Error()) - } -} - -// MongoMiddlewareCustom 中间件 -func (c *ApiClient) MongoMiddlewareCustom(ctx context.Context, api string, request gorequest.Response, sdkVersion string) { - data := apiMongolLog{ - LogTime: primitive.NewDateTimeFromTime(request.RequestTime), //【记录】时间 - RequestTime: dorm.NewBsonTimeFromTime(request.RequestTime), //【请求】时间 - RequestUri: request.RequestUri, //【请求】链接 - RequestUrl: gourl.UriParse(request.RequestUri).Url, //【请求】链接 - RequestApi: api, //【请求】接口 - RequestMethod: request.RequestMethod, //【请求】方式 - RequestParams: request.RequestParams, //【请求】参数 - RequestHeader: request.RequestHeader, //【请求】头部 - ResponseHeader: request.ResponseHeader, //【返回】头部 - ResponseStatusCode: request.ResponseStatusCode, //【返回】状态码 - ResponseContentLength: request.ResponseContentLength, //【返回】大小 - ResponseTime: dorm.NewBsonTimeFromTime(request.ResponseTime), //【返回】时间 - SdkVersion: sdkVersion, //【程序】Sdk版本 - } - if request.ResponseHeader.Get("Content-Type") == "image/jpeg" || request.ResponseHeader.Get("Content-Type") == "image/png" || request.ResponseHeader.Get("Content-Type") == "image/jpg" { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddlewareCustom.type]:%s %s", data.RequestUri, request.ResponseHeader.Get("Content-Type")) - } else { - if len(request.ResponseBody) > 0 { - data.ResponseBody = dorm.JsonDecodeNoError(request.ResponseBody) //【返回】内容 - } else { - if c.logDebug { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.MongoMiddlewareCustom]:%s %s", data.RequestUri, request.ResponseBody) - } - } - } - - if c.logDebug { - c.zapLog.WithTraceId(ctx).Sugar().Infof("[golog.api.mongoRecordJson.data]:%+v", data) - } - - err := c.mongoRecord(ctx, data) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("[golog.api.MongoMiddlewareCustom]:%s", err.Error()) - } -} diff --git a/const.go b/const.go index 2246d3f..db93410 100644 --- a/const.go +++ b/const.go @@ -1,5 +1,5 @@ package golog const ( - Version = "1.0.78" + Version = "1.0.79" ) diff --git a/gin.go b/gin.go index db98b4a..e651247 100644 --- a/gin.go +++ b/gin.go @@ -19,32 +19,20 @@ import ( // GinClient 框架 type GinClient struct { - gormClient *dorm.GormClient // 数据库驱动 - mongoClient *dorm.MongoClient // 数据库驱动 - ipService *goip.Client // ip服务 - zapLog *ZapLog // 日志服务 - logDebug bool // 日志开关 - gormConfig struct { + gormClient *dorm.GormClient // 数据库驱动 + ipService *goip.Client // ip服务 + zapLog *ZapLog // 日志服务 + logDebug bool // 日志开关 + gormConfig struct { tableName string // 表名 insideIp string // 内网ip hostname string // 主机名 goVersion string // go版本 } - mongoConfig struct { - databaseName string // 库名 - collectionName string // 表名 - insideIp string // 内网ip - hostname string // 主机名 - goVersion string // go版本 - } - log struct { - gorm bool // 日志开关 - mongo bool // 日志开关 - } config struct { - os string // 系统类型 - arch string // 系统架构 - maxProCs int // CPU核数 + os string // 系统类型 + arch string // 系统架构 + jsonStatus bool // json状态 } } @@ -52,18 +40,13 @@ type GinClient struct { // string 表名 type ginGormClientFun func() (*dorm.GormClient, string) -// client 数据库服务 -// string 库名 -// string 表名 -type ginMongoClientFun func() (*dorm.MongoClient, string, string) - // GinClientConfig 框架实例配置 type GinClientConfig struct { - IpService *goip.Client // ip服务 - GormClientFun ginGormClientFun // 日志配置 - MongoClientFun apiMongoClientFun // 日志配置 - Debug bool // 日志开关 - ZapLog *ZapLog // 日志服务 + IpService *goip.Client // ip服务 + GormClientFun ginGormClientFun // 日志配置 + Debug bool // 日志开关 + ZapLog *ZapLog // 日志服务 + JsonStatus bool // json状态 } // NewGinClient 创建框架实例化 @@ -80,14 +63,14 @@ func NewGinClient(config *GinClientConfig) (*GinClient, error) { c.logDebug = config.Debug + c.config.jsonStatus = config.JsonStatus + c.config.os = runtime.GOOS c.config.arch = runtime.GOARCH - c.config.maxProCs = runtime.GOMAXPROCS(0) gormClient, gormTableName := config.GormClientFun() - mongoClient, mongoDatabaseName, mongoCollectionName := config.MongoClientFun() - if (gormClient == nil || gormClient.Db == nil) || (mongoClient == nil || mongoClient.Db == nil) { + if gormClient == nil || gormClient.Db == nil { return nil, errors.New("没有设置驱动") } @@ -113,38 +96,6 @@ func NewGinClient(config *GinClientConfig) (*GinClient, error) { c.gormConfig.insideIp = goip.GetInsideIp(ctx) c.gormConfig.goVersion = runtime.Version() - c.log.gorm = true - - } - - if mongoClient != nil || mongoClient.Db != nil { - - c.mongoClient = mongoClient - - if mongoDatabaseName == "" { - return nil, errors.New("没有设置库名") - } - c.mongoConfig.databaseName = mongoDatabaseName - - if mongoCollectionName == "" { - return nil, errors.New("没有设置表名") - } - c.mongoConfig.collectionName = mongoCollectionName - - c.ipService = config.IpService - - c.mongoConfig.hostname = hostname - c.mongoConfig.insideIp = goip.GetInsideIp(ctx) - c.mongoConfig.goVersion = runtime.Version() - - c.log.mongo = true - - // 创建时间序列集合 - c.mongoCreateCollection(ctx) - - // 创建索引 - c.mongoCreateIndexes(ctx) - } return c, nil @@ -244,32 +195,16 @@ func (c *GinClient) Middleware() gin.HandlerFunc { var traceId = gotrace_id.GetGinTraceId(ginCtx) // 记录 - if c.log.gorm { - if dataJson { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.Middleware]准备使用{gormRecordJson}保存数据:%s", data) - } - c.gormRecordJson(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp) - } else { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.Middleware]准备使用{gormRecordXml}保存数据:%s", data) - } - c.gormRecordXml(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp) + if dataJson { + if c.logDebug { + c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.Middleware]准备使用{gormRecordJson}保存数据:%s", data) } - } - // 记录 - if c.log.mongo { - if dataJson { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.Middleware]准备使用{mongoRecordJson}保存数据:%s", data) - } - c.mongoRecordJson(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) - } else { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.Middleware]准备使用{mongoRecordXml}保存数据:%s", data) - } - c.mongoRecordXml(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) + c.gormRecordJson(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) + } else { + if c.logDebug { + c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.Middleware]准备使用{gormRecordXml}保存数据:%s", data) } + c.gormRecordXml(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) } }() } diff --git a/gin_gorm.go b/gin_gorm.go index dccb125..449894d 100644 --- a/gin_gorm.go +++ b/gin_gorm.go @@ -12,7 +12,7 @@ import ( "go.dtapp.net/gotime" "go.dtapp.net/gotrace_id" "go.dtapp.net/gourl" - "gorm.io/gorm" + "gorm.io/datatypes" "io/ioutil" "net" "os" @@ -20,46 +20,13 @@ import ( "time" ) -// 模型结构体 -type ginPostgresqlLog struct { - LogId uint `gorm:"primaryKey;comment:【记录】编号" json:"log_id,omitempty"` //【记录】编号 - TraceId string `gorm:"index;comment:【系统】跟踪编号" json:"trace_id,omitempty"` //【系统】跟踪编号 - RequestTime time.Time `gorm:"index;comment:【请求】时间" json:"request_time,omitempty"` //【请求】时间 - RequestUri string `gorm:"comment:【请求】请求链接 域名+路径+参数" json:"request_uri,omitempty"` //【请求】请求链接 域名+路径+参数 - RequestUrl string `gorm:"comment:【请求】请求链接 域名+路径" json:"request_url,omitempty"` //【请求】请求链接 域名+路径 - RequestApi string `gorm:"index;comment:【请求】请求接口 路径" json:"request_api,omitempty"` //【请求】请求接口 路径 - RequestMethod string `gorm:"index;comment:【请求】请求方式" json:"request_method,omitempty"` //【请求】请求方式 - RequestProto string `gorm:"comment:【请求】请求协议" json:"request_proto,omitempty"` //【请求】请求协议 - RequestUa string `gorm:"comment:【请求】请求UA" json:"request_ua,omitempty"` //【请求】请求UA - RequestReferer string `gorm:"comment:【请求】请求referer" json:"request_referer,omitempty"` //【请求】请求referer - RequestBody string `gorm:"comment:【请求】请求主体" json:"request_body,omitempty"` //【请求】请求主体 - RequestUrlQuery string `gorm:"comment:【请求】请求URL参数" json:"request_url_query,omitempty"` //【请求】请求URL参数 - RequestIp string `gorm:"index;comment:【请求】请求客户端Ip" json:"request_ip,omitempty"` //【请求】请求客户端Ip - RequestIpCountry string `gorm:"index;comment:【请求】请求客户端城市" json:"request_ip_country,omitempty"` //【请求】请求客户端城市 - RequestIpProvince string `gorm:"index;comment:【请求】请求客户端省份" json:"request_ip_province,omitempty"` //【请求】请求客户端省份 - RequestIpCity string `gorm:"index;comment:【请求】请求客户端城市" json:"request_ip_city,omitempty"` //【请求】请求客户端城市 - RequestIpIsp string `gorm:"index;comment:【请求】请求客户端运营商" json:"request_ip_isp,omitempty"` //【请求】请求客户端运营商 - RequestHeader string `gorm:"comment:【请求】请求头" json:"request_header,omitempty"` //【请求】请求头 - ResponseTime time.Time `gorm:"index;comment:【返回】时间" json:"response_time,omitempty"` //【返回】时间 - ResponseCode int `gorm:"index;comment:【返回】状态码" json:"response_code,omitempty"` //【返回】状态码 - ResponseMsg string `gorm:"comment:【返回】描述" json:"response_msg,omitempty"` //【返回】描述 - ResponseData string `gorm:"comment:【返回】数据" json:"response_data,omitempty"` //【返回】数据 - CostTime int64 `gorm:"comment:【系统】花费时间" json:"cost_time,omitempty"` //【系统】花费时间 - SystemHostName string `gorm:"index;comment:【系统】主机名" json:"system_host_name,omitempty"` //【系统】主机名 - SystemInsideIp string `gorm:"index;comment:【系统】内网ip" json:"system_inside_ip,omitempty"` //【系统】内网ip - SystemOs string `gorm:"index;comment:【系统】系统类型" json:"system_os,omitempty"` //【系统】系统类型 - SystemArch string `gorm:"index;comment:【系统】系统架构" json:"system_arch,omitempty"` //【系统】系统架构 - SystemCpuQuantity int `gorm:"index;comment:【系统】CPU核数" json:"system_cpu_quantity,omitempty"` //【系统】CPU核数 - GoVersion string `gorm:"index;comment:【程序】Go版本" json:"go_version,omitempty"` //【程序】Go版本 - SdkVersion string `gorm:"index;comment:【程序】Sdk版本" json:"sdk_version,omitempty"` //【程序】Sdk版本 -} - // GinGormClientConfig 框架实例配置 type GinGormClientConfig struct { IpService *goip.Client // ip服务 GormClientFun ginGormClientFun // 日志配置 Debug bool // 日志开关 ZapLog *ZapLog // 日志服务 + JsonStatus bool // json状态 } // NewGinGormClient 创建框架实例化 @@ -76,6 +43,8 @@ func NewGinGormClient(config *GinGormClientConfig) (*GinClient, error) { c.logDebug = config.Debug + c.config.jsonStatus = config.JsonStatus + client, tableName := config.GormClientFun() if client == nil || client.Db == nil { @@ -102,67 +71,142 @@ func NewGinGormClient(config *GinGormClientConfig) (*GinClient, error) { c.gormConfig.insideIp = goip.GetInsideIp(ctx) c.gormConfig.goVersion = runtime.Version() - c.log.gorm = true - return c, nil } // 创建模型 func (c *GinClient) gormAutoMigrate() (err error) { - err = c.gormClient.Db.Table(c.gormConfig.tableName).AutoMigrate(&ginPostgresqlLog{}) - if err != nil { - c.zapLog.WithLogger().Sugar().Infof("[golog.gin.gormAutoMigrate]:%s", err) + if c.config.jsonStatus { + err = c.gormClient.Db.Table(c.gormConfig.tableName).AutoMigrate(&ginPostgresqlLogJson{}) + if err != nil { + c.zapLog.WithLogger().Sugar().Errorf("创建模型:%s", err) + } + } else { + err = c.gormClient.Db.Table(c.gormConfig.tableName).AutoMigrate(&ginPostgresqlLogString{}) + if err != nil { + c.zapLog.WithLogger().Sugar().Errorf("创建模型:%s", err) + } } return err } // gormRecord 记录日志 -func (c *GinClient) gormRecord(postgresqlLog ginPostgresqlLog) (err error) { - - postgresqlLog.SystemHostName = c.gormConfig.hostname - postgresqlLog.SystemInsideIp = c.gormConfig.insideIp - postgresqlLog.GoVersion = c.gormConfig.goVersion - - postgresqlLog.SdkVersion = Version - - postgresqlLog.SystemOs = c.config.os - postgresqlLog.SystemArch = c.config.arch - postgresqlLog.SystemCpuQuantity = c.config.maxProCs - - err = c.gormClient.Db.Table(c.gormConfig.tableName).Create(&postgresqlLog).Error - if err != nil { - c.zapLog.WithTraceIdStr(postgresqlLog.TraceId).Sugar().Errorf("[golog.gin.gormRecord]:%s", err) +func (c *GinClient) gormRecord(data ginPostgresqlLogString) (err error) { + + data.SystemHostName = c.gormConfig.hostname + data.SystemInsideIp = c.gormConfig.insideIp + data.GoVersion = c.gormConfig.goVersion + + data.SdkVersion = Version + + data.SystemOs = c.config.os + data.SystemArch = c.config.arch + + if c.config.jsonStatus { + err = c.gormClient.Db.Table(c.gormConfig.tableName).Create(&ginPostgresqlLogJson{ + TraceId: data.TraceId, + RequestTime: data.RequestTime, + RequestUri: data.RequestUri, + RequestUrl: data.RequestUrl, + RequestApi: data.RequestApi, + RequestMethod: data.RequestMethod, + RequestProto: data.RequestProto, + RequestUa: data.RequestUa, + RequestReferer: data.RequestReferer, + RequestBody: datatypes.JSON(data.RequestBody), + RequestUrlQuery: datatypes.JSON(data.RequestUrlQuery), + RequestIp: data.RequestIp, + RequestIpCountry: data.RequestIpCountry, + RequestIpProvince: data.RequestIpProvince, + RequestIpCity: data.RequestIpCity, + RequestIpIsp: data.RequestIpIsp, + RequestIpLongitude: data.RequestIpLongitude, + RequestIpLatitude: data.RequestIpLatitude, + RequestHeader: datatypes.JSON(data.RequestHeader), + ResponseTime: data.ResponseTime, + ResponseCode: data.ResponseCode, + ResponseMsg: data.ResponseMsg, + ResponseData: datatypes.JSON(data.ResponseData), + CostTime: data.CostTime, + SystemHostName: data.SystemHostName, + SystemInsideIp: data.SystemInsideIp, + SystemOs: data.SystemOs, + SystemArch: data.SystemArch, + GoVersion: data.GoVersion, + SdkVersion: data.SdkVersion, + }).Error + if err != nil { + c.zapLog.WithTraceIdStr(data.TraceId).Sugar().Errorf("记录日志失败:%s", err) + } + } else { + err = c.gormClient.Db.Table(c.gormConfig.tableName).Create(&ginPostgresqlLogString{ + TraceId: data.TraceId, + RequestTime: data.RequestTime, + RequestUri: data.RequestUri, + RequestUrl: data.RequestUrl, + RequestApi: data.RequestApi, + RequestMethod: data.RequestMethod, + RequestProto: data.RequestProto, + RequestUa: data.RequestUa, + RequestReferer: data.RequestReferer, + RequestBody: data.RequestBody, + RequestUrlQuery: data.RequestUrlQuery, + RequestIp: data.RequestIp, + RequestIpCountry: data.RequestIpCountry, + RequestIpProvince: data.RequestIpProvince, + RequestIpCity: data.RequestIpCity, + RequestIpIsp: data.RequestIpIsp, + RequestIpLongitude: data.RequestIpLongitude, + RequestIpLatitude: data.RequestIpLatitude, + RequestHeader: data.RequestHeader, + ResponseTime: data.ResponseTime, + ResponseCode: data.ResponseCode, + ResponseMsg: data.ResponseMsg, + ResponseData: data.ResponseData, + CostTime: data.CostTime, + SystemHostName: data.SystemHostName, + SystemInsideIp: data.SystemInsideIp, + SystemOs: data.SystemOs, + SystemArch: data.SystemArch, + GoVersion: data.GoVersion, + SdkVersion: data.SdkVersion, + }).Error + if err != nil { + c.zapLog.WithTraceIdStr(data.TraceId).Sugar().Errorf("记录日志失败:%s", err) + } } return } -func (c *GinClient) gormRecordJson(ginCtx *gin.Context, traceId string, requestTime time.Time, requestBody []byte, responseCode int, responseBody string, startTime, endTime int64, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp string) { +func (c *GinClient) gormRecordJson(ginCtx *gin.Context, traceId string, requestTime time.Time, requestBody []byte, responseCode int, responseBody string, startTime, endTime int64, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp string, requestClientIpLocationLatitude, requestClientIpLocationLongitude float64) { if c.logDebug { c.zapLog.WithLogger().Sugar().Infof("[golog.gin.gormRecordJson]收到保存数据要求:%s", c.gormConfig.tableName) } - data := ginPostgresqlLog{ - TraceId: traceId, //【系统】跟踪编号 - RequestTime: requestTime, //【请求】时间 - RequestUrl: ginCtx.Request.RequestURI, //【请求】请求链接 - RequestApi: gourl.UriFilterExcludeQueryString(ginCtx.Request.RequestURI), //【请求】请求接口 - RequestMethod: ginCtx.Request.Method, //【请求】请求方式 - RequestProto: ginCtx.Request.Proto, //【请求】请求协议 - RequestUa: ginCtx.Request.UserAgent(), //【请求】请求UA - RequestReferer: ginCtx.Request.Referer(), //【请求】请求referer - RequestUrlQuery: dorm.JsonEncodeNoError(ginCtx.Request.URL.Query()), //【请求】请求URL参数 - RequestIp: clientIp, //【请求】请求客户端Ip - RequestIpCountry: requestClientIpCountry, //【请求】请求客户端城市 - RequestIpProvince: requestClientIpProvince, //【请求】请求客户端省份 - RequestIpCity: requestClientIpCity, //【请求】请求客户端城市 - RequestIpIsp: requestClientIpIsp, //【请求】请求客户端运营商 - RequestHeader: dorm.JsonEncodeNoError(ginCtx.Request.Header), //【请求】请求头 - ResponseTime: gotime.Current().Time, //【返回】时间 - ResponseCode: responseCode, //【返回】状态码 - ResponseData: responseBody, //【返回】数据 - CostTime: endTime - startTime, //【系统】花费时间 + data := ginPostgresqlLogString{ + TraceId: traceId, //【系统】跟踪编号 + RequestTime: requestTime, //【请求】时间 + RequestUrl: ginCtx.Request.RequestURI, //【请求】请求链接 + RequestApi: gourl.UriFilterExcludeQueryString(ginCtx.Request.RequestURI), //【请求】请求接口 + RequestMethod: ginCtx.Request.Method, //【请求】请求方式 + RequestProto: ginCtx.Request.Proto, //【请求】请求协议 + RequestUa: ginCtx.Request.UserAgent(), //【请求】请求UA + RequestReferer: ginCtx.Request.Referer(), //【请求】请求referer + RequestUrlQuery: dorm.JsonEncodeNoError(ginCtx.Request.URL.Query()), //【请求】请求URL参数 + RequestIp: clientIp, //【请求】请求客户端Ip + RequestIpCountry: requestClientIpCountry, //【请求】请求客户端城市 + RequestIpProvince: requestClientIpProvince, //【请求】请求客户端省份 + RequestIpCity: requestClientIpCity, //【请求】请求客户端城市 + RequestIpIsp: requestClientIpIsp, //【请求】请求客户端运营商 + RequestIpLatitude: requestClientIpLocationLatitude, // 【请求】请求客户端纬度 + RequestIpLongitude: requestClientIpLocationLongitude, // 【请求】请求客户端经度 + RequestHeader: dorm.JsonEncodeNoError(ginCtx.Request.Header), //【请求】请求头 + ResponseTime: gotime.Current().Time, //【返回】时间 + ResponseCode: responseCode, //【返回】状态码 + ResponseData: responseBody, //【返回】数据 + CostTime: endTime - startTime, //【系统】花费时间 } if ginCtx.Request.TLS == nil { data.RequestUri = "http://" + ginCtx.Request.Host + ginCtx.Request.RequestURI //【请求】请求链接 @@ -190,32 +234,34 @@ func (c *GinClient) gormRecordJson(ginCtx *gin.Context, traceId string, requestT } } -func (c *GinClient) gormRecordXml(ginCtx *gin.Context, traceId string, requestTime time.Time, requestBody []byte, responseCode int, responseBody string, startTime, endTime int64, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp string) { +func (c *GinClient) gormRecordXml(ginCtx *gin.Context, traceId string, requestTime time.Time, requestBody []byte, responseCode int, responseBody string, startTime, endTime int64, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp string, requestClientIpLocationLatitude, requestClientIpLocationLongitude float64) { if c.logDebug { c.zapLog.WithLogger().Sugar().Infof("[golog.gin.gormRecordXml]收到保存数据要求:%s", c.gormConfig.tableName) } - data := ginPostgresqlLog{ - TraceId: traceId, //【系统】跟踪编号 - RequestTime: requestTime, //【请求】时间 - RequestUrl: ginCtx.Request.RequestURI, //【请求】请求链接 - RequestApi: gourl.UriFilterExcludeQueryString(ginCtx.Request.RequestURI), //【请求】请求接口 - RequestMethod: ginCtx.Request.Method, //【请求】请求方式 - RequestProto: ginCtx.Request.Proto, //【请求】请求协议 - RequestUa: ginCtx.Request.UserAgent(), //【请求】请求UA - RequestReferer: ginCtx.Request.Referer(), //【请求】请求referer - RequestUrlQuery: dorm.JsonEncodeNoError(ginCtx.Request.URL.Query()), //【请求】请求URL参数 - RequestIp: clientIp, //【请求】请求客户端Ip - RequestIpCountry: requestClientIpCountry, //【请求】请求客户端城市 - RequestIpProvince: requestClientIpProvince, //【请求】请求客户端省份 - RequestIpCity: requestClientIpCity, //【请求】请求客户端城市 - RequestIpIsp: requestClientIpIsp, //【请求】请求客户端运营商 - RequestHeader: dorm.JsonEncodeNoError(ginCtx.Request.Header), //【请求】请求头 - ResponseTime: gotime.Current().Time, //【返回】时间 - ResponseCode: responseCode, //【返回】状态码 - ResponseData: responseBody, //【返回】数据 - CostTime: endTime - startTime, //【系统】花费时间 + data := ginPostgresqlLogString{ + TraceId: traceId, //【系统】跟踪编号 + RequestTime: requestTime, //【请求】时间 + RequestUrl: ginCtx.Request.RequestURI, //【请求】请求链接 + RequestApi: gourl.UriFilterExcludeQueryString(ginCtx.Request.RequestURI), //【请求】请求接口 + RequestMethod: ginCtx.Request.Method, //【请求】请求方式 + RequestProto: ginCtx.Request.Proto, //【请求】请求协议 + RequestUa: ginCtx.Request.UserAgent(), //【请求】请求UA + RequestReferer: ginCtx.Request.Referer(), //【请求】请求referer + RequestUrlQuery: dorm.JsonEncodeNoError(ginCtx.Request.URL.Query()), //【请求】请求URL参数 + RequestIp: clientIp, //【请求】请求客户端Ip + RequestIpCountry: requestClientIpCountry, //【请求】请求客户端城市 + RequestIpProvince: requestClientIpProvince, //【请求】请求客户端省份 + RequestIpCity: requestClientIpCity, //【请求】请求客户端城市 + RequestIpIsp: requestClientIpIsp, //【请求】请求客户端运营商 + RequestIpLatitude: requestClientIpLocationLatitude, // 【请求】请求客户端纬度 + RequestIpLongitude: requestClientIpLocationLongitude, // 【请求】请求客户端经度 + RequestHeader: dorm.JsonEncodeNoError(ginCtx.Request.Header), //【请求】请求头 + ResponseTime: gotime.Current().Time, //【返回】时间 + ResponseCode: responseCode, //【返回】状态码 + ResponseData: responseBody, //【返回】数据 + CostTime: endTime - startTime, //【系统】花费时间 } if ginCtx.Request.TLS == nil { data.RequestUri = "http://" + ginCtx.Request.Host + ginCtx.Request.RequestURI //【请求】请求链接 @@ -244,14 +290,13 @@ func (c *GinClient) gormRecordXml(ginCtx *gin.Context, traceId string, requestTi } } -// GormQuery 查询 -func (c *GinClient) GormQuery(ctx context.Context) *gorm.DB { - return c.gormClient.Db.Table(c.gormConfig.tableName) -} - // GormDelete 删除 func (c *GinClient) GormDelete(ctx context.Context, hour int64) error { - return c.gormClient.Db.Table(c.gormConfig.tableName).Where("request_time < ?", gotime.Current().BeforeHour(hour).Format()).Delete(&ginPostgresqlLog{}).Error + if c.config.jsonStatus { + return c.gormClient.Db.Table(c.gormConfig.tableName).Where("request_time < ?", gotime.Current().BeforeHour(hour).Format()).Delete(&ginPostgresqlLogJson{}).Error + } else { + return c.gormClient.Db.Table(c.gormConfig.tableName).Where("request_time < ?", gotime.Current().BeforeHour(hour).Format()).Delete(&ginPostgresqlLogString{}).Error + } } // GormMiddleware 中间件 @@ -306,6 +351,8 @@ func (c *GinClient) GormMiddleware() gin.HandlerFunc { var requestClientIpProvince string var requestClientIpCity string var requestClientIpIsp string + var requestClientIpLocationLatitude float64 + var requestClientIpLocationLongitude float64 if c.ipService != nil { if net.ParseIP(clientIp).To4() != nil { // IPv4 @@ -314,12 +361,16 @@ func (c *GinClient) GormMiddleware() gin.HandlerFunc { requestClientIpProvince = info.Ip2regionV2info.Province requestClientIpCity = info.Ip2regionV2info.City requestClientIpIsp = info.Ip2regionV2info.Operator + requestClientIpLocationLatitude = info.GeoipInfo.Location.Latitude + requestClientIpLocationLongitude = info.GeoipInfo.Location.Longitude } else if net.ParseIP(clientIp).To16() != nil { // IPv6 info := c.ipService.Analyse(clientIp) requestClientIpCountry = info.Ipv6wryInfo.Country requestClientIpProvince = info.Ipv6wryInfo.Province requestClientIpCity = info.Ipv6wryInfo.City + requestClientIpLocationLatitude = info.GeoipInfo.Location.Latitude + requestClientIpLocationLongitude = info.GeoipInfo.Location.Longitude } } @@ -332,12 +383,12 @@ func (c *GinClient) GormMiddleware() gin.HandlerFunc { if c.logDebug { c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.GormMiddleware]准备使用{gormRecordJson}保存数据:%s", data) } - c.gormRecordJson(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp) + c.gormRecordJson(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) } else { if c.logDebug { c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.GormMiddleware]准备使用{gormRecordXml}保存数据:%s", data) } - c.gormRecordXml(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp) + c.gormRecordXml(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) } } }() diff --git a/gin_gorm_model_json.go b/gin_gorm_model_json.go new file mode 100644 index 0000000..ea34079 --- /dev/null +++ b/gin_gorm_model_json.go @@ -0,0 +1,42 @@ +package golog + +import ( + "gorm.io/datatypes" + "time" +) + +// 模型 +type ginPostgresqlLogJson struct { + LogId uint `gorm:"primaryKey;comment:【记录】编号" json:"log_id,omitempty"` //【记录】编号 + TraceId string `gorm:"index;comment:【系统】跟踪编号" json:"trace_id,omitempty"` //【系统】跟踪编号 + RequestTime time.Time `gorm:"index;comment:【请求】时间" json:"request_time,omitempty"` //【请求】时间 + RequestUri string `gorm:"comment:【请求】请求链接 域名+路径+参数" json:"request_uri,omitempty"` //【请求】请求链接 域名+路径+参数 + RequestUrl string `gorm:"comment:【请求】请求链接 域名+路径" json:"request_url,omitempty"` //【请求】请求链接 域名+路径 + RequestApi string `gorm:"index;comment:【请求】请求接口 路径" json:"request_api,omitempty"` //【请求】请求接口 路径 + RequestMethod string `gorm:"index;comment:【请求】请求方式" json:"request_method,omitempty"` //【请求】请求方式 + RequestProto string `gorm:"comment:【请求】请求协议" json:"request_proto,omitempty"` //【请求】请求协议 + RequestUa string `gorm:"comment:【请求】请求UA" json:"request_ua,omitempty"` //【请求】请求UA + RequestReferer string `gorm:"comment:【请求】请求referer" json:"request_referer,omitempty"` //【请求】请求referer + RequestBody datatypes.JSON `gorm:"type:jsonb;comment:【请求】请求主体" json:"request_body,omitempty"` //【请求】请求主体 + RequestUrlQuery datatypes.JSON `gorm:"type:jsonb;comment:【请求】请求URL参数" json:"request_url_query,omitempty"` //【请求】请求URL参数 + RequestIp string `gorm:"index;comment:【请求】请求客户端Ip" json:"request_ip,omitempty"` //【请求】请求客户端Ip + RequestIpCountry string `gorm:"index;comment:【请求】请求客户端城市" json:"request_ip_country,omitempty"` //【请求】请求客户端城市 + RequestIpProvince string `gorm:"index;comment:【请求】请求客户端省份" json:"request_ip_province,omitempty"` //【请求】请求客户端省份 + RequestIpCity string `gorm:"index;comment:【请求】请求客户端城市" json:"request_ip_city,omitempty"` //【请求】请求客户端城市 + RequestIpIsp string `gorm:"index;comment:【请求】请求客户端运营商" json:"request_ip_isp,omitempty"` //【请求】请求客户端运营商 + RequestIpLongitude float64 `gorm:"index;comment:【请求】请求客户端经度" json:"request_ip_longitude,omitempty"` //【请求】请求客户端经度 + RequestIpLatitude float64 `gorm:"index;comment:【请求】请求客户端纬度" json:"request_ip_latitude,omitempty"` //【请求】请求客户端纬度 + //RequestIpLocation `gorm:"index;comment:【请求】请求客户端位置" json:"request_ip_location,omitempty"` //【请求】请求客户端位置 + RequestHeader datatypes.JSON `gorm:"type:jsonb;comment:【请求】请求头" json:"request_header,omitempty"` //【请求】请求头 + ResponseTime time.Time `gorm:"index;comment:【返回】时间" json:"response_time,omitempty"` //【返回】时间 + ResponseCode int `gorm:"index;comment:【返回】状态码" json:"response_code,omitempty"` //【返回】状态码 + ResponseMsg string `gorm:"comment:【返回】描述" json:"response_msg,omitempty"` //【返回】描述 + ResponseData datatypes.JSON `gorm:"type:jsonb;comment:【返回】数据" json:"response_data,omitempty"` //【返回】数据 + CostTime int64 `gorm:"comment:【系统】花费时间" json:"cost_time,omitempty"` //【系统】花费时间 + SystemHostName string `gorm:"index;comment:【系统】主机名" json:"system_host_name,omitempty"` //【系统】主机名 + SystemInsideIp string `gorm:"index;comment:【系统】内网ip" json:"system_inside_ip,omitempty"` //【系统】内网ip + SystemOs string `gorm:"index;comment:【系统】系统类型" json:"system_os,omitempty"` //【系统】系统类型 + SystemArch string `gorm:"index;comment:【系统】系统架构" json:"system_arch,omitempty"` //【系统】系统架构 + GoVersion string `gorm:"comment:【程序】Go版本" json:"go_version,omitempty"` //【程序】Go版本 + SdkVersion string `gorm:"comment:【程序】Sdk版本" json:"sdk_version,omitempty"` //【程序】Sdk版本 +} diff --git a/gin_gorm_model_string.go b/gin_gorm_model_string.go new file mode 100644 index 0000000..9284116 --- /dev/null +++ b/gin_gorm_model_string.go @@ -0,0 +1,39 @@ +package golog + +import "time" + +// 模型 +type ginPostgresqlLogString struct { + LogId uint `gorm:"primaryKey;comment:【记录】编号" json:"log_id,omitempty"` //【记录】编号 + TraceId string `gorm:"index;comment:【系统】跟踪编号" json:"trace_id,omitempty"` //【系统】跟踪编号 + RequestTime time.Time `gorm:"index;comment:【请求】时间" json:"request_time,omitempty"` //【请求】时间 + RequestUri string `gorm:"comment:【请求】请求链接 域名+路径+参数" json:"request_uri,omitempty"` //【请求】请求链接 域名+路径+参数 + RequestUrl string `gorm:"comment:【请求】请求链接 域名+路径" json:"request_url,omitempty"` //【请求】请求链接 域名+路径 + RequestApi string `gorm:"index;comment:【请求】请求接口 路径" json:"request_api,omitempty"` //【请求】请求接口 路径 + RequestMethod string `gorm:"index;comment:【请求】请求方式" json:"request_method,omitempty"` //【请求】请求方式 + RequestProto string `gorm:"comment:【请求】请求协议" json:"request_proto,omitempty"` //【请求】请求协议 + RequestUa string `gorm:"comment:【请求】请求UA" json:"request_ua,omitempty"` //【请求】请求UA + RequestReferer string `gorm:"comment:【请求】请求referer" json:"request_referer,omitempty"` //【请求】请求referer + RequestBody string `gorm:"comment:【请求】请求主体" json:"request_body,omitempty"` //【请求】请求主体 + RequestUrlQuery string `gorm:"comment:【请求】请求URL参数" json:"request_url_query,omitempty"` //【请求】请求URL参数 + RequestIp string `gorm:"index;comment:【请求】请求客户端Ip" json:"request_ip,omitempty"` //【请求】请求客户端Ip + RequestIpCountry string `gorm:"index;comment:【请求】请求客户端城市" json:"request_ip_country,omitempty"` //【请求】请求客户端城市 + RequestIpProvince string `gorm:"index;comment:【请求】请求客户端省份" json:"request_ip_province,omitempty"` //【请求】请求客户端省份 + RequestIpCity string `gorm:"index;comment:【请求】请求客户端城市" json:"request_ip_city,omitempty"` //【请求】请求客户端城市 + RequestIpIsp string `gorm:"index;comment:【请求】请求客户端运营商" json:"request_ip_isp,omitempty"` //【请求】请求客户端运营商 + RequestIpLongitude float64 `gorm:"index;comment:【请求】请求客户端经度" json:"request_ip_longitude,omitempty"` //【请求】请求客户端经度 + RequestIpLatitude float64 `gorm:"index;comment:【请求】请求客户端纬度" json:"request_ip_latitude,omitempty"` //【请求】请求客户端纬度 + //RequestIpLocation `gorm:"index;comment:【请求】请求客户端位置" json:"request_ip_location,omitempty"` //【请求】请求客户端位置 + RequestHeader string `gorm:"comment:【请求】请求头" json:"request_header,omitempty"` //【请求】请求头 + ResponseTime time.Time `gorm:"index;comment:【返回】时间" json:"response_time,omitempty"` //【返回】时间 + ResponseCode int `gorm:"index;comment:【返回】状态码" json:"response_code,omitempty"` //【返回】状态码 + ResponseMsg string `gorm:"comment:【返回】描述" json:"response_msg,omitempty"` //【返回】描述 + ResponseData string `gorm:"comment:【返回】数据" json:"response_data,omitempty"` //【返回】数据 + CostTime int64 `gorm:"comment:【系统】花费时间" json:"cost_time,omitempty"` //【系统】花费时间 + SystemHostName string `gorm:"index;comment:【系统】主机名" json:"system_host_name,omitempty"` //【系统】主机名 + SystemInsideIp string `gorm:"index;comment:【系统】内网ip" json:"system_inside_ip,omitempty"` //【系统】内网ip + SystemOs string `gorm:"index;comment:【系统】系统类型" json:"system_os,omitempty"` //【系统】系统类型 + SystemArch string `gorm:"index;comment:【系统】系统架构" json:"system_arch,omitempty"` //【系统】系统架构 + GoVersion string `gorm:"comment:【程序】Go版本" json:"go_version,omitempty"` //【程序】Go版本 + SdkVersion string `gorm:"comment:【程序】Sdk版本" json:"sdk_version,omitempty"` //【程序】Sdk版本 +} diff --git a/gin_mongo.go b/gin_mongo.go deleted file mode 100644 index a5dfb02..0000000 --- a/gin_mongo.go +++ /dev/null @@ -1,481 +0,0 @@ -package golog - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "github.com/gin-gonic/gin" - "go.dtapp.net/dorm" - "go.dtapp.net/goip" - "go.dtapp.net/gorequest" - "go.dtapp.net/gotime" - "go.dtapp.net/gotrace_id" - "go.dtapp.net/gourl" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "io/ioutil" - "net" - "os" - "runtime" - "time" -) - -type ginMongoLogRequestIpLocationLocation struct { - Type string `json:"type,omitempty" bson:"type,omitempty"` // GeoJSON类型 - Coordinates []float64 `json:"coordinates,omitempty" bson:"coordinates,omitempty"` // 经度,纬度 -} - -// 模型结构体 -type ginMongoLog struct { - LogId primitive.ObjectID `json:"log_id,omitempty" bson:"_id,omitempty"` //【记录】编号 - LogTime primitive.DateTime `json:"log_time,omitempty" bson:"log_time,omitempty"` //【记录】时间 - TraceId string `json:"trace_id,omitempty" bson:"trace_id,omitempty"` //【记录】跟踪编号 - RequestTime dorm.BsonTime `json:"request_time,omitempty" bson:"request_time,omitempty"` //【请求】时间 - RequestUri string `json:"request_uri,omitempty" bson:"request_uri,omitempty"` //【请求】请求链接 域名+路径+参数 - RequestUrl string `json:"request_url,omitempty" bson:"request_url,omitempty"` //【请求】请求链接 域名+路径 - RequestApi string `json:"request_api,omitempty" bson:"request_api,omitempty"` //【请求】请求接口 路径 - RequestMethod string `json:"request_method,omitempty" bson:"request_method,omitempty"` //【请求】请求方式 - RequestProto string `json:"request_proto,omitempty" bson:"request_proto,omitempty"` //【请求】请求协议 - RequestUa string `json:"request_ua,omitempty" bson:"request_ua,omitempty"` //【请求】请求UA - RequestReferer string `json:"request_referer,omitempty" bson:"request_referer,omitempty"` //【请求】请求referer - RequestBody interface{} `json:"request_body,omitempty" bson:"request_body,omitempty"` //【请求】请求主体 - RequestUrlQuery interface{} `json:"request_url_query,omitempty" bson:"request_url_query,omitempty"` //【请求】请求URL参数 - RequestIp string `json:"request_ip,omitempty" bson:"request_ip,omitempty"` //【请求】请求客户端Ip - RequestIpCountry string `json:"request_ip_country,omitempty" bson:"request_ip_country,omitempty"` //【请求】请求客户端国家 - RequestIpProvince string `json:"request_ip_province,omitempty" bson:"request_ip_province,omitempty"` //【请求】请求客户端省份 - RequestIpCity string `json:"request_ip_city,omitempty" bson:"request_ip_city,omitempty"` //【请求】请求客户端城市 - RequestIpIsp string `json:"request_ip_isp,omitempty" bson:"request_ip_isp,omitempty"` //【请求】请求客户端运营商 - RequestIpLocation ginMongoLogRequestIpLocationLocation `json:"request_ip_location,omitempty" bson:"request_ip_location,omitempty"` //【请求】请求客户端位置 - RequestHeader interface{} `json:"request_header,omitempty" bson:"request_header,omitempty"` //【请求】请求头 - ResponseTime dorm.BsonTime `json:"response_time,omitempty" bson:"response_time,omitempty"` //【返回】时间 - ResponseCode int `json:"response_code,omitempty" bson:"response_code,omitempty"` //【返回】状态码 - ResponseMsg string `json:"response_msg,omitempty" bson:"response_msg,omitempty"` //【返回】描述 - ResponseData interface{} `json:"response_data,omitempty" bson:"response_data,omitempty"` //【返回】数据 - CostTime int64 `json:"cost_time,omitempty" bson:"cost_time,omitempty"` //【系统】花费时间 - SystemHostName string `json:"system_host_name,omitempty" bson:"system_host_name,omitempty"` //【系统】主机名 - SystemInsideIp string `json:"system_inside_ip,omitempty" bson:"system_inside_ip,omitempty"` //【系统】内网ip - SystemOs string `json:"system_os,omitempty" bson:"system_os,omitempty"` //【系统】系统类型 - SystemArch string `json:"system_arch,omitempty" bson:"system_arch,omitempty"` //【系统】系统架构 - SystemCpuQuantity int `json:"system_cpu_quantity,omitempty" bson:"system_cpu_quantity,omitempty"` //【系统】CPU核数 - GoVersion string `json:"go_version,omitempty" bson:"go_version,omitempty"` //【程序】Go版本 - SdkVersion string `json:"sdk_version,omitempty" bson:"sdk_version,omitempty"` //【程序】Sdk版本 -} - -// GinMongoClientConfig 框架实例配置 -type GinMongoClientConfig struct { - IpService *goip.Client // ip服务 - MongoClientFun ginMongoClientFun // 日志配置 - Debug bool // 日志开关 - ZapLog *ZapLog // 日志服务 -} - -// NewGinMongoClient 创建框架实例化 -// client 数据库服务 -// databaseName 库名 -// collectionName 表名 -// ipService ip服务 -func NewGinMongoClient(config *GinMongoClientConfig) (*GinClient, error) { - - var ctx = context.Background() - - c := &GinClient{} - - c.zapLog = config.ZapLog - - c.logDebug = config.Debug - - client, databaseName, collectionName := config.MongoClientFun() - - if client == nil || client.Db == nil { - return nil, errors.New("没有设置驱动") - } - - c.mongoClient = client - - if databaseName == "" { - return nil, errors.New("没有设置库名") - } - c.mongoConfig.databaseName = databaseName - - if collectionName == "" { - return nil, errors.New("没有设置表名") - } - c.mongoConfig.collectionName = collectionName - - c.ipService = config.IpService - - hostname, _ := os.Hostname() - - c.mongoConfig.hostname = hostname - c.mongoConfig.insideIp = goip.GetInsideIp(ctx) - c.mongoConfig.goVersion = runtime.Version() - - c.log.mongo = true - - // 创建时间序列集合 - c.mongoCreateCollection(ctx) - - // 创建索引 - c.mongoCreateIndexes(ctx) - - return c, nil -} - -// 创建时间序列集合 -func (c *GinClient) mongoCreateCollection(ctx context.Context) { - var commandResult bson.M - commandErr := c.mongoClient.Db.Database(c.mongoConfig.databaseName).RunCommand(ctx, bson.D{{ - "listCollections", 1, - }}).Decode(&commandResult) - if commandErr != nil { - c.zapLog.WithTraceId(ctx).Sugar().Error("检查时间序列集合:", commandErr) - } else { - err := c.mongoClient.Db.Database(c.mongoConfig.databaseName).CreateCollection(ctx, c.mongoConfig.collectionName, options.CreateCollection().SetTimeSeriesOptions(options.TimeSeries().SetTimeField("log_time"))) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Error("创建时间序列集合:", err) - } - } -} - -// 创建索引 -func (c *GinClient) mongoCreateIndexes(ctx context.Context) { - indexes, err := c.mongoClient.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName).CreateManyIndexes(ctx, []mongo.IndexModel{ - { - Keys: bson.D{{ - Key: "trace_id", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "request_time", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "request_method", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "request_ip", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "request_ip_country", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "request_ip_province", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "request_ip_city", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "request_ip_isp", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "response_time", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "response_code", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "system_host_name", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "system_os", - Value: 1, - }}, - }, { - Keys: bson.D{{ - Key: "system_arch", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "go_version", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "sdk_version", - Value: -1, - }}, - }, { - Keys: bson.D{{ - Key: "request_ip_location", - Value: "2dsphere", - }}, - }, - }) - if err != nil { - c.zapLog.WithTraceId(ctx).Sugar().Errorf("创建索引:%s", err) - } - c.zapLog.WithTraceId(ctx).Sugar().Infof("创建索引:%s", indexes) -} - -// 记录日志 -func (c *GinClient) mongoRecord(ctx context.Context, mongoLog ginMongoLog) (err error) { - - mongoLog.SystemHostName = c.mongoConfig.hostname //【系统】主机名 - mongoLog.SystemInsideIp = c.mongoConfig.insideIp //【系统】内网ip - mongoLog.GoVersion = c.mongoConfig.goVersion //【程序】Go版本 - mongoLog.SdkVersion = Version //【程序】Sdk版本 - mongoLog.SystemOs = c.config.os //【系统】系统类型 - mongoLog.SystemArch = c.config.arch //【系统】系统架构 - mongoLog.SystemCpuQuantity = c.config.maxProCs //【系统】CPU核数 - mongoLog.LogId = primitive.NewObjectID() //【记录】编号 - - _, err = c.mongoClient.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName).InsertOne(ctx, mongoLog) - if err != nil { - c.zapLog.WithTraceIdStr(mongoLog.TraceId).Sugar().Errorf("[golog.gin.mongoRecord]:%s", err) - } - - return err -} - -func (c *GinClient) mongoRecordJson(ginCtx *gin.Context, traceId string, requestTime time.Time, requestBody []byte, responseCode int, responseBody string, startTime, endTime int64, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp string, requestClientIpLocationLatitude, requestClientIpLocationLongitude float64) { - - var ctx = gotrace_id.SetGinTraceIdContext(context.Background(), ginCtx) - - if c.logDebug { - c.zapLog.WithLogger().Sugar().Infof("[golog.gin.mongoRecordJson]收到保存数据要求:%s,%s", c.mongoConfig.databaseName, c.mongoConfig.collectionName) - } - - data := ginMongoLog{ - TraceId: traceId, //【记录】跟踪编号 - LogTime: primitive.NewDateTimeFromTime(requestTime), //【记录】时间 - RequestTime: dorm.NewBsonTimeFromTime(requestTime), //【请求】时间 - RequestUrl: ginCtx.Request.RequestURI, //【请求】请求链接 - RequestApi: gourl.UriFilterExcludeQueryString(ginCtx.Request.RequestURI), //【请求】请求接口 - RequestMethod: ginCtx.Request.Method, //【请求】请求方式 - RequestProto: ginCtx.Request.Proto, //【请求】请求协议 - RequestUa: ginCtx.Request.UserAgent(), //【请求】请求UA - RequestReferer: ginCtx.Request.Referer(), //【请求】请求referer - RequestUrlQuery: ginCtx.Request.URL.Query(), //【请求】请求URL参数 - RequestIp: clientIp, //【请求】请求客户端Ip - RequestIpCountry: requestClientIpCountry, //【请求】请求客户端国家 - RequestIpProvince: requestClientIpProvince, //【请求】请求客户端省份 - RequestIpCity: requestClientIpCity, //【请求】请求客户端城市 - RequestIpIsp: requestClientIpIsp, //【请求】请求客户端运营商 - RequestHeader: ginCtx.Request.Header, //【请求】请求头 - ResponseTime: dorm.NewBsonTimeCurrent(), //【返回】时间 - ResponseCode: responseCode, //【返回】状态码 - ResponseData: c.jsonUnmarshal(responseBody), //【返回】数据 - CostTime: endTime - startTime, //【系统】花费时间 - } - if ginCtx.Request.TLS == nil { - data.RequestUri = "http://" + ginCtx.Request.Host + ginCtx.Request.RequestURI //【请求】请求链接 - } else { - data.RequestUri = "https://" + ginCtx.Request.Host + ginCtx.Request.RequestURI //【请求】请求链接 - } - - if len(requestBody) > 0 { - data.RequestBody = dorm.JsonDecodeNoError(requestBody) //【请求】请求主体 - } else { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.mongoRecordJson.len]:%s,%s", data.RequestUri, requestBody) - } - } - - if requestClientIpLocationLatitude != 0 && requestClientIpLocationLongitude != 0 { - data.RequestIpLocation = ginMongoLogRequestIpLocationLocation{ - Type: "Point", - Coordinates: []float64{requestClientIpLocationLongitude, requestClientIpLocationLatitude}, - } - } - - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.mongoRecordJson.data]:%+v", data) - } - - err := c.mongoRecord(ctx, data) - if err != nil { - c.zapLog.WithTraceIdStr(traceId).Sugar().Errorf("[golog.gin.mongoRecordJson]:%s", err) - } -} - -func (c *GinClient) mongoRecordXml(ginCtx *gin.Context, traceId string, requestTime time.Time, requestBody []byte, responseCode int, responseBody string, startTime, endTime int64, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp string, requestClientIpLocationLatitude, requestClientIpLocationLongitude float64) { - - var ctx = gotrace_id.SetGinTraceIdContext(context.Background(), ginCtx) - - if c.logDebug { - c.zapLog.WithLogger().Sugar().Infof("[golog.gin.mongoRecordXml]收到保存数据要求:%s,%s", c.mongoConfig.databaseName, c.mongoConfig.collectionName) - } - - data := ginMongoLog{ - TraceId: traceId, //【记录】跟踪编号 - LogTime: primitive.NewDateTimeFromTime(requestTime), //【记录】时间 - RequestTime: dorm.NewBsonTimeFromTime(requestTime), //【请求】时间 - RequestUrl: ginCtx.Request.RequestURI, //【请求】请求链接 - RequestApi: gourl.UriFilterExcludeQueryString(ginCtx.Request.RequestURI), //【请求】请求接口 - RequestMethod: ginCtx.Request.Method, //【请求】请求方式 - RequestProto: ginCtx.Request.Proto, //【请求】请求协议 - RequestUa: ginCtx.Request.UserAgent(), //【请求】请求UA - RequestReferer: ginCtx.Request.Referer(), //【请求】请求referer - RequestUrlQuery: ginCtx.Request.URL.Query(), //【请求】请求URL参数 - RequestIp: clientIp, //【请求】请求客户端Ip - RequestIpCountry: requestClientIpCountry, //【请求】请求客户端国家 - RequestIpProvince: requestClientIpProvince, //【请求】请求客户端省份 - RequestIpCity: requestClientIpCity, //【请求】请求客户端城市 - RequestIpIsp: requestClientIpIsp, //【请求】请求客户端运营商 - RequestHeader: ginCtx.Request.Header, //【请求】请求头 - ResponseTime: dorm.NewBsonTimeCurrent(), //【返回】时间 - ResponseCode: responseCode, //【返回】状态码 - ResponseData: c.jsonUnmarshal(responseBody), //【返回】数据 - CostTime: endTime - startTime, //【系统】花费时间 - } - if ginCtx.Request.TLS == nil { - data.RequestUri = "http://" + ginCtx.Request.Host + ginCtx.Request.RequestURI //【请求】请求链接 - } else { - data.RequestUri = "https://" + ginCtx.Request.Host + ginCtx.Request.RequestURI //【请求】请求链接 - } - - if len(requestBody) > 0 { - data.RequestBody = dorm.XmlDecodeNoError(requestBody) //【请求】请求主体 - } else { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.mongoRecordXml.len]:%s,%s", data.RequestUri, requestBody) - } - } - - if requestClientIpLocationLatitude != 0 && requestClientIpLocationLongitude != 0 { - data.RequestIpLocation = ginMongoLogRequestIpLocationLocation{ - Type: "Point", - Coordinates: []float64{requestClientIpLocationLongitude, requestClientIpLocationLatitude}, - } - } - - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.mongoRecordXml.data]:%+v", data) - } - - err := c.mongoRecord(ctx, data) - if err != nil { - c.zapLog.WithTraceIdStr(traceId).Sugar().Errorf("[golog.gin.mongoRecordXml]:%s", err) - } -} - -// MongoQuery 查询 -func (c *GinClient) MongoQuery(ctx context.Context) *mongo.Collection { - return c.mongoClient.Db.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName) -} - -// MongoDelete 删除 -func (c *GinClient) MongoDelete(ctx context.Context, hour int64) (*mongo.DeleteResult, error) { - filter := bson.D{{"log_time", bson.D{{"$lt", primitive.NewDateTimeFromTime(gotime.Current().BeforeHour(hour).Time)}}}} - return c.mongoClient.Db.Database(c.mongoConfig.databaseName).Collection(c.mongoConfig.collectionName).DeleteMany(ctx, filter) -} - -// MongoMiddleware 中间件 -func (c *GinClient) MongoMiddleware() gin.HandlerFunc { - return func(ginCtx *gin.Context) { - - // 开始时间 - startTime := gotime.Current().TimestampWithMillisecond() - requestTime := gotime.Current().Time - - // 获取 - data, _ := ioutil.ReadAll(ginCtx.Request.Body) - - if c.logDebug { - c.zapLog.WithLogger().Sugar().Infof("[golog.gin.MongoMiddleware] %s", data) - } - - // 复用 - ginCtx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data)) - - blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: ginCtx.Writer} - ginCtx.Writer = blw - - // 处理请求 - ginCtx.Next() - - // 响应 - responseCode := ginCtx.Writer.Status() - responseBody := blw.body.String() - - //结束时间 - endTime := gotime.Current().TimestampWithMillisecond() - - go func() { - - var dataJson = true - - // 解析请求内容 - var jsonBody map[string]interface{} - - // 判断是否有内容 - if len(data) > 0 { - err := json.Unmarshal(data, &jsonBody) - if err != nil { - dataJson = false - } - } - - clientIp := gorequest.ClientIp(ginCtx.Request) - - var requestClientIpCountry string - var requestClientIpProvince string - var requestClientIpCity string - var requestClientIpIsp string - var requestClientIpLocationLatitude float64 - var requestClientIpLocationLongitude float64 - if c.ipService != nil { - if net.ParseIP(clientIp).To4() != nil { - // IPv4 - info := c.ipService.Analyse(clientIp) - requestClientIpCountry = info.Ip2regionV2info.Country - requestClientIpProvince = info.Ip2regionV2info.Province - requestClientIpCity = info.Ip2regionV2info.City - requestClientIpIsp = info.Ip2regionV2info.Operator - requestClientIpLocationLatitude = info.GeoipInfo.Location.Latitude - requestClientIpLocationLongitude = info.GeoipInfo.Location.Longitude - } else if net.ParseIP(clientIp).To16() != nil { - // IPv6 - info := c.ipService.Analyse(clientIp) - requestClientIpCountry = info.Ipv6wryInfo.Country - requestClientIpProvince = info.Ipv6wryInfo.Province - requestClientIpCity = info.Ipv6wryInfo.City - requestClientIpLocationLatitude = info.GeoipInfo.Location.Latitude - requestClientIpLocationLongitude = info.GeoipInfo.Location.Longitude - } - } - - // 记录 - if c.mongoClient != nil && c.mongoClient.Db != nil { - - var traceId = gotrace_id.GetGinTraceId(ginCtx) - - if dataJson { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.MongoMiddleware]准备使用{mongoRecordJson}保存数据:%s", data) - } - c.mongoRecordJson(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) - } else { - if c.logDebug { - c.zapLog.WithTraceIdStr(traceId).Sugar().Infof("[golog.gin.MongoMiddleware]准备使用{mongoRecordXml}保存数据:%s", data) - } - c.mongoRecordXml(ginCtx, traceId, requestTime, data, responseCode, responseBody, startTime, endTime, clientIp, requestClientIpCountry, requestClientIpProvince, requestClientIpCity, requestClientIpIsp, requestClientIpLocationLatitude, requestClientIpLocationLongitude) - } - } - }() - } -} diff --git a/go.mod b/go.mod index aff678c..263a2c9 100644 --- a/go.mod +++ b/go.mod @@ -11,9 +11,8 @@ require ( go.dtapp.net/gotime v1.0.5 go.dtapp.net/gotrace_id v1.0.6 go.dtapp.net/gourl v1.0.0 - go.mongodb.org/mongo-driver v1.10.2 go.uber.org/zap v1.23.0 - gorm.io/gorm v1.23.9 + gorm.io/datatypes v1.0.7 ) require ( @@ -74,6 +73,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect go.dtapp.net/gorandom v1.0.1 // indirect go.dtapp.net/gostring v1.0.10 // indirect + go.mongodb.org/mongo-driver v1.10.2 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect @@ -87,6 +87,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.3.6 // indirect gorm.io/driver/postgres v1.3.9 // indirect + gorm.io/gorm v1.23.9 // indirect mellium.im/sasl v0.3.0 // indirect modernc.org/libc v1.16.19 // indirect modernc.org/sqlite v1.18.0 // indirect diff --git a/go.sum b/go.sum index 41fa815..4ccf6e2 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,9 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -60,9 +63,12 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= @@ -114,6 +120,10 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -313,6 +323,7 @@ github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peK github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -331,6 +342,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= @@ -374,6 +386,7 @@ github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaF github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -554,12 +567,14 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -595,6 +610,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= @@ -722,16 +738,27 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/datatypes v1.0.7 h1:8NhJN4+annFjwV1WufDhFiPjdUvV1lSGUdg1UCjQIWY= +gorm.io/datatypes v1.0.7/go.mod h1:l9qkCuy0CdzDEop9HKUdcnC9gHC2sRlaFtHkTzsZRqg= +gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= gorm.io/driver/mysql v1.3.6 h1:BhX1Y/RyALb+T9bZ3t07wLnPZBukt+IRkMn8UZSNbGM= gorm.io/driver/mysql v1.3.6/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= +gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/postgres v1.3.9 h1:lWGiVt5CijhQAg0PWB7Od1RNcBw/jS4d2cAScBcSDXg= gorm.io/driver/postgres v1.3.9/go.mod h1:qw/FeqjxmYqW5dBcYNBsnhQULIApQdk7YuuDPktVi1U= +gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= +gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= +gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI= +gorm.io/driver/sqlserver v1.3.1/go.mod h1:w25Vrx2BG+CJNUu/xKbFhaKlGxT/nzRkhWCCoptX8tQ= +gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.9 h1:NSHG021i+MCznokeXR3udGaNyFyBQJW8MbjrJMVCfGw= diff --git a/vendor/gorm.io/datatypes/License b/vendor/gorm.io/datatypes/License new file mode 100644 index 0000000..037e165 --- /dev/null +++ b/vendor/gorm.io/datatypes/License @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013-NOW Jinzhu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/gorm.io/datatypes/README.md b/vendor/gorm.io/datatypes/README.md new file mode 100644 index 0000000..0760e4a --- /dev/null +++ b/vendor/gorm.io/datatypes/README.md @@ -0,0 +1,94 @@ +# GORM Data Types + +## JSON + +sqlite, mysql, postgres supported + +```go +import "gorm.io/datatypes" + +type UserWithJSON struct { + gorm.Model + Name string + Attributes datatypes.JSON +} + +DB.Create(&User{ + Name: "json-1", + Attributes: datatypes.JSON([]byte(`{"name": "jinzhu", "age": 18, "tags": ["tag1", "tag2"], "orgs": {"orga": "orga"}}`)), +} + +// Check JSON has keys +datatypes.JSONQuery("attributes").HasKey(value, keys...) + +db.Find(&user, datatypes.JSONQuery("attributes").HasKey("role")) +db.Find(&user, datatypes.JSONQuery("attributes").HasKey("orgs", "orga")) +// MySQL +// SELECT * FROM `users` WHERE JSON_EXTRACT(`attributes`, '$.role') IS NOT NULL +// SELECT * FROM `users` WHERE JSON_EXTRACT(`attributes`, '$.orgs.orga') IS NOT NULL + +// PostgreSQL +// SELECT * FROM "user" WHERE "attributes"::jsonb ? 'role' +// SELECT * FROM "user" WHERE "attributes"::jsonb -> 'orgs' ? 'orga' + + +// Check JSON extract value from keys equal to value +datatypes.JSONQuery("attributes").Equals(value, keys...) + +DB.First(&user, datatypes.JSONQuery("attributes").Equals("jinzhu", "name")) +DB.First(&user, datatypes.JSONQuery("attributes").Equals("orgb", "orgs", "orgb")) +// MySQL +// SELECT * FROM `user` WHERE JSON_EXTRACT(`attributes`, '$.name') = "jinzhu" +// SELECT * FROM `user` WHERE JSON_EXTRACT(`attributes`, '$.orgs.orgb') = "orgb" + +// PostgreSQL +// SELECT * FROM "user" WHERE json_extract_path_text("attributes"::json,'name') = 'jinzhu' +// SELECT * FROM "user" WHERE json_extract_path_text("attributes"::json,'orgs','orgb') = 'orgb' +``` + +NOTE: SQlite need to build with `json1` tag, e.g: `go build --tags json1`, refer https://github.com/mattn/go-sqlite3#usage + +## Date + +```go +import "gorm.io/datatypes" + +type UserWithDate struct { + gorm.Model + Name string + Date datatypes.Date +} + +user := UserWithDate{Name: "jinzhu", Date: datatypes.Date(time.Now())} +DB.Create(&user) +// INSERT INTO `user_with_dates` (`name`,`date`) VALUES ("jinzhu","2020-07-17 00:00:00") + +DB.First(&result, "name = ? AND date = ?", "jinzhu", datatypes.Date(curTime)) +// SELECT * FROM user_with_dates WHERE name = "jinzhu" AND date = "2020-07-17 00:00:00" ORDER BY `user_with_dates`.`id` LIMIT 1 +``` + +## Time + +MySQL, PostgreSQL, SQLite, SQLServer are supported. + +Time with nanoseconds is supported for some databases which support for time with fractional second scale. + +```go +import "gorm.io/datatypes" + +type UserWithTime struct { + gorm.Model + Name string + Time datatypes.Time +} + +user := UserWithTime{Name: "jinzhu", Time: datatypes.NewTime(1, 2, 3, 0)} +DB.Create(&user) +// INSERT INTO `user_with_times` (`name`,`time`) VALUES ("jinzhu","01:02:03") + +DB.First(&result, "name = ? AND time = ?", "jinzhu", datatypes.NewTime(1, 2, 3, 0)) +// SELECT * FROM user_with_times WHERE name = "jinzhu" AND time = "01:02:03" ORDER BY `user_with_times`.`id` LIMIT 1 +``` + +NOTE: If the current using database is SQLite, the field column type is defined as `TEXT` type +when GORM AutoMigrate because SQLite doesn't have time type. diff --git a/vendor/gorm.io/datatypes/date.go b/vendor/gorm.io/datatypes/date.go new file mode 100644 index 0000000..f0e7c51 --- /dev/null +++ b/vendor/gorm.io/datatypes/date.go @@ -0,0 +1,42 @@ +package datatypes + +import ( + "database/sql" + "database/sql/driver" + "time" +) + +type Date time.Time + +func (date *Date) Scan(value interface{}) (err error) { + nullTime := &sql.NullTime{} + err = nullTime.Scan(value) + *date = Date(nullTime.Time) + return +} + +func (date Date) Value() (driver.Value, error) { + y, m, d := time.Time(date).Date() + return time.Date(y, m, d, 0, 0, 0, 0, time.Time(date).Location()), nil +} + +// GormDataType gorm common data type +func (date Date) GormDataType() string { + return "date" +} + +func (date Date) GobEncode() ([]byte, error) { + return time.Time(date).GobEncode() +} + +func (date *Date) GobDecode(b []byte) error { + return (*time.Time)(date).GobDecode(b) +} + +func (date Date) MarshalJSON() ([]byte, error) { + return time.Time(date).MarshalJSON() +} + +func (date *Date) UnmarshalJSON(b []byte) error { + return (*time.Time)(date).UnmarshalJSON(b) +} diff --git a/vendor/gorm.io/datatypes/json.go b/vendor/gorm.io/datatypes/json.go new file mode 100644 index 0000000..496ca1c --- /dev/null +++ b/vendor/gorm.io/datatypes/json.go @@ -0,0 +1,280 @@ +package datatypes + +import ( + "context" + "database/sql/driver" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" + + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" +) + +// JSON defined JSON data type, need to implements driver.Valuer, sql.Scanner interface +type JSON json.RawMessage + +// Value return json value, implement driver.Valuer interface +func (j JSON) Value() (driver.Value, error) { + if len(j) == 0 { + return nil, nil + } + return string(j), nil +} + +// Scan scan value into Jsonb, implements sql.Scanner interface +func (j *JSON) Scan(value interface{}) error { + if value == nil { + *j = JSON("null") + return nil + } + var bytes []byte + switch v := value.(type) { + case []byte: + if len(v) > 0 { + bytes = make([]byte, len(v)) + copy(bytes, v) + } + case string: + bytes = []byte(v) + default: + return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value)) + } + + result := json.RawMessage(bytes) + *j = JSON(result) + return nil +} + +// MarshalJSON to output non base64 encoded []byte +func (j JSON) MarshalJSON() ([]byte, error) { + return json.RawMessage(j).MarshalJSON() +} + +// UnmarshalJSON to deserialize []byte +func (j *JSON) UnmarshalJSON(b []byte) error { + result := json.RawMessage{} + err := result.UnmarshalJSON(b) + *j = JSON(result) + return err +} + +func (j JSON) String() string { + return string(j) +} + +// GormDataType gorm common data type +func (JSON) GormDataType() string { + return "json" +} + +// GormDBDataType gorm db data type +func (JSON) GormDBDataType(db *gorm.DB, field *schema.Field) string { + switch db.Dialector.Name() { + case "sqlite": + return "JSON" + case "mysql": + return "JSON" + case "postgres": + return "JSONB" + } + return "" +} + +func (js JSON) GormValue(ctx context.Context, db *gorm.DB) clause.Expr { + if len(js) == 0 { + return gorm.Expr("NULL") + } + + data, _ := js.MarshalJSON() + + switch db.Dialector.Name() { + case "mysql": + if v, ok := db.Dialector.(*mysql.Dialector); ok && !strings.Contains(v.ServerVersion, "MariaDB") { + return gorm.Expr("CAST(? AS JSON)", string(data)) + } + } + + return gorm.Expr("?", string(data)) +} + +// JSONQueryExpression json query expression, implements clause.Expression interface to use as querier +type JSONQueryExpression struct { + column string + keys []string + hasKeys bool + equals bool + equalsValue interface{} + extract bool + path string +} + +// JSONQuery query column as json +func JSONQuery(column string) *JSONQueryExpression { + return &JSONQueryExpression{column: column} +} + +// Extract extract json with path +func (jsonQuery *JSONQueryExpression) Extract(path string) *JSONQueryExpression { + jsonQuery.extract = true + jsonQuery.path = path + return jsonQuery +} + +// HasKey returns clause.Expression +func (jsonQuery *JSONQueryExpression) HasKey(keys ...string) *JSONQueryExpression { + jsonQuery.keys = keys + jsonQuery.hasKeys = true + return jsonQuery +} + +// Keys returns clause.Expression +func (jsonQuery *JSONQueryExpression) Equals(value interface{}, keys ...string) *JSONQueryExpression { + jsonQuery.keys = keys + jsonQuery.equals = true + jsonQuery.equalsValue = value + return jsonQuery +} + +// Build implements clause.Expression +func (jsonQuery *JSONQueryExpression) Build(builder clause.Builder) { + if stmt, ok := builder.(*gorm.Statement); ok { + switch stmt.Dialector.Name() { + case "mysql", "sqlite": + switch { + case jsonQuery.extract: + builder.WriteString("JSON_EXTRACT(") + builder.WriteQuoted(jsonQuery.column) + builder.WriteByte(',') + builder.AddVar(stmt, jsonQuery.path) + builder.WriteString(")") + case jsonQuery.hasKeys: + if len(jsonQuery.keys) > 0 { + builder.WriteString("JSON_EXTRACT(") + builder.WriteQuoted(jsonQuery.column) + builder.WriteByte(',') + builder.AddVar(stmt, jsonQueryJoin(jsonQuery.keys)) + builder.WriteString(") IS NOT NULL") + } + case jsonQuery.equals: + if len(jsonQuery.keys) > 0 { + builder.WriteString("JSON_EXTRACT(") + builder.WriteQuoted(jsonQuery.column) + builder.WriteByte(',') + builder.AddVar(stmt, jsonQueryJoin(jsonQuery.keys)) + builder.WriteString(") = ") + if value, ok := jsonQuery.equalsValue.(bool); ok { + builder.WriteString(strconv.FormatBool(value)) + } else { + stmt.AddVar(builder, jsonQuery.equalsValue) + } + } + } + case "postgres": + switch { + case jsonQuery.hasKeys: + if len(jsonQuery.keys) > 0 { + stmt.WriteQuoted(jsonQuery.column) + stmt.WriteString("::jsonb") + for _, key := range jsonQuery.keys[0 : len(jsonQuery.keys)-1] { + stmt.WriteString(" -> ") + stmt.AddVar(builder, key) + } + + stmt.WriteString(" ? ") + stmt.AddVar(builder, jsonQuery.keys[len(jsonQuery.keys)-1]) + } + case jsonQuery.equals: + if len(jsonQuery.keys) > 0 { + builder.WriteString(fmt.Sprintf("json_extract_path_text(%v::json,", stmt.Quote(jsonQuery.column))) + + for idx, key := range jsonQuery.keys { + if idx > 0 { + builder.WriteByte(',') + } + stmt.AddVar(builder, key) + } + builder.WriteString(") = ") + + if _, ok := jsonQuery.equalsValue.(string); ok { + stmt.AddVar(builder, jsonQuery.equalsValue) + } else { + stmt.AddVar(builder, fmt.Sprint(jsonQuery.equalsValue)) + } + } + } + } + } +} + +// JSONOverlapsExpression JSON_OVERLAPS expression, implements clause.Expression interface to use as querier +type JSONOverlapsExpression struct { + column clause.Expression + val string +} + +// JSONOverlaps query column as json +func JSONOverlaps(column clause.Expression, value string) *JSONOverlapsExpression { + return &JSONOverlapsExpression{ + column: column, + val: value, + } +} + +// Build implements clause.Expression +// only mysql support JSON_OVERLAPS +func (json *JSONOverlapsExpression) Build(builder clause.Builder) { + if stmt, ok := builder.(*gorm.Statement); ok { + switch stmt.Dialector.Name() { + case "mysql": + builder.WriteString("JSON_OVERLAPS(") + json.column.Build(builder) + builder.WriteString(",") + builder.AddVar(stmt, json.val) + builder.WriteString(")") + } + } +} + +type columnExpression string + +func Column(col string) columnExpression { + return columnExpression(col) +} + +func (col columnExpression) Build(builder clause.Builder) { + if stmt, ok := builder.(*gorm.Statement); ok { + switch stmt.Dialector.Name() { + case "mysql", "sqlite", "postgres": + builder.WriteString(stmt.Quote(string(col))) + } + } +} + +const prefix = "$." + +func jsonQueryJoin(keys []string) string { + if len(keys) == 1 { + return prefix + keys[0] + } + + n := len(prefix) + n += len(keys) - 1 + for i := 0; i < len(keys); i++ { + n += len(keys[i]) + } + + var b strings.Builder + b.Grow(n) + b.WriteString(prefix) + b.WriteString(keys[0]) + for _, key := range keys[1:] { + b.WriteString(".") + b.WriteString(key) + } + return b.String() +} diff --git a/vendor/gorm.io/datatypes/json_map.go b/vendor/gorm.io/datatypes/json_map.go new file mode 100644 index 0000000..7845758 --- /dev/null +++ b/vendor/gorm.io/datatypes/json_map.go @@ -0,0 +1,96 @@ +package datatypes + +import ( + "context" + "database/sql/driver" + "encoding/json" + "errors" + "fmt" + "strings" + + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" +) + +// JSONMap defined JSON data type, need to implements driver.Valuer, sql.Scanner interface +type JSONMap map[string]interface{} + +// Value return json value, implement driver.Valuer interface +func (m JSONMap) Value() (driver.Value, error) { + if m == nil { + return nil, nil + } + ba, err := m.MarshalJSON() + return string(ba), err +} + +// Scan scan value into Jsonb, implements sql.Scanner interface +func (m *JSONMap) Scan(val interface{}) error { + if val == nil { + *m = make(JSONMap) + return nil + } + var ba []byte + switch v := val.(type) { + case []byte: + ba = v + case string: + ba = []byte(v) + default: + return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", val)) + } + t := map[string]interface{}{} + err := json.Unmarshal(ba, &t) + *m = t + return err +} + +// MarshalJSON to output non base64 encoded []byte +func (m JSONMap) MarshalJSON() ([]byte, error) { + if m == nil { + return []byte("null"), nil + } + t := (map[string]interface{})(m) + return json.Marshal(t) +} + +// UnmarshalJSON to deserialize []byte +func (m *JSONMap) UnmarshalJSON(b []byte) error { + t := map[string]interface{}{} + err := json.Unmarshal(b, &t) + *m = JSONMap(t) + return err +} + +// GormDataType gorm common data type +func (m JSONMap) GormDataType() string { + return "jsonmap" +} + +// GormDBDataType gorm db data type +func (JSONMap) GormDBDataType(db *gorm.DB, field *schema.Field) string { + switch db.Dialector.Name() { + case "sqlite": + return "JSON" + case "mysql": + return "JSON" + case "postgres": + return "JSONB" + case "sqlserver": + return "NVARCHAR(MAX)" + } + return "" +} + +func (jm JSONMap) GormValue(ctx context.Context, db *gorm.DB) clause.Expr { + data, _ := jm.MarshalJSON() + switch db.Dialector.Name() { + case "mysql": + if v, ok := db.Dialector.(*mysql.Dialector); ok && !strings.Contains(v.ServerVersion, "MariaDB") { + return gorm.Expr("CAST(? AS JSON)", string(data)) + } + } + return gorm.Expr("?", string(data)) +} diff --git a/vendor/gorm.io/datatypes/test_all.sh b/vendor/gorm.io/datatypes/test_all.sh new file mode 100644 index 0000000..4bf5a16 --- /dev/null +++ b/vendor/gorm.io/datatypes/test_all.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +dialects=("postgres" "postgres_simple" "mysql" "mssql" "sqlite") + +for dialect in "${dialects[@]}" ; do + if [ "$GORM_DIALECT" = "" ] || [ "$GORM_DIALECT" = "${dialect}" ] + then + GORM_DIALECT=${dialect} go test --tags "json1" + fi +done diff --git a/vendor/gorm.io/datatypes/time.go b/vendor/gorm.io/datatypes/time.go new file mode 100644 index 0000000..4cd0a05 --- /dev/null +++ b/vendor/gorm.io/datatypes/time.go @@ -0,0 +1,123 @@ +package datatypes + +import ( + "database/sql/driver" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "gorm.io/gorm" + "gorm.io/gorm/schema" +) + +// Time is time data type. +type Time time.Duration + +// NewTime is a constructor for Time and returns new Time. +func NewTime(hour, min, sec, nsec int) Time { + return newTime(hour, min, sec, nsec) +} + +func newTime(hour, min, sec, nsec int) Time { + return Time( + time.Duration(hour)*time.Hour + + time.Duration(min)*time.Minute + + time.Duration(sec)*time.Second + + time.Duration(nsec)*time.Nanosecond, + ) +} + +// GormDataType returns gorm common data type. This type is used for the field's column type. +func (Time) GormDataType() string { + return "time" +} + +// GormDBDataType returns gorm DB data type based on the current using database. +func (Time) GormDBDataType(db *gorm.DB, field *schema.Field) string { + switch db.Dialector.Name() { + case "mysql": + return "TIME" + case "postgres": + return "TIME" + case "sqlserver": + return "TIME" + case "sqlite": + return "TEXT" + default: + return "" + } +} + +// Scan implements sql.Scanner interface and scans value into Time, +func (t *Time) Scan(src interface{}) error { + switch v := src.(type) { + case []byte: + t.setFromString(string(v)) + case string: + t.setFromString(v) + case time.Time: + t.setFromTime(v) + default: + return errors.New(fmt.Sprintf("failed to scan value: %v", v)) + } + + return nil +} + +func (t *Time) setFromString(str string) { + var h, m, s, n int + fmt.Sscanf(str, "%02d:%02d:%02d.%09d", &h, &m, &s, &n) + *t = newTime(h, m, s, n) +} + +func (t *Time) setFromTime(src time.Time) { + *t = newTime(src.Hour(), src.Minute(), src.Second(), src.Nanosecond()) +} + +// Value implements driver.Valuer interface and returns string format of Time. +func (t Time) Value() (driver.Value, error) { + return t.String(), nil +} + +// String implements fmt.Stringer interface. +func (t Time) String() string { + if nsec := t.nanoseconds(); nsec > 0 { + return fmt.Sprintf("%02d:%02d:%02d.%09d", t.hours(), t.minutes(), t.seconds(), nsec) + } else { + // omit nanoseconds unless any value is specified + return fmt.Sprintf("%02d:%02d:%02d", t.hours(), t.minutes(), t.seconds()) + } +} + +func (t Time) hours() int { + return int(time.Duration(t).Truncate(time.Hour).Hours()) +} + +func (t Time) minutes() int { + return int((time.Duration(t) % time.Hour).Truncate(time.Minute).Minutes()) +} + +func (t Time) seconds() int { + return int((time.Duration(t) % time.Minute).Truncate(time.Second).Seconds()) +} + +func (t Time) nanoseconds() int { + return int((time.Duration(t) % time.Second).Nanoseconds()) +} + +// MarshalJSON implements json.Marshaler to convert Time to json serialization. +func (t Time) MarshalJSON() ([]byte, error) { + return json.Marshal(t.String()) +} + +// UnmarshalJSON implements json.Unmarshaler to deserialize json data. +func (t *Time) UnmarshalJSON(data []byte) error { + // ignore null + if string(data) == "null" { + return nil + } + t.setFromString(strings.Trim(string(data), `"`)) + return nil +} diff --git a/vendor/gorm.io/datatypes/url.go b/vendor/gorm.io/datatypes/url.go new file mode 100644 index 0000000..c58a895 --- /dev/null +++ b/vendor/gorm.io/datatypes/url.go @@ -0,0 +1,66 @@ +package datatypes + +import ( + "database/sql/driver" + "encoding/json" + "errors" + "fmt" + "net/url" + "strings" + + "gorm.io/gorm" + "gorm.io/gorm/schema" +) + +type URL url.URL + +func (u URL) Value() (driver.Value, error) { + return u.String(), nil +} + +func (u *URL) Scan(value interface{}) error { + var us string + switch v := value.(type) { + case []byte: + us = string(v) + case string: + us = v + default: + return errors.New(fmt.Sprint("Failed to parse URL:", value)) + } + uu, err := url.Parse(us) + if err != nil { + return err + } + *u = URL(*uu) + return nil +} + +func (URL) GormDataType() string { + return "url" +} + +func (URL) GormDBDataType(db *gorm.DB, field *schema.Field) string { + return "TEXT" +} + +func (u *URL) String() string { + return (*url.URL)(u).String() +} + +func (u URL) MarshalJSON() ([]byte, error) { + return json.Marshal(u.String()) +} + +func (u *URL) UnmarshalJSON(data []byte) error { + // ignore null + if string(data) == "null" { + return nil + } + uu, err := url.Parse(strings.Trim(string(data), `"'`)) + if err != nil { + return err + } + *u = URL(*uu) + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9c0606f..c2ae700 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -401,6 +401,9 @@ google.golang.org/protobuf/runtime/protoiface # gopkg.in/yaml.v2 v2.4.0 ## explicit; go 1.15 gopkg.in/yaml.v2 +# gorm.io/datatypes v1.0.7 +## explicit; go 1.14 +gorm.io/datatypes # gorm.io/driver/mysql v1.3.6 ## explicit; go 1.14 gorm.io/driver/mysql