go-logging
Synopsis
The go-logging packages build a logging system
upon Go's experimental slog package (https://pkg.go.dev/golang.org/x/exp/slog).

Overview
The Senzing go-logging packages use the message number to coordinate aspects of the log message such as
message identification, message text, and logging level.
Logging levels
go-logging extends the levels of logging to include:
TRACE, DEBUG, INFO, WARN, ERROR, FATAL, and PANIC.
The message number determines the log record level.
The ranges are:
| Level |
Range |
Use |
Comments |
| TRACE |
0000-0999 |
Entry/Exit tracing |
May contain sensitive data. |
| DEBUG |
1000-1999 |
Values seen during processing |
May contain sensitive data. |
| INFO |
2000-2999 |
Process steps achieved |
|
| WARN |
3000-3999 |
Unexpected situations, but processing was successful |
|
| ERROR |
4000-4999 |
Unexpected situations, processing was not successful |
|
| FATAL |
5000-5999 |
The process needs to shutdown |
|
| PANIC |
6000-6999 |
The underlying system is at issue |
|
|
8000-8999 |
Reserved for observer messages |
|
WARNING: TRACE and DEBUG are meant for problem determination and should not be used in normal processing
as the log records, by convention, may contain sensitive data.
Guards
go-logging supports "guards",
e.g. IsXxxxx() methods,
to avoid calling a Log() method that
wouldn't print anyway because of the logging level.
For instance, there's no reason to call a DEBUG Log() method when the
logging level is set to INFO. Guards prevent this.
Example:
if logger.IsDebug() {
logger.Log(1001, complexProcess())
}
Use
The basic use of senzing/go-logging looks like this:
import "github.com/senzing/go-logging/logging"
logger, _ := logging.New()
logger.Log(2001, "Hello world!")
Output:
{"time":"YYYY-MM-DDThh:mm:ss.nnnnnnnnn-00:00","level":"INFO","id":"2001","details":{"1":"Hello World!"}}
Although not all fields may be present for an individual message,
a complete message has these fields:
{
"time": "YYYY-MM-DDThh:mm:ss.nnnnnnnnn-00:00",
"level": "INFO",
"text": "Sent SQL in /var/tmp/tmpfile.sql to database sqlite3://na:xxxxx@/tmp/sqlite/G2C.db",
"id": "senzing-65032002",
"status": "status_message",
"duration": "",
"location": "In processDatabase() at senzingschema.go:129",
"errors": ["unknown value in foo", "bar has no value"],
"details": {
"1": "/var/tmp/tmpfile.sql",
"2": "sqlite3://na:xxxxx@/tmp/sqlite/G2C.db"
}
}
Logging output
By default, logging goes to STDERR.
Since go-logging is built upon the
log
package,
this can be modified using
log.SetOutput().
Examples:
-
To have the output go a file, it would be something like this:
import (
"log"
"os"
"io"
)
aFile, err := os.Open("/path/to/a/logfile")
log.SetOutput(io.Writer(aFile))
-
To have the output go to STDERR and a file, it would be something like this:
import (
"log"
"os"
"io"
)
aFile, err := os.Open("/path/to/a/logfile")
log.SetOutput(io.MultiWriter(os.Stderr, aFile))
In the suite of
senzing-tools,
logging is created by:
import (
"fmt"
"github.com/senzing/go-logging/logging"
)
var (
ComponentId = 9999 // See https://github.com/Senzing/knowledge-base/blob/main/lists/senzing-component-ids.md
IdMessages = map[int]string{ // Message templates. Example: https://github.com/Senzing/init-database/blob/main/senzingconfig/main.go
2000: "Today's greeting: %s",
4000: "Here's what happened: %s",
}
callerSkip = 3 // Used to determine "location" information. See https://pkg.go.dev/runtime#Caller
)
// Logging options. See https://github.com/Senzing/go-logging/blob/main/logging/main.go
loggerOptions := []interface{}{
&logging.OptionCallerSkip{Value: callerSkip},
}
// Create a logger from a factory.
logger, err := logging.NewSenzingToolsLogger(ComponentId, IdMessages, loggerOptions...)
if err != nil {
fmt.Println(err)
}
// Write log record.
logger.Log(2000, "Hello, world!")
// Create an error
err = logger.NewError(4000, "A bad thing")
fmt.Printf("The error: %v\n", err)
Example output:
{"time":"YYYY-MM-DDThh:mm:ss.nnZ","level":"INFO","text":"Today's greeting: Hello, world!","id":"senzing-99992000","location":"In main() at main.go:137","details":{"1":"Hello, world!"}}
The error: {"time":"YYYY-MM-DDThh:mm:ss.nnZ","level":"ERROR","id":"senzing-99994000","text":"Here's what happened: A bad thing","location":"In main() at main.go:140","details":{"1":"A bad thing"}}
References