This is an automated email from the ASF dual-hosted git repository.
hanahmily pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git
The following commit(s) were added to refs/heads/main by this push:
new 4390d4f Introduce logging system
4390d4f is described below
commit 4390d4f3410771666fc3b248ff281e12b13e7136
Author: Gao Hongtao <[email protected]>
AuthorDate: Fri Apr 9 09:15:51 2021 +0800
Introduce logging system
Signed-off-by: Gao Hongtao <[email protected]>
---
banyand/config/default/standalone.yaml | 3 +-
banyand/executor/executor.go | 6 +--
banyand/index/index.go | 6 +--
banyand/internal/cmd/standalone.go | 17 ++++---
banyand/series/series.go | 6 +--
banyand/shard/shard.go | 6 +--
go.mod | 1 +
pkg/config/logging.go | 1 +
pkg/logger/logger.go | 67 ++++++++++++++++++++++---
pkg/logger/setting.go | 77 ++++++++++++++++++++++++++++
pkg/logger/setting_test.go | 91 ++++++++++++++++++++++++++++++++++
11 files changed, 255 insertions(+), 26 deletions(-)
diff --git a/banyand/config/default/standalone.yaml
b/banyand/config/default/standalone.yaml
index 01d1873..33d0cc6 100644
--- a/banyand/config/default/standalone.yaml
+++ b/banyand/config/default/standalone.yaml
@@ -16,4 +16,5 @@
# specific language governing permissions and limitations
# under the License.
logging:
- level: info
\ No newline at end of file
+ env: dev
+ level: info
diff --git a/banyand/executor/executor.go b/banyand/executor/executor.go
index fb7993e..ac25e9e 100644
--- a/banyand/executor/executor.go
+++ b/banyand/executor/executor.go
@@ -35,17 +35,17 @@ type Executor struct {
func NewExecutor(bus *bus.Bus) *Executor {
return &Executor{
bus: bus,
- log: logger.Log.Scope("executor"),
+ log: logger.GetLogger("executor"),
}
}
func (s Executor) Rev(message bus.Message) {
- s.log.Sugar().Infow("rev", "msg", message.Data())
+ s.log.Info("rev", logger.Any("msg", message.Data()))
_ = s.bus.Publish(storage.TraceIndex,
bus.NewMessage(bus.MessageID(time.Now().UnixNano()), "index message"))
_ = s.bus.Publish(storage.TraceData,
bus.NewMessage(bus.MessageID(time.Now().UnixNano()), "data message"))
}
func (s Executor) Close() error {
- s.log.Sugar().Infow("closed")
+ s.log.Info("closed")
return nil
}
diff --git a/banyand/index/index.go b/banyand/index/index.go
index 5f228d5..d29eb89 100644
--- a/banyand/index/index.go
+++ b/banyand/index/index.go
@@ -30,15 +30,15 @@ type Index struct {
func NewIndex() *Index {
return &Index{
- log: logger.Log.Scope("Index"),
+ log: logger.GetLogger("Index"),
}
}
func (s Index) Rev(message bus.Message) {
- s.log.Sugar().Infow("rev", "msg", message.Data())
+ s.log.Info("rev", logger.Any("msg", message.Data()))
}
func (s Index) Close() error {
- s.log.Sugar().Infow("closed")
+ s.log.Info("closed")
return nil
}
diff --git a/banyand/internal/cmd/standalone.go
b/banyand/internal/cmd/standalone.go
index 3526eaf..27ca159 100644
--- a/banyand/internal/cmd/standalone.go
+++ b/banyand/internal/cmd/standalone.go
@@ -19,7 +19,6 @@ package cmd
import (
"context"
- "fmt"
"os"
"os/signal"
"syscall"
@@ -38,18 +37,24 @@ import (
"github.com/apache/skywalking-banyandb/pkg/version"
)
+var standAloneConfig config.Standalone
+
func newStandaloneCmd() *cobra.Command {
standaloneCmd := &cobra.Command{
Use: "standalone",
Version: version.Build(),
Short: "Run as the standalone mode",
- RunE: func(cmd *cobra.Command, args []string) (err error) {
- logger.Log.Info("starting as a standalone server")
- var sc config.Standalone
- if sc, err = config.Load(); err != nil {
+ PersistentPreRunE: func(cmd *cobra.Command, args []string) (err
error) {
+ if standAloneConfig, err = config.Load(); err != nil {
+ return err
+ }
+ if err = logger.InitLogger(standAloneConfig.Logging);
err != nil {
return err
}
- fmt.Println(sc)
+ return nil
+ },
+ RunE: func(cmd *cobra.Command, args []string) (err error) {
+ logger.GetLogger().Info("starting as a standalone
server")
dataBus := bus.NewBus()
err = multierr.Append(err,
dataBus.Subscribe(storage.TraceRaw, shard.NewShard(dataBus)))
err = multierr.Append(err,
dataBus.Subscribe(storage.TraceSharded, executor.NewExecutor(dataBus)))
diff --git a/banyand/series/series.go b/banyand/series/series.go
index 6790575..a51a2a1 100644
--- a/banyand/series/series.go
+++ b/banyand/series/series.go
@@ -30,15 +30,15 @@ type Series struct {
func NewSeries() *Series {
return &Series{
- log: logger.Log.Scope("series"),
+ log: logger.GetLogger("series"),
}
}
func (s Series) Rev(message bus.Message) {
- s.log.Sugar().Infow("rev", "msg", message.Data())
+ s.log.Info("rev", logger.Any("msg", message.Data()))
}
func (s Series) Close() error {
- s.log.Sugar().Infow("closed")
+ s.log.Info("closed")
return nil
}
diff --git a/banyand/shard/shard.go b/banyand/shard/shard.go
index 75c2100..a25baff 100644
--- a/banyand/shard/shard.go
+++ b/banyand/shard/shard.go
@@ -35,16 +35,16 @@ type Shard struct {
func NewShard(bus *bus.Bus) *Shard {
return &Shard{
bus: bus,
- log: logger.Log.Scope("shard"),
+ log: logger.GetLogger("shard"),
}
}
func (s Shard) Rev(message bus.Message) {
- s.log.Sugar().Infow("rev", "msg", message.Data())
+ s.log.Info("rev", logger.Any("msg", message.Data()))
_ = s.bus.Publish(storage.TraceSharded,
bus.NewMessage(bus.MessageID(time.Now().UnixNano()), "sharded message"))
}
func (s Shard) Close() error {
- s.log.Sugar().Infow("closed")
+ s.log.Info("closed")
return nil
}
diff --git a/go.mod b/go.mod
index a628b50..fd684ee 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.16
require (
github.com/spf13/cobra v1.1.3
github.com/spf13/viper v1.7.1
+ github.com/stretchr/testify v1.4.0
go.uber.org/atomic v1.7.0
go.uber.org/multierr v1.6.0
go.uber.org/zap v1.16.0
diff --git a/pkg/config/logging.go b/pkg/config/logging.go
index 85ecd8e..0ddb698 100644
--- a/pkg/config/logging.go
+++ b/pkg/config/logging.go
@@ -18,5 +18,6 @@
package config
type Logging struct {
+ Env string
Level string
}
diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go
index 7f78176..1429a5a 100644
--- a/pkg/logger/logger.go
+++ b/pkg/logger/logger.go
@@ -19,19 +19,72 @@ package logger
import (
"go.uber.org/zap"
+ "go.uber.org/zap/zapcore"
)
+// Logger is wrapper for zap logger with module, it is singleton.
type Logger struct {
- *zap.Logger
+ module string
+ logger *zap.Logger
}
-func (l Logger) Scope(scope string) *Logger {
- return &Logger{l.Logger.Named(scope)}
+// Debug logs a message at DebugLevel. The message includes any fields passed
+// at the log site, as well as any fields accumulated on the logger.
+func (l *Logger) Debug(msg string, fields ...zap.Field) {
+ l.logger.Debug(msg, fields...)
}
-var Log *Logger
+// Info logs a message at InfoLevel. The message includes any fields passed
+// at the log site, as well as any fields accumulated on the logger.
+func (l *Logger) Info(msg string, fields ...zap.Field) {
+ l.logger.Info(msg, fields...)
+}
+
+// Warn logs a message at WarnLevel. The message includes any fields passed
+// at the log site, as well as any fields accumulated on the logger.
+func (l *Logger) Warn(msg string, fields ...zap.Field) {
+ l.logger.Warn(msg, fields...)
+}
+
+// Error logs a message at ErrorLevel. The message includes any fields passed
+// at the log site, as well as any fields accumulated on the logger.
+func (l *Logger) Error(msg string, fields ...zap.Field) {
+ l.logger.Error(msg, fields...)
+}
+
+// String constructs a field with the given key and value.
+func String(key string, val string) zap.Field {
+ return zap.Field{Key: key, Type: zapcore.StringType, String: val}
+}
+
+// Error is shorthand for the common idiom NamedError("error", err).
+func Error(err error) zap.Field {
+ return zap.NamedError("error", err)
+}
+
+// Uint16 constructs a field with the given key and value.
+func Uint16(key string, val uint16) zap.Field {
+ return zap.Field{Key: key, Type: zapcore.Uint16Type, Integer:
int64(val)}
+}
+
+// Uint32 constructs a field with the given key and value.
+func Uint32(key string, val uint32) zap.Field {
+ return zap.Field{Key: key, Type: zapcore.Uint32Type, Integer:
int64(val)}
+}
+
+// Int32 constructs a field with the given key and value.
+func Int32(key string, val int32) zap.Field {
+ return zap.Field{Key: key, Type: zapcore.Int32Type, Integer: int64(val)}
+}
+
+// Int64 constructs a field with the given key and value.
+func Int64(key string, val int64) zap.Field {
+ return zap.Field{Key: key, Type: zapcore.Int64Type, Integer: val}
+}
-func init() {
- l, _ := zap.NewDevelopment()
- Log = &Logger{l}
+// Any takes a key and an arbitrary value and chooses the best way to represent
+// them as a field, falling back to a reflection-based approach only if
+// necessary.
+func Any(key string, value interface{}) zap.Field {
+ return zap.Any(key, value)
}
diff --git a/pkg/logger/setting.go b/pkg/logger/setting.go
new file mode 100644
index 0000000..5fb7dbd
--- /dev/null
+++ b/pkg/logger/setting.go
@@ -0,0 +1,77 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package logger
+
+import (
+ "strings"
+ "sync"
+
+ "go.uber.org/zap"
+ "go.uber.org/zap/zapcore"
+
+ "github.com/apache/skywalking-banyandb/pkg/config"
+)
+
+var (
+ root *Logger
+ once sync.Once
+)
+
+// GetLogger return logger with a scope
+func GetLogger(scope ...string) *Logger {
+ if len(scope) < 1 {
+ return root
+ }
+ module := strings.Join(scope, ".")
+ return &Logger{module: module, logger: root.logger.Named(module)}
+}
+
+// InitLogger initializes a zap logger from user config
+func InitLogger(cfg config.Logging) (err error) {
+ once.Do(func() {
+ root, err = getLogger(cfg)
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// getLogger initializes a root logger
+func getLogger(cfg config.Logging) (*Logger, error) {
+ // parse logging level
+ level := zap.NewAtomicLevelAt(zapcore.InfoLevel)
+ if err := level.UnmarshalText([]byte(cfg.Level)); err != nil {
+ return nil, err
+ }
+ var encoderConfig zap.Config
+ switch cfg.Env {
+ case "dev":
+ encoderConfig = zap.NewDevelopmentConfig()
+ encoderConfig.EncoderConfig.EncodeLevel =
zapcore.CapitalColorLevelEncoder
+ break
+ default:
+ encoderConfig = zap.NewProductionConfig()
+ }
+ encoderConfig.Level = level
+ l, err := encoderConfig.Build()
+ if err != nil {
+ return nil, err
+ }
+ return &Logger{module: "root", logger: l}, nil
+}
diff --git a/pkg/logger/setting_test.go b/pkg/logger/setting_test.go
new file mode 100644
index 0000000..d065af2
--- /dev/null
+++ b/pkg/logger/setting_test.go
@@ -0,0 +1,91 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package logger
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "go.uber.org/zap/zapcore"
+
+ "github.com/apache/skywalking-banyandb/pkg/config"
+)
+
+func TestInitLogger(t *testing.T) {
+ type args struct {
+ cfg config.Logging
+ }
+ type want struct {
+ isDev bool
+ level zapcore.Level
+ }
+ tests := []struct {
+ name string
+ args args
+ want want
+ wantErr bool
+ }{
+ {
+ name: "golden path",
+ args: args{config.Logging{Env: "prod", Level: "info"}},
+ want: want{level: zapcore.InfoLevel},
+ },
+ {
+ name: "empty config",
+ args: args{config.Logging{}},
+ want: want{level: zapcore.InfoLevel},
+ },
+ {
+ name: "development mode",
+ args: args{config.Logging{Env: "dev"}},
+ want: want{isDev: true, level: zapcore.InfoLevel},
+ },
+ {
+ name: "debug level",
+ args: args{config.Logging{Level: "debug"}},
+ want: want{level: zapcore.DebugLevel},
+ },
+ {
+ name: "invalid env",
+ args: args{config.Logging{Env: "invalid"}},
+ want: want{level: zapcore.InfoLevel},
+ },
+ {
+ name: "invalid level",
+ args: args{config.Logging{Level: "invalid"}},
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ var err error
+ var logger *Logger
+ if logger, err = getLogger(tt.args.cfg); (err != nil)
!= tt.wantErr {
+ t.Errorf("InitLogger() error = %v, wantErr %v",
err, tt.wantErr)
+ }
+ if err == nil {
+ assert.NotNil(t, logger)
+ assert.NotNil(t, logger.logger)
+ assert.NotEmpty(t, logger.module)
+ assert.Equal(t, tt.want.isDev,
reflect.ValueOf(*logger.logger).FieldByName("development").Bool())
+ assert.NotNil(t,
logger.logger.Check(tt.want.level, "foo"))
+ }
+ })
+ }
+}