]> Cypherpunks.ru repositories - goredo.git/blob - log.go
Properly space shorter output messages
[goredo.git] / log.go
1 /*
2 goredo -- redo implementation on pure Go
3 Copyright (C) 2020 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 // Logging facilities
19
20 package main
21
22 import (
23         "flag"
24         "fmt"
25         "os"
26         "strings"
27         "sync"
28 )
29
30 const (
31         EnvLevel   = "REDO_LEVEL"
32         EnvDebug   = "REDO_DEBUG"
33         EnvLogWait = "REDO_LOG_WAIT"
34         EnvLogLock = "REDO_LOG_LOCK"
35         EnvLogPid  = "REDO_LOG_PID"
36         EnvLogJS   = "REDO_LOG_JS"
37         EnvNoColor = "NO_COLOR"
38
39         CReset   = "\033[0m"
40         CBold    = "\033[1m"
41         CBlack   = "\033[30;1m"
42         CRed     = "\033[31;1m"
43         CGreen   = "\033[32;1m"
44         CYellow  = "\033[33;1m"
45         CBlue    = "\033[34;1m"
46         CMagenta = "\033[35;1m"
47         CCyan    = "\033[36;1m"
48         CWhite   = "\033[37;1m"
49
50         CDebug = CYellow
51         CRedo  = CGreen
52         CWait  = CBlue
53         CLock  = CCyan
54         CErr   = CRed
55         CWarn  = CMagenta
56         CJS    = CWhite
57         CNone  = "NONE"
58 )
59
60 var (
61         Level   = 0
62         NoColor bool
63         Debug   bool
64         LogWait bool
65         LogLock bool
66         LogJS   bool
67         MyPid   int
68
69         flagDebug   = flag.Bool("debug", false, fmt.Sprintf("enable debug logging (%s=1)", EnvDebug))
70         flagLogWait = flag.Bool("log-wait", false, fmt.Sprintf("enable wait messages logging (%s=1)", EnvLogWait))
71         flagLogLock = flag.Bool("log-lock", false, fmt.Sprintf("enable lock messages logging (%s=1)", EnvLogLock))
72         flagLogPid  = flag.Bool("log-pid", false, fmt.Sprintf("append PIDs (%s=1)", EnvLogPid))
73         flagLogJS   = flag.Bool("log-js", false, fmt.Sprintf("enable jobserver messages logging (%s=1)", EnvLogJS))
74
75         LogMutex   sync.Mutex
76         LogLenPrev int
77 )
78
79 func fillUpToTermSize(s, end string) string {
80         sLen := len(s)
81         if sLen < LogLenPrev {
82                 s += strings.Repeat(" ", LogLenPrev-sLen)
83                 LogLenPrev = sLen
84         } else {
85                 LogLenPrev = sLen
86         }
87         return s + end
88 }
89
90 func trace(level, format string, args ...interface{}) {
91         var p string
92         if MyPid != 0 {
93                 p = fmt.Sprintf("[%d] ", MyPid)
94         }
95         switch level {
96         case CNone:
97                 LogMutex.Lock()
98                 os.Stderr.WriteString(fillUpToTermSize(
99                         StderrPrefix+p+fmt.Sprintf(format, args...), "\n",
100                 ))
101                 LogMutex.Unlock()
102                 return
103         case CDebug:
104                 if !Debug {
105                         return
106                 }
107                 p += "dbg  "
108         case CWait:
109                 if !(LogWait || Debug) {
110                         return
111                 }
112                 p += "wait "
113         case CRedo:
114                 p += "redo "
115         case CLock:
116                 if !(LogLock || Debug) {
117                         return
118                 }
119                 p += "lock "
120         case CJS:
121                 if !(LogJS || Debug) {
122                         return
123                 }
124                 p += "js   "
125         case CErr:
126                 p += "err  "
127         case CWarn:
128                 p += "warn "
129         }
130         msg := fmt.Sprintf(format, args...)
131         msg = StderrPrefix + colourize(level, p+strings.Repeat(". ", Level)+msg)
132         LogMutex.Lock()
133         os.Stderr.WriteString(fillUpToTermSize(msg, "\n"))
134         LogMutex.Unlock()
135 }
136
137 func colourize(colour, s string) string {
138         if NoColor {
139                 return s
140         }
141         return colour + s + CReset
142 }