Skip to content

Commit ab5e07a

Browse files
Store AST directly in provider mappings (#6114) (#6158)
* Store AST directly in dynamic provider mappings * Store AST directly in context provider mappings (cherry picked from commit fe0f6b0) Co-authored-by: Mikołaj Świątek <mail@mikolajswiatek.com>
1 parent 19f8412 commit ab5e07a

File tree

3 files changed

+26
-47
lines changed

3 files changed

+26
-47
lines changed

internal/pkg/agent/transpiler/ast.go

+3
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,9 @@ func (a *AST) HashStr() string {
825825

826826
// Equal check if two AST are equals by using the computed hash.
827827
func (a *AST) Equal(other *AST) bool {
828+
if a.root == nil || other.root == nil {
829+
return a.root == other.root
830+
}
828831
return bytes.Equal(a.Hash(), other.Hash())
829832
}
830833

internal/pkg/composable/benchmark_test.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
package composable
66

77
import (
8-
"maps"
98
"os"
109
"path/filepath"
1110
"strings"
1211
"testing"
1312

13+
"github.com/elastic/elastic-agent/internal/pkg/agent/transpiler"
14+
1415
"gopkg.in/yaml.v3"
1516
"k8s.io/apimachinery/pkg/util/uuid"
1617

@@ -54,7 +55,8 @@ func BenchmarkGenerateVars100Pods(b *testing.B) {
5455
mappings: make(map[string]dynamicProviderMapping),
5556
}
5657
for i := 0; i < podCount; i++ {
57-
podData := maps.Clone(providerMapping)
58+
podData, err := transpiler.NewAST(providerMapping)
59+
require.NoError(b, err)
5860
podUID := uuid.NewUUID()
5961
podMapping := dynamicProviderMapping{
6062
mapping: podData,
@@ -63,8 +65,10 @@ func BenchmarkGenerateVars100Pods(b *testing.B) {
6365
}
6466
c.dynamicProviders[providerName] = providerState
6567
} else {
68+
providerAst, err := transpiler.NewAST(providerData[providerName])
69+
require.NoError(b, err)
6670
providerState := &contextProviderState{
67-
mapping: providerData[providerName],
71+
mapping: providerAst,
6872
}
6973
c.contextProviders[providerName] = providerState
7074
}

internal/pkg/composable/controller.go

+16-44
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,12 @@ func New(log *logger.Logger, c *config.Config, managed bool) (Controller, error)
7979
if err != nil {
8080
return nil, errors.New(err, fmt.Sprintf("failed to build provider '%s'", name), errors.TypeConfig, errors.M("provider", name))
8181
}
82+
emptyMapping, _ := transpiler.NewAST(nil)
8283
contextProviders[name] = &contextProviderState{
8384
// Safe for Context to be nil here because it will be filled in
8485
// by (*controller).Run before the provider is started.
8586
provider: provider,
87+
mapping: emptyMapping,
8688
}
8789
}
8890

@@ -275,20 +277,17 @@ func (c *controller) Close() {
275277
func (c *controller) generateVars(fetchContextProviders mapstr.M) []*transpiler.Vars {
276278
// build the vars list of mappings
277279
vars := make([]*transpiler.Vars, 1)
278-
mapping := map[string]interface{}{}
280+
mapping, _ := transpiler.NewAST(map[string]any{})
279281
for name, state := range c.contextProviders {
280-
mapping[name] = state.Current()
282+
_ = mapping.Insert(state.Current(), name)
281283
}
282-
// this is ensured not to error, by how the mappings states are verified
283-
mappingAst, _ := transpiler.NewAST(mapping)
284-
vars[0] = transpiler.NewVarsFromAst("", mappingAst, fetchContextProviders)
284+
vars[0] = transpiler.NewVarsFromAst("", mapping, fetchContextProviders)
285285

286286
// add to the vars list for each dynamic providers mappings
287287
for name, state := range c.dynamicProviders {
288288
for _, mappings := range state.Mappings() {
289-
local := mappingAst.ShallowClone()
290-
dynamicAst, _ := transpiler.NewAST(mappings.mapping)
291-
_ = local.Insert(dynamicAst, name)
289+
local := mapping.ShallowClone()
290+
_ = local.Insert(mappings.mapping, name)
292291
id := fmt.Sprintf("%s-%s", name, mappings.id)
293292
v := transpiler.NewVarsWithProcessorsFromAst(id, local, name, mappings.processors, fetchContextProviders)
294293
vars = append(vars, v)
@@ -302,7 +301,7 @@ type contextProviderState struct {
302301

303302
provider corecomp.ContextProvider
304303
lock sync.RWMutex
305-
mapping map[string]interface{}
304+
mapping *transpiler.AST
306305
signal chan bool
307306
}
308307

@@ -324,30 +323,25 @@ func (c *contextProviderState) Signal() {
324323
// Set sets the current mapping.
325324
func (c *contextProviderState) Set(mapping map[string]interface{}) error {
326325
var err error
327-
mapping, err = cloneMap(mapping)
328-
if err != nil {
329-
return err
330-
}
331-
// ensure creating vars will not error
332-
_, err = transpiler.NewVars("", mapping, nil)
326+
ast, err := transpiler.NewAST(mapping)
333327
if err != nil {
334328
return err
335329
}
336330

337331
c.lock.Lock()
338332
defer c.lock.Unlock()
339333

340-
if reflect.DeepEqual(c.mapping, mapping) {
334+
if c.mapping != nil && c.mapping.Equal(ast) {
341335
// same mapping; no need to update and signal
342336
return nil
343337
}
344-
c.mapping = mapping
338+
c.mapping = ast
345339
c.Signal()
346340
return nil
347341
}
348342

349343
// Current returns the current mapping.
350-
func (c *contextProviderState) Current() map[string]interface{} {
344+
func (c *contextProviderState) Current() *transpiler.AST {
351345
c.lock.RLock()
352346
defer c.lock.RUnlock()
353347
return c.mapping
@@ -356,7 +350,7 @@ func (c *contextProviderState) Current() map[string]interface{} {
356350
type dynamicProviderMapping struct {
357351
id string
358352
priority int
359-
mapping map[string]interface{}
353+
mapping *transpiler.AST
360354
processors transpiler.Processors
361355
}
362356

@@ -376,31 +370,25 @@ type dynamicProviderState struct {
376370
// to ensure that matching of variables occurs on the lower priority mappings first.
377371
func (c *dynamicProviderState) AddOrUpdate(id string, priority int, mapping map[string]interface{}, processors []map[string]interface{}) error {
378372
var err error
379-
mapping, err = cloneMap(mapping)
380-
if err != nil {
381-
return err
382-
}
383373
processors, err = cloneMapArray(processors)
384374
if err != nil {
385375
return err
386376
}
387-
// ensure creating vars will not error
388-
_, err = transpiler.NewVars("", mapping, nil)
377+
ast, err := transpiler.NewAST(mapping)
389378
if err != nil {
390379
return err
391380
}
392-
393381
c.lock.Lock()
394382
defer c.lock.Unlock()
395383
curr, ok := c.mappings[id]
396-
if ok && reflect.DeepEqual(curr.mapping, mapping) && reflect.DeepEqual(curr.processors, processors) {
384+
if ok && curr.mapping.Equal(ast) && reflect.DeepEqual(curr.processors, processors) {
397385
// same mapping; no need to update and signal
398386
return nil
399387
}
400388
c.mappings[id] = dynamicProviderMapping{
401389
id: id,
402390
priority: priority,
403-
mapping: mapping,
391+
mapping: ast,
404392
processors: processors,
405393
}
406394

@@ -458,22 +446,6 @@ func (c *dynamicProviderState) Mappings() []dynamicProviderMapping {
458446
return mappings
459447
}
460448

461-
func cloneMap(source map[string]interface{}) (map[string]interface{}, error) {
462-
if source == nil {
463-
return nil, nil
464-
}
465-
bytes, err := json.Marshal(source)
466-
if err != nil {
467-
return nil, fmt.Errorf("failed to clone: %w", err)
468-
}
469-
var dest map[string]interface{}
470-
err = json.Unmarshal(bytes, &dest)
471-
if err != nil {
472-
return nil, fmt.Errorf("failed to clone: %w", err)
473-
}
474-
return dest, nil
475-
}
476-
477449
func cloneMapArray(source []map[string]interface{}) ([]map[string]interface{}, error) {
478450
if source == nil {
479451
return nil, nil

0 commit comments

Comments
 (0)