package loggers import ( "fmt" "github.com/haydenhargreaves/Potion/internal/infrastructure/logging" "github.com/jmoiron/sqlx" ) type DatabaseLogger struct { db *sqlx.DB table string filter logging.LogLevel } var _ logging.Logger = (*DatabaseLogger)(nil) func NewDatabaseLogger(conn *sqlx.DB, table string, filter logging.LogLevel) (logging.Logger, error) { if conn == nil { return &DatabaseLogger{}, fmt.Errorf("Connection is nil, something is very wrong.") } // Ensure the DB is open if err := conn.Ping(); err != nil { return &DatabaseLogger{}, err } // Ensure the table exists exists, err := tableExists(conn, table) if err != nil { return &DatabaseLogger{}, err } if !exists { return &DatabaseLogger{}, fmt.Errorf("Database table '%s' does not exist on provided connection.", table) } logger := &DatabaseLogger{ db: conn, table: table, filter: filter, } return logger, nil } // tableExists queries a database connection and returns whether the table name provided // exists on the table. func tableExists(conn *sqlx.DB, tableName string) (bool, error) { var exists bool err := conn.QueryRow(` SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = $1 )`, tableName).Scan(&exists) return exists, err } // Log implements the interface. func (l *DatabaseLogger) Log(level logging.LogLevel, format string, v ...any) { // level is too low, do not log if !l.filter.MatchFilter(level) { return } message := fmt.Sprintf(format, v...) query := "INSERT INTO logs (level, message) VALUES ($1, $2);" // Ignoring result and error, cuz what the hell would we do with them lol _, err := l.db.Exec(query, level, message) // TODO: Remove if err != nil { println(err) } }