Skip to content

Commit 2aa83f6

Browse files
committed
chore: add a more targeted version
1 parent 4610126 commit 2aa83f6

File tree

2 files changed

+93
-115
lines changed

2 files changed

+93
-115
lines changed

confmap/merge.go

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,65 @@ package confmap // import "go.opentelemetry.io/collector/confmap"
55

66
import (
77
"reflect"
8+
9+
"github.com/gobwas/glob"
10+
"github.com/knadh/koanf/maps"
811
)
912

1013
func mergeAppend(src, dest map[string]any) error {
11-
// mergeAppend recursively merges the src map into the dest map (left to right),
12-
// modifying and expanding the dest map in the process.
13-
// This function does not overwrite lists, and ensures that the final value is a name-aware
14-
// copy of lists from src and dest.
14+
// Compile the globs once
15+
patterns := []string{
16+
"service::extensions",
17+
"service::**::receivers",
18+
"service::**::exporters",
19+
}
20+
var globs []glob.Glob
21+
for _, p := range patterns {
22+
if g, err := glob.Compile(p); err == nil {
23+
globs = append(globs, g)
24+
}
25+
}
26+
27+
// Flatten both source and destination maps
28+
srcFlat, _ := maps.Flatten(src, []string{}, KeyDelimiter)
29+
destFlat, _ := maps.Flatten(dest, []string{}, KeyDelimiter)
1530

16-
for sKey, sVal := range src {
17-
dVal, dOk := dest[sKey]
18-
if !dOk {
19-
// key is not present in destination config. Hence, add it to destination map
20-
dest[sKey] = sVal
31+
for key, sVal := range srcFlat {
32+
if !isMatch(key, globs) {
2133
continue
2234
}
2335

36+
dVal, exists := destFlat[key]
37+
if !exists {
38+
continue // Let maps.Merge handle missing keys
39+
}
40+
2441
srcVal := reflect.ValueOf(sVal)
2542
destVal := reflect.ValueOf(dVal)
2643

27-
if destVal.Kind() != srcVal.Kind() {
28-
// different kinds. Override the destination map
29-
dest[sKey] = sVal
30-
continue
31-
}
32-
33-
switch srcVal.Kind() {
34-
case reflect.Array, reflect.Slice:
35-
// both of them are array. Merge them
36-
dest[sKey] = mergeSlice(srcVal, destVal)
37-
case reflect.Map:
38-
// both of them are maps. Recursively call the mergeAppend
39-
_ = mergeAppend(sVal.(map[string]any), dVal.(map[string]any))
40-
default:
41-
// any other datatype. Override the destination map
42-
dest[sKey] = sVal
44+
// Only merge if the value is a slice or array; let maps.Merge handle other types
45+
if srcVal.Kind() == reflect.Slice || srcVal.Kind() == reflect.Array {
46+
srcFlat[key] = mergeSlice(srcVal, destVal)
4347
}
4448
}
4549

50+
// Unflatten and merge
51+
mergedSrc := maps.Unflatten(srcFlat, KeyDelimiter)
52+
maps.Merge(mergedSrc, dest)
53+
4654
return nil
4755
}
4856

57+
// isMatch checks if a key matches any glob in the list
58+
func isMatch(key string, globs []glob.Glob) bool {
59+
for _, g := range globs {
60+
if g.Match(key) {
61+
return true
62+
}
63+
}
64+
return false
65+
}
66+
4967
func mergeSlice(src, dest reflect.Value) any {
5068
slice := reflect.MakeSlice(src.Type(), 0, src.Cap()+dest.Cap())
5169
for i := 0; i < dest.Len(); i++ {

confmap/testdata/merge-append-scenarios.yaml

Lines changed: 50 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
pipelines:
6767
traces:
6868
receivers: [nop, nop2]
69-
processors: [nop, nop2]
69+
processors: [nop2]
7070
exporters: [nop, nop2]
7171
- name: merge-mode-append
7272
configs:
@@ -134,7 +134,7 @@
134134
pipelines:
135135
traces:
136136
receivers: [nop, nop2]
137-
processors: [nop, nop2]
137+
processors: [nop2]
138138
exporters: [nop, nop2]
139139
- name: merge-mode-append-override-old-values
140140
configs:
@@ -335,70 +335,6 @@
335335
traces:
336336
receivers: [nop, nop2, nop3]
337337
exporters: [nop, nop2, nop3]
338-
- name: merge-mode-append-processor
339-
configs:
340-
-
341-
receivers:
342-
nop:
343-
344-
exporters:
345-
nop:
346-
347-
extensions:
348-
nop:
349-
processors:
350-
processor:
351-
path: [path]
352-
service:
353-
extensions: [nop]
354-
pipelines:
355-
traces:
356-
receivers: [nop]
357-
processors: [processor]
358-
exporters: [nop]
359-
-
360-
receivers:
361-
nop2:
362-
363-
exporters:
364-
nop2:
365-
366-
extensions:
367-
nop2:
368-
processors:
369-
processor:
370-
path: [path2]
371-
372-
service:
373-
extensions: [nop2]
374-
pipelines:
375-
traces:
376-
receivers: [nop2]
377-
processors: [processor]
378-
exporters: [nop2]
379-
expected:
380-
receivers:
381-
nop:
382-
nop2:
383-
384-
exporters:
385-
nop:
386-
nop2:
387-
388-
extensions:
389-
nop:
390-
nop2:
391-
processors:
392-
processor:
393-
path: [path, path2]
394-
395-
service:
396-
extensions: [nop, nop2]
397-
pipelines:
398-
traces:
399-
receivers: [nop, nop2]
400-
processors: [processor]
401-
exporters: [nop, nop2]
402338
- name: merge-mode-append-processor-service
403339
configs:
404340
-
@@ -454,7 +390,7 @@
454390
nop2:
455391
processors:
456392
processor:
457-
path: [path, path2]
393+
path: [path2]
458394

459395
service:
460396
extensions: [nop, nop2]
@@ -543,7 +479,7 @@
543479

544480
processors:
545481
processor:
546-
path: [path, path2, path3]
482+
path: [path3]
547483
processor2:
548484

549485
service:
@@ -603,19 +539,16 @@
603539
receivers: [nop]
604540
processors: [nop]
605541
exporters: [nop]
606-
- name: merge-mode-extra-processor
542+
- name: merge-mode-multiple-pipelines
607543
configs:
608544
-
609545
receivers:
610546
nop:
611547
key: val
612548

613549
processors:
614-
attributes/example:
615-
actions:
616-
- key: key
617-
value: "value"
618-
action: upsert
550+
nop:
551+
key: val
619552

620553
exporters:
621554
nop:
@@ -631,41 +564,68 @@
631564
receivers: [nop]
632565
processors: [attributes/example]
633566
exporters: [nop]
567+
logs:
568+
receivers: [nop]
569+
processors: [attributes/example]
570+
exporters: [nop]
634571
-
635-
extensions:
636-
nop2:
572+
receivers:
573+
nop1:
574+
key: val
575+
637576
processors:
638-
nop2:
577+
nop1:
578+
key: val
579+
580+
exporters:
581+
nop1:
582+
key: 2
583+
584+
extensions:
585+
nop1:
586+
639587
service:
640-
extensions: [nop2]
588+
extensions: [nop1]
641589
pipelines:
642590
traces:
643-
processors: [nop2]
591+
receivers: [nop1]
592+
processors: [nop1]
593+
exporters: [nop1]
594+
logs:
595+
receivers: [nop1]
596+
processors: [nop1]
597+
exporters: [nop1]
644598
expected:
645599
receivers:
646600
nop:
647601
key: val
602+
nop1:
603+
key: val
648604

649605
processors:
650-
nop2:
651-
attributes/example:
652-
actions:
653-
- key: key
654-
value: "value"
655-
action: upsert
606+
nop:
607+
key: val
608+
nop1:
609+
key: val
656610

657611
exporters:
658612
nop:
659613
key: 2
614+
nop1:
615+
key: 2
660616

661617
extensions:
662618
nop:
663-
nop2:
619+
nop1:
664620

665621
service:
666-
extensions: [nop, nop2]
622+
extensions: [nop, nop1]
667623
pipelines:
668624
traces:
669-
receivers: [nop]
670-
processors: [attributes/example, nop2]
671-
exporters: [nop]
625+
receivers: [nop, nop1]
626+
processors: [nop1]
627+
exporters: [nop, nop1]
628+
logs:
629+
receivers: [nop, nop1]
630+
processors: [nop1]
631+
exporters: [nop, nop1]

0 commit comments

Comments
 (0)