]> Cypherpunks.ru repositories - goredo.git/blob - log.go
Download link for 1.5.0 release
[goredo.git] / log.go
1 /*
2 goredo -- djb's redo implementation on pure Go
3 Copyright (C) 2020-2021 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         EnvNoProgress = "REDO_NO_PROGRESS"
36         EnvDebug      = "REDO_DEBUG"
37         EnvLogWait    = "REDO_LOG_WAIT"
38         EnvLogLock    = "REDO_LOG_LOCK"
39         EnvLogPid     = "REDO_LOG_PID"
40         EnvLogJS      = "REDO_LOG_JS"
41         EnvNoColor    = "NO_COLOR"
42 )
43
44 var (
45         Level      = 0
46         NoColor    bool
47         NoProgress bool
48         Debug      bool
49         LogWait    bool
50         LogLock    bool
51         LogJS      bool
52         MyPid      int
53
54         CDebug string
55         CRedo  string
56         CWait  string
57         CLock  string
58         CErr   string
59         CWarn  string
60         CJS    string
61         CReset string
62         CNone  string = "NONE"
63
64         flagNoProgress = flag.Bool("no-progress", false, fmt.Sprintf("no progress printing (%s=1), also implies -no-status", EnvNoProgress))
65         flagDebug      = flag.Bool("d", false, fmt.Sprintf("enable debug logging (%s=1)", EnvDebug))
66         flagLogWait    = flag.Bool("log-wait", false, fmt.Sprintf("enable wait messages logging (%s=1)", EnvLogWait))
67         flagLogLock    = flag.Bool("log-lock", false, fmt.Sprintf("enable lock messages logging (%s=1)", EnvLogLock))
68         flagLogPid     = flag.Bool("log-pid", false, fmt.Sprintf("append PIDs (%s=1)", EnvLogPid))
69         flagLogJS      = flag.Bool("log-js", false, fmt.Sprintf("enable jobserver messages logging (%s=1)", EnvLogJS))
70
71         LogMutex     sync.Mutex
72         KeyEraseLine string
73 )
74
75 func init() {
76         var b bytes.Buffer
77         t := term.NewTerminal(&b, "")
78         CDebug = string(t.Escape.Yellow)
79         CRedo = string(t.Escape.Green)
80         CWait = string(t.Escape.Blue)
81         CLock = string(t.Escape.Cyan)
82         CErr = string(t.Escape.Red)
83         CWarn = string(t.Escape.Magenta)
84         CJS = string(t.Escape.White)
85         CReset = string(t.Escape.Reset)
86         KeyEraseLine = fmt.Sprintf("%s[K", CReset[0:1])
87 }
88
89 func erasedStatus(s, end string) string {
90         if NoProgress {
91                 return s + end
92         }
93         return s + KeyEraseLine + 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                 p = erasedStatus(StderrPrefix+p+fmt.Sprintf(format, args...), "\n")
104                 LogMutex.Lock()
105                 os.Stderr.WriteString(p)
106                 LogMutex.Unlock()
107                 return
108         case CDebug:
109                 if !Debug {
110                         return
111                 }
112                 p += "dbg  "
113         case CWait:
114                 if !(LogWait || Debug) {
115                         return
116                 }
117                 p += "wait "
118         case CRedo:
119                 if NoProgress {
120                         return
121                 }
122                 p += "redo "
123         case CLock:
124                 if !(LogLock || Debug) {
125                         return
126                 }
127                 p += "lock "
128         case CJS:
129                 if !(LogJS || Debug) {
130                         return
131                 }
132                 p += "js   "
133         case CErr:
134                 p += "err  "
135         case CWarn:
136                 p += "warn "
137         }
138         msg := fmt.Sprintf(format, args...)
139         msg = StderrPrefix + colourize(level, p+strings.Repeat(". ", Level)+msg)
140         msg = erasedStatus(msg, "\n")
141         LogMutex.Lock()
142         os.Stderr.WriteString(msg)
143         LogMutex.Unlock()
144 }
145
146 func colourize(colour, s string) string {
147         if NoColor {
148                 return s
149         }
150         return colour + s + CReset
151 }