package main import ( "context" "database/sql" "fmt" "io" "net/http" "os" "time" "screenmark/screenmark/.gen/haystack/haystack/model" . "screenmark/screenmark/.gen/haystack/haystack/table" "github.com/go-chi/chi/v5" . "github.com/go-jet/jet/v2/postgres" "github.com/robert-nix/ansihtml" "github.com/charmbracelet/log" "github.com/google/uuid" "github.com/muesli/termenv" ) type DatabaseWriter struct { dbPool *sql.DB imageId uuid.UUID } func (w *DatabaseWriter) Write(p []byte) (n int, err error) { if len(p) == 0 { return 0, nil } insertLogStmt := Logs. INSERT(Logs.Log, Logs.ImageID). VALUES(string(p), w.imageId) _, err = insertLogStmt.Exec(w.dbPool) if err != nil { return 0, err } else { return len(p), nil } } func (w *DatabaseWriter) GetImageLogs(ctx context.Context, imageId uuid.UUID) ([]string, error) { getImageLogsStmt := Logs. SELECT(Logs.Log). WHERE(Logs.ImageID.EQ(UUID(imageId))) logs := []model.Logs{} err := getImageLogsStmt.QueryContext(ctx, w.dbPool, &logs) if err != nil { return []string{}, err } stringLogs := make([]string, len(logs)) for i, log := range logs { stringLogs[i] = log.Log } return stringLogs, nil } func createLogHandler(logWriter *DatabaseWriter) func(r chi.Router) { return func(r chi.Router) { r.Get("/{imageId}", func(w http.ResponseWriter, r *http.Request) { stringImageId := r.PathValue("imageId") imageId, err := uuid.Parse(stringImageId) if err != nil { w.WriteHeader(http.StatusBadGateway) return } logs, err := logWriter.GetImageLogs(r.Context(), imageId) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } html := "" imageTag := fmt.Sprintf(``, stringImageId) for _, log := range logs { html += fmt.Sprintf("
%s
", string(ansihtml.ConvertToHTML([]byte(log)))+"\n") } css := ` ` fullHtml := fmt.Sprintf("Logs%s%s%s", css, imageTag, html) w.Header().Add("Content-Type", "text/html") w.Write([]byte(fullHtml)) w.WriteHeader(http.StatusOK) }) } } func newDatabaseWriter(dbPool *sql.DB, imageId uuid.UUID) *DatabaseWriter { return &DatabaseWriter{ dbPool: dbPool, imageId: imageId, } } func createDbStdoutWriter(dbPool *sql.DB, imageId uuid.UUID) io.Writer { return io.MultiWriter(os.Stdout, newDatabaseWriter(dbPool, imageId)) } func createLogger(prefix string, writer io.Writer) *log.Logger { logger := log.NewWithOptions(writer, log.Options{ ReportTimestamp: true, TimeFormat: time.Kitchen, Prefix: prefix, Formatter: log.TextFormatter, }) logger.SetColorProfile(termenv.TrueColor) logger.SetLevel(log.DebugLevel) return logger }