Skip to content

Commit ece9906

Browse files
committed
feat: use winston logger for app level logs
Ticket: WP-4645
1 parent 7778f2f commit ece9906

File tree

4 files changed

+100
-46
lines changed

4 files changed

+100
-46
lines changed

src/enclavedApp.ts

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* @prettier
33
*/
44
import express from 'express';
5-
import debug from 'debug';
65
import https from 'https';
76
import http from 'http';
87
import morgan from 'morgan';
@@ -20,28 +19,25 @@ import {
2019
prepareIpc,
2120
readCertificates,
2221
} from './shared/appUtils';
23-
24-
const debugLogger = debug('enclaved:express');
22+
import logger from './logger';
2523

2624
/**
2725
* Create a startup function which will be run upon server initialization
2826
*/
2927
export function startup(config: EnclavedConfig, baseUri: string): () => void {
3028
return function () {
31-
/* eslint-disable no-console */
32-
console.log('BitGo Enclaved Express running');
33-
console.log(`Base URI: ${baseUri}`);
34-
console.log(`TLS Mode: ${config.tlsMode}`);
35-
console.log(`mTLS Enabled: ${config.tlsMode === TlsMode.MTLS}`);
36-
console.log(`Request Client Cert: ${config.mtlsRequestCert}`);
37-
console.log(`Reject Unauthorized: ${config.mtlsRejectUnauthorized}`);
38-
/* eslint-enable no-console */
29+
logger.info('BitGo Enclaved Express running');
30+
logger.info(`Base URI: ${baseUri}`);
31+
logger.info(`TLS Mode: ${config.tlsMode}`);
32+
logger.info(`mTLS Enabled: ${config.tlsMode === TlsMode.MTLS}`);
33+
logger.info(`Request Client Cert: ${config.mtlsRequestCert}`);
34+
logger.info(`Reject Unauthorized: ${config.mtlsRejectUnauthorized}`);
3935
};
4036
}
4137

