- Sidebar : retrait des liens files, logs, services (non implémentés) - Migration 001 : suppression des inserts files/logs/services - Migration 002 : DELETE des modules inexistants en DB existante - logbuffer : ring buffer mémoire branché sur log.SetOutput - GET /api/settings/logs : retourne les 300 dernières lignes de log - Settings : onglet Logs avec auto-refresh (5s/10s/30s/60s/désactivé, défaut 10s) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
53 lines
1.2 KiB
Go
53 lines
1.2 KiB
Go
// Package logbuffer maintient un tampon circulaire en mémoire des lignes de log.
|
|
// Il implémente io.Writer pour être branché sur log.SetOutput via io.MultiWriter.
|
|
package logbuffer
|
|
|
|
import (
|
|
"bytes"
|
|
"sync"
|
|
)
|
|
|
|
const maxLines = 500
|
|
|
|
// Buffer est un tampon circulaire thread-safe de lignes de log.
|
|
type Buffer struct {
|
|
mu sync.RWMutex
|
|
lines []string
|
|
}
|
|
|
|
// Write implémente io.Writer. Découpe p en lignes et les ajoute au tampon.
|
|
func (b *Buffer) Write(p []byte) (int, error) {
|
|
b.mu.Lock()
|
|
defer b.mu.Unlock()
|
|
|
|
for _, line := range bytes.Split(p, []byte("\n")) {
|
|
s := string(bytes.TrimRight(line, "\r"))
|
|
if s == "" {
|
|
continue
|
|
}
|
|
b.lines = append(b.lines, s)
|
|
if len(b.lines) > maxLines {
|
|
b.lines = b.lines[len(b.lines)-maxLines:]
|
|
}
|
|
}
|
|
return len(p), nil
|
|
}
|
|
|
|
// Lines retourne les n dernières lignes (ou toutes si n <= 0 ou n > taille).
|
|
func (b *Buffer) Lines(n int) []string {
|
|
b.mu.RLock()
|
|
defer b.mu.RUnlock()
|
|
|
|
total := len(b.lines)
|
|
if n <= 0 || n >= total {
|
|
result := make([]string, total)
|
|
copy(result, b.lines)
|
|
return result
|
|
}
|
|
result := make([]string, n)
|
|
copy(result, b.lines[total-n:])
|
|
return result
|
|
}
|
|
|
|
// Global est l'instance partagée utilisée par main.go et les handlers.
|
|
var Global = &Buffer{}
|