mirror of
https://github.com/v2rayA/v2rayA.git
synced 2026-10-28 21:08:07 +08:00
Without --log-file the viewer said "log printed to console, please see log in console", which the Windows service, the launchd job and every "log to console" setup cannot do. The logger now also keeps its last 4 MiB in memory and the viewer reads that tail when there is no file; the lines carry the same timestamp and level prefix as the file adapter's. The log area also gave way to nothing: at 50vh a short window pushed the filters and the export button below the fold with only a scrollbar to hint at them. It now shrinks so the footer stays visible.
72 lines
2.1 KiB
Go
72 lines
2.1 KiB
Go
package log
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/v2rayA/beego/v2/logs"
|
|
)
|
|
|
|
// memoryWriter keeps the most recent log output in memory so the web log
|
|
// viewer has something to show when v2rayA runs without --log-file — the
|
|
// Windows service and every "log to console" setup. It used to answer
|
|
// "log printed to console, please see log in console", which a service user
|
|
// cannot do.
|
|
type memoryWriter struct {
|
|
mu sync.Mutex
|
|
buf []byte
|
|
max int
|
|
base int64 // absolute offset of buf[0] in the stream of everything written
|
|
}
|
|
|
|
const memoryLogCapacity = 4 << 20 // 4 MiB, tens of thousands of lines
|
|
|
|
var memory = &memoryWriter{max: memoryLogCapacity}
|
|
|
|
func init() {
|
|
logs.Register("memory", func() logs.Logger { return memory })
|
|
}
|
|
|
|
func (w *memoryWriter) Init(string) error { return nil }
|
|
func (w *memoryWriter) Destroy() {}
|
|
func (w *memoryWriter) Flush() {}
|
|
func (w *memoryWriter) SetFormatter(logs.LogFormatter) {}
|
|
|
|
// WriteMsg renders the line the way the file adapter does, so the viewer
|
|
// sees the same text whichever source it reads.
|
|
func (w *memoryWriter) WriteMsg(lm *logs.LogMsg) error {
|
|
line := fmt.Sprintf("%s %s\n", lm.When.Format("2006/01/02 15:04:05.000"), lm.OldStyleFormat())
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
w.buf = append(w.buf, line...)
|
|
if len(w.buf) > w.max {
|
|
// Drop whole lines from the front until the buffer fits again.
|
|
cut := len(w.buf) - w.max
|
|
if nl := bytes.IndexByte(w.buf[cut:], '\n'); nl >= 0 {
|
|
cut += nl + 1
|
|
}
|
|
w.base += int64(cut)
|
|
w.buf = append([]byte(nil), w.buf[cut:]...)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ReadMemory returns the buffered log from absolute offset skip, or from the
|
|
// oldest line still held when skip is older than that, together with the
|
|
// offset the returned data starts at.
|
|
func ReadMemory(skip int64) (data []byte, start int64) {
|
|
memory.mu.Lock()
|
|
defer memory.mu.Unlock()
|
|
end := memory.base + int64(len(memory.buf))
|
|
switch {
|
|
case skip < memory.base:
|
|
start = memory.base
|
|
case skip > end:
|
|
start = end
|
|
default:
|
|
start = skip
|
|
}
|
|
return append([]byte(nil), memory.buf[start-memory.base:]...), start
|
|
}
|