func (z *intLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger {
	if opts == nil {
		opts = &StandardLoggerOptions{}
	}
	return log.New(z.StandardWriter(opts), "", 0)
}
Create a *log.Logger that will send it's data through this Logger. This
allows packages that expect to be using the standard library log to actually
use this logger.
package hclog
import (
	"bufio"
	"bytes"
	"encoding"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"reflect"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)
var (
	_levelToBracket = map[Level]string{
		Debug: "[DEBUG]",
		Trace: "[TRACE]",
		Info:  "[INFO] ",
		Warn:  "[WARN] ",
		Error: "[ERROR]",
	}
)
func New(opts *LoggerOptions) Logger {
	if opts == nil {
		opts = &LoggerOptions{}
	}
	output := opts.Output
	if output == nil {
		output = os.Stderr
	}
	level := opts.Level
	if level == NoLevel {
		level = DefaultLevel
	}
	mtx := opts.Mutex
	if mtx == nil {
		mtx = new(sync.Mutex)
	}
	ret := &intLogger{
		m:          mtx,
		json:       opts.JSONFormat,
		caller:     opts.IncludeLocation,
		name:       opts.Name,
		timeFormat: TimeFormat,
		w:          bufio.NewWriter(output),
		level:      new(int32),
	}
	if opts.TimeFormat != "" {
		ret.timeFormat = opts.TimeFormat
	}
	atomic.StoreInt32(ret.level, int32(level))
	return ret
}
type intLogger struct {
	json       bool
	caller     bool
	name       string
	timeFormat string
	m     *sync.Mutex
	w     *bufio.Writer
	level *int32
	implied []interface{}
}
var _ Logger = &intLogger{}
const TimeFormat = "2006-01-02T15:04:05.000Z0700"
func (z *intLogger) Log(level Level, msg string, args ...interface{}) {
	if level < Level(atomic.LoadInt32(z.level)) {
		return
	}
	t := time.Now()
	z.m.Lock()
	defer z.m.Unlock()
	if z.json {
		z.logJson(t, level, msg, args...)
	} else {
		z.log(t, level, msg, args...)
	}
	z.w.Flush()
}
func trimCallerPath(path string) string {
	idx := strings.LastIndexByte(path, '/')
	if idx == -1 {
		return path
	}
	idx = strings.LastIndexByte(path[:idx], '/')
	if idx == -1 {
		return path
	}
	return path[idx+1:]
}
func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{}) {
	z.w.WriteString(t.Format(z.timeFormat))
	z.w.WriteByte(' ')
	s, ok := _levelToBracket[level]
	if ok {
		z.w.WriteString(s)
	} else {
		z.w.WriteString("[?????]")
	}
	if z.caller {
		if _, file, line, ok := runtime.Caller(3); ok {
			z.w.WriteByte(' ')
			z.w.WriteString(trimCallerPath(file))
			z.w.WriteByte(':')
			z.w.WriteString(strconv.Itoa(line))
			z.w.WriteByte(':')
		}
	}
	z.w.WriteByte(' ')
	if z.name != "" {
		z.w.WriteString(z.name)
		z.w.WriteString(": ")
	}
	z.w.WriteString(msg)
	args = append(z.implied, args...)
	var stacktrace CapturedStacktrace
	if args != nil && len(args) > 0 {
		if len(args)%2 != 0 {
			cs, ok := args[len(args)-1].(CapturedStacktrace)
			if ok {
				args = args[:len(args)-1]
				stacktrace = cs
			} else {
				args = append(args, "<unknown>")
			}
		}
		z.w.WriteByte(':')
	FOR:
		for i := 0; i < len(args); i = i + 2 {
			var (
				val string
				raw bool
			)
			switch st := args[i+1].(type) {
			case string:
				val = st
			case int:
				val = strconv.FormatInt(int64(st), 10)
			case int64:
				val = strconv.FormatInt(int64(st), 10)
			case int32:
				val = strconv.FormatInt(int64(st), 10)
			case int16:
				val = strconv.FormatInt(int64(st), 10)
			case int8:
				val = strconv.FormatInt(int64(st), 10)
			case uint:
				val = strconv.FormatUint(uint64(st), 10)
			case uint64:
				val = strconv.FormatUint(uint64(st), 10)
			case uint32:
				val = strconv.FormatUint(uint64(st), 10)
			case uint16:
				val = strconv.FormatUint(uint64(st), 10)
			case uint8:
				val = strconv.FormatUint(uint64(st), 10)
			case CapturedStacktrace:
				stacktrace = st
				continue FOR
			case Format:
				val = fmt.Sprintf(st[0].(string), st[1:]...)
			default:
				v := reflect.ValueOf(st)
				if v.Kind() == reflect.Slice {
					val = z.renderSlice(v)
					raw = true
				} else {
					val = fmt.Sprintf("%v", st)
				}
			}
			z.w.WriteByte(' ')
			z.w.WriteString(args[i].(string))
			z.w.WriteByte('=')
			if !raw && strings.ContainsAny(val, " \t\n\r") {
				z.w.WriteByte('"')
				z.w.WriteString(val)
				z.w.WriteByte('"')
			} else {
				z.w.WriteString(val)
			}
		}
	}
	z.w.WriteString("\n")
	if stacktrace != "" {
		z.w.WriteString(string(stacktrace))
	}
}
func (z *intLogger) renderSlice(v reflect.Value) string {
	var buf bytes.Buffer
	buf.WriteRune('[')
	for i := 0; i < v.Len(); i++ {
		if i > 0 {
			buf.WriteString(", ")
		}
		sv := v.Index(i)
		var val string
		switch sv.Kind() {
		case reflect.String:
			val = sv.String()
		case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
			val = strconv.FormatInt(sv.Int(), 10)
		case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			val = strconv.FormatUint(sv.Uint(), 10)
		default:
			val = fmt.Sprintf("%v", sv.Interface())
		}
		if strings.ContainsAny(val, " \t\n\r") {
			buf.WriteByte('"')
			buf.WriteString(val)
			buf.WriteByte('"')
		} else {
			buf.WriteString(val)
		}
	}
	buf.WriteRune(']')
	return buf.String()
}
func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interface{}) {
	vals := map[string]interface{}{
		"@message":   msg,
		"@timestamp": t.Format("2006-01-02T15:04:05.000000Z07:00"),
	}
	var levelStr string
	switch level {
	case Error:
		levelStr = "error"
	case Warn:
		levelStr = "warn"
	case Info:
		levelStr = "info"
	case Debug:
		levelStr = "debug"
	case Trace:
		levelStr = "trace"
	default:
		levelStr = "all"
	}
	vals["@level"] = levelStr
	if z.name != "" {
		vals["@module"] = z.name
	}
	if z.caller {
		if _, file, line, ok := runtime.Caller(3); ok {
			vals["@caller"] = fmt.Sprintf("%s:%d", file, line)
		}
	}
	args = append(z.implied, args...)
	if args != nil && len(args) > 0 {
		if len(args)%2 != 0 {
			cs, ok := args[len(args)-1].(CapturedStacktrace)
			if ok {
				args = args[:len(args)-1]
				vals["stacktrace"] = cs
			} else {
				args = append(args, "<unknown>")
			}
		}
		for i := 0; i < len(args); i = i + 2 {
			if _, ok := args[i].(string); !ok {
				continue
			}
			val := args[i+1]
			switch sv := val.(type) {
			case error:
				switch sv.(type) {
				case json.Marshaler, encoding.TextMarshaler:
				default:
					val = sv.Error()
				}
			case Format:
				val = fmt.Sprintf(sv[0].(string), sv[1:]...)
			}
			vals[args[i].(string)] = val
		}
	}
	err := json.NewEncoder(z.w).Encode(vals)
	if err != nil {
		panic(err)
	}
}
func (z *intLogger) Debug(msg string, args ...interface{}) {
	z.Log(Debug, msg, args...)
}
func (z *intLogger) Trace(msg string, args ...interface{}) {
	z.Log(Trace, msg, args...)
}
func (z *intLogger) Info(msg string, args ...interface{}) {
	z.Log(Info, msg, args...)
}
func (z *intLogger) Warn(msg string, args ...interface{}) {
	z.Log(Warn, msg, args...)
}
func (z *intLogger) Error(msg string, args ...interface{}) {
	z.Log(Error, msg, args...)
}
func (z *intLogger) IsTrace() bool {
	return Level(atomic.LoadInt32(z.level)) == Trace
}
func (z *intLogger) IsDebug() bool {
	return Level(atomic.LoadInt32(z.level)) <= Debug
}
func (z *intLogger) IsInfo() bool {
	return Level(atomic.LoadInt32(z.level)) <= Info
}
func (z *intLogger) IsWarn() bool {
	return Level(atomic.LoadInt32(z.level)) <= Warn
}
func (z *intLogger) IsError() bool {
	return Level(atomic.LoadInt32(z.level)) <= Error
}
func (z *intLogger) With(args ...interface{}) Logger {
	if len(args)%2 != 0 {
		panic("With() call requires paired arguments")
	}
	var nz intLogger = *z
	result := make(map[string]interface{}, len(z.implied)+len(args))
	keys := make([]string, 0, len(z.implied)+len(args))
	for i := 0; i < len(z.implied); i += 2 {
		key := z.implied[i].(string)
		keys = append(keys, key)
		result[key] = z.implied[i+1]
	}
	for i := 0; i < len(args); i += 2 {
		key := args[i].(string)
		_, exists := result[key]
		if !exists {
			keys = append(keys, key)
		}
		result[key] = args[i+1]
	}
	sort.Strings(keys)
	nz.implied = make([]interface{}, 0, len(z.implied)+len(args))
	for _, k := range keys {
		nz.implied = append(nz.implied, k)
		nz.implied = append(nz.implied, result[k])
	}
	return &nz
}
func (z *intLogger) Named(name string) Logger {
	var nz intLogger = *z
	if nz.name != "" {
		nz.name = nz.name + "." + name
	} else {
		nz.name = name
	}
	return &nz
}
func (z *intLogger) ResetNamed(name string) Logger {
	var nz intLogger = *z
	nz.name = name
	return &nz
}
func (z *intLogger) SetLevel(level Level) {
	atomic.StoreInt32(z.level, int32(level))
}