2026-02-03 22:33:55 -07:00

78 lines
1.8 KiB
Go

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)
}
}