]> Cypherpunks.ru repositories - goredo.git/blob - log.go
Redundant @documentencoding
[goredo.git] / log.go
1 /*
2 goredo -- djb's redo implementation on pure Go
3 Copyright (C) 2020-2023 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  = "NONE"
63
64         flagDebug      = flag.Bool("d", false, fmt.Sprintf("enable debug logging (%s=1)", EnvDebug))
65         flagNoProgress *bool
66         flagLogWait    *bool
67         flagLogLock    *bool
68         flagLogPid     *bool
69         flagLogJS      *bool
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         cmdName := CmdName()
89         if !(cmdName == CmdNameRedo || cmdName == CmdNameRedoIfchange) {
90                 return
91         }
92         flagNoProgress = flag.Bool("no-progress", false,
93                 fmt.Sprintf("no progress printing (%s=1), also implies -no-status", EnvNoProgress))
94         flagLogWait = flag.Bool("log-wait", false,
95                 fmt.Sprintf("enable wait messages logging (%s=1)", EnvLogWait))
96         flagLogLock = flag.Bool("log-lock", false,
97                 fmt.Sprintf("enable lock messages logging (%s=1)", EnvLogLock))
98         flagLogPid = flag.Bool("log-pid", false,
99                 fmt.Sprintf("append PIDs (%s=1)", EnvLogPid))
100         flagLogJS = flag.Bool("log-js", false,
101                 fmt.Sprintf("enable jobserver messages logging (%s=1)", EnvLogJS))
102 }
103
104 func erasedStatus(s, end string) string {
105         if NoProgress || NoColor {
106                 return s + end
107         }
108         return s + KeyEraseLine + end
109 }
110
111 func tracef(level, format string, args ...interface{}) {
112         var p string
113         if MyPid != 0 {
114                 p = fmt.Sprintf("[%d] ", MyPid)
115         }
116         switch level {
117         case CNone:
118                 p = erasedStatus(StderrPrefix+p+fmt.Sprintf(format, args...), "\n")
119                 LogMutex.Lock()
120                 os.Stderr.WriteString(p)
121                 LogMutex.Unlock()
122                 return
123         case CDebug:
124                 if !Debug {
125                         return
126                 }
127                 p += "dbg  "
128         case CWait:
129                 if !(LogWait || Debug) {
130                         return
131                 }
132                 p += "wait "
133         case CRedo:
134                 if NoProgress {
135                         return
136                 }
137                 p += "redo "
138         case CLock:
139                 if !(LogLock || Debug) {
140                         return
141                 }
142                 p += "lock "
143         case CJS:
144                 if !(LogJS || Debug) {
145                         return
146                 }
147                 p += "js   "
148         case CErr:
149                 p += "err  "
150         case CWarn:
151                 p += "warn "
152         }
153         msg := fmt.Sprintf(format, args...)
154         msg = StderrPrefix + colourize(level, p+strings.Repeat(". ", Level)+msg)
155         msg = erasedStatus(msg, "\n")
156         LogMutex.Lock()
157         os.Stderr.WriteString(msg)
158         LogMutex.Unlock()
159 }
160
161 func colourize(colour, s string) string {
162         if NoColor {
163                 return s
164         }
165         return colour + s + CReset
166 }