func levelFromString(s string) logLevel {
	switch s {
	case "debug":
		return levelDebug
	case "info":
		return levelInfo
	case "error":
		return levelError
	default:
		return levelInfo
	}
}
levelFromString returns logLevel for given string. It
return `levelInfo` as a default.
package log
import (
	"fmt"
	"os"
)
type output struct {
	std     *os.File
	message string
}
var outputCh = make(chan output, 10000)
var global *Logger
func Init(level string, json bool) {
	global = New(level, json)
}
func Debug(msg Message) {
	global.printf(levelDebug, msg, os.Stdout)
}
func Info(msg Message) {
	global.printf(levelInfo, msg, os.Stdout)
}
func Error(msg Message) {
	global.printf(levelError, msg, os.Stderr)
}
func Close() {
	close(outputCh)
	<-global.donech
}
type Logger struct {
	donech chan struct{}
	json   bool
	level  logLevel
}
func New(level string, json bool) *Logger {
	logLevel := levelFromString(level)
	logger := &Logger{
		donech: make(chan struct{}),
		json:   json,
		level:  logLevel,
	}
	go logger.out()
	return logger
}
func (l *Logger) printf(level logLevel, message Message, std *os.File) {
	if level < l.level {
		return
	}
	if l.json {
		outputCh <- output{
			message: message.JSON(),
			std:     std,
		}
	} else {
		outputCh <- output{
			message: fmt.Sprintf("%v%v", level, message.String()),
			std:     std,
		}
	}
}
func (l *Logger) out() {
	defer close(l.donech)
	for output := range outputCh {
		_, _ = fmt.Fprintln(output.std, output.message)
	}
}
type logLevel int
const (
	levelDebug logLevel = iota
	levelInfo
	levelError
)
func (l logLevel) String() string {
	switch l {
	case levelInfo:
		return ""
	case levelError:
		return "ERROR "
	case levelDebug:
		return "DEBUG "
	default:
		return "UNKNOWN "
	}
}