logging: github.com/FogCreek/logging Index | Files

package logging

import "github.com/FogCreek/logging"

Package logging implements tag based logging.

Logging is generally broken into two pieces: what to log and where to log it. These values are often specified by named loggers with formatters that specify the format of log messages, a level that specifies how much to log and some sort of target to specify where to log. The fog creek logging package for Go takes a slightly different approach based on our experience with real world logging.

A default logger provides an easy path to logging. The logging package provides methods to directly log ot the default logger without accessing it

logging.Info("information message")

is the same as

logging.DefaultLogger().Info("information message")

You can also use named loggers, to scope log levels to packages.

logging.GetLogger("my logger").Infof("%v", aVar)

Tags provide a way to set levels across concepts, perpendicular to logger names.

tags := ["network", "server"]
logging.DebugWithTags(tags, "tagged message")

Levels are used to filter logging. There are five levels:

* VERBOSE
* DEBUG
* INFO
* WARN
* ERROR

By default INFO messages and above are allowed. Each logger can have a level. A method to set the default level is available, and actually sets the level on the default logger.

logging.SetDefaultLogLevel(logging.INFO)

is equivalent to

logging.DefaultLogger().SetLogLevel(logging.INFO)

Levels can also be set by tag, which overrides the loggers level. By default loggers use the default loggers level.

Loggers have a four methods for each log level, one for formatted messages, and one for just a simple array of values, plus a version of each of these with tags.

ErrorWithTagsf(tags []string, fmt string, args ...interface{})
ErrorWithTags(tags []string, args ...interface{})
Errorf(fmt string, args ...interface{})
Error(args ...interface{})

WarnWithTagsf(tags []string, fmt string, args ...interface{})
WarnWithTags(tags []string, args ...interface{})
Warnf(fmt string, args ...interface{})
Warn(args ...interface{})

InfoWithTagsf(tags []string, fmt string, args ...interface{})
InfoWithTags(tags []string, args ...interface{})
Infof(fmt string, args ...interface{})
Info(args ...interface{})

DebugWithTagsf(tags []string, fmt string, args ...interface{})
DebugWithTags(tags []string, args ...interface{})
Debugf(fmt string, args ...interface{})
Debug(args ...interface{})

Verbose is special, since it rarely should/would be called without formatting.

VerboseWithTagsf(tags []string, fmt string, args ...interface{})
Verbosef(fmt string, args ...interface{})

Log messages are formatted by a format function. Which can be set per logger, by default, loggers copy the default loggers format.

Logging ultimately goes through one or more appenders to get the messages to the console, a file or wherever. All loggers share the same appenders - but appenders can be associated with a level which is unrelated to tags.

Each logger has an optional buffer, that will be flushed whenever its level/tags change. This buffer contains un-passed messages. So that it is possible to configure the system to capture messages and replay them latter. Replayed messages are tagged and have a double time stamp.

To use go vet with this package you can use the form:

go tool vet -printfuncs "ErrorWithTagsf,Errorf,WarnWithTagsf,Warnf,InfoWithTagsf,Infof,DebugWithTagsf,Debugf" <package>

Package logging for Go takes a slightly different approach based on our experience with real world logging.

A default logger provides an easy path to logging. Named loggers provide a way to set levels by package. Tags provide a way to set levels across concepts, perpendicular to logger names. Default log levels and default tag levels are independent of the default logger. All loggers share the same appenders - but appenders can be associated with a level which is unrelated to tags. Each logger has an optional buffer, that will be flushd whenever its level/tags change. This buffer contains un-passed messages. So that it is possible to configure the system to capture messages and replay them later. Replayed messages are tagged and have a double time stamp. A default appender is initialized to send log messages to stderr.

Index

Package Files

appender.go doc.go formatter.go golog_adapter.go logging.go loglevel.go rollingFileAppender.go syslog_appender.go

func AdaptStandardLogging Uses

func AdaptStandardLogging(level LogLevel, tags []string)

AdaptStandardLogging points the standard logging to fog creek logging using the provided level and tags. The default will be info with no tags.

func AddAppender Uses

func AddAppender(appender LogAppender)

AddAppender adds a new global appender for use by all loggers. Levels can be used to restrict logging to specific appenders.

func AddTag Uses

func AddTag(tags []string, newTag string) []string

AddTag creates a new array and adds a string to it. This insures that no slices are shared for tags.

