From c79c1f2c9a681a9faf3e77da4b34312303d8d1ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=99=E2=97=A6=20The=20Tablet=20=E2=9D=80=20GamerGirla?= =?UTF-8?q?ndCo=20=E2=97=A6=E2=9D=A7?= Date: Mon, 14 Jul 2025 16:01:51 -0400 Subject: [PATCH] add ability to configure ORM logging, log destination, and more --- diamond.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/diamond.go b/diamond.go index f00b4ac..ffb4b0a 100644 --- a/diamond.go +++ b/diamond.go @@ -5,21 +5,31 @@ import ( "fmt" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" + "io" "log/slog" + "os" + "rockfic.com/orm/internal/logging" "time" ) const LevelQuery = slog.Level(-6) const defaultKey = "default" +type Config struct { + DryRun bool + LogLevel slog.Level + LogTo io.Writer +} + type Engine struct { modelMap *internalModelMap conn *pgxpool.Pool m2mSeen map[string]bool dryRun bool - cfg *pgxpool.Config + pgCfg *pgxpool.Config ctx context.Context logger *slog.Logger + cfg *Config levelVar *slog.LevelVar connStr string } @@ -91,19 +101,57 @@ func (e *Engine) MigrateDropping() error { 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() { 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{ modelMap: &internalModelMap{ Map: make(map[string]*Model), }, - m2mSeen: make(map[string]bool), - dryRun: connString == "", - ctx: context.Background(), + m2mSeen: make(map[string]bool), + dryRun: connString == "", + 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 != "" { engines.Mux.Lock() if len(engines.Engines) == 0 || engines.Engines[defaultKey] == nil { @@ -114,14 +162,14 @@ func Open(connString string) (*Engine, error) { e.connStr = "" engines.Mux.Unlock() var err error - e.cfg, err = pgxpool.ParseConfig(connString) - e.cfg.MinConns = 5 - e.cfg.MaxConns = 10 - e.cfg.MaxConnIdleTime = time.Minute * 2 + e.pgCfg, err = pgxpool.ParseConfig(connString) + e.pgCfg.MinConns = 5 + e.pgCfg.MaxConns = 10 + e.pgCfg.MaxConnIdleTime = time.Minute * 2 if err != nil { return nil, err } - e.conn, err = pgxpool.NewWithConfig(e.ctx, e.cfg) + e.conn, err = pgxpool.NewWithConfig(e.ctx, e.pgCfg) if err != nil { return nil, err }