Make log viewer responsive on large files
This commit is contained in:
parent
0e74f28379
commit
9237bae4ff
60
main.go
60
main.go
|
|
@ -385,36 +385,70 @@ func (s *appState) openLogViewer(title, path string, live bool) {
|
||||||
d.SetOnClosed(func() { close(stop) })
|
d.SetOnClosed(func() { close(stop) })
|
||||||
d.Show()
|
d.Show()
|
||||||
|
|
||||||
|
readTail := func() string {
|
||||||
|
const maxBytes int64 = 200 * 1024
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("Failed to read log: %v", err)
|
||||||
|
}
|
||||||
|
size := info.Size()
|
||||||
|
start := int64(0)
|
||||||
|
if size > maxBytes {
|
||||||
|
start = size - maxBytes
|
||||||
|
}
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("Failed to read log: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if start > 0 {
|
||||||
|
if _, err := f.Seek(start, io.SeekStart); err != nil {
|
||||||
|
return fmt.Sprintf("Failed to read log: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data, err := io.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("Failed to read log: %v", err)
|
||||||
|
}
|
||||||
|
if start > 0 {
|
||||||
|
return fmt.Sprintf("... showing last %d KB ...\n%s", maxBytes/1024, string(data))
|
||||||
|
}
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
// Read file asynchronously to avoid blocking UI
|
// Read file asynchronously to avoid blocking UI
|
||||||
go func() {
|
go func() {
|
||||||
data, err := os.ReadFile(path)
|
content := readTail()
|
||||||
if err != nil {
|
|
||||||
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
|
|
||||||
text.SetText(fmt.Sprintf("Failed to read log: %v", err))
|
|
||||||
}, false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
|
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
|
||||||
text.SetText(string(data))
|
text.SetText(content)
|
||||||
// Auto-scroll to bottom
|
// Auto-scroll to bottom
|
||||||
scroll.ScrollToBottom()
|
scroll.ScrollToBottom()
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
// Start live updates if requested
|
// Start live updates if requested
|
||||||
if live {
|
if live {
|
||||||
ticker := time.NewTicker(1 * time.Second)
|
ticker := time.NewTicker(2 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
var lastSize int64 = -1
|
||||||
|
var lastText string
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-stop:
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
b, err := os.ReadFile(path)
|
info, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b = []byte(fmt.Sprintf("failed to read log: %v", err))
|
continue
|
||||||
}
|
}
|
||||||
content := string(b)
|
if info.Size() == lastSize {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lastSize = info.Size()
|
||||||
|
content := readTail()
|
||||||
|
if content == lastText {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lastText = content
|
||||||
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
|
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
|
||||||
text.SetText(content)
|
text.SetText(content)
|
||||||
}, false)
|
}, false)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user