// Copyright 2012-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //Package logger provides logging facilities for the NATS server package logger import ( "fmt" "log" "os" ) // Logger is the server logger type Logger struct { logger *log.Logger debug bool trace bool infoLabel string errorLabel string fatalLabel string debugLabel string traceLabel string logFile *os.File // file pointer for the file logger. } // NewStdLogger creates a logger with output directed to Stderr func NewStdLogger(time, debug, trace, colors, pid bool) *Logger { flags := 0 if time { flags = log.LstdFlags | log.Lmicroseconds } pre := "" if pid { pre = pidPrefix() } l := &Logger{ logger: log.New(os.Stderr, pre, flags), debug: debug, trace: trace, } if colors { setColoredLabelFormats(l) } else { setPlainLabelFormats(l) } return l } // NewFileLogger creates a logger with output directed to a file func NewFileLogger(filename string, time, debug, trace, pid bool) *Logger { fileflags := os.O_WRONLY | os.O_APPEND | os.O_CREATE f, err := os.OpenFile(filename, fileflags, 0660) if err != nil { log.Fatalf("error opening file: %v", err) } flags := 0 if time { flags = log.LstdFlags | log.Lmicroseconds } pre := "" if pid { pre = pidPrefix() } l := &Logger{ logger: log.New(f, pre, flags), debug: debug, trace: trace, logFile: f, } setPlainLabelFormats(l) return l } // Close implements the io.Closer interface to clean up // resources in the server's logger implementation. // Caller must ensure threadsafety. func (l *Logger) Close() error { if f := l.logFile; f != nil { l.logFile = nil return f.Close() } return nil } // Generate the pid prefix string func pidPrefix() string { return fmt.Sprintf("[%d] ", os.Getpid()) } func setPlainLabelFormats(l *Logger) { l.infoLabel = "[INF] " l.debugLabel = "[DBG] " l.errorLabel = "[ERR] " l.fatalLabel = "[FTL] " l.traceLabel = "[TRC] " } func setColoredLabelFormats(l *Logger) { colorFormat := "[\x1b[%dm%s\x1b[0m] " l.infoLabel = fmt.Sprintf(colorFormat, 32, "INF") l.debugLabel = fmt.Sprintf(colorFormat, 36, "DBG") l.errorLabel = fmt.Sprintf(colorFormat, 31, "ERR") l.fatalLabel = fmt.Sprintf(colorFormat, 31, "FTL") l.traceLabel = fmt.Sprintf(colorFormat, 33, "TRC") } // Noticef logs a notice statement func (l *Logger) Noticef(format string, v ...interface{}) { l.logger.Printf(l.infoLabel+format, v...) } // Errorf logs an error statement func (l *Logger) Errorf(format string, v ...interface{}) { l.logger.Printf(l.errorLabel+format, v...) } // Fatalf logs a fatal error func (l *Logger) Fatalf(format string, v ...interface{}) { l.logger.Fatalf(l.fatalLabel+format, v...) } // Debugf logs a debug statement func (l *Logger) Debugf(format string, v ...interface{}) { if l.debug { l.logger.Printf(l.debugLabel+format, v...) } } // Tracef logs a trace statement func (l *Logger) Tracef(format string, v ...interface{}) { if l.trace { l.logger.Printf(l.traceLabel+format, v...) } }