mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
182 lines
5.6 KiB
Go
182 lines
5.6 KiB
Go
package logger
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
|
|
"github.com/hashicorp/go-hclog"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// integrity check
|
|
var _ hclog.Logger = &LogrusHCLogAdapter{}
|
|
|
|
var levels = map[hclog.Level]logrus.Level{
|
|
hclog.NoLevel: logrus.PanicLevel,
|
|
hclog.Error: logrus.ErrorLevel,
|
|
hclog.Warn: logrus.WarnLevel,
|
|
hclog.Info: logrus.InfoLevel,
|
|
hclog.Debug: logrus.DebugLevel,
|
|
hclog.Trace: logrus.TraceLevel,
|
|
}
|
|
|
|
// LogrusHCLogAdapter is used to adapt a logrus logger object to the hclog.Logger interface for syft plugins.
|
|
type LogrusHCLogAdapter struct {
|
|
logger *logrus.Logger
|
|
entry *logrus.Entry
|
|
}
|
|
|
|
func NewLogrusHCLogAdapter(logger *logrus.Logger, fields map[string]interface{}) *LogrusHCLogAdapter {
|
|
if fields != nil {
|
|
return &LogrusHCLogAdapter{
|
|
logger: logger,
|
|
entry: logger.WithFields(fields),
|
|
}
|
|
}
|
|
return &LogrusHCLogAdapter{
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (l *LogrusHCLogAdapter) log(level hclog.Level, msg string, args ...interface{}) {
|
|
if l.entry != nil {
|
|
l.entry.WithFields(makeArgFields(args...)).Log(levels[level], msg)
|
|
return
|
|
}
|
|
l.logger.WithFields(makeArgFields(args...)).Log(levels[level], msg)
|
|
}
|
|
|
|
// Args are alternating key, val pairs
|
|
// keys must be strings
|
|
// vals can be any type, but display is implementation specific
|
|
// Emit a message and key/value pairs at a provided log level
|
|
func (l *LogrusHCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
|
|
l.log(level, msg, args...)
|
|
}
|
|
|
|
// Emit a message and key/value pairs at the TRACE level
|
|
func (l *LogrusHCLogAdapter) Trace(msg string, args ...interface{}) {
|
|
l.log(hclog.Trace, msg, args...)
|
|
}
|
|
|
|
// Emit a message and key/value pairs at the DEBUG level
|
|
func (l *LogrusHCLogAdapter) Debug(msg string, args ...interface{}) {
|
|
l.log(hclog.Debug, msg, args...)
|
|
}
|
|
|
|
// Emit a message and key/value pairs at the INFO level
|
|
func (l *LogrusHCLogAdapter) Info(msg string, args ...interface{}) {
|
|
l.log(hclog.Info, msg, args...)
|
|
}
|
|
|
|
// Emit a message and key/value pairs at the WARN level
|
|
func (l *LogrusHCLogAdapter) Warn(msg string, args ...interface{}) {
|
|
l.log(hclog.Warn, msg, args...)
|
|
}
|
|
|
|
// Emit a message and key/value pairs at the ERROR level
|
|
func (l *LogrusHCLogAdapter) Error(msg string, args ...interface{}) {
|
|
l.log(hclog.Error, msg, args...)
|
|
}
|
|
|
|
// Indicate if TRACE logs would be emitted. This and the other Is* guards
|
|
// are used to elide expensive logging code based on the current level.
|
|
func (l *LogrusHCLogAdapter) IsTrace() bool {
|
|
return l.logger.Level <= logrus.TraceLevel
|
|
}
|
|
|
|
// Indicate if DEBUG logs would be emitted. This and the other Is* guards
|
|
// are used to elide expensive logging code based on the current level.
|
|
func (l *LogrusHCLogAdapter) IsDebug() bool {
|
|
return l.logger.Level <= logrus.DebugLevel
|
|
}
|
|
|
|
// Indicate if INFO logs would be emitted. This and the other Is* guards
|
|
// are used to elide expensive logging code based on the current level.
|
|
func (l *LogrusHCLogAdapter) IsInfo() bool {
|
|
return l.logger.Level <= logrus.InfoLevel
|
|
}
|
|
|
|
// Indicate if WARN logs would be emitted. This and the other Is* guards
|
|
// are used to elide expensive logging code based on the current level.
|
|
func (l *LogrusHCLogAdapter) IsWarn() bool {
|
|
return l.logger.Level <= logrus.WarnLevel
|
|
}
|
|
|
|
// Indicate if ERROR logs would be emitted. This and the other Is* guards
|
|
// are used to elide expensive logging code based on the current level.
|
|
func (l *LogrusHCLogAdapter) IsError() bool {
|
|
return l.logger.Level <= logrus.ErrorLevel
|
|
}
|
|
|
|
// ImpliedArgs returns With key/value pairs
|
|
func (l *LogrusHCLogAdapter) ImpliedArgs() []interface{} {
|
|
// TODO: not implemented
|
|
return nil
|
|
}
|
|
|
|
// Creates a sublogger that will always have the given key/value pairs
|
|
func (l *LogrusHCLogAdapter) With(args ...interface{}) hclog.Logger {
|
|
l.entry = l.logger.WithFields(makeArgFields(args...))
|
|
return l
|
|
}
|
|
|
|
// Returns the Name of the logger
|
|
func (l *LogrusHCLogAdapter) Name() string {
|
|
// TODO: not implemented
|
|
return ""
|
|
}
|
|
|
|
// 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. That way, a major subsystem can use this to decorate all it's own logs
|
|
// without losing context.
|
|
func (l *LogrusHCLogAdapter) Named(name string) hclog.Logger {
|
|
return NewLogrusHCLogAdapter(l.logger, logrus.Fields{"name": name})
|
|
}
|
|
|
|
// 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 (l *LogrusHCLogAdapter) ResetNamed(name string) hclog.Logger {
|
|
return NewLogrusHCLogAdapter(l.logger, logrus.Fields{"name": name})
|
|
}
|
|
|
|
// Updates the level. This should affect all sub-loggers as well. If an
|
|
// implementation cannot update the level on the fly, it should no-op.
|
|
func (l *LogrusHCLogAdapter) SetLevel(level hclog.Level) {
|
|
l.logger.SetLevel(levels[level])
|
|
}
|
|
|
|
// Return a value that conforms to the stdlib log.Logger interface
|
|
func (l *LogrusHCLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
|
|
return log.New(l.StandardWriter(opts), "", log.LstdFlags)
|
|
}
|
|
|
|
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
|
func (l *LogrusHCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
|
|
return &HCLogStdlogAdapter{
|
|
log: l,
|
|
inferLevels: opts.InferLevels,
|
|
forceLevel: opts.ForceLevel,
|
|
}
|
|
}
|
|
|
|
func makeArgFields(args ...interface{}) logrus.Fields {
|
|
if len(args)%2 != 0 {
|
|
panic(fmt.Errorf("odd number of logger key-value pairs (%d): %+v", len(args), args))
|
|
}
|
|
|
|
var key string
|
|
var fields = make(logrus.Fields)
|
|
for i, arg := range args {
|
|
if i%2 == 0 {
|
|
key = arg.(string)
|
|
} else {
|
|
fields[key] = arg
|
|
}
|
|
}
|
|
return fields
|
|
}
|