Skip to content

Commit 5798b30

Browse files
authored
INFOPLAT-2449: Use chainlink-common otelzap core in chainlink global logger (#19089)
* Refactor node startup logic to enable telemetry and dependencies earlier in the subcommands * Wire up OTel logs streaming, integrate chainlink logger with otel * Revert CSA test * Reorder before/after node functions * Add AfterNode execution to the tests * Fix test by cleaning resources only when they are provisioned * Fix lint * Remove redundant check for empty keystore * Fix test by cleaning * Fix lint shadowing * Fix hanging test * Change cleanup in the test
1 parent ebab9c3 commit 5798b30

12 files changed

Lines changed: 549 additions & 219 deletions

File tree

.changeset/slick-badgers-behave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink": patch
3+
---
4+
5+
#added Wire up OTel logs streaming, integrate chainlink logger with otel

core/cmd/app.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,20 +261,28 @@ func NewApp(s *Shell) *cli.App {
261261
return err
262262
}
263263

264+
// Configure a new logger with OTel atomic core support
264265
lggrCfg := logger.Config{
265-
LogLevel: s.Config.Log().Level(),
266-
Dir: s.Config.Log().File().Dir(),
267-
JsonConsole: s.Config.Log().JSONConsole(),
268-
UnixTS: s.Config.Log().UnixTimestamps(),
266+
LogLevel: s.Config.Log().Level(),
267+
Dir: s.Config.Log().File().Dir(),
268+
JsonConsole: s.Config.Log().JSONConsole(),
269+
UnixTS: s.Config.Log().UnixTimestamps(),
270+
//nolint:gosec // filemaxsizesmb won't exceed max int
269271
FileMaxSizeMB: int(logFileMaxSizeMB),
270272
FileMaxAgeDays: int(s.Config.Log().File().MaxAgeDays()),
271273
FileMaxBackups: int(s.Config.Log().File().MaxBackups()),
272274
SentryEnabled: s.Config.Sentry().DSN() != "",
273275
}
274-
l, closeFn := lggrCfg.New()
276+
277+
// Noop atomic core that can be swapped out later for OTel support
278+
atomicCore := logger.NewAtomicCore()
279+
280+
l, closeFn := lggrCfg.NewWithCores(atomicCore)
275281

276282
s.Logger = l
277283
s.CloseLogger = closeFn
284+
// s.SetOtelCore is a hook that can be used to set the OTel core
285+
s.SetOtelCore = atomicCore.Store
278286

279287
return nil
280288
},

core/cmd/shell.go

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import (
5050
"github.com/smartcontractkit/chainlink/v2/core/services/llo"
5151
"github.com/smartcontractkit/chainlink/v2/core/services/llo/retirement"
5252
"github.com/smartcontractkit/chainlink/v2/core/services/periodicbackup"
53+
"github.com/smartcontractkit/chainlink/v2/core/services/pg"
5354
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc"
5455
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache"
5556
"github.com/smartcontractkit/chainlink/v2/core/services/versioning"
@@ -59,7 +60,6 @@ import (
5960
"github.com/smartcontractkit/chainlink/v2/core/sessions"
6061
"github.com/smartcontractkit/chainlink/v2/core/static"
6162
"github.com/smartcontractkit/chainlink/v2/core/store/migrate"
62-
"github.com/smartcontractkit/chainlink/v2/core/utils"
6363
"github.com/smartcontractkit/chainlink/v2/core/web"
6464
)
6565

@@ -139,11 +139,9 @@ func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTeleme
139139
return err
140140
}
141141

142-
var (
143-
// ErrorNoAPICredentialsAvailable is returned when not run from a terminal
144-
// and no API credentials have been provided
145-
ErrorNoAPICredentialsAvailable = errors.New("API credentials must be supplied")
146-
)
142+
// ErrNoAPICredentialsAvailable is returned when not run from a terminal
143+
// and no API credentials have been provided
144+
var ErrNoAPICredentialsAvailable = errors.New("API credentials must be supplied")
147145

