The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/plugins/backendplugin/grpcplugin/log_wrapper.go

168 lines
4.3 KiB

package grpcplugin
import (
"fmt"
"io"
"log"
"github.com/hashicorp/go-hclog"
plog "github.com/grafana/grafana/pkg/plugins/log"
)
type logWrapper struct {
Logger plog.Logger
name string
impliedArgs []any
}
func formatArgs(args ...any) []any {
if len(args) == 0 || len(args)%2 != 0 {
return args
}
res := []any{}
for n := 0; n < len(args); n += 2 {
key := args[n]
if stringKey, ok := key.(string); ok && stringKey == "timestamp" {
continue
}
res = append(res, key)
res = append(res, args[n+1])
}
return res
}
// Emit a message and key/value pairs at a provided log level
func (lw logWrapper) Log(level hclog.Level, msg string, args ...any) {
switch level {
case hclog.Trace:
lw.Trace(msg, args...)
case hclog.Debug:
lw.Debug(msg, args...)
case hclog.Info:
lw.Info(msg, args...)
case hclog.Warn:
lw.Warn(msg, args...)
case hclog.Error:
lw.Error(msg, args...)
default:
// TODO: Handle hclog.NoLevel
}
}
// Emit a message and key/value pairs at the TRACE level
func (lw logWrapper) Trace(msg string, args ...any) {
lw.Logger.Debug(msg, formatArgs(args...)...)
}
// Emit a message and key/value pairs at the DEBUG level
func (lw logWrapper) Debug(msg string, args ...any) {
lw.Logger.Debug(msg, formatArgs(args...)...)
}
// Emit a message and key/value pairs at the INFO level
func (lw logWrapper) Info(msg string, args ...any) {
lw.Logger.Info(msg, formatArgs(args...)...)
}
// Emit a message and key/value pairs at the WARN level
func (lw logWrapper) Warn(msg string, args ...any) {
lw.Logger.Warn(msg, formatArgs(args...)...)
}
// Emit a message and key/value pairs at the ERROR level
func (lw logWrapper) Error(msg string, args ...any) {
lw.Logger.Error(msg, formatArgs(args...)...)
}
// Indicate if TRACE logs would be emitted.
func (lw logWrapper) IsTrace() bool { return true }
// Indicate if DEBUG logs would be emitted.
func (lw logWrapper) IsDebug() bool { return true }
// Indicate if INFO logs would be emitted.
func (lw logWrapper) IsInfo() bool { return true }
// Indicate if WARN logs would be emitted.
func (lw logWrapper) IsWarn() bool { return true }
// Indicate if ERROR logs would be emitted.
func (lw logWrapper) IsError() bool { return true }
// ImpliedArgs returns With key/value pairs
func (lw logWrapper) ImpliedArgs() []any {
return lw.impliedArgs
}
// Creates a sublogger that will always have the given key/value pairs
func (lw logWrapper) With(args ...any) hclog.Logger {
return logWrapper{
Logger: lw.Logger.New(args...),
name: lw.name,
impliedArgs: args,
}
}
// Returns the Name of the logger
func (lw logWrapper) Name() string {
return lw.name
}
// Create a logger that will prepend the name string on the front of all messages.
// If the logger already has a name, the new value will be appended to the current
// name.
func (lw logWrapper) Named(name string) hclog.Logger {
if name == "stdio" {
// discard logs from stdio hashicorp/go-plugin gRPC service since
// it's not enabled/in use per default.
// discard debug log of "waiting for stdio data".
// discard warn log of "received EOF, stopping recv loop".
return hclog.NewNullLogger()
}
if lw.name != "" {
name = fmt.Sprintf("%s.%s", lw.name, name)
}
return logWrapper{
Logger: lw.Logger.New(),
name: name,
impliedArgs: lw.impliedArgs,
}
}
// Create a logger that will prepend the name string on the front of all messages.
// This sets the name of the logger to the value directly, unlike Named which honor
// the current name as well.
func (lw logWrapper) ResetNamed(name string) hclog.Logger {
return logWrapper{
Logger: lw.Logger.New(),
name: name,
impliedArgs: lw.impliedArgs,
}
}
// No-op. The wrapped logger implementation cannot update the level on the fly.
func (lw logWrapper) GetLevel() hclog.Level {
return hclog.Trace
}
// No-op. The wrapped logger implementation cannot update the level on the fly.
func (lw logWrapper) SetLevel(level hclog.Level) {}
// Return a value that conforms to the stdlib log.Logger interface
func (lw logWrapper) StandardLogger(ops *hclog.StandardLoggerOptions) *log.Logger {
return nil
}
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
func (lw logWrapper) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
return io.Discard
}