From 4b017a4b40e361efc7371a12ade66698d56ccaac Mon Sep 17 00:00:00 2001 From: Kim Tore Jensen Date: Tue, 17 Sep 2024 13:28:28 +0200 Subject: [PATCH] Remove telemetry parser code --- pkg/deployclient/config.go | 10 ---- pkg/telemetry/telemetry.go | 96 --------------------------------- pkg/telemetry/telemetry_test.go | 72 ------------------------- 3 files changed, 178 deletions(-) diff --git a/pkg/deployclient/config.go b/pkg/deployclient/config.go index 318f30ab..cec884ea 100644 --- a/pkg/deployclient/config.go +++ b/pkg/deployclient/config.go @@ -2,13 +2,11 @@ package deployclient import ( "encoding/hex" - "fmt" "os" "strconv" "strings" "time" - "github.com/nais/deploy/pkg/telemetry" flag "github.com/spf13/pflag" ) @@ -33,8 +31,6 @@ type Config struct { RetryInterval time.Duration Team string Traceparent string - TelemetryInput string - Telemetry *telemetry.PipelineTimings Timeout time.Duration TracingDashboardURL string OpenTelemetryCollectorURL string @@ -63,7 +59,6 @@ func InitConfig(cfg *Config) { flag.StringVar(&cfg.Team, "team", os.Getenv("TEAM"), "Team making the deployment. Auto-detected from nais.yaml if possible. (env TEAM)") flag.StringVar(&cfg.OpenTelemetryCollectorURL, "otel-collector-endpoint", getEnv("OTEL_COLLECTOR_ENDPOINT", DefaultOtelCollectorEndpoint), "OpenTelemetry collector endpoint. (env OTEL_COLLECTOR_ENDPOINT)") flag.StringVar(&cfg.Traceparent, "traceparent", os.Getenv("TRACEPARENT"), "The W3C Trace Context traceparent value for the workflow run. (env TRACEPARENT)") - flag.StringVar(&cfg.TelemetryInput, "telemetry", os.Getenv("TELEMETRY"), "Telemetry data from CI pipeline. (env TELEMETRY)") flag.DurationVar(&cfg.Timeout, "timeout", getEnvDuration("TIMEOUT", DefaultDeployTimeout), "Time to wait for successful deployment. (env TIMEOUT)") flag.StringVar(&cfg.TracingDashboardURL, "tracing-dashboard-url", getEnv("TRACING_DASHBOARD_URL", DefaultTracingDashboardURL), "Base URL to Grafana tracing dashboard onto which the trace ID can be appended (env TRACING_DASHBOARD_URL)") flag.StringSliceVar(&cfg.Variables, "var", getEnvStringSlice("VAR"), "Template variable in the form KEY=VALUE. Can be specified multiple times. (env VAR)") @@ -140,10 +135,5 @@ func (cfg *Config) Validate() error { return ErrMalformedAPIKey } - cfg.Telemetry, err = telemetry.ParsePipelineTelemetry(cfg.TelemetryInput) - if err != nil { - return fmt.Errorf("%w: %w", ErrInvalidTelemetryFormat, err) - } - return nil } diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index 2902a4de..72cdce73 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -4,9 +4,7 @@ package telemetry import ( "context" - "fmt" "runtime" - "strconv" "strings" "time" @@ -131,100 +129,6 @@ func AddDeploymentRequestSpanAttributes(span otrace.Span, request *pb.Deployment ) } -// Holds timestamps from pipeline indicating when certain steps were started or finished. -// If `Validate()` returns nil, this object is safe to use and contains chronologically ordered timestamps -// for every field. -type PipelineTimings struct { - LatestCommit time.Time - Start time.Time - BuildStart time.Time - AttestStart time.Time - End time.Time -} - -func (pt *PipelineTimings) Validate() error { - if pt.LatestCommit.After(pt.BuildStart) || pt.Start.After(pt.BuildStart) || pt.BuildStart.After(pt.AttestStart) || pt.AttestStart.After(pt.End) { - return fmt.Errorf("pipeline timings are not in expected chronological order, ensure that: latest_commit < pipeline_start < build_start < attest_start < pipeline_end") - } - return nil -} - -func (pt *PipelineTimings) StartTracing(ctx context.Context) (context.Context, otrace.Span) { - if pt == nil { - return Tracer().Start(ctx, "Continuous integration pipeline", otrace.WithSpanKind(otrace.SpanKindClient)) - } - - rootCtx, rootSpan := Tracer().Start(ctx, "Continuous integration pipeline", otrace.WithTimestamp(pt.LatestCommit), otrace.WithSpanKind(otrace.SpanKindClient)) - rootSpan.AddEvent("Latest commit to repository", otrace.WithTimestamp(pt.LatestCommit)) - { - ciCtx, ciSpan := Tracer().Start(rootCtx, "Github Action: docker-build-push", otrace.WithTimestamp(pt.Start), otrace.WithSpanKind(otrace.SpanKindClient)) - { - _, buildSpan := Tracer().Start(ciCtx, "Docker: Build and push", otrace.WithTimestamp(pt.BuildStart)) - buildSpan.End(otrace.WithTimestamp(pt.AttestStart)) - } - { - _, attestSpan := Tracer().Start(ciCtx, "SLSA: SBOM sign and attest", otrace.WithTimestamp(pt.AttestStart)) - attestSpan.End(otrace.WithTimestamp(pt.End)) - } - ciSpan.End(otrace.WithTimestamp(pt.End)) - } - - return rootCtx, rootSpan -} - -// Parse pipeline build timings. -// -// Uses the following input format: -// -// latest_commit=1726040395,pipeline_start=1726050395,pipeline_end=1726050512,build_start=1726050400,attest_start=1726050492 -// -// This output usually comes from `docker-build-push.steps.output.telemetry`. -// -// If there is no timing data, both return values will be nil. -// If all timing data is valid, returns a timings object and nil error. -func ParsePipelineTelemetry(s string) (*PipelineTimings, error) { - if len(s) == 0 { - return nil, nil - } - - timings := &PipelineTimings{} - fragments := strings.Split(s, ",") - for _, keyValue := range fragments { - key, value, found := strings.Cut(keyValue, "=") - if !found { - return nil, fmt.Errorf("expected 'key=value', found '%s'", keyValue) - } - - epoch, err := strconv.Atoi(value) - if err != nil { - return nil, fmt.Errorf("expected UNIX epoch, found '%s'", value) - } - - ts := time.Unix(int64(epoch), 0) - ts = ts.UTC() - - switch key { - case "latest_commit": - timings.LatestCommit = ts - case "pipeline_start": - timings.Start = ts - case "pipeline_end": - timings.End = ts - case "build_start": - timings.BuildStart = ts - case "attest_start": - timings.AttestStart = ts - default: - return nil, fmt.Errorf("expected key to be one of 'latest_commit', 'pipeline_start', 'pipeline_end', 'build_start', 'attest_start'; found '%s'", key) - } - } - err := timings.Validate() - if err != nil { - return nil, err - } - return timings, nil -} - func newPropagator() propagation.TextMapPropagator { return propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, diff --git a/pkg/telemetry/telemetry_test.go b/pkg/telemetry/telemetry_test.go index 015480a2..b610ae91 100644 --- a/pkg/telemetry/telemetry_test.go +++ b/pkg/telemetry/telemetry_test.go @@ -3,83 +3,11 @@ package telemetry_test import ( "context" "testing" - "time" "github.com/nais/deploy/pkg/telemetry" "github.com/stretchr/testify/assert" ) -func TestParsePipelineTelemetry(t *testing.T) { - t.Run("default case with five timings in correct order without quoting", func(t *testing.T) { - input := "latest_commit=1726040395,pipeline_start=1726050395,pipeline_end=1726050512,build_start=1726050400,attest_start=1726050492" - expected := &telemetry.PipelineTimings{ - LatestCommit: time.Date(2024, time.September, 11, 7, 39, 55, 0, time.UTC), - Start: time.Date(2024, time.September, 11, 10, 26, 35, 0, time.UTC), - BuildStart: time.Date(2024, time.September, 11, 10, 26, 40, 0, time.UTC), - AttestStart: time.Date(2024, time.September, 11, 10, 28, 12, 0, time.UTC), - End: time.Date(2024, time.September, 11, 10, 28, 32, 0, time.UTC), - } - output, err := telemetry.ParsePipelineTelemetry(input) - assert.NoError(t, err) - assert.Equal(t, expected, output) - }) - - t.Run("missing some of the timings", func(t *testing.T) { - input := "pipeline_start=1726050395,pipeline_end=1726050512" - output, err := telemetry.ParsePipelineTelemetry(input) - assert.EqualError(t, err, "pipeline timings are not in expected chronological order, ensure that: latest_commit < pipeline_start < build_start < attest_start < pipeline_end") - assert.Nil(t, output) - }) - - t.Run("wrong timing order", func(t *testing.T) { - for _, input := range []string{ - "pipeline_start=2,build_start=1", - "build_start=2,attest_start=1", - "attest_start=2,pipeline_end=1", - "pipeline_start=2,pipeline_end=1", - } { - output, err := telemetry.ParsePipelineTelemetry(input) - assert.EqualError(t, err, "pipeline timings are not in expected chronological order, ensure that: latest_commit < pipeline_start < build_start < attest_start < pipeline_end") - assert.Nil(t, output) - } - }) - - t.Run("unexpected timing parameter", func(t *testing.T) { - input := "pipeline_start=1,foobar=2" - output, err := telemetry.ParsePipelineTelemetry(input) - assert.EqualError(t, err, "expected key to be one of 'latest_commit', 'pipeline_start', 'pipeline_end', 'build_start', 'attest_start'; found 'foobar'") - assert.Nil(t, output) - }) - - t.Run("timing parameter not an integer", func(t *testing.T) { - input := "pipeline_start=2024-09-11" - output, err := telemetry.ParsePipelineTelemetry(input) - assert.EqualError(t, err, "expected UNIX epoch, found '2024-09-11'") - assert.Nil(t, output) - }) - - t.Run("parameter list missing value", func(t *testing.T) { - input := "pipeline_start=1,pipeline_end" - output, err := telemetry.ParsePipelineTelemetry(input) - assert.EqualError(t, err, "expected 'key=value', found 'pipeline_end'") - assert.Nil(t, output) - }) - - t.Run("parameter list missing key", func(t *testing.T) { - input := "pipeline_start=1,=2" - output, err := telemetry.ParsePipelineTelemetry(input) - assert.EqualError(t, err, "expected key to be one of 'latest_commit', 'pipeline_start', 'pipeline_end', 'build_start', 'attest_start'; found ''") - assert.Nil(t, output) - }) - - t.Run("no data", func(t *testing.T) { - input := "" - output, err := telemetry.ParsePipelineTelemetry(input) - assert.NoError(t, err) - assert.Nil(t, output) - }) -} - func TestTraceID(t *testing.T) { t.Run("happy case", func(t *testing.T) { traceParentHeader := "00-ada6313c1a5b6ffdf0d085fadc3265cb-6018288557ffff51-01"