From 7a17e55b35e452790dc57a399d179c9a914f04c6 Mon Sep 17 00:00:00 2001 From: Matheus Nogueira Date: Wed, 6 Sep 2023 14:20:50 -0300 Subject: [PATCH 1/6] feat(server): allow trace to be incremented in UpdateTestRun endpoint --- server/http/controller.go | 3 +++ server/traces/trace_entities.go | 18 ++++++++++++++++++ server/traces/traces_test.go | 19 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/server/http/controller.go b/server/http/controller.go index 30e5c39468..0247e3400e 100644 --- a/server/http/controller.go +++ b/server/http/controller.go @@ -23,6 +23,7 @@ import ( "github.com/kubeshop/tracetest/server/test" "github.com/kubeshop/tracetest/server/testsuite" "github.com/kubeshop/tracetest/server/tracedb" + "github.com/kubeshop/tracetest/server/traces" "github.com/kubeshop/tracetest/server/variableset" "github.com/labstack/gommon/log" "go.opentelemetry.io/otel/trace" @@ -725,6 +726,8 @@ func (c *controller) UpdateTestRun(ctx context.Context, testID string, runID int // Prevents bad data in other fields to override correct data existingRun.TriggerResult = run.TriggerResult + newTrace := traces.MergeTraces(existingRun.Trace, run.Trace) + existingRun.Trace = &newTrace err = c.testRunRepository.UpdateRun(ctx, existingRun) if err != nil { diff --git a/server/traces/trace_entities.go b/server/traces/trace_entities.go index 33e5727cb8..983fb65b71 100644 --- a/server/traces/trace_entities.go +++ b/server/traces/trace_entities.go @@ -18,6 +18,24 @@ type Trace struct { Flat map[trace.SpanID]*Span `json:"-"` } +func MergeTraces(traces ...*Trace) Trace { + if len(traces) == 0 { + return NewTrace(id.NewRandGenerator().TraceID().String(), []Span{}) + } + + traceID := traces[0].ID + spans := make([]Span, 0) + for _, trace := range traces { + if trace == nil { + continue + } + + spans = append(spans, trace.Spans()...) + } + + return NewTrace(traceID.String(), spans) +} + func NewTrace(traceID string, spans []Span) Trace { spanMap := make(map[string]*Span, 0) for _, span := range spans { diff --git a/server/traces/traces_test.go b/server/traces/traces_test.go index 69ca73ef12..49fa9a7b69 100644 --- a/server/traces/traces_test.go +++ b/server/traces/traces_test.go @@ -203,6 +203,25 @@ func TestEventsAreInjectedIntoAttributes(t *testing.T) { assert.Equal(t, "value", events[1].Attributes["attribute2"]) } +func TestMergingZeroTraces(t *testing.T) { + trace := traces.MergeTraces() + assert.NotEmpty(t, trace.ID) +} + +func TestMergingFragmentsFromSameTrace(t *testing.T) { + traceID := id.NewRandGenerator().TraceID().String() + rootSpan := newSpan("Root") + childSpan1 := newSpan("child 1", withParent(&rootSpan)) + childSpan2 := newSpan("child 2", withParent(&rootSpan)) + + firstFragment := traces.NewTrace(traceID, []traces.Span{childSpan2}) + secondFragment := traces.NewTrace(traceID, []traces.Span{rootSpan, childSpan1}) + + trace := traces.MergeTraces(&firstFragment, &secondFragment) + assert.NotEmpty(t, trace.ID) + assert.Len(t, trace.Flat, 3) +} + type option func(*traces.Span) func withParent(parent *traces.Span) option { From 84b9a7635ba13ef61c6d047edd2742f70f9bb608 Mon Sep 17 00:00:00 2001 From: Matheus Nogueira Date: Wed, 6 Sep 2023 15:07:46 -0300 Subject: [PATCH 2/6] fix: make sure trace.Spans() consider tree object when flat is nil --- server/traces/trace_entities.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/traces/trace_entities.go b/server/traces/trace_entities.go index 983fb65b71..7de54e9766 100644 --- a/server/traces/trace_entities.go +++ b/server/traces/trace_entities.go @@ -194,6 +194,11 @@ func (t *Trace) Spans() []Span { return []Span{} } + if len(t.Flat) == 0 { + t.Flat = make(map[trace.SpanID]*Span) + flattenSpans(t.Flat, t.RootSpan) + } + spans := make([]Span, 0, len(t.Flat)) for _, span := range t.Flat { spans = append(spans, *span) From 417024e9140d1272eeca5b2bb8b697e7580c77b5 Mon Sep 17 00:00:00 2001 From: Matheus Nogueira Date: Wed, 6 Sep 2023 14:20:50 -0300 Subject: [PATCH 3/6] feat(server): allow trace to be incremented in UpdateTestRun endpoint --- server/http/controller.go | 3 +++ server/traces/trace_entities.go | 18 ++++++++++++++++++ server/traces/traces_test.go | 19 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/server/http/controller.go b/server/http/controller.go index 83f06b1360..d3878d11bf 100644 --- a/server/http/controller.go +++ b/server/http/controller.go @@ -22,6 +22,7 @@ import ( "github.com/kubeshop/tracetest/server/test" "github.com/kubeshop/tracetest/server/testsuite" "github.com/kubeshop/tracetest/server/tracedb" + "github.com/kubeshop/tracetest/server/traces" "github.com/kubeshop/tracetest/server/variableset" "github.com/labstack/gommon/log" "go.opentelemetry.io/otel/trace" @@ -718,6 +719,8 @@ func (c *controller) UpdateTestRun(ctx context.Context, testID string, runID int // Prevents bad data in other fields to override correct data existingRun.TriggerResult = run.TriggerResult + newTrace := traces.MergeTraces(existingRun.Trace, run.Trace) + existingRun.Trace = &newTrace err = c.testRunRepository.UpdateRun(ctx, existingRun) if err != nil { diff --git a/server/traces/trace_entities.go b/server/traces/trace_entities.go index 33e5727cb8..983fb65b71 100644 --- a/server/traces/trace_entities.go +++ b/server/traces/trace_entities.go @@ -18,6 +18,24 @@ type Trace struct { Flat map[trace.SpanID]*Span `json:"-"` } +func MergeTraces(traces ...*Trace) Trace { + if len(traces) == 0 { + return NewTrace(id.NewRandGenerator().TraceID().String(), []Span{}) + } + + traceID := traces[0].ID + spans := make([]Span, 0) + for _, trace := range traces { + if trace == nil { + continue + } + + spans = append(spans, trace.Spans()...) + } + + return NewTrace(traceID.String(), spans) +} + func NewTrace(traceID string, spans []Span) Trace { spanMap := make(map[string]*Span, 0) for _, span := range spans { diff --git a/server/traces/traces_test.go b/server/traces/traces_test.go index 69ca73ef12..49fa9a7b69 100644 --- a/server/traces/traces_test.go +++ b/server/traces/traces_test.go @@ -203,6 +203,25 @@ func TestEventsAreInjectedIntoAttributes(t *testing.T) { assert.Equal(t, "value", events[1].Attributes["attribute2"]) } +func TestMergingZeroTraces(t *testing.T) { + trace := traces.MergeTraces() + assert.NotEmpty(t, trace.ID) +} + +func TestMergingFragmentsFromSameTrace(t *testing.T) { + traceID := id.NewRandGenerator().TraceID().String() + rootSpan := newSpan("Root") + childSpan1 := newSpan("child 1", withParent(&rootSpan)) + childSpan2 := newSpan("child 2", withParent(&rootSpan)) + + firstFragment := traces.NewTrace(traceID, []traces.Span{childSpan2}) + secondFragment := traces.NewTrace(traceID, []traces.Span{rootSpan, childSpan1}) + + trace := traces.MergeTraces(&firstFragment, &secondFragment) + assert.NotEmpty(t, trace.ID) + assert.Len(t, trace.Flat, 3) +} + type option func(*traces.Span) func withParent(parent *traces.Span) option { From 4cc3e0807bb6055829e6443c839f639ae2e499aa Mon Sep 17 00:00:00 2001 From: Matheus Nogueira Date: Wed, 6 Sep 2023 15:07:46 -0300 Subject: [PATCH 4/6] fix: make sure trace.Spans() consider tree object when flat is nil --- server/traces/trace_entities.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/traces/trace_entities.go b/server/traces/trace_entities.go index 983fb65b71..7de54e9766 100644 --- a/server/traces/trace_entities.go +++ b/server/traces/trace_entities.go @@ -194,6 +194,11 @@ func (t *Trace) Spans() []Span { return []Span{} } + if len(t.Flat) == 0 { + t.Flat = make(map[trace.SpanID]*Span) + flattenSpans(t.Flat, t.RootSpan) + } + spans := make([]Span, 0, len(t.Flat)) for _, span := range t.Flat { spans = append(spans, *span) From 0778f8560d39e08cfc3bf6cc5556e385e5212b22 Mon Sep 17 00:00:00 2001 From: Matheus Nogueira Date: Thu, 14 Sep 2023 20:48:18 -0300 Subject: [PATCH 5/6] fix: panic when adding attributes to span --- server/traces/span_entitiess.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/traces/span_entitiess.go b/server/traces/span_entitiess.go index d907b2b713..b630ce387d 100644 --- a/server/traces/span_entitiess.go +++ b/server/traces/span_entitiess.go @@ -226,6 +226,10 @@ func decodeChildren(parent *Span, children []encodedSpan, cache spanCache) ([]*S } func (span Span) setMetadataAttributes() Span { + if span.Attributes == nil { + span.Attributes = Attributes{} + } + span.Attributes[TracetestMetadataFieldName] = span.Name span.Attributes[TracetestMetadataFieldType] = spanType(span.Attributes) span.Attributes[TracetestMetadataFieldDuration] = spanDuration(span) From b6a87c9f5a967ca704032964cb5f2a96b7617b20 Mon Sep 17 00:00:00 2001 From: Matheus Nogueira Date: Fri, 15 Sep 2023 16:50:43 -0300 Subject: [PATCH 6/6] remove condition --- server/traces/trace_entities.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/server/traces/trace_entities.go b/server/traces/trace_entities.go index 4978684740..8f8650c294 100644 --- a/server/traces/trace_entities.go +++ b/server/traces/trace_entities.go @@ -194,11 +194,6 @@ func (t *Trace) Spans() []Span { return []Span{} } - if len(t.Flat) == 0 { - t.Flat = make(map[trace.SpanID]*Span) - flattenSpans(t.Flat, t.RootSpan) - } - spans := make([]Span, 0, len(t.Flat)) for _, span := range t.Flat { spans = append(spans, *span)