Files
autoPriority/logging.go
T

154 lines
3.7 KiB
Go

//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()
}