]> Cypherpunks.ru repositories - goredo.git/blob - log.go
Do not use deprecated os.SEEK_*
[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         LogLenPrev int
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 }
87
88 func fillUpToTermSize(s, end string) string {
89         sLen := len(s)
90         if sLen < LogLenPrev {
91                 s += strings.Repeat(" ", LogLenPrev-sLen)
92                 LogLenPrev = sLen
93         } else {
94                 LogLenPrev = sLen
95         }
96         return s + end
97 }
98
99 func trace(level, format string, args ...interface{}) {
100         var p string
101         if MyPid != 0 {
102                 p = fmt.Sprintf("[%d] ", MyPid)
103         }
104         switch level {
105         case CNone:
106                 LogMutex.Lock()
107                 os.Stderr.WriteString(fillUpToTermSize(
108                         StderrPrefix+p+fmt.Sprintf(format, args...), "\n",
109                 ))
110                 LogMutex.Unlock()
111                 return
112         case CDebug:
113                 if !Debug {
114                         return
115                 }
116                 p += "dbg  "
117         case CWait:
118                 if !(LogWait || Debug) {
119                         return
120                 }
121                 p += "wait "
122         case CRedo:
123                 if NoProgress {
124                         return
125                 }
126                 p += "redo "
127         case CLock:
128                 if !(LogLock || Debug) {
129                         return
130                 }
131                 p += "lock "
132         case CJS:
133                 if !(LogJS || Debug) {
134                         return
135                 }
136                 p += "js   "
137         case CErr:
138                 p += "err  "
139         case CWarn:
140                 p += "warn "
141         }
142         msg := fmt.Sprintf(format, args...)
143         msg = StderrPrefix + colourize(level, p+strings.Repeat(". ", Level)+msg)
144         LogMutex.Lock()
145         os.Stderr.WriteString(fillUpToTermSize(msg, "\n"))
146         LogMutex.Unlock()
147 }
148
149 func colourize(colour, s string) string {
150         if NoColor {
151                 return s
152         }
153         return colour + s + CReset
154 }