Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[confmap] - new feature flag for append merging strategy #12097

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
e42eb1e
chore: new ffeature flag for mergiing configs
VihasMakwana Jan 15, 2025
bd97e5f
remove fatureflag, add command flag
VihasMakwana Jan 27, 2025
096f3d6
gotidy
VihasMakwana Jan 27, 2025
a3e2367
lint
VihasMakwana Jan 27, 2025
45d5c56
Merge branch 'main' into new-merge-strategy
VihasMakwana Jan 27, 2025
d3fe610
rename flag
VihasMakwana Jan 27, 2025
9059b29
bug
VihasMakwana Jan 27, 2025
3df306a
increase test coverage
VihasMakwana Jan 27, 2025
2ec9b7d
simplify
VihasMakwana Jan 28, 2025
77be9b9
increase test coverage
VihasMakwana Jan 28, 2025
5685baa
lint
VihasMakwana Jan 28, 2025
58906f0
update changelog
VihasMakwana Feb 3, 2025
24be7ff
chore: minimal changes to confmap
VihasMakwana Feb 4, 2025
a8983da
remove blank line
VihasMakwana Feb 4, 2025
f845cc9
fix testcase
VihasMakwana Feb 4, 2025
3a11a04
add feature flag
VihasMakwana Feb 10, 2025
4d7bdb8
comments
VihasMakwana Feb 10, 2025
5378693
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 10, 2025
8eb287b
make gotidy
VihasMakwana Feb 10, 2025
a220efc
lint
VihasMakwana Feb 10, 2025
3b40166
revert fine-grained control
VihasMakwana Feb 12, 2025
662b9e4
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 12, 2025
ec3f65d
update documentation
VihasMakwana Feb 13, 2025
e7d637e
readme
VihasMakwana Feb 13, 2025
8f8e62e
review comments
VihasMakwana Feb 13, 2025
fda5468
go tidy
VihasMakwana Feb 13, 2025
895a376
lint
VihasMakwana Feb 13, 2025
2d4cda7
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 13, 2025
b5ce338
lint and crosslink
VihasMakwana Feb 13, 2025
c170536
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 13, 2025
d553f4e
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 18, 2025
391ab98
go tidy
VihasMakwana Feb 18, 2025
eb254e7
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 19, 2025
22fa0a2
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 19, 2025
b3ebced
review comments
VihasMakwana Feb 24, 2025
8cc3fe4
lint and ci
VihasMakwana Feb 24, 2025
bd450b3
test
VihasMakwana Feb 24, 2025
161526a
revert to feature flag
VihasMakwana Feb 26, 2025
a6c03ad
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 26, 2025
5412333
chore: nit. drop MergeMaps
VihasMakwana Feb 26, 2025
1e69470
chore: lint
VihasMakwana Feb 26, 2025
876e4d3
lint
VihasMakwana Feb 28, 2025
088fa2b
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 28, 2025
3aaf23a
remove //nolint
VihasMakwana Feb 28, 2025
86c64d3
Merge branch 'main' into new-merge-strategy
VihasMakwana Feb 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .chloggen/new-merge-strategy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: confmap

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Introduce a new feature flag to allow for merging lists instead of discarding the existing ones.

# One or more tracking issues or pull requests related to the change
issues: [8394, 8754, 10370]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: |
You can enable this option via the command line by running following command:
otelcol --config=main.yaml --config=extra_config.yaml --feature-gates=-confmap.enableMergeAppendOption

# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
4 changes: 4 additions & 0 deletions cmd/mdatagen/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ require (
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
Expand All @@ -51,6 +52,7 @@ require (
go.opentelemetry.io/collector/component/componentstatus v0.120.0 // indirect
go.opentelemetry.io/collector/consumer/consumererror v0.120.0 // indirect
go.opentelemetry.io/collector/consumer/xconsumer v0.120.0 // indirect
go.opentelemetry.io/collector/featuregate v1.25.0 // indirect
go.opentelemetry.io/collector/pdata/pprofile v0.120.0 // indirect
go.opentelemetry.io/collector/pdata/testdata v0.120.0 // indirect
go.opentelemetry.io/collector/pipeline v0.120.0 // indirect
Expand Down Expand Up @@ -118,3 +120,5 @@ replace go.opentelemetry.io/collector/consumer/consumererror => ../../consumer/c
replace go.opentelemetry.io/collector/scraper => ../../scraper

replace go.opentelemetry.io/collector/scraper/scrapertest => ../../scraper/scrapertest

replace go.opentelemetry.io/collector/featuregate => ../../featuregate
2 changes: 2 additions & 0 deletions cmd/mdatagen/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 85 additions & 0 deletions confmap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,91 @@ The `Resolve` method proceeds in the following steps:
4. For each "Converter", call "Convert" for the "result".
5. Return the "result", aka effective, configuration.

#### (Experimental) Append merging strategy for lists

You can opt-in to experimentally combine slices instead of discarding the existing ones by enabling the `confmap.enableMergeAppendOption` feature flag. Lists are appended in the order in which they appear in their configuration sources.
This will **not** become the default in the future, we are still deciding how this should be configured and want your feedback on [this issue](https://github.com/open-telemetry/opentelemetry-collector/issues/8754).

##### Example
Consider the following configs,

```yaml
# main.yaml
receivers:
otlp/in:
processors:
attributes/example:
actions:
- key: key
value: "value"
action: upsert

exporters:
otlp/out:
extensions:
file_storage:

service:
pipelines:
traces:
receivers: [ otlp/in ]
processors: [ attributes/example ]
exporters: [ otlp/out ]
extensions: [ file_storage ]
```


```yaml
# extra_extension.yaml
processors:
batch:
extensions:
healthcheckv2:

service:
extensions: [ healthcheckv2 ]
pipelines:
traces:
processors: [ batch ]
```

If you run the Collector with following command,
```
otelcol --config=main.yaml --config=extra_extension.yaml --feature-gates=confmap.enableMergeAppendOption
```
then the final configuration after config resolution will look like following:

```yaml
# main.yaml
receivers:
otlp/in:
processors:
attributes/example:
actions:
- key: key
value: "value"
action: upsert
batch:
exporters:
otlp/out:
extensions:
file_storage:
healthcheckv2:

service:
pipelines:
traces:
receivers: [ otlp/in ]
processors: [ attributes/example, batch ]
exporters: [ otlp/out ]
extensions: [ file_storage, healthcheckv2 ]
```

Notice that the `service::extensions` list is a combination of both configurations. By default, the value of the last configuration source passed, `extra_extension`, would be used, so the extensions list would be: `service::extensions: [healthcheckv2]`.

> [!NOTE]
> By enabling this feature gate, all the lists in the given configuration will be merged.

### Watching for Updates
After the configuration was processed, the `Resolver` can be used as a single point to watch for updates in the
configuration retrieved via the `Provider` used to retrieve the “initial” configuration and to generate the “effective” one.
Expand Down
9 changes: 9 additions & 0 deletions confmap/confmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,15 @@ func (l *Conf) Merge(in *Conf) error {
return l.k.Merge(in.k)
}

// mergeAppend merges the input given configuration into the existing config.
// Note that the given map may be modified.
// Additionally, mergeAppend performs deduplication when merging lists.
// For example, if listA = [extension1, extension2] and listB = [extension1, extension3],
// the resulting list will be [extension1, extension2, extension3].
func (l *Conf) mergeAppend(in *Conf) error {
return l.k.Load(confmap.Provider(in.ToStringMap(), ""), nil, koanf.WithMergeFunc(mergeAppend))
}

// Sub returns new Conf instance representing a sub-config of this instance.
// It returns an error is the sub-config is not a map[string]any (use Get()), and an empty Map if none exists.
func (l *Conf) Sub(key string) (*Conf, error) {
Expand Down
7 changes: 4 additions & 3 deletions confmap/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/knadh/koanf/providers/confmap v0.1.0
github.com/knadh/koanf/v2 v2.1.2
github.com/stretchr/testify v1.10.0
go.opentelemetry.io/collector/featuregate v1.25.0
go.uber.org/goleak v1.3.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
Expand All @@ -16,15 +17,15 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)

retract (
v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module, use v0.76.1
v0.69.0 // Release failed, use v0.69.1
)

replace go.opentelemetry.io/collector/featuregate => ../featuregate
8 changes: 2 additions & 6 deletions confmap/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions confmap/internal/e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/collector/featuregate v1.25.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand All @@ -31,3 +33,5 @@ replace go.opentelemetry.io/collector/confmap/provider/fileprovider => ../../pro
replace go.opentelemetry.io/collector/confmap/provider/envprovider => ../../provider/envprovider

replace go.opentelemetry.io/collector/config/configopaque => ../../../config/configopaque

replace go.opentelemetry.io/collector/featuregate => ../../../featuregate
2 changes: 2 additions & 0 deletions confmap/internal/e2e/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 79 additions & 0 deletions confmap/merge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package confmap // import "go.opentelemetry.io/collector/confmap"

import (
"reflect"

"github.com/knadh/koanf/maps"
)

func mergeAppend(src, dest map[string]any) error {
// mergeAppend recursively merges the src map into the dest map (left to right),
// modifying and expanding the dest map in the process.
// This function does not overwrite lists, and ensures that the final value is a name-aware
// copy of lists from src and dest.

// First, merge the src and dest config maps
mergeMaps(src, dest)

// Second, unflatten the new config
src = maps.Unflatten(src, KeyDelimiter)

// merge rest of the config.
maps.Merge(src, dest)
return nil
}

func mergeMaps(src, dest map[string]any) {
for dKey, dVal := range dest {
sVal, sOk := src[dKey]
if !sOk {
// old key is not present in new config. Hence, add it to src
src[dKey] = dVal
continue
}

srcVal := reflect.ValueOf(sVal)
destVal := reflect.ValueOf(dVal)

if destVal.Kind() != srcVal.Kind() {
// different kinds, maps.Merge will override the old config
continue
}

switch srcVal.Kind() {
case reflect.Array, reflect.Slice:
// both of them are array. Merge them
src[dKey] = mergeSlice(srcVal, destVal)
case reflect.Map:
// both of them are maps. Recursively call the mergeMaps
mergeMaps(sVal.(map[string]any), dVal.(map[string]any))
}
}
}

func mergeSlice(src, dest reflect.Value) any {
slice := reflect.MakeSlice(src.Type(), 0, src.Cap()+dest.Cap())
for i := 0; i < dest.Len(); i++ {
slice = reflect.Append(slice, dest.Index(i))
}

for i := 0; i < src.Len(); i++ {
if isPresent(slice, src.Index(i)) {
continue
}
slice = reflect.Append(slice, src.Index(i))
}
return slice.Interface()
}

func isPresent(slice reflect.Value, val reflect.Value) bool {
for i := 0; i < slice.Len(); i++ {
if slice.Index(i).Equal(val) {
return true
}
}
return false
}
4 changes: 4 additions & 0 deletions confmap/provider/envprovider/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/collector/featuregate v1.25.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace go.opentelemetry.io/collector/confmap => ../../

replace go.opentelemetry.io/collector/featuregate => ../../../featuregate
2 changes: 2 additions & 0 deletions confmap/provider/envprovider/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions confmap/provider/fileprovider/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/collector/featuregate v1.25.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace go.opentelemetry.io/collector/confmap => ../../

replace go.opentelemetry.io/collector/featuregate => ../../../featuregate
2 changes: 2 additions & 0 deletions confmap/provider/fileprovider/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading