Skip to content
This repository was archived by the owner on Dec 10, 2020. It is now read-only.

Commit d8a0f3b

Browse files
holgerd77ryanio
authored andcommitted
Unified logger and loglevel options in Config, throw on unsupported option combinations (servers and transports, logger and loglevel)
1 parent 835dad0 commit d8a0f3b

File tree

5 files changed

+77
-45
lines changed

5 files changed

+77
-45
lines changed

bin/cli.ts

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
#!/usr/bin/env node
22

33
const chains = require('@ethereumjs/common/dist/chains').chains
4-
import { getLogger } from '../lib/logging'
54
import { parseParams } from '../lib/util'
65
import Node from '../lib/node'
76
import { Server as RPCServer } from 'jayson'
87
import { Config } from '../lib/config'
98
import Common from '@ethereumjs/common'
109
import { RPCManager } from '../lib/rpc'
10+
import { Logger } from 'winston'
1111
const level = require('level')
1212
const path = require('path')
1313
const fs = require('fs-extra')
1414

1515
const networks = Object.entries(chains.names)
16+
1617
const args = require('yargs')
1718
.options({
1819
network: {
@@ -56,12 +57,12 @@ const args = require('yargs')
5657
},
5758
rpcaddr: {
5859
describe: 'HTTP-RPC server listening interface',
59-
default: 'localhost',
60+
default: Config.RPCADDR_DEFAULT,
6061
},
6162
loglevel: {
6263
describe: 'Logging verbosity',
6364
choices: ['error', 'warn', 'info', 'debug'],
64-
default: 'info',
65+
default: Config.LOGLEVEL_DEFAULT,
6566
},
6667
minPeers: {
6768
describe: 'Peers needed before syncing',
@@ -79,37 +80,38 @@ const args = require('yargs')
7980
},
8081
})
8182
.locale('en_EN').argv
82-
const logger = getLogger({ loglevel: args.loglevel })
83+
84+
let logger: Logger | null = null
8385

