logger

package
v2.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2020 License: MIT Imports: 8 Imported by: 0

Documentation

Index

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

type LogServiceOptions struct {
	CancellationDeadline time.Duration
}

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL