Documentation
¶
Index ¶
- type LogContext
- func (l *LogContext) Debug(message string)
- func (l *LogContext) DebugD(message, details string)
- func (l *LogContext) DebugJ(message, details string)
- func (l *LogContext) Error(message string)
- func (l *LogContext) ErrorD(message, details string)
- func (l *LogContext) ErrorJ(message, details string)
- func (l *LogContext) Fatal(message string)
- func (l *LogContext) FatalD(message, details string)
- func (l *LogContext) FatalJ(message, details string)
- func (l *LogContext) Info(message string)
- func (l *LogContext) InfoD(message, details string)
- func (l *LogContext) InfoJ(message, details string)
- func (l *LogContext) Trace(message string)
- func (l *LogContext) TraceD(message, details string)
- func (l *LogContext) TraceJ(message, details string)
- func (l *LogContext) Warn(message string)
- func (l *LogContext) WarnD(message, details string)
- func (l *LogContext) WarnJ(message, details string)
- func (l LogContext) Write(message []byte) (int, error)
- type LogDetail
- type LogEntry
- type LogLevel
- type LogService
- func InitializeUDP(hostURI string, serviceContext ServiceContext) LogService
- func InitializeUDPWithOptions(hostURI string, serviceContext ServiceContext, options LogServiceOptions) LogService
- func InitializeWriter(writer io.Writer, serviceContext ServiceContext) LogService
- func InitializeWriterWithOptions(w io.Writer, serviceContext ServiceContext, options LogServiceOptions) LogService
- type LogServiceOptions
- type LogSeverity
- type ServiceContext
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type LogContext ¶
type LogContext struct { // Site specifies a general location in a codebase from which a group of // log messages may emit. Site string // Operation specifies the a general operation being conducted within this // context. All log messages within this context have a direct relationship // to this operation. Operation string // contains filtered or unexported fields }
LogContext defines high level information for a structured log entry. Information in LogContext is applicable to multiple log calls, and describe the general environment in which a series of related log calls will be made.
func (*LogContext) Debug ¶
func (l *LogContext) Debug(message string)
Debug logs fairly graunlar information about system state.
func (*LogContext) DebugD ¶
func (l *LogContext) DebugD(message, details string)
DebugD logs relatively detailed information about system state along with extra detail.
func (*LogContext) DebugJ ¶
func (l *LogContext) DebugJ(message, details string)
DebugJ logs relatively detailed information about system state along with extra detail, while also escaping all reserved JSON characters.
func (*LogContext) Error ¶
func (l *LogContext) Error(message string)
Error logs events of considerable importance that will prevent normal program execution, but might still allow the application to continue running.
func (*LogContext) ErrorD ¶
func (l *LogContext) ErrorD(message, details string)
ErrorD logs events of considerable importance that will prevent normal program execution, but might still allow the application to continue running along with extra detail.
func (*LogContext) ErrorJ ¶
func (l *LogContext) ErrorJ(message, details string)
ErrorJ logs events of considerable importance that will prevent normal program execution, but might still allow the application to continue running along with extra detail, while also escaping all reserved JSON characters.
func (*LogContext) Fatal ¶
func (l *LogContext) Fatal(message string)
Fatal logs the most severe events. Fatal events are likely to have caused a service to terminate.
func (*LogContext) FatalD ¶
func (l *LogContext) FatalD(message, details string)
FatalD logs the most severe events. Fatal events are likely to have caused a service to terminate.
func (*LogContext) FatalJ ¶
func (l *LogContext) FatalJ(message, details string)
FatalJ logs the most severe events. Fatal events are likely to have caused a service to terminate, while also escaping all reserved JSON characters.
func (*LogContext) Info ¶
func (l *LogContext) Info(message string)
Info logs general informational messages useful for describing system state.
func (*LogContext) InfoD ¶
func (l *LogContext) InfoD(message, details string)
InfoD logs general informational messages useful for describing system state along with extra detail.
func (*LogContext) InfoJ ¶
func (l *LogContext) InfoJ(message, details string)
InfoJ logs general informational messages useful for describing system state along with extra detail, while also escaping all reserved JSON characters.
func (*LogContext) Trace ¶
func (l *LogContext) Trace(message string)
Trace logs the most granular information about system state.
func (*LogContext) TraceD ¶
func (l *LogContext) TraceD(message, details string)
TraceD logs the most granular information about system state along with extra detail.
func (*LogContext) TraceJ ¶
func (l *LogContext) TraceJ(message, details string)
TraceJ logs the most granular information about system state along with extra detail, while also escaping all reserved JSON characters.
func (*LogContext) Warn ¶
func (l *LogContext) Warn(message string)
Warn logs information about potentially harmful situations of interest.
func (*LogContext) WarnD ¶
func (l *LogContext) WarnD(message, details string)
WarnD logs information about potentially harmful situations of interest along with extra detail.
func (*LogContext) WarnJ ¶
func (l *LogContext) WarnJ(message, details string)
WarnJ logs information about potentially harmful situations of interest along with extra detail, while also escaping all reserved JSON characters.
func (LogContext) Write ¶
func (l LogContext) Write(message []byte) (int, error)
Write enables this context to be used as an io.Writer. Messages sent via the Write method are interpretted as Trace level events. The Write method always inspects the inbound message and escapes any JSON characters to avoid unintentionally mangling the expected log entry.
Example ¶
LogContexts also support the io.Writer interface, so they can be used to hook into any external writer, such as through the use of `log.SetOutput`.
package main import ( "fmt" "log" "regexp" "time" "github.com/eltorocorp/nobslogger/v2/logger" ) type fakeWriter struct{} // Write just replaces the timestamp internally assigned by the LogService // with a constant value so the tests remain deterministic. func (fakeWriter) Write(message []byte) (int, error) { re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.(\d{5}|\d{6})-\d{2}:\d{2}`) msg := re.ReplaceAllString(string(message), "2009-01-20T12:05:00.000000-04:00") fmt.Println(msg) return len(msg), nil } func main() { serviceContext := logger.ServiceContext{ Environment: "test", SystemName: "examples", ServiceName: "example runner", ServiceInstanceID: "1", } serviceOptions := logger.LogServiceOptions{ CancellationDeadline: 10 * time.Millisecond, } loggerSvc := logger.InitializeWriterWithOptions(new(fakeWriter), serviceContext, serviceOptions) logger := loggerSvc.NewContext("ExampleLogContext", "Write") // Here we simulate hooking the LogContext into the an existing std/logger. // In this example we create a new logger via `log.New`, the this could also // be done using `log.SetOutput`. stdlibLogger := log.New(logger, "", 0) // When we call Println, the current LogContext will log the message at the // Trace level. // Note that the expected output will include an escaped newline character. // This is added by the Println function, and is properly escaped by // nobslogger to prevent mangling the JSON output. stdlibLogger.Println("Hello from the standard library logger!") loggerSvc.Finish() }
Output: {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"ExampleLogContext","operation":"Write","level":"100","severity":"trace","msg":"Hello from the standard library logger!\n","details":""}
type LogDetail ¶
type LogDetail struct { Level LogLevel Severity LogSeverity Timestamp string Message string Details string }
A LogDetail defines low level information for a structured log entry.
type LogEntry ¶
type LogEntry struct { ServiceContext LogContext LogDetail }
A LogEntry defines the highest level structured log entry.
type LogLevel ¶
type LogLevel string
LogLevel numerically defines the general severity of a log entry.
const ( LogLevelTrace LogLevel = "100" LogLevelDebug LogLevel = "200" LogLevelInfo LogLevel = "300" LogLevelWarn LogLevel = "400" LogLevelError LogLevel = "500" LogLevelFatal LogLevel = "600" )
LogLevel constants. LogLevels are backed by strings rather than ints to avoid conversions to string when serializing for UDP (see `LogEntry.Serialize()`)
type LogService ¶
type LogService struct {
// contains filtered or unexported fields
}
LogService provides access to a writer such as that for a file system or an upstream UDP endpoint.
Example (ContextAcrossGoroutines) ¶
LogService supports having one (or more) log contexts span multiple goroutines.
package main import ( "fmt" "regexp" "time" "github.com/eltorocorp/nobslogger/v2/logger" ) type fakeWriter struct{} // Write just replaces the timestamp internally assigned by the LogService // with a constant value so the tests remain deterministic. func (fakeWriter) Write(message []byte) (int, error) { re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.(\d{5}|\d{6})-\d{2}:\d{2}`) msg := re.ReplaceAllString(string(message), "2009-01-20T12:05:00.000000-04:00") fmt.Println(msg) return len(msg), nil } func main() { serviceContext := logger.ServiceContext{ Environment: "test", SystemName: "examples", ServiceName: "example runner", ServiceInstanceID: "1", } serviceOptions := logger.LogServiceOptions{ CancellationDeadline: 10 * time.Millisecond, } loggerSvc := logger.InitializeWriterWithOptions(new(fakeWriter), serviceContext, serviceOptions) logger := loggerSvc.NewContext("single context", "used across multiple goroutines") logger.Info("Log from goroutine 1") go func() { logger.Info("Log from goroutine 2") }() go func() { logger.Info("Log from goroutine 3") }() loggerSvc.Finish() }
Output: {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"single context","operation":"used across multiple goroutines","level":"300","severity":"info","msg":"Log from goroutine 1","details":""} {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"single context","operation":"used across multiple goroutines","level":"300","severity":"info","msg":"Log from goroutine 2","details":""} {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"single context","operation":"used across multiple goroutines","level":"300","severity":"info","msg":"Log from goroutine 3","details":""}
Example (MultipleContexts) ¶
LogService supports having multiple logging contexts that may be initialized from separate goroutines.
package main import ( "fmt" "regexp" "time" "github.com/eltorocorp/nobslogger/v2/logger" ) type fakeWriter struct{} // Write just replaces the timestamp internally assigned by the LogService // with a constant value so the tests remain deterministic. func (fakeWriter) Write(message []byte) (int, error) { re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.(\d{5}|\d{6})-\d{2}:\d{2}`) msg := re.ReplaceAllString(string(message), "2009-01-20T12:05:00.000000-04:00") fmt.Println(msg) return len(msg), nil } func main() { serviceContext := logger.ServiceContext{ Environment: "test", SystemName: "examples", ServiceName: "example runner", ServiceInstanceID: "1", } serviceOptions := logger.LogServiceOptions{ CancellationDeadline: 10 * time.Millisecond, } loggerSvc := logger.InitializeWriterWithOptions(new(fakeWriter), serviceContext, serviceOptions) go func() { logger := loggerSvc.NewContext("goroutine 1", "running example") logger.Info("Here is some info from goroutine 1") }() go func() { logger := loggerSvc.NewContext("goroutine 2", "running example") logger.Info("Here is some info from goroutine 2") }() loggerSvc.Finish() }
Output: {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"goroutine 1","operation":"running example","level":"300","severity":"info","msg":"Here is some info from goroutine 1","details":""} {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"goroutine 2","operation":"running example","level":"300","severity":"info","msg":"Here is some info from goroutine 2","details":""}
Example (VariousContextMethods) ¶
LogService contexts support a vartiety of log methods, including, but not limited to those shown in this example.
package main import ( "fmt" "regexp" "time" "github.com/eltorocorp/nobslogger/v2/logger" ) type fakeWriter struct{} // Write just replaces the timestamp internally assigned by the LogService // with a constant value so the tests remain deterministic. func (fakeWriter) Write(message []byte) (int, error) { re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.(\d{5}|\d{6})-\d{2}:\d{2}`) msg := re.ReplaceAllString(string(message), "2009-01-20T12:05:00.000000-04:00") fmt.Println(msg) return len(msg), nil } func main() { serviceContext := logger.ServiceContext{ Environment: "test", SystemName: "examples", ServiceName: "example runner", ServiceInstanceID: "1", } serviceOptions := logger.LogServiceOptions{ CancellationDeadline: 10 * time.Millisecond, } loggerSvc := logger.InitializeWriterWithOptions(new(fakeWriter), serviceContext, serviceOptions) logger := loggerSvc.NewContext("goroutine 1", "running example") logger.Info("An info-level message.") logger.InfoD("An info-level message.", "With more details!") logger.Debug("A debug-level message") logger.DebugD("A debug-level message.", "With extra details!") loggerSvc.Finish() }
Output: {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"goroutine 1","operation":"running example","level":"300","severity":"info","msg":"An info-level message.","details":""} {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"goroutine 1","operation":"running example","level":"300","severity":"info","msg":"An info-level message.","details":"With more details!"} {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"goroutine 1","operation":"running example","level":"200","severity":"debug","msg":"A debug-level message","details":""} {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"goroutine 1","operation":"running example","level":"200","severity":"debug","msg":"A debug-level message.","details":"With extra details!"}
func InitializeUDP ¶
func InitializeUDP(hostURI string, serviceContext ServiceContext) LogService
InitializeUDP establishes a connection to a specified UDP server (such as logstash), and returns a LogService instance through which more detailed logging contexts can be spawned (see NewContext)
This function will panic if an error occurs while establishing the connection to the UDP server.
NobSlogger does not make any attempts at UDP MTU discovery, and will not prohibit the host system from attempting to send log messages that exceed the network's UDP MTU limit. If this limit is exceeded, one of two things may occur:
1) The LogService may return an error while attempting to transmit the message. In this case, the LogService will try to log (via UDP) that it has received an error while shipping log data. This message will have a severity of "Error". If the error log transmission fails, the LogService will post the resulting error message to StdErr, and continue on.
2) If an outbound UDP packet is split or lost downstream, the LogService may not have any awareness that the it was lost. In this case the destination system might receive a partial log message. As such, it is recommended that the destination service be running a json codec that is able to identify and flag if/when an inbound message is incomplete.
hostURI: Must be a fully qualified URI including port.
func InitializeUDPWithOptions ¶
func InitializeUDPWithOptions(hostURI string, serviceContext ServiceContext, options LogServiceOptions) LogService
InitializeUDPWithOptions is the samme as InitializeUDP, but with custom LogServiceOptions supplied. See InitializeUDP.
func InitializeWriter ¶
func InitializeWriter(writer io.Writer, serviceContext ServiceContext) LogService
InitializeWriter establishes a logging service that transmits logs to the provided io.Writer.
Example ¶
package main import ( "fmt" "regexp" "time" "github.com/eltorocorp/nobslogger/v2/logger" ) type fakeWriter struct{} // Write just replaces the timestamp internally assigned by the LogService // with a constant value so the tests remain deterministic. func (fakeWriter) Write(message []byte) (int, error) { re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.(\d{5}|\d{6})-\d{2}:\d{2}`) msg := re.ReplaceAllString(string(message), "2009-01-20T12:05:00.000000-04:00") fmt.Println(msg) return len(msg), nil } func main() { // Establish a ServiceContext. // This records the highest level information about the system being logged. serviceContext := logger.ServiceContext{ Environment: "test", SystemName: "examples", ServiceName: "example runner", ServiceInstanceID: "1", } // Setup options for the service. In this case, we're instructing the service // to wait at least one second for any remaining log entries to flush // before exiting. serviceOptions := logger.LogServiceOptions{ CancellationDeadline: 10 * time.Millisecond, } // Initialize the LogService. loggerSvc := logger.InitializeWriterWithOptions(new(fakeWriter), serviceContext, serviceOptions) // Get a new logger (LogContext) from the LogService. logger := loggerSvc.NewContext("ExampleInitializeWriter_ServiceContext", "running example") // Log something. logger.Info("Here is some info") loggerSvc.Finish() }
Output: {"timestamp":"2009-01-20T12:05:00.000000-04:00","environment":"test","system_name":"examples","service_name":"example runner","service_instance_id":"1","site":"ExampleInitializeWriter_ServiceContext","operation":"running example","level":"300","severity":"info","msg":"Here is some info","details":""}
func InitializeWriterWithOptions ¶
func InitializeWriterWithOptions(w io.Writer, serviceContext ServiceContext, options LogServiceOptions) LogService
InitializeWriterWithOptions is the same as InitializeWriter, but with custom LogServiceOptions supplied. See InitializeWriter.
func (*LogService) Finish ¶
func (ls *LogService) Finish()
Finish sets a deadline for any concurrent LogContexts to finish sending any remaining messages; then blocks until that deadline has expired. Finish will reset its internal deadline if any messages are received during the waiting period. Finish will only unblock once the full deadline duration has elapsed with no inbound log activity.
Finish makes a good faith attempt to flush all inbound messages during the waiting period. However, it remains the host system's responsibility to wind down all components that might be broadcasting logs to LogContexts before calling Finish.
If the host system continues to send log messages to the log service while Finishing, the log service will either a) never exit because it keeps receiving messages or b) exit before all messages have been processed.
func (*LogService) NewContext ¶
func (ls *LogService) NewContext(site, operation string) LogContext
NewContext provides high level structured information used to decorate log messages, and exposes methods for writing at various log levels.
type LogServiceOptions ¶
LogServiceOptions exposes configuration settings for LogService behavior.
type LogSeverity ¶
type LogSeverity string
LogSeverity defines the general severity of a log entry.
const ( LogSeverityTrace LogSeverity = "trace" LogSeverityDebug LogSeverity = "debug" LogSeverityInfo LogSeverity = "info" LogSeverityWarn LogSeverity = "warn" LogSeverityError LogSeverity = "error" LogSeverityFatal LogSeverity = "fatal" )
LogSeverity constants
type ServiceContext ¶
type ServiceContext struct { // Environment, i.e. dev, stage, prod, etc. Environment string // The name of the system at large which this service acts within. SystemName string // The name of this particular service. ServiceName string // An ID that defines this service instance uniquely from other instances // of the same service within this system and environment. ServiceInstanceID string }
ServiceContext defines structural log elements that are applied to every log entry from this log service instance.