|
|
@@ -8,6 +8,7 @@ import (
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
"sync"
|
|
|
+ "sync/atomic"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
@@ -18,6 +19,30 @@ const (
|
|
|
termMsgJust = 40
|
|
|
)
|
|
|
|
|
|
+// locationTrims are trimmed for display to avoid unwieldy log lines.
|
|
|
+var locationTrims = []string{
|
|
|
+ "github.com/ethereum/go-ethereum/",
|
|
|
+ "github.com/ethereum/ethash/",
|
|
|
+}
|
|
|
+
|
|
|
+// PrintOrigins sets or unsets log location (file:line) printing for terminal
|
|
|
+// format output.
|
|
|
+func PrintOrigins(print bool) {
|
|
|
+ if print {
|
|
|
+ atomic.StoreUint32(&locationEnabled, 1)
|
|
|
+ } else {
|
|
|
+ atomic.StoreUint32(&locationEnabled, 0)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// locationEnabled is an atomic flag controlling whether the terminal formatter
|
|
|
+// should append the log locations too when printing entries.
|
|
|
+var locationEnabled uint32
|
|
|
+
|
|
|
+// locationLength is the maxmimum path length encountered, which all logs are
|
|
|
+// padded to to aid in alignment.
|
|
|
+var locationLength uint32
|
|
|
+
|
|
|
type Format interface {
|
|
|
Format(r *Record) []byte
|
|
|
}
|
|
|
@@ -64,12 +89,33 @@ func TerminalFormat() Format {
|
|
|
|
|
|
b := &bytes.Buffer{}
|
|
|
lvl := strings.ToUpper(r.Lvl.String())
|
|
|
- if color > 0 {
|
|
|
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %s ", color, lvl, r.Time.Format(termTimeFormat), r.Msg)
|
|
|
+ if atomic.LoadUint32(&locationEnabled) != 0 {
|
|
|
+ // Log origin printing was requested, format the location path and line number
|
|
|
+ location := fmt.Sprintf("%+v", r.Call)
|
|
|
+ for _, prefix := range locationTrims {
|
|
|
+ location = strings.TrimPrefix(location, prefix)
|
|
|
+ }
|
|
|
+ // Maintain the maximum location length for fancyer alignment
|
|
|
+ align := int(atomic.LoadUint32(&locationLength))
|
|
|
+ if align < len(location) {
|
|
|
+ align = len(location)
|
|
|
+ atomic.StoreUint32(&locationLength, uint32(align))
|
|
|
+ }
|
|
|
+ padding := strings.Repeat(" ", align-len(location))
|
|
|
+
|
|
|
+ // Assemble and print the log heading
|
|
|
+ if color > 0 {
|
|
|
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s|%s]%s %s ", color, lvl, r.Time.Format(termTimeFormat), location, padding, r.Msg)
|
|
|
+ } else {
|
|
|
+ fmt.Fprintf(b, "[%s] [%s|%s]%s %s ", lvl, r.Time.Format(termTimeFormat), location, padding, r.Msg)
|
|
|
+ }
|
|
|
} else {
|
|
|
- fmt.Fprintf(b, "[%s] [%s] %s ", lvl, r.Time.Format(termTimeFormat), r.Msg)
|
|
|
+ if color > 0 {
|
|
|
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %s ", color, lvl, r.Time.Format(termTimeFormat), r.Msg)
|
|
|
+ } else {
|
|
|
+ fmt.Fprintf(b, "[%s] [%s] %s ", lvl, r.Time.Format(termTimeFormat), r.Msg)
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
// try to justify the log output for short messages
|
|
|
if len(r.Ctx) > 0 && len(r.Msg) < termMsgJust {
|
|
|
b.Write(bytes.Repeat([]byte{' '}, termMsgJust-len(r.Msg)))
|