fixes linting errors
This commit is contained in:
parent
3bc019fd4e
commit
c6819aa61d
5 changed files with 102 additions and 37 deletions
41
backend.go
41
backend.go
|
@ -1,12 +1,13 @@
|
||||||
package logging
|
package logging
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Backend is the interface that specifies the methods that a backend must
|
||||||
|
// implement
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
Write(*Record) error
|
Write(*Record) error
|
||||||
SetFormatter(*Formatter)
|
SetFormatter(*Formatter)
|
||||||
|
@ -19,6 +20,7 @@ type Backend interface {
|
||||||
// Backend to write in file-like objects
|
// Backend to write in file-like objects
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// FileBackend is a backend that writes to a file.
|
||||||
type FileBackend struct {
|
type FileBackend struct {
|
||||||
l io.Writer
|
l io.Writer
|
||||||
formatter *Formatter
|
formatter *Formatter
|
||||||
|
@ -26,7 +28,8 @@ type FileBackend struct {
|
||||||
filepath string
|
filepath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new backend to write the logs on the standard output
|
// NewStdoutBackend creates a new backend to write the logs on the standard
|
||||||
|
// output
|
||||||
func NewStdoutBackend() (b *FileBackend) {
|
func NewStdoutBackend() (b *FileBackend) {
|
||||||
b = &FileBackend{
|
b = &FileBackend{
|
||||||
l: os.Stdout,
|
l: os.Stdout,
|
||||||
|
@ -35,7 +38,7 @@ func NewStdoutBackend() (b *FileBackend) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new backend to write the logs on the error output
|
// NewStderrBackend creates a new backend to write the logs on the error output
|
||||||
func NewStderrBackend() (b *FileBackend) {
|
func NewStderrBackend() (b *FileBackend) {
|
||||||
b = &FileBackend{
|
b = &FileBackend{
|
||||||
l: os.Stderr,
|
l: os.Stderr,
|
||||||
|
@ -44,21 +47,23 @@ func NewStderrBackend() (b *FileBackend) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new backend to write the logs in a given file
|
// NewFileBackend creates a new backend to write the logs in a given file
|
||||||
func NewFileBackend(filename string) (b *FileBackend, e error) {
|
func NewFileBackend(filename string) (*FileBackend, error) {
|
||||||
filename_fd, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
fd, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) //nolint: gosec
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e = errors.New(fmt.Sprintf("Cannot open log file %s (%s)", filename, err.Error()))
|
return nil, fmt.Errorf("Cannot open log file %s: %w", filename, err)
|
||||||
}
|
}
|
||||||
b = &FileBackend{
|
|
||||||
l: filename_fd,
|
b := &FileBackend{
|
||||||
|
l: fd,
|
||||||
formatter: &defaultFormatter,
|
formatter: &defaultFormatter,
|
||||||
filepath: filename,
|
filepath: filename,
|
||||||
}
|
}
|
||||||
return
|
|
||||||
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new backend to write the logs in a given io.Writer
|
// NewIoBackend creates a new backend to write the logs in a given io.Writer
|
||||||
func NewIoBackend(buf io.Writer) (b *FileBackend) {
|
func NewIoBackend(buf io.Writer) (b *FileBackend) {
|
||||||
return &FileBackend{
|
return &FileBackend{
|
||||||
l: buf,
|
l: buf,
|
||||||
|
@ -72,18 +77,23 @@ func (b FileBackend) Write(r *Record) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLevel changes the log level of the backend
|
||||||
func (b *FileBackend) SetLevel(l Level) {
|
func (b *FileBackend) SetLevel(l Level) {
|
||||||
b.level = l
|
b.level = l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Level returns the log level set for this backend
|
||||||
func (b *FileBackend) Level() Level {
|
func (b *FileBackend) Level() Level {
|
||||||
return b.level
|
return b.level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFormatter defines the formatter for this backend
|
||||||
func (b *FileBackend) SetFormatter(f *Formatter) {
|
func (b *FileBackend) SetFormatter(f *Formatter) {
|
||||||
b.formatter = f
|
b.formatter = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reopen closes and reopens the file it writes to. It should be used after log
|
||||||
|
// rotation
|
||||||
func (b *FileBackend) Reopen() error {
|
func (b *FileBackend) Reopen() error {
|
||||||
if b.filepath == "" {
|
if b.filepath == "" {
|
||||||
return nil
|
return nil
|
||||||
|
@ -95,7 +105,7 @@ func (b *FileBackend) Reopen() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := os.OpenFile(b.filepath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
fd, err := os.OpenFile(b.filepath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) //nolint: gosec
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Cannot open log file %s: %w", b.filepath, err)
|
return fmt.Errorf("Cannot open log file %s: %w", b.filepath, err)
|
||||||
}
|
}
|
||||||
|
@ -109,24 +119,31 @@ func (b *FileBackend) Reopen() error {
|
||||||
// Noop Backend
|
// Noop Backend
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// NoopBackend does nothing and discards all log entries without writing them anywhere
|
||||||
type NoopBackend struct{}
|
type NoopBackend struct{}
|
||||||
|
|
||||||
|
// NewNoopBackend creates a noop backend
|
||||||
func NewNoopBackend() (Backend, error) {
|
func NewNoopBackend() (Backend, error) {
|
||||||
return &NoopBackend{}, nil
|
return &NoopBackend{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write is a noop
|
||||||
func (nb *NoopBackend) Write(r *Record) error {
|
func (nb *NoopBackend) Write(r *Record) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFormatter is a noop
|
||||||
func (nb *NoopBackend) SetFormatter(f *Formatter) {}
|
func (nb *NoopBackend) SetFormatter(f *Formatter) {}
|
||||||
|
|
||||||
|
// SetLevel is a noop
|
||||||
func (nb *NoopBackend) SetLevel(level Level) {}
|
func (nb *NoopBackend) SetLevel(level Level) {}
|
||||||
|
|
||||||
|
// Level always returns DefeultLevel
|
||||||
func (nb *NoopBackend) Level() Level {
|
func (nb *NoopBackend) Level() Level {
|
||||||
return DefaultLevel
|
return DefaultLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reopen is a noop
|
||||||
func (nb *NoopBackend) Reopen() error {
|
func (nb *NoopBackend) Reopen() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,16 @@ import (
|
||||||
// Syslog Backend
|
// Syslog Backend
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// SyslogBackend writes the logs to a syslog system
|
||||||
type SyslogBackend struct {
|
type SyslogBackend struct {
|
||||||
w *syslog.Writer
|
w *syslog.Writer
|
||||||
formatter *Formatter
|
formatter *Formatter
|
||||||
level Level
|
level Level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSyslogBackend initializes a new connection to a syslog server with the
|
||||||
|
// given facility.
|
||||||
|
// tag can contain an identifier for the log stream. It defaults to os.Arg[0].
|
||||||
func NewSyslogBackend(facilityName string, tag string) (Backend, error) {
|
func NewSyslogBackend(facilityName string, tag string) (Backend, error) {
|
||||||
f, err := facility(facilityName)
|
f, err := facility(facilityName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -34,37 +38,42 @@ func NewSyslogBackend(facilityName string, tag string) (Backend, error) {
|
||||||
return sb, nil
|
return sb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write sends an entry to the syslog server
|
||||||
func (sb *SyslogBackend) Write(r *Record) (err error) {
|
func (sb *SyslogBackend) Write(r *Record) (err error) {
|
||||||
text := (*sb.formatter)(r)
|
text := (*sb.formatter)(r)
|
||||||
switch r.Level {
|
switch r.Level {
|
||||||
case DEBUG:
|
case Debug:
|
||||||
err = sb.w.Debug(text)
|
err = sb.w.Debug(text)
|
||||||
case INFO:
|
case Info:
|
||||||
err = sb.w.Info(text)
|
err = sb.w.Info(text)
|
||||||
case WARNING:
|
case Warning:
|
||||||
err = sb.w.Warning(text)
|
err = sb.w.Warning(text)
|
||||||
case ERROR:
|
case Error:
|
||||||
err = sb.w.Err(text)
|
err = sb.w.Err(text)
|
||||||
case CRITICAL:
|
case Critical:
|
||||||
err = sb.w.Crit(text)
|
err = sb.w.Crit(text)
|
||||||
case FATAL:
|
case Fatal:
|
||||||
err = sb.w.Emerg(text)
|
err = sb.w.Emerg(text)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFormatter defines the formatter for this backend
|
||||||
func (sb *SyslogBackend) SetFormatter(f *Formatter) {
|
func (sb *SyslogBackend) SetFormatter(f *Formatter) {
|
||||||
sb.formatter = f
|
sb.formatter = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLevel changes the log level of the backend
|
||||||
func (sb *SyslogBackend) SetLevel(level Level) {
|
func (sb *SyslogBackend) SetLevel(level Level) {
|
||||||
sb.level = level
|
sb.level = level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Level returns the log level set for this backend
|
||||||
func (sb *SyslogBackend) Level() Level {
|
func (sb *SyslogBackend) Level() Level {
|
||||||
return sb.level
|
return sb.level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reopen is a no-op
|
||||||
func (sb *SyslogBackend) Reopen() error {
|
func (sb *SyslogBackend) Reopen() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -93,9 +102,10 @@ var facilities = map[string]syslog.Priority{
|
||||||
}
|
}
|
||||||
|
|
||||||
func facility(name string) (syslog.Priority, error) {
|
func facility(name string) (syslog.Priority, error) {
|
||||||
if p, ok := facilities[strings.ToLower(name)]; !ok {
|
p, ok := facilities[strings.ToLower(name)]
|
||||||
|
if !ok {
|
||||||
return 0, fmt.Errorf("Facility '%s' does not exist", name)
|
return 0, fmt.Errorf("Facility '%s' does not exist", name)
|
||||||
} else {
|
}
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
53
logger.go
53
logger.go
|
@ -7,35 +7,38 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Logger is a facility that writes logs to one or more backands (files,
|
||||||
|
// stdout/stderr, syslog, etc.) which can be configured independently
|
||||||
|
//
|
||||||
|
// Loggers are concurrent-safe.
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
// added to avoid concurrent writes
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
name string
|
name string
|
||||||
level Level
|
|
||||||
backends []Backend
|
backends []Backend
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLogger initializes a new Logger with no backend and with the default log level.
|
||||||
func NewLogger(name string) (l *Logger) {
|
func NewLogger(name string) (l *Logger) {
|
||||||
l = &Logger{
|
l = &Logger{
|
||||||
name: name,
|
name: name,
|
||||||
level: DEFAULT_LEVEL,
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new Backend to the logger
|
// AddBackend add a new Backend to the logger. All set backends are kept.
|
||||||
func (l *Logger) AddBackend(b Backend) {
|
func (l *Logger) AddBackend(b Backend) {
|
||||||
l.backends = append(l.backends, b)
|
l.backends = append(l.backends, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the backend list to the logger. Any existing backend will be lost
|
// SetBackend sets the backend list to the logger. Any existing backend will be lost.
|
||||||
|
// FIXME must close file backends to avoid fd leaks
|
||||||
func (l *Logger) SetBackend(b ...Backend) {
|
func (l *Logger) SetBackend(b ...Backend) {
|
||||||
l.backends = b
|
l.backends = b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLevel changes the log level of all regisered backends to the given level.
|
||||||
func (l *Logger) SetLevel(level Level) {
|
func (l *Logger) SetLevel(level Level) {
|
||||||
l.level = level
|
|
||||||
for _, backend := range l.backends {
|
for _, backend := range l.backends {
|
||||||
backend.SetLevel(level)
|
backend.SetLevel(level)
|
||||||
}
|
}
|
||||||
|
@ -51,12 +54,18 @@ func (b *buffer) Write(p []byte) (n int, err error) {
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsStdLog encapsulate the logger in an instance of lof.Logger from the
|
||||||
|
// standard library and returns it.
|
||||||
|
//
|
||||||
|
// It is there for interoperability reasons.
|
||||||
func (l *Logger) AsStdLog(level Level) *log.Logger {
|
func (l *Logger) AsStdLog(level Level) *log.Logger {
|
||||||
stdLogger := log.New(&buffer{logger: l, level: level}, "", 0)
|
stdLogger := log.New(&buffer{logger: l, level: level}, "", 0)
|
||||||
|
|
||||||
return stdLogger
|
return stdLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log sends a record containing the message `m` to the registered backends
|
||||||
|
// whose level is at least `level`
|
||||||
func (l *Logger) Log(level Level, m string) {
|
func (l *Logger) Log(level Level, m string) {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
|
@ -64,56 +73,74 @@ func (l *Logger) Log(level Level, m string) {
|
||||||
r := NewRecord(l.name, level, m)
|
r := NewRecord(l.name, level, m)
|
||||||
for _, backend := range l.backends {
|
for _, backend := range l.backends {
|
||||||
if r.Level >= backend.Level() {
|
if r.Level >= backend.Level() {
|
||||||
backend.Write(r)
|
_ = backend.Write(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug logs a message with the Debug level
|
||||||
func (l *Logger) Debug(text string) {
|
func (l *Logger) Debug(text string) {
|
||||||
l.Log(DEBUG, text)
|
l.Log(Debug, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debugf formats the message with given args and logs the result with the
|
||||||
|
// Debug level
|
||||||
func (l *Logger) Debugf(text string, args ...interface{}) {
|
func (l *Logger) Debugf(text string, args ...interface{}) {
|
||||||
l.Debug(fmt.Sprintf(text, args...))
|
l.Debug(fmt.Sprintf(text, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info logs a message with the Info level
|
||||||
func (l *Logger) Info(text string) {
|
func (l *Logger) Info(text string) {
|
||||||
l.Log(INFO, text)
|
l.Log(Info, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Infof formats the message with given args and logs the result with the
|
||||||
|
// Info level
|
||||||
func (l *Logger) Infof(text string, args ...interface{}) {
|
func (l *Logger) Infof(text string, args ...interface{}) {
|
||||||
l.Info(fmt.Sprintf(text, args...))
|
l.Info(fmt.Sprintf(text, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning logs a message with the Warning level
|
||||||
func (l *Logger) Warning(text string) {
|
func (l *Logger) Warning(text string) {
|
||||||
l.Log(WARNING, text)
|
l.Log(Warning, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warningf formats the message with given args and logs the result with the
|
||||||
|
// Warning level
|
||||||
func (l *Logger) Warningf(text string, args ...interface{}) {
|
func (l *Logger) Warningf(text string, args ...interface{}) {
|
||||||
l.Warning(fmt.Sprintf(text, args...))
|
l.Warning(fmt.Sprintf(text, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error logs a message with the Error level
|
||||||
func (l *Logger) Error(text string) {
|
func (l *Logger) Error(text string) {
|
||||||
l.Log(ERROR, text)
|
l.Log(Error, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Errorf formats the message with given args and logs the result with the
|
||||||
|
// Error level
|
||||||
func (l *Logger) Errorf(text string, args ...interface{}) {
|
func (l *Logger) Errorf(text string, args ...interface{}) {
|
||||||
l.Error(fmt.Sprintf(text, args...))
|
l.Error(fmt.Sprintf(text, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Critical logs a message with the Critical level
|
||||||
func (l *Logger) Critical(text string) {
|
func (l *Logger) Critical(text string) {
|
||||||
l.Log(CRITICAL, text)
|
l.Log(Critical, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Criticalf formats the message with given args and logs the result with the
|
||||||
|
// Critical level
|
||||||
func (l *Logger) Criticalf(text string, args ...interface{}) {
|
func (l *Logger) Criticalf(text string, args ...interface{}) {
|
||||||
l.Critical(fmt.Sprintf(text, args...))
|
l.Critical(fmt.Sprintf(text, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fatal logs a message with the Fatal level
|
||||||
func (l *Logger) Fatal(text string) {
|
func (l *Logger) Fatal(text string) {
|
||||||
l.Log(DEBUG, text)
|
l.Log(Debug, text)
|
||||||
os.Exit(100)
|
os.Exit(100)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fatalf formats the message with given args and logs the result with the
|
||||||
|
// Fatal level
|
||||||
func (l *Logger) Fatalf(text string, args ...interface{}) {
|
func (l *Logger) Fatalf(text string, args ...interface{}) {
|
||||||
l.Fatal(fmt.Sprintf(text, args...))
|
l.Fatal(fmt.Sprintf(text, args...))
|
||||||
}
|
}
|
||||||
|
|
12
logging.go
12
logging.go
|
@ -1,7 +1,6 @@
|
||||||
package logging
|
package logging
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -12,8 +11,10 @@ var (
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Level is the type of log levels
|
||||||
type Level byte
|
type Level byte
|
||||||
|
|
||||||
|
//nolint: golint
|
||||||
const (
|
const (
|
||||||
Debug Level = iota
|
Debug Level = iota
|
||||||
Info
|
Info
|
||||||
|
@ -26,21 +27,28 @@ const (
|
||||||
|
|
||||||
var levelNames = [6]string{"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "FATAL"}
|
var levelNames = [6]string{"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "FATAL"}
|
||||||
|
|
||||||
|
// Name returns the name of the log level
|
||||||
func (l Level) Name() string {
|
func (l Level) Name() string {
|
||||||
return levelNames[l]
|
return levelNames[l]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LevelByName creates a log level given its name. It returns an error if the
|
||||||
|
// name does not match any level.
|
||||||
func LevelByName(l string) (Level, error) {
|
func LevelByName(l string) (Level, error) {
|
||||||
for pos, name := range levelNames {
|
for pos, name := range levelNames {
|
||||||
if name == l {
|
if name == l {
|
||||||
return Level(pos), nil
|
return Level(pos), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DEBUG, errors.New(fmt.Sprintf("Invalid log level %s", l))
|
return Debug, fmt.Errorf("Invalid log level %s", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Formatter is the types of the functions that can be used to format a log
|
||||||
|
// entry. They take a pointer to a record and return a formatted string.
|
||||||
type Formatter func(*Record) string
|
type Formatter func(*Record) string
|
||||||
|
|
||||||
|
// GetLogger returns a logger given its name. if the logger does not exist, it
|
||||||
|
// initializes one with the defaults (it logs to stdout with level debug)
|
||||||
func GetLogger(name string) (l *Logger) {
|
func GetLogger(name string) (l *Logger) {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Record contains the data to be logged. It is passed to a formatter to
|
||||||
|
// generate the logged message
|
||||||
type Record struct {
|
type Record struct {
|
||||||
Logger string
|
Logger string
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
|
@ -11,6 +13,7 @@ type Record struct {
|
||||||
Message string
|
Message string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRecord creates a new record, setting its timestamp to time.Now()
|
||||||
func NewRecord(name string, l Level, m string) (r *Record) {
|
func NewRecord(name string, l Level, m string) (r *Record) {
|
||||||
r = &Record{
|
r = &Record{
|
||||||
Logger: name,
|
Logger: name,
|
||||||
|
|
Loading…
Reference in a new issue