99 lines
3.0 KiB
Go

// Source: https://github.com/distribution/distribution
// Copyright 2014 https://github.com/distribution/distribution Authors
//
// Licensed 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 dcontext
import (
"context"
"fmt"
"runtime"
"github.com/rs/zerolog"
)
// Logger provides a leveled-logging interface.
type Logger interface {
Msgf(format string, v ...interface{})
Msg(msg string)
}
type loggerKey struct{}
// WithLogger creates a new context with provided logger.
func WithLogger(ctx context.Context, logger Logger) context.Context {
return context.WithValue(ctx, loggerKey{}, logger)
}
// GetLoggerWithFields returns a logger instance with the specified fields
// without affecting the context. Extra specified keys will be resolved from
// the context.
func GetLoggerWithFields(
ctx context.Context, log *zerolog.Event,
fields map[interface{}]interface{}, keys ...interface{},
) Logger {
logger := getZerologLogger(ctx, log, keys...)
for key, value := range fields {
logger.Interface(fmt.Sprint(key), value)
}
return logger
}
// GetLogger returns the logger from the current context, if present. If one
// or more keys are provided, they will be resolved on the context and
// included in the logger. While context.Value takes an interface, any key
// argument passed to GetLogger will be passed to fmt.Sprint when expanded as
// a logging key field. If context keys are integer constants, for example,
// its recommended that a String method is implemented.
func GetLogger(ctx context.Context, l *zerolog.Event, keys ...interface{}) Logger {
return getZerologLogger(ctx, l, keys...)
}
// getZerologLogger returns the zerolog logger for the context. If one more keys
// are provided, they will be resolved on the context and included in the
// logger. Only use this function if specific zerolog functionality is
// required.
func getZerologLogger(ctx context.Context, l *zerolog.Event, keys ...interface{}) *zerolog.Event {
var logger *zerolog.Event
// Get a logger, if it is present.
loggerInterface := ctx.Value(loggerKey{})
if loggerInterface != nil {
if lgr, ok := loggerInterface.(*zerolog.Event); ok {
logger = lgr
}
}
if logger == nil {
logger = l.Str("go.version", runtime.Version())
// Fill in the instance id, if we have it.
instanceID := ctx.Value("instance.id")
if instanceID != nil {
logger.Interface("instance.id", instanceID)
}
}
for _, key := range keys {
v := ctx.Value(key)
if v != nil {
logger.Interface(fmt.Sprint(key), v)
}
}
return logger
}