func Errorln(v ...interface{}) {
	std.Output(ERROR, 2, fmt.Sprintln(v...))
}
Errorln calls OutputErr to print to the standard logger's error channel.
Arguments are handled in the manner of fmt.Println.
package logger
import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"runtime"
	"sync"
	"text/template"
	"time"
	middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
	requestutil "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests/util"
)
type AuthStatus string
type Level int
const (
	DefaultStandardLoggingFormat = "[{{.Timestamp}}] [{{.File}}] {{.Message}}"
	DefaultAuthLoggingFormat = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] [{{.Status}}] {{.Message}}"
	DefaultRequestLoggingFormat = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] {{.Host}} {{.RequestMethod}} {{.Upstream}} {{.RequestURI}} {{.Protocol}} {{.UserAgent}} {{.StatusCode}} {{.ResponseSize}} {{.RequestDuration}}"
	AuthSuccess AuthStatus = "AuthSuccess"
	AuthFailure AuthStatus = "AuthFailure"
	AuthError AuthStatus = "AuthError"
	Llongfile = 1 << iota
	Lshortfile
	LUTC
	LstdFlags = Lshortfile
	DEFAULT Level = iota
	ERROR
)
type stdLogMessageData struct {
	Timestamp,
	File,
	Message string
}
type authLogMessageData struct {
	Client,
	Host,
	Protocol,
	RequestID,
	RequestMethod,
	Timestamp,
	UserAgent,
	Username,
	Status,
	Message string
}
type reqLogMessageData struct {
	Client,
	Host,
	Protocol,
	RequestID,
	RequestDuration,
	RequestMethod,
	RequestURI,
	ResponseSize,
	StatusCode,
	Timestamp,
	Upstream,
	UserAgent,
	Username string
}
type GetClientFunc = func(r *http.Request) string
type Logger struct {
	mu             sync.Mutex
	flag           int
	writer         io.Writer
	errWriter      io.Writer
	stdEnabled     bool
	authEnabled    bool
	reqEnabled     bool
	getClientFunc  GetClientFunc
	excludePaths   map[string]struct{}
	stdLogTemplate *template.Template
	authTemplate   *template.Template
	reqTemplate    *template.Template
}
func New(flag int) *Logger {
	return &Logger{
		writer:         os.Stdout,
		errWriter:      os.Stderr,
		flag:           flag,
		stdEnabled:     true,
		authEnabled:    true,
		reqEnabled:     true,
		getClientFunc:  func(r *http.Request) string { return r.RemoteAddr },
		excludePaths:   nil,
		stdLogTemplate: template.Must(template.New("std-log").Parse(DefaultStandardLoggingFormat)),
		authTemplate:   template.Must(template.New("auth-log").Parse(DefaultAuthLoggingFormat)),
		reqTemplate:    template.Must(template.New("req-log").Parse(DefaultRequestLoggingFormat)),
	}
}
var std = New(LstdFlags)
func (l *Logger) formatLogMessage(calldepth int, message string) []byte {
	now := time.Now()
	file := "???:0"
	if l.flag&(Lshortfile|Llongfile) != 0 {
		file = l.GetFileLineString(calldepth + 1)
	}
	var logBuff = new(bytes.Buffer)
	err := l.stdLogTemplate.Execute(logBuff, stdLogMessageData{
		Timestamp: FormatTimestamp(now),
		File:      file,
		Message:   message,
	})
	if err != nil {
		panic(err)
	}
	_, err = logBuff.Write([]byte("\n"))
	if err != nil {
		panic(err)
	}
	return logBuff.Bytes()
}
func (l *Logger) Output(lvl Level, calldepth int, message string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	if !l.stdEnabled {
		return
	}
	msg := l.formatLogMessage(calldepth+1, message)
	var err error
	switch lvl {
	case ERROR:
		_, err = l.errWriter.Write(msg)
	default:
		_, err = l.writer.Write(msg)
	}
	if err != nil {
		panic(err)
	}
}
func (l *Logger) PrintAuthf(username string, req *http.Request, status AuthStatus, format string, a ...interface{}) {
	if !l.authEnabled {
		return
	}
	now := time.Now()
	if username == "" {
		username = "-"
	}
	client := l.getClientFunc(req)
	l.mu.Lock()
	defer l.mu.Unlock()
	scope := middlewareapi.GetRequestScope(req)
	err := l.authTemplate.Execute(l.writer, authLogMessageData{
		Client:        client,
		Host:          requestutil.GetRequestHost(req),
		Protocol:      req.Proto,
		RequestID:     scope.RequestID,
		RequestMethod: req.Method,
		Timestamp:     FormatTimestamp(now),
		UserAgent:     fmt.Sprintf("%q", req.UserAgent()),
		Username:      username,
		Status:        string(status),
		Message:       fmt.Sprintf(format, a...),
	})
	if err != nil {
		panic(err)
	}
	_, err = l.writer.Write([]byte("\n"))
	if err != nil {
		panic(err)
	}
}
func (l *Logger) PrintReq(username, upstream string, req *http.Request, url url.URL, ts time.Time, status int, size int) {
	if !l.reqEnabled {
		return
	}
	if _, ok := l.excludePaths[url.Path]; ok {
		return
	}
	duration := float64(time.Since(ts)) / float64(time.Second)
	if username == "" {
		username = "-"
	}
	if upstream == "" {
		upstream = "-"
	}
	if url.User != nil && username == "-" {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}
	client := l.getClientFunc(req)
	l.mu.Lock()
	defer l.mu.Unlock()
	scope := middlewareapi.GetRequestScope(req)
	err := l.reqTemplate.Execute(l.writer, reqLogMessageData{
		Client:          client,
		Host:            requestutil.GetRequestHost(req),
		Protocol:        req.Proto,
		RequestID:       scope.RequestID,
		RequestDuration: fmt.Sprintf("%0.3f", duration),
		RequestMethod:   req.Method,
		RequestURI:      fmt.Sprintf("%q", url.RequestURI()),
		ResponseSize:    fmt.Sprintf("%d", size),
		StatusCode:      fmt.Sprintf("%d", status),
		Timestamp:       FormatTimestamp(ts),
		Upstream:        upstream,
		UserAgent:       fmt.Sprintf("%q", req.UserAgent()),
		Username:        username,
	})
	if err != nil {
		panic(err)
	}
	_, err = l.writer.Write([]byte("\n"))
	if err != nil {
		panic(err)
	}
}
func (l *Logger) GetFileLineString(calldepth int) string {
	var file string
	var line int
	var ok bool
	_, file, line, ok = runtime.Caller(calldepth)
	if !ok {
		file = "???"
		line = 0
	}
	if l.flag&Lshortfile != 0 {
		short := file
		for i := len(file) - 1; i > 0; i-- {
			if file[i] == '/' {
				short = file[i+1:]
				break
			}
		}
		file = short
	}
	return fmt.Sprintf("%s:%d", file, line)
}
func (l *Logger) FormatTimestamp(ts time.Time) string {
	if l.flag&LUTC != 0 {
		ts = ts.UTC()
	}
	return ts.Format("2006/01/02 15:04:05")
}
func (l *Logger) Flags() int {
	l.mu.Lock()
	defer l.mu.Unlock()
	return l.flag
}
func (l *Logger) SetFlags(flag int) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.flag = flag
}
func (l *Logger) SetStandardEnabled(e bool) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.stdEnabled = e
}
func (l *Logger) SetErrToInfo(e bool) {
	l.mu.Lock()
	defer l.mu.Unlock()
	if e {
		l.errWriter = l.writer
	} else {
		l.errWriter = os.Stderr
	}
}
func (l *Logger) SetAuthEnabled(e bool) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.authEnabled = e
}
func (l *Logger) SetReqEnabled(e bool) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.reqEnabled = e
}
func (l *Logger) SetGetClientFunc(f GetClientFunc) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.getClientFunc = f
}
func (l *Logger) SetExcludePaths(s []string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.excludePaths = make(map[string]struct{})
	for _, p := range s {
		l.excludePaths[p] = struct{}{}
	}
}
func (l *Logger) SetStandardTemplate(t string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.stdLogTemplate = template.Must(template.New("std-log").Parse(t))
}
func (l *Logger) SetAuthTemplate(t string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.authTemplate = template.Must(template.New("auth-log").Parse(t))
}
func (l *Logger) SetReqTemplate(t string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.reqTemplate = template.Must(template.New("req-log").Parse(t))
}
func FormatTimestamp(ts time.Time) string {
	return std.FormatTimestamp(ts)
}
func Flags() int {
	return std.Flags()
}
func SetFlags(flag int) {
	std.SetFlags(flag)
}
func SetOutput(w io.Writer) {
	std.mu.Lock()
	defer std.mu.Unlock()
	std.writer = w
}
func SetErrOutput(w io.Writer) {
	std.mu.Lock()
	defer std.mu.Unlock()
	std.errWriter = w
}
func SetStandardEnabled(e bool) {
	std.SetStandardEnabled(e)
}
func SetErrToInfo(e bool) {
	std.SetErrToInfo(e)
}
func SetAuthEnabled(e bool) {
	std.SetAuthEnabled(e)
}
func SetReqEnabled(e bool) {
	std.SetReqEnabled(e)
}
func SetGetClientFunc(f GetClientFunc) {
	std.SetGetClientFunc(f)
}
func SetExcludePaths(s []string) {
	std.SetExcludePaths(s)
}
func SetStandardTemplate(t string) {
	std.SetStandardTemplate(t)
}
func SetAuthTemplate(t string) {
	std.SetAuthTemplate(t)
}
func SetReqTemplate(t string) {
	std.SetReqTemplate(t)
}
func Print(v ...interface{}) {
	std.Output(DEFAULT, 2, fmt.Sprint(v...))
}
func Printf(format string, v ...interface{}) {
	std.Output(DEFAULT, 2, fmt.Sprintf(format, v...))
}
func Println(v ...interface{}) {
	std.Output(DEFAULT, 2, fmt.Sprintln(v...))
}
func Error(v ...interface{}) {
	std.Output(ERROR, 2, fmt.Sprint(v...))
}
func Errorf(format string, v ...interface{}) {
	std.Output(ERROR, 2, fmt.Sprintf(format, v...))
}