Docs
Install
Golang

Golang

HyperDX uses the OpenTelemetry standard for collecting telemetry data (logs and traces). Traces are auto-generated with automatic instrumentation, so manual instrumentation isn't required to get value out of tracing.

This Guide Integrates:

✅ Logs✅ Metrics✅ Traces

Getting Started

Install OpenTelemetry Instrumentation Packages

To install the OpenTelemetry and Hyperdx Go packages, use the command below. It is recommended to check out the current instrumentation packages (opens in a new tab) and install the necessary packages to ensure that the trace information is attached correctly.

go get -u go.opentelemetry.io/otel
go get -u github.com/hyperdxio/otel-config-go
go get -u github.com/hyperdxio/opentelemetry-go
go get -u github.com/hyperdxio/opentelemetry-logs-go

Native HTTP Server Example (net/http)

For this example, we will be using net/http/otelhttp.

go get -u go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp

Refer to the commented sections to learn how to instrument your Go application.

package main
 
import (
	"context"
	"io"
	"log"
	"net/http"
	"os"
 
	"github.com/hyperdxio/opentelemetry-go/otelzap"
	"github.com/hyperdxio/opentelemetry-logs-go/exporters/otlp/otlplogs"
	"github.com/hyperdxio/otel-config-go/otelconfig"
	"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
	"go.opentelemetry.io/otel/trace"
	"go.uber.org/zap"
	sdk "github.com/hyperdxio/opentelemetry-logs-go/sdk/logs"
	semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
  "go.opentelemetry.io/otel/sdk/resource"
)
 
// configure common attributes for all logs
func newResource() *resource.Resource {
	hostName, _ := os.Hostname()
	return resource.NewWithAttributes(
		semconv.SchemaURL,
		semconv.ServiceVersion("1.0.0"),
		semconv.HostName(hostName),
	)
}
 
// attach trace id to the log
func WithTraceMetadata(ctx context.Context, logger *zap.Logger) *zap.Logger {
	spanContext := trace.SpanContextFromContext(ctx)
	if !spanContext.IsValid() {
		// ctx does not contain a valid span.
		// There is no trace metadata to add.
		return logger
	}
	return logger.With(
		zap.String("trace_id", spanContext.TraceID().String()),
		zap.String("span_id", spanContext.SpanID().String()),
	)
}
 
 
func main() {
	// Initialize otel config and use it across the entire app
	otelShutdown, err := otelconfig.ConfigureOpenTelemetry()
	if err != nil {
		log.Fatalf("error setting up OTel SDK - %e", err)
	}
	defer otelShutdown()
 
	ctx := context.Background()
 
	// configure opentelemetry logger provider
	logExporter, _ := otlplogs.NewExporter(ctx)
	loggerProvider := sdk.NewLoggerProvider(
		sdk.WithBatcher(logExporter),
	)
	// gracefully shutdown logger to flush accumulated signals before program finish
	defer loggerProvider.Shutdown(ctx)
 
	// create new logger with opentelemetry zap core and set it globally
	logger := zap.New(otelzap.NewOtelCore(loggerProvider))
	zap.ReplaceGlobals(logger)
	logger.Warn("hello world", zap.String("foo", "bar"))
 
	http.Handle("/", otelhttp.NewHandler(wrapHandler(logger, ExampleHandler), "example-service"))
 
	port := os.Getenv("PORT")
	if port == "" {
		port = "7777"
	}
 
	logger.Info("** Service Started on Port " + port + " **")
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		logger.Fatal(err.Error())
	}
}
 
// Use this to wrap all handlers to add trace metadata to the logger
func wrapHandler(logger *zap.Logger, handler http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		logger := WithTraceMetadata(r.Context(), logger)
		logger.Info("request received", zap.String("url", r.URL.Path), zap.String("method", r.Method))
		handler(w, r)
		logger.Info("request completed", zap.String("path", r.URL.Path), zap.String("method", r.Method))
	}
}
 
func ExampleHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Content-Type", "application/json")
	io.WriteString(w, `{"status":"ok"}`)
}

Gin Application Example

For this example, we will be using gin-gonic/gin.

go get -u go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin

Refer to the commented sections to learn how to instrument your Go application.

package main
 
import (
	"context"
	"log"
	"net/http"
 
	"github.com/gin-gonic/gin"
	"github.com/hyperdxio/opentelemetry-go/otelzap"
	"github.com/hyperdxio/opentelemetry-logs-go/exporters/otlp/otlplogs"
	sdk "github.com/hyperdxio/opentelemetry-logs-go/sdk/logs"
	"github.com/hyperdxio/otel-config-go/otelconfig"
	"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
	"go.opentelemetry.io/otel/trace"
	"go.uber.org/zap"
)
 
// attach trace id to the log
func WithTraceMetadata(ctx context.Context, logger *zap.Logger) *zap.Logger {
	spanContext := trace.SpanContextFromContext(ctx)
	if !spanContext.IsValid() {
		// ctx does not contain a valid span.
		// There is no trace metadata to add.
		return logger
	}
	return logger.With(
		zap.String("trace_id", spanContext.TraceID().String()),
		zap.String("span_id", spanContext.SpanID().String()),
	)
}
 
func main() {
	// Initialize otel config and use it across the entire app
	otelShutdown, err := otelconfig.ConfigureOpenTelemetry()
	if err != nil {
		log.Fatalf("error setting up OTel SDK - %e", err)
	}
 
	defer otelShutdown()
 
	ctx := context.Background()
 
	// configure opentelemetry logger provider
	logExporter, _ := otlplogs.NewExporter(ctx)
	loggerProvider := sdk.NewLoggerProvider(
		sdk.WithBatcher(logExporter),
	)
 
	// gracefully shutdown logger to flush accumulated signals before program finish
	defer loggerProvider.Shutdown(ctx)
 
	// create new logger with opentelemetry zap core and set it globally
	logger := zap.New(otelzap.NewOtelCore(loggerProvider))
	zap.ReplaceGlobals(logger)
 
	// Create a new Gin router
	router := gin.Default()
 
	router.Use(otelgin.Middleware("service-name"))
 
	// Define a route that responds to GET requests on the root URL
	router.GET("/", func(c *gin.Context) {
		_logger := WithTraceMetadata(c.Request.Context(), logger)
		_logger.Info("Hello World!")
		c.String(http.StatusOK, "Hello World!")
	})
 
	// Run the server on port 7777
	router.Run(":7777")
}
 

Configure Environment Variables

Afterwards you'll need to configure the following environment variables in your shell to ship telemetry to HyperDX:

export OTEL_EXPORTER_OTLP_ENDPOINT=https://in-otel.hyperdx.io \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_SERVICE_NAME='<NAME_OF_YOUR_APP_OR_SERVICE>' \
OTEL_EXPORTER_OTLP_HEADERS='authorization=<YOUR_HYPERDX_API_KEY_HERE>'

The OTEL_SERVICE_NAME environment variable is used to identify your service in the HyperDX app, it can be any name you want.

The OTEL_EXPORTER_OTLP_HEADERS environment variable is used to link your telemetry to your HyperDX account, and the API Key can be grabbed from the team page (opens in a new tab)

Hi, how can I help you?