log search implementation
This commit is contained in:
parent
01c285de1b
commit
1397274967
67
log/log.go
67
log/log.go
|
@ -15,6 +15,7 @@ type (
|
||||||
|
|
||||||
Log struct {
|
Log struct {
|
||||||
ID string `json:"id" db:"id"`
|
ID string `json:"id" db:"id"`
|
||||||
|
Level LogLevel `json:"level" db:"level"`
|
||||||
Type string `json:"type" db:"type"`
|
Type string `json:"type" db:"type"`
|
||||||
Content string `json:"content" db:"content"`
|
Content string `json:"content" db:"content"`
|
||||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||||
|
@ -35,6 +36,8 @@ const (
|
||||||
LEVEL_WARN LogLevel = 1
|
LEVEL_WARN LogLevel = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DEFAULT_LOG_PAGE_LENGTH = 25
|
||||||
|
|
||||||
func (self *Logger) Info(logType string, format string, args ...any) {
|
func (self *Logger) Info(logType string, format string, args ...any) {
|
||||||
logString := fmt.Sprintf(format, args...)
|
logString := fmt.Sprintf(format, args...)
|
||||||
fmt.Printf("[%s] INFO: %s", logType, logString)
|
fmt.Printf("[%s] INFO: %s", logType, logString)
|
||||||
|
@ -58,21 +61,61 @@ func (self *Logger) Fatal(logType string, format string, args ...any) {
|
||||||
// we won't need to push fatal logs to DB, as these usually precede a panic or crash
|
// we won't need to push fatal logs to DB, as these usually precede a panic or crash
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Logger) Fetch(id string) *Log {
|
func (self *Logger) Fetch(id string) (*Log, error) {
|
||||||
// TODO: log fetch
|
log := Log{}
|
||||||
return nil
|
err := self.DB.Get(&log, "SELECT * FROM auditlog WHERE id=$1", id)
|
||||||
|
return &log, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Logger) Search(typeFilters []string, content string, offset int, limit int) []Log {
|
func (self *Logger) Search(levelFilters []LogLevel, typeFilters []string, content string, offset int, limit int) ([]*Log, error) {
|
||||||
// TODO: log search
|
logs := []*Log{}
|
||||||
return []Log{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Logger) Delete(id string) error {
|
params := []any{ limit, offset }
|
||||||
// TODO: log deletion
|
conditions := ""
|
||||||
// consider: logging the deletion of logs?
|
|
||||||
// or just not deleting logs at all
|
if len(content) > 0 {
|
||||||
return nil
|
content = "%" + content + "%"
|
||||||
|
conditions += " WHERE content LIKE $3"
|
||||||
|
params = append(params, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(levelFilters) > 0 {
|
||||||
|
conditions += " AND level IN ("
|
||||||
|
for i := range levelFilters {
|
||||||
|
conditions += fmt.Sprintf("$%d", len(params) + 1)
|
||||||
|
if i < len(levelFilters) - 1 {
|
||||||
|
conditions += ","
|
||||||
|
}
|
||||||
|
params = append(params, levelFilters[i])
|
||||||
|
}
|
||||||
|
conditions += ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(typeFilters) > 0 {
|
||||||
|
conditions += " AND type IN ("
|
||||||
|
for i := range typeFilters {
|
||||||
|
conditions += fmt.Sprintf("$%d", len(params) + 1)
|
||||||
|
if i < len(typeFilters) - 1 {
|
||||||
|
conditions += ","
|
||||||
|
}
|
||||||
|
params = append(params, typeFilters[i])
|
||||||
|
}
|
||||||
|
conditions += ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf(
|
||||||
|
"SELECT * FROM auditlog%s ORDER BY created_at DESC LIMIT $1 OFFSET $2",
|
||||||
|
conditions,
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: remove after testing
|
||||||
|
fmt.Println(query)
|
||||||
|
|
||||||
|
err := self.DB.Select(&logs, query, params...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createLog(db *sqlx.DB, logLevel LogLevel, logType string, content string) error {
|
func createLog(db *sqlx.DB, logLevel LogLevel, logType string, content string) error {
|
||||||
|
|
17
main.go
17
main.go
|
@ -3,7 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
stdLog "log"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -20,6 +20,7 @@ import (
|
||||||
"arimelody-web/model"
|
"arimelody-web/model"
|
||||||
"arimelody-web/templates"
|
"arimelody-web/templates"
|
||||||
"arimelody-web/view"
|
"arimelody-web/view"
|
||||||
|
"arimelody-web/log"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
@ -342,6 +343,18 @@ func main() {
|
||||||
fmt.Printf("Account \"%s\" deleted successfully.\n", account.Username)
|
fmt.Printf("Account \"%s\" deleted successfully.\n", account.Username)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case "testLogSearch":
|
||||||
|
// TODO: rename to "logs"; add parameters
|
||||||
|
logger := log.Logger { DB: app.DB }
|
||||||
|
logs, err := logger.Search([]log.LogLevel{ log.LEVEL_INFO, log.LEVEL_WARN }, []string{ log.TYPE_ACCOUNT, log.TYPE_MUSIC }, "ari", 0, 100)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "FATAL: Failed to fetch logs: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
for _, log := range(logs) {
|
||||||
|
fmt.Printf("[%s] [%s] [%d] [%s] %s\n", log.CreatedAt.Format(time.UnixDate), log.ID, log.Level, log.Type, log.Content)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// command help
|
// command help
|
||||||
|
@ -401,7 +414,7 @@ func main() {
|
||||||
// start the web server!
|
// start the web server!
|
||||||
mux := createServeMux(&app)
|
mux := createServeMux(&app)
|
||||||
fmt.Printf("Now serving at http://%s:%d\n", app.Config.Host, app.Config.Port)
|
fmt.Printf("Now serving at http://%s:%d\n", app.Config.Host, app.Config.Port)
|
||||||
log.Fatal(
|
stdLog.Fatal(
|
||||||
http.ListenAndServe(fmt.Sprintf("%s:%d", app.Config.Host, app.Config.Port),
|
http.ListenAndServe(fmt.Sprintf("%s:%d", app.Config.Host, app.Config.Port),
|
||||||
HTTPLog(DefaultHeaders(mux)),
|
HTTPLog(DefaultHeaders(mux)),
|
||||||
))
|
))
|
||||||
|
|
Loading…
Reference in a new issue