github.com/mailgun/holster/v4@v4.20.0/errors/context_map.go (about)

     1  package errors
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/mailgun/holster/v4/callstack"
     9  	pkgerrors "github.com/pkg/errors" //nolint:gomodguard // Legacy code requires deprecated package.
    10  )
    11  
    12  // Implements the `error` `causer` and `Contexter` interfaces
    13  type withContext struct {
    14  	context WithContext
    15  	msg     string
    16  	cause   error
    17  	stack   *callstack.CallStack
    18  }
    19  
    20  func (c *withContext) Cause() error {
    21  	return c.cause
    22  }
    23  
    24  func (c *withContext) Error() string {
    25  	if c.msg == "" {
    26  		return c.cause.Error()
    27  	}
    28  	return c.msg + ": " + c.cause.Error()
    29  }
    30  
    31  func (c *withContext) StackTrace() pkgerrors.StackTrace {
    32  	if child, ok := c.cause.(callstack.HasStackTrace); ok {
    33  		return child.StackTrace()
    34  	}
    35  	return c.stack.StackTrace()
    36  }
    37  
    38  func (c *withContext) Context() map[string]interface{} {
    39  	result := make(map[string]interface{}, len(c.context))
    40  	for key, value := range c.context {
    41  		result[key] = value
    42  	}
    43  
    44  	// downstream context values have precedence as they are closer to the cause
    45  	if child, ok := c.cause.(HasContext); ok {
    46  		downstream := child.Context()
    47  		if downstream == nil {
    48  			return result
    49  		}
    50  
    51  		for key, value := range downstream {
    52  			result[key] = value
    53  		}
    54  	}
    55  	return result
    56  }
    57  
    58  func (c *withContext) Format(s fmt.State, verb rune) {
    59  	switch verb {
    60  	case 'v':
    61  		_, _ = fmt.Fprintf(s, "%s: %+v (%s)", c.msg, c.Cause(), c.FormatFields())
    62  	case 's', 'q':
    63  		_, _ = io.WriteString(s, c.Error())
    64  	}
    65  }
    66  
    67  func (c *withContext) FormatFields() string {
    68  	var buf bytes.Buffer
    69  	var count int
    70  
    71  	for key, value := range c.context {
    72  		if count > 0 {
    73  			buf.WriteString(", ")
    74  		}
    75  		buf.WriteString(fmt.Sprintf("%+v=%+v", key, value))
    76  		count++
    77  	}
    78  	return buf.String()
    79  }
    80  
    81  func (c *withContext) Unwrap() error {
    82  	return c.cause
    83  }