Introduction
In this article, we’ll create a logging wrapper module that will log messages to Syslog: a standard network-based logging protocol that works on a wide variety of different types of devices and applications.
I chose Syslog because I want to stream FizzBuzz Pro microservices’ logs to Papertrail, and Papertrail has a Syslog server for that purpose listening on a UDP port.
Creating a Papertrail Syslog Destination
Before getting into code, I’ll create a Papertrail log destination. Our logger will use this destination as a sink to stream logs.
Papertrail is a “logging as a service” solution that aggregates logs from applications, devices, and platforms to a central location.
For that, I’ll go to my dashboard, find Log Destinations, and tap Create Log Destination:
Then I’ll give my log destination a description, tap Create, and I’ll be all set:
Note
When you tap Create, you’ll see an endpoint URL in the form of
logs$n.papertrailapp.com:$port
. Note the URL down; you’ll need it when configuring your logger.
Dependencies
Let’s start with the dependencies that we need.
We’ll use the fizz-env
module from the last article. Other dependencies we need are all parts of Go standard library.
// $WORKSPACE/fizz-logging/pkg/log/log.go
package log
import (
"fmt"
"github.com/zerotohero-dev/fizz-env/pkg/env"
"log"
"log/syslog"
"os"
)
Initializing a Syslog Writer
Next up, we’ll write a method that initializes our logger. appName
is the name of our app, typically the name of the microservice that you are streaming the logs for.
// $WORKSPACE/fizz-logging/pkg/log/log.go
var writer *syslog.Writer
func Init(appName string) *syslog.Writer {
e := env.New()
e.SanitizeLog()
// The destination is in the form
// "logs$n.papertrailapp.com:$port".
dest := e.Log.Destination
w, err := syslog.Dial("udp", dest,
syslog.LOG_INFO|syslog.LOG_USER, appName)
if err != nil {
Info("failed to dial syslog for log destination '" +
dest + "'.")
return nil
}
// Cache the writer for other helper methods to call.
writer = w
return writer
}
Wrapping Common Log Methods
Then we’ll create utility methods that call our Syslog writer writer
.
Note that if writer
hasn’t been initialized, or if writer
cannot be initialized, we fall back to the Go standard library’s log
module instead.
// $WORKSPACE/fizz-logging/pkg/log/log.go
func Info(s string, args ...interface{}) {
if writer == nil {
log.Printf(s, args...)
return
}
_ = writer.Info(fmt.Sprintf(s, args...))
}
func Err(s string, args ...interface{}) {
if writer == nil {
log.Printf(s, args...)
return
}
_ = writer.Err(fmt.Sprintf(s, args...))
}
func Warning(s string, args ...interface{}) {
if writer == nil {
log.Printf(s, args...)
return
}
_ = writer.Warning(fmt.Sprintf(s, args...))
}
func Fatal(e interface{}) {
log.Fatal(e)
}
Our Papertrail Syslog Logger in Action
Let’s see our logger in action:
// This will be our microservice that uses the logger.
package main
import "github.com/zerotohero-dev/fizz-logging/pkg/log"
func main() {
// Initialize the logger first:
log.Init("fizz-crypto-svc")
// Log something:
response := 2
log.Info("Got a response '%d' from the server.", response)
}
If you have set up everything correctly, running the above main()
method will stream a log similar to the following to your PaperTrail console.
Conclusion
In this article, we’ve created a logger class that uses a Syslog writer to stream logs to Papertrail over UDP.
We will use (and improve) this logger while developing our FizzBuzz ProAPI microservices.
Read the Source
Below, you’ll find the zip archives of the projects and other related artifacts that we’ve covered in this article.
Enjoy… And may the source be with you 🦄.