func CaptureLoggingErrors Uses

func CaptureLoggingErrors(errs chan<- error)

CaptureLoggingErrors allows the logging user to provide a channel for capturing logging errors. Any error during the logging process, like an appender failing will be sent to this channel. By default there is no error channel. Logging will not block when writting to the error channel so make sure the channel is big enough to capture errors

func CheckLevel Uses

func CheckLevel(l LogLevel, tags []string) bool

CheckLevel tests the default logger for its permissions

func ClearAppenders Uses

func ClearAppenders()

ClearAppenders removes all of the global appenders, mainly used during configuration. Will pause and restart logging

func ClearLoggers Uses

func ClearLoggers()

ClearLoggers is provided so that an application can completely reset its logging configuration, for example on a SIGHUP

func Debug Uses

func Debug(args ...interface{})

Debug logs an DEBUG level message with no tags and provided arguments joined into a string. Uses the default logger.

func DebugWithTags Uses

func DebugWithTags(tags []string, args ...interface{})

DebugWithTags logs an DEBUG level message with the provided tags and provided arguments joined into a string. Uses the default logger.

func DebugWithTagsf Uses

func DebugWithTagsf(tags []string, fmt string, args ...interface{})

DebugWithTagsf logs an DEBUG level message with the provided tags and formatted string. Uses the default logger.

func Debugf Uses

func Debugf(fmt string, args ...interface{})

Debugf logs an DEBUG level message with the no tags and formatted string. Uses the default logger.

func DisableVerboseLogging Uses

func DisableVerboseLogging()

DisableVerboseLogging by default verbose logging is ignored, use this method to turn off verbose logging if you have enabled it

func EnableVerboseLogging Uses

func EnableVerboseLogging()

EnableVerboseLogging by default verbose logging is ignored, use this method to allow verbose logging

func Error Uses

func Error(args ...interface{})

Error logs an ERROR level message with no tags and provided arguments joined into a string. Uses the default logger.

func ErrorWithTags Uses

func ErrorWithTags(tags []string, args ...interface{})

ErrorWithTags logs an ERROR level message with the provided tags and provided arguments joined into a string. Uses the default logger.

func ErrorWithTagsf Uses

func ErrorWithTagsf(tags []string, fmt string, args ...interface{})

ErrorWithTagsf logs an ERROR level message with the provided tags and formatted string. Uses the default logger.

func Errorf Uses

func Errorf(fmt string, args ...interface{})

Errorf logs an ERROR level message with the no tags and formatted string. Uses the default logger.

func Info Uses

func Info(args ...interface{})

Info logs an INFO level message with no tags and provided arguments joined into a string. Uses the default logger.

func InfoWithTags Uses

func InfoWithTags(tags []string, args ...interface{})

InfoWithTags logs an INFO level message with the provided tags and provided arguments joined into a string. Uses the default logger.

func InfoWithTagsf Uses

func InfoWithTagsf(tags []string, fmt string, args ...interface{})

InfoWithTagsf logs an INFO level message with the provided tags and formatted string. Uses the default logger.

func Infof Uses

func Infof(fmt string, args ...interface{})

Infof logs an INFO level message with the no tags and formatted string. Uses the default logger.

func PauseLogging Uses

func PauseLogging()

PauseLogging stops all logging from being processed. Pause will not wait for all log messages to be processed

func RestartLogging Uses

func RestartLogging()

RestartLogging starts messages logging again

func SetDefaultBufferLength Uses

func SetDefaultBufferLength(length int)

SetDefaultBufferLength sets the buffer length for the default logger, new loggers will use this length. Existing loggers with buffers are not affected, those with buffers are not effected.

func SetDefaultFormatter Uses

func SetDefaultFormatter(formatter LogFormatter)

SetDefaultFormatter sets the default formatter used by appenders that don't have their own

func SetDefaultLogLevel Uses

func SetDefaultLogLevel(l LogLevel)

SetDefaultLogLevel sets the default loggers log level, flushes all buffers in case messages are cleared for logging

func SetDefaultTagLogLevel Uses

func SetDefaultTagLogLevel(tag string, l LogLevel)

SetDefaultTagLogLevel sets the default loggers level for the specified tag, flushes all buffers in case messages are cleared for logging..

func StopLogging Uses

func StopLogging()

