Documentation ¶
Overview ¶
Package logharbour is a comprehensive logging system. It supports different log levels, log types, and can encode log entries in JSON. It also provides a fallback mechanism in case the primary log writer fails.
Example ¶
Example of using With prefixed methods to set various fields of the logger.
// Open a file for logging. file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } defer file.Close() // Create a fallback writer that uses the file as the primary writer and stdout as the fallback. fallbackWriter := NewFallbackWriter(file, os.Stdout) // Create a logger context with the default priority. lctx := NewLoggerContext(Info) // Initialize the logger. logger := NewLogger(lctx, "MyApp", fallbackWriter) // Create a new logger with various fields set. logger = logger.WithModule("Module1"). WithWho("John Doe"). WithStatus(Success). WithRemoteIP("192.168.1.1") // Use the new logger to log an activity. logger.LogActivity("User logged in", map[string]any{"username": "john"}) // Log a data change entry. // log a data change entry. logger.LogDataChange("User updated profile", *NewChangeInfo("User", "Update"). AddChange("email", "oldEmail@example.com", "john@example.com")) // Change logger priority at runtime. lctx.ChangeMinLogPriority(Debug2) // Log a debug entry. logger.LogDebug("Debugging user session", map[string]any{"sessionID": "12345"}) // // { // "app_name": "MyApp", // "module": "Module1", // "priority": "Info", // "who": "John Doe", // "status": 1, // "remote_ip": "192.168.1.1", // "type": "Activity", // "message": "User logged in", // "data": { // "username": "john" // } // } // { // "app_name": "MyApp", // "module": "Module1", // "priority": "Info", // "who": "John Doe", // "status": 1, // "remote_ip": "192.168.1.1", // "type": "Change", // "message": "User updated profile", // "data": { // "entity": "User", // "operation": "Update", // "changes": { // "email": "john@example.com" // } // } // } // { // "app_name": "MyApp", // "module": "Module1", // "priority": "Debug2", // "who": "John Doe", // "status": 1, // "remote_ip": "192.168.1.1", // "type": "Debug", // "message": "Debugging user session", // "data": { // "variables": { // "sessionID": "12345" // }, // "fileName": "main2.go", // "lineNumber": 30, // "functionName": "main", // "stackTrace": "...", // "pid": 1234, // "runtime": "go1.15.6" // } // }
Output:
Index ¶
- Constants
- func GetDebugInfo(skip int) (fileName string, lineNumber int, functionName string, stackTrace string)
- type ActivityInfo
- type ChangeDetail
- type ChangeInfo
- type Consumer
- type DebugInfo
- type ElasticsearchClient
- type ElasticsearchWriter
- type FallbackWriter
- type KafkaConfig
- type KafkaWriter
- type KafkaWriterOption
- type LogEntry
- type LogPriority
- type LogType
- type Logger
- func (l *Logger) Crit() *Logger
- func (l *Logger) Debug0() *Logger
- func (l *Logger) Debug1() *Logger
- func (l *Logger) Debug2() *Logger
- func (l *Logger) Err() *Logger
- func (l *Logger) Error(err error) *Logger
- func (l *Logger) Info() *Logger
- func (l *Logger) Log(message string)
- func (l *Logger) LogActivity(message string, data ActivityInfo)
- func (l *Logger) LogDataChange(message string, data ChangeInfo)
- func (l *Logger) LogDebug(message string, data any)
- func (l *Logger) Sec() *Logger
- func (l *Logger) Warn() *Logger
- func (l *Logger) WithClass(whatClass string) *Logger
- func (l *Logger) WithInstanceId(whatInstanceId string) *Logger
- func (l *Logger) WithModule(module string) *Logger
- func (l *Logger) WithOp(op string) *Logger
- func (l *Logger) WithPriority(priority LogPriority) *Logger
- func (l *Logger) WithRemoteIP(remoteIP string) *Logger
- func (l *Logger) WithStatus(status Status) *Logger
- func (l *Logger) WithWho(who string) *Logger
- type LoggerContext
- type MessageHandler
- type Status
Examples ¶
Constants ¶
const ( LogPriorityDebug2 = "Debug2" LogPriorityDebug1 = "Debug1" LogPriorityDebug0 = "Debug0" LogPriorityInfo = "Info" LogPriorityWarn = "Warn" LogPriorityErr = "Err" LogPriorityCrit = "Crit" LogPrioritySec = "Sec" LogPriorityUnknown = "Unknown" )
const ( LogTypeChange = "C" LogTypeActivity = "A" LogTypeDebug = "D" LogTypeUnknown = "U" )
const DefaultPriority = Info
Variables ¶
This section is empty.
Functions ¶
func GetDebugInfo ¶
func GetDebugInfo(skip int) (fileName string, lineNumber int, functionName string, stackTrace string)
GetDebugInfo returns debug information including file name, line number, function name and stack trace. The 'skip' parameter determines how many stack frames to ascend, with 0 identifying the caller of GetDebugInfo.
Types ¶
type ActivityInfo ¶
type ActivityInfo any
ActivityInfo holds information about system activities like web service calls or function executions.
type ChangeDetail ¶ added in v0.11.0
type ChangeDetail struct { Field string `json:"field"` OldVal any `json:"old_value"` NewVal any `json:"new_value"` }
func NewChangeDetail ¶ added in v0.11.0
func NewChangeDetail(field string, oldValue, newValue any) ChangeDetail
NewChangeDetail creates a new ChangeDetail instance.
type ChangeInfo ¶
type ChangeInfo struct { Entity string `json:"entity"` Op string `json:"op"` Changes []ChangeDetail `json:"changes"` }
ChangeInfo holds information about data changes such as creations, updates, or deletions.
Example usage of ChangeInfo and ChangeDetail to log changes to an entity.
func LogEntityChange() { // Create a new ChangeInfo for the "User" entity undergoing an "Update" operation and add changes. changeInfo := NewChangeInfo("User", "Update"). AddChange("email", "oldEmail@example.com", "newEmail@example.com"). AddChange("username", "oldUsername", "newUsername") logger.LogDataChange("User details updated", *changeInfo) }
func NewChangeInfo ¶ added in v0.11.0
func NewChangeInfo(entity, operation string) *ChangeInfo
NewChangeInfo creates a new ChangeInfo instance.
func (*ChangeInfo) AddChange ¶ added in v0.11.0
func (ci *ChangeInfo) AddChange(field string, oldValue, newValue any) *ChangeInfo
AddChange adds a new ChangeDetail to a ChangeInfo instance and returns the ChangeInfo.
type Consumer ¶ added in v0.12.0
Consumer defines the interface for a Kafka consumer.
func NewConsumer ¶ added in v0.12.0
func NewConsumer(brokers []string, topic string, handler MessageHandler) (Consumer, error)
type DebugInfo ¶
type DebugInfo struct { Pid int `json:"pid"` Runtime string `json:"runtime"` FileName string `json:"file"` LineNumber int `json:"line"` FunctionName string `json:"func"` StackTrace string `json:"stackTrace"` Data map[string]any `json:"data"` }
DebugInfo holds debugging information that can help in software diagnostics.
type ElasticsearchClient ¶ added in v0.12.0
type ElasticsearchClient struct {
// contains filtered or unexported fields
}
func NewElasticsearchClient ¶ added in v0.12.0
func NewElasticsearchClient(cfg elasticsearch.Config) (*ElasticsearchClient, error)
NewElasticsearchClient creates a new Elasticsearch client with the given configuration
type ElasticsearchWriter ¶ added in v0.12.0
ElasticsearchWriter defines methods for Elasticsearch writer
type FallbackWriter ¶
type FallbackWriter struct {
// contains filtered or unexported fields
}
FallbackWriter provides an io.Writer that automatically falls back to a secondary writer if the primary writer fails. It is also used if logentry is not valid so that we can still log erroneous entries without writing them to the primary writer.
func NewFallbackWriter ¶
func NewFallbackWriter(primary, fallback io.Writer) *FallbackWriter
NewFallbackWriter creates a new FallbackWriter with a specified primary and fallback writer.
func (*FallbackWriter) Write ¶
func (fw *FallbackWriter) Write(p []byte) (n int, err error)
Write attempts to write the byte slice to the primary writer, falling back to the secondary writer on error. It returns the number of bytes written and any error encountered that caused the write to stop early.
type KafkaConfig ¶ added in v0.11.0
type KafkaConfig struct { Brokers []string // List of broker addresses Topic string // Kafka topic to write messages to // Producer configurations Retries *int // Maximum number of times to retry sending a message RequiredAcks *sarama.RequiredAcks // Number of acknowledgments required before considering a message as sent Timeout *time.Duration // Maximum duration to wait for the broker to acknowledge the receipt of a message ReturnErrors *bool // Whether to return errors that occurred while producing the message ReturnSuccesses *bool // Whether to return successes of produced messages CompressionLevel *int // Compression level to use for messages // Network configurations DialTimeout *time.Duration // Timeout for establishing network connections ReadTimeout *time.Duration // Timeout for network reads WriteTimeout *time.Duration // Timeout for network writes MaxOpenRequests *int // Maximum number of unacknowledged requests to send before blocking // Client configurations ClientID *string // User-provided string sent with every request for logging, debugging, and auditing purposes }
KafkaConfig is a struct that holds the configuration for a Kafka producer. All fields are pointers, which allows us to distinguish between a field that is not set and a field set with its zero value.
type KafkaWriter ¶ added in v0.11.0
KafkaWriter defines methods for Kafka writer
func NewKafkaWriter ¶ added in v0.11.0
func NewKafkaWriter(kafkaConfig KafkaConfig, opts ...KafkaWriterOption) (KafkaWriter, error)
type KafkaWriterOption ¶ added in v0.11.0
type KafkaWriterOption func(*kafkaWriter)
func WithPoolSize ¶ added in v0.11.0
func WithPoolSize(size int) KafkaWriterOption
type LogEntry ¶
type LogEntry struct { App string `json:"app"` // Name of the application. System string `json:"system"` // System where the application is running. Module string `json:"module"` // The module or subsystem within the application Type LogType `json:"type"` // Type of the log entry. Pri LogPriority `json:"pri"` // Severity level of the log entry. When time.Time `json:"when"` // Time at which the log entry was created. Who string `json:"who"` // User or service performing the operation. Op string `json:"op"` // Operation being performed Class string `json:"class"` // Unique ID, name of the object instance on which the operation was being attempted InstanceId string `json:"instance"` // Unique ID, name, or other "primary key" information of the object instance on which the operation was being attempted Status Status `json:"status"` // 0 or 1, indicating success (1) or failure (0), or some other binary representation Error string `json:"error,omitempty"` // Error message or error chain related to the log entry, if any. RemoteIP string `json:"remote_ip"` // IP address of the caller from where the operation is being performed. Msg string `json:"msg"` // A descriptive message for the log entry. Data any `json:"data"` // The payload of the log entry, can be any type. }
LogEntry encapsulates all the relevant information for a log message.
type LogPriority ¶
type LogPriority int
logPriority defines the severity level of a log message.
const ( Debug2 LogPriority = iota + 1 // Debug2 represents extremely verbose debugging information. Debug1 // Debug1 represents detailed debugging information. Debug0 // Debug0 represents high-level debugging information. Info // Info represents informational messages. Warn // Warn represents warning messages. Err // Err represents error messages where operations failed to complete. Crit // Crit represents critical failure messages. Sec // Sec represents security alert messages. )
func (LogPriority) MarshalJSON ¶
func (lp LogPriority) MarshalJSON() ([]byte, error)
MarshalJSON is required by the encoding/json package. It converts the logPriority to its string representation and returns it as a JSON-encoded value.
func (LogPriority) String ¶ added in v0.5.0
func (lp LogPriority) String() string
String returns the string representation of the logPriority.
func (*LogPriority) UnmarshalJSON ¶ added in v0.5.0
func (lp *LogPriority) UnmarshalJSON(data []byte) error
type LogType ¶
type LogType int
LogType defines the category of a log message.
func (LogType) MarshalJSON ¶
MarshalJSON is required by the encoding/json package. It converts the LogType to its string representation and returns it as a JSON-encoded value.
func (*LogType) UnmarshalJSON ¶ added in v0.5.0
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger provides a structured interface for logging. It's designed for each goroutine to have its own instance. Logger is safe for concurrent use. However, it's not recommended to share a Logger instance across multiple goroutines.
If the writer is a FallbackWriter and validation of a log entry fails, the Logger will automatically write the invalid entry to the FallbackWriter's fallback writer. If writing to fallback writer also fails then it writes to STDERR.
The 'With' prefixed methods in the Logger are used to create a new Logger instance with a specific field set to a new value. These methods create a copy of the current Logger, then set the desired field to the new value, and finally return the new Logger. This approach provides a flexible way to create a new Logger with specific settings, without having to provide all settings at once or change the settings of an existing Logger.
func NewLogger ¶
func NewLogger(context *LoggerContext, appName string, writer io.Writer) *Logger
NewLogger creates a new Logger with the specified application name and writer. We recommend using NewLoggerWithFallback instead of this method.
func NewLoggerWithFallback ¶
func NewLoggerWithFallback(context *LoggerContext, appName string, fallbackWriter *FallbackWriter) *Logger
NewLoggerWithFallback creates a new Logger with a fallback writer. The fallback writer is used if the primary writer fails or if validation of a log entry fails.
func (*Logger) Crit ¶ added in v0.7.0
Crit returns a new Logger with the 'priority' field set to Crit.
func (*Logger) Debug0 ¶ added in v0.7.0
Debug0 returns a new Logger with the 'priority' field set to Debug0.
func (*Logger) Debug1 ¶ added in v0.7.0
Debug1 returns a new Logger with the 'priority' field set to Debug1.
func (*Logger) Debug2 ¶ added in v0.7.0
Debug2 returns a new Logger with the 'priority' field set to Debug2.
func (*Logger) Info ¶ added in v0.7.0
Info returns a new Logger with the 'priority' field set to Info.
func (*Logger) LogActivity ¶
func (l *Logger) LogActivity(message string, data ActivityInfo)
LogActivity logs an activity event.
func (*Logger) LogDataChange ¶
func (l *Logger) LogDataChange(message string, data ChangeInfo)
LogDataChange logs a data change event.
func (*Logger) Warn ¶ added in v0.7.0
Warn returns a new Logger with the 'priority' field set to Warn.
func (*Logger) WithClass ¶ added in v0.12.0
WithClass returns a new Logger with the 'whatClass' field set to the specified value.
func (*Logger) WithInstanceId ¶ added in v0.12.0
WithInstanceId returns a new Logger with the 'whatInstanceId' field set to the specified value.
func (*Logger) WithModule ¶
WithModule returns a new Logger with the 'module' field set to the specified value.
func (*Logger) WithPriority ¶
func (l *Logger) WithPriority(priority LogPriority) *Logger
WithPriority returns a new Logger with the 'priority' field set to the specified value.
There are shortcut functions like Info(), Warn(), etc. provided as a convenient way to set the priority level for a single call. Each of these function creates a new Logger instance with the specified priority and returns it. The original Logger instance remains unchanged. For example, instead of writing
logger.WithPriority(logharbour.Info).LogChange(...),
you can simply write
logger.Info().LogChange(...)
func (*Logger) WithRemoteIP ¶
WithRemoteIP returns a new Logger with the 'remoteIP' field set to the specified value.
func (*Logger) WithStatus ¶
WithStatus returns a new Logger with the 'status' field set to the specified value.
type LoggerContext ¶ added in v0.10.0
type LoggerContext struct {
// contains filtered or unexported fields
}
LoggerContext provides a shared context (state) for instances of Logger. It contains a minLogPriority field that determines the minimum log priority level that should be logged by any Logger using this context. The mu Mutex ensures that all operations on the minLogPriority field are mutually exclusive, regardless of which goroutine they are performed in.
func NewLoggerContext ¶ added in v0.10.0
func NewLoggerContext(minLogPriority LogPriority) *LoggerContext
NewLoggerContext creates a new LoggerContext with the specified minimum log priority. The returned LoggerContext can be used to create Logger instances with a shared context for all the Logger instances.
func (*LoggerContext) ChangeMinLogPriority ¶ added in v0.12.0
func (lc *LoggerContext) ChangeMinLogPriority(minLogPriority LogPriority)
ChangePriority changes the priority level of the Logger.
func (*LoggerContext) IsDebugMode ¶ added in v0.12.0
func (lc *LoggerContext) IsDebugMode() bool
IsDebugMode checks if debug mode is enabled atomically.
func (*LoggerContext) SetDebugMode ¶ added in v0.12.0
func (lc *LoggerContext) SetDebugMode(enable bool)
SetDebugMode sets the debug mode for all loggers sharing this context. Passing true enables debug logging, while false disables it.
type MessageHandler ¶ added in v0.12.0
type MessageHandler func(messages []*sarama.ConsumerMessage) error
MessageHandler is a function type that processes messages from Kafka.