Skip to content

Commit 116c181

Browse files
authored
Introduce switchDictionary methods for profiles (#14075)
This is the next step towards #13106 It introduces private `switchDictionary` methods for all profile structs, so their base dictionary can be switched, which is a requirement (and maybe the biggest bit) of merging profiles. Right now, the private method isn't called yet, because this PR is already very big, and I believe introducing `MergeTo` should be in another PR. But the gist is that to merge profiles together, we need to change the base dictionary for the profiles that are being moved before we can merge the two slices of resource profiles into one.
1 parent f498a89 commit 116c181

24 files changed

+2179
-0
lines changed

pdata/pprofile/function.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,54 @@
33

44
package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"
55

6+
import "fmt"
7+
68
// Equal checks equality with another Function
79
func (fn Function) Equal(val Function) bool {
810
return fn.NameStrindex() == val.NameStrindex() &&
911
fn.SystemNameStrindex() == val.SystemNameStrindex() &&
1012
fn.FilenameStrindex() == val.FilenameStrindex() &&
1113
fn.StartLine() == val.StartLine()
1214
}
15+
16+
// switchDictionary updates the Function, switching its indices from one
17+
// dictionary to another.
18+
func (fn Function) switchDictionary(src, dst ProfilesDictionary) error {
19+
if fn.NameStrindex() > 0 {
20+
if src.StringTable().Len() < int(fn.NameStrindex()) {
21+
return fmt.Errorf("invalid name index %d", fn.NameStrindex())
22+
}
23+
24+
idx, err := SetString(dst.StringTable(), src.StringTable().At(int(fn.NameStrindex())))
25+
if err != nil {
26+
return fmt.Errorf("couldn't set name: %w", err)
27+
}
28+
fn.SetNameStrindex(idx)
29+
}
30+
31+
if fn.SystemNameStrindex() > 0 {
32+
if src.StringTable().Len() < int(fn.SystemNameStrindex()) {
33+
return fmt.Errorf("invalid system name index %d", fn.SystemNameStrindex())
34+
}
35+
36+
idx, err := SetString(dst.StringTable(), src.StringTable().At(int(fn.SystemNameStrindex())))
37+
if err != nil {
38+
return fmt.Errorf("couldn't set system name: %w", err)
39+
}
40+
fn.SetSystemNameStrindex(idx)
41+
}
42+
43+
if fn.FilenameStrindex() > 0 {
44+
if src.StringTable().Len() < int(fn.FilenameStrindex()) {
45+
return fmt.Errorf("invalid filename index %d", fn.FilenameStrindex())
46+
}
47+
48+
idx, err := SetString(dst.StringTable(), src.StringTable().At(int(fn.FilenameStrindex())))
49+
if err != nil {
50+
return fmt.Errorf("couldn't set filename: %w", err)
51+
}
52+
fn.SetFilenameStrindex(idx)
53+
}
54+
55+
return nil
56+
}

pdata/pprofile/function_test.go

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
package pprofile
55

66
import (
7+
"errors"
78
"testing"
89

910
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
1012
)
1113

1214
func TestFunctionEqual(t *testing.T) {
@@ -63,6 +65,193 @@ func TestFunctionEqual(t *testing.T) {
6365
}
6466
}
6567

68+
func TestFunctionSwitchDictionary(t *testing.T) {
69+
for _, tt := range []struct {
70+
name string
71+
function Function
72+
73+
src ProfilesDictionary
74+
dst ProfilesDictionary
75+
76+
wantFunction Function
77+
wantDictionary ProfilesDictionary
78+
wantErr error
79+
}{
80+
{
81+
name: "with an empty key value and unit",
82+
function: NewFunction(),
83+
84+
src: NewProfilesDictionary(),
85+
dst: NewProfilesDictionary(),
86+
87+
wantFunction: NewFunction(),
88+
wantDictionary: NewProfilesDictionary(),
89+
},
90+
{
91+
name: "with an existing name",
92+
function: func() Function {
93+
fn := NewFunction()
94+
fn.SetNameStrindex(1)
95+
return fn
96+
}(),
97+
98+
src: func() ProfilesDictionary {
99+
d := NewProfilesDictionary()
100+
d.StringTable().Append("", "test")
101+
return d
102+
}(),
103+
dst: func() ProfilesDictionary {
104+
d := NewProfilesDictionary()
105+
d.StringTable().Append("", "foo")
106+
return d
107+
}(),
108+
109+
wantFunction: func() Function {
110+
fn := NewFunction()
111+
fn.SetNameStrindex(2)
112+
return fn
113+
}(),
114+
wantDictionary: func() ProfilesDictionary {
115+
d := NewProfilesDictionary()
116+
d.StringTable().Append("", "foo", "test")
117+
return d
118+
}(),
119+
},
120+
{
121+
name: "with a name index that does not match anything",
122+
function: func() Function {
123+
fn := NewFunction()
124+
fn.SetNameStrindex(1)
125+
return fn
126+
}(),
127+
128+
src: NewProfilesDictionary(),
129+
dst: NewProfilesDictionary(),
130+
131+
wantFunction: func() Function {
132+
fn := NewFunction()
133+
fn.SetNameStrindex(1)
134+
return fn
135+
}(),
136+
wantDictionary: NewProfilesDictionary(),
137+
wantErr: errors.New("invalid name index 1"),
138+
},
139+
{
140+
name: "with an existing system name",
141+
function: func() Function {
142+
fn := NewFunction()
143+
fn.SetSystemNameStrindex(1)
144+
return fn
145+
}(),
146+
147+
src: func() ProfilesDictionary {
148+
d := NewProfilesDictionary()
149+
d.StringTable().Append("", "test")
150+
return d
151+
}(),
152+
dst: func() ProfilesDictionary {
153+
d := NewProfilesDictionary()
154+
d.StringTable().Append("", "foo")
155+
return d
156+
}(),
157+
158+
wantFunction: func() Function {
159+
fn := NewFunction()
160+
fn.SetSystemNameStrindex(2)
161+
return fn
162+
}(),
163+
wantDictionary: func() ProfilesDictionary {
164+
d := NewProfilesDictionary()
165+
d.StringTable().Append("", "foo", "test")
166+
return d
167+
}(),
168+
},
169+
{
170+
name: "with a system name index that does not match anything",
171+
function: func() Function {
172+
fn := NewFunction()
173+
fn.SetSystemNameStrindex(1)
174+
return fn
175+
}(),
176+
177+
src: NewProfilesDictionary(),
178+
dst: NewProfilesDictionary(),
179+
180+
wantFunction: func() Function {
181+
fn := NewFunction()
182+
fn.SetSystemNameStrindex(1)
183+
return fn
184+
}(),
185+
wantDictionary: NewProfilesDictionary(),
186+
wantErr: errors.New("invalid system name index 1"),
187+
},
188+
{
189+
name: "with an existing filename",
190+
function: func() Function {
191+
fn := NewFunction()
192+
fn.SetFilenameStrindex(1)
193+
return fn
194+
}(),
195+
196+
src: func() ProfilesDictionary {
197+
d := NewProfilesDictionary()
198+
d.StringTable().Append("", "test")
199+
return d
200+
}(),
201+
dst: func() ProfilesDictionary {
202+
d := NewProfilesDictionary()
203+
d.StringTable().Append("", "foo")
204+
return d
205+
}(),
206+
207+
wantFunction: func() Function {
208+
fn := NewFunction()
209+
fn.SetFilenameStrindex(2)
210+
return fn
211+
}(),
212+
wantDictionary: func() ProfilesDictionary {
213+
d := NewProfilesDictionary()
214+
d.StringTable().Append("", "foo", "test")
215+
return d
216+
}(),
217+
},
218+
{
219+
name: "with a filename index that does not match anything",
220+
function: func() Function {
221+
fn := NewFunction()
222+
fn.SetFilenameStrindex(1)
223+
return fn
224+
}(),
225+
226+
src: NewProfilesDictionary(),
227+
dst: NewProfilesDictionary(),
228+
229+
wantFunction: func() Function {
230+
fn := NewFunction()
231+
fn.SetFilenameStrindex(1)
232+
return fn
233+
}(),
234+
wantDictionary: NewProfilesDictionary(),
235+
wantErr: errors.New("invalid filename index 1"),
236+
},
237+
} {
238+
t.Run(tt.name, func(t *testing.T) {
239+
fn := tt.function
240+
dst := tt.dst
241+
err := fn.switchDictionary(tt.src, dst)
242+
243+
if tt.wantErr == nil {
244+
require.NoError(t, err)
245+
} else {
246+
require.Equal(t, tt.wantErr, err)
247+
}
248+
249+
assert.Equal(t, tt.wantFunction, fn)
250+
assert.Equal(t, tt.wantDictionary, dst)
251+
})
252+
}
253+
}
254+
66255
func buildFunction(name, sName, fileName int32, startLine int64) Function {
67256
f := NewFunction()
68257
f.SetNameStrindex(name)

pdata/pprofile/keyvalueandunit.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,42 @@
33

44
package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"
55

6+
import "fmt"
7+
68
// Equal checks equality with another KeyValueAndUnit
79
// It assumes both structs refer to the same dictionary.
810
func (ms KeyValueAndUnit) Equal(val KeyValueAndUnit) bool {
911
return ms.KeyStrindex() == val.KeyStrindex() &&
1012
ms.UnitStrindex() == val.UnitStrindex() &&
1113
ms.Value().Equal(val.Value())
1214
}
15+
16+
// switchDictionary updates the KeyValueAndUnit, switching its indices from one
17+
// dictionary to another.
18+
func (ms KeyValueAndUnit) switchDictionary(src, dst ProfilesDictionary) error {
19+
if ms.KeyStrindex() > 0 {
20+
if src.StringTable().Len() < int(ms.KeyStrindex()) {
21+
return fmt.Errorf("invalid key index %d", ms.KeyStrindex())
22+
}
23+
24+
idx, err := SetString(dst.StringTable(), src.StringTable().At(int(ms.KeyStrindex())))
25+
if err != nil {
26+
return fmt.Errorf("couldn't set key: %w", err)
27+
}
28+
ms.SetKeyStrindex(idx)
29+
}
30+
31+
if ms.UnitStrindex() > 0 {
32+
if src.StringTable().Len() < int(ms.UnitStrindex()) {
33+
return fmt.Errorf("invalid unit index %d", ms.UnitStrindex())
34+
}
35+
36+
idx, err := SetString(dst.StringTable(), src.StringTable().At(int(ms.UnitStrindex())))
37+
if err != nil {
38+
return fmt.Errorf("couldn't set unit: %w", err)
39+
}
40+
ms.SetUnitStrindex(idx)
41+
}
42+
43+
return nil
44+
}

0 commit comments

Comments
 (0)