Colored Keys Logger (Winston)
File Location
What It Is
Library: Winston
Purpose
Made for:
- Readable console output during development
- Structured JSON logs in files for production/post-mortems
- Quiet tests by default (opt-in to see logs)
TL;DR Usage
With Module Tag
import { createLogger } from '../lib/logger/logger';
const log = createLogger('deploy'); // adds module tag
log.info('Starting deploy…');
log.debug('Config loaded', { network: process.env.HARDHAT_NETWORK });
try {
// …
} catch (err) {
log.error('Deploy failed', err as Error); // error details are captured in meta
}
Without Module Tag
import logger from '../lib/logger/logger';
logger.warn('Low balance for gas', { address: '0xabc…' });
Where Logs Go
Console (enabled unless muted in “test mode”)
- Colorized level
- HH:mm:ss timestamp
- Optional [module]
- Message
Not strictly single-line: message is on one line, but metadata is pretty-printed and may span multiple lines.
Files (when useFileLogs
is true)
logs/contracts.log
: Records entries at or above configured global levellogs/error.log
: Error level only
Rotation
- 5 MB per file
- 3 files kept
- Timestamp is time-only: “HH:mm:ss”
Format Details
Console Format
{timestamp} [optional-module] [level]: message {stringifiedMeta}
Example
12:04:31 [deploy] [info]: Starting deploy…
12:04:31 [deploy] [debug]: Config loaded {
"network": "sepolia",
"gasPrice": "15 gwei"
}
12:04:32 [deploy] [error]: Deploy failed {
"stack": "Error: nonce too low\n at ...",
"message": "nonce too low",
"name": "Error"
}
File Format (JSON)
{
"level":"error",
"message":"Deploy failed",
"service":"colored-keys",
"network":"sepolia",
"module":"deploy",
"timestamp":"12:04:32",
"stack":"Error: nonce too low\n at ...",
"name":"Error"
}
Environment Variables
Variable | Values | Effect |
---|---|---|
NODE_ENV | production / other | Default log level: info in production, debug otherwise |
LOG_LEVEL | error warn info http verbose debug silly | Overrides global logger level |
HARDHAT_NETWORK | e.g. hardhat sepolia | Adds network to default metadata |
FORCE_DEV_FILE_LOGS | true / false | Enables file logging in development |
DISABLE_FILE_LOGS | true / false | Disables file logging in all environments |
SHOW_TEST_LOGS | true / false | Unmutes console transport in test mode |
File-logging Decision
useFileLogs = !DISABLE_FILE_LOGS && (FORCE_DEV_FILE_LOGS || NODE_ENV === 'production')
”Test Mode” Conditions
Console is silent when:
NODE_ENV === 'test' OR HARDHAT_NETWORK === 'hardhat'
Unless SHOW_TEST_LOGS === 'true'
Default Metadata
Every log includes:
{
"service": "colored-keys",
"network": process.env.HARDHAT_NETWORK || "hardhat"
}
createLogger('my-module')
adds:
{
"module": "my-module"
}
API Surface
Available Methods
error
warn
info
http
verbose
debug
silly
Operational Notes
⚠️
- Log directory (
./logs
) is created automatically - Avoid logging huge objects in tight loops
- Ensure
logs/
is ignored in version control
Extending the Logger
import winston from 'winston';
import logger from '../lib/logger/logger';
logger.add(new winston.transports.Http({
host: 'log-collector.internal',
path: '/ingest',
ssl: true,
level: 'info',
}));
Troubleshooting
Common Issues
-
No log files in development?
- Set
FORCE_DEV_FILE_LOGS=true
- Or run with
NODE_ENV=production
- Set
-
Empty test output?
- Set
SHOW_TEST_LOGS=true
- Set
-
Missing module name?
- Use
createLogger('your-module')
- Use
-
Need different verbosity?
- Set
LOG_LEVEL
(debug for max detail, info for production)
- Set