forked from influxdata/influxdb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move the logger package from influxdb to platform
We are moving the necessary code for 2.0 from the influxdb 1.X repository to the platform 2.0 repository. The logger is an unnecessary dependency on the old influxdb that is making life more complicated.
- Loading branch information
1 parent
18cdd69
commit e7e17d6
Showing
21 changed files
with
489 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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", | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package logger | ||
|
||
import ( | ||
"context" | ||
|
||
"go.uber.org/zap" | ||
) | ||
|
||
type key int | ||
|
||
const ( | ||
loggerKey key = iota | ||
) | ||
|
||
// NewContextWithLogger returns a new context with log added. | ||
func NewContextWithLogger(ctx context.Context, log *zap.Logger) context.Context { | ||
return context.WithValue(ctx, loggerKey, log) | ||
} | ||
|
||
// LoggerFromContext returns the zap.Logger associated with ctx or nil if no logger has been assigned. | ||
func LoggerFromContext(ctx context.Context) *zap.Logger { | ||
l, _ := ctx.Value(loggerKey).(*zap.Logger) | ||
return l | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package logger | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/influxdata/platform/pkg/snowflake" | ||
"go.uber.org/zap" | ||
"go.uber.org/zap/zapcore" | ||
) | ||
|
||
const ( | ||
// TraceIDKey is the logging context key used for identifying unique traces. | ||
TraceIDKey = "trace_id" | ||
|
||
// OperationNameKey is the logging context key used for identifying name of an operation. | ||
OperationNameKey = "op_name" | ||
|
||
// OperationEventKey is the logging context key used for identifying a notable | ||
// event during the course of an operation. | ||
OperationEventKey = "op_event" | ||
|
||
// OperationElapsedKey is the logging context key used for identifying time elapsed to finish an operation. | ||
OperationElapsedKey = "op_elapsed" | ||
|
||
// DBInstanceKey is the logging context key used for identifying name of the relevant database. | ||
DBInstanceKey = "db_instance" | ||
|
||
// DBRetentionKey is the logging context key used for identifying name of the relevant retention policy. | ||
DBRetentionKey = "db_rp" | ||
|
||
// DBShardGroupKey is the logging context key used for identifying relevant shard group. | ||
DBShardGroupKey = "db_shard_group" | ||
|
||
// DBShardIDKey is the logging context key used for identifying name of the relevant shard number. | ||
DBShardIDKey = "db_shard_id" | ||
) | ||
const ( | ||
eventStart = "start" | ||
eventEnd = "end" | ||
) | ||
|
||
var ( | ||
gen = snowflake.New(0) | ||
) | ||
|
||
func nextID() string { | ||
return gen.NextString() | ||
} | ||
|
||
// TraceID returns a field for tracking the trace identifier. | ||
func TraceID(id string) zapcore.Field { | ||
return zap.String(TraceIDKey, id) | ||
} | ||
|
||
// OperationName returns a field for tracking the name of an operation. | ||
func OperationName(name string) zapcore.Field { | ||
return zap.String(OperationNameKey, name) | ||
} | ||
|
||
// OperationElapsed returns a field for tracking the duration of an operation. | ||
func OperationElapsed(d time.Duration) zapcore.Field { | ||
return zap.Duration(OperationElapsedKey, d) | ||
} | ||
|
||
// OperationEventStart returns a field for tracking the start of an operation. | ||
func OperationEventStart() zapcore.Field { | ||
return zap.String(OperationEventKey, eventStart) | ||
} | ||
|
||
// OperationEventFinish returns a field for tracking the end of an operation. | ||
func OperationEventEnd() zapcore.Field { | ||
return zap.String(OperationEventKey, eventEnd) | ||
} | ||
|
||
// Database returns a field for tracking the name of a database. | ||
func Database(name string) zapcore.Field { | ||
return zap.String(DBInstanceKey, name) | ||
} | ||
|
||
// Database returns a field for tracking the name of a database. | ||
func RetentionPolicy(name string) zapcore.Field { | ||
return zap.String(DBRetentionKey, name) | ||
} | ||
|
||
// ShardGroup returns a field for tracking the shard group identifier. | ||
func ShardGroup(id uint64) zapcore.Field { | ||
return zap.Uint64(DBShardGroupKey, id) | ||
} | ||
|
||
// Shard returns a field for tracking the shard identifier. | ||
func Shard(id uint64) zapcore.Field { | ||
return zap.Uint64(DBShardIDKey, id) | ||
} | ||
|
||
// NewOperation uses the exiting log to create a new logger with context | ||
// containing a trace id and the operation. Prior to returning, a standardized message | ||
// is logged indicating the operation has started. The returned function should be | ||
// called when the operation concludes in order to log a corresponding message which | ||
// includes an elapsed time and that the operation has ended. | ||
func NewOperation(log *zap.Logger, msg, name string, fields ...zapcore.Field) (*zap.Logger, func()) { | ||
f := []zapcore.Field{TraceID(nextID()), OperationName(name)} | ||
if len(fields) > 0 { | ||
f = append(f, fields...) | ||
} | ||
|
||
now := time.Now() | ||
log = log.With(f...) | ||
log.Info(msg+" (start)", OperationEventStart()) | ||
|
||
return log, func() { log.Info(msg+" (end)", OperationEventEnd(), OperationElapsed(time.Since(now))) } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
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" | ||
) | ||
|
||
const TimeFormat = "2006-01-02T15:04:05.000000Z07:00" | ||
|
||
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, | ||
), zap.Fields(zap.String("log_id", nextID()))), 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(TimeFormat)) | ||
} | ||
config.EncodeDuration = func(d time.Duration, encoder zapcore.PrimitiveArrayEncoder) { | ||
val := float64(d) / float64(time.Millisecond) | ||
encoder.AppendString(fmt.Sprintf("%.3fms", val)) | ||
} | ||
config.LevelKey = "lvl" | ||
return config | ||
} | ||
|
||
// IsTerminal checks if w is a file and whether it is an interactive terminal session. | ||
func IsTerminal(w io.Writer) bool { | ||
if f, ok := w.(interface { | ||
Fd() uintptr | ||
}); ok { | ||
return isatty.IsTerminal(f.Fd()) | ||
} | ||
return false | ||
} | ||
|
||
const ( | ||
year = 365 * 24 * time.Hour | ||
week = 7 * 24 * time.Hour | ||
day = 24 * time.Hour | ||
) | ||
|
||
func DurationLiteral(key string, val time.Duration) zapcore.Field { | ||
if val == 0 { | ||
return zap.String(key, "0s") | ||
} | ||
|
||
var ( | ||
value int | ||
unit string | ||
) | ||
switch { | ||
case val%year == 0: | ||
value = int(val / year) | ||
unit = "y" | ||
case val%week == 0: | ||
value = int(val / week) | ||
unit = "w" | ||
case val%day == 0: | ||
value = int(val / day) | ||
unit = "d" | ||
case val%time.Hour == 0: | ||
value = int(val / time.Hour) | ||
unit = "h" | ||
case val%time.Minute == 0: | ||
value = int(val / time.Minute) | ||
unit = "m" | ||
case val%time.Second == 0: | ||
value = int(val / time.Second) | ||
unit = "s" | ||
default: | ||
value = int(val / time.Millisecond) | ||
unit = "ms" | ||
} | ||
return zap.String(key, fmt.Sprintf("%d%s", value, unit)) | ||
} |
Oops, something went wrong.