Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [#358] add logger for DB #908

Merged
merged 8 commits into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion contracts/database/db/db.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,81 @@
package db

import "database/sql"
import (
"context"
"database/sql"
)

type DB interface {
Table(name string) Query
WithContext(ctx context.Context) DB
}

type Query interface {
// Avg(column string) (any, error)
// Count(dest *int64) error
// Chunk(size int, callback func(rows []any) error) error
// CrossJoin(table string, on any, args ...any) Query
// DoesntExist() (bool, error)
// Distinct() Query
// dump
// dumpRawSql
// Each(callback func(rows []any) error) error
// Exists() (bool, error)
// Find(dest any, conds ...any) error
First(dest any) error
// firstOrFail
// decrement
Delete() (*Result, error)
Get(dest any) error
// GroupBy(column string) Query
// GroupByRaw(query string, args ...any) Query
// having
// HavingRaw(query any, args ...any) Query
// increment
// inRandomOrder
Insert(data any) (*Result, error)
// incrementEach
// insertGetId
// Join(table string, on any, args ...any) Query
// latest
// LeftJoin(table string, on any, args ...any) Query
// limit
// lockForUpdate
// Max(column string) (any, error)
// offset
// OrderBy(column string) Query
// orderByDesc
// OrderByRaw(query string, args ...any) Query
// OrWhere(query any, args ...any) Query
// OrWhereLike()
// OrWhereNotLike
// Pluck(column string, dest any) error
// RightJoin(table string, on any, args ...any) Query
// Select(dest any, columns ...string) error
// SelectRaw(query string, args ...any) (any, error)
// sharedLock
// skip
// take
Update(data any) (*Result, error)
// updateOrInsert
// Value(column string, dest any) error
// when
Where(query any, args ...any) Query
// WhereAll()
// WhereAny()
// whereBetween
// whereColumn
// whereExists
// WhereLike()
// WhereIn()
// WhereNone()
// WhereNot()
// whereNotBetween
// whereNotIn
// WhereNotLike()
// whereNotNull
// WhereNull(column string) Query
// WhereRaw(query string, args ...any) Query
}

type Result struct {
Expand Down
2 changes: 2 additions & 0 deletions contracts/database/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type Driver interface {
Config() database.Config
DB() (*sql.DB, error)
Docker() (docker.DatabaseDriver, error)
// Explain generate SQL string with given parameters
Explain(sql string, vars ...any) string
Gorm() (*gorm.DB, GormQuery, error)
Grammar() schema.Grammar
Processor() schema.Processor
Expand Down
28 changes: 28 additions & 0 deletions contracts/database/logger/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package logger

import (
"context"

"gorm.io/gorm/logger"

"github.com/goravel/framework/support/carbon"
)

// Level log level
type Level int

const (
Silent Level = iota + 1
Error
Warn
Info
)

type Logger interface {
Level(Level) Logger
Info(context.Context, string, ...any)
Warn(context.Context, string, ...any)
Error(context.Context, string, ...any)
Trace(ctx context.Context, begin carbon.Carbon, sql string, rowsAffected int64, err error)
ToGorm() logger.Interface
}
23 changes: 16 additions & 7 deletions database/db/db.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
package db

import (
"context"
"fmt"

"github.com/jmoiron/sqlx"

"github.com/goravel/framework/contracts/config"
"github.com/goravel/framework/contracts/database"
"github.com/goravel/framework/contracts/database/db"
contractsdriver "github.com/goravel/framework/contracts/database/driver"
contractslogger "github.com/goravel/framework/contracts/database/logger"
"github.com/goravel/framework/contracts/log"
"github.com/goravel/framework/database/logger"
"github.com/goravel/framework/errors"
)

type DB struct {
builder db.Builder
config database.Config
ctx context.Context
driver contractsdriver.Driver
logger contractslogger.Logger
}

func NewDB(config database.Config, builder db.Builder) db.DB {
return &DB{config: config, builder: builder}
func NewDB(ctx context.Context, driver contractsdriver.Driver, logger contractslogger.Logger, builder db.Builder) db.DB {
return &DB{ctx: ctx, driver: driver, logger: logger, builder: builder}
}

func BuildDB(config config.Config, connection string) (db.DB, error) {
func BuildDB(config config.Config, log log.Log, connection string) (db.DB, error) {
driverCallback, exist := config.Get(fmt.Sprintf("database.connections.%s.via", connection)).(func() (contractsdriver.Driver, error))
if !exist {
return nil, errors.DatabaseConfigNotFound
Expand All @@ -37,9 +42,13 @@ func BuildDB(config config.Config, connection string) (db.DB, error) {
return nil, err
}

return NewDB(driver.Config(), sqlx.NewDb(instance, driver.Config().Driver)), nil
return NewDB(context.Background(), driver, logger.NewLogger(config, log), sqlx.NewDb(instance, driver.Config().Driver)), nil
}

func (r *DB) Table(name string) db.Query {
return NewQuery(r.config, r.builder, name)
return NewQuery(r.ctx, r.driver, r.builder, r.logger, name)
}

func (r *DB) WithContext(ctx context.Context) db.DB {
return NewDB(ctx, r.driver, r.logger, r.builder)
}
12 changes: 7 additions & 5 deletions database/db/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,19 @@ func TestBuildDB(t *testing.T) {
driverCallback := func() (contractsdriver.Driver, error) {
return mockDriver, nil
}
mockConfig.On("Get", "database.connections.mysql.via").Return(driverCallback)
mockDriver.On("DB").Return(&sql.DB{}, nil)
mockDriver.On("Config").Return(database.Config{Driver: "mysql"})
mockConfig.EXPECT().Get("database.connections.mysql.via").Return(driverCallback).Once()
mockDriver.EXPECT().DB().Return(&sql.DB{}, nil).Once()
mockDriver.EXPECT().Config().Return(database.Config{Driver: "mysql"}).Once()
mockConfig.EXPECT().GetBool("app.debug").Return(false).Once()
mockConfig.EXPECT().GetInt("database.slow_threshold", 200).Return(200).Once()
},
expectedError: nil,
},
{
name: "Config Not Found",
connection: "invalid",
setup: func() {
mockConfig.On("Get", "database.connections.invalid.via").Return(nil)
mockConfig.EXPECT().Get("database.connections.invalid.via").Return(nil).Once()
},
expectedError: errors.DatabaseConfigNotFound,
},
Expand All @@ -54,7 +56,7 @@ func TestBuildDB(t *testing.T) {
mockDriver = mocksdriver.NewDriver(t)
test.setup()

db, err := BuildDB(mockConfig, test.connection)
db, err := BuildDB(mockConfig, nil, test.connection)
if test.expectedError != nil {
assert.Equal(t, test.expectedError, err)
assert.Nil(t, db)
Expand Down
Loading
Loading