Skip to content

Commit 2240e92

Browse files
logger
1 parent 2dca2b0 commit 2240e92

File tree

4 files changed

+98
-59
lines changed

4 files changed

+98
-59
lines changed

engine/cld/mcms/proposalanalysis/engine.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalanalysis/formatter"
1919
"github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalanalysis/internal"
2020
"github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalanalysis/types"
21+
"github.com/smartcontractkit/chainlink-deployments-framework/pkg/logger"
2122
experimentalanalyzer "github.com/smartcontractkit/chainlink-deployments-framework/experimental/analyzer"
2223
)
2324

@@ -32,12 +33,13 @@ type analyzerEngine struct {
3233
evmRegistry experimentalanalyzer.EVMABIRegistry
3334
solanaRegistry experimentalanalyzer.SolanaDecoderRegistry
3435
executionContext types.ExecutionContext // Store for formatters
36+
logger logger.Logger
3537
}
3638

3739
var _ types.AnalyzerEngine = &analyzerEngine{}
3840

3941
// NewAnalyzerEngine creates a new analyzer engine
40-
// Options can be provided to customize the engine behavior, such as injecting registries
42+
// Options can be provided to customize the engine behavior, such as injecting registries and logger
4143
func NewAnalyzerEngine(opts ...EngineOption) types.AnalyzerEngine {
4244
// Apply options to get configuration
4345
cfg := ApplyEngineOptions(opts...)
@@ -47,6 +49,7 @@ func NewAnalyzerEngine(opts ...EngineOption) types.AnalyzerEngine {
4749
formatterRegistry: formatter.NewFormatterRegistry(),
4850
evmRegistry: cfg.GetEVMRegistry(),
4951
solanaRegistry: cfg.GetSolanaRegistry(),
52+
logger: cfg.GetLogger(),
5053
}
5154
return engine
5255
}
@@ -220,7 +223,7 @@ func (ae *analyzerEngine) analyzeProposal(
220223
for _, batchOp := range decodedProposal.BatchOperations() {
221224
analyzedBatchOp, err := ae.analyzeBatchOperation(ctx, actx, ectx, batchOp)
222225
if err != nil {
223-
// log error but continue
226+
ae.logger.Errorw("Failed to analyze batch operation", "chainSelector", batchOp.ChainSelector(), "error", err)
224227
continue
225228
}
226229
batchOps = append(batchOps, analyzedBatchOp)
@@ -261,7 +264,7 @@ func (ae *analyzerEngine) analyzeProposal(
261264

262265
annotations, err := proposalAnalyzer.Analyze(ctx, req, decodedProposal)
263266
if err != nil {
264-
// log error but continue with other analyzers
267+
ae.logger.Errorw("Proposal analyzer failed", "analyzerID", proposalAnalyzer.ID(), "error", err)
265268
continue
266269
}
267270
// Track which analyzer created the annotations
@@ -290,7 +293,7 @@ func (ae *analyzerEngine) analyzeBatchOperation(
290293
for _, call := range decodedBatchOperation.Calls() {
291294
analyzedCall, err := ae.analyzeCall(ctx, actx, ectx, call)
292295
if err != nil {
293-
// log error but continue
296+
ae.logger.Errorw("Failed to analyze call", "callName", call.Name(), "error", err)
294297
continue
295298
}
296299
calls = append(calls, analyzedCall)
@@ -331,7 +334,7 @@ func (ae *analyzerEngine) analyzeBatchOperation(
331334

332335
annotations, err := batchOpAnalyzer.Analyze(ctx, req, decodedBatchOperation)
333336
if err != nil {
334-
// log error but continue
337+
ae.logger.Errorw("Batch operation analyzer failed", "analyzerID", batchOpAnalyzer.ID(), "chainSelector", decodedBatchOperation.ChainSelector(), "error", err)
335338
continue
336339
}
337340
trackedAnnotations := trackAnnotations(annotations, batchOpAnalyzer.ID())
@@ -359,7 +362,7 @@ func (ae *analyzerEngine) analyzeCall(
359362
for _, param := range decodedCall.Inputs() {
360363
analyzedParam, err := ae.analyzeParameter(ctx, actx, ectx, param)
361364
if err != nil {
362-
// log error but continue
365+
ae.logger.Errorw("Failed to analyze input parameter", "paramName", param.Name(), "paramType", param.Type(), "error", err)
363366
continue
364367
}
365368
inputs = append(inputs, analyzedParam)
@@ -369,7 +372,7 @@ func (ae *analyzerEngine) analyzeCall(
369372
for _, param := range decodedCall.Outputs() {
370373
analyzedParam, err := ae.analyzeParameter(ctx, actx, ectx, param)
371374
if err != nil {
372-
// log error but continue
375+
ae.logger.Errorw("Failed to analyze output parameter", "paramName", param.Name(), "paramType", param.Type(), "error", err)
373376
continue
374377
}
375378
outputs = append(outputs, analyzedParam)
@@ -412,7 +415,7 @@ func (ae *analyzerEngine) analyzeCall(
412415

413416
annotations, err := callAnalyzer.Analyze(ctx, req, decodedCall)
414417
if err != nil {
415-
// log error but continue
418+
ae.logger.Errorw("Call analyzer failed", "analyzerID", callAnalyzer.ID(), "callName", decodedCall.Name(), "error", err)
416419
continue
417420
}
418421
trackedAnnotations := trackAnnotations(annotations, callAnalyzer.ID())
@@ -466,7 +469,7 @@ func (ae *analyzerEngine) analyzeParameter(
466469

467470
annotations, err := paramAnalyzer.Analyze(ctx, req, decodedParameter)
468471
if err != nil {
469-
// log error but continue
472+
ae.logger.Errorw("Parameter analyzer failed", "analyzerID", paramAnalyzer.ID(), "paramName", decodedParameter.Name(), "paramType", decodedParameter.Type(), "error", err)
470473
continue
471474
}
472475
trackedAnnotations := trackAnnotations(annotations, paramAnalyzer.ID())

engine/cld/mcms/proposalanalysis/engine_options.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package proposalanalysis
22

33
import (
4+
"github.com/smartcontractkit/chainlink-deployments-framework/pkg/logger"
45
experimentalanalyzer "github.com/smartcontractkit/chainlink-deployments-framework/experimental/analyzer"
56
)
67

@@ -11,6 +12,7 @@ type EngineOption func(*engineConfig)
1112
type engineConfig struct {
1213
evmRegistry experimentalanalyzer.EVMABIRegistry
1314
solanaRegistry experimentalanalyzer.SolanaDecoderRegistry
15+
logger logger.Logger
1416
}
1517

1618
// WithEVMRegistry allows injecting an EVM ABI registry into the analyzer engine
@@ -62,3 +64,26 @@ func (cfg *engineConfig) GetEVMRegistry() experimentalanalyzer.EVMABIRegistry {
6264
func (cfg *engineConfig) GetSolanaRegistry() experimentalanalyzer.SolanaDecoderRegistry {
6365
return cfg.solanaRegistry
6466
}
67+
68+
// WithLogger allows injecting a logger into the analyzer engine
69+
// The logger will be used for logging errors and debug information during analysis
70+
// If not provided, the engine will use a no-op logger
71+
//
72+
// Example:
73+
//
74+
// lggr, _ := logger.New()
75+
// engine := proposalanalysis.NewAnalyzerEngine(proposalanalysis.WithLogger(lggr))
76+
func WithLogger(lggr logger.Logger) EngineOption {
77+
return func(cfg *engineConfig) {
78+
cfg.logger = lggr
79+
}
80+
}
81+
82+
// GetLogger returns the logger from the config
83+
// Returns a no-op logger if none was provided
84+
func (cfg *engineConfig) GetLogger() logger.Logger {
85+
if cfg.logger == nil {
86+
return logger.Nop()
87+
}
88+
return cfg.logger
89+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package proposalanalysis
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"github.com/smartcontractkit/chainlink-deployments-framework/pkg/logger"
9+
)
10+
11+
func TestEngineOptions(t *testing.T) {
12+
t.Run("WithLogger option sets logger", func(t *testing.T) {
13+
lggr := logger.Test(t)
14+
cfg := ApplyEngineOptions(WithLogger(lggr))
15+
16+
assert.NotNil(t, cfg.GetLogger())
17+
})
18+
19+
t.Run("GetLogger returns nop logger when not set", func(t *testing.T) {
20+
cfg := ApplyEngineOptions()
21+
22+
lggr := cfg.GetLogger()
23+
assert.NotNil(t, lggr)
24+
// Verify it's a nop logger by checking it doesn't panic when called
25+
lggr.Info("test message")
26+
lggr.Errorw("test error", "key", "value")
27+
})
28+
29+
t.Run("multiple options can be combined", func(t *testing.T) {
30+
lggr := logger.Test(t)
31+
cfg := ApplyEngineOptions(
32+
WithLogger(lggr),
33+
WithEVMRegistry(nil),
34+
WithSolanaRegistry(nil),
35+
)
36+
37+
assert.NotNil(t, cfg.GetLogger())
38+
assert.Nil(t, cfg.GetEVMRegistry())
39+
assert.Nil(t, cfg.GetSolanaRegistry())
40+
})
41+
}

engine/cld/mcms/proposalanalysis/engine_test.go

Lines changed: 20 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,31 @@ import (
44
"testing"
55

66
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
78

8-
"github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalanalysis/analyzer"
9-
"github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalanalysis/types"
9+
"github.com/smartcontractkit/chainlink-deployments-framework/pkg/logger"
1010
)
1111

12-
func TestTrackAnnotations(t *testing.T) {
13-
t.Run("tracks annotations with analyzer ID", func(t *testing.T) {
14-
// Create some test annotations
15-
ann1 := analyzer.NewAnnotation("test1", "INFO", "value1")
16-
ann2 := analyzer.NewAnnotation("test2", "WARN", "value2")
17-
annotations := types.Annotations{ann1, ann2}
18-
19-
// Track them with an analyzer ID
20-
tracked := TrackAnnotations(annotations, "test-analyzer")
21-
22-
// Verify we got the same number of annotations back
23-
assert.Len(t, tracked, 2)
24-
25-
// Verify the annotations maintain their original properties
26-
assert.Equal(t, "test1", tracked[0].Name())
27-
assert.Equal(t, "INFO", tracked[0].Type())
28-
assert.Equal(t, "value1", tracked[0].Value())
29-
30-
assert.Equal(t, "test2", tracked[1].Name())
31-
assert.Equal(t, "WARN", tracked[1].Type())
32-
assert.Equal(t, "value2", tracked[1].Value())
33-
34-
// Verify they can be retrieved by analyzer ID
35-
annotated := &analyzer.Annotated{}
36-
annotated.AddAnnotations(tracked...)
37-
38-
retrieved := annotated.GetAnnotationsByAnalyzer("test-analyzer")
39-
assert.Len(t, retrieved, 2)
40-
assert.Equal(t, "test1", retrieved[0].Name())
41-
assert.Equal(t, "test2", retrieved[1].Name())
12+
func TestEngineWithLogger(t *testing.T) {
13+
t.Run("engine accepts logger from options", func(t *testing.T) {
14+
lggr := logger.Test(t)
15+
engine := NewAnalyzerEngine(WithLogger(lggr))
16+
17+
assert.NotNil(t, engine)
18+
// Verify the logger is set by checking the concrete type
19+
concreteEngine, ok := engine.(*analyzerEngine)
20+
require.True(t, ok)
21+
assert.NotNil(t, concreteEngine.logger)
22+
assert.Equal(t, "TestEngineWithLogger/engine_accepts_logger_from_options", concreteEngine.logger.Name())
4223
})
4324

44-
t.Run("handles empty annotations slice", func(t *testing.T) {
45-
annotations := types.Annotations{}
46-
tracked := TrackAnnotations(annotations, "test-analyzer")
47-
48-
assert.Len(t, tracked, 0)
49-
assert.NotNil(t, tracked)
50-
})
51-
52-
t.Run("preserves annotation values of different types", func(t *testing.T) {
53-
ann1 := analyzer.NewAnnotation("int-value", "INFO", 42)
54-
ann2 := analyzer.NewAnnotation("bool-value", "INFO", true)
55-
ann3 := analyzer.NewAnnotation("slice-value", "INFO", []string{"a", "b", "c"})
56-
annotations := types.Annotations{ann1, ann2, ann3}
57-
58-
tracked := TrackAnnotations(annotations, "multi-type-analyzer")
25+
t.Run("engine uses nop logger when not provided", func(t *testing.T) {
26+
engine := NewAnalyzerEngine()
5927

60-
assert.Equal(t, 42, tracked[0].Value())
61-
assert.Equal(t, true, tracked[1].Value())
62-
assert.Equal(t, []string{"a", "b", "c"}, tracked[2].Value())
28+
assert.NotNil(t, engine)
29+
// Verify the logger is set (will be Nop logger)
30+
concreteEngine, ok := engine.(*analyzerEngine)
31+
require.True(t, ok)
32+
assert.NotNil(t, concreteEngine.logger)
6333
})
6434
}

0 commit comments

Comments
 (0)