mirror of https://github.com/knative/pkg.git
115 lines
3.4 KiB
Go
115 lines
3.4 KiB
Go
// Copyright 2020 Knative Authors
|
|
// Copyright (c) 2016 Uber Technologies, Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
package logging
|
|
|
|
import (
|
|
"github.com/davecgh/go-spew/spew"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
|
|
"go.uber.org/multierr"
|
|
)
|
|
|
|
const (
|
|
_oddNumberErrMsg = "Ignored key without a value."
|
|
_nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys."
|
|
)
|
|
|
|
var spewConfig *spew.ConfigState
|
|
|
|
func init() {
|
|
spewConfig = spew.NewDefaultConfig()
|
|
spewConfig.DisableCapacities = true
|
|
spewConfig.SortKeys = true
|
|
spewConfig.SpewKeys = true
|
|
spewConfig.ContinueOnMethod = true
|
|
}
|
|
|
|
func (o *TLogger) handleFields(args []interface{}) []zap.Field {
|
|
if len(args) == 0 {
|
|
return nil
|
|
}
|
|
s := o.l.Sugar()
|
|
|
|
// Allocate enough space for the worst case; if users pass only structured
|
|
// fields, we shouldn't penalize them with extra allocations.
|
|
fields := make([]zap.Field, 0, len(args))
|
|
var invalid invalidPairs
|
|
|
|
for i := 0; i < len(args); {
|
|
// This is a strongly-typed field. Consume it and move on.
|
|
if f, ok := args[i].(zap.Field); ok {
|
|
fields = append(fields, f)
|
|
i++
|
|
continue
|
|
}
|
|
|
|
// Make sure this element isn't a dangling key.
|
|
if i == len(args)-1 {
|
|
s.DPanic(_oddNumberErrMsg, zap.Any("ignored", args[i]))
|
|
break
|
|
}
|
|
|
|
// Consume this value and the next, treating them as a key-value pair. If the
|
|
// key isn't a string, add this pair to the slice of invalid pairs.
|
|
key, val := args[i], args[i+1]
|
|
if keyStr, ok := key.(string); !ok {
|
|
// Subsequent errors are likely, so allocate once up front.
|
|
if cap(invalid) == 0 {
|
|
invalid = make(invalidPairs, 0, len(args)/2)
|
|
}
|
|
invalid = append(invalid, invalidPair{i, key, val})
|
|
} else {
|
|
fields = append(fields, zap.Any(keyStr, val))
|
|
}
|
|
i += 2
|
|
}
|
|
|
|
// If we encountered any invalid key-value pairs, log an error.
|
|
if len(invalid) > 0 {
|
|
s.DPanic(_nonStringKeyErrMsg, zap.Array("invalid", invalid), zap.String("all_input", spew.Sprintf("%#+v", args)))
|
|
}
|
|
return fields
|
|
}
|
|
|
|
type invalidPair struct {
|
|
position int
|
|
key, value interface{}
|
|
}
|
|
|
|
func (p invalidPair) MarshalLogObject(enc zapcore.ObjectEncoder) error {
|
|
enc.AddInt64("position", int64(p.position))
|
|
zap.Any("key", p.key).AddTo(enc)
|
|
zap.Any("value", p.value).AddTo(enc)
|
|
return nil
|
|
}
|
|
|
|
type invalidPairs []invalidPair
|
|
|
|
func (ps invalidPairs) MarshalLogArray(enc zapcore.ArrayEncoder) error {
|
|
var err error
|
|
for i := range ps {
|
|
err = multierr.Append(err, enc.AppendObject(ps[i]))
|
|
}
|
|
return err
|
|
}
|