From 433b7e060d2e7b65bc11bf45bbd2c37926d34ebc Mon Sep 17 00:00:00 2001 From: Min Ho Park Date: Mon, 10 Jul 2017 15:37:17 -0400 Subject: [PATCH] Add Storage Integration Testing (#236) * create integration test framework for storage + create elasticsearch integration test * refactor queries format * rename comparison fns to fit its behavior * fix rand.Uint64() (does not exist in go1.7) * revert env var check * refactor trace w/ query checker to separate file + test * import list reorder * change itest direction * change integration test format * make fmt/lint * make fmt/lint * prettify output when test fails * fmt * delete query to trace checker * remove unnecessary code * add integration test script * fix syntax * add comment about fixtures and queries * fix travis yml to run es integ test * remove es integ test from install travis * fix typo * fix err check bug * fmt * move sorting fns to model * fix imports * fix code reviews * change trace fixtures to describe the trace * revert idl * trust people * sort refactored * fix trace comparison test + raise timeout for es-integration test * code review * remove numtraces check * add multiple-trace test case * code review --- .travis.yml | 4 + Makefile | 4 + model/sort.go | 97 +++++ model/sort_test.go | 126 ++++++ plugin/storage/es/spanstore/reader.go | 7 +- plugin/storage/es/spanstore/reader_test.go | 12 +- .../integration/domain_trace_compare_test.go | 80 ++++ .../integration/es_integration_test.go | 106 +++++ .../storage/integration/fixtures/queries.json | 380 ++++++++++++++++++ .../integration/fixtures/traces/default.json | 27 ++ .../fixtures/traces/dur_trace.json | 27 ++ .../fixtures/traces/example_trace.json | 119 ++++++ .../fixtures/traces/log_tags_trace.json | 53 +++ .../fixtures/traces/max_dur_trace.json | 27 ++ .../fixtures/traces/multi_index_trace.json | 50 +++ .../traces/multi_spot_tags_trace.json | 50 +++ .../fixtures/traces/multiple1_trace.json | 27 ++ .../fixtures/traces/multiple2_trace.json | 27 ++ .../fixtures/traces/multiple3_trace.json | 27 ++ .../traces/multispottag_dur_trace.json | 55 +++ .../traces/multispottag_maxdur_trace.json | 56 +++ .../traces/multispottag_opname_dur_trace.json | 56 +++ .../multispottag_opname_maxdur_trace.json | 56 +++ .../traces/multispottag_opname_trace.json | 51 +++ .../fixtures/traces/opname_dur_trace.json | 27 ++ .../fixtures/traces/opname_maxdur_trace.json | 42 ++ .../fixtures/traces/opname_trace.json | 27 ++ .../fixtures/traces/process_tags_trace.json | 53 +++ .../fixtures/traces/span_tags_trace.json | 44 ++ .../fixtures/traces/tags_dur_trace.json | 53 +++ .../fixtures/traces/tags_maxdur_trace.json | 53 +++ .../traces/tags_opname_dur_trace.json | 53 +++ .../traces/tags_opname_maxdur_trace.json | 71 ++++ .../fixtures/traces/tags_opname_trace.json | 60 +++ .../storage/integration/integration_test.go | 276 +++++++++++++ travis/es-integration-test.sh | 8 + 36 files changed, 2282 insertions(+), 9 deletions(-) create mode 100644 model/sort.go create mode 100644 model/sort_test.go create mode 100644 plugin/storage/integration/domain_trace_compare_test.go create mode 100644 plugin/storage/integration/es_integration_test.go create mode 100644 plugin/storage/integration/fixtures/queries.json create mode 100644 plugin/storage/integration/fixtures/traces/default.json create mode 100644 plugin/storage/integration/fixtures/traces/dur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/example_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/log_tags_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/max_dur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multi_index_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multi_spot_tags_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multiple1_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multiple2_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multiple3_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multispottag_dur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multispottag_maxdur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multispottag_opname_dur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multispottag_opname_maxdur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/multispottag_opname_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/opname_dur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/opname_maxdur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/opname_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/process_tags_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/span_tags_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/tags_dur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/tags_maxdur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/tags_opname_dur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/tags_opname_maxdur_trace.json create mode 100644 plugin/storage/integration/fixtures/traces/tags_opname_trace.json create mode 100644 plugin/storage/integration/integration_test.go create mode 100755 travis/es-integration-test.sh diff --git a/.travis.yml b/.travis.yml index fb1be11ef5d..ec0a07b8b29 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,9 @@ matrix: - go: 1.7 env: - DOCKER=true + - go: 1.7 + env: + - ES_INTEGRATION_TEST=true # TODO 1.8 tests take way too long to run 900s vs 250s for 1.7 # - go: 1.8 # env: @@ -49,3 +52,4 @@ script: - if [ "$ALL_IN_ONE" == true ]; then bash ./travis/build-all-in-one-image.sh ; else echo 'skipping all_in_one'; fi - if [ "$CROSSDOCK" == true ]; then bash ./travis/build-crossdock.sh ; else echo 'skipping crossdock'; fi - if [ "$DOCKER" == true ]; then bash ./travis/build-docker-images.sh ; else echo 'skipping docker images'; fi + - if [ "$ES_INTEGRATION_TEST" == true ]; then bash ./travis/es-integration-test.sh ; else echo 'skipping elastic search integration test'; fi diff --git a/Makefile b/Makefile index 15954701fa1..fd78a0d7929 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,10 @@ test: go-gen integration-test: go-gen $(GOTEST) -tags=integration ./cmd/standalone/... +.PHONY: es-integration-test +es-integration-test: go-gen + $(GOTEST) ./plugin/storage/integration/... + .PHONY: fmt fmt: $(GOFMT) -e -s -l -w $(ALL_SRC) diff --git a/model/sort.go b/model/sort.go new file mode 100644 index 00000000000..5f07bd1a326 --- /dev/null +++ b/model/sort.go @@ -0,0 +1,97 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package model + +import ( + "sort" +) + +type traceByTraceID []*Trace + +func (s traceByTraceID) Len() int { return len(s) } +func (s traceByTraceID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s traceByTraceID) Less(i, j int) bool { + if len(s[i].Spans) == 0 { + return true + } else if len(s[j].Spans) == 0 { + return false + } else { + return s[i].Spans[0].TraceID.Low < s[j].Spans[0].TraceID.Low + } +} + +// SortTraces deep sorts a list of traces by TraceID. +func SortTraces(traces []*Trace) { + sort.Sort(traceByTraceID(traces)) + for _, trace := range traces { + SortTrace(trace) + } +} + +type spanBySpanID []*Span + +func (s spanBySpanID) Len() int { return len(s) } +func (s spanBySpanID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s spanBySpanID) Less(i, j int) bool { return s[i].SpanID < s[j].SpanID } + +// SortTrace deep sorts a trace's spans by SpanID. +func SortTrace(trace *Trace) { + sort.Sort(spanBySpanID(trace.Spans)) + for _, span := range trace.Spans { + sortSpan(span) + } +} + +func sortSpan(span *Span) { + span.NormalizeTimestamps() + sortTags(span.Tags) + sortLogs(span.Logs) + sortProcess(span.Process) +} + +type tagByKey []KeyValue + +func (t tagByKey) Len() int { return len(t) } +func (t tagByKey) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t tagByKey) Less(i, j int) bool { return t[i].Key < t[j].Key } + +func sortTags(tags []KeyValue) { + sort.Sort(tagByKey(tags)) +} + +type logByTimestamp []Log + +func (t logByTimestamp) Len() int { return len(t) } +func (t logByTimestamp) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t logByTimestamp) Less(i, j int) bool { return t[i].Timestamp.Before(t[j].Timestamp) } + +func sortLogs(logs []Log) { + sort.Sort(logByTimestamp(logs)) + for _, log := range logs { + sortTags(log.Fields) + } +} + +func sortProcess(process *Process) { + if process != nil { + sortTags(process.Tags) + } +} diff --git a/model/sort_test.go b/model/sort_test.go new file mode 100644 index 00000000000..824f57bad0e --- /dev/null +++ b/model/sort_test.go @@ -0,0 +1,126 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package model + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +var ( + currTime = time.Now() +) + +func TestSortTraces(t *testing.T) { + t1 := &Trace{ + Spans: []*Span{ + { + TraceID: TraceID{Low: 1}, + SpanID: SpanID(2), + Tags: []KeyValue{{Key: "world"}, {Key: "hello"}}, + Process: &Process{ + ServiceName: "hello", + Tags: []KeyValue{{Key: "hello"}, {Key: "world"}}, + }, + }, + { + TraceID: TraceID{Low: 1}, + SpanID: SpanID(1), + Logs: []Log{ + { + Timestamp: currTime, + Fields: []KeyValue{{Key: "world"}, {Key: "hello"}}, + }, + { + Timestamp: currTime.Add(-time.Hour), + Fields: []KeyValue{{Key: "hello"}, {Key: "world"}}, + }, + }, + }, + }, + } + t2 := &Trace{ + Spans: []*Span{ + { + TraceID: TraceID{Low: 1}, + SpanID: SpanID(2), + Tags: []KeyValue{{Key: "world"}, {Key: "hello"}}, + Process: &Process{ + ServiceName: "hello", + Tags: []KeyValue{{Key: "hello"}, {Key: "world"}}, + }, + }, + { + TraceID: TraceID{Low: 1}, + SpanID: SpanID(1), + Logs: []Log{ + { + Timestamp: currTime.Add(-time.Hour), + Fields: []KeyValue{{Key: "world"}, {Key: "hello"}}, + }, + { + Timestamp: currTime, + Fields: []KeyValue{{Key: "hello"}, {Key: "world"}}, + }, + }, + }, + }, + } + SortTrace(t1) + SortTrace(t2) + assert.EqualValues(t, t1, t2) +} + +func TestSortListOfTraces(t *testing.T) { + t1 := &Trace{ + Spans: []*Span{ + { + TraceID: TraceID{Low: 1}, + }, + { + TraceID: TraceID{Low: 1}, + }, + }, + } + t2 := &Trace{ + Spans: []*Span{ + { + TraceID: TraceID{Low: 2}, + }, + }, + } + t3 := &Trace{ + Spans: []*Span{ + { + TraceID: TraceID{Low: 3}, + }, + }, + } + t4 := &Trace{} + + list1 := []*Trace{t1, t4, t2, t3} + list2 := []*Trace{t4, t2, t1, t3} + SortTraces(list1) + SortTraces(list2) + assert.EqualValues(t, list1, list2) +} diff --git a/plugin/storage/es/spanstore/reader.go b/plugin/storage/es/spanstore/reader.go index d1a3b55b857..4dfdb65bf70 100644 --- a/plugin/storage/es/spanstore/reader.go +++ b/plugin/storage/es/spanstore/reader.go @@ -55,7 +55,7 @@ const ( tagKeyField = "key" tagValueField = "value" - defaultDocCount = 3000 + defaultDocCount = 10000 // the default elasticsearch allowed limit defaultNumTraces = 100 ) @@ -177,7 +177,7 @@ func (s *SpanReader) findIndices(traceQuery *spanstore.TraceQueryParameters) []s var indices []string current := traceQuery.StartTimeMax for current.After(traceQuery.StartTimeMin) && current.After(threeDaysAgo) { - index := indexWithDate(current) + index := IndexWithDate(current) exists, _ := s.client.IndexExists(index).Do(s.ctx) // Don't care about error, if it's an error, exists will be false anyway if exists { indices = append(indices, index) @@ -187,7 +187,8 @@ func (s *SpanReader) findIndices(traceQuery *spanstore.TraceQueryParameters) []s return indices } -func indexWithDate(date time.Time) string { +// IndexWithDate returns the index name formatted to date. +func IndexWithDate(date time.Time) string { return indexPrefix + date.Format("2006-01-02") } diff --git a/plugin/storage/es/spanstore/reader_test.go b/plugin/storage/es/spanstore/reader_test.go index 1e2228a415e..96c427f185f 100644 --- a/plugin/storage/es/spanstore/reader_test.go +++ b/plugin/storage/es/spanstore/reader_test.go @@ -287,9 +287,9 @@ func TestSpanReader_findIndicesEmptyQuery(t *testing.T) { twoDaysAgo := today.AddDate(0, 0, -2) expected := []string{ - indexWithDate(today), - indexWithDate(yesterday), - indexWithDate(twoDaysAgo), + IndexWithDate(today), + IndexWithDate(yesterday), + IndexWithDate(twoDaysAgo), } assert.EqualValues(t, expected, actual) @@ -327,8 +327,8 @@ func TestSpanReader_findIndicesOnlyRecent(t *testing.T) { twoDaysAgo := today.AddDate(0, 0, -2) expected := []string{ - indexWithDate(yesterday), - indexWithDate(twoDaysAgo), + IndexWithDate(yesterday), + IndexWithDate(twoDaysAgo), } assert.EqualValues(t, expected, actual) @@ -337,7 +337,7 @@ func TestSpanReader_findIndicesOnlyRecent(t *testing.T) { func TestSpanReader_indexWithDate(t *testing.T) { withSpanReader(func(r *spanReaderTest) { - actual := indexWithDate(time.Date(1995, time.April, 21, 4, 21, 19, 95, time.UTC)) + actual := IndexWithDate(time.Date(1995, time.April, 21, 4, 21, 19, 95, time.UTC)) assert.Equal(t, "jaeger-1995-04-21", actual) }) } diff --git a/plugin/storage/integration/domain_trace_compare_test.go b/plugin/storage/integration/domain_trace_compare_test.go new file mode 100644 index 00000000000..721529394e1 --- /dev/null +++ b/plugin/storage/integration/domain_trace_compare_test.go @@ -0,0 +1,80 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package integration + +import ( + "encoding/json" + "testing" + + "github.com/kr/pretty" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/uber/jaeger/model" +) + +func CompareSliceOfTraces(t *testing.T, expected []*model.Trace, actual []*model.Trace) { + require.Equal(t, len(expected), len(actual)) + model.SortTraces(expected) + model.SortTraces(actual) + for i := range expected { + checkSize(t, expected[i], actual[i]) + } + if !assert.EqualValues(t, expected, actual) { + for _, err := range pretty.Diff(expected, actual) { + t.Log(err) + } + out, err := json.Marshal(actual) + assert.NoError(t, err) + t.Logf("Actual traces: %s", string(out)) + } +} + +func CompareTraces(t *testing.T, expected *model.Trace, actual *model.Trace) { + if expected.Spans == nil { + require.Nil(t, actual.Spans) + return + } + model.SortTrace(expected) + model.SortTrace(actual) + checkSize(t, expected, actual) + if !assert.EqualValues(t, expected, actual) { + for _, err := range pretty.Diff(expected, actual) { + t.Log(err) + } + out, err := json.Marshal(actual) + assert.NoError(t, err) + t.Logf("Actual trace: %s", string(out)) + } +} + +func checkSize(t *testing.T, expected *model.Trace, actual *model.Trace) { + require.True(t, len(expected.Spans) == len(actual.Spans)) + for i := range expected.Spans { + expectedSpan := expected.Spans[i] + actualSpan := actual.Spans[i] + require.True(t, len(expectedSpan.Tags) == len(actualSpan.Tags)) + require.True(t, len(expectedSpan.Logs) == len(actualSpan.Logs)) + if expectedSpan.Process != nil && actualSpan.Process != nil { + require.True(t, len(expectedSpan.Process.Tags) == len(actualSpan.Process.Tags)) + } + } +} diff --git a/plugin/storage/integration/es_integration_test.go b/plugin/storage/integration/es_integration_test.go new file mode 100644 index 00000000000..99bb9ba2ee8 --- /dev/null +++ b/plugin/storage/integration/es_integration_test.go @@ -0,0 +1,106 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package integration + +import ( + "context" + "net/http" + "os" + "testing" + "time" + + "github.com/olivere/elastic" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/uber/jaeger/pkg/es" + "github.com/uber/jaeger/pkg/testutils" + "github.com/uber/jaeger/plugin/storage/es/spanstore" +) + +const ( + host = "0.0.0.0" + queryPort = "9200" + queryHostPort = host + ":" + queryPort + queryURL = "http://" + queryHostPort + username = "elastic" // the elasticsearch default username + password = "changeme" // the elasticsearch default password +) + +type ESStorageIntegration struct { + client *elastic.Client + StorageIntegration +} + +func (s *ESStorageIntegration) initializeES() error { + rawClient, err := elastic.NewClient( + elastic.SetURL(queryURL), + elastic.SetBasicAuth(username, password), + elastic.SetSniff(false)) + if err != nil { + return err + } + client := es.WrapESClient(rawClient) + logger, _ := testutils.NewLogger() + writer := spanstore.NewSpanWriter(client, logger) + reader := spanstore.NewSpanReader(client, logger) + + s.client = rawClient + s.writer = writer + s.reader = reader + s.logger = logger + s.cleanUp = s.esCleanUp + s.refresh = s.esRefresh + s.cleanUp() + return nil +} + +func (s *ESStorageIntegration) esCleanUp() error { + _, err := s.client.DeleteIndex("*").Do(context.Background()) + return err +} + +func (s *ESStorageIntegration) esRefresh() error { + _, err := s.client.Refresh().Do(context.Background()) + return err +} + +func healthCheck() error { + for i := 0; i < 200; i++ { + if _, err := http.Get(queryURL); err == nil { + return nil + } + time.Sleep(100 * time.Millisecond) + } + return errors.New("elastic search is not ready") +} + +func TestAll(t *testing.T) { + if os.Getenv("ES_INTEGRATION_TEST") == "" { + t.Skip("Set ES_INTEGRATION_TEST env variable to run an integration test on ElasticSearch backend") + } + if err := healthCheck(); err != nil { + t.Fatal(err) + } + s := &ESStorageIntegration{} + require.NoError(t, s.initializeES()) + s.IntegrationTestAll(t) +} diff --git a/plugin/storage/integration/fixtures/queries.json b/plugin/storage/integration/fixtures/queries.json new file mode 100644 index 00000000000..bbb094991f9 --- /dev/null +++ b/plugin/storage/integration/fixtures/queries.json @@ -0,0 +1,380 @@ +[ + { + "Caption": "Tags in one spot - Tags", + "Query": { + "ServiceName": "query01-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["span_tags_trace"] + }, + { + "Caption": "Tags in one spot - Logs", + "Query": { + "ServiceName": "query02-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["log_tags_trace"] + }, + { + "Caption": "Tags in one spot - Process", + "Query": { + "ServiceName": "query03-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["process_tags_trace"] + }, + { + "Caption": "Tags in different spots", + "Query": { + "ServiceName": "query04-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multi_spot_tags_trace"] + }, + { + "Caption": "Trace spans over multiple indices", + "Query": { + "ServiceName": "query05-service", + "OperationName": "", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multi_index_trace"] + }, + { + "Caption": "Operation name", + "Query": { + "ServiceName": "query06-service", + "OperationName": "query06-operation", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["opname_trace"] + }, + { + "Caption": "Operation name + max Duration", + "Query": { + "ServiceName": "query07-service", + "OperationName": "query07-operation", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 2000, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["opname_maxdur_trace"] + }, + { + "Caption": "Operation name + Duration range", + "Query": { + "ServiceName": "query08-service", + "OperationName": "query08-operation", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 4500, + "DurationMax": 5500, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["opname_dur_trace"] + }, + { + "Caption": "Duration range", + "Query": { + "ServiceName": "query09-service", + "OperationName": "", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 4500, + "DurationMax": 5500, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["dur_trace"] + }, + { + "Caption": "max Duration", + "Query": { + "ServiceName": "query10-service", + "OperationName": "", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 1000, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["max_dur_trace"] + }, + { + "Caption": "default", + "Query": { + "ServiceName": "query11-service", + "OperationName": "", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["default"] + }, + { + "Caption": "Tags + Operation name", + "Query": { + "ServiceName": "query12-service", + "OperationName": "query12-operation", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["tags_opname_trace"] + }, + { + "Caption": "Tags + Operation name + max Duration", + "Query": { + "ServiceName": "query13-service", + "OperationName": "query13-operation", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 2000, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["tags_opname_maxdur_trace"] + }, + { + "Caption": "Tags + Operation name + Duration range", + "Query": { + "ServiceName": "query14-service", + "OperationName": "query14-operation", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 4500, + "DurationMax": 5500, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["tags_opname_dur_trace"] + }, + { + "Caption": "Tags + Duration range", + "Query": { + "ServiceName": "query15-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 4500, + "DurationMax": 5500, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["tags_dur_trace"] + }, + { + "Caption": "Tags + max Duration", + "Query": { + "ServiceName": "query16-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 1000, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["tags_maxdur_trace"] + }, + { + "Caption": "Multi-spot Tags + Operation name", + "Query": { + "ServiceName": "query17-service", + "OperationName": "query17-operation", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multispottag_opname_trace"] + }, + { + "Caption": "Multi-spot Tags + Operation name + max Duration", + "Query": { + "ServiceName": "query18-service", + "OperationName": "query18-operation", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 2000, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multispottag_opname_maxdur_trace"] + }, + { + "Caption": "Multi-spot Tags + Operation name + Duration range", + "Query": { + "ServiceName": "query19-service", + "OperationName": "query19-operation", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 4500, + "DurationMax": 5500, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multispottag_opname_dur_trace"] + }, + { + "Caption": "Multi-spot Tags + Duration range", + "Query": { + "ServiceName": "query20-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 4500, + "DurationMax": 5500, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multispottag_dur_trace"] + }, + { + "Caption": "Multi-spot Tags + max Duration", + "Query": { + "ServiceName": "query21-service", + "OperationName": "", + "Tags": { + "sameplacetag1":"sameplacevalue", + "sameplacetag2":"123", + "sameplacetag3":"72.5", + "sameplacetag4":"true" + }, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 1000, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multispottag_maxdur_trace"] + }, + { + "Caption": "Multiple Traces", + "Query": { + "ServiceName": "query22-service", + "OperationName": "", + "Tags": null, + "StartTimeMin": "2017-01-26T15:46:31.639875Z", + "StartTimeMax": "2017-01-26T17:46:31.639875Z", + "DurationMin": 0, + "DurationMax": 0, + "NumTraces": 1000 + }, + "ExpectedFixtures": ["multiple1_trace", "multiple2_trace", "multiple3_trace"] + } +] diff --git a/plugin/storage/integration/fixtures/traces/default.json b/plugin/storage/integration/fixtures/traces/default.json new file mode 100644 index 00000000000..7087d466de4 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/default.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "11", + "spanID": "3", + "operationName": "", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "query11-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/dur_trace.json b/plugin/storage/integration/fixtures/traces/dur_trace.json new file mode 100644 index 00000000000..e96a7c07491 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/dur_trace.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "9", + "spanID": "3", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query09-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/example_trace.json b/plugin/storage/integration/fixtures/traces/example_trace.json new file mode 100644 index 00000000000..30e63b33a1b --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/example_trace.json @@ -0,0 +1,119 @@ +{ + "Spans": [ + { + "traceID": "11", + "spanID": "3", + "operationName": "example-operation-1", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "example-service-1", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + }, + { + "traceID": "11", + "spanID": "4", + "operationName": "example-operation-2", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "example-service-2", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + }, + { + "traceID": "11", + "spanID": "5", + "operationName": "example-operation-1", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "example-service-3", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + }, + { + "traceID": "11", + "spanID": "6", + "operationName": "example-operation-3", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "example-service-1", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + }, + { + "traceID": "11", + "spanID": "7", + "operationName": "example-operation-4", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "example-service-1", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/log_tags_trace.json b/plugin/storage/integration/fixtures/traces/log_tags_trace.json new file mode 100644 index 00000000000..3ca7aeac404 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/log_tags_trace.json @@ -0,0 +1,53 @@ +{ + "Spans": [ + { + "traceID": "2", + "spanID": "1", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query02-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/max_dur_trace.json b/plugin/storage/integration/fixtures/traces/max_dur_trace.json new file mode 100644 index 00000000000..b0a5e1c3a04 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/max_dur_trace.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "10", + "spanID": "2", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 1000, + "tags": [], + "process": { + "serviceName": "query10-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multi_index_trace.json b/plugin/storage/integration/fixtures/traces/multi_index_trace.json new file mode 100644 index 00000000000..36a0cf7e159 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multi_index_trace.json @@ -0,0 +1,50 @@ +{ + "Spans": [ + { + "traceID": "5", + "spanID": "1", + "operationName": "operation-list-test2", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query05-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + }, + { + "traceID": "5", + "spanID": "2", + "operationName": "operation-list-test3", + "references": [], + "startTime": "2017-01-25T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query05-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multi_spot_tags_trace.json b/plugin/storage/integration/fixtures/traces/multi_spot_tags_trace.json new file mode 100644 index 00000000000..ca43d1edc1e --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multi_spot_tags_trace.json @@ -0,0 +1,50 @@ +{ + "Spans": [ + { + "traceID": "4", + "spanID": "1", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [ + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + } + ], + "process": { + "serviceName": "query04-service", + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multiple1_trace.json b/plugin/storage/integration/fixtures/traces/multiple1_trace.json new file mode 100644 index 00000000000..541acb6a387 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multiple1_trace.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "221", + "spanID": "3", + "operationName": "", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "query22-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multiple2_trace.json b/plugin/storage/integration/fixtures/traces/multiple2_trace.json new file mode 100644 index 00000000000..bb5aacf2521 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multiple2_trace.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "222", + "spanID": "3", + "operationName": "", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "query22-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multiple3_trace.json b/plugin/storage/integration/fixtures/traces/multiple3_trace.json new file mode 100644 index 00000000000..a2827956dc6 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multiple3_trace.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "223", + "spanID": "3", + "operationName": "", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 100000, + "tags": [], + "process": { + "serviceName": "query22-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multispottag_dur_trace.json b/plugin/storage/integration/fixtures/traces/multispottag_dur_trace.json new file mode 100644 index 00000000000..11073d75d90 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multispottag_dur_trace.json @@ -0,0 +1,55 @@ +{ + "Spans": [ + { + "traceID": "20", + "spanID": "3", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [ + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + } + ], + "process": { + "serviceName": "query20-service", + "tags": [ + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multispottag_maxdur_trace.json b/plugin/storage/integration/fixtures/traces/multispottag_maxdur_trace.json new file mode 100644 index 00000000000..e54f78a2dd9 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multispottag_maxdur_trace.json @@ -0,0 +1,56 @@ +{ + "Spans": [ + { + "traceID": "21", + "spanID": "5", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 1000, + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + } + ], + "process": { + "serviceName": "query21-service", + "tags": [ + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multispottag_opname_dur_trace.json b/plugin/storage/integration/fixtures/traces/multispottag_opname_dur_trace.json new file mode 100644 index 00000000000..229bdc2c89e --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multispottag_opname_dur_trace.json @@ -0,0 +1,56 @@ +{ + "Spans": [ + { + "traceID": "19", + "spanID": "5", + "operationName": "query19-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + } + ], + "process": { + "serviceName": "query19-service", + "tags": [ + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multispottag_opname_maxdur_trace.json b/plugin/storage/integration/fixtures/traces/multispottag_opname_maxdur_trace.json new file mode 100644 index 00000000000..f8fb32db67b --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multispottag_opname_maxdur_trace.json @@ -0,0 +1,56 @@ +{ + "Spans": [ + { + "traceID": "18", + "spanID": "4", + "operationName": "query18-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 1000, + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + } + ], + "process": { + "serviceName": "query18-service", + "tags": [ + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/multispottag_opname_trace.json b/plugin/storage/integration/fixtures/traces/multispottag_opname_trace.json new file mode 100644 index 00000000000..6d1a6f6d7d2 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/multispottag_opname_trace.json @@ -0,0 +1,51 @@ +{ + "Spans": [ + { + "traceID": "17", + "spanID": "4", + "operationName": "query17-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [ + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + } + ], + "process": { + "serviceName": "query17-service", + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + } + ] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/opname_dur_trace.json b/plugin/storage/integration/fixtures/traces/opname_dur_trace.json new file mode 100644 index 00000000000..b9cd5e64923 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/opname_dur_trace.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "8", + "spanID": "2", + "operationName": "query08-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query08-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/opname_maxdur_trace.json b/plugin/storage/integration/fixtures/traces/opname_maxdur_trace.json new file mode 100644 index 00000000000..be06d03adc8 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/opname_maxdur_trace.json @@ -0,0 +1,42 @@ +{ + "Spans": [ + { + "traceID": "7", + "spanID": "3", + "parentSpanID": "2", + "operationName": "query07-operation", + "tags": [], + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 1000, + "process": { + "serviceName": "query07-service", + "tags": [] + }, + "logs": [] + }, + { + "traceID": "7", + "spanID": "2", + "operationName": "query07-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 2000, + "tags": [], + "process": { + "serviceName": "query07-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/opname_trace.json b/plugin/storage/integration/fixtures/traces/opname_trace.json new file mode 100644 index 00000000000..8f8f713182b --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/opname_trace.json @@ -0,0 +1,27 @@ +{ + "Spans": [ + { + "traceID": "6", + "spanID": "1", + "operationName": "query06-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query06-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/process_tags_trace.json b/plugin/storage/integration/fixtures/traces/process_tags_trace.json new file mode 100644 index 00000000000..029bf564ccb --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/process_tags_trace.json @@ -0,0 +1,53 @@ +{ + "Spans": [ + { + "traceID": "3", + "spanID": "1", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query03-service", + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/span_tags_trace.json b/plugin/storage/integration/fixtures/traces/span_tags_trace.json new file mode 100644 index 00000000000..241c3681953 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/span_tags_trace.json @@ -0,0 +1,44 @@ +{ + "Spans": [ + { + "traceID": "1", + "spanID": "2", + "operationName": "some-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 7000, + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ], + "process": { + "serviceName": "query01-service", + "tags": [] + }, + "logs": [] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/tags_dur_trace.json b/plugin/storage/integration/fixtures/traces/tags_dur_trace.json new file mode 100644 index 00000000000..dc242d767a6 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/tags_dur_trace.json @@ -0,0 +1,53 @@ +{ + "Spans": [ + { + "traceID": "15", + "spanID": "4", + "operationName": "placeholder", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ], + "process": { + "serviceName": "query15-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/tags_maxdur_trace.json b/plugin/storage/integration/fixtures/traces/tags_maxdur_trace.json new file mode 100644 index 00000000000..833fd1cabe3 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/tags_maxdur_trace.json @@ -0,0 +1,53 @@ +{ + "Spans": [ + { + "traceID": "16", + "spanID": "5", + "operationName": "", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 1000, + "tags": [], + "process": { + "serviceName": "query16-service", + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/tags_opname_dur_trace.json b/plugin/storage/integration/fixtures/traces/tags_opname_dur_trace.json new file mode 100644 index 00000000000..d0d9576ea91 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/tags_opname_dur_trace.json @@ -0,0 +1,53 @@ +{ + "Spans": [ + { + "traceID": "14", + "spanID": "3", + "operationName": "query14-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 5000, + "tags": [], + "process": { + "serviceName": "query14-service", + "tags": [] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/tags_opname_maxdur_trace.json b/plugin/storage/integration/fixtures/traces/tags_opname_maxdur_trace.json new file mode 100644 index 00000000000..ef627105be6 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/tags_opname_maxdur_trace.json @@ -0,0 +1,71 @@ +{ + "Spans": [ + { + "traceID": "13", + "spanID": "7", + "operationName": "query13-operation", + "references": [], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 1000, + "tags": [ + { + "key": "tag1", + "vType": "string", + "vStr": "value1" + } + ], + "process": { + "serviceName": "query13-service", + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ] + }, + "logs": [ + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "tag3", + "vType": "string", + "vStr": "value3" + } + ] + }, + { + "timestamp": "2017-01-26T16:46:31.639875Z", + "fields": [ + { + "key": "something", + "vType": "string", + "vStr": "blah" + } + ] + } + ] + } + ] +} diff --git a/plugin/storage/integration/fixtures/traces/tags_opname_trace.json b/plugin/storage/integration/fixtures/traces/tags_opname_trace.json new file mode 100644 index 00000000000..2a2bb2e48e6 --- /dev/null +++ b/plugin/storage/integration/fixtures/traces/tags_opname_trace.json @@ -0,0 +1,60 @@ +{ + "Spans": [ + { + "traceID": "12", + "spanID": "4", + "operationName": "query12-operation", + "references": [ + { + "refType": "child-of", + "traceID": "ff", + "spanID": "ff" + }, + { + "refType": "child-of", + "traceID": "1", + "spanID": "2" + }, + { + "refType": "follows-from", + "traceID": "1", + "spanID": "2" + } + ], + "tags": [ + { + "key": "sameplacetag1", + "vType": "string", + "vStr": "sameplacevalue" + }, + { + "key": "sameplacetag2", + "vType": "int64", + "vNum": 123 + }, + { + "key": "sameplacetag4", + "vType": "bool", + "vNum": 1 + }, + { + "key": "sameplacetag3", + "vType": "float64", + "vNum": 4634802150889750528 + }, + { + "key": "blob", + "vType": "binary", + "vBlob": "AAAwOQ==" + } + ], + "startTime": "2017-01-26T16:46:31.639875Z", + "duration": 2000, + "process": { + "serviceName": "query12-service", + "tags": [] + }, + "logs": [] + } + ] +} diff --git a/plugin/storage/integration/integration_test.go b/plugin/storage/integration/integration_test.go new file mode 100644 index 00000000000..62e0e8db44b --- /dev/null +++ b/plugin/storage/integration/integration_test.go @@ -0,0 +1,276 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package integration + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "math/rand" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/uber/jaeger/model" + "github.com/uber/jaeger/storage/spanstore" +) + +const ( + iterations = 30 + waitForBackendComment = "Waiting for storage backend to update documents, iteration %d out of %d" +) + +type StorageIntegration struct { + logger *zap.Logger + writer spanstore.Writer + reader spanstore.Reader + + // cleanUp() should ensure that the storage backend is clean before another test. + // called either before or after each test, and should be idempotent + cleanUp func() error + + // refresh() should ensure that the storage backend is up to date before being queried. + // called between set-up and queries in each test + refresh func() error +} + +// QueryFixtures and TraceFixtures are under ./fixtures/queries.json and ./fixtures/traces/*.json respectively. +// Each query fixture includes: +// Caption: describes the query we are testing +// Query: the query we are testing +// ExpectedFixture: the trace fixture that we want back from these queries. +// Queries are not necessarily numbered, but since each query requires a service name, +// the service name is formatted "query##-service". +type QueryFixtures struct { + Caption string + Query *spanstore.TraceQueryParameters + ExpectedFixtures []string +} + +func (s *StorageIntegration) IntegrationTestGetServices(t *testing.T) { + t.Log("Testing GetServices ...") + + expected := []string{"example-service-1", "example-service-2", "example-service-3"} + s.getBasicFixture(t) + require.NoError(t, s.refresh()) + + var found bool + + var actual []string + for i := 0; i < iterations; i++ { + s.logger.Info(fmt.Sprintf(waitForBackendComment, i+1, iterations)) + actual, err := s.reader.GetServices() + require.NoError(t, err) + if found = assert.ObjectsAreEqualValues(expected, actual); found { + break + } + time.Sleep(100 * time.Millisecond) // Will wait up to 3 seconds at worst. + } + + if !assert.True(t, found) { + t.Log("\t Expected:", expected) + t.Log("\t Actual :", actual) + } + assert.NoError(t, s.cleanUp()) +} + +func (s *StorageIntegration) IntegrationTestGetOperations(t *testing.T) { + t.Log("Testing GetOperations ...") + + expected := []string{"example-operation-1", "example-operation-3", "example-operation-4"} + s.getBasicFixture(t) + require.NoError(t, s.refresh()) + + var found bool + var actual []string + for i := 0; i < iterations; i++ { + s.logger.Info(fmt.Sprintf(waitForBackendComment, i+1, iterations)) + actual, err := s.reader.GetOperations("example-service-1") + require.NoError(t, err) + if found = assert.ObjectsAreEqualValues(expected, actual); found { + break + } + time.Sleep(100 * time.Millisecond) // Will wait up to 3 seconds at worst. + } + + if !assert.True(t, found) { + t.Log("\t Expected:", expected) + t.Log("\t Actual :", actual) + } + assert.NoError(t, s.cleanUp()) +} + +func (s *StorageIntegration) IntegrationTestGetTrace(t *testing.T) { + t.Log("Testing GetTrace ...") + + expected := s.getBasicFixture(t) + expectedTraceID := expected.Spans[0].TraceID + require.NoError(t, s.refresh()) + + var actual *model.Trace + for i := 0; i < iterations; i++ { + s.logger.Info(fmt.Sprintf(waitForBackendComment, i+1, iterations)) + var err error + actual, err = s.reader.GetTrace(expectedTraceID) + if err == nil && len(actual.Spans) == len(expected.Spans) { + break + } + time.Sleep(100 * time.Millisecond) // Will wait up to 3 seconds at worst. + } + + CompareTraces(t, expected, actual) + assert.NoError(t, s.cleanUp()) +} + +func (s *StorageIntegration) IntegrationTestFindTraces(t *testing.T) { + t.Log("Testing FindTraces ...") + t.Log("\t(Note: all cases include ServiceName + StartTime range)") + queries, err := getQueries() + require.NoError(t, err) + for _, query := range queries { + t.Logf("\t\t* Query case: + %s", query.Caption) + s.integrationTestFindTracesByQuery(t, query.Query, query.ExpectedFixtures) + } +} + +func (s *StorageIntegration) integrationTestFindTracesByQuery(t *testing.T, query *spanstore.TraceQueryParameters, expectedFixtures []string) { + expected, err := getTraceFixtures(expectedFixtures) + require.NoError(t, err) + require.NoError(t, s.writeTraces(expected)) + require.NoError(t, s.refresh()) + + var found bool + var actual []*model.Trace + for i := 0; i < iterations; i++ { + s.logger.Info(fmt.Sprintf(waitForBackendComment, i+1, iterations)) + actual, err = s.reader.FindTraces(query) + if err == nil { + if found = tracesMatch(actual, expected); found { + CompareSliceOfTraces(t, expected, actual) + break + } + } + time.Sleep(100 * time.Millisecond) + } + if !assert.True(t, found) { + CompareSliceOfTraces(t, expected, actual) + } + assert.NoError(t, s.cleanUp()) +} + +func (s *StorageIntegration) writeTraces(traces []*model.Trace) error { + for _, trace := range traces { + if err := s.writeTrace(trace); err != nil { + return err + } + } + return nil +} + +func (s *StorageIntegration) writeTrace(trace *model.Trace) error { + for _, span := range trace.Spans { + if err := s.writer.WriteSpan(span); err != nil { + return err + } + } + return nil +} + +func (s *StorageIntegration) getBasicFixture(t *testing.T) *model.Trace { + trace, err := getTraceFixture("example_trace") + require.NoError(t, err) + require.NoError(t, s.writeTrace(trace)) + return trace +} + +func getTraceFixture(fixture string) (*model.Trace, error) { + var trace model.Trace + fileName := fmt.Sprintf("fixtures/traces/%s.json", fixture) + if err := getFixture(fileName, &trace); err != nil { + return nil, err + } + return &trace, nil +} + +func getTraceFixtures(fixtures []string) ([]*model.Trace, error) { + traces := make([]*model.Trace, len(fixtures)) + for i, fixture := range fixtures { + trace, err := getTraceFixture(fixture) + if err != nil { + return nil, err + } + traces[i] = trace + } + return traces, nil +} + +func getQueries() ([]*QueryFixtures, error) { + var queries []*QueryFixtures + if err := getFixture("fixtures/queries.json", &queries); err != nil { + return nil, err + } + return queries, nil +} + +func getFixture(path string, object interface{}) error { + inStr, err := ioutil.ReadFile(path) + if err != nil { + return err + } + return json.Unmarshal(correctTime(inStr), object) +} + +// required, because we want to only query on recent traces, so we replace all the dates with recent dates. +func correctTime(json []byte) []byte { + jsonString := string(json) + today := time.Now().Format("2006-01-02") + yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02") + retString := strings.Replace(jsonString, "2017-01-26", today, -1) + retString = strings.Replace(retString, "2017-01-25", yesterday, -1) + return []byte(retString) +} + +func tracesMatch(actual []*model.Trace, expected []*model.Trace) bool { + if len(actual) != len(expected) { + return false + } + return spanCount(actual) == spanCount(expected) +} + +func spanCount(traces []*model.Trace) int { + var count int + for _, trace := range traces { + count += len(trace.Spans) + } + return count +} + +func (s *StorageIntegration) IntegrationTestAll(t *testing.T) { + rand.Seed(time.Now().UnixNano()) + s.IntegrationTestGetServices(t) + s.IntegrationTestGetOperations(t) + s.IntegrationTestGetTrace(t) + s.IntegrationTestFindTraces(t) +} diff --git a/travis/es-integration-test.sh b/travis/es-integration-test.sh new file mode 100755 index 00000000000..0abff280bb3 --- /dev/null +++ b/travis/es-integration-test.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +docker pull docker.elastic.co/elasticsearch/elasticsearch:5.4.0 +export CID=$(docker run -d -p 9200:9200 -e "http.host=0.0.0.0" -e "transport.host=127.0.0.1" docker.elastic.co/elasticsearch/elasticsearch:5.4.0) +export ES_INTEGRATION_TEST=test +make es-integration-test +unset ES_INTEGRATION_TEST +docker kill $CID