-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoutput.go
132 lines (119 loc) · 3.09 KB
/
output.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"fmt"
"log"
"os"
"sync"
)
/* Message defines an output message for OutputMonitor */
type Message struct {
Server string
Data string
Stdout bool
}
/* OutputMonitor prints out stats and server data to screen */
func OutputMonitor(total int, padding int, srv *sync.WaitGroup) (chan Message, chan int) {
var cntActive int
var cntComplete int
var Template string
var OutDev *os.File
message := make(chan Message)
active := make(chan int)
type OutputStats map[string]bool
StdoutStats := make(OutputStats)
StderrStats := make(OutputStats)
PrintToTerminal := IsTerminal(os.Stdout)
/* initialize output template strings */
OutTemplate := "%*s%s \033[01;32m->\033[0m %s"
ErrTemplate := "%*s%s \033[01;31m=>\033[0m %s"
/* disable colored output in case output is redirected */
if !PrintToTerminal {
PrintToTerminal = false
OutTemplate = "%*s%s -> %s"
}
if !IsTerminal(os.Stderr) {
ErrTemplate = "%*s%s => %s"
}
/* ClearProgress defines a local function to clear command progress */
ClearProgress := func() {
if _, err := fmt.Fprintf(os.Stderr, "\r%*s\r", 41, " "); err != nil {
log.Println(err)
}
}
PrintProgress := func() {
if _, err := fmt.Fprintf(os.Stderr, "[%d/%d] %.2f%% complete, %d active",
cntComplete,
total,
float64(cntComplete)*float64(100)/float64(total),
cntActive,
); err != nil {
log.Println(err)
}
}
/* statistics variables */
var StdoutServersCount int
var StderrServersCount int
var StdoutLinesCount int
var StderrLinesCount int
OutputCallback := func(message chan Message, active chan int, srv *sync.WaitGroup) {
defer srv.Done()
for cntComplete != total {
select {
case msg := <-message:
if msg.Stdout {
Template = OutTemplate
if _, ok := StdoutStats[msg.Server]; !ok {
StdoutStats[msg.Server] = true
StdoutServersCount++
}
StdoutLinesCount++
OutDev = os.Stdout
} else {
Template = ErrTemplate
if _, ok := StderrStats[msg.Server]; !ok {
StderrStats[msg.Server] = true
StderrServersCount++
}
StderrLinesCount++
OutDev = os.Stderr
}
if PrintToTerminal {
/* clear progress */
ClearProgress()
}
if _, err := fmt.Fprintf(OutDev, Template, padding-len(msg.Server)+1, " ", msg.Server, msg.Data); err != nil {
log.Println(err)
}
if PrintToTerminal {
/* print progress */
PrintProgress()
}
case cnt := <-active:
/* update active count and exit if cntActive is zero */
if cnt < 0 {
cntComplete = cntComplete - cnt
}
cntActive = cntActive + cnt
ClearProgress()
PrintProgress()
}
}
/* calculate and print end stats */
ClearProgress()
_, err := fmt.Fprintf(os.Stderr,
"\n Done. Processed: %d / Output: %d (%d) / \033[01;32m->\033[0m %d (%d) / \033[01;31m=>\033[0m %d (%d)\n",
total,
StdoutServersCount+StderrServersCount,
StdoutLinesCount+StderrLinesCount,
StdoutServersCount,
StdoutLinesCount,
StderrServersCount,
StderrLinesCount,
)
if err != nil {
log.Println(err)
}
}
go OutputCallback(message, active, srv)
return message, active
}