Documentation
¶
Overview ¶
Package logtic is a yet another logging library for golang projects.
The goal of logtic is to be as transparent and easy to use as possible, allowing applications and libraries to seamlessly log to a single file. Logtic can be used in libraries and won't cause any problems if the parent application isn't using logtic.
Logtic supports multiple sources, which annotate the outputted log lines. It also supports defining a minimum desired log level, which can be changed at any time. Events printed to the terminal output support color-coded severities.
Events can be printed as formatted strings, like with `fmt.Printf`, or can be parameterized events which can be easily parsed by log analysis tools such as Splunk.
By default, logtic will only print to stdout and stderr, but when configured it can also write to a log file. Log files include the date-time for each event in RFC-3339 format.
Logtic provides a default logging instance but also supports unique instances that can operate in parallel, writing to unique files and having unique settings.
Log files can be rotated using the provided rotate method.
Logtic is optimized for Linux & Unix environments but offers limited support for Windows.
Example ¶
Common setup for file-based logging
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
// Set the log file path and default log level (if desired)
logtic.Log.FilePath = "./file.log"
logtic.Log.Level = logtic.LevelInfo
if err := logtic.Log.Open(); err != nil {
// There was an error opening the log file for writing
panic(err)
}
log := logtic.Log.Connect("MyApp")
log.Warn("Print something %s", "COOL!")
// Don't forget to close the log file when your application exits
logtic.Log.Close()
}
Output:
Index ¶
- Constants
- Variables
- func FormatBytesB(b uint64) string
- func FormatBytesD(b uint64) string
- func StringFromParameters(parameters map[string]any) string
- type IColor
- type LogLevel
- type Logger
- type LoggerOptions
- type Source
- func (s *Source) ClearLevelOverride()
- func (s *Source) Debug(format string, a ...interface{})
- func (s *Source) Error(format string, a ...interface{})
- func (s *Source) Fatal(format string, a ...interface{})
- func (s *Source) GoLogger(level LogLevel) *log.Logger
- func (s *Source) Info(format string, a ...interface{})
- func (s *Source) OverrideLevel(level LogLevel)
- func (s *Source) PDebug(event string, parameters map[string]any)
- func (s *Source) PError(event string, parameters map[string]any)
- func (s *Source) PFatal(event string, parameters map[string]any)
- func (s *Source) PInfo(event string, parameters map[string]any)
- func (s *Source) PPanic(event string, parameters map[string]any)
- func (s *Source) PWarn(event string, parameters map[string]any)
- func (s *Source) PWrite(level LogLevel, event string, parameters map[string]any)
- func (s *Source) Panic(format string, a ...interface{})
- func (s *Source) Warn(format string, a ...interface{})
- func (s *Source) Write(level LogLevel, format string, a ...interface{})
Examples ¶
Constants ¶
const ( // LevelDebug debug messages for troubleshooting application behaviour LevelDebug = LogLevel(3) // LevelInfo informational messages for normal operation of the application LevelInfo = LogLevel(2) // LevelWarn warning messages for potential issues LevelWarn = LogLevel(1) // LevelError error messages for problems LevelError = LogLevel(0) )
Variables ¶
var Log = New()
Log is the default logging instance.
Functions ¶
func FormatBytesB ¶
FormatBytesB takes in a number of bytes and returns a human readable string with binary units (up-to Exbibyte)
Example ¶
package main
import (
"fmt"
"git.ecn.io/ian/logtic"
)
func main() {
fmt.Println(logtic.FormatBytesB(10485760))
}
Output: 10.0 MiB
func FormatBytesD ¶
FormatBytesB takes in a number of bytes and returns a human readable string with decimal units (up-to Exabyte)
Example ¶
package main
import (
"fmt"
"git.ecn.io/ian/logtic"
)
func main() {
fmt.Println(logtic.FormatBytesD(10000000))
}
Output: 10.0 MB
func StringFromParameters ¶
StringFromParameters return a key=value string for the given parameters. Depending on the type of the parameter value, it may be wrapped in single quotes. Byte slices are represented as hexadecimal strings. Parameters are always alphabetically sorted in the outputted string.
Example ¶
package main
import (
"fmt"
"time"
"git.ecn.io/ian/logtic"
)
func main() {
fmt.Println(logtic.StringFromParameters(map[string]any{
"hello": "world!",
"meaning_of_life": 42,
"pie": 3.12,
"does_golang_rock": true,
"secret_sauce": []byte("mayo ketchup sriracha"),
"unix_epoch": time.Unix(0, 0).UTC(),
"prime_numbers": []int{2, 3, 5, 7, 11},
}))
}
Output: does_golang_rock='true' hello='world!' meaning_of_life=42 pie=3.120000 prime_numbers='[2 3 5 7 11]' secret_sauce=6d61796f206b657463687570207372697261636861 unix_epoch='1970-01-01T00:00:00Z'
Types ¶
type IColor ¶
type IColor interface {
// Apply a bright black (gray) color to m
HiBlack(m string) string
// Apply a blue color to m
Blue(m string) string
// Apply a yellow color to m
Yellow(m string) string
// Apply a red color to m
Red(m string) string
}
IColor describes an interface for applying color to a message. By default, logtic only supports ANSI color codes. On platforms where these codes don't work - such as the legacy Console Host on Windows, you may implement your own color interface that applies colors as need for your platform.
type Logger ¶
type Logger struct {
// The path to the log file.
FilePath string
// The minimum level of events captured in the log file and printed to console. Inclusive.
Level LogLevel
// The file mode (permissions) used for the log file and rotated log files.
FileMode os.FileMode
// Options various options for this logger
Options LoggerOptions
// Stdout the writer to use for standard output. Defaults to the system stdout.
Stdout io.Writer
// Stdout the writer to use for standard error. Defaults to the system stderr.
Stderr io.Writer
// Color is the interface to apply color to messages. Defaults to using ANSI color codes.
Color IColor
// contains filtered or unexported fields
}
Logger describes a logging instance
func New ¶
func New() *Logger
New will create a new logging instance with all default options. You should only use new if you want a separate logging instance from the default instance, which is automatically created for you.
func (*Logger) Connect ¶
Connect will prepare a new logtic source with the given name for this logging instance. Sources can be written even if there is no open logtic log instance.
Example ¶
This example shows how to connect a new source to a logtic instance
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
// You can connect to logtic before a log file has been opened
// however, any events will not be captured until logtic.Log.Open()
// has been called
source1 := logtic.Log.Connect("Source1")
source2 := logtic.Log.Connect("Source2")
source1.Warn("Important warning")
source2.Error("Something went wrong")
}
Output:
func (*Logger) Open ¶
Open will open the file specified by FilePath on this logging instance. The file will be created if it does not already exist, otherwise it will be appended to.
Example ¶
This example shows how to set up a unique logging instance, separate form the default instance
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
logger := logtic.New()
// You must tell logtic where the log file is
// before any events will be captured
logger.FilePath = "./file.log"
// The default level is Error, you can change that at any time
logger.Level = logtic.LevelInfo
if err := logger.Open(); err != nil {
// There was an error opening the log file for writing
panic(err)
}
}
Output:
Example (WithoutFile) ¶
This example shows how to prepare logtic to only print to the console, without writing to a log file
package main
import (
"os"
"git.ecn.io/ian/logtic"
)
func main() {
logger := logtic.New()
// You don't have to specify os.DevNull, however it is good pratice to be explicit that it is
// not being written to any file
logger.FilePath = os.DevNull
// The default level is Error, you can change that at any time
logger.Level = logtic.LevelInfo
if err := logger.Open(); err != nil {
// You probably should panic here, or exit the app
// as failing to open a file to DevNull is a bad sign
panic(err)
}
}
Output:
func (*Logger) Reset ¶
func (l *Logger) Reset()
Reset will reset this logging instance to its original state. Open files will be closed.
func (*Logger) Rotate ¶
Rotate allows you to rate the log file of this logging instance.
When Rotate is called, all pending operations are completed and the current log file is closed. The `act` function is then called where you are expected to perform your rotation operation. If `act` returns an error then the rotation is considered to have failed. It is highly recommended that you either panic or call logger.Reset() as logtic may be in an undefined state and log calls may cause panics.
If `act` returns nil, then the `Open()` method is called for this logger and if successful we return logging operations.
If no log file has been opened on this logger, calls to Rotate do nothing.
func (*Logger) RotateDate ¶
RotateDate will rotate the log file of this logging instance. The current log file will be renamed and suffixed with the date in a YYYY-MM-DD format. A new log file will be opened with the original file path and used for all subsequent writes. Writes will be blocked while the rotation is in progress. If a file matching the name of what would be used for the rotated file, a dash and numerical suffix is added to the end of the name.
If an error is returned during rotation it is highly recommended that you either panic or call logger.Reset() as logtic may be in an undefined state and log calls may cause panics.
If no log file has been opened on this logger, calls to RotateDate do nothing.
Example ¶
This example shows how to trigger a log file rotation
package main
import (
"time"
"git.ecn.io/ian/logtic"
)
func main() {
logtic.Log.FilePath = "/path/to/log/file.log"
if err := logtic.Log.Open(); err != nil {
panic(err)
}
if err := logtic.Log.RotateDate(time.Now().AddDate(0, 0, -1)); err != nil {
// There was an error rotating the log
// It's recommended that you panic or exit here, as logtic is now in an undefined state
panic(err)
}
}
Output:
type LoggerOptions ¶
type LoggerOptions struct {
// Should logtic escape control characters automatically. For example, replaces actual newlines with a literal \n.
// Enabled by default.
EscapeCharacters bool
}
LoggerOptions describe logger options
type Source ¶
type Source struct {
Name string
// contains filtered or unexported fields
}
Source describes a source for log events
func (*Source) ClearLevelOverride ¶
func (s *Source) ClearLevelOverride()
ClearLevelOverride will clear any override log level for this source, reverting back to the level of the parent instance
func (*Source) Debug ¶
Debug will log a debug formatted message.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.Debug("This is a %s message", "debug")
// Terminal output: [DEBUG][Example] This is a debug message
// File output: 2021-03-15T21:43:34-07:00 [DEBUG][Example] This is a debug message
}
Output:
func (*Source) Error ¶
Error will log an error formatted message. Errors are printed to stderr.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.Error("This is a %s message", "error")
// Terminal output: [ERROR][Example] This is a error message
// File output: 2021-03-15T21:43:34-07:00 [ERROR][Example] This is a error message
}
Output:
func (*Source) Fatal ¶
Fatal will log a fatal formatted error message and exit the application with status 1. Fatal messages are printed to stderr.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.Fatal("This is a %s message", "fatal")
// Terminal output: [FATAL][Example] This is a fatal message
// File output: 2021-03-15T21:43:34-07:00 [FATAL][Example] This is a fatal message
}
Output:
func (*Source) GoLogger ¶
GoLogger returns a logger that acts as a proxy between the go/log package and logtic. Printf events sent to this logger will be forwarded to this source with the given level.
func (*Source) Info ¶
Info will log an informational formatted message.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.Info("This is a %s message", "info")
// Terminal output: [INFO][Example] This is a info message
// File output: 2021-03-15T21:43:34-07:00 [INFO][Example] This is a info message
}
Output:
func (*Source) OverrideLevel ¶
OverrideLevel will specify a new log level for this source alone, ignoring the log level of the parent instance
func (*Source) PDebug ¶
PDebug will log a debug parameterized message. Parameterized messages are formatted as key=value strings. Depending on the type of the parameter value, it may be wrapped in single quotes. Byte slices are represented as hexadecimal strings. Parameters are always alphabetically sorted in the outputted string.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.PDebug("Debug event", map[string]any{
"param1": "string",
"param2": 123,
})
// Terminal output: [DEBUG][Example] Debug event: param1='string' param2=123
// File output: 2021-03-15T21:43:34-07:00 [DEBUG][Example] Debug event: param1='string' param2=123
}
Output:
func (*Source) PError ¶
PError will log an error parameterized message. Errors are printed to stderr. Parameterized messages are formatted as key=value strings. Depending on the type of the parameter value, it may be wrapped in single quotes. Byte slices are represented as hexadecimal strings. Parameters are always alphabetically sorted in the outputted string.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.PError("Error event", map[string]any{
"param1": "string",
"param2": 123,
})
// Terminal output: [ERROR][Example] Error event: param1='string' param2=123
// File output: 2021-03-15T21:43:34-07:00 [ERROR][Example] Error event: param1='string' param2=123
}
Output:
func (*Source) PFatal ¶
PFatal will log a fatal parameterized error message and exit the application with status 1. Fatal messages are printed to stderr. Parameterized messages are formatted as key=value strings. Depending on the type of the parameter value, it may be wrapped in single quotes. Byte slices are represented as hexadecimal strings. Parameters are always alphabetically sorted in the outputted string.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.PFatal("Fatal event", map[string]any{
"param1": "string",
"param2": 123,
})
// Terminal output: [FATAL][Example] Fatal event: param1='string' param2=123
// File output: 2021-03-15T21:43:34-07:00 [FATAL][Example] Fatal event: param1='string' param2=123
}
Output:
func (*Source) PInfo ¶
PInfo will log an informational parameterized message. Parameterized messages are formatted as key=value strings. Depending on the type of the parameter value, it may be wrapped in single quotes. Byte slices are represented as hexadecimal strings. Parameters are always alphabetically sorted in the outputted string.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.PInfo("Info event", map[string]any{
"param1": "string",
"param2": 123,
})
// Terminal output: [INFO][Example] Info event: param1='string' param2=123
// File output: 2021-03-15T21:43:34-07:00 [INFO][Example] Info event: param1='string' param2=123
}
Output:
func (*Source) PPanic ¶
PPanic functions like source.PFatal() but panics rather than exits. Parameterized messages are formatted as key=value strings. Depending on the type of the parameter value, it may be wrapped in single quotes. Byte slices are represented as hexadecimal strings. Parameters are always alphabetically sorted in the outputted string.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.PPanic("Panic event", map[string]any{
"param1": "string",
"param2": 123,
})
// Terminal output: [FATAL][Example] Panic event: param1='string' param2=123
// File output: 2021-03-15T21:43:34-07:00 [FATAL][Example] Panic event: param1='string' param2=123
}
Output:
func (*Source) PWarn ¶
PWarn will log a warning parameterized message. Parameterized messages are formatted as key=value strings. Depending on the type of the parameter value, it may be wrapped in single quotes. Byte slices are represented as hexadecimal strings. Parameters are always alphabetically sorted in the outputted string.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.PWarn("Warning event", map[string]any{
"param1": "string",
"param2": 123,
})
// Terminal output: [WARN][Example] Warning event: param1='string' param2=123
// File output: 2021-03-15T21:43:34-07:00 [WARN][Example] Warning event: param1='string' param2=123
}
Output:
func (*Source) PWrite ¶
PWrite will call the matching write function for the given level, printing the provided message. For example:
source.PWrite(logtic.LevelDebug, "My Event", map[string]any{"key": "value"})
is the same as:
source.PDebug("My Event", map[string]any{"key": "value"})
func (*Source) Panic ¶
Panic functions like source.Fatal() but panics rather than exits.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.Panic("This is a %s message", "fatal")
// Terminal output: [FATAL][Example] This is a fatal message
// File output: 2021-03-15T21:43:34-07:00 [FATAL][Example] This is a fatal message
}
Output:
func (*Source) Warn ¶
Warn will log a warning formatted message.
Example ¶
package main
import (
"git.ecn.io/ian/logtic"
)
func main() {
log := logtic.Log.Connect("Example")
log.Warn("This is a %s message", "warning")
// Terminal output: [WARN][Example] This is a warning message
// File output: 2021-03-15T21:43:34-07:00 [WARN][Example] This is a warning message
}
Output:
Source Files
¶
- color.go
- go_logger.go
- level.go
- logger.go
- logtic.go
- params.go
- rotate.go
- source.go