StopLogging can only be called once, and completely stops the logging process

func VerboseWithTagsf Uses

func VerboseWithTagsf(tags []string, fmt string, args ...interface{})

VerboseWithTagsf logs an VERBOSE level message with the provided tags and formatted string. Uses the default logger. Verbose messages are not buffered

func Verbosef Uses

func Verbosef(fmt string, args ...interface{})

Verbosef logs an VERBOSE level message with the no tags and formatted string. Uses the default logger. Verbose messages are not buffered

func WaitForIncoming Uses

func WaitForIncoming()

WaitForIncoming should be used in tests or system shutdowns to make sure that all of the log messages pushed into the logging channel are processed and appended appropriately.

func Warn Uses

func Warn(args ...interface{})

Warn logs an WARN level message with no tags and provided arguments joined into a string. Uses the default logger.

func WarnWithTags Uses

func WarnWithTags(tags []string, args ...interface{})

WarnWithTags logs an WARN level message with the provided tags and provided arguments joined into a string. Uses the default logger.

func WarnWithTagsf Uses

func WarnWithTagsf(tags []string, fmt string, args ...interface{})

WarnWithTagsf logs an WARN level message with the provided tags and formatted string. Uses the default logger.

func Warnf Uses

func Warnf(fmt string, args ...interface{})

Warnf logs an WARN level message with the no tags and formatted string. Uses the default logger.

type BaseLogAppender Uses

type BaseLogAppender struct {
    // contains filtered or unexported fields
}

BaseLogAppender provides a simple struct for building log appenders.

func (*BaseLogAppender) CheckLevel Uses

func (appender *BaseLogAppender) CheckLevel(l LogLevel) bool

CheckLevel tests the level in the BaseLogAppender struct

func (*BaseLogAppender) SetFormatter Uses

func (appender *BaseLogAppender) SetFormatter(formatter LogFormatter)

SetFormatter stores the formatting function in the BaseLogAppender struct

func (*BaseLogAppender) SetLevel Uses

func (appender *BaseLogAppender) SetLevel(l LogLevel)

SetLevel stores the level in the BaseLogAppender struct

type ClosableAppender Uses

type ClosableAppender interface {
    LogAppender
    io.Closer
}

ClosableAppender defines an optional single method for appenders that need to be closed when they will not be used anymore. An example is a file appender.

type ConsoleAppender Uses

type ConsoleAppender struct {
    BaseLogAppender
    // contains filtered or unexported fields
}

ConsoleAppender can be used to write log records to standard err or standard out.

func NewStdErrAppender Uses

func NewStdErrAppender() *ConsoleAppender

NewStdErrAppender creates a console appender configured to write to standard err.

func NewStdOutAppender Uses

func NewStdOutAppender() *ConsoleAppender

NewStdOutAppender creates a console appender configured to write to standard out.

func (*ConsoleAppender) Log Uses

func (appender *ConsoleAppender) Log(record *LogRecord) error

Log writes the record, if its level passes the appenders level to stderr or stdout

type ErrorAppender Uses

type ErrorAppender struct {
    NullAppender
}

ErrorAppender is provided for testing and will generate an error when asked to log a message, it will also maintain a count

func NewErrorAppender Uses

func NewErrorAppender() *ErrorAppender

NewErrorAppender creates an ErrorAppender

func (*ErrorAppender) Log Uses

func (appender *ErrorAppender) Log(record *LogRecord) error

Log adds to the count and returns an error

type LogAppender Uses

type LogAppender interface {
    //Log takes a record and should append it
    Log(record *LogRecord) error
    //SetLevel should remember the level assigned to this appender and check
    //it to filter incoming records
    SetLevel(l LogLevel)
    //SetFormatter should remember the formatting function that this
    //appender should use to generate strings from LogRecords
    SetFormatter(formatter LogFormatter)
}

LogAppender is used to push log records to a destination like a file

type LogFormat Uses

type LogFormat string

LogFormat is the name of a known formatting function.

const FULL LogFormat = "full"

FULL formats messages with the date to ms accuracy, the level, tags and message. Replayed messages have a special field added.

const MINIMAL LogFormat = "minimal"

MINIMAL describes a formatter that just prints the message, replays are not indicated

const MINIMALTAGGED LogFormat = "minimaltagged"

MINIMALTAGGED describes a formatter that just prints the level, tags and message, replays are not indicated

