otelroundtripper

package module
v0.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2023 License: MIT Imports: 10 Imported by: 0

README

go-otelroundtripper

Build codecov Scrutinizer Code Quality Go Report Card GitHub contributors GitHub license PkgGoDev

This package provides an easy way to collect http related metrics (e.g Response times, Status Codes, number of in flight requests etc) for your HTTP API Clients. You can do this by using this round tripper when instantiating the http.Client{}.

Why this package exists

I currently have to integrate with multiple APIs and I needed a simple way to export metrics for those external API's. Sometimes external API's have their own SDK and the only input is http.Client. In this scenario, I can create an HTTP client with a round tripper automatically exports metrics according to the open telemetry specification.

Installation

go-otelroundtripper is compatible with modern Go releases in module mode, with Go installed:

go get github.com/NdoleStudio/go-otelroundtripper

Alternatively the same can be achieved if you use import in a package:

import "github.com/NdoleStudio/go-otelroundtripper"

Usage

This is a sample code that instantiates an HTTP client which sends requests to https://example.com. You can see a runnable example here

client := http.Client{
    Transport: New(
		WithName("example.com")
        WithMeter(global.MeterProvider()Meter("otel-round-tripper")),
        WithAttributes(
            semconv.ServiceNameKey.String("otel-round-tripper"),
        ),
    ),
}

response, err := client.Get("https://example.com")

Metrics Emitted

The following metrics will be emitted by this package. Note that * will be replaced by the prefix passed in WithName().

  • *.no_request http calls with nil http.Request
  • *.errors http requests which had an error response i.e err != nil
  • *.success http requests which were successfull. Meaning there were no transport errors
  • *.timeouts http requests which timed out
  • *.cancelled http requests with cancelled context
  • *.deadline_exceeded http requests with context dateline exceeded
  • *.total_duration total time it takes to execute the http request in milliseconds
  • *.in_flight concurrent http requests
  • *.attempts http requests attempted
  • *.failures http requests with http status code >= 400
  • *.redirects http requests with 300 <= http status code < 400

Testing

You can run the unit tests for this client from the root directory using the command below:

go test -v

License

This project is licensed under the MIT License - see the LICENSE file for details

Documentation

Overview

Example
package main

import (
	"context"
	"encoding/json"
	"go.opentelemetry.io/otel"
	"log"
	"math/rand"
	"net/http"
	"os"
	"strconv"
	"time"

	"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
	"go.opentelemetry.io/otel/sdk/metric"
	semconv "go.opentelemetry.io/otel/semconv/v1.18.0"
)

func InstallExportPipeline(ctx context.Context) func() {
	// Print with a JSON encoder that indents with two spaces.
	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")
	exporter, err := stdoutmetric.New(stdoutmetric.WithEncoder(enc))
	if err != nil {
		log.Fatalf("creating stdoutmetric exporter: %v", err)
	}

	// Register the exporter with an SDK via a periodic reader.
	sdk := metric.NewMeterProvider(
		metric.WithReader(metric.NewPeriodicReader(exporter)),
	)

	otel.SetMeterProvider(sdk)

	return func() {
		if err := sdk.Shutdown(ctx); err != nil {
			log.Fatalf("stopping sdk: %v", err)
		}
	}
}

func main() {
	ctx := context.Background()

	// Registers a meter Provider globally.
	cleanup := InstallExportPipeline(ctx)
	defer cleanup()

	client := http.Client{
		Transport: New(
			WithMeter(otel.GetMeterProvider().Meter("otel-round-tripper")),
			WithAttributes(
				semconv.ServiceNameKey.String("otel-round-tripper"),
			),
		),
	}

	random := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < 10; i++ {
		// Add a random sleep duration so that we will see the metrics in the console
		url := "https://httpstat.us/200?sleep=" + strconv.Itoa(random.Intn(1000)+1000) //nolint:gosec

		log.Printf("GET: %s", url)
		response, err := client.Get(url)
		if err != nil {
			log.Panicf("cannot perform http request: %v", err)
		}

		_ = response.Body.Close()
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(options ...Option) http.RoundTripper

New creates a new instance of the http.RoundTripper

Types

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option applies a configuration to the given config

func WithAttributes

func WithAttributes(attributes ...attribute.KeyValue) Option

WithAttributes sets a list of attribute.KeyValue labels for all metrics associated with this round tripper

func WithMeter

func WithMeter(meter metric.Meter) Option

WithMeter sets the underlying metric.Meter that is used to create metric instruments By default the no-op meter is used.

func WithName

func WithName(name string) Option

WithName sets the prefix for the metrics emitted by this round tripper. by default, the "http.client" name is used.

func WithParent

func WithParent(parent http.RoundTripper) Option

WithParent sets the underlying http.RoundTripper which is wrapped by this round tripper. If the provided http.RoundTripper is nil, http.DefaultTransport will be used as the base http.RoundTripper

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL