Go
Traces | Metrics | App Logs | Custom Logs | Profiling |
---|---|---|---|---|
✅ | ✅ | ✖ | ✅ | ✅ |
This guide walks you through setting up Application Performance Monitoring (APM) on a Go application. These instructions can also be found on the Installation page in your Middleware Account. View example code here.
Prerequisites
- Middleware Agent: See the Installation Instructions for more details.
- Go Version 1.17 or above: Check your Go version with
go version
Install
Step 1: Install Go
APM Package
Run the following command in your terminal.
main.go
go get github.com/middleware-labs/golang-apm@latest
Step 2: Import Tracker
Add the following lines to the entry point of your application, and as the first import.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" )
Add the following snippet to your main function. The accessToken is your account key, which will be pre-filled if you're logged into the documentation. It may also be found on the Installation page in the platform.
If using a Golang web framework, additional code may be required, see Framework-Specific Configuration.
go track.Track( track.WithConfigTag("service", {APM-SERVICE-NAME}), track.WithConfigTag("accessToken", "<MW_API_KEY>"), )
go track.Track( track.WithConfigTag("service", {APM-SERVICE-NAME}), track.WithConfigTag("accessToken", "<MW_API_KEY>"), track.WithConfigTag("target", "https://<MW_UID>.middleware.io:443"), )
Host Based Configuration
If you are deploying the host using Kubernetes or Docker you will need to set the environment variable MW_AGENT_SERVICE
.
This variable can be ignored when the agent is running on the same host as the application.
Add MW_AGENT_SERVICE
environment variable to your application:
docker run \ -e MW_AGENT_SERVICE=<DOCKER_BRIDGE_GATEWAY_ADDRESS> \ -p 8000:8000 -it --rm --name CONTAINER_NAME DOCKER_IMAGE:IMAGE_TAG
The DOCKER_BRIDGE_GATEWAY_ADDRESS
is the IP address of the gateway between the Docker host and bridge network. This is 172.17.0.1
by default. Learn more about Docker bridge networking here
Identify the namespace where the Infra Agent is running:
kubectl get service --all-namespaces | grep mw-service
Then add the following environment variable to your application deployment YAML file:
MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local
Framework-Specific Configuration
If any of the following Go web frameworks are used in your application, additional configuration is required. View additional configuration steps per framework below.
gin/gonic
Middleware APM requires Gin v1.1.18
or higher.
Install the Middleware APM Gin package.
main.go
go get github.com/middleware-labs/golang-apm-gin@latest
Add the Middleware APM Gin package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mwgin "github.com/middleware-labs/golang-apm-gin/gin" )
Initialize the Middleware APM wherever the Gin package is initialized, typically in the main function.
r := gin.Default() config, _ := track.Track( track.WithConfigTag("service","<apm-service-name>"), track.WithConfigTag("accessToken","<MW_API_KEY>"), ) r.Use(mwgin.Middleware(config))
gorilla/mux
Middleware APM requires MUX v1.8.0
Install the Middleware APM MUX package.
main.go
go get github.com/middleware-labs/golang-apm-mux@latest
Add the Middleware APM MUX package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mwmux "github.com/middleware-labs/golang-apm-mux/mux" )
Initialize the Middleware APM wherever the MUX package is initialized, typically in the main function.
r := mux.newRouter() config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) r.Use(mwmux.Middleware(config))
go-chi
Middleware APM requires go-chi/chi v1.5.4
or higher.
Install the Middleware APM go-chi package.
main.go
go get github.com/middleware-labs/agent-apm-go-chi-legacy@latest
Add the Middleware APM go-chi package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mwchi "github.com/middleware-labs/agent-apm-go-chi-legacy" )
Initialize the Middleware APM wherever the go-chi package is initialized, typically in the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) r := chi.NewRouter() r.Use(mwchi.Middleware("<my-server>", mwchi.WithChiRoutes(r)))
go-chi/v5
Middleware APM requires go-chi/chi/v5 v5.0.8
or higher.
Install the Middleware APM go-chi package.
main.go
go get github.com/middleware-labs/agent-apm-go-chi@latest
Add the Middleware APM go-chi package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mwchi "github.com/middleware-labs/agent-apm-go-chi" )
Initialize the Middleware APM wherever the go-chi package is initialized, typically in the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) r := chi.NewRouter() r.Use(mwchi.Middleware("<my-server>", mwchi.WithChiRoutes(r)))
astaxie-beego
Middleware APM requires astaxie/beego v1.12.3
or higher.
Install the Middleware APM astaxie-beego package.
main.go
go get github.com/middleware-labs/golang-apm-beego@latest
Add the Middleware APM astaxie-beego package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mw_beego "github.com/middleware-labs/golang-apm-beego/beego" )
Initialize the Middleware APM wherever the astaxie-beego package is initialized, typically in the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) mware := mw_beego.Middleware(config)
beego/v2
Middleware APM requires beego/v2 v2.0.7
or higher.
Install the Middleware APM astaxie-beego package.
main.go
go get github.com/middleware-labs/golang-apm-beego@latest
Add the Middleware APM astaxie-beego package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mw_beego "github.com/middleware-labs/golang-apm-beego/beego" )
Initialize the Middleware APM wherever the astaxie-beego package is initialized, typically in the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) mware := mw_beego.Middleware(config)
database/sql
Middleware APM requires go-sql-driver/mysql v1.7.1
or higher.
Install the Middleware APM SQL package.
main.go
go get github.com/middleware-labs/golang-apm-sql@latest
Add the Middleware APM SQL package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mw_sql "github.com/middleware-labs/golang-apm-sql/sql" )
Initialize the Middleware APM wherever the SQL package is initialized, typically in the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) db, err := mw_sql.Open("mysql", "uname:password@tcp(127.0.0.1:3306)/dbname")
go-pg/pg
Middleware APM requires go-pg/pg v10.11.1
or higher.
Install the Middleware APM PG package.
main.go
go get github.com/middleware-labs/golang-apm-pg@latest
Add the Middleware APM PG package to the existing import statement from Step 2.
main.go
import ( "github.com/go-pg/pg/v10" track "github.com/middleware-labs/golang-apm/tracker" mw_pg "github.com/middleware-labs/golang-apm-pg/pg" )
Initialize the Middleware APM wherever the PG package is initialized, typically in the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) db := pg.Connect(&pg.Options{ Addr: ":5432", User: "postgres", Password: "postgres", Database: "dbname", })
jinzhu/gorm
Middleware APM requires jinzhu/gorm v1.9.16
or higher.
Install the Middleware APM SQL package.
main.go
go get github.com/middleware-labs/golang-apm-sql@latest
Add the Middleware APM SQL package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mw_sql "github.com/middleware-labs/golang-apm-sql/sql" )
Initialize the Middleware APM inside the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) db, err := mw_sql.Open(driverName, dataSourceName, mw_sql.WithDBName(dbname), mw_sql.WithAttributes(tracker.String("db.system","mysql")))
gorm.io/gorm
Middleware APM requires gorm.io/gorm v1.25.1
or higher.
Install the Middleware APM GORM package.
main.go
go get github.com/middleware-labs/go-agent-gorm@latest
To instrument GORM, you need to install the plugin
main.go
import ( "gorm.io/driver/sqlite" "gorm.io/gorm" track "github.com/middleware-labs/golang-apm/tracker" mw_gorm "github.com/middleware-labs/go-agent-gorm/gorm" ) track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"),
Then use db.WithContext(ctx) to propagate the active span.
main.go
var num int if err := db.WithContext(ctx).Raw("SELECT 42").Scan(&num).Error; err != nil { panic(err) }
mongo
Middleware APM requires go.mongodb.org/mongo-driver v1.12.1
or higher.
Install the Middleware APM Mongo package.
main.go
go get github.com/middleware-labs/golang-apm-mongo@latest
Add the Middleware APM Mongo package to the existing import statement from Step 2.
main.go
import ( "go.mongodb.org/mongo-driver/mongo/options" track "github.com/middleware-labs/golang-apm/tracker" mw_mongo "github.com/middleware-labs/golang-apm-mongo/mongo" )
Initialize the Middleware APM inside the main function.
config, _ := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) opts := options.Client() opts.Monitor = mw_mongo.NewMonitor() opts.ApplyURI(<uri>)
gRPC
Middleware APM requires google.golang.org/grpc v1.53.0
or higher.
Install the Middleware APM gRPC package.
main.go
go get github.com/middleware-labs/golang-apm-grpc@latest
Add the Middleware APM grpc package to the existing import statement from Step 2.
main.go
import ( mw_grpc "github.com/middleware-labs/golang-apm-grpc/grpc" track "github.com/middleware-labs/golang-apm/tracker" )
Initialize the Middleware APM wherever the grpc server is initialized, typically in the main function.
track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) server := grpc.NewServer( grpc.UnaryInterceptor(mw_grpc.UnaryServerInterceptor()), grpc.StreamInterceptor(mw_grpc.StreamServerInterceptor()))
Initialize the Middleware APM wherever the grpc client is initialized, typically in the main function.
config, err := track.Track( track.WithConfigTag("service", "<apm-service-name>"), track.WithConfigTag("accessToken", "<MW_API_KEY>"), ) if err != nil { fmt.Println("err", err) } defer func() { if err := config.Tp.Shutdown(context.Background()); err != nil {
net/http
Install the Middleware APM net/http package.
main.go
go github.com/middleware-labs/golang-apm-http
Add the Middleware APM http package to the existing import statement from Step 2.
main.go
import ( track "github.com/middleware-labs/golang-apm/tracker" mwhttp "github.com/middleware-labs/golang-apm-http/http" )
The code snippet below initializes Middleware Go APM package and shows how to use it with net/http.
go track.Track( track.WithConfigTag(track.Service, "your service name"), track.WithConfigTag(track.Token, "your access token"), ) http.Handle("/hello", mwhttp.MiddlewareHandler(http.HandlerFunc(hello), "hello"))
Sending Custom Data
Custom Logs
To ingest custom logs into Middleware, utilize the following functions inside your logging method based on desired log severity levels.
logrus
otellog "github.com/middleware-labs/golang-apm/mwotellogrus" track "github.com/middleware-labs/golang-apm/tracker" log "github.com/sirupsen/logrus" .... config, _ := track.Track( track.WithConfigTag("service", "your-service-name"), track.WithConfigTag("accessToken", "access_token"), )
slog
"log/slog" "github.com/middleware-labs/golang-apm/mwotelslog" track "github.com/middleware-labs/golang-apm/tracker" .... config, _ := track.Track( track.WithConfigTag("service", "your-service-name"), track.WithConfigTag("accessToken", "access_token"), ) defer func() {
zap
mwotelzap "github.com/middleware-labs/golang-apm/mwotelzap" track "github.com/middleware-labs/golang-apm/tracker" "go.uber.org/zap" "go.uber.org/zap/zapcore" .... config, _ := track.Track( track.WithConfigTag("service", "your-service-name"), track.WithConfigTag("accessToken", "access_token"),
Record Error
Use the track.ErrorRecording(ctx,error)
method to record a stack trace when an error occurs. See an example of this method below.
err := errors.New("something went wrong") track.ErrorRecording(ctx, err)
Get Current Span
To get the current span, you’ll need to pull it out of a context.Context you have a handle on:
track.SpanFromContext(ctx)
Custom Spans
To create a span with a tracer, you'll need a context.Context
instance, usually derived from a request object. This context may already carry a parent span from an existing instrumentation.
config,err := track.Track( track.WithConfigTag("service", {APM-SERVICE-NAME}), track.WithConfigTag("accessToken", "your-initial-token"), ) tp := config.Tp _,span := tp.Tracer("example-tracer").Start(ctx,"example-span") defer span.End()
Custom Events
span.AddEvent("Starting to find books")
Custom Attributes
Attributes are keys and values that are applied as metadata to your spans and are useful for aggregating, filtering, and grouping traces. Attributes can be added at span creation, or at any other time during the lifecycle of a span before it has completed.
ctx := c.Request.Context() track.SetAttribute(ctx, "user.id", "1")
Custom Resource Attributes
Resource attributes are key-value pairs that describe specific characteristics of a service or system component, like its name, version, or environment. These attributes help in tracking and analyzing the behavior of the resource in logs, metrics, or traces.
customResourceAttributes = map[string]interface{}{ "key1": "value1", "key2": 42, "key3": true, } track.WithConfigTag(track.CustomResourceAttributes,customResourceAttributes),
Continuous Profiling
Application Profiling is auto-configured upon completing Step 2.
Continuous profiling captures real-time performance insights from your application to enable rapid identification of resource allocation, bottlenecks, and more. Navigate to the Continuous Profiling section to learn more about using Continuous Profiling with the Go APM.
Telemetry Options
The Pause* options allow you to disable specific telemetry data (metrics, traces, logs) and profiling. Use these to reduce overhead by pausing unnecessary data collection.
PauseMetrics
If you want to disable metrics, you can use PauseMetrics, or you can set the environment variable MW_APM_COLLECT_METRICS to false.
track.WithConfigTag(track.PauseMetrics,true),
PauseDefaultMetrics
If you want to disable only default runtime metrics.
track.WithConfigTag(track.PauseDefaultMetrics,true),
PauseTraces
If you want to disable traces, you can use PauseTraces, or you can set the environment variable MW_APM_COLLECT_TRACES to false.
track.WithConfigTag(track.PauseTraces,true),
PauseLogs
If you want to disable logs, you can use PauseLogs, or you can set the environment variable MW_APM_COLLECT_LOGS to false.
track.WithConfigTag(track.PauseLogs,true),
PauseProfiling
If you want to disable Profiling, you can use PauseProfiling, or you can set the environment variable MW_APM_COLLECT_PROFILING to false.
track.WithConfigTag(track.PauseProfiling,true),
Debug Mode
The debug option enables detailed logging of metrics, traces, and logs by printing structured telemetry data directly to the standard output. This mode is ideal for local development and troubleshooting, providing real-time insights into the application's execution and performance.
track.WithConfigTag(track.Debug,true),
Debug Log File
When DebugLogFile is enabled, structured telemetry data (metrics, traces, logs) is saved to files instead of being printed to the standard output. This allows for easier storage, analysis, and sharing of debug information without cluttering the console during development.
track.WithConfigTag(track.Debug,true), track.WithConfigTag(track.DebugLogFile,true),
Need assistance or want to learn more about Middleware? Contact our support team in Slack.