Introduction to Go Custom Metrics with Logz.io RemoteWrite SDK from Logz.io

RemoteWrite for Go

We recently announced the release of our RemoteWrite SDK to support custom metrics from applications using several different languages – The first SDKs allow shipping of metrics from Golang (Go), PythonJava, Node.js, and .NET.

This tutorial will cover the Golang SDK.

The SDKs cover not just Logz.io, but can be used by any platform that supports the Prometheus remote write endpoint. Prometheus users can send metrics directly to Logz.io using the RemoteWrite protocol, with each capable of working with frameworks like Thanos, Cortex, and of course M3DB

Configure Golang for Shipping Custom Metrics 

Go is one of the simpler implementations, as the only prerequisite you’ll need is Go itself. The latest version, as of this writing, is 1.17.1. 

You can head to Go’s official download page to find packages for all OS’s. Alternatively, you can download with Homebrew for Mac or install on Docker.

On Mac:

brew install go

On Docker:

docker pull golang

Next, install the OpenTelemetry SDK and exporter.

go get -u go.opentelemetry.io/contrib/exporters/metric/cortex

Next, create a .go file for your application. Have your Logz.io Metrics Token and Logz.io listener address ready to add to the file. Finally, add the following instrumentation code to the file and paste in the token and address:

package main

import (
	"context"
	"fmt"
	"time"

	"go.opentelemetry.io/contrib/exporters/metric/cortex"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/metric"
	controller "go.opentelemetry.io/otel/sdk/metric/controller/basic"
	"go.opentelemetry.io/otel/sdk/resource"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

func main() {
	// Create a new Config struct.
	config := cortex.Config{
		Endpoint:      "<<LISTENER-HOST>>",
		RemoteTimeout: 30 * time.Second,
		PushInterval:  15 * time.Second,
		BearerToken:   "<<PROMETHEUS-METRICS-SHIPPING-TOKEN>>",
	}
	// Create and install the exporter. Additionally, set the push interval to 15 seconds
	// and add a resource to the controller.
	pusher, err := cortex.InstallNewPipeline(config,
		controller.WithCollectPeriod(15*time.Second),
		controller.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			attribute.String("p8s_logzio_name", "LABEL_NAME")),
		),
	)
	if err != nil {
		fmt.Printf("Error: %v", err)
	}
	ctx := context.Background()
	defer handleErr(pusher.Stop(ctx))
	// Create a counter and a value recorder
	meter := pusher.MeterProvider().Meter("go_metrics")
	// Create instruments
	counter := metric.Must(meter).NewInt64Counter(
		"go_metrics.counter",
		metric.WithDescription("Counts things"),
	)
	// Start the metrics pipeline
	pusher.Start(ctx)
	// Record values to the instruments and add labels
	counter.Add(ctx, 10, attribute.String("key", "value"))
}
func handleErr(err error) {
	if err != nil {
		fmt.Println("Encountered error: ", err.Error())
	}
}

For the address, it should be structured as either of these two options depending on if you’re using the http or https protocol:

http://listener.logz.io:8052
https://listener.logz.io:8053

You can also add customized names for your metrics at attribute.String().

Individual Go Custom Metric Options

Including counter, you can create one of six  types of metric instruments with OpenTelemetry: updowncounter, valuerecorder, sumobserver, updownsumobserver, valueobserver. Other instruments include an asynchronous counter, asynchronous gauge, asynchronous updowncounter, and histograms.

Instruments report measurements (i.e., the metric values themselves), meters are a class that create instruments; MeterProvider is the entry point for the API and the meters.

To add any of those instruments to your configuration, use the code snippets in our docs. Here’s one example using the counter instrument:

// create counter instruments
counter := metric.Must(meter).NewInt64Counter(
	"go_metrics.counter",
	metric.WithDescription("your metric description"),
)
float_counter := metric.Must(meter).NewFloat64Counter(
	"go_metrics.float_counter",
	metric.WithDescription("your metric description"),
)
// Record values to the instruments and add labels
counter.Add(ctx, int64(10), attribute.String("key", "value"))
float_counter.Add(ctx, float64(8.3), attribute.String("key", "value"))

As an alternative example, you can employ an updowncounter:

// create updowncounter instruments
updowncounter := metric.Must(meter).NewInt64UpDownCounter(
	"go_metrics.updowncounter",
	metric.WithDescription("your metric description"),
)
float_updowncounter := metric.Must(meter).NewFloat64UpDownCounter(
	"go_metrics.float_updowncounter",
	metric.WithDescription("your metric description"),
)
// Record values to the instruments and add labels
updowncounter.Add(ctx, int64(-3), attribute.String("key", "value"))
float_updowncounter.Add(ctx, float64(8.3), attribute.String("key", "value"))

Better Metrics

This integration shows Logz.io’s commitment to and enthusiasm for OpenTelemetry, and also accommodates developers working in and on original projects. Direct-from-code metrics – plus other forms of telemetry – will see further support from us with new SDK options in other languages in the very near future.

Subscribe to the Logz.io blog for more updates!

Try Prometheus-as-a-Service and our Advanced Metrics UI!

Internal

Organize Your Kubernetes Logs On One Unified SaaS Platform

Learn More