4238
function isTLS(config: EnclavedConfig): boolean {
4339
const { keyPath, crtPath, tlsKey, tlsCert, tlsMode } = config;
44-
console.log('TLS Configuration:', {
40+
logger.debug('TLS Configuration:', {
4541
tlsMode,
4642
hasKeyPath: Boolean(keyPath),
4743
hasCrtPath: Boolean(crtPath),
@@ -64,12 +60,12 @@ async function createHttpsServer(
6460
if (tlsKey && tlsCert) {
6561
key = tlsKey;
6662
cert = tlsCert;
67-
console.log('Using TLS key and cert from environment variables');
63+
logger.info('Using TLS key and cert from environment variables');
6864
} else if (keyPath && crtPath) {
6965
const certificates = await readCertificates(keyPath, crtPath);
7066
key = certificates.key;
7167
cert = certificates.cert;
72-
console.log(`Using TLS key and cert from files: ${keyPath}, ${crtPath}`);
68+
logger.info(`Using TLS key and cert from files: ${keyPath}, ${crtPath}`);
7369
} else {
7470
throw new Error('Failed to get TLS key and certificate');
7571
}
@@ -127,12 +123,12 @@ export function createBaseUri(config: EnclavedConfig): string {
127123
* Create and configure the express application
128124
*/
129125
export function app(cfg: EnclavedConfig): express.Application {
130-
debugLogger('app is initializing');
126+
logger.debug('app is initializing');
131127

132128
const app = express();
133129

134130
setupLogging(app, cfg);
135-
debugLogger('logging setup');
131+
logger.debug('logging setup');
136132

137133
// Add custom morgan token for mTLS client certificate
138134
morgan.token('remote-user', function (req: express.Request) {
@@ -146,7 +142,7 @@ export function app(cfg: EnclavedConfig): express.Application {
146142
routes.setupRoutes(app);
147143

148144
// Add error handler
149-
app.use(createErrorHandler(debugLogger));
145+
app.use(createErrorHandler(logger));
150146

151147
return app;
152148
}

src/logger.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import winston from "winston";
2+
3+
// Define log levels
4+
const levels = {
5+
error: 0,
6+
warn: 1,
7+
info: 2,
8+
http: 3,
9+
debug: 4,
10+
};
11+
12+
// Define level based on environment
13+
const level = () => {
14+
const env = process.env.NODE_ENV || "development";
15+
const isDevelopment = env === "development";
16+
return isDevelopment ? "debug" : "warn";
17+
};
18+
19+
// Define colors for each level
20+
const colors = {
21+
error: "red",
22+
warn: "yellow",
23+
info: "green",
24+
http: "magenta",
25+
debug: "white",
26+
};
27+
28+
// Add colors to winston
29+
winston.addColors(colors);
30+
31+
// Define the format for the logs
32+
const format = winston.format.combine(
33+
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss:ms" }),
34+
winston.format.colorize({ all: true }),
35+
winston.format.printf(
36+
(info) => `${info.timestamp} ${info.level}: ${info.message}`
37+
)
38+
);
39+
40+
// Define which transports the logger must use
41+
const transports = [
42+
// Console transport
43+
new winston.transports.Console(),
44+
// Error log file transport
45+
new winston.transports.File({
46+
filename: "logs/error.log",
47+
level: "error",
48+
}),
49+
// All logs file transport
50+
new winston.transports.File({ filename: "logs/all.log" }),
51+
];
52+
53+
// Create the logger instance
54+
const logger = winston.createLogger({
55+
level: level(),
56+
levels,
57+
format,
58+
transports,
59+
});
60+
61+
export default logger;

src/masterExpressApp.ts

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* @prettier
33
*/
44
import express from 'express';
5-
import debug from 'debug';
65
import https from 'https';
76
import http from 'http';
87
import superagent from 'superagent';
@@ -28,22 +27,20 @@ import { ProxyAgent } from 'proxy-agent';
2827
import { promiseWrapper } from './routes';
2928
import pjson from '../package.json';
3029
import { handleGenerateWalletOnPrem } from './masterBitgoExpress/generateWallet';
30+
import logger from './logger';
3131

32-
const debugLogger = debug('master-express:express');
3332
const BITGOEXPRESS_USER_AGENT = `BitGoExpress/${pjson.version} BitGoJS/${version}`;
3433

3534
/**
3635
* Create a startup function which will be run upon server initialization
3736
*/
3837
export function startup(config: MasterExpressConfig, baseUri: string): () => void {
3938
return function () {
40-
/* eslint-disable no-console */
41-
console.log('BitGo Master Express running');
42-
console.log(`Base URI: ${baseUri}`);
43-
console.log(`Environment: ${config.env}`);
44-
console.log(`SSL Enabled: ${config.enableSSL}`);
45-
console.log(`Proxy Enabled: ${config.enableProxy}`);
46-
/* eslint-enable no-console */
39+
logger.info('BitGo Master Express running');
40+
logger.info(`Base URI: ${baseUri}`);
41+
logger.info(`Environment: ${config.env}`);
42+
logger.info(`SSL Enabled: ${config.enableSSL}`);
43+
logger.info(`Proxy Enabled: ${config.enableProxy}`);
4744
};
4845
}
4946

@@ -123,12 +120,12 @@ async function createHttpsServer(
123120
if (sslKey && sslCert) {
124121
key = sslKey;
125122
cert = sslCert;
126-
console.log('Using SSL key and cert from environment variables');
123+
logger.info('Using SSL key and cert from environment variables');
127124
} else if (keyPath && crtPath) {
128125
const certificates = await readCertificates(keyPath, crtPath);
129126
key = certificates.key;
130127
cert = certificates.cert;
131-
console.log(`Using SSL key and cert from files: ${keyPath}, ${crtPath}`);
128+
logger.info(`Using SSL key and cert from files: ${keyPath}, ${crtPath}`);
132129
} else {
133130
throw new Error('Failed to get SSL key and certificate');
134131
}
@@ -165,16 +162,17 @@ function setupMasterExpressRoutes(app: express.Application): void {
165162
setupHealthCheckRoutes(app, 'master express');
166163

167164
const cfg = config() as MasterExpressConfig;
168-
console.log('SSL Enabled:', cfg.enableSSL);
169-
console.log('Enclaved Express URL:', cfg.enclavedExpressUrl);
170-
console.log('Certificate exists:', Boolean(cfg.enclavedExpressSSLCert));
171-
console.log('Certificate length:', cfg.enclavedExpressSSLCert.length);
172-
console.log('Certificate content:', cfg.enclavedExpressSSLCert);
165+
logger.debug('SSL Configuration:', {
166+
sslEnabled: cfg.enableSSL,
167+
enclavedExpressUrl: cfg.enclavedExpressUrl,
168+
hasCertificate: Boolean(cfg.enclavedExpressSSLCert),
169+
certificateLength: cfg.enclavedExpressSSLCert.length,
170+
});
173171

174172
// Add enclaved express ping route
175173
app.post('/ping/enclavedExpress', async (req, res) => {
176174
try {
177-
console.log('Pinging enclaved express');
175+
logger.debug('Pinging enclaved express');
178176

179177
const response = await superagent
180178
.get(`${cfg.enclavedExpressUrl}/ping`)
@@ -192,7 +190,7 @@ function setupMasterExpressRoutes(app: express.Application): void {
192190
enclavedResponse: response.body,
193191
});
194192
} catch (error) {
195-
debugLogger('Failed to ping enclaved express:', error);
193+
logger.error('Failed to ping enclaved express:', { error });
196194
res.status(500).json({
197195
error: 'Failed to ping enclaved express',
198196
details: error instanceof Error ? error.message : String(error),
@@ -215,19 +213,19 @@ function setupMasterExpressRoutes(app: express.Application): void {
215213
});
216214
});
217215

218-
debugLogger('Master express routes configured');
216+
logger.debug('Master express routes configured');
219217
}
220218

221219
/**
222220
* Create and configure the express application for master express mode
223221
*/
224222
export function app(cfg: MasterExpressConfig): express.Application {
225-
debugLogger('master express app is initializing');
223+
logger.debug('master express app is initializing');
226224

227225
const app = express();
228226

229227
setupLogging(app, cfg);
230-
debugLogger('logging setup');
228+
logger.debug('logging setup');
231229

232230
setupDebugNamespaces(cfg.debugNamespace);
233231
setupCommonMiddleware(app, cfg);
@@ -236,7 +234,7 @@ export function app(cfg: MasterExpressConfig): express.Application {
236234
setupMasterExpressRoutes(app);
237235

238236
// Add error handler
239-
app.use(createErrorHandler(debugLogger));
237+
app.use(createErrorHandler());
240238

241239
return app;
242240
}

src/shared/appUtils.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
*/
44
import express from 'express';
55
import path from 'path';
6-
import debug from 'debug';
76
import https from 'https';
87
import http from 'http';
98
import morgan from 'morgan';
@@ -12,6 +11,7 @@ import timeout from 'connect-timeout';
1211
import bodyParser from 'body-parser';
1312
import _ from 'lodash';
1413
import pjson from '../../package.json';
14+
import logger from '../logger';
1515

1616
import { Config } from '../config';
1717

@@ -25,8 +25,7 @@ export function setupLogging(app: express.Application, config: Config): void {
2525
// create a write stream (in append mode)
2626
const accessLogPath = path.resolve(config.logFile);
2727
const accessLogStream = fs.createWriteStream(accessLogPath, { flags: 'a' });
28-
/* eslint-disable-next-line no-console */
29-
console.log('Log location: ' + accessLogPath);
28+
logger.info(`Log location: ${accessLogPath}`);
3029
// setup the logger
3130
middleware = morgan('combined', { stream: accessLogStream });
3231
} else {
@@ -42,8 +41,8 @@ export function setupLogging(app: express.Application, config: Config): void {
4241
export function setupDebugNamespaces(debugNamespace?: string[]): void {
4342
if (_.isArray(debugNamespace)) {
4443
for (const ns of debugNamespace) {
45-
if (ns && !debug.enabled(ns)) {
46-
debug.enable(ns);
44+
if (ns) {
45+
logger.debug(`Enabling debug namespace: ${ns}`);
4746
}
4847
}
4948
}
@@ -73,14 +72,14 @@ export function setupCommonMiddleware(app: express.Application, config: Config):
7372
/**
7473
* Create error handling middleware
7574
*/
76-
export function createErrorHandler(debugLogger: debug.Debugger) {
75+
export function createErrorHandler() {
7776
return function (
7877
err: any,
7978
req: express.Request,
8079
res: express.Response,
8180
_next: express.NextFunction,
8281
) {
83-
debugLogger('Error: ' + (err && err.message ? err.message : String(err)));
82+
logger.error('Error:', { error: err && err.message ? err.message : String(err) });
8483
const statusCode = err && err.status ? err.status : 500;
8584
const result = {
8685
error: err && err.message ? err.message : String(err),

0 commit comments

Comments
 (0)