add ability to configure ORM logging, log destination, and more

This commit is contained in:
☙◦ The Tablet ❀ GamerGirlandCo ◦❧ 2025-07-14 16:01:51 -04:00
parent 01d912cac6
commit c79c1f2c9a
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C

View File

@ -5,21 +5,31 @@ import (
"fmt" "fmt"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
"io"
"log/slog" "log/slog"
"os"
"rockfic.com/orm/internal/logging"
"time" "time"
) )
const LevelQuery = slog.Level(-6) const LevelQuery = slog.Level(-6)
const defaultKey = "default" const defaultKey = "default"
type Config struct {
DryRun bool
LogLevel slog.Level
LogTo io.Writer
}
type Engine struct { type Engine struct {
modelMap *internalModelMap modelMap *internalModelMap
conn *pgxpool.Pool conn *pgxpool.Pool
m2mSeen map[string]bool m2mSeen map[string]bool
dryRun bool dryRun bool
cfg *pgxpool.Config pgCfg *pgxpool.Config
ctx context.Context ctx context.Context
logger *slog.Logger logger *slog.Logger
cfg *Config
levelVar *slog.LevelVar levelVar *slog.LevelVar
connStr string connStr string
} }
@ -91,19 +101,57 @@ func (e *Engine) MigrateDropping() error {
return e.Migrate() return e.Migrate()
} }
func (e *Engine) logQuery(msg, sql string, args []any) {
e.logger.Log(e.ctx, LevelQuery, msg, "sql", sql, "args", logTrunc(200, args))
}
func (e *Engine) logSql(msg, sql string) {
e.logger.Log(e.ctx, LevelQuery, msg, "sql", sql)
}
func (e *Engine) Disconnect() { func (e *Engine) Disconnect() {
e.conn.Close() e.conn.Close()
} }
func Open(connString string) (*Engine, error) { func Open(connString string, cfg *Config) (*Engine, error) {
if cfg == nil {
cfg = &Config{
LogLevel: slog.LevelInfo,
LogTo: os.Stdout,
DryRun: connString == "",
}
} else {
if cfg.LogTo == nil {
cfg.LogTo = os.Stdout
}
}
e := &Engine{ e := &Engine{
modelMap: &internalModelMap{ modelMap: &internalModelMap{
Map: make(map[string]*Model), Map: make(map[string]*Model),
}, },
m2mSeen: make(map[string]bool), m2mSeen: make(map[string]bool),
dryRun: connString == "", dryRun: connString == "",
ctx: context.Background(), ctx: context.Background(),
levelVar: new(slog.LevelVar),
cfg: cfg,
} }
e.levelVar.Set(cfg.LogLevel)
replacer := func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.LevelKey {
level := a.Value.Any().(slog.Level)
switch level {
case LevelQuery:
a.Value = slog.StringValue("query")
}
}
return a
}
e.logger = slog.New(logging.NewFormattedHandler(cfg.LogTo, logging.Options{
Level: e.levelVar,
ReplaceAttr: replacer,
Format: "{{.Time}} [{{.Level}}] {{.Message}} | {{ rest }}",
}))
slog.SetDefault(e.logger)
if connString != "" { if connString != "" {
engines.Mux.Lock() engines.Mux.Lock()
if len(engines.Engines) == 0 || engines.Engines[defaultKey] == nil { if len(engines.Engines) == 0 || engines.Engines[defaultKey] == nil {
@ -114,14 +162,14 @@ func Open(connString string) (*Engine, error) {
e.connStr = "" e.connStr = ""
engines.Mux.Unlock() engines.Mux.Unlock()
var err error var err error
e.cfg, err = pgxpool.ParseConfig(connString) e.pgCfg, err = pgxpool.ParseConfig(connString)
e.cfg.MinConns = 5 e.pgCfg.MinConns = 5
e.cfg.MaxConns = 10 e.pgCfg.MaxConns = 10
e.cfg.MaxConnIdleTime = time.Minute * 2 e.pgCfg.MaxConnIdleTime = time.Minute * 2
if err != nil { if err != nil {
return nil, err return nil, err
} }
e.conn, err = pgxpool.NewWithConfig(e.ctx, e.cfg) e.conn, err = pgxpool.NewWithConfig(e.ctx, e.pgCfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }