@@ -1,6 +1,7 @@
11package logger
22
33import (
4+ "bytes"
45 "fmt"
56 "io"
67 "net/http"
@@ -15,6 +16,9 @@ import (
1516// AuthStatus defines the different types of auth logging that occur
1617type AuthStatus string
1718
19+// Level indicates the log level for log messages
20+type Level int
21+
1822const (
1923 // DefaultStandardLoggingFormat defines the default standard log format
2024 DefaultStandardLoggingFormat = "[{{.Timestamp}}] [{{.File}}] {{.Message}}"
@@ -38,6 +42,11 @@ const (
3842 LUTC
3943 // LstdFlags flag for initial values for the logger
4044 LstdFlags = Lshortfile
45+
46+ // DEFAULT is the default log level (effectively INFO)
47+ DEFAULT Level = iota
48+ // ERROR is for error-level logging
49+ ERROR
4150)
4251
4352// These are the containers for all values that are available as variables in the logging formats.
@@ -87,6 +96,7 @@ type Logger struct {
8796 mu sync.Mutex
8897 flag int
8998 writer io.Writer
99+ errWriter io.Writer
90100 stdEnabled bool
91101 authEnabled bool
92102 reqEnabled bool
@@ -100,7 +110,8 @@ type Logger struct {
100110// New creates a new Standarderr Logger.
101111func New(flag int) *Logger {
102112 return &Logger{
103− writer: os.Stderr,
113+ writer: os.Stdout,
114+ errWriter: os.Stderr,
104115 flag: flag,
105116 stdEnabled: true,
106117 authEnabled: true,
@@ -115,13 +126,7 @@ func New(flag int) *Logger {
115126
116127var std = New(LstdFlags)
117128
118−// Output a standard log template with a simple message.
119−// Write a final newline at the end of every message.
120−func (l *Logger) Output(calldepth int, message string) {
121− if !l.stdEnabled {
122− return
123− }
124−
129+func (l *Logger) formatLogMessage(calldepth int, message string) []byte {
125130 now := time.Now()
126131 file := "???:0"
127132
@@ -129,10 +134,8 @@ func (l *Logger) Output(calldepth int, message string) {
129134 file = l.GetFileLineString(calldepth + 1)
130135 }
131136
132− l.mu.Lock()
133− defer l.mu.Unlock()
134−
135− err := l.stdLogTemplate.Execute(l.writer, stdLogMessageData{
137+ var logBuff = new(bytes.Buffer)
138+ err := l.stdLogTemplate.Execute(logBuff, stdLogMessageData{
136139 Timestamp: FormatTimestamp(now),
137140 File: file,
138141 Message: message,
@@ -145,6 +148,26 @@ func (l *Logger) Output(calldepth int, message string) {
145148 if err != nil {
146149 panic(err)
147150 }
151+ logBuff.Write([]byte("\n"))
152+
153+ return logBuff.Bytes()
154+}
155+
156+// Output a standard log template with a simple message to default output channel.
157+// Write a final newline at the end of every message.
158+func (l *Logger) Output(lvl Level, calldepth int, message string) {
159+ l.mu.Lock()
160+ defer l.mu.Unlock()
161+ if !l.stdEnabled {
162+ return
163+ }
164+ msg := l.formatLogMessage(calldepth, message)
165+ switch lvl {
166+ case ERROR:
167+ l.errWriter.Write(msg)
168+ default:
169+ l.writer.Write(msg)
170+ }
148171}
149172
150173// PrintAuthf writes auth info to the logger. Requires an http.Request to
@@ -302,6 +325,17 @@ func (l *Logger) SetStandardEnabled(e bool) {
302325 l.stdEnabled = e
303326}
304327
328+// SetErrToInfo enables or disables error logging to error writer instead of the default.
329+func (l *Logger) SetErrToInfo(e bool) {
330+ l.mu.Lock()
331+ defer l.mu.Unlock()
332+ if e {
333+ l.errWriter = l.writer
334+ } else {
335+ l.errWriter = os.Stderr
336+ }
337+}
338+
305339// SetAuthEnabled enables or disables auth logging.
306340func (l *Logger) SetAuthEnabled(e bool) {
307341 l.mu.Lock()
@@ -371,19 +405,32 @@ func SetFlags(flag int) {
371405 std.SetFlags(flag)
372406}
373407
374−// SetOutput sets the output destination for the standard logger.
408+// SetOutput sets the output destination for the standard logger's default channel.
375409func SetOutput(w io.Writer) {
376410 std.mu.Lock()
377411 defer std.mu.Unlock()
378412 std.writer = w
379413}
380414
415+// SetErrOutput sets the output destination for the standard logger's error channel.
416+func SetErrOutput(w io.Writer) {
417+ std.mu.Lock()
418+ defer std.mu.Unlock()
419+ std.errWriter = w
420+}
421+
381422// SetStandardEnabled enables or disables standard logging for the
382423// standard logger.
383424func SetStandardEnabled(e bool) {
384425 std.SetStandardEnabled(e)
385426}
386427
428+// SetErrToInfo enables or disables error logging to output writer instead of
429+// error writer.
430+func SetErrToInfo(e bool) {
431+ std.SetErrToInfo(e)
432+}
433+
387434// SetAuthEnabled enables or disables auth logging for the standard
388435// logger.
389436func SetAuthEnabled(e bool) {
@@ -428,57 +475,75 @@ func SetReqTemplate(t string) {
428475// Print calls Output to print to the standard logger.
429476// Arguments are handled in the manner of fmt.Print.
430477func Print(v ...interface{}) {
431− std.Output(2, fmt.Sprint(v...))
478+ std.Output(DEFAULT, 2, fmt.Sprint(v...))
432479}
433480
434481// Printf calls Output to print to the standard logger.
435482// Arguments are handled in the manner of fmt.Printf.
436483func Printf(format string, v ...interface{}) {
437− std.Output(2, fmt.Sprintf(format, v...))
484+ std.Output(DEFAULT, 2, fmt.Sprintf(format, v...))
438485}
439486
440487// Println calls Output to print to the standard logger.
441488// Arguments are handled in the manner of fmt.Println.
442489func Println(v ...interface{}) {
443− std.Output(2, fmt.Sprintln(v...))
490+ std.Output(DEFAULT, 2, fmt.Sprintln(v...))
491+}
492+
493+// Error calls OutputErr to print to the standard logger's error channel.
494+// Arguments are handled in the manner of fmt.Print.
495+func Error(v ...interface{}) {
496+ std.Output(ERROR, 2, fmt.Sprint(v...))
497+}
498+
499+// Errorf calls OutputErr to print to the standard logger's error channel.
500+// Arguments are handled in the manner of fmt.Printf.
501+func Errorf(format string, v ...interface{}) {
502+ std.Output(ERROR, 2, fmt.Sprintf(format, v...))
503+}
504+
505+// Errorln calls OutputErr to print to the standard logger's error channel.
506+// Arguments are handled in the manner of fmt.Println.
507+func Errorln(v ...interface{}) {
508+ std.Output(ERROR, 2, fmt.Sprintln(v...))
444509}
445510
446511// Fatal is equivalent to Print() followed by a call to os.Exit(1).
447512func Fatal(v ...interface{}) {
448− std.Output(2, fmt.Sprint(v...))
513+ std.Output(ERROR, 2, fmt.Sprint(v...))
449514 os.Exit(1)
450515}
451516
452517// Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
453518func Fatalf(format string, v ...interface{}) {
454− std.Output(2, fmt.Sprintf(format, v...))
519+ std.Output(ERROR, 2, fmt.Sprintf(format, v...))
455520 os.Exit(1)
456521}
457522
458523// Fatalln is equivalent to Println() followed by a call to os.Exit(1).
459524func Fatalln(v ...interface{}) {
460− std.Output(2, fmt.Sprintln(v...))
525+ std.Output(ERROR, 2, fmt.Sprintln(v...))
461526 os.Exit(1)
462527}
463528
464529// Panic is equivalent to Print() followed by a call to panic().
465530func Panic(v ...interface{}) {
466531 s := fmt.Sprint(v...)
467− std.Output(2, s)
532+ std.Output(ERROR, 2, s)
468533 panic(s)
469534}
470535
471536// Panicf is equivalent to Printf() followed by a call to panic().
472537func Panicf(format string, v ...interface{}) {
473538 s := fmt.Sprintf(format, v...)
474− std.Output(2, s)
539+ std.Output(ERROR, 2, s)
475540 panic(s)
476541}
477542
478543// Panicln is equivalent to Println() followed by a call to panic().
479544func Panicln(v ...interface{}) {
480545 s := fmt.Sprintln(v...)
481− std.Output(2, s)
546+ std.Output(ERROR, 2, s)
482547 panic(s)
483548}
484549