diff --git a/.changeset/cuddly-toys-warn.md b/.changeset/cuddly-toys-warn.md new file mode 100644 index 00000000000..8e15ba65014 --- /dev/null +++ b/.changeset/cuddly-toys-warn.md @@ -0,0 +1,14 @@ +--- +"chainlink": patch +--- + +Add "VerboseLogging" option to mercury + +Off by default, can be enabled like so: + +```toml +[Mercury] +VerboseLogging = true +``` + +#updated diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 265609b064c..d1b922cf291 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -605,6 +605,11 @@ env = 'test' # Example [Mercury] +# VerboseLogging enables detailed logging of mercury/LLO operations. These logs +# can be expensive since they may serialize large structs, so they are disabled +# by default. +VerboseLogging = false # Default + # Mercury.Cache controls settings for the price retrieval cache querying a mercury server [Mercury.Cache] # LatestReportTTL controls how "stale" we will allow a price to be e.g. if diff --git a/core/config/mercury_config.go b/core/config/mercury_config.go index f16fc4661a5..d1b4b142e20 100644 --- a/core/config/mercury_config.go +++ b/core/config/mercury_config.go @@ -27,4 +27,5 @@ type Mercury interface { Cache() MercuryCache TLS() MercuryTLS Transmitter() MercuryTransmitter + VerboseLogging() bool } diff --git a/core/config/toml/types.go b/core/config/toml/types.go index c8b983b7c26..f827f086225 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -1324,15 +1324,19 @@ func (m *MercuryTransmitter) setFrom(f *MercuryTransmitter) { } type Mercury struct { - Cache MercuryCache `toml:",omitempty"` - TLS MercuryTLS `toml:",omitempty"` - Transmitter MercuryTransmitter `toml:",omitempty"` + Cache MercuryCache `toml:",omitempty"` + TLS MercuryTLS `toml:",omitempty"` + Transmitter MercuryTransmitter `toml:",omitempty"` + VerboseLogging *bool `toml:",omitempty"` } func (m *Mercury) setFrom(f *Mercury) { m.Cache.setFrom(&f.Cache) m.TLS.setFrom(&f.TLS) m.Transmitter.setFrom(&f.Transmitter) + if v := f.VerboseLogging; v != nil { + m.VerboseLogging = v + } } func (m *Mercury) ValidateConfig() (err error) { diff --git a/core/internal/testutils/configtest/general_config.go b/core/internal/testutils/configtest/general_config.go index 5ba3bf1724f..63aba18c351 100644 --- a/core/internal/testutils/configtest/general_config.go +++ b/core/internal/testutils/configtest/general_config.go @@ -58,6 +58,8 @@ func overrides(c *chainlink.Config, s *chainlink.Secrets) { c.JobPipeline.ReaperInterval = commonconfig.MustNewDuration(0) c.JobPipeline.VerboseLogging = ptr(true) + c.Mercury.VerboseLogging = ptr(true) + c.P2P.V2.Enabled = ptr(false) c.WebServer.SessionTimeout = commonconfig.MustNewDuration(2 * time.Minute) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 884ea17a81c..33cd3d80cc2 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -272,7 +272,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 52d8cc141e8..afa240ad6be 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1211,8 +1211,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc0/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 h1:dsTmitRaVizHxoYFoGz4+y/zVa8XnvKUiTaZdx+6t9M= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1/go.mod h1:6DgCnHMGdBaIh0bLs1dK0MtdeMZfeNhc/nvBUN6KIUg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 h1:tBJo/Rn0Ur7XtzqTEgIhLYDDWdcXBf985AF0PegsDk8= diff --git a/core/services/chainlink/config_mercury.go b/core/services/chainlink/config_mercury.go index 1b64e0bde45..bc4aed6fb07 100644 --- a/core/services/chainlink/config_mercury.go +++ b/core/services/chainlink/config_mercury.go @@ -81,3 +81,7 @@ func (m *mercuryConfig) TLS() config.MercuryTLS { func (m *mercuryConfig) Transmitter() config.MercuryTransmitter { return &mercuryTransmitterConfig{c: m.c.Transmitter} } + +func (m *mercuryConfig) VerboseLogging() bool { + return *m.c.VerboseLogging +} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 576a932e3c6..c8cd5ec4790 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -729,6 +729,7 @@ func TestConfig_Marshal(t *testing.T) { TransmitQueueMaxSize: ptr(uint32(123)), TransmitTimeout: commoncfg.MustNewDuration(234 * time.Second), }, + VerboseLogging: ptr(true), } for _, tt := range []struct { @@ -1186,6 +1187,8 @@ URL = 'http://stark.node' APIKey = 'key' `}, {"Mercury", Config{Core: toml.Core{Mercury: full.Mercury}}, `[Mercury] +VerboseLogging = true + [Mercury.Cache] LatestReportTTL = '1m40s' MaxStaleAge = '1m41s' diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index 7ee0143870f..1bad3fd91c6 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -222,6 +222,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index c041a2857b4..78f52805dfe 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -232,6 +232,8 @@ env = 'dev' test = 'load' [Mercury] +VerboseLogging = true + [Mercury.Cache] LatestReportTTL = '1m40s' MaxStaleAge = '1m41s' diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 22a49476dc4..61c5e3fa266 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -222,6 +222,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/core/services/llo/bm/dummy_transmitter.go b/core/services/llo/bm/dummy_transmitter.go index 5573350b4e6..a0adf5e477a 100644 --- a/core/services/llo/bm/dummy_transmitter.go +++ b/core/services/llo/bm/dummy_transmitter.go @@ -10,6 +10,8 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-data-streams/llo" + "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" @@ -57,8 +59,26 @@ func (t *transmitter) Transmit( report ocr3types.ReportWithInfo[llotypes.ReportInfo], sigs []types.AttributedOnchainSignature, ) error { + lggr := t.lggr + switch report.Info.ReportFormat { + case llotypes.ReportFormatJSON: + r, err := (llo.JSONReportCodec{}).Decode(report.Report) + if err != nil { + lggr.Debugw("Failed to decode JSON report", "err", err) + } + lggr = lggr.With( + "report.Report.ConfigDigest", r.ConfigDigest, + "report.Report.ChainSelector", r.ChainSelector, + "report.Report.SeqNr", r.SeqNr, + "report.Report.ChannelID", r.ChannelID, + "report.Report.ValidAfterSeconds", r.ValidAfterSeconds, + "report.Report.ValidUntilSeconds", r.ValidUntilSeconds, + "report.Report.Values", r.Values, + "report.Report.Specimen", r.Specimen, + ) + } transmitSuccessCount.Inc() - t.lggr.Debugw("Transmit", "digest", digest, "seqNr", seqNr, "report.Report", report.Report, "report.Info", report.Info, "sigs", sigs) + lggr.Infow("Transmit (dummy)", "digest", digest, "seqNr", seqNr, "report.Report", report.Report, "report.Info", report.Info, "sigs", sigs) return nil } diff --git a/core/services/llo/data_source.go b/core/services/llo/data_source.go index 30f646e1cb3..596f3a884a9 100644 --- a/core/services/llo/data_source.go +++ b/core/services/llo/data_source.go @@ -4,15 +4,18 @@ import ( "context" "fmt" "math/big" + "sort" "sync" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + "golang.org/x/exp/maps" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) @@ -31,16 +34,35 @@ var ( ) ) -type ErrMissingStream struct { - id string -} - type Registry interface { Get(streamID streams.StreamID) (strm streams.Stream, exists bool) } -func (e ErrMissingStream) Error() string { - return fmt.Sprintf("missing stream definition for: %q", e.id) +type ErrObservationFailed struct { + inner error + reason string + streamID streams.StreamID + run *pipeline.Run +} + +func (e *ErrObservationFailed) Error() string { + s := fmt.Sprintf("StreamID: %d; Reason: %s", e.streamID, e.reason) + if e.inner != nil { + s += fmt.Sprintf("; Err: %v", e.inner) + } + if e.run != nil { + // NOTE: Could log more info about the run here if necessary + s += fmt.Sprintf("; RunID: %d; RunErrors: %v", e.run.ID, e.run.AllErrors) + } + return s +} + +func (e *ErrObservationFailed) String() string { + return e.Error() +} + +func (e *ErrObservationFailed) Unwrap() error { + return e.inner } var _ llo.DataSource = &dataSource{} @@ -54,54 +76,86 @@ func newDataSource(lggr logger.Logger, registry Registry) llo.DataSource { return &dataSource{lggr.Named("DataSource"), registry} } -// Observe looks up all streams in the registry and returns a map of stream ID => value -func (d *dataSource) Observe(ctx context.Context, streamIDs map[llotypes.StreamID]struct{}) (llo.StreamValues, error) { +// Observe looks up all streams in the registry and populates a map of stream ID => value +func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, opts llo.DSOpts) error { var wg sync.WaitGroup - wg.Add(len(streamIDs)) - sv := make(llo.StreamValues) - var mu sync.Mutex - - d.lggr.Debugw("Observing streams", "streamIDs", streamIDs) + wg.Add(len(streamValues)) + var svmu sync.Mutex + var errors []ErrObservationFailed + var errmu sync.Mutex + + if opts.VerboseLogging() { + streamIDs := make([]streams.StreamID, 0, len(streamValues)) + for streamID := range streamValues { + streamIDs = append(streamIDs, streamID) + } + sort.Slice(streamIDs, func(i, j int) bool { return streamIDs[i] < streamIDs[j] }) + d.lggr.Debugw("Observing streams", "streamIDs", streamIDs, "seqNr", opts.SeqNr()) + } - for streamID := range streamIDs { + for _, streamID := range maps.Keys(streamValues) { go func(streamID llotypes.StreamID) { defer wg.Done() - var res llo.ObsResult[*big.Int] + var val *big.Int stream, exists := d.registry.Get(streamID) - if exists { - run, trrs, err := stream.Run(ctx) - if err != nil { - var runID int64 - if run != nil { - runID = run.ID - } - d.lggr.Debugw("Observation failed for stream", "err", err, "streamID", streamID, "runID", runID) - promObservationErrorCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() - } else { - // TODO: support types other than *big.Int - // https://smartcontract-it.atlassian.net/browse/MERC-3525 - val, err := streams.ExtractBigInt(trrs) - if err == nil { - res.Val = val - res.Valid = true - } - } - } else { - d.lggr.Errorw(fmt.Sprintf("Missing stream: %q", streamID), "streamID", streamID) + if !exists { + errmu.Lock() + errors = append(errors, ErrObservationFailed{streamID: streamID, reason: fmt.Sprintf("missing stream: %d", streamID)}) + errmu.Unlock() promMissingStreamCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() + return + } + run, trrs, err := stream.Run(ctx) + if err != nil { + errmu.Lock() + errors = append(errors, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "pipeline run failed"}) + errmu.Unlock() + promObservationErrorCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() + return + } + // TODO: support types other than *big.Int + // https://smartcontract-it.atlassian.net/browse/MERC-3525 + val, err = streams.ExtractBigInt(trrs) + if err != nil { + errmu.Lock() + errors = append(errors, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "failed to extract big.Int"}) + errmu.Unlock() + return } - mu.Lock() - defer mu.Unlock() - sv[streamID] = res + if val != nil { + svmu.Lock() + defer svmu.Unlock() + streamValues[streamID] = val + } }(streamID) } wg.Wait() - d.lggr.Debugw("Observed streams", "streamIDs", streamIDs, "values", sv) + // Failed observations are always logged at warn level + var failedStreamIDs []streams.StreamID + if len(errors) > 0 { + sort.Slice(errors, func(i, j int) bool { return errors[i].streamID < errors[j].streamID }) + failedStreamIDs = make([]streams.StreamID, len(errors)) + for i, e := range errors { + failedStreamIDs[i] = e.streamID + } + d.lggr.Warnw("Observation failed for streams", "failedStreamIDs", failedStreamIDs, "errors", errors, "seqNr", opts.SeqNr()) + } + + if opts.VerboseLogging() { + successes := make([]streams.StreamID, 0, len(streamValues)) + for strmID, res := range streamValues { + if res != nil { + successes = append(successes, strmID) + } + } + sort.Slice(successes, func(i, j int) bool { return successes[i] < successes[j] }) + d.lggr.Debugw("Observation complete", "successfulStreamIDs", successes, "failedStreamIDs", failedStreamIDs, "values", streamValues, "seqNr", opts.SeqNr()) + } - return sv, nil + return nil } diff --git a/core/services/llo/data_source_test.go b/core/services/llo/data_source_test.go index c956e3770c9..a975468c933 100644 --- a/core/services/llo/data_source_test.go +++ b/core/services/llo/data_source_test.go @@ -41,40 +41,46 @@ func makeStreamWithSingleResult[T any](res T, err error) *mockStream { } } +func makeStreamValues() llo.StreamValues { + return llo.StreamValues{ + 1: nil, + 2: nil, + 3: nil, + } +} + +type mockOpts struct{} + +func (m mockOpts) VerboseLogging() bool { return true } +func (m mockOpts) SeqNr() uint64 { return 42 } + func Test_DataSource(t *testing.T) { lggr := logger.TestLogger(t) reg := &mockRegistry{make(map[streams.StreamID]*mockStream)} ds := newDataSource(lggr, reg) ctx := testutils.Context(t) - streamIDs := make(map[streams.StreamID]struct{}) - streamIDs[streams.StreamID(1)] = struct{}{} - streamIDs[streams.StreamID(2)] = struct{}{} - streamIDs[streams.StreamID(3)] = struct{}{} - t.Run("Observe", func(t *testing.T) { - t.Run("returns errors if no streams are defined", func(t *testing.T) { - vals, err := ds.Observe(ctx, streamIDs) + t.Run("doesn't set any values if no streams are defined", func(t *testing.T) { + vals := makeStreamValues() + err := ds.Observe(ctx, vals, mockOpts{}) assert.NoError(t, err) - assert.Equal(t, llo.StreamValues{ - 2: llo.ObsResult[*big.Int]{Val: nil, Valid: false}, - 1: llo.ObsResult[*big.Int]{Val: nil, Valid: false}, - 3: llo.ObsResult[*big.Int]{Val: nil, Valid: false}, - }, vals) + assert.Equal(t, makeStreamValues(), vals) }) t.Run("observes each stream with success and returns values matching map argument", func(t *testing.T) { reg.streams[1] = makeStreamWithSingleResult[*big.Int](big.NewInt(2181), nil) reg.streams[2] = makeStreamWithSingleResult[*big.Int](big.NewInt(40602), nil) reg.streams[3] = makeStreamWithSingleResult[*big.Int](big.NewInt(15), nil) - vals, err := ds.Observe(ctx, streamIDs) + vals := makeStreamValues() + err := ds.Observe(ctx, vals, mockOpts{}) assert.NoError(t, err) assert.Equal(t, llo.StreamValues{ - 2: llo.ObsResult[*big.Int]{Val: big.NewInt(40602), Valid: true}, - 1: llo.ObsResult[*big.Int]{Val: big.NewInt(2181), Valid: true}, - 3: llo.ObsResult[*big.Int]{Val: big.NewInt(15), Valid: true}, + 2: big.NewInt(40602), + 1: big.NewInt(2181), + 3: big.NewInt(15), }, vals) }) t.Run("observes each stream and returns success/errors", func(t *testing.T) { @@ -82,13 +88,14 @@ func Test_DataSource(t *testing.T) { reg.streams[2] = makeStreamWithSingleResult[*big.Int](big.NewInt(40602), nil) reg.streams[3] = makeStreamWithSingleResult[*big.Int](nil, errors.New("something exploded 2")) - vals, err := ds.Observe(ctx, streamIDs) + vals := makeStreamValues() + err := ds.Observe(ctx, vals, mockOpts{}) assert.NoError(t, err) assert.Equal(t, llo.StreamValues{ - 2: llo.ObsResult[*big.Int]{Val: big.NewInt(40602), Valid: true}, - 1: llo.ObsResult[*big.Int]{Val: nil, Valid: false}, - 3: llo.ObsResult[*big.Int]{Val: nil, Valid: false}, + 2: big.NewInt(40602), + 1: nil, + 3: nil, }, vals) }) }) diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index 6cdad6290fc..fcb379d1fbc 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -51,6 +51,7 @@ type DelegateConfig struct { // LLO ChannelDefinitionCache llotypes.ChannelDefinitionCache + ReportingPluginConfig llo.Config // OCR3 BinaryNetworkEndpointFactory ocr2types.BinaryNetworkEndpointFactory @@ -107,7 +108,7 @@ func (d *delegate) Start(ctx context.Context) error { OffchainKeyring: d.cfg.OffchainKeyring, OnchainKeyring: d.cfg.OnchainKeyring, ReportingPluginFactory: llo.NewPluginFactory( - d.prrc, d.src, d.cfg.ChannelDefinitionCache, d.ds, d.cfg.Logger.Named("LLOReportingPlugin"), d.codecs, + d.cfg.ReportingPluginConfig, d.prrc, d.src, d.cfg.ChannelDefinitionCache, d.ds, d.cfg.Logger.Named("LLOReportingPlugin"), d.codecs, ), MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": d.cfg.JobName.ValueOrZero()}, prometheus.DefaultRegisterer), }) diff --git a/core/services/llo/static_channel_definitions_cache.go b/core/services/llo/static_channel_definitions_cache.go index bf26dd781ee..98ef3642cb7 100644 --- a/core/services/llo/static_channel_definitions_cache.go +++ b/core/services/llo/static_channel_definitions_cache.go @@ -32,6 +32,7 @@ func NewStaticChannelDefinitionCache(lggr logger.Logger, dfnstr string) (llotype func (s *staticCDC) Start(context.Context) error { return s.StartOnce("StaticChannelDefinitionCache", func() error { + s.lggr.Infow("Initialized static channel definition cache", "definitions", s.definitions) return nil }) } diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 9066afd740b..a6843401aa7 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -35,6 +35,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/core" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -185,6 +186,7 @@ type mercuryConfig interface { Cache() coreconfig.MercuryCache TLS() coreconfig.MercuryTLS Transmitter() coreconfig.MercuryTransmitter + VerboseLogging() bool } type thresholdConfig interface { @@ -966,6 +968,9 @@ func (d *Delegate) newServicesLLO( OffchainKeyring: kb, OnchainKeyring: kr, OCRLogger: ocrLogger, + + // Enable verbose logging if either Mercury.VerboseLogging is on or OCR2.TraceLogging is on + ReportingPluginConfig: datastreamsllo.Config{VerboseLogging: d.cfg.Mercury().VerboseLogging() || d.cfg.OCR2().TraceLogging()}, } oracle, err := llo.NewDelegate(cfg) if err != nil { diff --git a/core/services/ocr2/plugins/llo/integration_test.go b/core/services/ocr2/plugins/llo/integration_test.go index d80a422e680..75cc7edc5d9 100644 --- a/core/services/ocr2/plugins/llo/integration_test.go +++ b/core/services/ocr2/plugins/llo/integration_test.go @@ -459,7 +459,7 @@ func TestIntegration_LLO_Dummy(t *testing.T) { relayConfig := fmt.Sprintf(`chainID = "%s" configTracker = { configDigest = "%s", - configCoung = 1, + configCount = 0, signers = %s, transmitters = %s, f = %d, @@ -499,6 +499,9 @@ channelDefinitions = %q`, serverPubKey, channelDefinitions) assert.Equal(t, cd[2:], fields["digest"]) assert.Equal(t, llotypes.ReportInfo{LifeCycleStage: "production", ReportFormat: llotypes.ReportFormatJSON}, fields["report.Info"]) + if fields["report.Report"] == nil { + t.Fatal("FAIL: expected log fields to contain 'report.Report'") + } binaryReport := fields["report.Report"].(types.Report) report, err := (datastreamsllo.JSONReportCodec{}).Decode(binaryReport) require.NoError(t, err) diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 288d8133db7..4da5b1da651 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -37,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/streams" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/services/workflows" @@ -1063,6 +1064,8 @@ func (r *Resolver) CreateJob(ctx context.Context, args struct { jb, err = workflows.ValidatedWorkflowJobSpec(args.Input.TOML) case job.StandardCapabilities: jb, err = standardcapabilities.ValidatedStandardCapabilitiesSpec(args.Input.TOML) + case job.Stream: + jb, err = streams.ValidatedStreamSpec(args.Input.TOML) default: return NewCreateJobPayload(r.App, nil, map[string]string{ "Job Type": fmt.Sprintf("unknown job type: %s", jbt), diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index 7ee0143870f..1bad3fd91c6 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -222,6 +222,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 76326f9a4d4..3e083bd1844 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -232,6 +232,8 @@ env = 'dev' test = 'load' [Mercury] +VerboseLogging = true + [Mercury.Cache] LatestReportTTL = '1m40s' MaxStaleAge = '1m41s' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 8e6682dee3f..f391804b7cd 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -222,6 +222,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 9e10615a010..7a4d3ca62ca 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1670,9 +1670,18 @@ env is an example user specified key-value pair ## Mercury ```toml [Mercury] +VerboseLogging = false # Default ``` +### VerboseLogging +```toml +VerboseLogging = false # Default +``` +VerboseLogging enables detailed logging of mercury/LLO operations. These logs +can be expensive since they may serialize large structs, so they are disabled +by default. + ## Mercury.Cache ```toml [Mercury.Cache] diff --git a/go.mod b/go.mod index 25313ef25f8..000154b6017 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc0 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba @@ -349,5 +349,4 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - ) diff --git a/go.sum b/go.sum index 9f5bbd4b57f..92790159cac 100644 --- a/go.sum +++ b/go.sum @@ -1169,8 +1169,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc0/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 h1:dsTmitRaVizHxoYFoGz4+y/zVa8XnvKUiTaZdx+6t9M= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1/go.mod h1:6DgCnHMGdBaIh0bLs1dK0MtdeMZfeNhc/nvBUN6KIUg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 h1:tBJo/Rn0Ur7XtzqTEgIhLYDDWdcXBf985AF0PegsDk8= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 5d9097be77c..dd6f2be123d 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -377,7 +377,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 8571ff760a8..6b29839d5c4 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1516,8 +1516,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc0/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 h1:dsTmitRaVizHxoYFoGz4+y/zVa8XnvKUiTaZdx+6t9M= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1/go.mod h1:6DgCnHMGdBaIh0bLs1dK0MtdeMZfeNhc/nvBUN6KIUg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 h1:tBJo/Rn0Ur7XtzqTEgIhLYDDWdcXBf985AF0PegsDk8= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index f2ac456baa4..9cb8968a7e2 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -365,7 +365,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index b98f370181e..44b7798a447 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1506,8 +1506,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc github.com/smartcontractkit/chainlink-common v0.1.7-0.20240703234618-dc1fbe45acc0/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1 h1:dsTmitRaVizHxoYFoGz4+y/zVa8XnvKUiTaZdx+6t9M= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702145022-37a2c3a742d1/go.mod h1:6DgCnHMGdBaIh0bLs1dK0MtdeMZfeNhc/nvBUN6KIUg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240708130426-294b81e4afe7 h1:tBJo/Rn0Ur7XtzqTEgIhLYDDWdcXBf985AF0PegsDk8= diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index 9c50188141c..1063d9c2a5a 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -234,6 +234,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index e8e1046cef5..327e84c51bb 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -278,6 +278,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index c7b651e3aeb..724b59e52d3 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -278,6 +278,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 1eee9f595c3..e0eefcba85b 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -278,6 +278,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 3c6e24a897b..6a09dd06c47 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -263,6 +263,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 73d557c0ae7..1955e919da3 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -268,6 +268,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 76a134b7761..3ba20f6f9d6 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -275,6 +275,8 @@ Mode = 'tls' TLSCertPath = '' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s' diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index d8d0de337aa..a652943e26b 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -257,6 +257,8 @@ Mode = 'unencrypted' TLSCertPath = 'something' [Mercury] +VerboseLogging = false + [Mercury.Cache] LatestReportTTL = '1s' MaxStaleAge = '1h0m0s'