github.com/instana/golang-sensor

:rocket: Go Distributed Tracing & Metrics Sensor for Instana


Keywords
distributed-tracing, go, golang, gopher, instana, instrumentation, metrics, metrics-gathering, monitoring, opentracing, performance, performance-monitoring, trace, tracing
License
MIT
Install
go get github.com/instana/golang-sensor

Documentation

IBM Instana Go Tracer

Build Status PkgGoDev OpenTracing Go Report Card

The IBM Instana Go Tracer is an SDK that collects traces, metrics, logs and provides profiling for Go applications. The tracer is part of the IBM Instana Observability tool set.

Compatibility

Tracer Version Go version
v1.62.0 and higher v1.21.0 and higher
v1.47.0 to v1.61.0 v1.13.0 and higher
Less than v1.47.0 v1.9.0 and higher

Note

Make sure to always use the latest version of the tracer, as it provides new features, improvements, security updates and fixes.

Important

Since v1.53.0, the Go Tracer uses fsm v1.0.1 internally. Customers using fsm prior to v1 in their projects will need to update it to v1.

Installation

To add the tracer to your project, run:

go get -u github.com/instana/go-sensor@latest

Note

As a good practice, add this command to your CI pipeline or your automated tool before building the application to keep the tracer up to date.

Usage

Initial Setup

Once the tracer is added to the project, import the package into the entrypoint file of your application:

import (
  ...
  instana "github.com/instana/go-sensor"
)

Create a reference to the collector and initialize it with a service name:

var (
  ...
  col instana.TracerLogger
)

func init() {
  ...
  col = instana.InitCollector(&instana.Options{
    Service: "My app",
  })
}

Note

The tracer expects the Instana Agent to be up and running in the default port 42699. You can change the port with the environment variable INSTANA_AGENT_PORT.

Note

For non default options, like the Agent host and port, the tracer can be configured either via SDK options, environment variables or Agent options.

Collecting Metrics

Once the collector has been initialized with instana.InitCollector, application metrics such as memory, CPU consumption, active goroutine count etc will be automatically collected and reported to the Agent without further actions or configurations to the SDK. This data is then already available in the dashboard.

Tracing Calls

Let's collect traces of calls received by an HTTP server.

Before any changes, your code should look something like this:

// endpointHandler is the standard http.Handler function
http.HandleFunc("/endpoint", endpointHandler)

log.Fatal(http.ListenAndServe(":9090", nil))

Wrap the endpointHandler function with instana.TracingHandlerFunc. Now your code should look like this:

// endpointHandler is now wrapped by `instana.TracingHandlerFunc`
http.HandleFunc("/endpoint", instana.TracingHandlerFunc(col, "/endpoint", endpointHandler))

log.Fatal(http.ListenAndServe(":9090", nil))

When running the application, every time /endpoint is called, the tracer will collect this data and send it to the Instana Agent. You can monitor traces to this endpoint in the Instana UI.

Profiling

Unlike metrics, profiling needs to be enabled with the EnableAutoProfile option, as seen here:

col = instana.InitCollector(&instana.Options{
  Service: "My app",
  EnableAutoProfile: true,
})

You should be able to see your application profiling in the Instana UI under Analytics/Profiles.

Logging

In terms of logging, the SDK provides two distinct logging features:

  1. Traditional logging, that is, logs reported to the standard output, usually used for debugging purposes
  2. Instana logs, a feature that allows customers to report logs to the dashboard under Analytics/Logs

Traditional Logging

Many logs are provided by the SDK, usually prefixed with "INSTANA" and are useful to understand what the tracer is doing underneath. It can also be used for debugging and troubleshoot reasons. Customers can also provide logs by calling one of the following: Collector.Info(), Collector.Warn(), Collector.Error(), Collector.Debug(). You can setup the log level via options or the INSTANA_LOG_LEVEL environment variable.

You can find detailed information in the Instana documentation.

Instana Logs

Instana Logs are spans of the type log.go that are rendered in a special format in the dashboard. You can create logs and report them to the agent or attach them as children of an existing span.

The code snippet below shows how to create logs and send them to the agent:

col := instana.InitCollector(&instana.Options{
  Service: "My Go App",
})

col.StartSpan("log.go", []ot.StartSpanOption{
  ot.Tags{
    "log.level":   "error", // available levels: info, warn, error, debug
    "log.message": "error from log.go span",
  },
}...).Finish() // make sure to "finish" the span, so it's sent to the agent

This log can then be visualized in the dashboard under Analytics/Logs. You can add a filter by service name. In our example, the service name is "My Go App".

Opt-in Exit Spans

Go tracer support the opt-in feature for the exit spans. When enabled, the collector can start capturing exit spans, even without an entry span. This capability is particularly useful for scenarios like cronjobs and other background tasks, enabling the users to tailor the tracing according to their specific requirements. By setting the INSTANA_ALLOW_ROOT_EXIT_SPAN variable, users can choose whether the tracer should start a trace with an exit span or not. The environment variable can have 2 values. (1: Tracer should record exit spans for the outgoing calls, when it has no active entry span. 0 or any other values: Tracer should not start a trace with an exit span).

export INSTANA_ALLOW_ROOT_EXIT_SPAN=1

Complete Example

Basic Usage

package main

import (
  "log"
  "net/http"

  instana "github.com/instana/go-sensor"
)

func main() {
  col := instana.InitCollector(&instana.Options{
    Service:           "Basic Usage",
    EnableAutoProfile: true,
  })

  http.HandleFunc("/endpoint", instana.TracingHandlerFunc(col, "/endpoint", func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
  }))

  log.Fatal(http.ListenAndServe(":7070", nil))
}

Wrapping up

Let's quickly summarize what we have seen so far:

  1. We learned how to install, import and initialize the Instana Go Tracer.
  2. Once the tracer is initialized, application metrics are collected out of the box.
  3. Application profiling can be enabled via the EnableAutoProfile option.
  4. Tracing incoming HTTP requests by wrapping the Go standard library http.Handler with instana.TracingHandlerFunc.

With this knowledge it's already possible to make your Go application traceable by our SDK. But there is much more you can do to enhance tracing for your application.

The basic functionality covers tracing for the following standard Go features:

  1. HTTP incoming requests
  2. HTTP outgoing requests
  3. SQL drivers

As we already covered HTTP incoming requests, we suggest that you understand how to collect data from HTTP outgoing requests and SQL driver databases.

Another interesting feature is the usage of additional packages located under instrumentation. Each of these packages provide tracing for specific Go packages like the AWS SDK, Gorm and Fiber.

What's Next

  1. Tracer Options
  2. Tracing HTTP Outgoing Requests
  3. Tracing SQL Driver Databases
  4. Tracing Other Go Packages
  5. Instrumenting Code Manually