-
Notifications
You must be signed in to change notification settings - Fork 33
Logger Readme
The logger module has the following configuration options found here:
{
"logger": {
"level": "debug",
"format": "pretty"
}
}
-
level
: log level; one ofdebug
,info
,warn
,error
,fatal
,panic
-
format
: log format; one ofpretty
,json
NOTE: Additional process wrapper ma change stdout output. For example, reflex
, used for hot reloading, modifies the log lines. This can be avoided by using the --decoration
flag.
The developer needs to provide the logging level for each log message:
- Debug:
logger.Global.Logger.Debug().Msg(msg)
- Error with
err
:logger.Global.Logger.Error().Err(err).Msg(msg)
- Error without
err
:logger.Global.Logger.Error().Msg(msg)
- Fatal::
logger.Global.Fatal().Err(err).Msg(msg)
Metadata can, and should, be attached to each log level. Using the same key throughout makes the logs easier to parse.
Refer to the zerolog documentation for more information on the available field types.
For example, a single int field can be added like so:
logger.Global.Logger.Debug().Uint64("height", height).Msg("Block committed")
A single string field can be added like so:
logger.Global.Logger.Debug().String("hash", hash).Msg("Block committed")
Multiple fields can be provided using a map:
fields := map[string]interface{}{
"height": height,
"hash": hash,
}
logger.Global.Logger.Debug.Fields(fields).Msg("Block committed")
The global logger should be used when logging outside a module:
import (
...
"github.com/pokt-network/pocket/logger"
...
)
func DoSomething() {
logger.Global.Fatal().Msg("Oops, something went wrong!")
...
}
Each module should have its own logger to appropriately namespace the logs.
type sweetModule struct {
logger *modules.Logger
}
func (m *sweetModule) DoSomething() {
m.logger.Fatal().Msg("Something is fishy!")
...
}
Global
logger is always available from the logger
package.
Each module has its own logger to provide an additional layer of granularity.
Please initiate loggers in the Start
method of the module, like this:
type sweetModule struct {
logger *modules.Logger
}
func (m *sweetModule) Start() error {
m.logger = logger.Global.CreateLoggerForModule(u.GetModuleName())
...
}
A common helpful practice is to create a logger that can be easily filtered for within a specific context, such as a specific submodule, a function or a code path.
m.logger.With().Str("source", "contextName").Logger(),
For example:
func (m *Module) fooFunc() {
fooLogger := m.logger.With().Str("source", "fooFunc").Logger(),
// use fooLogger here
}
Logs are written to stdout. In LocalNet, Loki is used to capture log output. Logs can then be queried using LogQL syntax. Grafana can be used to visualize the logs.
When running LocalNet via make localnet_up
, Grafana can be accessed at localhost:42000.
DOCUMENT: Add common query examples.
Contents
- Home
- Persistence
- Changelog
-
Persistence
- Indexer
- Rpc
- Runtime
- State_Machine
-
Guides
- Roadmap
-
Guides
- Learning
- Guides
-
Guides
- Contributing
- Devlog
-
Guides
- Dependencies
-
Guides
- Releases
- Guides
- P2P
-
Shared
- Crypto
- Shared
-
Shared
- Modules
-
Build
- Config
- Consensus
-
Guides
- Telemetry
- Utility
- Logger