Add logging configuration to the main configuration file

Make logfmt the default log output format with json and a more user
friendly console into possible options.
pull/9056/head
Jonathan A. Sternberg 2017-11-03 09:25:48 -05:00 committed by Jonathan A. Sternberg
parent 56b4a91acf
commit ccf2e549b8
7 changed files with 92 additions and 17 deletions

1
Godeps
View File

@ -18,6 +18,7 @@ github.com/influxdata/influxql 7c0f432656229c2084ee825680ef39a2228ccdb3
github.com/influxdata/usage-client 6d3895376368aa52a3a81d2a16e90f0f52371967
github.com/influxdata/yamux 1f58ded512de5feabbe30b60c7d33a7a896c5f16
github.com/influxdata/yarpc 036268cdec22b7074cd6d50cc6d7315c667063c7
github.com/jsternberg/zap-logfmt 8107add5122c6d595e530dabc25a0f259fa7ad38
github.com/jwilder/encoding 27894731927e49b0a9023f00312be26733744815
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7

View File

@ -16,8 +16,6 @@ import (
"github.com/influxdata/influxdb/cmd/influxd/help"
"github.com/influxdata/influxdb/cmd/influxd/restore"
"github.com/influxdata/influxdb/cmd/influxd/run"
"github.com/influxdata/influxdb/logger"
"go.uber.org/zap"
)
// These variables are populated via the Go linker.
@ -52,8 +50,6 @@ func main() {
// Main represents the program execution.
type Main struct {
Logger *zap.Logger
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
@ -62,7 +58,6 @@ type Main struct {
// NewMain return a new instance of Main.
func NewMain() *Main {
return &Main{
Logger: logger.New(os.Stderr),
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
@ -82,7 +77,6 @@ func (m *Main) Run(args ...string) error {
cmd.Version = version
cmd.Commit = commit
cmd.Branch = branch
cmd.Logger = m.Logger
if err := cmd.Run(args...); err != nil {
return fmt.Errorf("run: %s", err)
@ -90,23 +84,23 @@ func (m *Main) Run(args ...string) error {
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
m.Logger.Info("Listening for signals")
cmd.Logger.Info("Listening for signals")
// Block until one of the signals above is received
<-signalCh
m.Logger.Info("Signal received, initializing clean shutdown...")
cmd.Logger.Info("Signal received, initializing clean shutdown...")
go cmd.Close()
// Block again until another signal is received, a shutdown timeout elapses,
// or the Command is gracefully closed
m.Logger.Info("Waiting for clean shutdown...")
cmd.Logger.Info("Waiting for clean shutdown...")
select {
case <-signalCh:
m.Logger.Info("second signal received, initializing hard shutdown")
cmd.Logger.Info("second signal received, initializing hard shutdown")
case <-time.After(time.Second * 30):
m.Logger.Info("time limit reached, initializing hard shutdown")
cmd.Logger.Info("time limit reached, initializing hard shutdown")
case <-cmd.Closed:
m.Logger.Info("server shutdown completed")
cmd.Logger.Info("server shutdown completed")
}
// goodbye.

View File

@ -13,6 +13,7 @@ import (
"strconv"
"time"
"github.com/influxdata/influxdb/logger"
"go.uber.org/zap"
)
@ -70,6 +71,18 @@ func (cmd *Command) Run(args ...string) error {
return err
}
// Attempt to parse the config once in advance. If this fails, use the
// default logging configuration.
if config, err := cmd.ParseConfig(options.GetConfigPath()); err == nil {
if l, err := config.Logging.New(cmd.Stderr); err == nil {
cmd.Logger = l
}
}
// We were unable to read the configuration file. Use the default logging format.
if cmd.Logger == nil {
cmd.Logger = logger.New(cmd.Stderr)
}
// Print sweet InfluxDB logo.
fmt.Fprint(cmd.Stdout, logo)

View File

@ -15,6 +15,7 @@ import (
"github.com/BurntSushi/toml"
"github.com/influxdata/influxdb/coordinator"
"github.com/influxdata/influxdb/logger"
"github.com/influxdata/influxdb/monitor"
"github.com/influxdata/influxdb/monitor/diagnostics"
"github.com/influxdata/influxdb/services/collectd"
@ -49,6 +50,7 @@ type Config struct {
Monitor monitor.Config `toml:"monitor"`
Subscriber subscriber.Config `toml:"subscriber"`
HTTPD httpd.Config `toml:"http"`
Logging logger.Config `toml:"logging"`
Storage storage.Config `toml:"ifql"`
GraphiteInputs []graphite.Config `toml:"graphite"`
CollectdInputs []collectd.Config `toml:"collectd"`
@ -75,6 +77,7 @@ func NewConfig() *Config {
c.Monitor = monitor.NewConfig()
c.Subscriber = subscriber.NewConfig()
c.HTTPD = httpd.NewConfig()
c.Logging = logger.NewConfig()
c.Storage = storage.NewConfig()
c.GraphiteInputs = []graphite.Config{graphite.NewConfig()}

View File

@ -270,6 +270,21 @@
# bind-address = ":8082"
###
### [logging]
###
### Controls how the logger emits logs to the output.
###
[logging]
# Determines which log encoder to use for logs. Available options
# are logfmt, console, and json. console is a more user-friendly
# output format, but not as easily machine-readable.
# format = "logfmt"
# Determines which level of logs will be emitted.
# level = "info"
###
### [subscriber]
###

17
logger/config.go Normal file
View File

@ -0,0 +1,17 @@
package logger
import (
"go.uber.org/zap/zapcore"
)
type Config struct {
Format string `toml:"format"`
Level zapcore.Level `toml:"level"`
}
// NewConfig returns a new instance of Config with defaults.
func NewConfig() Config {
return Config{
Format: "logfmt",
}
}

View File

@ -1,14 +1,50 @@
package logger
import (
"fmt"
"io"
"time"
"github.com/jsternberg/zap-logfmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func New(w io.Writer) *zap.Logger {
return zap.New(zapcore.NewCore(
zaplogfmt.NewEncoder(newEncoderConfig()),
zapcore.Lock(zapcore.AddSync(w)),
zapcore.DebugLevel,
))
}
func (c *Config) New(defaultOutput io.Writer) (*zap.Logger, error) {
encoder, err := newEncoder(c.Format)
if err != nil {
return nil, err
}
return zap.New(zapcore.NewCore(
encoder,
zapcore.AddSync(defaultOutput),
c.Level,
)), nil
}
func newEncoder(format string) (zapcore.Encoder, error) {
config := newEncoderConfig()
switch format {
case "json":
return zapcore.NewJSONEncoder(config), nil
case "console":
return zapcore.NewConsoleEncoder(config), nil
case "logfmt", "":
return zaplogfmt.NewEncoder(config), nil
default:
return nil, fmt.Errorf("unknown logging format: %s", format)
}
}
func newEncoderConfig() zapcore.EncoderConfig {
config := zap.NewProductionEncoderConfig()
config.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(ts.UTC().Format(time.RFC3339))
@ -16,9 +52,5 @@ func New(w io.Writer) *zap.Logger {
config.EncodeDuration = func(d time.Duration, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(d.String())
}
return zap.New(zapcore.NewCore(
zapcore.NewConsoleEncoder(config),
zapcore.Lock(zapcore.AddSync(w)),
zapcore.DebugLevel,
))
return config
}