Sending Go Application Logs to Loggly
If you’ve been building web apps long enough, you’ve certainly read through your fair share of logs. One of the more painful parts of going through web app logs is getting them all to the same place. It’s only then you can review your logs and troubleshoot your applications.
In this article, we’ll build a simple Go web app to send logs to SolarWinds® Loggly®. By using the Logrus structured logger for Go and the Logrusly hook for Logrus, we’ll get a jump start on logging and sending those logs directly to Loggly. We’ll also use the Gin Web Framework to provide a simpler route to getting our web app up and running.
Building a simple web application
Since we’re mostly looking at getting our logs to Loggly, we’ll make our application extremely simple. Gin is a lightweight web application framework that emphasizes high performance. The API for building applications is based on the Martini framework. This was popularized during the rise of the Go language, focusing on the HTTP verbs used to make requests against the application.
For this demonstration, we’ll start with the simple ping/pong request outlined in Gin’s quickstart guide. Go get the Gin package and put this code in a file within the module where you installed the package:
This code sets up a default Gin router, which will do things like provide 404 responses for unrecognized routes. It then adds a route on the /ping path, which responds with a simple JSON message of “pong” and a 200 success code. Like we said, it’s extremely simple.
Out of the box, when we run this code, it will log to the standard output.
This is fine for the purposes of our tutorial, but if we’re deploying this anywhere, we’ll want our logs aggregated at our Loggly instance. Let’s look at how Logrus and Logrusly can help us with that.
Structured logging to the cloud
The default Gin logger is useful for seeing information about your application as it’s running. But for our example, we’ll set up Logrus to send structured logs to Loggly when there’s something we might want to be warned about.
First of all, make sure you get both Logrus and Logrusly installed where your app is located:
Once both of these are installed, you can update your imports in your app:
You’ll also need to add the customer token from Loggly to add logs to your Loggly account. Copy and paste it in as a string variable outside your main function:
Next you’ll need to initialize a Logrus logger and add the Logrusly hook to it within the main function:
Let’s discuss what’s going on here. The initialization of the new Loggly hook is where most of the action happens:
- This is where we insert our Loggly customer token.
- We specify a name for the host where this is running (“localhost”).
- We use logrus
.WarnLevelto instruct Logrus to only send things that have a level of Warn or above.
- We indicate that we want to tag all of the logs using this logging hook with two tags: one called “aTag” and the other called “anotherTag.” (Of course, if you were deploying this as your logger, you’d want to use a more appropriate tagging system and provide a real host name, but this should give you an idea of what you can do with this library.)
Finally, add the logging information you want on each of your routes:
Let’s unpack this code too:
l.WithFieldssets up a logger that constructs a log message with the fields we provide.
- We add the location and the response given by the app.
With .Warn("FYI"),we instruct Logrus to log a message of “FYI” at the warning level any time this endpoint is hit.
h.Flush()instructs the hook to send any logs up to Loggly after serving the response to the client hitting this endpoint.
With this in place, here is what we end up sending to Loggly:
When we expand the log item, we see the tags that were added. We can even take a look at the raw message sent to Loggly.
Logrus provides a selection of other levels we could use. Specifically, we could instruct the logger to use the Info logging level. In this example, that wouldn’t end up sending anything to Loggly, since we specified to send only Warn level and above. If we logged a message at the Error level, then that message—with its level higher than Warn—would be sent automatically to Loggly.
Logrus also provides
.Panic() or even
.Fatal() levels of log messages. These will result in your app giving a stack trace on the machine running the code. In the case of
.Panic(), it will require the application to recover, while in the case of
.Fatal(), it will kill the server entirely. So be careful with either of these. That said, Logrus will faithfully send your logs to Loggly if you use either of them.
Once your logs get to Loggly, you can take advantage of log analysis features such as:
- Fast, high-powered, structured search
- Intuitive filtering by fields and time windows
- Custom dashboards and visualizations
- Aggregation of multiple logs into a single place for context and correlation
- Alerts and notifications on custom-defined rules
As your Go applications grow in complexity, logging locally isn’t going to cut it. You’ll have multiple services running—likely on different hosts—and manually sifting through logs across your entire application will be unwieldy. Fortunately, libraries like Logrus and Logrusly simplify the task of sending your logs to a remote, central location—like Loggly.
With logs from every component of your Go application aggregated in a central place, you’ll have the foundation in place for faster troubleshooting. No more trying to hunt down log messages in individual components. No more constant context switching. In Loggly, you’ll get a unified log data stream that is easy to filter, search, and monitor. To learn more about Loggly, sign up for a free trial or request a free demo.
The Loggly and SolarWinds trademarks, service marks, and logos are the exclusive property of SolarWinds Worldwide, LLC or its affiliates. All other trademarks are the property of their respective owners.