feat: add tray control, priority restoration and session logging
This commit is contained in:
1 parent
4f8f6218ad
commit
4880aa46dc
25 files changed
+3072
-676
No files matched your search
+153
@@ -0,0 +1,153 @@
|
||||
//go:build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func cleanLogText(s string, limit int) string {
|
||||
var out []rune
|
||||
for _, r := range s {
|
||||
if unicode.IsControl(r) || unicode.In(r, unicode.Cf) || r == '|' {
|
||||
r = ' '
|
||||
}
|
||||
if len(out) >= limit {
|
||||
if limit >= 3 {
|
||||
out = append(out[:limit-3], '.', '.', '.')
|
||||
}
|
||||
break
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
func priorityRank(p uint32) int {
|
||||
switch p {
|
||||
case PriorityClassIdle:
|
||||
return 0
|
||||
case PriorityClassBelowNormal:
|
||||
return 1
|
||||
case PriorityClassNormal:
|
||||
return 2
|
||||
case PriorityClassAboveNormal:
|
||||
return 3
|
||||
case PriorityClassHigh:
|
||||
return 4
|
||||
case PriorityClassRealtime:
|
||||
return 5
|
||||
}
|
||||
return -1
|
||||
}
|
||||
func logMemory(b uint64) string {
|
||||
if b >= 1<<30 {
|
||||
return fmt.Sprintf("%.1f ГБ", float64(b)/(1<<30))
|
||||
}
|
||||
if b >= 1<<20 {
|
||||
return fmt.Sprintf("%d МБ", b>>20)
|
||||
}
|
||||
if b >= 1<<10 {
|
||||
return fmt.Sprintf("%d КБ", b>>10)
|
||||
}
|
||||
return fmt.Sprintf("%d Б", b)
|
||||
}
|
||||
func writeLogTable(b *strings.Builder, cells [][]string) {
|
||||
widths := make([]int, len(cells[0]))
|
||||
for _, row := range cells {
|
||||
for i, value := range row {
|
||||
widths[i] = max(widths[i], utf8.RuneCountInString(value))
|
||||
}
|
||||
}
|
||||
var border strings.Builder
|
||||
border.WriteByte('+')
|
||||
for _, width := range widths {
|
||||
border.WriteString(strings.Repeat("-", width+2))
|
||||
border.WriteByte('+')
|
||||
}
|
||||
border.WriteByte('\n')
|
||||
b.WriteString(border.String())
|
||||
for n, row := range cells {
|
||||
b.WriteByte('|')
|
||||
for i, value := range row {
|
||||
fmt.Fprintf(b, " %-*s |", widths[i], value)
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
if n == 0 {
|
||||
b.WriteString(border.String())
|
||||
}
|
||||
}
|
||||
b.WriteString(border.String())
|
||||
}
|
||||
func formatReport(r scanReport, when time.Time) string {
|
||||
if r.Title == "" && len(r.Rows) == 0 && len(r.Errors) == 0 {
|
||||
return ""
|
||||
}
|
||||
var b strings.Builder
|
||||
header := func(title string) {
|
||||
fmt.Fprintf(&b, "[%s] %s", when.Format("02.01.2006 15:04:05"), cleanLogText(title, 200))
|
||||
if r.DryRun {
|
||||
b.WriteString(" [DRY-RUN: ПЛАН, БЕЗ ИЗМЕНЕНИЙ]")
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
if r.Title != "" || len(r.Rows) > 0 {
|
||||
title := r.Title
|
||||
if title == "" {
|
||||
title = "ИЗМЕНЕНИЕ ПРИОРИТЕТОВ"
|
||||
}
|
||||
header(title)
|
||||
if len(r.Rows) > 0 {
|
||||
rows := append([]priorityChange(nil), r.Rows...)
|
||||
sort.SliceStable(rows, func(i, j int) bool {
|
||||
if rows[i].Heavy != rows[j].Heavy {
|
||||
return rows[i].Heavy
|
||||
}
|
||||
return rows[i].PID < rows[j].PID
|
||||
})
|
||||
cells := [][]string{{"Процесс", "PID", "Память", "Повышено", "Понижено"}}
|
||||
for _, row := range rows {
|
||||
columns := []string{cleanLogText(row.Name, 64), strconv.FormatUint(uint64(row.PID), 10), logMemory(row.RSS), "", ""}
|
||||
if row.Blocked {
|
||||
columns[3] = "в блоклисте"
|
||||
} else if row.Unchanged {
|
||||
columns[3] = "уже " + prioName(row.After)
|
||||
} else {
|
||||
change := prioName(row.Before) + " -> " + prioName(row.After)
|
||||
if priorityRank(row.After) > priorityRank(row.Before) {
|
||||
columns[3] = change
|
||||
} else {
|
||||
columns[4] = change
|
||||
}
|
||||
}
|
||||
cells = append(cells, columns)
|
||||
}
|
||||
writeLogTable(&b, cells)
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
if len(r.Errors) > 0 {
|
||||
header("ОШИБКИ")
|
||||
rows := append([]processError(nil), r.Errors...)
|
||||
sort.SliceStable(rows, func(i, j int) bool { return rows[i].PID < rows[j].PID })
|
||||
cells := [][]string{{"Процесс", "PID", "Описание ошибки"}}
|
||||
for _, problem := range rows {
|
||||
name, pid := problem.Name, "-"
|
||||
if name == "" {
|
||||
name = "autoPriority"
|
||||
}
|
||||
if problem.PID != 0 {
|
||||
pid = strconv.FormatUint(uint64(problem.PID), 10)
|
||||
}
|
||||
cells = append(cells, []string{cleanLogText(name, 64), pid, cleanLogText(problem.Description, 1500)})
|
||||
}
|
||||
writeLogTable(&b, cells)
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
Reference in new issue
Block a user