const SIMPLE LogFormat = "simple"

SIMPLE describes a formatter that just prints the date, level and message, replays are not indicated

func FormatFromString Uses

func FormatFromString(formatName string) LogFormat

FormatFromString converts a string name to a LogFormat. Valid arguemnts include full, simple, minimaltagged and minimal. An unknown string will be treated like simple.

type LogFormatter Uses

type LogFormatter func(level LogLevel, tags []string, message string, t time.Time, original time.Time) string

LogFormatter is a function type used to convert a log record into a string. Original time is provided times when the formatter has to construct a replayed message from the buffer

func GetFormatter Uses

func GetFormatter(formatName LogFormat) LogFormatter

GetFormatter returns the function associated with a named format.

type LogLevel Uses

type LogLevel uint8

LogLevel is the type used to indicate the importance of a logging request

const (
    //DEFAULT is the default log level, loggers with default level will use the default loggers level
    DEFAULT LogLevel = iota
    //VERBOSE is the wordiest log level, useful for very big text output that may
    //be the last result during testing or debugging
    VERBOSE
    //DEBUG is generally the lowest level used when testing
    DEBUG
    //INFO is used for generally helpful but not important messages
    INFO
    //WARN is provided for warnings that do not represent a major program error
    WARN
    //ERROR is the highest log level and should only be used for exceptional conditions
    ERROR
)

func LevelFromString Uses

func LevelFromString(str string) LogLevel

LevelFromString converts a level in any case to a LogLevel, valid values are error, warning, warn, info, informative, debug and verbose.

func (LogLevel) String Uses

func (level LogLevel) String() string

String converts a log level to an upper case string

type LogRecord Uses

type LogRecord struct {
    //Time is the time that the log record is being appended, can be
    //different from Original if the record was buffered
    Time time.Time
    //Original is the original time for the log record
    Original time.Time
    //Level is the level the record was logged at
    Level LogLevel
    //Tags are the custom tags assigned to the record when it was logged
    Tags []string
    //Message is the actual log message
    Message string
    //Logger is the logger associated with this log record, if any
    Logger *LoggerImpl
}

LogRecord is the type used in the logging buffer

func NewLogRecord Uses

func NewLogRecord(logger *LoggerImpl, level LogLevel, tags []string, message string, time time.Time, original time.Time) *LogRecord

NewLogRecord creates a log record object

type Logger Uses

type Logger interface {
    ErrorWithTagsf(tags []string, fmt string, args ...interface{})
    ErrorWithTags(tags []string, args ...interface{})
    Errorf(fmt string, args ...interface{})
    Error(args ...interface{})

    WarnWithTagsf(tags []string, fmt string, args ...interface{})
    WarnWithTags(tags []string, args ...interface{})
    Warnf(fmt string, args ...interface{})
    Warn(args ...interface{})

    InfoWithTagsf(tags []string, fmt string, args ...interface{})
    InfoWithTags(tags []string, args ...interface{})
    Infof(fmt string, args ...interface{})
    Info(args ...interface{})

    DebugWithTagsf(tags []string, fmt string, args ...interface{})
    DebugWithTags(tags []string, args ...interface{})
    Debugf(fmt string, args ...interface{})
    Debug(args ...interface{})

    VerboseWithTagsf(tags []string, fmt string, args ...interface{})
    Verbosef(fmt string, args ...interface{})

    SetLogLevel(l LogLevel)
    SetTagLevel(tag string, l LogLevel)
    CheckLevel(l LogLevel, tags []string) bool

    SetBufferLength(length int)
}

Logger is the interface for the objects that are the target of logging messages. Logging methods imply a level. For example, Info() implies a level of LogLevel.INFO.

func DefaultLogger Uses

func DefaultLogger() Logger

DefaultLogger returns a logger that can be used when a named logger isn't required

func GetLogger Uses

func GetLogger(name string) Logger

GetLogger returns a named logger, creating it if necessary. The logger will have the default settings. By default the logger will use the DefaultLoggers level and tag levels

type LoggerImpl Uses

type LoggerImpl struct {
    // contains filtered or unexported fields
}

LoggerImpl stores the data for a logger. A Logger maintains its own level, tag levels and buffer. Each logger is named.

func (*LoggerImpl) CheckLevel Uses

func (logger *LoggerImpl) CheckLevel(l LogLevel, tags []string) bool

CheckLevel checks tags, then check the level on this , or the default level

func (*LoggerImpl) Debug Uses

func (logger *LoggerImpl) Debug(args ...interface{})

Debug logs an DEBUG level message with no tags and provided arguments joined into a string.

func (*LoggerImpl) DebugWithTags Uses

func (logger *LoggerImpl) DebugWithTags(tags []string, args ...interface{})

DebugWithTags logs an DEBUG level message with the provided tags and provided arguments joined into a string.

func (*LoggerImpl) DebugWithTagsf Uses

func (logger *LoggerImpl) DebugWithTagsf(tags []string, fmt string, args ...interface{})

DebugWithTagsf logs an DEBUG level message with the provided tags and formatted string.

func (*LoggerImpl) Debugf Uses

func (logger *LoggerImpl) Debugf(fmt string, args ...interface{})

Debugf logs an DEBUG level message with the no tags and formatted string.

func (*LoggerImpl) Error Uses

func (logger *LoggerImpl) Error(args ...interface{})

Error logs an ERROR level message with no tags and provided arguments joined into a string.

func (*LoggerImpl) ErrorWithTags Uses

func (logger *LoggerImpl) ErrorWithTags(tags []string, args ...interface{})

ErrorWithTags logs an ERROR level message with the provided tags and provided arguments joined into a string.

func (*LoggerImpl) ErrorWithTagsf Uses

func (logger *LoggerImpl) ErrorWithTagsf(tags []string, fmt string, args ...interface{})

ErrorWithTagsf logs an ERROR level message with the provided tags and formatted string.

func (*LoggerImpl) Errorf Uses

func (logger *LoggerImpl) Errorf(fmt string, args ...interface{})

Errorf logs an ERROR level message with the no tags and formatted string.

func (*LoggerImpl) Info Uses

func (logger *LoggerImpl) Info(args ...interface{})

Info logs an INFO level message with no tags and provided arguments joined into a string.

func (*LoggerImpl) InfoWithTags Uses

func (logger *LoggerImpl) InfoWithTags(tags []string, args ...interface{})

InfoWithTags logs an INFO level message with the provided tags and provided arguments joined into a string.

func (*LoggerImpl) InfoWithTagsf Uses

func (logger *LoggerImpl) InfoWithTagsf(tags []string, fmt string, args ...interface{})

InfoWithTagsf logs an INFO level message with the provided tags and formatted string.

func (*LoggerImpl) Infof Uses

func (logger *LoggerImpl) Infof(fmt string, args ...interface{})

Infof logs an INFO level message with the no tags and formatted string.

func (*LoggerImpl) SetBufferLength Uses

func (logger *LoggerImpl) SetBufferLength(length int)

SetBufferLength clears the buffer and creates a new one of the specified length.

func (*LoggerImpl) SetLogLevel Uses

func (logger *LoggerImpl) SetLogLevel(l LogLevel)

SetLogLevel sets the level of messages allowed for a logger. This level can be overriden for specific tags using SetTagLevel. Changing the level for a Logger flushes its buffer in case messages are now free to be logged. This means that buffered messages might be printed out of order, but will be formatted to indicate this.

func (*LoggerImpl) SetTagLevel Uses

func (logger *LoggerImpl) SetTagLevel(tag string, l LogLevel)

SetTagLevel assigns a log level to a specific tag. This level can override the general level for a logger allowing specific log messages to slip through and be appended to the logs

func (*LoggerImpl) VerboseWithTagsf Uses

func (logger *LoggerImpl) VerboseWithTagsf(tags []string, fmt string, args ...interface{})

VerboseWithTagsf logs an VERBOSE level message with the provided tags and formatted string. Verbose messages are not buffered

func (*LoggerImpl) Verbosef Uses

func (logger *LoggerImpl) Verbosef(fmt string, args ...interface{})

Verbosef logs an VERBOSE level message with the no tags and formatted string. Verbose messages are not buffered

func (*LoggerImpl) Warn Uses

func (logger *LoggerImpl) Warn(args ...interface{})

Warn logs an WARN level message with no tags and provided arguments joined into a string.

func (*LoggerImpl) WarnWithTags Uses

func (logger *LoggerImpl) WarnWithTags(tags []string, args ...interface{})

WarnWithTags logs an WARN level message with the provided tags and provided arguments joined into a string.

