133 lines
4.1 KiB
Go
133 lines
4.1 KiB
Go
// Licensed to Elasticsearch B.V. under one or more contributor
|
|
// license agreements. See the NOTICE file distributed with
|
|
// this work for additional information regarding copyright
|
|
// ownership. Elasticsearch B.V. licenses this file to you 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 internal
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/pkg/errors"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
type ecsError struct {
|
|
error
|
|
}
|
|
|
|
func NewError(err error) zapcore.ObjectMarshaler {
|
|
return ecsError{err}
|
|
}
|
|
|
|
func (err ecsError) MarshalLogObject(enc zapcore.ObjectEncoder) error {
|
|
enc.AddString("message", err.Error())
|
|
if e, ok := err.error.(stackTracer); ok {
|
|
enc.AddString("stack_trace", fmt.Sprintf("%+v", e.StackTrace()))
|
|
}
|
|
|
|
// TODO(simitt): support for improved error handling
|
|
// https://github.com/elastic/ecs-logging-go-zap/issues/8
|
|
if e, ok := err.error.(errorGroup); ok {
|
|
if errorCause := e.Errors(); len(errorCause) > 0 {
|
|
return enc.AddArray("cause", errArray(errorCause))
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// interface used by github.com/pkg/errors
|
|
type stackTracer interface {
|
|
StackTrace() errors.StackTrace
|
|
}
|
|
|
|
// *** code below this line is mostly copied from github.com/zapcore/core.go
|
|
// and is subject to the license below***
|
|
|
|
// Copyright (c) 2017 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.
|
|
|
|
type errorGroup interface {
|
|
// Provides read-only access to the underlying list of errors, preferably
|
|
// without causing any allocs.
|
|
Errors() []error
|
|
}
|
|
|
|
// Note that errArry and errArrayElem are very similar to the version
|
|
// implemented in the top-level error.go file. We can't re-use this because
|
|
// that would require exporting errArray as part of the zapcore API.
|
|
|
|
// Encodes a list of errors using the standard error encoding logic.
|
|
type errArray []error
|
|
|
|
func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
|
for i := range errs {
|
|
if errs[i] == nil {
|
|
continue
|
|
}
|
|
|
|
el := newErrArrayElem(errs[i])
|
|
arr.AppendObject(el)
|
|
el.Free()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var _errArrayElemPool = sync.Pool{New: func() interface{} {
|
|
return &errArrayElem{}
|
|
}}
|
|
|
|
// Encodes any error into a {"error": ...} re-using the same errors logic.
|
|
//
|
|
// May be passed in place of an array to build a single-element array.
|
|
type errArrayElem struct{ err error }
|
|
|
|
func newErrArrayElem(err error) *errArrayElem {
|
|
e := _errArrayElemPool.Get().(*errArrayElem)
|
|
e.err = err
|
|
return e
|
|
}
|
|
|
|
func (e *errArrayElem) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
|
return arr.AppendObject(e)
|
|
}
|
|
|
|
func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) error {
|
|
return ecsError{e.err}.MarshalLogObject(enc)
|
|
}
|
|
|
|
func (e *errArrayElem) Free() {
|
|
e.err = nil
|
|
_errArrayElemPool.Put(e)
|
|
}
|