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-goNative 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/otelhttpRefer 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/otelginRefer 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)
