Skip to content

Commit 4fadd1a

Browse files
authored
Otel more (#742)
instrument `otelslog` to ship logs as well, this rejiggers some env vars around so that things use the more generic `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`. also adds a few more spans/attrs for the various `imagetest_test` phases
1 parent 12b59c6 commit 4fadd1a

File tree

12 files changed

+253
-167
lines changed

12 files changed

+253
-167
lines changed

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ require (
3434
github.com/moby/docker-image-spec v1.3.1
3535
github.com/samber/slog-multi v1.7.1
3636
github.com/stretchr/testify v1.11.1
37+
go.opentelemetry.io/contrib/bridges/otelslog v0.15.0
3738
go.opentelemetry.io/otel v1.40.0
39+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.16.0
3840
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0
3941
go.opentelemetry.io/otel/sdk v1.40.0
42+
go.opentelemetry.io/otel/sdk/log v0.16.0
4043
go.opentelemetry.io/otel/trace v1.40.0
4144
golang.org/x/sync v0.19.0
4245
k8s.io/api v0.35.1
@@ -173,6 +176,7 @@ require (
173176
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect
174177
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
175178
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect
179+
go.opentelemetry.io/otel/log v0.16.0 // indirect
176180
go.opentelemetry.io/otel/metric v1.40.0 // indirect
177181
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
178182
go.step.sm/crypto v0.76.0 // indirect

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,20 +500,30 @@ go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo=
500500
go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I=
501501
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
502502
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
503+
go.opentelemetry.io/contrib/bridges/otelslog v0.15.0 h1:yOYhGNPZseueTTvWp5iBD3/CthrmvayUXYEX862dDi4=
504+
go.opentelemetry.io/contrib/bridges/otelslog v0.15.0/go.mod h1:CvaNVqIfcybc+7xqZNubbE+26K6P7AKZF/l0lE2kdCk=
503505
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo=
504506
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ=
505507
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
506508
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
507509
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
508510
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
511+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.16.0 h1:djrxvDxAe44mJUrKataUbOhCKhR3F8QCyWucO16hTQs=
512+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.16.0/go.mod h1:dt3nxpQEiSoKvfTVxp3TUg5fHPLhKtbcnN3Z1I1ePD0=
509513
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
510514
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
511515
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 h1:wVZXIWjQSeSmMoxF74LzAnpVQOAFDo3pPji9Y4SOFKc=
512516
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0/go.mod h1:khvBS2IggMFNwZK/6lEeHg/W57h/IX6J4URh57fuI40=
517+
go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4=
518+
go.opentelemetry.io/otel/log v0.16.0/go.mod h1:rWsmqNVTLIA8UnwYVOItjyEZDbKIkMxdQunsIhpUMes=
513519
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
514520
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
515521
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
516522
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
523+
go.opentelemetry.io/otel/sdk/log v0.16.0 h1:e/b4bdlQwC5fnGtG3dlXUrNOnP7c8YLVSpSfEBIkTnI=
524+
go.opentelemetry.io/otel/sdk/log v0.16.0/go.mod h1:JKfP3T6ycy7QEuv3Hj8oKDy7KItrEkus8XJE6EoSzw4=
525+
go.opentelemetry.io/otel/sdk/log/logtest v0.16.0 h1:/XVkpZ41rVRTP4DfMgYv1nEtNmf65XPPyAdqV90TMy4=
526+
go.opentelemetry.io/otel/sdk/log/logtest v0.16.0/go.mod h1:iOOPgQr5MY9oac/F5W86mXdeyWZGleIx3uXO98X2R6Y=
517527
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
518528
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
519529
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=

internal/drivers/aks/driver.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/charmbracelet/log"
2828
"github.com/google/go-containerregistry/pkg/name"
2929
"github.com/google/uuid"
30+
"go.opentelemetry.io/otel/trace"
3031
"k8s.io/client-go/kubernetes"
3132
"k8s.io/client-go/rest"
3233
"k8s.io/client-go/tools/clientcmd"
@@ -328,6 +329,7 @@ func (k *driver) setupCommonClients() error {
328329

329330
func (k *driver) Setup(ctx context.Context) error {
330331
log := clog.FromContext(ctx)
332+
span := trace.SpanFromContext(ctx)
331333

332334
if err := k.setupCommonClients(); err != nil {
333335
return err
@@ -367,6 +369,7 @@ func (k *driver) Setup(ctx context.Context) error {
367369
if err = k.createCluster(ctx); err != nil {
368370
return err
369371
}
372+
span.AddEvent("aks.cluster.created")
370373
}
371374

372375
if err = k.createPodIdentityAssociation(ctx); err != nil {
@@ -376,10 +379,12 @@ func (k *driver) Setup(ctx context.Context) error {
376379
if err = k.createClusterIdentityAssociation(ctx); err != nil {
377380
return err
378381
}
382+
span.AddEvent("aks.identity.configured")
379383

380384
if err = k.attachACRs(ctx); err != nil {
381385
return err
382386
}
387+
span.AddEvent("aks.acr.attached")
383388

384389
if err = k.writeKubeConfig(ctx); err != nil {
385390
return err

internal/drivers/docker_in_docker/driver.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/google/go-containerregistry/pkg/v1/remote"
2626
"github.com/google/uuid"
2727
v1 "github.com/moby/docker-image-spec/specs-go/v1"
28+
"go.opentelemetry.io/otel/trace"
2829
)
2930

3031
type driver struct {
@@ -106,6 +107,8 @@ func (d *driver) Teardown(ctx context.Context) error {
106107
// Run implements drivers.TestDriver.
107108
func (d *driver) Run(ctx context.Context, ref name.Reference) (*drivers.RunResult, error) {
108109
// Build the driver image, uses the provided dind image appended with the ref
110+
span := trace.SpanFromContext(ctx)
111+
109112
tref, err := bundler.Mutate(ctx, d.ImageRef, ref.Context(), bundler.MutateOpts{
110113
RemoteOptions: d.ropts,
111114
ImageMutators: []func(ggcrv1.Image) (ggcrv1.Image, error){
@@ -150,6 +153,7 @@ func (d *driver) Run(ctx context.Context, ref name.Reference) (*drivers.RunResul
150153
if err != nil {
151154
return nil, fmt.Errorf("failed to build driver image: %w", err)
152155
}
156+
span.AddEvent("dind.image.built")
153157

154158
nw, err := d.cli.CreateNetwork(ctx, &docker.NetworkRequest{})
155159
if err != nil {
@@ -161,6 +165,7 @@ func (d *driver) Run(ctx context.Context, ref name.Reference) (*drivers.RunResul
161165
}); err != nil {
162166
return nil, err
163167
}
168+
span.AddEvent("dind.network.created")
164169

165170
cliCfg, err := d.cliCfg.Content()
166171
if err != nil {
@@ -199,6 +204,7 @@ func (d *driver) Run(ctx context.Context, ref name.Reference) (*drivers.RunResul
199204

200205
cname := fmt.Sprintf("%s-%s", d.name, uuid.New().String()[:8])
201206
clog.InfoContext(ctx, "running docker-in-docker test", "image_ref", tref.String(), "container_name", cname)
207+
span.AddEvent("dind.container.started")
202208
cid, err := d.cli.Run(ctx, &docker.Request{
203209
Name: cname,
204210
Ref: tref,
@@ -223,6 +229,7 @@ func (d *driver) Run(ctx context.Context, ref name.Reference) (*drivers.RunResul
223229
})
224230

225231
result := &drivers.RunResult{}
232+
span.AddEvent("dind.container.completed")
226233

227234
arc, aerr := docker.GetFile(ctx, d.cli, cid, entrypoint.ArtifactsPath)
228235
if aerr != nil {

internal/drivers/ec2/driver.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/google/go-containerregistry/pkg/name"
2323
"github.com/google/uuid"
2424
"github.com/kballard/go-shellquote"
25+
"go.opentelemetry.io/otel/trace"
2526
"golang.org/x/crypto/ssh"
2627
"k8s.io/apimachinery/pkg/util/wait"
2728
)
@@ -103,6 +104,7 @@ func (d *driver) setupExistingInstance(ctx context.Context) error {
103104

104105
func (d *driver) setupNewInstance(ctx context.Context) error {
105106
log := clog.FromContext(ctx)
107+
span := trace.SpanFromContext(ctx)
106108

107109
d.name = "imagetest-ec2-" + uuid.New().String()[:8]
108110
log.Info("setting up EC2 driver", "name", d.name, "vpc_id", d.cfg.VPCID)
@@ -167,18 +169,22 @@ func (d *driver) setupNewInstance(ctx context.Context) error {
167169
if err := d.create(ctx, d.instance); err != nil {
168170
return fmt.Errorf("creating instance: %w", err)
169171
}
172+
span.AddEvent("ec2.instance.created")
170173

171174
if err := d.instance.wait(ctx); err != nil {
172175
return fmt.Errorf("waiting for instance: %w", err)
173176
}
177+
span.AddEvent("ec2.instance.running")
174178

175179
if err := d.prepareInstance(ctx); err != nil {
176180
return fmt.Errorf("preparing instance: %w", err)
177181
}
182+
span.AddEvent("ec2.cloudinit.complete")
178183

179184
if err := d.runSetupCommands(ctx); err != nil {
180185
return fmt.Errorf("running setup commands: %w", err)
181186
}
187+
span.AddEvent("ec2.setup.complete")
182188

183189
log.Info("EC2 driver setup complete", "instance_id", d.instance.id, "public_ip", d.instance.publicIP)
184190

internal/drivers/eks_with_eksctl/driver.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/charmbracelet/log"
2323
"github.com/google/go-containerregistry/pkg/name"
2424
"github.com/google/uuid"
25+
"go.opentelemetry.io/otel/trace"
2526
"k8s.io/client-go/kubernetes"
2627
"k8s.io/client-go/rest"
2728
"k8s.io/client-go/tools/clientcmd"
@@ -428,6 +429,7 @@ func (k *driver) deletePodIdentityAssociation(ctx context.Context) error {
428429

429430
func (k *driver) Setup(ctx context.Context) error {
430431
log := clog.FromContext(ctx)
432+
span := trace.SpanFromContext(ctx)
431433

432434
if n, ok := os.LookupEnv("IMAGETEST_EKS_CLUSTER"); ok {
433435
log.Infof("Using cluster name from IMAGETEST_EKS_CLUSTER: %s", n)
@@ -489,16 +491,19 @@ func (k *driver) Setup(ctx context.Context) error {
489491
return fmt.Errorf("eksctl create cluster: %w", err)
490492
}
491493
log.Infof("Created cluster %s without nodegroups", k.clusterName)
494+
span.AddEvent("eks.cluster.created")
492495
}
493496

494497
if err := k.createNodeGroup(ctx); err != nil {
495498
return err
496499
}
500+
span.AddEvent("eks.nodegroup.created")
497501

498502
if k.podIdentityAssociations != nil {
499503
if err = k.createPodIdentityAssociation(ctx); err != nil {
500504
return fmt.Errorf("creating pod identity association: %w", err)
501505
}
506+
span.AddEvent("eks.identity.configured")
502507
}
503508

504509
config, err := clientcmd.BuildConfigFromFlags("", k.kubeconfig)

internal/drivers/k3s_in_docker/driver.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/docker/go-connections/nat"
2020
"github.com/google/go-containerregistry/pkg/name"
2121
v1 "github.com/moby/docker-image-spec/specs-go/v1"
22+
"go.opentelemetry.io/otel/trace"
2223
corev1 "k8s.io/api/core/v1"
2324
"k8s.io/apimachinery/pkg/api/resource"
2425
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -162,6 +163,7 @@ configs:
162163
if err != nil {
163164
return fmt.Errorf("creating docker network: %w", err)
164165
}
166+
trace.SpanFromContext(ctx).AddEvent("k3s.network.created")
165167

166168
if err := k.stack.Add(func(ctx context.Context) error {
167169
return cli.RemoveNetwork(ctx, nw)
@@ -224,6 +226,7 @@ configs:
224226
}); err != nil {
225227
return err
226228
}
229+
trace.SpanFromContext(ctx).AddEvent("k3s.container.started")
227230

228231
kcfgraw, err := resp.ReadFile(ctx, "/etc/rancher/k3s/k3s.yaml")
229232
if err != nil {
@@ -251,6 +254,7 @@ configs:
251254
}
252255

253256
config.Host = fmt.Sprintf("https://%s:%s", binding.HostIP, binding.HostPort)
257+
trace.SpanFromContext(ctx).AddEvent("k3s.kubeconfig.ready")
254258

255259
kcli, err := kubernetes.NewForConfig(config)
256260
if err != nil {
@@ -288,6 +292,7 @@ configs:
288292
if err := k.waitReady(ctx); err != nil {
289293
return fmt.Errorf("waiting for k3s to be ready: %w", err)
290294
}
295+
trace.SpanFromContext(ctx).AddEvent("k3s.cluster.ready")
291296

292297
// Ensure some common mount propagation fixes are applied to make this feel
293298
// more like a "real" cluster
@@ -315,6 +320,7 @@ configs:
315320
return fmt.Errorf("running post start hook: %w", err)
316321
}
317322
}
323+
trace.SpanFromContext(ctx).AddEvent("k3s.hooks.complete")
318324
}
319325

320326
return nil

internal/drivers/lambda/driver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/chainguard-dev/clog"
1313
"github.com/chainguard-dev/terraform-provider-imagetest/internal/drivers"
1414
"github.com/google/go-containerregistry/pkg/name"
15+
"go.opentelemetry.io/otel/trace"
1516
)
1617

1718
type driver struct {
@@ -74,6 +75,8 @@ func (k *driver) Run(ctx context.Context, ref name.Reference) (*drivers.RunResul
7475
return nil, fmt.Errorf("creating Lambda function: %w", err)
7576
}
7677
clog.FromContext(ctx).Info("Created Lambda function", "name", k.functionName)
78+
span := trace.SpanFromContext(ctx)
79+
span.AddEvent("lambda.function.created")
7780

7881
var out *lambda.GetFunctionOutput
7982
L:
@@ -99,6 +102,7 @@ L:
99102
return nil, fmt.Errorf("function state is %s: %s", out.Configuration.State, *out.Configuration.StateReason)
100103
}
101104
clog.FromContext(ctx).Info("Lambda function is active", "name", k.functionName)
105+
span.AddEvent("lambda.function.active")
102106

103107
// Invoke the function to ensure it is ready.
104108
if out, err := k.client.Invoke(ctx, &lambda.InvokeInput{FunctionName: &k.functionName}); err != nil {

internal/drivers/pod/pod.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"github.com/chainguard-dev/terraform-provider-imagetest/internal/drivers"
1818
"github.com/chainguard-dev/terraform-provider-imagetest/internal/entrypoint"
1919
"github.com/google/go-containerregistry/pkg/name"
20+
"go.opentelemetry.io/otel/attribute"
21+
"go.opentelemetry.io/otel/trace"
2022
authv1 "k8s.io/api/authorization/v1"
2123
corev1 "k8s.io/api/core/v1"
2224
rbacv1 "k8s.io/api/rbac/v1"
@@ -85,15 +87,19 @@ func Run(ctx context.Context, kcfg *rest.Config, options ...RunOpts) (*drivers.R
8587
}
8688
o.client = kcli
8789

90+
span := trace.SpanFromContext(ctx)
91+
8892
if err := o.preflight(ctx); err != nil {
8993
return nil, err
9094
}
95+
span.AddEvent("pod.preflight.complete")
9196

9297
pobj, err := o.client.CoreV1().Pods(o.Namespace).
9398
Create(ctx, o.pod(), metav1.CreateOptions{})
9499
if err != nil {
95100
return nil, fmt.Errorf("failed to create pod: %w", err)
96101
}
102+
span.AddEvent("pod.created")
97103

98104
pw, err := o.client.CoreV1().Pods(pobj.Namespace).Watch(ctx, metav1.ListOptions{
99105
FieldSelector: fmt.Sprintf("metadata.name=%s", pobj.Name),
@@ -121,6 +127,8 @@ func Run(ctx context.Context, kcfg *rest.Config, options ...RunOpts) (*drivers.R
121127
result := &drivers.RunResult{Artifact: &drivers.RunArtifactResult{}}
122128
if err := o.getArtifact(ctx, pobj, result); err != nil {
123129
clog.ErrorContext(ctx, "failed to get artifact", "error", err)
130+
} else {
131+
span.AddEvent("pod.artifact.retrieved")
124132
}
125133

126134
return result, monitorErr
@@ -253,6 +261,7 @@ func monitor(ctx context.Context, cli kubernetes.Interface, pod *corev1.Pod) err
253261

254262
if !logStarted && p.Status.Phase == corev1.PodRunning {
255263
logStarted = true
264+
trace.SpanFromContext(ctx).AddEvent("pod.running")
256265
clog.InfoContext(ctx, "starting log stream")
257266
logch = startLogStream(ctx, cli, pod)
258267
}
@@ -263,6 +272,9 @@ func monitor(ctx context.Context, cli kubernetes.Interface, pod *corev1.Pod) err
263272

264273
for _, cs := range p.Status.ContainerStatuses {
265274
if cs.Name == SandboxContainerName && cs.State.Terminated != nil {
275+
trace.SpanFromContext(ctx).AddEvent("pod.completed",
276+
trace.WithAttributes(attribute.Int64("exit_code", int64(cs.State.Terminated.ExitCode))),
277+
)
266278
clog.InfoContext(ctx, "sandbox container terminated",
267279
"exit_code", cs.State.Terminated.ExitCode,
268280
"reason", cs.State.Terminated.Reason,

0 commit comments

Comments
 (0)