8486
/**
8587
* Initializes and starts a Node and reacts on the
8688
* main node lifecycle events
87-
*
89+
*
8890
* @param config
8991
*/
9092
async function runNode(config: Config) {
9193
const syncDataDir = config.getSyncDataDirectory()
9294
fs.ensureDirSync(syncDataDir)
93-
logger.info(`Sync data directory: ${syncDataDir}`)
94-
95-
logger.info('Initializing Ethereumjs client...')
95+
config.logger.info(`Sync data directory: ${syncDataDir}`)
96+
97+
config.logger.info('Initializing Ethereumjs client...')
9698
if (config.lightserv) {
97-
logger.info(`Serving light peer requests`)
99+
config.logger.info(`Serving light peer requests`)
98100
}
99101
const node = new Node({
100102
config,
101103
db: level(syncDataDir),
102104
})
103-
node.on('error', (err: any) => logger.error(err))
105+
node.on('error', (err: any) => config.logger.error(err))
104106
node.on('listening', (details: any) => {
105-
logger.info(`Listener up transport=${details.transport} url=${details.url}`)
107+
config.logger.info(`Listener up transport=${details.transport} url=${details.url}`)
106108
})
107109
node.on('synchronized', () => {
108-
logger.info('Synchronized')
110+
config.logger.info('Synchronized')
109111
})
110-
logger.info(`Connecting to network: ${config.common.chainName()}`)
112+
config.logger.info(`Connecting to network: ${config.common.chainName()}`)
111113
await node.open()
112-
logger.info('Synchronizing blockchain...')
114+
config.logger.info('Synchronizing blockchain...')
113115
await node.start()
114116

115117
return node
@@ -119,7 +121,7 @@ function runRpcServer(node: Node, config: Config) {
119121
const { rpcport, rpcaddr } = config
120122
const manager = new RPCManager(node, config)
121123
const server = new RPCServer(manager.getMethods())
122-
logger.info(`RPC HTTP endpoint opened: http://${rpcaddr}:${rpcport}`)
124+
config.logger.info(`RPC HTTP endpoint opened: http://${rpcaddr}:${rpcport}`)
123125
server.http().listen(rpcport)
124126

125127
return server
@@ -130,7 +132,7 @@ function runRpcServer(node: Node, config: Config) {
130132
*/
131133
async function run() {
132134
// give network id precedence over network name
133-
let chain: string | number
135+
let chain: string | number
134136
if (args.networkId) {
135137
chain = args.networkId
136138
} else {
@@ -140,16 +142,17 @@ async function run() {
140142
const common = new Common({ chain, hardfork: 'chainstart' })
141143
const config = new Config({
142144
common,
143-
logger,
144145
syncmode: args.syncmode,
145146
lightserv: args.lightserv,
146147
transports: args.transports,
147148
rpc: args.rpc,
148149
rpcport: args.rpcport,
149150
rpcaddr: args.rpcaddr,
151+
loglevel: args.loglevel,
150152
minPeers: args.minPeers,
151153
maxPeers: args.maxPeers,
152154
})
155+
logger = config.logger
153156

154157
// TODO: see todo below wrt resolving chain param parsing
155158
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -159,12 +162,12 @@ async function run() {
159162
const server = config.rpc ? runRpcServer(node, config) : null
160163

161164
process.on('SIGINT', async () => {
162-
logger.info('Caught interrupt signal. Shutting down...')
165+
config.logger.info('Caught interrupt signal. Shutting down...')
163166
if (server) server.http().close()
164167
await node.stop()
165-
logger.info('Exiting.')
168+
config.logger.info('Exiting.')
166169
process.exit()
167170
})
168171
}
169172

170-
run().catch((err) => logger.error(err))
173+
run().catch((err) => logger!.error(err))

lib/config.ts

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const os = require('os')
22
import Common from '@ethereumjs/common'
33
import { Logger } from 'winston'
4-
import { defaultLogger } from './logging'
4+
import { defaultLogger, getLogger } from './logging'
55
import { Libp2pServer, RlpxServer } from './net/server'
66
import { parseTransports } from './util'
77

@@ -12,12 +12,6 @@ export interface Options {
1212
* Default: chain 'mainnet' and hardfork 'chainstart'
1313
*/
1414
common?: Common
15-
/**
16-
* The logger instance with the log level set (winston)
17-
*
18-
* Default: Logger with loglevel 'debug'
19-
*/
20-
logger?: Logger
2115
/**
2216
* Synchronization mode ('fast' or 'light')
2317
*
@@ -49,20 +43,34 @@ export interface Options {
4943
servers?: (RlpxServer | Libp2pServer)[]
5044
/**
5145
* Enable the JSON-RPC server
52-
*
46+
*
5347
* Default: false
5448
*/
5549
rpc?: boolean
5650
/**
5751
* HTTP-RPC server listening port
58-
*
52+
*
5953
* Default: 8545
6054
*/
6155
rpcport?: number
6256
/**
6357
* HTTP-RPC server listening interface
6458
*/
6559
rpcaddr?: string
60+
/**
61+
* Logging verbosity
62+
*
63+
* Choices: ['error', 'warn', 'info', 'debug']
64+
* Default: 'info'
65+
*/
66+
loglevel?: string
67+
/**
68+
* A custom winston logger can be provided
69+
* if setting logging verbosity is not sufficient
70+
*
71+
* Default: Logger with loglevel 'info'
72+
*/
73+
logger?: Logger
6674
/**
6775
* Number of peers needed before syncing
6876
*
@@ -82,14 +90,14 @@ export class Config {
8290
// hardfork awareness is implemented within the library
8391
// Also a fix for https://github.com/ethereumjs/ethereumjs-vm/issues/757
8492
public static readonly COMMON_DEFAULT = new Common({ chain: 'mainnet', hardfork: 'chainstart' })
85-
public static readonly LOGGER_DEFAULT = defaultLogger
8693
public static readonly SYNCMODE_DEFAULT = 'fast'
8794
public static readonly LIGHTSERV_DEFAULT = false
8895
public static readonly DATADIR_DEFAULT = `${os.homedir()}/Library/Ethereum`
8996
public static readonly TRANSPORTS_DEFAULT = ['rlpx:port=30303', 'libp2p']
9097
public static readonly RPC_DEFAULT = false
9198
public static readonly RPCPORT_DEFAULT = 8545
9299
public static readonly RPCADDR_DEFAULT = 'localhost'
100+
public static readonly LOGLEVEL_DEFAULT = 'info'
93101
public static readonly MINPEERS_DEFAULT = 2
94102
public static readonly MAXPEERS_DEFAULT = 25
95103

@@ -102,6 +110,7 @@ export class Config {
102110
public readonly rpc: boolean
103111
public readonly rpcport: number
104112
public readonly rpcaddr: string
113+
public readonly loglevel: string
105114
public readonly minPeers: number
106115
public readonly maxPeers: number
107116

@@ -110,18 +119,44 @@ export class Config {
110119
constructor(options: Options = {}) {
111120
// TODO: map chainParams (and lib/util.parseParams) to new Common format
112121
this.common = options.common ?? Config.COMMON_DEFAULT
113-
this.logger = options.logger ?? Config.LOGGER_DEFAULT
114122
this.syncmode = options.syncmode ?? Config.SYNCMODE_DEFAULT
115123
this.lightserv = options.lightserv ?? Config.LIGHTSERV_DEFAULT
116124
this.transports = options.transports ?? Config.TRANSPORTS_DEFAULT
117125
this.datadir = options.datadir ?? Config.DATADIR_DEFAULT
118126
this.rpc = options.rpc ?? Config.RPC_DEFAULT
119127
this.rpcport = options.rpcport ?? Config.RPCPORT_DEFAULT
120128
this.rpcaddr = options.rpcaddr ?? Config.RPCADDR_DEFAULT
129+
this.loglevel = options.loglevel ?? Config.LOGLEVEL_DEFAULT
121130
this.minPeers = options.minPeers ?? Config.MINPEERS_DEFAULT
122131
this.maxPeers = options.maxPeers ?? Config.MAXPEERS_DEFAULT
123132

133+
if (options.logger) {
134+
if (options.loglevel) {
135+
throw new Error('Config initialization with both logger and loglevel options not allowed')
136+
}
137+
138+
// Logger option takes precedence
139+
this.logger = options.logger
140+
} else {
141+
// Use the default logger to keep the logger deactivation in the test working
142+
// along these lines in the test files
143+
// import { defaultLogger } from '../../lib/logging'
144+
// defaultLogger.silent = true
145+
// TODO: find a more generic solution here
146+
if (this.loglevel === 'info') {
147+
this.logger = defaultLogger
148+
} else {
149+
this.logger = getLogger({ loglevel: this.loglevel })
150+
}
151+
}
152+
124153
if (options.servers) {
154+
if (options.transports) {
155+
throw new Error(
156+
'Config initialization with both servers and transports options not allowed'
157+
)
158+
}
159+
125160
// Servers option takes precedence
126161
this.servers = options.servers
127162
} else {

lib/logging.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ export function getLogger(options = { loglevel: 'info' }) {
4949
return logger
5050
}
5151

52-
export const defaultLogger = getLogger({ loglevel: 'debug' })
52+
export const defaultLogger = getLogger({ loglevel: 'info' })

lib/node.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ export default class Node extends events.EventEmitter {
3232
this.services = [
3333
this.config.syncmode === 'fast'
3434
? new FastEthereumService({
35-
config: this.config,
36-
db: options.db,
37-
})
35+
config: this.config,
36+
db: options.db,
37+
})
3838
: new LightEthereumService({
39-
config: this.config,
40-
db: options.db,
41-
}),
39+
config: this.config,
40+
db: options.db,
41+
}),
4242
]
4343
this.opened = false
4444
this.started = false
@@ -115,4 +115,4 @@ export default class Node extends events.EventEmitter {
115115
server(name: string) {
116116
return this.config.servers.find((s) => s.name === name)
117117
}
118-
}
118+
}

test/blockchain/chain.spec.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,6 @@ import { Buffer } from 'buffer' //eslint-disable-line @typescript-eslint/no-unus
1212
import { Config } from '../../lib/config'
1313

1414
tape('[Chain]', (t) => {
15-
t.test('should test object creation without logger', (t) => {
16-
t.equal(new Chain({ config: new Config() }).config.logger, defaultLogger)
17-
18-
t.end()
19-
})
20-
2115
t.test('should test blockchain DB is initialized', (t) => {
2216
const chain = new Chain({ config: new Config() }) // eslint-disable-line no-new
2317

0 commit comments

Comments
 (0)