Implement a log handler
With the cfg
and log
packages, you can implement a handler and make it available via config.
Before you begin
Here is a preview of all the code you'll cover in this guide:
main.go
package main
import (
"fmt"
"time"
"github.com/justtrackio/gosoline/pkg/cfg"
"github.com/justtrackio/gosoline/pkg/log"
)
type MyCustomHandlerSettings struct {
Channel string `cfg:"channel"`
}
type MyCustomHandler struct {
channel string
}
func (h *MyCustomHandler) Channels() []string {
return []string{h.channel}
}
func (h *MyCustomHandler) Level() int {
return log.PriorityInfo
}
func (h *MyCustomHandler) Log(timestamp time.Time, level int, msg string, args []interface{}, err error, data log.Data) error {
fmt.Printf("%s happenend at %s", msg, timestamp.Format(time.RFC822))
return nil
}
func MyCustomHandlerFactory(config cfg.Config, name string) (log.Handler, error) {
settings := &MyCustomHandlerSettings{}
log.UnmarshalHandlerSettingsFromConfig(config, name, settings)
return &MyCustomHandler{
channel: settings.Channel,
}, nil
}
func main() {
log.AddHandlerFactory("my-custom-handler", MyCustomHandlerFactory)
}
Implement your custom log handler
Import your gosoline dependencies
Add the following imports to your code:
import (
"fmt"
"time"
"github.com/justtrackio/gosoline/pkg/cfg"
"github.com/justtrackio/gosoline/pkg/log"
)
Here, you imported some standard dependencies, along with the cfg
and log
packages from gosoline.
Create a settings struct
Create a struct that stores log settings:
type MyCustomHandlerSettings struct {
Channel string `cfg:"channel"`
}
cfg:
defines the key you'll use to bind the channel
value from the configuration object to this struct.
Create a new handler
type MyCustomHandler struct {
channel string
}
This handler struct stores the log channel
. To use your handler, you must implement the required methods of the Handler
interface.
Implement the Channels
method
Create a getter for the log channels:
func (h *MyCustomHandler) Channels() []string {
return []string{h.channel}
}
This returns an array of channels, including the one stored on MyCustomHandler
.
Implement the Level
method
Create a getter for the log priority level:
func (h *MyCustomHandler) Level() int {
return log.PriorityInfo
}
Here, you'll return the info level priority.
Implement the Log
method
Create a getter for the log message:
func (h *MyCustomHandler) Log(timestamp time.Time, level int, msg string, args []interface{}, err error, data log.Data) error {
fmt.Printf("%s happenend at %s", msg, timestamp.Format(time.RFC822))
return nil
}
Here, you accept, among other things, a msg
string and a timestamp
. Then, you print a formatted log message, using these values.
Create a handler factory
Create a custom handler factory:
func MyCustomHandlerFactory(config cfg.Config, name string) (log.Handler, error) {
// 1
settings := &MyCustomHandlerSettings{}
// 2
log.UnmarshalHandlerSettingsFromConfig(config, name, settings)
// 3
return &MyCustomHandler{
channel: settings.Channel,
}, nil
}
This accepts a configuration and a name and returns a Handler. You accomplish this with the following steps:
- Initialize
settings
to a new, emptyMyCustomHandlerSettings
struct, which you defined in the last step. - Store the configuration values from the configuration in the
settings
struct. - Create a new
MyCustomHandler
, using thesettings.Channel
.
Add your handler factory
In main()
, or wherever is most appropriate for your application, add your custom handler factory:
log.AddHandlerFactory("my-custom-handler", MyCustomHandlerFactory)
This sets the handler type to "my-custom-handler".
Conclusion
That's it! In this guide, you:
- Implemented a custom Handler.
- Created a handler factory.
- Added your factory to the logging configuration.
Check out these resources to learn more about logging with gosoline: