From b83828b35141b9b309fd22a2c785920b09d7e09a Mon Sep 17 00:00:00 2001 From: Dan Jaglowski Date: Wed, 29 May 2024 15:37:24 -0400 Subject: [PATCH 1/3] [chore] Add internal pdatautil.GroupByScope --- .github/CODEOWNERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1bdb4f8fe2fc..252b6399dddb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -288,10 +288,10 @@ testbed/mockdatasenders/mockdatadogagentexporter/ @open-telemetry/collect # List of distribution maintainers for OpenTelemetry Collector Contrib # ##################################################### -reports/distributions/core.yaml @open-telemetry/collector-contrib-approvers -reports/distributions/contrib.yaml @open-telemetry/collector-contrib-approvers +reports/distributions/core.yaml @open-telemetry/collector-contrib-approvers +reports/distributions/contrib.yaml @open-telemetry/collector-contrib-approvers ## UNMAINTAINED components -exporter/skywalkingexporter/ @open-telemetry/collector-contrib-approvers +exporter/skywalkingexporter/ @open-telemetry/collector-contrib-approvers From 8883d315a25b125648e6a27448a64de7afebe18e Mon Sep 17 00:00:00 2001 From: Dan Jaglowski Date: Wed, 29 May 2024 15:37:24 -0400 Subject: [PATCH 2/3] [chore] Add internal pdatautil.GroupByScope --- internal/pdatautil/resource.go | 53 +++++ internal/pdatautil/resource_test.go | 333 ++++++++++++++++++++++++++++ internal/pdatautil/scope.go | 63 ++++++ internal/pdatautil/scope_test.go | 156 +++++++++++++ 4 files changed, 605 insertions(+) create mode 100644 internal/pdatautil/resource.go create mode 100644 internal/pdatautil/resource_test.go create mode 100644 internal/pdatautil/scope.go create mode 100644 internal/pdatautil/scope_test.go diff --git a/internal/pdatautil/resource.go b/internal/pdatautil/resource.go new file mode 100644 index 000000000000..1b5a82256584 --- /dev/null +++ b/internal/pdatautil/resource.go @@ -0,0 +1,53 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pdatautil // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/pdatautil" + +import ( + "go.opentelemetry.io/collector/pdata/plog" + + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil" +) + +// GroupByResourceLogs groups ScopeLogs by Resource. Modifications are made in place. +func GroupByResourceLogs(rls plog.ResourceLogsSlice) { + // Hash each ResourceLogs based on identifying information. + resourceHashes := make([][16]byte, rls.Len()) + for i := 0; i < rls.Len(); i++ { + resourceHashes[i] = pdatautil.MapHash(rls.At(i).Resource().Attributes()) + } + + // Find the first occurrence of each hash and note the index. + firstScopeIndex := make([]int, rls.Len()) + for i := 0; i < rls.Len(); i++ { + firstScopeIndex[i] = i + for j := 0; j < i; j++ { + if resourceHashes[i] == resourceHashes[j] { + firstScopeIndex[i] = j + break + } + } + } + + // Merge Resources with the same hash. + for i := 0; i < rls.Len(); i++ { + if i == firstScopeIndex[i] { + // This is the first occurrence of this hash. + continue + } + rls.At(i).ScopeLogs().MoveAndAppendTo(rls.At(firstScopeIndex[i]).ScopeLogs()) + } + + // Remove the ResourceLogs which were merged onto others. + i := 0 + rls.RemoveIf(func(plog.ResourceLogs) bool { + remove := i != firstScopeIndex[i] + i++ + return remove + }) + + // Merge ScopeLogs within each ResourceLogs. + for i := 0; i < rls.Len(); i++ { + GroupByScopeLogs(rls.At(i).ScopeLogs()) + } +} diff --git a/internal/pdatautil/resource_test.go b/internal/pdatautil/resource_test.go new file mode 100644 index 000000000000..2795026a060a --- /dev/null +++ b/internal/pdatautil/resource_test.go @@ -0,0 +1,333 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pdatautil + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/plog" + + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/plogtest" +) + +func TestGroupByResourceLogs(t *testing.T) { + testCases := []struct { + name string + input []resourceLogs + expected []resourceLogs + }{ + { + name: "empty", + input: []resourceLogs{}, + expected: []resourceLogs{}, + }, + { + name: "single", + input: []resourceLogs{newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + ), + }, + expected: []resourceLogs{newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + ), + }, + }, + { + name: "distinct", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + ), + newResourceLogs(2, + newScopeLogs(3, 31, 32, 33), + newScopeLogs(4, 41, 42, 43), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + ), + newResourceLogs(2, + newScopeLogs(3, 31, 32, 33), + newScopeLogs(4, 41, 42, 43), + ), + }, + }, + { + name: "simple_merge_scopes", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(1, 14, 15, 16), + ), + newResourceLogs(2, + newScopeLogs(2, 21, 22, 23), + newScopeLogs(2, 24, 25, 26), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + ), + newResourceLogs(2, + newScopeLogs(2, 21, 22, 23, 24, 25, 26), + ), + }, + }, + { + name: "merge_scopes_on_some_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(1, 14, 15, 16), + ), + newResourceLogs(2, + newScopeLogs(2, 21, 22, 23), + newScopeLogs(3, 31, 32, 33), + ), + newResourceLogs(3, + newScopeLogs(4, 41, 42, 43), + newScopeLogs(4, 44, 45, 46), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + ), + newResourceLogs(2, + newScopeLogs(2, 21, 22, 23), + newScopeLogs(3, 31, 32, 33), + ), + newResourceLogs(3, + newScopeLogs(4, 41, 42, 43, 44, 45, 46), + ), + }, + }, + { + name: "leave_same_scopes_on_distinct_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + ), + newResourceLogs(2, + newScopeLogs(1, 11, 12, 13), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + ), + newResourceLogs(2, + newScopeLogs(1, 11, 12, 13), + ), + }, + }, + { + name: "merge_scopes_within_distinct_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(1, 14, 15, 16), + ), + newResourceLogs(2, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(1, 14, 15, 16), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + ), + newResourceLogs(2, + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + ), + }, + }, + { + name: "merge_resources_preserve_distinct_scopes", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + ), + newResourceLogs(1, + newScopeLogs(3, 31, 32, 33), + newScopeLogs(4, 41, 42, 43), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + newScopeLogs(3, 31, 32, 33), + newScopeLogs(4, 41, 42, 43), + ), + }, + }, + { + name: "merge_interleaved_scopes_within_resource", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + newScopeLogs(1, 14, 15, 16), + newScopeLogs(2, 24, 25, 26), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + newScopeLogs(2, 21, 22, 23, 24, 25, 26), + ), + }, + }, + { + name: "merge_interleaved_scopes_across_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + ), + newResourceLogs(1, + newScopeLogs(1, 14, 15, 16), + newScopeLogs(2, 24, 25, 26), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + newScopeLogs(2, 21, 22, 23, 24, 25, 26), + ), + }, + }, + { + name: "merge_interleaved_scopes_across_interleaved_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103), + newScopeLogs(22, 201, 202, 203), + ), + newResourceLogs(2, + newScopeLogs(33, 301, 302, 303), + newScopeLogs(44, 401, 402, 403), + ), + newResourceLogs(1, + newScopeLogs(11, 104, 105, 106), + newScopeLogs(22, 204, 205, 206), + ), + newResourceLogs(2, + newScopeLogs(33, 304, 305, 306), + newScopeLogs(44, 404, 405, 406), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103, 104, 105, 106), + newScopeLogs(22, 201, 202, 203, 204, 205, 206), + ), + newResourceLogs(2, + newScopeLogs(33, 301, 302, 303, 304, 305, 306), + newScopeLogs(44, 401, 402, 403, 404, 405, 406), + ), + }, + }, + { + name: "merge_some_scopes_across_some_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103), + newScopeLogs(22, 201, 202, 203), + ), + newResourceLogs(2, + newScopeLogs(33, 301, 302, 303), + newScopeLogs(11, 104, 105, 106), + ), + newResourceLogs(1, + newScopeLogs(33, 301, 302, 303), + newScopeLogs(11, 104, 105, 106), + ), + newResourceLogs(2, + newScopeLogs(33, 304, 305, 306), + newScopeLogs(44, 404, 405, 406), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103, 104, 105, 106), + newScopeLogs(22, 201, 202, 203), + newScopeLogs(33, 301, 302, 303), + ), + newResourceLogs(2, + newScopeLogs(33, 301, 302, 303, 304, 305, 306), + newScopeLogs(11, 104, 105, 106), + newScopeLogs(44, 404, 405, 406), + ), + }, + }, + { + name: "merge_all_resources_and_scopes", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 101, 102), + newScopeLogs(1, 103, 104), + ), + newResourceLogs(1, + newScopeLogs(1, 105, 106), + newScopeLogs(1, 107, 108), + ), + newResourceLogs(1, + newScopeLogs(1, 109, 110), + newScopeLogs(1, 111, 112), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(1, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112), + ), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := plog.NewResourceLogsSlice() + for _, r := range tc.input { + r.setup(actual.AppendEmpty()) + } + expected := plog.NewResourceLogsSlice() + for _, r := range tc.expected { + r.setup(expected.AppendEmpty()) + } + + GroupByResourceLogs(actual) + assert.Equal(t, expected.Len(), actual.Len()) + for i := 0; i < expected.Len(); i++ { + assert.NoError(t, plogtest.CompareResourceLogs(expected.At(i), actual.At(i))) + } + }) + } +} + +type resourceLogs struct { + num int + scopes []scopeLogs +} + +func newResourceLogs(num int, scopes ...scopeLogs) resourceLogs { + return resourceLogs{ + num: num, + scopes: scopes, + } +} + +func (r resourceLogs) setup(rl plog.ResourceLogs) { + rl.Resource().Attributes().PutStr("attr.name", fmt.Sprintf("attr_%d", r.num)) + for _, s := range r.scopes { + s.setup(rl.ScopeLogs().AppendEmpty()) + } +} diff --git a/internal/pdatautil/scope.go b/internal/pdatautil/scope.go new file mode 100644 index 000000000000..ec23f095d268 --- /dev/null +++ b/internal/pdatautil/scope.go @@ -0,0 +1,63 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pdatautil // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/pdatautil" + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/plog" + + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil" +) + +// GroupByScopeLogs groups LogRecords by scope. Modifications are made in place. +func GroupByScopeLogs(sls plog.ScopeLogsSlice) { + // Hash each ScopeLogs based on identifying information. + scopeHashes := make([][16]byte, sls.Len()) + for i := 0; i < sls.Len(); i++ { + scopeHashes[i] = HashScopeLogs(sls.At(i)) + } + + // Find the first occurrence of each hash and note the index. + firstScopeIndex := make([]int, sls.Len()) + for i := 0; i < sls.Len(); i++ { + firstScopeIndex[i] = i + for j := 0; j < i; j++ { + if scopeHashes[i] == scopeHashes[j] { + firstScopeIndex[i] = j + break + } + } + } + + // Merge ScopeLogs with the same hash. + for i := 0; i < sls.Len(); i++ { + if i == firstScopeIndex[i] { + // This is the first occurrence of this hash. + continue + } + sls.At(i).LogRecords().MoveAndAppendTo(sls.At(firstScopeIndex[i]).LogRecords()) + } + + // Remove the ScopeLogs which were merged onto others. + i := 0 + sls.RemoveIf(func(plog.ScopeLogs) bool { + remove := i != firstScopeIndex[i] + i++ + return remove + }) +} + +// Creates a hash based on the ScopeLogs attributes, name, and version +func HashScopeLogs(sl plog.ScopeLogs) [16]byte { + scopeHash := pcommon.NewMap() + scopeHash.PutStr("schema_url", sl.SchemaUrl()) + scopeHash.PutStr("name", sl.Scope().Name()) + scopeHash.PutStr("version", sl.Scope().Version()) + scopeHash.PutStr("attributes_hash", hashToString(pdatautil.MapHash(sl.Scope().Attributes()))) + return pdatautil.MapHash(scopeHash) +} + +func hashToString(hash [16]byte) string { + return string(hash[:]) +} diff --git a/internal/pdatautil/scope_test.go b/internal/pdatautil/scope_test.go new file mode 100644 index 000000000000..05766e599d1a --- /dev/null +++ b/internal/pdatautil/scope_test.go @@ -0,0 +1,156 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pdatautil + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/plog" + + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/plogtest" +) + +func TestGroupByScopeLogs(t *testing.T) { + testCases := []struct { + name string + input []scopeLogs + expected []scopeLogs + }{ + { + name: "empty", + input: []scopeLogs{}, + expected: []scopeLogs{}, + }, + { + name: "single", + input: []scopeLogs{ + newScopeLogs(1, 11, 12, 13), + }, + expected: []scopeLogs{ + newScopeLogs(1, 11, 12, 13), + }, + }, + { + name: "distinct", + input: []scopeLogs{ + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + }, + expected: []scopeLogs{ + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + }, + }, + { + name: "simple_merge", + input: []scopeLogs{ + newScopeLogs(1, 11, 12, 13), + newScopeLogs(1, 14, 15, 16), + }, + expected: []scopeLogs{ + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + }, + }, + { + name: "interleaved", + input: []scopeLogs{ + newScopeLogs(1, 11, 12, 13), + newScopeLogs(2, 21, 22, 23), + newScopeLogs(1, 14, 15, 16), + newScopeLogs(2, 24, 25, 26), + }, + expected: []scopeLogs{ + newScopeLogs(1, 11, 12, 13, 14, 15, 16), + newScopeLogs(2, 21, 22, 23, 24, 25, 26), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := plog.NewScopeLogsSlice() + for _, s := range tc.input { + s.setup(actual.AppendEmpty()) + } + expected := plog.NewScopeLogsSlice() + for _, s := range tc.expected { + s.setup(expected.AppendEmpty()) + } + + GroupByScopeLogs(actual) + assert.Equal(t, expected.Len(), actual.Len()) + for i := 0; i < expected.Len(); i++ { + assert.NoError(t, plogtest.CompareScopeLogs(expected.At(i), actual.At(i))) + } + }) + } +} + +type scopeLogs struct { + num int + recordNums []int +} + +func newScopeLogs(num int, recordNums ...int) scopeLogs { + return scopeLogs{ + num: num, + recordNums: recordNums, + } +} + +func (s scopeLogs) setup(sl plog.ScopeLogs) { + sl.SetSchemaUrl(fmt.Sprintf("schema_%d", s.num)) + ss := sl.Scope() + ss.SetName(fmt.Sprintf("name_%d", s.num)) + ss.SetVersion(fmt.Sprintf("version_%d", s.num)) + ss.Attributes().PutStr("attr.name", fmt.Sprintf("attr_%d", s.num)) + for _, n := range s.recordNums { + lr := sl.LogRecords().AppendEmpty() + lr.Attributes().PutInt("num", int64(n)) + lr.Body().SetInt(int64(n)) + } +} + +func TestHashScopeLogs(t *testing.T) { + schemas := []string{"", "schema_1", "schema_2"} + names := []string{"", "name_1", "name_2"} + versions := []string{"", "version_1", "version_2"} + attributes := []map[string]any{ + {}, + {"attr.name": "attr_1"}, + {"attr.name": "attr_2"}, + {"attr.name": "attr_1", "other.name": "other"}, + } + + distinctScopeLogs := make([]plog.ScopeLogs, 0, len(schemas)*len(names)*len(versions)*len(attributes)) + + for _, schema := range schemas { + for _, name := range names { + for _, version := range versions { + for _, attr := range attributes { + sl := plog.NewScopeLogs() + sl.SetSchemaUrl(schema) + ss := sl.Scope() + ss.SetName(name) + ss.SetVersion(version) + require.NoError(t, ss.Attributes().FromRaw(attr)) + distinctScopeLogs = append(distinctScopeLogs, sl) + } + } + } + } + + for i, slOne := range distinctScopeLogs { + for j, slTwo := range distinctScopeLogs { + if i == j { + assert.Equal(t, HashScopeLogs(slOne), HashScopeLogs(slTwo)) + } else { + assert.NotEqual(t, HashScopeLogs(slOne), HashScopeLogs(slTwo)) + } + } + } +} From 14a4574bb5c22ec7a5893ba2abcbae206c21b5d3 Mon Sep 17 00:00:00 2001 From: Dan Jaglowski Date: Fri, 31 May 2024 09:48:13 -0400 Subject: [PATCH 3/3] Add internal pdatautil Flatten funcs --- .github/CODEOWNERS | 6 +- internal/pdatautil/logs.go | 23 ++ internal/pdatautil/logs_test.go | 153 +++++++++++-- internal/pdatautil/resource.go | 53 ----- internal/pdatautil/resource_test.go | 333 ---------------------------- internal/pdatautil/scope.go | 63 ------ internal/pdatautil/scope_test.go | 156 ------------- 7 files changed, 161 insertions(+), 626 deletions(-) delete mode 100644 internal/pdatautil/resource.go delete mode 100644 internal/pdatautil/resource_test.go delete mode 100644 internal/pdatautil/scope.go delete mode 100644 internal/pdatautil/scope_test.go diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 252b6399dddb..1bdb4f8fe2fc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -288,10 +288,10 @@ testbed/mockdatasenders/mockdatadogagentexporter/ @open-telemetry/collect # List of distribution maintainers for OpenTelemetry Collector Contrib # ##################################################### -reports/distributions/core.yaml @open-telemetry/collector-contrib-approvers -reports/distributions/contrib.yaml @open-telemetry/collector-contrib-approvers +reports/distributions/core.yaml @open-telemetry/collector-contrib-approvers +reports/distributions/contrib.yaml @open-telemetry/collector-contrib-approvers ## UNMAINTAINED components -exporter/skywalkingexporter/ @open-telemetry/collector-contrib-approvers +exporter/skywalkingexporter/ @open-telemetry/collector-contrib-approvers diff --git a/internal/pdatautil/logs.go b/internal/pdatautil/logs.go index b27557d09e55..344bc6c2a8a2 100644 --- a/internal/pdatautil/logs.go +++ b/internal/pdatautil/logs.go @@ -10,6 +10,29 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil" ) +// FlattenResourceLogs moves each LogRecord onto a dedicated ResourceLogs and ScopeLogs. +// Modifications are made in place. Order of LogRecords is preserved. +func FlattenLogs(rls plog.ResourceLogsSlice) { + tmp := plog.NewResourceLogsSlice() + rls.MoveAndAppendTo(tmp) + for i := 0; i < tmp.Len(); i++ { + groupedResource := tmp.At(i) + for j := 0; j < groupedResource.ScopeLogs().Len(); j++ { + groupedScope := groupedResource.ScopeLogs().At(j) + for k := 0; k < groupedScope.LogRecords().Len(); k++ { + flatResource := rls.AppendEmpty() + groupedResource.Resource().Attributes().CopyTo(flatResource.Resource().Attributes()) + flatScope := flatResource.ScopeLogs().AppendEmpty() + flatScope.SetSchemaUrl(groupedScope.SchemaUrl()) + flatScope.Scope().SetName(groupedScope.Scope().Name()) + flatScope.Scope().SetVersion(groupedScope.Scope().Version()) + groupedScope.Scope().Attributes().CopyTo(flatScope.Scope().Attributes()) + groupedScope.LogRecords().At(k).CopyTo(flatScope.LogRecords().AppendEmpty()) + } + } + } +} + // GroupByResourceLogs groups ScopeLogs by Resource. Modifications are made in place. func GroupByResourceLogs(rls plog.ResourceLogsSlice) { // Hash each ResourceLogs based on identifying information. diff --git a/internal/pdatautil/logs_test.go b/internal/pdatautil/logs_test.go index e45632bdafc1..48329fac7876 100644 --- a/internal/pdatautil/logs_test.go +++ b/internal/pdatautil/logs_test.go @@ -14,6 +14,121 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/plogtest" ) +func TestFlattenResourceLogs(t *testing.T) { + testCases := []struct { + name string + input []resourceLogs + expected []resourceLogs + }{ + { + name: "empty", + input: []resourceLogs{}, + expected: []resourceLogs{}, + }, + { + name: "single", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 111), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 111), + ), + }, + }, + { + name: "flatten_single_scope_in_single_resource", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, newScopeLogs(11, 101)), + newResourceLogs(1, newScopeLogs(11, 102)), + newResourceLogs(1, newScopeLogs(11, 103)), + }, + }, + { + name: "flatten_multiple_scopes_in_single_resource", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103), + newScopeLogs(22, 201, 202, 203), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, newScopeLogs(11, 101)), + newResourceLogs(1, newScopeLogs(11, 102)), + newResourceLogs(1, newScopeLogs(11, 103)), + newResourceLogs(1, newScopeLogs(22, 201)), + newResourceLogs(1, newScopeLogs(22, 202)), + newResourceLogs(1, newScopeLogs(22, 203)), + }, + }, + { + name: "flatten_single_scope_in_multiple_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103), + ), + newResourceLogs(2, + newScopeLogs(11, 104, 105, 106), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, newScopeLogs(11, 101)), + newResourceLogs(1, newScopeLogs(11, 102)), + newResourceLogs(1, newScopeLogs(11, 103)), + newResourceLogs(2, newScopeLogs(11, 104)), + newResourceLogs(2, newScopeLogs(11, 105)), + newResourceLogs(2, newScopeLogs(11, 106)), + }, + }, + { + name: "flatten_multiple_scopes_in_multiple_resources", + input: []resourceLogs{ + newResourceLogs(1, + newScopeLogs(11, 101, 102, 103), + newScopeLogs(22, 201, 202, 203), + ), + newResourceLogs(2, + newScopeLogs(11, 104, 105, 106), + newScopeLogs(22, 204, 205, 206), + ), + }, + expected: []resourceLogs{ + newResourceLogs(1, newScopeLogs(11, 101)), + newResourceLogs(1, newScopeLogs(11, 102)), + newResourceLogs(1, newScopeLogs(11, 103)), + newResourceLogs(1, newScopeLogs(22, 201)), + newResourceLogs(1, newScopeLogs(22, 202)), + newResourceLogs(1, newScopeLogs(22, 203)), + newResourceLogs(2, newScopeLogs(11, 104)), + newResourceLogs(2, newScopeLogs(11, 105)), + newResourceLogs(2, newScopeLogs(11, 106)), + newResourceLogs(2, newScopeLogs(22, 204)), + newResourceLogs(2, newScopeLogs(22, 205)), + newResourceLogs(2, newScopeLogs(22, 206)), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := setupResourceLogsSlice(tc.input) + expected := setupResourceLogsSlice(tc.expected) + FlattenLogs(actual) + assert.Equal(t, expected.Len(), actual.Len()) + for i := 0; i < expected.Len(); i++ { + assert.NoError(t, plogtest.CompareResourceLogs(expected.At(i), actual.At(i))) + } + }) + } +} + func TestGroupByResourceLogs(t *testing.T) { testCases := []struct { name string @@ -296,15 +411,8 @@ func TestGroupByResourceLogs(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - actual := plog.NewResourceLogsSlice() - for _, r := range tc.input { - r.setup(actual.AppendEmpty()) - } - expected := plog.NewResourceLogsSlice() - for _, r := range tc.expected { - r.setup(expected.AppendEmpty()) - } - + actual := setupResourceLogsSlice(tc.input) + expected := setupResourceLogsSlice(tc.expected) GroupByResourceLogs(actual) assert.Equal(t, expected.Len(), actual.Len()) for i := 0; i < expected.Len(); i++ { @@ -372,15 +480,8 @@ func TestGroupByScopeLogs(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - actual := plog.NewScopeLogsSlice() - for _, s := range tc.input { - s.setup(actual.AppendEmpty()) - } - expected := plog.NewScopeLogsSlice() - for _, s := range tc.expected { - s.setup(expected.AppendEmpty()) - } - + actual := setupScopeLogsSlice(tc.input) + expected := setupScopeLogsSlice(tc.expected) GroupByScopeLogs(actual) assert.Equal(t, expected.Len(), actual.Len()) for i := 0; i < expected.Len(); i++ { @@ -449,6 +550,14 @@ func (r resourceLogs) setup(rl plog.ResourceLogs) { } } +func setupResourceLogsSlice(trls []resourceLogs) plog.ResourceLogsSlice { + rls := plog.NewResourceLogsSlice() + for _, trl := range trls { + trl.setup(rls.AppendEmpty()) + } + return rls +} + type scopeLogs struct { num int recordNums []int @@ -473,3 +582,11 @@ func (s scopeLogs) setup(sl plog.ScopeLogs) { lr.Body().SetInt(int64(n)) } } + +func setupScopeLogsSlice(tsls []scopeLogs) plog.ScopeLogsSlice { + sls := plog.NewScopeLogsSlice() + for _, tsl := range tsls { + tsl.setup(sls.AppendEmpty()) + } + return sls +} diff --git a/internal/pdatautil/resource.go b/internal/pdatautil/resource.go deleted file mode 100644 index 1b5a82256584..000000000000 --- a/internal/pdatautil/resource.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package pdatautil // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/pdatautil" - -import ( - "go.opentelemetry.io/collector/pdata/plog" - - "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil" -) - -// GroupByResourceLogs groups ScopeLogs by Resource. Modifications are made in place. -func GroupByResourceLogs(rls plog.ResourceLogsSlice) { - // Hash each ResourceLogs based on identifying information. - resourceHashes := make([][16]byte, rls.Len()) - for i := 0; i < rls.Len(); i++ { - resourceHashes[i] = pdatautil.MapHash(rls.At(i).Resource().Attributes()) - } - - // Find the first occurrence of each hash and note the index. - firstScopeIndex := make([]int, rls.Len()) - for i := 0; i < rls.Len(); i++ { - firstScopeIndex[i] = i - for j := 0; j < i; j++ { - if resourceHashes[i] == resourceHashes[j] { - firstScopeIndex[i] = j - break - } - } - } - - // Merge Resources with the same hash. - for i := 0; i < rls.Len(); i++ { - if i == firstScopeIndex[i] { - // This is the first occurrence of this hash. - continue - } - rls.At(i).ScopeLogs().MoveAndAppendTo(rls.At(firstScopeIndex[i]).ScopeLogs()) - } - - // Remove the ResourceLogs which were merged onto others. - i := 0 - rls.RemoveIf(func(plog.ResourceLogs) bool { - remove := i != firstScopeIndex[i] - i++ - return remove - }) - - // Merge ScopeLogs within each ResourceLogs. - for i := 0; i < rls.Len(); i++ { - GroupByScopeLogs(rls.At(i).ScopeLogs()) - } -} diff --git a/internal/pdatautil/resource_test.go b/internal/pdatautil/resource_test.go deleted file mode 100644 index 2795026a060a..000000000000 --- a/internal/pdatautil/resource_test.go +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package pdatautil - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/pdata/plog" - - "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/plogtest" -) - -func TestGroupByResourceLogs(t *testing.T) { - testCases := []struct { - name string - input []resourceLogs - expected []resourceLogs - }{ - { - name: "empty", - input: []resourceLogs{}, - expected: []resourceLogs{}, - }, - { - name: "single", - input: []resourceLogs{newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - ), - }, - expected: []resourceLogs{newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - ), - }, - }, - { - name: "distinct", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - ), - newResourceLogs(2, - newScopeLogs(3, 31, 32, 33), - newScopeLogs(4, 41, 42, 43), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - ), - newResourceLogs(2, - newScopeLogs(3, 31, 32, 33), - newScopeLogs(4, 41, 42, 43), - ), - }, - }, - { - name: "simple_merge_scopes", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(1, 14, 15, 16), - ), - newResourceLogs(2, - newScopeLogs(2, 21, 22, 23), - newScopeLogs(2, 24, 25, 26), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - ), - newResourceLogs(2, - newScopeLogs(2, 21, 22, 23, 24, 25, 26), - ), - }, - }, - { - name: "merge_scopes_on_some_resources", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(1, 14, 15, 16), - ), - newResourceLogs(2, - newScopeLogs(2, 21, 22, 23), - newScopeLogs(3, 31, 32, 33), - ), - newResourceLogs(3, - newScopeLogs(4, 41, 42, 43), - newScopeLogs(4, 44, 45, 46), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - ), - newResourceLogs(2, - newScopeLogs(2, 21, 22, 23), - newScopeLogs(3, 31, 32, 33), - ), - newResourceLogs(3, - newScopeLogs(4, 41, 42, 43, 44, 45, 46), - ), - }, - }, - { - name: "leave_same_scopes_on_distinct_resources", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - ), - newResourceLogs(2, - newScopeLogs(1, 11, 12, 13), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - ), - newResourceLogs(2, - newScopeLogs(1, 11, 12, 13), - ), - }, - }, - { - name: "merge_scopes_within_distinct_resources", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(1, 14, 15, 16), - ), - newResourceLogs(2, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(1, 14, 15, 16), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - ), - newResourceLogs(2, - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - ), - }, - }, - { - name: "merge_resources_preserve_distinct_scopes", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - ), - newResourceLogs(1, - newScopeLogs(3, 31, 32, 33), - newScopeLogs(4, 41, 42, 43), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - newScopeLogs(3, 31, 32, 33), - newScopeLogs(4, 41, 42, 43), - ), - }, - }, - { - name: "merge_interleaved_scopes_within_resource", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - newScopeLogs(1, 14, 15, 16), - newScopeLogs(2, 24, 25, 26), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - newScopeLogs(2, 21, 22, 23, 24, 25, 26), - ), - }, - }, - { - name: "merge_interleaved_scopes_across_resources", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - ), - newResourceLogs(1, - newScopeLogs(1, 14, 15, 16), - newScopeLogs(2, 24, 25, 26), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - newScopeLogs(2, 21, 22, 23, 24, 25, 26), - ), - }, - }, - { - name: "merge_interleaved_scopes_across_interleaved_resources", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(11, 101, 102, 103), - newScopeLogs(22, 201, 202, 203), - ), - newResourceLogs(2, - newScopeLogs(33, 301, 302, 303), - newScopeLogs(44, 401, 402, 403), - ), - newResourceLogs(1, - newScopeLogs(11, 104, 105, 106), - newScopeLogs(22, 204, 205, 206), - ), - newResourceLogs(2, - newScopeLogs(33, 304, 305, 306), - newScopeLogs(44, 404, 405, 406), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(11, 101, 102, 103, 104, 105, 106), - newScopeLogs(22, 201, 202, 203, 204, 205, 206), - ), - newResourceLogs(2, - newScopeLogs(33, 301, 302, 303, 304, 305, 306), - newScopeLogs(44, 401, 402, 403, 404, 405, 406), - ), - }, - }, - { - name: "merge_some_scopes_across_some_resources", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(11, 101, 102, 103), - newScopeLogs(22, 201, 202, 203), - ), - newResourceLogs(2, - newScopeLogs(33, 301, 302, 303), - newScopeLogs(11, 104, 105, 106), - ), - newResourceLogs(1, - newScopeLogs(33, 301, 302, 303), - newScopeLogs(11, 104, 105, 106), - ), - newResourceLogs(2, - newScopeLogs(33, 304, 305, 306), - newScopeLogs(44, 404, 405, 406), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(11, 101, 102, 103, 104, 105, 106), - newScopeLogs(22, 201, 202, 203), - newScopeLogs(33, 301, 302, 303), - ), - newResourceLogs(2, - newScopeLogs(33, 301, 302, 303, 304, 305, 306), - newScopeLogs(11, 104, 105, 106), - newScopeLogs(44, 404, 405, 406), - ), - }, - }, - { - name: "merge_all_resources_and_scopes", - input: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 101, 102), - newScopeLogs(1, 103, 104), - ), - newResourceLogs(1, - newScopeLogs(1, 105, 106), - newScopeLogs(1, 107, 108), - ), - newResourceLogs(1, - newScopeLogs(1, 109, 110), - newScopeLogs(1, 111, 112), - ), - }, - expected: []resourceLogs{ - newResourceLogs(1, - newScopeLogs(1, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112), - ), - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - actual := plog.NewResourceLogsSlice() - for _, r := range tc.input { - r.setup(actual.AppendEmpty()) - } - expected := plog.NewResourceLogsSlice() - for _, r := range tc.expected { - r.setup(expected.AppendEmpty()) - } - - GroupByResourceLogs(actual) - assert.Equal(t, expected.Len(), actual.Len()) - for i := 0; i < expected.Len(); i++ { - assert.NoError(t, plogtest.CompareResourceLogs(expected.At(i), actual.At(i))) - } - }) - } -} - -type resourceLogs struct { - num int - scopes []scopeLogs -} - -func newResourceLogs(num int, scopes ...scopeLogs) resourceLogs { - return resourceLogs{ - num: num, - scopes: scopes, - } -} - -func (r resourceLogs) setup(rl plog.ResourceLogs) { - rl.Resource().Attributes().PutStr("attr.name", fmt.Sprintf("attr_%d", r.num)) - for _, s := range r.scopes { - s.setup(rl.ScopeLogs().AppendEmpty()) - } -} diff --git a/internal/pdatautil/scope.go b/internal/pdatautil/scope.go deleted file mode 100644 index ec23f095d268..000000000000 --- a/internal/pdatautil/scope.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package pdatautil // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/pdatautil" - -import ( - "go.opentelemetry.io/collector/pdata/pcommon" - "go.opentelemetry.io/collector/pdata/plog" - - "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil" -) - -// GroupByScopeLogs groups LogRecords by scope. Modifications are made in place. -func GroupByScopeLogs(sls plog.ScopeLogsSlice) { - // Hash each ScopeLogs based on identifying information. - scopeHashes := make([][16]byte, sls.Len()) - for i := 0; i < sls.Len(); i++ { - scopeHashes[i] = HashScopeLogs(sls.At(i)) - } - - // Find the first occurrence of each hash and note the index. - firstScopeIndex := make([]int, sls.Len()) - for i := 0; i < sls.Len(); i++ { - firstScopeIndex[i] = i - for j := 0; j < i; j++ { - if scopeHashes[i] == scopeHashes[j] { - firstScopeIndex[i] = j - break - } - } - } - - // Merge ScopeLogs with the same hash. - for i := 0; i < sls.Len(); i++ { - if i == firstScopeIndex[i] { - // This is the first occurrence of this hash. - continue - } - sls.At(i).LogRecords().MoveAndAppendTo(sls.At(firstScopeIndex[i]).LogRecords()) - } - - // Remove the ScopeLogs which were merged onto others. - i := 0 - sls.RemoveIf(func(plog.ScopeLogs) bool { - remove := i != firstScopeIndex[i] - i++ - return remove - }) -} - -// Creates a hash based on the ScopeLogs attributes, name, and version -func HashScopeLogs(sl plog.ScopeLogs) [16]byte { - scopeHash := pcommon.NewMap() - scopeHash.PutStr("schema_url", sl.SchemaUrl()) - scopeHash.PutStr("name", sl.Scope().Name()) - scopeHash.PutStr("version", sl.Scope().Version()) - scopeHash.PutStr("attributes_hash", hashToString(pdatautil.MapHash(sl.Scope().Attributes()))) - return pdatautil.MapHash(scopeHash) -} - -func hashToString(hash [16]byte) string { - return string(hash[:]) -} diff --git a/internal/pdatautil/scope_test.go b/internal/pdatautil/scope_test.go deleted file mode 100644 index 05766e599d1a..000000000000 --- a/internal/pdatautil/scope_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package pdatautil - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/pdata/plog" - - "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/plogtest" -) - -func TestGroupByScopeLogs(t *testing.T) { - testCases := []struct { - name string - input []scopeLogs - expected []scopeLogs - }{ - { - name: "empty", - input: []scopeLogs{}, - expected: []scopeLogs{}, - }, - { - name: "single", - input: []scopeLogs{ - newScopeLogs(1, 11, 12, 13), - }, - expected: []scopeLogs{ - newScopeLogs(1, 11, 12, 13), - }, - }, - { - name: "distinct", - input: []scopeLogs{ - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - }, - expected: []scopeLogs{ - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - }, - }, - { - name: "simple_merge", - input: []scopeLogs{ - newScopeLogs(1, 11, 12, 13), - newScopeLogs(1, 14, 15, 16), - }, - expected: []scopeLogs{ - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - }, - }, - { - name: "interleaved", - input: []scopeLogs{ - newScopeLogs(1, 11, 12, 13), - newScopeLogs(2, 21, 22, 23), - newScopeLogs(1, 14, 15, 16), - newScopeLogs(2, 24, 25, 26), - }, - expected: []scopeLogs{ - newScopeLogs(1, 11, 12, 13, 14, 15, 16), - newScopeLogs(2, 21, 22, 23, 24, 25, 26), - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - actual := plog.NewScopeLogsSlice() - for _, s := range tc.input { - s.setup(actual.AppendEmpty()) - } - expected := plog.NewScopeLogsSlice() - for _, s := range tc.expected { - s.setup(expected.AppendEmpty()) - } - - GroupByScopeLogs(actual) - assert.Equal(t, expected.Len(), actual.Len()) - for i := 0; i < expected.Len(); i++ { - assert.NoError(t, plogtest.CompareScopeLogs(expected.At(i), actual.At(i))) - } - }) - } -} - -type scopeLogs struct { - num int - recordNums []int -} - -func newScopeLogs(num int, recordNums ...int) scopeLogs { - return scopeLogs{ - num: num, - recordNums: recordNums, - } -} - -func (s scopeLogs) setup(sl plog.ScopeLogs) { - sl.SetSchemaUrl(fmt.Sprintf("schema_%d", s.num)) - ss := sl.Scope() - ss.SetName(fmt.Sprintf("name_%d", s.num)) - ss.SetVersion(fmt.Sprintf("version_%d", s.num)) - ss.Attributes().PutStr("attr.name", fmt.Sprintf("attr_%d", s.num)) - for _, n := range s.recordNums { - lr := sl.LogRecords().AppendEmpty() - lr.Attributes().PutInt("num", int64(n)) - lr.Body().SetInt(int64(n)) - } -} - -func TestHashScopeLogs(t *testing.T) { - schemas := []string{"", "schema_1", "schema_2"} - names := []string{"", "name_1", "name_2"} - versions := []string{"", "version_1", "version_2"} - attributes := []map[string]any{ - {}, - {"attr.name": "attr_1"}, - {"attr.name": "attr_2"}, - {"attr.name": "attr_1", "other.name": "other"}, - } - - distinctScopeLogs := make([]plog.ScopeLogs, 0, len(schemas)*len(names)*len(versions)*len(attributes)) - - for _, schema := range schemas { - for _, name := range names { - for _, version := range versions { - for _, attr := range attributes { - sl := plog.NewScopeLogs() - sl.SetSchemaUrl(schema) - ss := sl.Scope() - ss.SetName(name) - ss.SetVersion(version) - require.NoError(t, ss.Attributes().FromRaw(attr)) - distinctScopeLogs = append(distinctScopeLogs, sl) - } - } - } - } - - for i, slOne := range distinctScopeLogs { - for j, slTwo := range distinctScopeLogs { - if i == j { - assert.Equal(t, HashScopeLogs(slOne), HashScopeLogs(slTwo)) - } else { - assert.NotEqual(t, HashScopeLogs(slOne), HashScopeLogs(slTwo)) - } - } - } -}