egorm

package module
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2022 License: MIT Imports: 30 Imported by: 0

README

egorm 组件使用指南

goproxy.cn Release Example Doc

1 简介

gorm 进行了轻量封装,并提供了以下功能:

  • 规范了标准配置格式,提供了统一的 Load().Build() 方法。
  • 支持自定义拦截器
  • 提供了默认的 Debug 拦截器,开启 Debug 后可输出 Request、Response 至终端。
  • 提供了默认的 Metric 拦截器,开启后可采集 Prometheus 指标数据
  • 提供了默认的 OpenTelemetry 拦截器,开启后可采集 Tracing Span 数据

2 说明

  • ego版本:ego@v1.0.1
  • egorm版本: egorm@1.0.2

3 使用方式

go get github.com/ego-component/egorm

4 GORM配置

type Config struct {
    Dialect                    string        // 选择数据库种类,默认mysql,postgres,mssql
    DSN                        string        // DSN地址: mysql://username:password@tcp(127.0.0.1:3306)/mysql?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&loc=Local&timeout=1s&readTimeout=3s&writeTimeout=3s
    Debug                      bool          // 是否开启调试,默认不开启,开启后并加上export EGO_DEBUG=true,可以看到每次请求,配置名、地址、耗时、请求数据、响应数据
    RawDebug                   bool          // 是否开启原生调试开关,默认不开启
    MaxIdleConns               int           // 最大空闲连接数,默认10
    MaxOpenConns               int           // 最大活动连接数,默认100
    ConnMaxLifetime            time.Duration // 连接的最大存活时间,默认300s
    OnFail                     string        // 创建连接的错误级别,=panic时,如果创建失败,立即panic,默认连接不上panic
    SlowLogThreshold           time.Duration // 慢日志阈值,默认500ms
    EnableMetricInterceptor    bool          // 是否开启监控,默认开启
    EnableTraceInterceptor     bool          // 是否开启链路追踪,默认开启
    EnableDetailSQL            bool          // 记录错误sql时,是否打印包含参数的完整sql语句,select * from aid = ?;
    EnableAccessInterceptor    bool          // 是否开启,记录请求数据
    EnableAccessInterceptorReq bool          // 是否开启记录请求参数
    EnableAccessInterceptorRes bool          // 是否开启记录响应参数
}

5 普通GORM查询

5.1 用户配置

[mysql.test]
   debug = true # ego重写gorm debug,打开后可以看到,配置名、代码执行行号、地址、耗时、请求数据、响应数据
   dsn = "root:root@tcp(127.0.0.1:3306)/ego?charset=utf8&parseTime=True&loc=Local&readTimeout=1s&timeout=1s&writeTimeout=3s"

5.2 优雅的Debug

通过开启debug配置和命令行的export EGO_DEBUG=true,我们就可以在测试环境里看到请求里的配置名、地址、耗时、请求数据、响应数据 image 当然你也可以开启gorm原生的调试,将rawDebug设置为true

5.3 用户代码

配置创建一个 gorm 的配置项,其中内容按照上文配置进行填写。以上这个示例里这个配置key是gorm.test

代码中创建一个 gorm 实例 egorm.Load("key").Build(),代码中的 key 和配置中的 key 要保持一致。创建完 gorm 实例后,就可以直接使用他对 db 进行 crud

package main

import (
	"github.com/gotomicro/ego"
	"github.com/ego-component/egorm"
	"github.com/gotomicro/ego/core/elog"
)

/**
1.新建一个数据库叫test
2.执行以下example,export EGO_DEBUG=true && go run main.go --config=config.toml
*/
type User struct {
	Id       int    `gorm:"not null" json:"id"`
	Nickname string `gorm:"not null" json:"name"`
}

func (User) TableName() string {
	return "user2"
}

func main() {
	err := ego.New().Invoker(
		openDB,
		testDB,
	).Run()
	if err != nil {
		elog.Error("startup", elog.Any("err", err))
	}
}

var gormDB *egorm.Component

func openDB() error {
	gormDB = egorm.Load("mysql.test").Build()
	models := []interface{}{
		&User{},
	}
	gormDB.SingularTable(true)
	gormDB.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(models...)
	gormDB.Create(&User{
		Nickname: "ego",
	})
	return nil
}

func testDB() error {
	var user User
	err := gormDB.Where("id = ?", 100).Find(&user).Error
	elog.Info("user info", elog.String("name", user.Nickname))
	return err
}

