forked from trpc-group/trpc-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogger_factory.go
154 lines (134 loc) · 3.74 KB
/
logger_factory.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Tencent is pleased to support the open source community by making tRPC available.
// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
// If you have downloaded a copy of the tRPC source code from Tencent,
// please note that tRPC source code is licensed under the Apache 2.0 License that can be found in the LICENSE file.
package log
import (
"errors"
"fmt"
"sync"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"trpc.group/trpc-go/trpc-go/plugin"
)
func init() {
RegisterWriter(OutputConsole, DefaultConsoleWriterFactory)
RegisterWriter(OutputFile, DefaultFileWriterFactory)
Register(defaultLoggerName, NewZapLog(defaultConfig))
plugin.Register(defaultLoggerName, DefaultLogFactory)
}
const (
pluginType = "log"
defaultLoggerName = "default"
)
var (
// DefaultLogger the default Logger. The initial output is console. When frame start, it is
// over write by configuration.
DefaultLogger Logger
// DefaultLogFactory is the default log loader. Users may replace it with their own
// implementation.
DefaultLogFactory = &Factory{}
mu sync.RWMutex
loggers = make(map[string]Logger)
)
// Register registers Logger. It supports multiple Logger implementation.
func Register(name string, logger Logger) {
mu.Lock()
defer mu.Unlock()
if logger == nil {
panic("log: Register logger is nil")
}
if _, dup := loggers[name]; dup && name != defaultLoggerName {
panic("log: Register called twiced for logger name " + name)
}
loggers[name] = logger
if name == defaultLoggerName {
DefaultLogger = logger
}
}
// GetDefaultLogger gets the default Logger.
// To configure it, set key in configuration file to default.
// The console output is the default value.
func GetDefaultLogger() Logger {
mu.RLock()
l := DefaultLogger
mu.RUnlock()
return l
}
// SetLogger sets the default Logger.
func SetLogger(logger Logger) {
mu.Lock()
DefaultLogger = logger
mu.Unlock()
}
// Get returns the Logger implementation by log name.
// log.Debug use DefaultLogger to print logs. You may also use log.Get("name").Debug.
func Get(name string) Logger {
mu.RLock()
l := loggers[name]
mu.RUnlock()
return l
}
// Sync syncs all registered loggers.
func Sync() {
mu.RLock()
defer mu.RUnlock()
for _, logger := range loggers {
_ = logger.Sync()
}
}
// Decoder decodes the log.
type Decoder struct {
OutputConfig *OutputConfig
Core zapcore.Core
ZapLevel zap.AtomicLevel
}
// Decode decodes writer configuration, copy one.
func (d *Decoder) Decode(cfg interface{}) error {
output, ok := cfg.(**OutputConfig)
if !ok {
return fmt.Errorf("decoder config type:%T invalid, not **OutputConfig", cfg)
}
*output = d.OutputConfig
return nil
}
// Factory is the log plugin factory.
// When server start, the configuration is feed to Factory to generate a log instance.
type Factory struct{}
// Type returns the log plugin type.
func (f *Factory) Type() string {
return pluginType
}
// Setup starts, load and register logs.
func (f *Factory) Setup(name string, dec plugin.Decoder) error {
if dec == nil {
return errors.New("log config decoder empty")
}
cfg, callerSkip, err := f.setupConfig(dec)
if err != nil {
return err
}
logger := NewZapLogWithCallerSkip(cfg, callerSkip)
if logger == nil {
return errors.New("new zap logger fail")
}
Register(name, logger)
return nil
}
func (f *Factory) setupConfig(configDec plugin.Decoder) (Config, int, error) {
cfg := Config{}
if err := configDec.Decode(&cfg); err != nil {
return nil, 0, err
}
if len(cfg) == 0 {
return nil, 0, errors.New("log config output empty")
}
// If caller skip is not configured, use 2 as default.
callerSkip := 2
for i := 0; i < len(cfg); i++ {
if cfg[i].CallerSkip != 0 {
callerSkip = cfg[i].CallerSkip
}
}
return cfg, callerSkip, nil
}