Skip to main content
GreenSlope

Go quickstart

Target: first trace in your tenant in about five minutes. Go's OTel ecosystem is less auto-instrumenting than Node's — you'll wire one handler wrapper manually. That's the only sharp edge.

1. Sign up and grab your tenant key

Create a tenant and copy your tenant ingest key. Export it to your environment:

export GREENSLOPE_INGEST_KEY="gs_ing_live_…"

2. Install the OTel modules

go get \
  go.opentelemetry.io/otel \
  go.opentelemetry.io/otel/sdk \
  go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp \
  go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp \
  go.opentelemetry.io/otel/semconv/v1.26.0

3. Initialise the tracer provider

// telemetry.go
package main
 
import (
	"context"
	"os"
 
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)
 
func initTracing(ctx context.Context, serviceName, version, releaseID string) (func(context.Context) error, error) {
	exp, err := otlptracehttp.New(ctx,
		otlptracehttp.WithEndpoint("ingest.greenslope.io"),
		otlptracehttp.WithURLPath("/v1/otel/v1/traces"),
		otlptracehttp.WithHeaders(map[string]string{
			"x-greenslope-key": os.Getenv("GREENSLOPE_INGEST_KEY"),
		}),
	)
	if err != nil {
		return nil, err
	}
 
	res, err := resource.New(ctx,
		resource.WithAttributes(
			semconv.ServiceName(serviceName),
			semconv.ServiceVersion(version),
			attribute.String("greenslope.release.id", releaseID),
		),
	)
	if err != nil {
		return nil, err
	}
 
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(exp),
		sdktrace.WithResource(res),
	)
	otel.SetTracerProvider(tp)
	return tp.Shutdown, nil
}

4. Wrap your HTTP handler

Unlike Node, Go doesn't auto-patch net/http — you opt-in per handler. Wrap your mux with otelhttp.NewHandler:

// main.go
package main
 
import (
	"context"
	"log"
	"net/http"
	"os"
 
	"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
 
func main() {
	ctx := context.Background()
	shutdown, err := initTracing(ctx, "api", "0.0.0",
		os.Getenv("GIT_SHA"))
	if err != nil {
		log.Fatal(err)
	}
	defer shutdown(ctx)
 
	mux := http.NewServeMux()
	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("ok"))
	})
 
	log.Fatal(http.ListenAndServe(":3000",
		otelhttp.NewHandler(mux, "server")))
}

5. Run and hit the endpoint

go run .
# in another terminal
curl http://localhost:3000/health

Verify

Open Live traces at app.greenslope.io. Look for a span with http.route=/health and your three resource attributes set.

Blank? Check Troubleshooting.

Related