func (l *loggingT) printWithFileLine(s severity, file string, line int, args ...interface{}) {
	buf := l.formatHeader(s, file, line)
	fmt.Fprint(buf, args...)
	if buf.Bytes()[buf.Len()-1] != '\n' {
		buf.WriteByte('\n')
	}
	l.output(s, buf, file, line)
}
printWithFileLine behaves like print but uses the provided file and line number.  If
alsoLogToStderr is true, the log message always appears on standard error
package flog
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	stdLog "log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)
type severity int32  
const (
	debugLog severity = iota
	infoLog
	warningLog
	errorLog
	criticalLog
	fatalLog
	numSeverity = 6
)
const severityChar = "VIWECF"
var (
	pid = os.Getpid()
)
var severityName = []string{
	debugLog:    "DEBUG",
	infoLog:     "INFO",
	warningLog:  "WARNING",
	errorLog:    "ERROR",
	criticalLog: "CRITICAL",
	fatalLog:    "FATAL",
}
func (s *severity) get() severity {
	return severity(atomic.LoadInt32((*int32)(s)))
}
func (s *severity) set(val severity) {
	atomic.StoreInt32((*int32)(s), int32(val))
}
func (s *severity) String() string {
	return strconv.FormatInt(int64(*s), 10)
}
func severityByName(s string) (severity, bool) {
	s = strings.ToUpper(s)
	for i, name := range severityName {
		if name == s {
			return severity(i), true
		}
	}
	return 0, false
}
type OutputStats struct {
	lines int64
	bytes int64
}
func (s *OutputStats) Lines() int64 {
	return atomic.LoadInt64(&s.lines)
}
func (s *OutputStats) Bytes() int64 {
	return atomic.LoadInt64(&s.bytes)
}
var Stats struct {
	Debug, Info, Warning, Error, Critical OutputStats
}
var severityStats = [numSeverity]*OutputStats{
	debugLog:    &Stats.Debug,
	infoLog:     &Stats.Info,
	warningLog:  &Stats.Warning,
	errorLog:    &Stats.Error,
	criticalLog: &Stats.Critical,
}
type Level int32
func (l *Level) get() Level {
	return Level(atomic.LoadInt32((*int32)(l)))
}
func (l *Level) set(val Level) {
	atomic.StoreInt32((*int32)(l), int32(val))
}
func (l *Level) String() string {
	return strconv.FormatInt(int64(*l), 10)
}
func (l *Level) Get() interface{} {
	return *l
}
func (l *Level) Set(value string) error {
	v, err := strconv.Atoi(value)
	if err != nil {
		return err
	}
	logging.mu.Lock()
	defer logging.mu.Unlock()
	logging.setVState(Level(v), logging.vmodule.filter, false)
	return nil
}
type moduleSpec struct {
	filter []modulePat
}
type modulePat struct {
	pattern string
	literal bool  
	level   Level
}
func (m *modulePat) match(file string) bool {
	if m.literal {
		return file == m.pattern
	}
	match, _ := filepath.Match(m.pattern, file)
	return match
}
func (m *moduleSpec) String() string {
	logging.mu.Lock()
	defer logging.mu.Unlock()
	var b bytes.Buffer
	for i, f := range m.filter {
		if i > 0 {
			b.WriteRune(',')
		}
		fmt.Fprintf(&b, "%s=%d", f.pattern, f.level)
	}
	return b.String()
}
func (m *moduleSpec) Get() interface{} {
	return nil
}
var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N")
func (m *moduleSpec) Set(value string) error {
	var filter []modulePat
	for _, pat := range strings.Split(value, ",") {
		if len(pat) == 0 {
			continue
		}
		patLev := strings.Split(pat, "=")
		if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
			return errVmoduleSyntax
		}
		pattern := patLev[0]
		v, err := strconv.Atoi(patLev[1])
		if err != nil {
			return errors.New("syntax error: expect comma-separated list of filename=N")
		}
		if v < 0 {
			return errors.New("negative value for vmodule level")
		}
		if v == 0 {
			continue  
		}
		filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
	}
	logging.mu.Lock()
	defer logging.mu.Unlock()
	logging.setVState(logging.verbosity, filter, true)
	return nil
}
func isLiteral(pattern string) bool {
	return !strings.ContainsAny(pattern, `\*?[]`)
}
type traceLocation struct {
	file string
	line int
}
func (t *traceLocation) isSet() bool {
	return t.line > 0
}
func (t *traceLocation) match(file string, line int) bool {
	if t.line != line {
		return false
	}
	if i := strings.LastIndex(file, "/"); i >= 0 {
		file = file[i+1:]
	}
	return t.file == file
}
func (t *traceLocation) String() string {
	logging.mu.Lock()
	defer logging.mu.Unlock()
	return fmt.Sprintf("%s:%d", t.file, t.line)
}
func (t *traceLocation) Get() interface{} {
	return nil
}
var errTraceSyntax = errors.New("syntax error: expect file.go:234")
func (t *traceLocation) Set(value string) error {
	if value == "" {
		logging.mu.Lock()
		defer logging.mu.Unlock()
		t.line = 0
		t.file = ""
		return nil
	}
	fields := strings.Split(value, ":")
	if len(fields) != 2 {
		return errTraceSyntax
	}
	file, line := fields[0], fields[1]
	if !strings.Contains(file, ".") {
		return errTraceSyntax
	}
	v, err := strconv.Atoi(line)
	if err != nil {
		return errTraceSyntax
	}
	if v <= 0 {
		return errors.New("negative or zero value for level")
	}
	logging.mu.Lock()
	defer logging.mu.Unlock()
	t.line = v
	t.file = file
	return nil
}
type loggingT struct {
	freeList *sync.Pool
	mu sync.Mutex
	pcs [1]uintptr
	vmap map[uintptr]Level
	filterLength int32
	traceLocation traceLocation
	vmodule   moduleSpec  
	verbosity Level       
	out io.Writer
}
type buffer struct {
	bytes.Buffer
	tmp [64]byte  
}
var logging loggingT
func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) {
	logging.verbosity.set(0)
	atomic.StoreInt32(&logging.filterLength, 0)
	if setFilter {
		logging.vmodule.filter = filter
		logging.vmap = make(map[uintptr]Level)
	}
	atomic.StoreInt32(&logging.filterLength, int32(len(filter)))
	logging.verbosity.set(verbosity)
}
func (l *loggingT) getBuffer() *buffer {
	b := l.freeList.Get().(*buffer)
	b.Reset()
	return b
}
func (l *loggingT) putBuffer(b *buffer) {
	if b.Len() >= 256 {
		return
	}
	l.freeList.Put(b)
}
var timeNow = time.Now  
func (l *loggingT) header(s severity, depth int) (*buffer, string, int) {
	_, file, line, ok := runtime.Caller(3 + depth)
	if !ok {
		file = "???"
		line = 1
	} else {
		slash := strings.LastIndex(file, "/")
		if slash >= 0 {
			file = file[slash+1:]
		}
	}
	return l.formatHeader(s, file, line), file, line
}
func (l *loggingT) formatHeader(s severity, file string, line int) *buffer {
	now := timeNow()
	if line < 0 {
		line = 0  
	}
	if s > fatalLog {
		s = infoLog  
	}
	buf := l.getBuffer()
	_, month, day := now.Date()
	hour, minute, second := now.Clock()
	buf.tmp[0] = severityChar[s]
	buf.twoDigits(1, int(month))
	buf.twoDigits(3, day)
	buf.tmp[5] = ' '
	buf.twoDigits(6, hour)
	buf.tmp[8] = ':'
	buf.twoDigits(9, minute)
	buf.tmp[11] = ':'
	buf.twoDigits(12, second)
	buf.tmp[14] = '.'
	buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
	buf.tmp[21] = ' '
	buf.nDigits(7, 22, pid, ' ')  
	buf.tmp[29] = ' '
	buf.Write(buf.tmp[:30])
	buf.WriteString(file)
	buf.tmp[0] = ':'
	n := buf.someDigits(1, line)
	buf.tmp[n+1] = ']'
	buf.tmp[n+2] = ' '
	buf.Write(buf.tmp[:n+3])
	return buf
}
const digits = "0123456789"
func (buf *buffer) twoDigits(i, d int) {
	buf.tmp[i+1] = digits[d%10]
	d /= 10
	buf.tmp[i] = digits[d%10]
}
func (buf *buffer) nDigits(n, i, d int, pad byte) {
	j := n - 1
	for ; j >= 0 && d > 0; j-- {
		buf.tmp[i+j] = digits[d%10]
		d /= 10
	}
	for ; j >= 0; j-- {
		buf.tmp[i+j] = pad
	}
}
func (buf *buffer) someDigits(i, d int) int {
	j := len(buf.tmp)
	for {
		j--
		buf.tmp[j] = digits[d%10]
		d /= 10
		if d == 0 {
			break
		}
	}
	return copy(buf.tmp[i:], buf.tmp[j:])
}
func (l *loggingT) println(s severity, args ...interface{}) {
	buf, file, line := l.header(s, 0)
	fmt.Fprintln(buf, args...)
	l.output(s, buf, file, line)
}
func (l *loggingT) print(s severity, args ...interface{}) {
	l.printDepth(s, 1, args...)
}
func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) {
	buf, file, line := l.header(s, depth)
	fmt.Fprint(buf, args...)
	if buf.Bytes()[buf.Len()-1] != '\n' {
		buf.WriteByte('\n')
	}
	l.output(s, buf, file, line)
}
func (l *loggingT) printf(s severity, format string, args ...interface{}) {
	buf, file, line := l.header(s, 0)
	fmt.Fprintf(buf, format, args...)
	if buf.Bytes()[buf.Len()-1] != '\n' {
		buf.WriteByte('\n')
	}
	l.output(s, buf, file, line)
}