package database import ( "context" "database/sql" "log/slog" "time" ) const slowQueryThreshold = 50 * time.Millisecond // logSlowQuery logs queries that take longer than slowQueryThreshold func logSlowQuery(logger *slog.Logger, query string, start time.Time) { elapsed := time.Since(start) if elapsed > slowQueryThreshold { logger.Debug("Slow query", "query", query, "duration", elapsed) } } // queryRow wraps QueryRow with slow query logging func (d *Database) queryRow(query string, args ...interface{}) *sql.Row { start := time.Now() defer logSlowQuery(d.logger, query, start) return d.db.QueryRow(query, args...) } // query wraps Query with slow query logging // nolint:unused // kept for future use to ensure all queries go through slow query logging func (d *Database) query(query string, args ...interface{}) (*sql.Rows, error) { start := time.Now() defer logSlowQuery(d.logger, query, start) return d.db.Query(query, args...) } // exec wraps Exec with slow query logging func (d *Database) exec(query string, args ...interface{}) error { start := time.Now() defer logSlowQuery(d.logger, query, start) _, err := d.db.Exec(query, args...) return err } // loggingTx wraps sql.Tx to log slow queries type loggingTx struct { *sql.Tx logger *slog.Logger } // QueryRow wraps sql.Tx.QueryRow to log slow queries func (tx *loggingTx) QueryRow(query string, args ...interface{}) *sql.Row { start := time.Now() defer logSlowQuery(tx.logger, query, start) return tx.Tx.QueryRow(query, args...) } // Query wraps sql.Tx.Query to log slow queries func (tx *loggingTx) Query(query string, args ...interface{}) (*sql.Rows, error) { start := time.Now() defer logSlowQuery(tx.logger, query, start) return tx.Tx.Query(query, args...) } // QueryContext wraps sql.Tx.QueryContext to log slow queries func (tx *loggingTx) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) { start := time.Now() defer logSlowQuery(tx.logger, query, start) return tx.Tx.QueryContext(ctx, query, args...) } // QueryRowContext wraps sql.Tx.QueryRowContext to log slow queries func (tx *loggingTx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { start := time.Now() defer logSlowQuery(tx.logger, query, start) return tx.Tx.QueryRowContext(ctx, query, args...) } // Exec wraps sql.Tx.Exec to log slow queries func (tx *loggingTx) Exec(query string, args ...interface{}) (sql.Result, error) { start := time.Now() defer logSlowQuery(tx.logger, query, start) return tx.Tx.Exec(query, args...) } // ExecContext wraps sql.Tx.ExecContext to log slow queries func (tx *loggingTx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { start := time.Now() defer logSlowQuery(tx.logger, query, start) return tx.Tx.ExecContext(ctx, query, args...) }