]> Cypherpunks.ru repositories - goredo.git/blob - log.go
Symlinks -cleanup friendliness
[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         "bytes"
24         "flag"
25         "fmt"
26         "os"
27         "strings"
28         "sync"
29
30         "golang.org/x/term"
31 )
32
33 const (
34         EnvLevel   = "REDO_LEVEL"
35         EnvDebug   = "REDO_DEBUG"
36         EnvLogWait = "REDO_LOG_WAIT"
37         EnvLogLock = "REDO_LOG_LOCK"
38         EnvLogPid  = "REDO_LOG_PID"
39         EnvLogJS   = "REDO_LOG_JS"
40         EnvNoColor = "NO_COLOR"
41 )
42
43 var (
44         Level   = 0
45         NoColor bool
46         Debug   bool
47         LogWait bool
48         LogLock bool
49         LogJS   bool
50         MyPid   int
51
52         CDebug string
53         CRedo  string
54         CWait  string
55         CLock  string
56         CErr   string
57         CWarn  string
58         CJS    string
59         CReset string
60         CNone  string = "NONE"
61
62         flagDebug   = flag.Bool("debug", false, fmt.Sprintf("enable debug logging (%s=1)", EnvDebug))
63         flagLogWait = flag.Bool("log-wait", false, fmt.Sprintf("enable wait messages logging (%s=1)", EnvLogWait))
64         flagLogLock = flag.Bool("log-lock", false, fmt.Sprintf("enable lock messages logging (%s=1)", EnvLogLock))
65         flagLogPid  = flag.Bool("log-pid", false, fmt.Sprintf("append PIDs (%s=1)", EnvLogPid))
66         flagLogJS   = flag.Bool("log-js", false, fmt.Sprintf("enable jobserver messages logging (%s=1)", EnvLogJS))
67
68         LogMutex   sync.Mutex
69         LogLenPrev int
70 )
71
72 func init() {
73         var b bytes.Buffer
74         t := term.NewTerminal(&b, "")
75         CDebug = string(t.Escape.Yellow)
76         CRedo = string(t.Escape.Green)
77         CWait = string(t.Escape.Blue)
78         CLock = string(t.Escape.Cyan)
79         CErr = string(t.Escape.Red)
80         CWarn = string(t.Escape.Magenta)
81         CJS = string(t.Escape.White)
82         CReset = string(t.Escape.Reset)
83 }
84
85 func fillUpToTermSize(s, end string) string {
86         sLen := len(s)
87         if sLen < LogLenPrev {
88                 s += strings.Repeat(" ", LogLenPrev-sLen)
89                 LogLenPrev = sLen
90         } else {
91                 LogLenPrev = sLen
92         }
93         return s + end
94 }
95
96 func trace(level, format string, args ...interface{}) {
97         var p string
98         if MyPid != 0 {
99                 p = fmt.Sprintf("[%d] ", MyPid)
100         }
101         switch level {
102         case CNone:
103                 LogMutex.Lock()
104                 os.Stderr.WriteString(fillUpToTermSize(
105                         StderrPrefix+p+fmt.Sprintf(format, args...), "\n",
106                 ))
107                 LogMutex.Unlock()
108                 return
109         case CDebug:
110                 if !Debug {
111                         return
112                 }
113                 p += "dbg  "
114         case CWait:
115                 if !(LogWait || Debug) {
116                         return
117                 }
118                 p += "wait "
119         case CRedo:
120                 p += "redo "
121         case CLock:
122                 if !(LogLock || Debug) {
123                         return
124                 }
125                 p += "lock "
126         case CJS:
127                 if !(LogJS || Debug) {
128                         return
129                 }
130                 p += "js   "
131         case CErr:
132                 p += "err  "
133         case CWarn:
134                 p += "warn "
135         }
136         msg := fmt.Sprintf(format, args...)
137         msg = StderrPrefix + colourize(level, p+strings.Repeat(". ", Level)+msg)
138         LogMutex.Lock()
139         os.Stderr.WriteString(fillUpToTermSize(msg, "\n"))
140         LogMutex.Unlock()
141 }
142
143 func colourize(colour, s string) string {
144         if NoColor {
145                 return s
146         }
147         return colour + s + CReset
148 }