Skip to content

Commit c641ec4

Browse files
OpenTelemetry tracing (#189)
1 parent 3cc2388 commit c641ec4

15 files changed

Lines changed: 224 additions & 22 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ The deprecated `lstk config profile` command still works but points users to `ls
6565

6666
Environment variables:
6767
- `LOCALSTACK_AUTH_TOKEN` - Auth token (skips browser login if set)
68+
- `LSTK_OTEL=1` - Enables OpenTelemetry trace export (disabled by default); when enabled, standard `OTEL_EXPORTER_OTLP_*` env vars are respected by the SDK. Requires an OTLP-compatible backend to receive and visualize telemetry — for local development, `make otel` starts one (UI at http://localhost:16686).
6869

6970
# Code Style
7071

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ endif
55
BUILD_DIR=bin
66
export CGO_ENABLED=0
77

8-
.PHONY: build clean test test-integration lint mock-generate
8+
.PHONY: build clean test test-integration lint mock-generate otel
99

1010
$(BUILD_DIR)/$(BINARY_NAME):
1111
go build -o $(BUILD_DIR)/$(BINARY_NAME) .
@@ -27,6 +27,9 @@ test-integration: $(BUILD_DIR)/$(BINARY_NAME)
2727
cd test/integration && go run gotest.tools/gotestsum@latest --format testname $$JUNIT -- -count=1 $(if $(RUN),-run $(RUN)) ./...; \
2828
fi
2929

30+
otel:
31+
docker compose -f docker-compose.tracing.yaml up -d
32+
3033
mock-generate:
3134
go generate ./...
3235

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ lstk --non-interactive
154154
|---|---|
155155
| `LOCALSTACK_AUTH_TOKEN` | Auth token used for non-interactive runs or to skip browser login |
156156
| `LOCALSTACK_DISABLE_EVENTS=1` | Disables telemetry event reporting |
157+
| `LSTK_OTEL=1` | Enables OpenTelemetry trace export (disabled by default). When enabled, standard `OTEL_EXPORTER_OTLP_*` env vars are respected by the SDK (e.g. `OTEL_EXPORTER_OTLP_ENDPOINT` defaults to `http://localhost:4318`). Requires an OTLP-compatible backend to receive and visualize telemetry — for local development, `make otel` starts one (UI at http://localhost:16686). |
157158
| `DOCKER_HOST` | Override the Docker daemon socket (e.g. `unix:///home/user/.colima/default/docker.sock`). When unset, lstk tries the default socket and then probes common alternatives (Colima, OrbStack). |
158159

159160
## Usage

cmd/root.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ import (
55
"fmt"
66
"os"
77
"path/filepath"
8+
"strings"
89
"time"
910

11+
"go.opentelemetry.io/otel"
12+
"go.opentelemetry.io/otel/attribute"
13+
"go.opentelemetry.io/otel/codes"
14+
1015
"github.com/localstack/lstk/internal/api"
1116
"github.com/localstack/lstk/internal/auth"
1217
"github.com/localstack/lstk/internal/config"
@@ -16,6 +21,7 @@ import (
1621
"github.com/localstack/lstk/internal/output"
1722
"github.com/localstack/lstk/internal/runtime"
1823
"github.com/localstack/lstk/internal/telemetry"
24+
"github.com/localstack/lstk/internal/tracing"
1925
"github.com/localstack/lstk/internal/ui"
2026
"github.com/localstack/lstk/internal/update"
2127
"github.com/localstack/lstk/internal/version"
@@ -81,6 +87,22 @@ func Execute(ctx context.Context) error {
8187
logger = log.Nop()
8288
}
8389
defer cleanup()
90+
91+
shutdownTracing := func(context.Context) error { return nil }
92+
if cfg.TracesEnabled {
93+
logger.Info("otel tracing enabled")
94+
shutdownTracing = tracing.Init(ctx, logger)
95+
}
96+
defer func() {
97+
// Use a fresh context: the parent ctx may already be cancelled (e.g. Ctrl+C)
98+
// by the time this defer runs, which would cause Shutdown to return immediately
99+
// without flushing buffered spans to the collector.
100+
shutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
101+
defer cancel()
102+
if err := shutdownTracing(shutCtx); err != nil {
103+
logger.Error("failed to shut down tracing: %v", err)
104+
}
105+
}()
84106
logger.Info("lstk %s starting", version.Version())
85107

86108
// Resolve auth token for telemetry: keyring first, then env var.
@@ -96,6 +118,9 @@ func Execute(ctx context.Context) error {
96118
root := NewRootCmd(cfg, tel, logger)
97119
root.SilenceErrors = true
98120
root.SilenceUsage = true
121+
if cfg.TracesEnabled {
122+
wrapCommandsWithTracing(root)
123+
}
99124

100125
if err := root.ExecuteContext(ctx); err != nil {
101126
if !output.IsSilent(err) {
@@ -212,10 +237,39 @@ func commandWithTelemetry(name string, tel *telemetry.Client, fn func(*cobra.Com
212237
}
213238
}
214239

240+
// wrapCommandsWithTracing walks the Cobra command tree and wraps every RunE with
241+
// an OTel span. This is done once after the tree is built so individual commands
242+
// don't need to know about tracing at all.
243+
func wrapCommandsWithTracing(cmd *cobra.Command) {
244+
if cmd.RunE != nil {
245+
original := cmd.RunE
246+
spanName := strings.ReplaceAll(cmd.CommandPath(), " ", ".")
247+
cmd.RunE = func(c *cobra.Command, args []string) error {
248+
ctx, span := otel.Tracer("github.com/localstack/lstk").Start(c.Context(), spanName)
249+
defer span.End()
250+
c.SetContext(ctx)
251+
252+
err := original(c, args)
253+
if err != nil {
254+
span.RecordError(err)
255+
span.SetStatus(codes.Error, err.Error())
256+
span.SetAttributes(attribute.Int("lstk.exit_code", 1))
257+
} else {
258+
span.SetAttributes(attribute.Int("lstk.exit_code", 0))
259+
}
260+
return err
261+
}
262+
}
263+
for _, child := range cmd.Commands() {
264+
wrapCommandsWithTracing(child)
265+
}
266+
}
267+
215268
func isInteractiveMode(cfg *env.Env) bool {
216269
return !cfg.NonInteractive && ui.IsInteractive()
217270
}
218271

272+
219273
const maxLogSize = 1 << 20 // 1 MB
220274

221275
func newLogger() (log.Logger, func(), error) {

cmd/status.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cmd
22

33
import (
44
"fmt"
5-
"net/http"
65
"os"
76

87
"github.com/localstack/lstk/internal/config"
@@ -32,7 +31,7 @@ func newStatusCmd(cfg *env.Env, tel *telemetry.Client) *cobra.Command {
3231
return fmt.Errorf("failed to get config: %w", err)
3332
}
3433

35-
awsClient := aws.NewClient(&http.Client{})
34+
awsClient := aws.NewClient()
3635

3736
if isInteractiveMode(cfg) {
3837
return ui.RunStatus(cmd.Context(), rt, appCfg.Containers, cfg.LocalStackHost, awsClient)

docker-compose.tracing.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Starts Jaeger for local trace collection and visualization.
2+
# UI: http://localhost:16686
3+
# OTLP HTTP: http://localhost:4318 (used by lstk)
4+
# OTLP gRPC: localhost:4317
5+
#
6+
# Usage:
7+
# docker compose -f docker-compose.tracing.yaml up -d
8+
9+
services:
10+
jaeger:
11+
image: jaegertracing/all-in-one:latest
12+
environment:
13+
COLLECTOR_OTLP_ENABLED: "true"
14+
ports:
15+
- "4317:4317" # OTLP gRPC
16+
- "4318:4318" # OTLP HTTP
17+
- "16686:16686" # UI

env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ export LSTK_WEB_APP_URL=https://app.staging.aws.localstack.cloud
99

1010
# Force file-based keyring backend instead of system keychain (optional)
1111
# export LSTK_KEYRING=file
12+
13+
# Enable OpenTelemetry trace export (disabled by default)
14+
# export LSTK_OTEL=1

go.mod

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ require (
2222
github.com/spf13/viper v1.21.0
2323
github.com/stretchr/testify v1.11.1
2424
github.com/zalando/go-keyring v0.2.8
25+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0
26+
go.opentelemetry.io/otel v1.40.0
27+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0
28+
go.opentelemetry.io/otel/sdk v1.40.0
29+
go.opentelemetry.io/otel/trace v1.40.0
2530
go.uber.org/mock v0.6.0
2631
golang.org/x/term v0.42.0
2732
gopkg.in/ini.v1 v1.67.1
@@ -32,6 +37,7 @@ require (
3237
github.com/Microsoft/go-winio v0.6.2 // indirect
3338
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
3439
github.com/aymanbagabas/go-udiff v0.3.1 // indirect
40+
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
3541
github.com/cespare/xxhash/v2 v2.3.0 // indirect
3642
github.com/charmbracelet/colorprofile v0.4.2 // indirect
3743
github.com/charmbracelet/harmonica v0.2.0 // indirect
@@ -55,6 +61,7 @@ require (
5561
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
5662
github.com/godbus/dbus/v5 v5.2.2 // indirect
5763
github.com/google/go-cmp v0.7.0 // indirect
64+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect
5865
github.com/inconshreveable/mousetrap v1.1.0 // indirect
5966
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
6067
github.com/mattn/go-isatty v0.0.20 // indirect
@@ -78,14 +85,17 @@ require (
7885
github.com/subosito/gotenv v1.6.0 // indirect
7986
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
8087
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
81-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect
82-
go.opentelemetry.io/otel v1.40.0 // indirect
83-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 // indirect
88+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect
8489
go.opentelemetry.io/otel/metric v1.40.0 // indirect
85-
go.opentelemetry.io/otel/trace v1.40.0 // indirect
90+
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
8691
go.yaml.in/yaml/v3 v3.0.4 // indirect
92+
golang.org/x/net v0.49.0 // indirect
8793
golang.org/x/sys v0.43.0 // indirect
8894
golang.org/x/text v0.34.0 // indirect
8995
golang.org/x/time v0.14.0 // indirect
96+
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect
97+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
98+
google.golang.org/grpc v1.78.0 // indirect
99+
google.golang.org/protobuf v1.36.11 // indirect
90100
gopkg.in/yaml.v3 v3.0.1 // indirect
91101
)

go.sum

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,16 @@ github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPE
7272
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
7373
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
7474
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
75+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
76+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
7577
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
7678
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
7779
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
7880
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7981
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
8082
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
83+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak=
84+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII=
8185
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
8286
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
8387
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -165,8 +169,12 @@ go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
165169
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
166170
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0=
167171
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8=
172+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
173+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
168174
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4=
169175
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU=
176+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 h1:wVZXIWjQSeSmMoxF74LzAnpVQOAFDo3pPji9Y4SOFKc=
177+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0/go.mod h1:khvBS2IggMFNwZK/6lEeHg/W57h/IX6J4URh57fuI40=
170178
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
171179
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
172180
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
@@ -177,6 +185,8 @@ go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZY
177185
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
178186
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
179187
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
188+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
189+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
180190
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
181191
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
182192
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@@ -185,6 +195,8 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM
185195
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
186196
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
187197
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
198+
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
199+
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
188200
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
189201
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
190202
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -196,14 +208,24 @@ golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
196208
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
197209
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
198210
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
211+
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
212+
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
199213
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls=
200214
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto=
215+
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
216+
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
201217
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=
202218
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
219+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
220+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
203221
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
204222
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
223+
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
224+
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
205225
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
206226
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
227+
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
228+
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
207229
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
208230
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
209231
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

internal/api/client.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"net/url"
1111
"time"
1212

13+
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
14+
1315
"github.com/localstack/lstk/internal/log"
1416
"github.com/localstack/lstk/internal/version"
1517
)
@@ -114,9 +116,17 @@ type PlatformClient struct {
114116

115117
func NewPlatformClient(apiEndpoint string, logger log.Logger) *PlatformClient {
116118
return &PlatformClient{
117-
baseURL: apiEndpoint,
118-
httpClient: &http.Client{Timeout: 30 * time.Second},
119-
logger: logger,
119+
baseURL: apiEndpoint,
120+
httpClient: &http.Client{
121+
Timeout: 30 * time.Second,
122+
Transport: otelhttp.NewTransport(
123+
http.DefaultTransport,
124+
otelhttp.WithSpanNameFormatter(func(_ string, r *http.Request) string {
125+
return "platform " + r.Method + " " + r.URL.Path
126+
}),
127+
),
128+
},
129+
logger: logger,
120130
}
121131
}
122132

0 commit comments

Comments
 (0)