148146
// Shell for the node, local commands and remote commands.
149147
type Shell struct {
@@ -152,6 +150,7 @@ type Shell struct {
152150
Logger logger.Logger // initialized in Before
153151
Registerer prometheus.Registerer // initialized in Before
154152
CloseLogger func() error // called in After
153+
SetOtelCore func(*zapcore.Core) // reference to AtomicCore.Store
155154
AppFactory AppFactory
156155
KeyStoreAuthenticator TerminalKeyStoreAuthenticator
157156
FallbackAPIInitializer APIInitializer
@@ -167,6 +166,12 @@ type Shell struct {
167166
configFilesIsSet bool
168167
secretsFiles []string
169168
secretsFileIsSet bool
169+
170+
LDB pg.LockedDB // initialized in BeforeNode
171+
DS sqlutil.DataSource // initialized in BeforeNode
172+
KeyStore keystore.Master // initialized in BeforeNode
173+
174+
CleanupOnce sync.Once // ensures cleanup happens exactly once
170175
}
171176

172177
func (s *Shell) errorOut(err error) cli.ExitCoder {
@@ -190,42 +195,19 @@ func (s *Shell) configExitErr(validateFn func() error) cli.ExitCoder {
190195

191196
// AppFactory implements the NewApplication method.
192197
type AppFactory interface {
193-
NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, appRegisterer prometheus.Registerer, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (chainlink.Application, error)
198+
NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, appRegisterer prometheus.Registerer, ds sqlutil.DataSource, keyStore keystore.Master) (chainlink.Application, error)
194199
}
195200

196201
// ChainlinkAppFactory is used to create a new Application.
197202
type ChainlinkAppFactory struct{}
198203

199204
// NewApplication returns a new instance of the node with the given config.
200-
func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, appRegisterer prometheus.Registerer, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (app chainlink.Application, err error) {
205+
func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, appRegisterer prometheus.Registerer, ds sqlutil.DataSource, keyStore keystore.Master) (app chainlink.Application, err error) {
201206
err = migrate.SetMigrationENVVars(cfg.EVMConfigs())
202207
if err != nil {
203208
return nil, err
204209
}
205210

206-
err = handleNodeVersioning(ctx, db, appLggr, cfg.RootDir(), cfg.Database(), cfg.WebServer().HTTPPort())
207-
if err != nil {
208-
return nil, err
209-
}
210-
211-
ds := sqlutil.WrapDataSource(db, appLggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout), sqlutil.MonitorHook(cfg.Database().LogSQL))
212-
keyStore := keystore.New(ds, utils.GetScryptParams(cfg), appLggr.Infof)
213-
214-
err = keyStoreAuthenticator.Authenticate(ctx, keyStore, cfg.Password())
215-
if err != nil {
216-
return nil, errors.Wrap(err, "error authenticating keystore")
217-
}
218-
219-
beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(ctx, keyStore.CSA())
220-
if err != nil {
221-
return nil, errors.Wrap(err, "failed to build Beholder auth")
222-
}
223-
224-
err = initGlobals(cfg.Prometheus(), cfg.Tracing(), cfg.Telemetry(), appLggr, csaPubKeyHex, beholderAuthHeaders)
225-
if err != nil {
226-
appLggr.Errorf("Failed to initialize globals: %v", err)
227-
}
228-
229211
mercuryPool := wsrpc.NewPool(appLggr, cache.Config{
230212
LatestReportTTL: cfg.Mercury().Cache().LatestReportTTL(),
231213
MaxStaleAge: cfg.Mercury().Cache().MaxStaleAge(),
@@ -738,13 +720,13 @@ type DiskCookieStore struct {
738720

739721
// Save stores a cookie.
740722
func (d DiskCookieStore) Save(cookie *http.Cookie) error {
741-
return os.WriteFile(d.cookiePath(), []byte(cookie.String()), 0600)
723+
return os.WriteFile(d.cookiePath(), []byte(cookie.String()), 0o600)
742724
}
743725

744726
// Removes any stored cookie.
745727
func (d DiskCookieStore) Reset() error {
746728
// Write empty bytes
747-
return os.WriteFile(d.cookiePath(), []byte(""), 0600)
729+
return os.WriteFile(d.cookiePath(), []byte(""), 0o600)
748730
}
749731

750732
// Retrieve returns any Saved cookies.
@@ -785,7 +767,7 @@ func NewUserCache(subdir string, lggr func() logger.Logger) (*UserCache, error)
785767
}
786768

787769
func (cs *UserCache) ensure() {
788-
if err := os.MkdirAll(cs.dir, 0700); err != nil {
770+
if err := os.MkdirAll(cs.dir, 0o700); err != nil {
789771
cs.lggr().Errorw("Failed to make user cache dir", "dir", cs.dir, "err", err)
790772
}
791773
}
@@ -859,7 +841,7 @@ func (t *promptingAPIInitializer) Initialize(ctx context.Context, orm sessions.B
859841
// If there are no users in the database, prompt for initial admin user creation
860842
if len(dbUsers) == 0 {
861843
if !t.prompter.IsTerminal() {
862-
return sessions.User{}, ErrorNoAPICredentialsAvailable
844+
return sessions.User{}, ErrNoAPICredentialsAvailable
863845
}
864846

865847
for {
@@ -886,7 +868,6 @@ func (t *promptingAPIInitializer) Initialize(ctx context.Context, orm sessions.B
886868
// Otherwise, multiple admin users exist, prompt for which to use
887869
email := t.prompter.Prompt("Enter email of API user account to assume: ")
888870
user, err := orm.FindUser(ctx, email)
889-
890871
if err != nil {
891872
return sessions.User{}, err
892873
}

0 commit comments

Comments
 (0)