6 GORM的日志

任何gorm的请求都会记录gorm的错误access日志,如果需要对gorm的日志做定制化处理,可参考以下使用方式。

6.1 开启GORM的access日志

线上在并发量不高,或者核心业务下可以开启全量access日志,这样方便我们排查问题

6.2 开启日志方式

在原有的mysql配置中,加入以下三行配置,gorm的日志里就会记录响应的数据

[mysql.test]
enableAccessInterceptor=true       # 是否开启,记录请求数据
enableAccessInterceptorReq=true    # 是否开启记录请求参数
enableAccessInterceptorRes=true    # 是否开启记录响应参数

img.png

6.3 开启日志的详细数据

记录请求参数日志为了安全起见,默认是不开启详细的sql数据,记录的是参数绑定的SQL日志,如果需要开启详细数据,需要在配置里添加``

[mysql.test]
enableDetailSQL=true       # 记录sql时,是否打印包含参数的完整sql语句,select * from aid = ?;

img.png

6.4 开启日志的链路数据

代码方面使用db.WithContext(ctx),会在access日志中自动记录trace id信息

6.5 开启自定义日志字段的数据

在使用了ego的自定义字段功能export EGO_LOG_EXTRA_KEYS=X-Ego-Uid,将对应的数据塞入到context中,那么gorm的access日志就可以记录对应字段信息。 参考详细文档

func testDB() error {
	var user User
	for _, db := range DBs {
		ctx := context.Background()
		ctx = transport.WithValue(ctx, "X-Ego-Uid", 9527)
		err := db.WithContext(ctx).Where("id = ?", 100).First(&user).Error
		elog.Info("user info", elog.String("name", user.Nickname), elog.FieldErr(err))
	}
	return nil
}

Documentation

Index

Constants

View Source
const PackageName = "component.egorm"

PackageName ...

Variables

View Source
var (
	// ErrRecordNotFound returns a "record not found error". Occurs only when attempting to query the database with a struct; querying with a slice won't return this error
	ErrRecordNotFound = gorm.ErrRecordNotFound
)

Functions

func BuildQuery

func BuildQuery(conds Conds) (sql string, binds []interface{})

BuildQuery 根据conds构建sql和绑定的参数

func DefaultConfig

func DefaultConfig() *config

DefaultConfig 返回默认配置

Types

type Association

type Association = gorm.Association

Association ...

type Component

type Component = gorm.DB

Component ...

func WithContext

func WithContext(ctx context.Context, db *Component) *Component

WithContext ...

type Cond

type Cond struct {
	// Op MySQL中查询条件,如like,=,in
	Op string
	// Val 查询条件对应的值
	Val interface{}
}

Cond 为字段查询结构体

type Conds

type Conds map[string]interface{}

Conds 为Cond类型map,用于定义Where方法参数 map[field.name]interface{}

type Container

type Container struct {
	// contains filtered or unexported fields
}

Container ...

func DefaultContainer

func DefaultContainer() *Container

DefaultContainer ...

func Load

func Load(key string) *Container

Load ...

func (*Container) Build

func (c *Container) Build(options ...Option) *Component

Build 构建组件

type DB

type DB gorm.DB

DB ...

type Dialector

type Dialector = gorm.Dialector

Dialector ...

type Field

type Field = schema.Field

Field ...

type Handler

type Handler func(*gorm.DB)

Handler ...

type Interceptor

type Interceptor func(string, *manager.DSN, string, *config, *elog.Component) func(next Handler) Handler

Interceptor ...

type Logger

type Logger = logger.Interface

Logger ...

type Model

type Model = gorm.Model

Model ...

type NamingStrategy

type NamingStrategy = schema.NamingStrategy

NamingStrategy ...

type Option

type Option func(c *Container)

Option 可选项

func WithDSN

func WithDSN(dsn string) Option

WithDSN 设置dsn

func WithDSNParser

func WithDSNParser(parser manager.DSNParser) Option

WithDSNParser 设置自定义dsnParser

func WithInterceptor

func WithInterceptor(is ...Interceptor) Option

WithInterceptor 设置自定义拦截器

type Processor

type Processor interface {
	Get(name string) func(*gorm.DB)
	Replace(name string, handler func(*gorm.DB)) error
}

Processor ...

Directories

Path Synopsis
examples
internal
dsn

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL