Simplify admin publishing pipeline
This commit is contained in:
parent
13e7e4026d
commit
9186801c7f
37 changed files with 750 additions and 3367 deletions
139
backend/internal/admin/logging.go
Normal file
139
backend/internal/admin/logging.go
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
package admin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type rotatingLogWriter struct {
|
||||
path string
|
||||
maxBytes int64
|
||||
maxBackups int
|
||||
file *os.File
|
||||
size int64
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func ConfigureLogging(cfg Config) (io.Closer, error) {
|
||||
if cfg.LogFile == "" {
|
||||
return nil, nil
|
||||
}
|
||||
writer, err := newRotatingLogWriter(cfg.LogFile, cfg.LogMaxBytes, cfg.LogMaxBackups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
multi := io.MultiWriter(os.Stdout, writer)
|
||||
log.SetOutput(multi)
|
||||
log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.LUTC)
|
||||
return writer, nil
|
||||
}
|
||||
|
||||
func newRotatingLogWriter(path string, maxBytes int64, maxBackups int) (*rotatingLogWriter, error) {
|
||||
if maxBytes <= 0 {
|
||||
maxBytes = 10 * 1024 * 1024
|
||||
}
|
||||
if maxBackups <= 0 {
|
||||
maxBackups = 5
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
return nil, fmt.Errorf("create log dir: %w", err)
|
||||
}
|
||||
file, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open log file: %w", err)
|
||||
}
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
file.Close()
|
||||
return nil, fmt.Errorf("stat log file: %w", err)
|
||||
}
|
||||
return &rotatingLogWriter{
|
||||
path: path,
|
||||
maxBytes: maxBytes,
|
||||
maxBackups: maxBackups,
|
||||
file: file,
|
||||
size: info.Size(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (w *rotatingLogWriter) Write(p []byte) (int, error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
if w.size+int64(len(p)) > w.maxBytes {
|
||||
if err := w.rotateLocked(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
n, err := w.file.Write(p)
|
||||
w.size += int64(n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *rotatingLogWriter) Close() error {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
if w.file == nil {
|
||||
return nil
|
||||
}
|
||||
err := w.file.Close()
|
||||
w.file = nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *rotatingLogWriter) rotateLocked() error {
|
||||
if w.file != nil {
|
||||
if err := w.file.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
stamp := time.Now().UTC().Format("20060102T150405")
|
||||
rotated := fmt.Sprintf("%s.%s", w.path, stamp)
|
||||
if err := os.Rename(w.path, rotated); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("rotate log: %w", err)
|
||||
}
|
||||
if err := w.pruneLocked(); err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.OpenFile(w.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open rotated log file: %w", err)
|
||||
}
|
||||
w.file = file
|
||||
w.size = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *rotatingLogWriter) pruneLocked() error {
|
||||
pattern := w.path + ".*"
|
||||
matches, err := filepath.Glob(pattern)
|
||||
if err != nil {
|
||||
return fmt.Errorf("list rotated logs: %w", err)
|
||||
}
|
||||
if len(matches) <= w.maxBackups {
|
||||
return nil
|
||||
}
|
||||
sortStrings(matches)
|
||||
for _, path := range matches[:len(matches)-w.maxBackups] {
|
||||
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("remove old log %s: %w", path, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortStrings(values []string) {
|
||||
for i := 1; i < len(values); i++ {
|
||||
value := values[i]
|
||||
j := i - 1
|
||||
for ; j >= 0 && values[j] > value; j-- {
|
||||
values[j+1] = values[j]
|
||||
}
|
||||
values[j+1] = value
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue