Merge pull request #9056 from influxdata/js-configure-logging
Add logging configuration to the main configuration filepull/9445/head
commit
dd21fa15fd
|
@ -3,7 +3,7 @@ v1.5.0 [unreleased]
|
|||
|
||||
### Breaking changes
|
||||
|
||||
- The default logging format has been changed. See [#9055](https://github.com/influxdata/influxdb/pull/9055) for details.
|
||||
- The default logging format has been changed. See [#9055](https://github.com/influxdata/influxdb/pull/9055) and [#9066](https://github.com/influxdata/influxdb/pull/9056) for details.
|
||||
|
||||
### Features
|
||||
|
||||
|
|
2
Godeps
2
Godeps
|
@ -18,7 +18,9 @@ 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 5ea53862c7fa897f44ae0b3004283308c0b0c9d1
|
||||
github.com/jwilder/encoding 27894731927e49b0a9023f00312be26733744815
|
||||
github.com/mattn/go-isatty 6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c
|
||||
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c
|
||||
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
||||
github.com/paulbellamy/ratecounter 5a11f585a31379765c190c033b6ad39956584447
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
- github.com/influxdata/yamux [MOZILLA PUBLIC LICENSE](https://github.com/influxdata/yamux/blob/master/LICENSE)
|
||||
- github.com/influxdata/yarpc [MIT LICENSE](https://github.com/influxdata/yarpc/blob/master/LICENSE)
|
||||
- github.com/jwilder/encoding [MIT LICENSE](https://github.com/jwilder/encoding/blob/master/LICENSE)
|
||||
- github.com/mattn/go-isatty [MIT LICENSE](https://github.com/mattn/go-isatty/blob/master/LICENSE)
|
||||
- github.com/matttproud/golang_protobuf_extensions [APACHE LICENSE](https://github.com/matttproud/golang_protobuf_extensions/blob/master/LICENSE)
|
||||
- github.com/opentracing/opentracing-go [MIT LICENSE](https://github.com/opentracing/opentracing-go/blob/master/LICENSE)
|
||||
- github.com/paulbellamy/ratecounter [MIT LICENSE](https://github.com/paulbellamy/ratecounter/blob/master/LICENSE)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxdb/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -70,14 +71,43 @@ 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.
|
||||
var (
|
||||
suppressLogo bool
|
||||
logErr error
|
||||
)
|
||||
if config, err := cmd.ParseConfig(options.GetConfigPath()); err == nil {
|
||||
suppressLogo = config.Logging.SuppressLogo
|
||||
if l, err := config.Logging.New(cmd.Stderr); err == nil {
|
||||
cmd.Logger = l
|
||||
} else {
|
||||
logErr = err
|
||||
}
|
||||
} else {
|
||||
logErr = err
|
||||
}
|
||||
|
||||
// We were unable to read the configuration file. Use the default logging format.
|
||||
if logErr != nil {
|
||||
cmd.Logger = logger.New(cmd.Stderr)
|
||||
}
|
||||
|
||||
// Print sweet InfluxDB logo.
|
||||
fmt.Fprint(cmd.Stdout, logo)
|
||||
if !suppressLogo {
|
||||
fmt.Fprint(cmd.Stdout, logo)
|
||||
}
|
||||
|
||||
// Mark start-up in log.
|
||||
cmd.Logger.Info(fmt.Sprintf("InfluxDB starting, version %s, branch %s, commit %s",
|
||||
cmd.Version, cmd.Branch, cmd.Commit))
|
||||
cmd.Logger.Info(fmt.Sprintf("Go version %s, GOMAXPROCS set to %d", runtime.Version(), runtime.GOMAXPROCS(0)))
|
||||
|
||||
// If there was an error on startup when creating the logger, output it now.
|
||||
if logErr != nil {
|
||||
cmd.Logger.Error("Unable to configure logger", zap.Error(logErr))
|
||||
}
|
||||
|
||||
// Write the PID file.
|
||||
if err := cmd.writePIDFile(options.PIDFile); err != nil {
|
||||
return fmt.Errorf("write pid file: %s", err)
|
||||
|
|
|
@ -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()}
|
||||
|
|
|
@ -270,6 +270,24 @@
|
|||
# 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"
|
||||
|
||||
# Suppresses the logo output that is printed when the program is started.
|
||||
# suppress-logo = false
|
||||
|
||||
###
|
||||
### [subscriber]
|
||||
###
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Format string `toml:"format"`
|
||||
Level zapcore.Level `toml:"level"`
|
||||
SuppressLogo bool `toml:"suppress-logo"`
|
||||
}
|
||||
|
||||
// NewConfig returns a new instance of Config with defaults.
|
||||
func NewConfig() Config {
|
||||
return Config{
|
||||
Format: "auto",
|
||||
}
|
||||
}
|
|
@ -1,14 +1,66 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/jsternberg/zap-logfmt"
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
func New(w io.Writer) *zap.Logger {
|
||||
config := NewConfig()
|
||||
l, _ := config.New(w)
|
||||
return l
|
||||
}
|
||||
|
||||
func (c *Config) New(defaultOutput io.Writer) (*zap.Logger, error) {
|
||||
w := defaultOutput
|
||||
format := c.Format
|
||||
if format == "console" {
|
||||
// Disallow the console logger if the output is not a terminal.
|
||||
return nil, fmt.Errorf("unknown logging format: %s", format)
|
||||
}
|
||||
|
||||
// If the format is empty or auto, then set the format depending
|
||||
// on whether or not a terminal is present.
|
||||
if format == "" || format == "auto" {
|
||||
if isTerminal(w) {
|
||||
format = "console"
|
||||
} else {
|
||||
format = "logfmt"
|
||||
}
|
||||
}
|
||||
|
||||
encoder, err := newEncoder(format)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return zap.New(zapcore.NewCore(
|
||||
encoder,
|
||||
zapcore.Lock(zapcore.AddSync(w)),
|
||||
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 +68,14 @@ 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
|
||||
}
|
||||
|
||||
func isTerminal(w io.Writer) bool {
|
||||
if f, ok := w.(interface {
|
||||
Fd() uintptr
|
||||
}); ok {
|
||||
return isatty.IsTerminal(f.Fd())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue