-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlog.go
128 lines (112 loc) · 4.39 KB
/
log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright (c) 2016, 2018 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"os"
"path/filepath"
"github.com/decred/slog"
"github.com/jrick/logrotate/rotator"
"github.com/raedahgroup/dcrchainanalysis/v1/analytics"
"github.com/raedahgroup/dcrchainanalysis/v1/rpcutils"
)
//
// ****Decred Chain Analysis Tool Log Levels Constitution.****
// 1. log.Error - Indicates that something went wrong. After logging then system
// exit with an an error MAYBE called or another safer
// implementation can be invoked. Acive by default.
// by default.
// 2. log.Info - Logs common and significant data flows/function calls. Active
// by default.
// 3. log.Debug - Logs fine-grained informational events that are most useful
// when debugging this application. Should only information
// relevant to system maintainers. Not active by default.
// 6. log.Trace - Logs finer-grained informational events than the DEBUG.
// Inputs and outputs of a specific algorithm/process should be
// logged using TRACE. Not active by default.
// 4. log.Critical - Logs Fatal errors and then system exit with an error call
// MUST be invoked. Not active by default.
// 5. log.Warn - Logs about something that is not right but current function/method
// execution can proceed without much effect or disruption. Not
// active by default.
//
// logWriter implements an io.Writer that outputs to both standard output and
// the write-end pipe of an initialized log rotator.
type logWriter struct{}
func (logWriter) Write(p []byte) (n int, err error) {
os.Stdout.Write(p)
logRotator.Write(p)
return len(p), nil
}
// Loggers per subsystem. A single backend logger is created and all subsytem
// loggers created from it will write to the backend. When adding new
// subsystems, add the subsystem logger variable here and to the
// subsystemLoggers map.
//
// Loggers can not be used before the log rotator has been initialized with a
// log file. This must be performed early during application startup by calling
// initLogRotator.
var (
// backendLog is the logging backend used to create all subsystem loggers.
// The backend must not be used before the log rotator has been initialized,
// or data races and/or nil pointer dereferences will occur.
backendLog = slog.NewBackend(logWriter{})
// logRotator is one of the logging outputs. It should be closed on
// application shutdown.
logRotator *rotator.Rotator
analyticsLog = backendLog.Logger("DCA-ANLY")
rpcutilsLog = backendLog.Logger("DCA-RPC")
log = backendLog.Logger("DCA-NFTN")
)
// Initialize package-global logger variables.
func init() {
rpcutils.UseLogger(rpcutilsLog)
analytics.UseLogger(analyticsLog)
}
// subsystemLoggers maps each subsystem identifier to its associated logger.
var subsystemLoggers = map[string]slog.Logger{
"DCA-RPC": rpcutilsLog,
"DCA-NFTN": log,
"DCA-ANLY": analyticsLog,
}
// initLogRotator initializes the logging rotater to write logs to logFile and
// create roll files in the same directory. It must be called before the
// package-global log rotater variables are used.
func initLogRotator(logFile string) {
logDir, _ := filepath.Split(logFile)
err := os.MkdirAll(logDir, 0700)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
os.Exit(1)
}
r, err := rotator.New(logFile, 10*1024, false, 8)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
os.Exit(1)
}
logRotator = r
}
// setLogLevel sets the logging level for provided subsystem. Invalid
// subsystems are ignored. Uninitialized subsystems are dynamically created as
// needed.
func setLogLevel(subsystemID string, logLevel string) {
// Ignore invalid subsystems.
logger, ok := subsystemLoggers[subsystemID]
if !ok {
return
}
// Defaults to info if the log level is invalid.
level, _ := slog.LevelFromString(logLevel)
logger.SetLevel(level)
}
// setLogLevels sets the log level for all subsystem loggers to the passed
// level. It also dynamically creates the subsystem loggers as needed, so it
// can be used to initialize the logging system.
func setLogLevels(logLevel string) {
// Configure all sub-systems with the new logging level. Dynamically
// create loggers as needed.
for subsystemID := range subsystemLoggers {
setLogLevel(subsystemID, logLevel)
}
}