mirror of
https://github.com/go-kratos/kratos.git
synced 2025-03-17 21:07:54 +02:00
feat(log): add global logger appliance, as process level default logger (#1761)
* add global logger appliance, as process level default logger * replace DefaultLogger as global logger
This commit is contained in:
parent
d082075676
commit
0ed2e0f379
2
app.go
2
app.go
@ -39,7 +39,7 @@ type App struct {
|
||||
func New(opts ...Option) *App {
|
||||
o := options{
|
||||
ctx: context.Background(),
|
||||
logger: log.NewHelper(log.DefaultLogger),
|
||||
logger: log.NewHelper(log.GetLogger()),
|
||||
sigs: []os.Signal{syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT},
|
||||
registrarTimeout: 10 * time.Second,
|
||||
stopTimeout: 10 * time.Second,
|
||||
|
@ -49,7 +49,7 @@ type config struct {
|
||||
// New new a config with options.
|
||||
func New(opts ...Option) Config {
|
||||
o := options{
|
||||
logger: log.DefaultLogger,
|
||||
logger: log.GetLogger(),
|
||||
decoder: defaultDecoder,
|
||||
resolver: defaultResolver,
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ func TestConfig(t *testing.T) {
|
||||
WithSource(newTestJSONSource(_testJSON)),
|
||||
WithDecoder(defaultDecoder),
|
||||
WithResolver(defaultResolver),
|
||||
WithLogger(log.DefaultLogger),
|
||||
WithLogger(log.GetLogger()),
|
||||
)
|
||||
err = c.Close()
|
||||
assert.Nil(t, err)
|
||||
@ -133,7 +133,7 @@ func TestConfig(t *testing.T) {
|
||||
sources: []Source{jSource},
|
||||
decoder: defaultDecoder,
|
||||
resolver: defaultResolver,
|
||||
logger: log.DefaultLogger,
|
||||
logger: log.GetLogger(),
|
||||
}
|
||||
cf := &config{}
|
||||
cf.opts = opts
|
||||
|
@ -99,7 +99,7 @@ func WithLogger(logger log.Logger) Option {
|
||||
|
||||
func NewSource(opts ...Option) config.Source {
|
||||
op := options{
|
||||
logger: log.DefaultLogger,
|
||||
logger: log.GetLogger(),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&op)
|
||||
@ -167,7 +167,7 @@ func resolve(key string, value interface{}, target map[string]interface{}) {
|
||||
// current exists, then check existing value type, if it's not map
|
||||
// that means duplicate keys, and at least one is not map instance.
|
||||
if cursor, ok = v.(map[string]interface{}); !ok {
|
||||
_ = log.DefaultLogger.Log(log.LevelWarn,
|
||||
_ = log.GetLogger().Log(log.LevelWarn,
|
||||
"msg",
|
||||
fmt.Sprintf("duplicate key: %v\n", strings.Join(keys[:i+1], ".")),
|
||||
)
|
||||
|
@ -63,7 +63,7 @@ func (c *customChangeListener) OnNewestChange(changeEvent *storage.FullChangeEve
|
||||
|
||||
func newWatcher(a *apollo, logger log.Logger) (config.Watcher, error) {
|
||||
if logger == nil {
|
||||
logger = log.DefaultLogger
|
||||
logger = log.GetLogger()
|
||||
}
|
||||
|
||||
changeCh := make(chan []*config.KeyValue)
|
||||
|
126
log/global.go
Normal file
126
log/global.go
Normal file
@ -0,0 +1,126 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// globalLogger is designed as a global logger in current process.
|
||||
var (
|
||||
global = &loggerAppliance{}
|
||||
)
|
||||
|
||||
type loggerAppliance struct {
|
||||
lock sync.Mutex
|
||||
logger Logger
|
||||
helper *Helper
|
||||
}
|
||||
|
||||
func init() {
|
||||
global.SetLogger(DefaultLogger)
|
||||
}
|
||||
|
||||
func (a *loggerAppliance) SetLogger(in Logger) {
|
||||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
a.logger = in
|
||||
a.helper = NewHelper(a.logger)
|
||||
}
|
||||
|
||||
func (a *loggerAppliance) GetLogger() Logger {
|
||||
return a.logger
|
||||
}
|
||||
|
||||
// SetLogger should be called before any other log call.
|
||||
// And it is NOT THREAD SAFE.
|
||||
func SetLogger(logger Logger) {
|
||||
global.SetLogger(logger)
|
||||
}
|
||||
|
||||
func GetLogger() Logger {
|
||||
return global.GetLogger()
|
||||
}
|
||||
|
||||
// Log Print log by level and keyvals.
|
||||
func Log(level Level, keyvals ...interface{}) {
|
||||
_ = global.logger.Log(level, keyvals...)
|
||||
}
|
||||
|
||||
// Debug logs a message at debug level.
|
||||
func Debug(a ...interface{}) {
|
||||
global.helper.Log(LevelDebug, global.helper.msgKey, fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Debugf logs a message at debug level.
|
||||
func Debugf(format string, a ...interface{}) {
|
||||
global.helper.Log(LevelDebug, global.helper.msgKey, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Debugw logs a message at debug level.
|
||||
func Debugw(keyvals ...interface{}) {
|
||||
global.helper.Log(LevelDebug, keyvals...)
|
||||
}
|
||||
|
||||
// Info logs a message at info level.
|
||||
func Info(a ...interface{}) {
|
||||
global.helper.Log(LevelInfo, global.helper.msgKey, fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Infof logs a message at info level.
|
||||
func Infof(format string, a ...interface{}) {
|
||||
global.helper.Log(LevelInfo, global.helper.msgKey, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Infow logs a message at info level.
|
||||
func Infow(keyvals ...interface{}) {
|
||||
global.helper.Log(LevelInfo, keyvals...)
|
||||
}
|
||||
|
||||
// Warn logs a message at warn level.
|
||||
func Warn(a ...interface{}) {
|
||||
global.helper.Log(LevelWarn, global.helper.msgKey, fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Warnf logs a message at warnf level.
|
||||
func Warnf(format string, a ...interface{}) {
|
||||
global.helper.Log(LevelWarn, global.helper.msgKey, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Warnw logs a message at warnf level.
|
||||
func Warnw(keyvals ...interface{}) {
|
||||
global.helper.Log(LevelWarn, keyvals...)
|
||||
}
|
||||
|
||||
// Error logs a message at error level.
|
||||
func Error(a ...interface{}) {
|
||||
global.helper.Log(LevelError, global.helper.msgKey, fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Errorf logs a message at error level.
|
||||
func Errorf(format string, a ...interface{}) {
|
||||
global.helper.Log(LevelError, global.helper.msgKey, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Errorw logs a message at error level.
|
||||
func Errorw(keyvals ...interface{}) {
|
||||
global.helper.Log(LevelError, keyvals...)
|
||||
}
|
||||
|
||||
// Fatal logs a message at fatal level.
|
||||
func Fatal(a ...interface{}) {
|
||||
global.helper.Log(LevelFatal, global.helper.msgKey, fmt.Sprint(a...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalf logs a message at fatal level.
|
||||
func Fatalf(format string, a ...interface{}) {
|
||||
global.helper.Log(LevelFatal, global.helper.msgKey, fmt.Sprintf(format, a...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalw logs a message at fatal level.
|
||||
func Fatalw(keyvals ...interface{}) {
|
||||
global.helper.Log(LevelFatal, keyvals...)
|
||||
os.Exit(1)
|
||||
}
|
68
log/global_test.go
Normal file
68
log/global_test.go
Normal file
@ -0,0 +1,68 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGlobalLog(t *testing.T) {
|
||||
buffer := &bytes.Buffer{}
|
||||
SetLogger(NewStdLogger(buffer))
|
||||
|
||||
testCases := []struct {
|
||||
level Level
|
||||
content []interface{}
|
||||
}{
|
||||
{
|
||||
LevelDebug,
|
||||
[]interface{}{"test debug"},
|
||||
},
|
||||
{
|
||||
LevelInfo,
|
||||
[]interface{}{"test info"},
|
||||
},
|
||||
{
|
||||
LevelInfo,
|
||||
[]interface{}{"test %s", "info"},
|
||||
},
|
||||
{
|
||||
LevelWarn,
|
||||
[]interface{}{"test warn"},
|
||||
},
|
||||
{
|
||||
LevelError,
|
||||
[]interface{}{"test error"},
|
||||
},
|
||||
{
|
||||
LevelError,
|
||||
[]interface{}{"test %s", "error"},
|
||||
},
|
||||
}
|
||||
|
||||
expected := []string{}
|
||||
for _, tc := range testCases {
|
||||
msg := fmt.Sprintf(tc.content[0].(string), tc.content[1:]...)
|
||||
switch tc.level {
|
||||
case LevelDebug:
|
||||
Debugf(tc.content[0].(string), tc.content[1:]...)
|
||||
expected = append(expected, fmt.Sprintf("%s msg=%s", "DEBUG", msg))
|
||||
case LevelInfo:
|
||||
Infof(tc.content[0].(string), tc.content[1:]...)
|
||||
expected = append(expected, fmt.Sprintf("%s msg=%s", "INFO", msg))
|
||||
case LevelWarn:
|
||||
Warnf(tc.content[0].(string), tc.content[1:]...)
|
||||
expected = append(expected, fmt.Sprintf("%s msg=%s", "WARN", msg))
|
||||
case LevelError:
|
||||
Errorf(tc.content[0].(string), tc.content[1:]...)
|
||||
expected = append(expected, fmt.Sprintf("%s msg=%s", "ERROR", msg))
|
||||
}
|
||||
}
|
||||
expected = append(expected, "")
|
||||
|
||||
t.Logf("Content: %s", buffer.String())
|
||||
if buffer.String() != strings.Join(expected, "\n") {
|
||||
t.Errorf("Expected: %s, got: %s", strings.Join(expected, "\n"), buffer.String())
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ func WithLogger(logger log.Logger) Option {
|
||||
// Recovery is a server middleware that recovers from any panics.
|
||||
func Recovery(opts ...Option) middleware.Middleware {
|
||||
op := options{
|
||||
logger: log.DefaultLogger,
|
||||
logger: log.GetLogger(),
|
||||
handler: func(ctx context.Context, req, err interface{}) error {
|
||||
return ErrUnknownRequest
|
||||
},
|
||||
|
@ -19,7 +19,7 @@ func TestOnce(t *testing.T) {
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
panic("panic reason")
|
||||
}
|
||||
_, e := Recovery(WithLogger(log.DefaultLogger))(next)(context.Background(), "panic")
|
||||
_, e := Recovery(WithLogger(log.GetLogger()))(next)(context.Background(), "panic")
|
||||
t.Logf("succ and reason is %v", e)
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ type builder struct {
|
||||
func NewBuilder(d registry.Discovery, opts ...Option) resolver.Builder {
|
||||
b := &builder{
|
||||
discoverer: d,
|
||||
logger: log.DefaultLogger,
|
||||
logger: log.GetLogger(),
|
||||
timeout: time.Second * 10,
|
||||
insecure: false,
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func TestWatch(t *testing.T) {
|
||||
r := &discoveryResolver{
|
||||
w: &testWatch{},
|
||||
cc: &testClientConn{te: t},
|
||||
log: log.NewHelper(log.DefaultLogger),
|
||||
log: log.NewHelper(log.GetLogger()),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
insecure: false,
|
||||
@ -75,7 +75,7 @@ func TestWatchError(t *testing.T) {
|
||||
r := &discoveryResolver{
|
||||
w: &testWatch{err: errors.New("bad")},
|
||||
cc: &testClientConn{te: t},
|
||||
log: log.NewHelper(log.DefaultLogger),
|
||||
log: log.NewHelper(log.GetLogger()),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
@ -93,7 +93,7 @@ func TestWatchContextCancel(t *testing.T) {
|
||||
r := &discoveryResolver{
|
||||
w: &testWatch{err: context.Canceled},
|
||||
cc: &testClientConn{te: t},
|
||||
log: log.NewHelper(log.DefaultLogger),
|
||||
log: log.NewHelper(log.GetLogger()),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ func NewServer(opts ...ServerOption) *Server {
|
||||
address: ":0",
|
||||
timeout: 1 * time.Second,
|
||||
health: health.NewServer(),
|
||||
log: log.NewHelper(log.DefaultLogger),
|
||||
log: log.NewHelper(log.GetLogger()),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(srv)
|
||||
|
@ -57,7 +57,7 @@ func newResolver(ctx context.Context, discovery registry.Discovery, target *Targ
|
||||
r := &resolver{
|
||||
target: target,
|
||||
watcher: watcher,
|
||||
logger: log.NewHelper(log.DefaultLogger),
|
||||
logger: log.NewHelper(log.GetLogger()),
|
||||
rebalancer: rebalancer,
|
||||
insecure: insecure,
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ func NewServer(opts ...ServerOption) *Server {
|
||||
enc: DefaultResponseEncoder,
|
||||
ene: DefaultErrorEncoder,
|
||||
strictSlash: true,
|
||||
log: log.NewHelper(log.DefaultLogger),
|
||||
log: log.NewHelper(log.GetLogger()),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(srv)
|
||||
|
Loading…
x
Reference in New Issue
Block a user