func (*LoggerImpl) WarnWithTagsf Uses

func (logger *LoggerImpl) WarnWithTagsf(tags []string, fmt string, args ...interface{})

WarnWithTagsf logs an WARN level message with the provided tags and formatted string.

func (*LoggerImpl) Warnf Uses

func (logger *LoggerImpl) Warnf(fmt string, args ...interface{})

Warnf logs an WARN level message with the no tags and formatted string.

type MemoryAppender Uses

type MemoryAppender struct {
    BaseLogAppender
    //LoggedMesssages is the list of messages that have been logged to this appender
    LoggedMessages []string
}

MemoryAppender is useful for testing and keeps a list of logged messages

func NewMemoryAppender Uses

func NewMemoryAppender() *MemoryAppender

NewMemoryAppender creates a new empty memory appender

func (*MemoryAppender) GetLoggedMessages Uses

func (appender *MemoryAppender) GetLoggedMessages() []string

GetLoggedMessages returns the list of logged messages as strings.

func (*MemoryAppender) Log Uses

func (appender *MemoryAppender) Log(record *LogRecord) error

Log checks the log records level and if it passes appends the record to the list

type NullAppender Uses

type NullAppender struct {
    BaseLogAppender
    // contains filtered or unexported fields
}

NullAppender is a simple log appender that just counts the number of log messages

func NewNullAppender Uses

func NewNullAppender() *NullAppender

NewNullAppender creates a null appender

func (*NullAppender) Count Uses

func (appender *NullAppender) Count() int64

Count returns the count of messages logged

func (*NullAppender) Log Uses

func (appender *NullAppender) Log(record *LogRecord) error

Log adds 1 to the count

type RollingFileAppender Uses

type RollingFileAppender struct {
    BaseLogAppender
    // contains filtered or unexported fields
}

RollingFileAppender is the wrapper for a rolling file log appender.

A RollingFile appender will log to a file specified by prefix, which can contain a path, and a suffix, like "log". The appender will concatenate the prefix and suffix using the following format "prefix.#.suffix" where # is the log file number. The current file will be "prefix.suffix". Note, the . between the elements, the prefix and suffix should not include these.

Files can be rolled on size or manually by calling Roll().

The maxFiles must be at least 1 MaxFileSize must be at least 1024 - and is measured in bytes, if the max files is 1 the max file size is ignored

The actual file size will exceed maxFileSize, because the roller will not roll until a log message pushes the file past the size.

func NewRollingFileAppender Uses

func NewRollingFileAppender(prefix string, suffix string, maxFileSize int64, maxFiles int16) *RollingFileAppender

NewRollingFileAppender is used to create a rolling file appender

func (*RollingFileAppender) Close Uses

func (appender *RollingFileAppender) Close() error

Close closes the current file after flushing any buffered data

func (*RollingFileAppender) Log Uses

func (appender *RollingFileAppender) Log(record *LogRecord) error

Log a record to the current file

func (*RollingFileAppender) Roll Uses

func (appender *RollingFileAppender) Roll() error

Roll moves the file to the next number, up to the max files.

type SysLogAppender Uses

type SysLogAppender struct {
    BaseLogAppender
    // contains filtered or unexported fields
}

SysLogAppender is the logging appender for appending to the syslog service

func NewSysLogAppender Uses

func NewSysLogAppender() *SysLogAppender

NewSysLogAppender creates a sys log appender

func (*SysLogAppender) Close Uses

func (appender *SysLogAppender) Close() error

Close shuts down the syslog connection

func (*SysLogAppender) Log Uses

func (appender *SysLogAppender) Log(record *LogRecord) error

Log adds a record to the sys log

type WriterAppender Uses

type WriterAppender struct {
    BaseLogAppender
    // contains filtered or unexported fields
}

WriterAppender is a simple appender that pushes messages as bytes to a writer

func NewWriterAppender Uses

func NewWriterAppender(writer io.Writer) *WriterAppender

NewWriterAppender creates an appender from the specified writer.

func (*WriterAppender) Log Uses

func (appender *WriterAppender) Log(record *LogRecord) error

Log checks the log record's level and then writes the formatted record to the writer, followed by the bytes for "\n"

Package logging imports 12 packages (graph). Updated 2016-07-16. Refresh now. Tools for package owners. This is an inactive package (no imports and no commits in at least two years).