func (e *TraceErr) DebugReport() string {
	var buf bytes.Buffer
	err := reportTemplate.Execute(&buf, errorReport{
		OrigErrType:    fmt.Sprintf("%T", e.Err),
		OrigErrMessage: e.Err.Error(),
		Fields:         e.Fields,
		StackTrace:     e.Traces.String(),
		UserMessage:    e.UserMessage(),
	})
	if err != nil {
		return fmt.Sprint("error generating debug report: ", err.Error())
	}
	return buf.String()
}
DebugReport returns developer-friendly error report
package trace
import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"strings"
	"sync/atomic"
	"github.com/gravitational/trace/internal"
	"golang.org/x/net/context"
)
var debug int32
func SetDebug(enabled bool) {
	if enabled {
		atomic.StoreInt32(&debug, 1)
	} else {
		atomic.StoreInt32(&debug, 0)
	}
}
func IsDebug() bool {
	return atomic.LoadInt32(&debug) == 1
}
func Wrap(err error, args ...interface{}) Error {
	if err == nil {
		return nil
	}
	var trace Error
	if traceErr, ok := err.(Error); ok {
		trace = traceErr
	} else {
		trace = newTrace(err, 2)
	}
	if len(args) > 0 {
		trace = trace.AddUserMessage(args[0], args[1:]...)
	}
	return trace
}
func Unwrap(err error) error {
	if err, ok := err.(ErrorWrapper); ok {
		return err.OrigError()
	}
	return err
}
type UserMessager interface {
	UserMessage() string
}
type ErrorWrapper interface {
	OrigError() error
}
type DebugReporter interface {
	DebugReport() string
}
func UserMessage(err error) string {
	if err == nil {
		return ""
	}
	if wrap, ok := err.(UserMessager); ok {
		return wrap.UserMessage()
	}
	return err.Error()
}
func UserMessageWithFields(err error) string {
	if err == nil {
		return ""
	}
	if wrap, ok := err.(Error); ok {
		if len(wrap.GetFields()) == 0 {
			return wrap.UserMessage()
		}
		var kvps []string
		for k, v := range wrap.GetFields() {
			kvps = append(kvps, fmt.Sprintf("%v=%q", k, v))
		}
		return fmt.Sprintf("%v %v", strings.Join(kvps, " "), wrap.UserMessage())
	}
	return err.Error()
}
func DebugReport(err error) string {
	if err == nil {
		return ""
	}
	if reporter, ok := err.(DebugReporter); ok {
		return reporter.DebugReport()
	}
	return err.Error()
}
func GetFields(err error) map[string]interface{} {
	if err == nil {
		return map[string]interface{}{}
	}
	if wrap, ok := err.(Error); ok {
		return wrap.GetFields()
	}
	return map[string]interface{}{}
}
func WrapWithMessage(err error, message interface{}, args ...interface{}) Error {
	var trace Error
	if traceErr, ok := err.(Error); ok {
		trace = traceErr
	} else {
		trace = newTrace(err, 2)
	}
	trace.AddUserMessage(message, args...)
	return trace
}
func Errorf(format string, args ...interface{}) (err error) {
	err = fmt.Errorf(format, args...)
	return newTrace(err, 2)
}
func Fatalf(format string, args ...interface{}) error {
	if IsDebug() {
		panic(fmt.Sprintf(format, args...))
	} else {
		return Errorf(format, args...)
	}
}
func newTrace(err error, depth int) *TraceErr {
	traces := internal.CaptureTraces(depth)
	return &TraceErr{Err: err, Traces: traces}
}
type Traces = internal.Traces
type Trace = internal.Trace
func (r *TraceErr) MarshalJSON() ([]byte, error) {
	if r == nil {
		return nil, nil
	}
	type marshalableError TraceErr
	err := marshalableError(*r)
	err.Err = &RawTrace{Message: r.Err.Error()}
	return json.Marshal(err)
}
type TraceErr struct {
	Err error `json:"error"`
	Traces `json:"traces,omitempty"`
	Message string `json:"message,omitempty"`
	Messages []string `json:"messages,omitempty"`
	Fields map[string]interface{} `json:"fields,omitempty"`
}
type Fields map[string]interface{}
func (r *RawTrace) Error() string {
	return r.Message
}
type RawTrace struct {
	Err json.RawMessage `json:"error,omitempty"`
	Traces `json:"traces,omitempty"`
	Message string `json:"message,omitempty"`
	Messages []string `json:"messages,omitempty"`
	Fields map[string]interface{} `json:"fields,omitempty"`
}
func (e *TraceErr) AddUserMessage(formatArg interface{}, rest ...interface{}) *TraceErr {
	newMessage := fmt.Sprintf(fmt.Sprintf("%v", formatArg), rest...)
	e.Messages = append(e.Messages, newMessage)
	return e
}
func (e *TraceErr) AddFields(fields map[string]interface{}) *TraceErr {
	if e.Fields == nil {
		e.Fields = make(map[string]interface{}, len(fields))
	}
	for k, v := range fields {
		e.Fields[k] = v
	}
	return e
}
func (e *TraceErr) AddField(k string, v interface{}) *TraceErr {
	if e.Fields == nil {
		e.Fields = make(map[string]interface{}, 1)
	}
	e.Fields[k] = v
	return e
}
func (e *TraceErr) UserMessage() string {
	if len(e.Messages) > 0 {
		var buf bytes.Buffer
		fmt.Fprintln(&buf, e.Messages[len(e.Messages)-1])
		index, indent := len(e.Messages)-1, 1
		for ; index > 0; index, indent = index-1, indent+1 {
			fmt.Fprintf(&buf, "%v%v\n", strings.Repeat("\t", indent), e.Messages[index-1])
		}
		fmt.Fprintf(&buf, "%v%v", strings.Repeat("\t", indent), UserMessage(e.Err))
		return buf.String()
	}
	if e.Message != "" {
		return e.Message
	}
	return UserMessage(e.Err)
}