Logging – keeping track of your data

Logging, the act of recording events that occur in a system, is essential to creating performant software systems. Being able to record and validate events within a programming system is a great way to ensure that you're maintaining code quality across versions of your applications. Logs can often quickly show a bug in your software, and being able to consume that information in a quick fashion can often help lower your mean time to recovery (MTTR).

There are many different logging packages for Go. A few of the most popular packages are as follows:

We are going to use the Zap package as our example, as benchmarks have shown. Using the standard library logger is often sufficient (if you've noticed, this is the package that I've used for logging in the book thus far). Having a structured logging package such as Zap available can make up for a pleasant experience because it offers a couple of features that the standard library logger doesn't offer out of the box, such as the following:

  • Logging levels
  • Structured logs (JSON in particular)
  • Typed logs

It also performs best in comparison benchmarks among the loggers. Zap has two different types of logging available, the sugared logger and the structured logger. The structured logger is slightly more performant, whereas the sugared logger is more loosely typed. As this is a book about performance, we are going to take a look at the structured logger as it's more performant, but both logging options are more than adequate for production use. 

Having a logger that has different logging levels is important because it allows you to determine which logs need dire attention and which logs are just returning information. This also lets you set a priority for your team depending on how urgent a fix is when you hit a logging inflection point.

Having logs that can be structured is helpful for ingestion into other systems. JSON logging is quickly becoming more and more popular because log aggregation tools such as the following accept JSON logging:

  • The ELK Stack (ElasticSearch, Logstash, and Kibana)
  • Loggly
  • Splunk
  • Sumologic
  • Datadog
  • Google Stackdriver Logging

As we saw with our APM solutions, we can utilize these logging services to aggregate large groupings of logs in a centralized location, whether it be on premise or in the cloud.

Having typed logs allows you to organize your logging data in a way that makes sense to your program or business. Maintaining consistency in your logging can allow for your system operators and site reliability engineers to more quickly diagnose problems, resulting in a shorter MTTR for production incidents.

Let's have a look at a logging example with Zap:

  1. First, we instantiate our package and import the time package and the Zap logger:
package main

import (
"time"
"go.uber.org/zap"

)
  1. We then set up a logging production configuration that will return logs to stdout (following the twelve-factor app process). These can often go to log routers such as Fluentd (https://www.fluentd.org/), and we can test all of the different log levels available in Zap:
func main() {

c := zap.NewProductionConfig()
c.OutputPaths = []string{"stdout"}
logger, _ := c.Build()

logger.Debug("We can use this logging level to debug. This won't be printed, as the NewProduction logger only prints info and above log levels.")

logger.Info("This is an INFO message for your code. We can log individual structured things here", zap.String("url", "https://reddit.com"), zap.Int("connectionAttempts", 3), zap.Time("requestTime", time.Now()))

logger.Warn("This is a WARNING message for your code. It will not exit your program.")

logger.Error("This is an ERROR message for your code. It will not exit your program, but it will print your error message -> ")

logger.Fatal("This is a Fatal message for your code. It will exit your program with an os.Exit(1).")

logger.Panic("This is a panic message for your code. It will exit your program. We won't see this execute because we have already exited from the above logger.Fatal log message. This also exits with an os.Exit(1)")

}

After we run our logger, we can see some pretty clean JSON output. We can also use a utility such as jq (https://stedolan.github.io/jq/) in order to make this easily consumable in your local environment: 

As we mentioned, having a structured, leveled logger in your Go application will help you to troubleshoot more quickly and effectively.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.20.224.107