Skip to content
This repository was archived by the owner on Jun 3, 2019. It is now read-only.

Commit 111a170

Browse files
oyeanujSteven Truesdell
authored andcommitted
Server logging enhancements (#508)
* Improving logging experience + consolidating to single log function * Adding pretty-error for more readable node error stack * Fix eslint error * Logging requests received * Re-commit logging requests received
1 parent 338ecfd commit 111a170

File tree

7 files changed

+88
-27
lines changed

7 files changed

+88
-27
lines changed

config/utils/envVars.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
*/
88

99
import appRootDir from 'app-root-dir';
10-
import colors from 'colors/safe';
1110
import dotenv from 'dotenv';
1211
import fs from 'fs';
1312
import path from 'path';
1413

1514
import ifElse from '../../shared/utils/logic/ifElse';
1615
import removeNil from '../../shared/utils/arrays/removeNil';
1716

17+
import { log } from '../../internal/utils';
18+
1819
// PRIVATES
1920

2021
function registerEnvFile() {
@@ -40,7 +41,11 @@ function registerEnvFile() {
4041
// If we found an env file match the register it.
4142
if (envFilePath) {
4243
// eslint-disable-next-line no-console
43-
console.log(colors.bgBlue.white(`==> Registering environment variables from: ${envFilePath}`));
44+
log({
45+
title: 'server',
46+
level: 'special',
47+
message: `Registering environment variables from: ${envFilePath}`,
48+
});
4449
dotenv.config({ path: envFilePath });
4550
}
4651
}

internal/utils.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,21 @@ export function log(options) {
2626
}
2727

2828
const level = options.level || 'info';
29-
const msg = `==> ${title} -> ${options.message}`;
29+
const msg = `${title}: ${options.message}`;
3030

3131
switch (level) {
32-
case 'warn': console.log(colors.yellow(msg)); break;
33-
case 'error': console.log(colors.bgRed.white(msg)); break;
32+
case 'warn':
33+
console.log(colors.yellow(msg));
34+
break;
35+
case 'error':
36+
console.log(colors.bgRed.white(msg));
37+
break;
38+
case 'special':
39+
console.log(colors.italic.cyan(msg));
40+
break;
3441
case 'info':
35-
default: console.log(colors.green(msg));
42+
default:
43+
console.log(colors.green.dim(msg));
3644
}
3745
}
3846

internal/webpack/configFactory.js

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import path from 'path';
66
import webpack from 'webpack';
77
import WebpackMd5Hash from 'webpack-md5-hash';
88

9-
import { happyPackPlugin } from '../utils';
9+
import { happyPackPlugin, log } from '../utils';
1010
import { ifElse } from '../../shared/utils/logic';
1111
import { mergeDeep } from '../../shared/utils/objects';
1212
import { removeNil } from '../../shared/utils/arrays';
@@ -44,18 +44,20 @@ export default function webpackConfigFactory(buildOptions) {
4444
const ifDevClient = ifElse(isDev && isClient);
4545
const ifProdClient = ifElse(isProd && isClient);
4646

47-
console.log(
48-
`==> Creating ${isProd
47+
log({
48+
level: 'info',
49+
title: 'Webpack',
50+
message: `Creating ${isProd
4951
? 'an optimised'
5052
: 'a development'} bundle configuration for the "${target}"`,
51-
);
53+
});
5254

5355
const bundleConfig =
5456
isServer || isClient
5557
? // This is either our "server" or "client" bundle.
56-
config(['bundles', target])
58+
config(['bundles', target])
5759
: // Otherwise it must be an additional node bundle.
58-
config(['additionalNodeBundles', target]);
60+
config(['additionalNodeBundles', target]);
5961

6062
if (!bundleConfig) {
6163
throw new Error('No bundle configuration exists for target:', target);
@@ -124,9 +126,9 @@ export default function webpackConfigFactory(buildOptions) {
124126

125127
target: isClient
126128
? // Only our client bundle will target the web as a runtime.
127-
'web'
129+
'web'
128130
: // Any other bundle must be targetting node as a runtime.
129-
'node',
131+
'node',
130132

131133
// Ensure that webpack polyfills the following node features for use
132134
// within any bundles that are targetting node as a runtime. This will be
@@ -517,12 +519,12 @@ export default function webpackConfigFactory(buildOptions) {
517519
// paths used on the client.
518520
publicPath: isDev
519521
? // When running in dev mode the client bundle runs on a
520-
// seperate port so we need to put an absolute path here.
521-
`http://${config('host')}:${config('clientDevServerPort')}${config(
522-
'bundles.client.webPath',
523-
)}`
522+
// seperate port so we need to put an absolute path here.
523+
`http://${config('host')}:${config('clientDevServerPort')}${config(
524+
'bundles.client.webPath',
525+
)}`
524526
: // Otherwise we just use the configured web path for the client.
525-
config('bundles.client.webPath'),
527+
config('bundles.client.webPath'),
526528
// We only emit files when building a web bundle, for the server
527529
// bundle we only care about the file loader being able to create
528530
// the correct asset URLs.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"modernizr": "3.5.0",
7070
"normalize.css": "7.0.0",
7171
"offline-plugin": "4.8.3",
72+
"pretty-error": "2.1.1",
7273
"prop-types": "15.5.10",
7374
"react": "15.6.1",
7475
"react-async-bootstrapper": "1.1.1",

server/index.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import serviceWorker from './middleware/serviceWorker';
1111
import offlinePage from './middleware/offlinePage';
1212
import errorHandlers from './middleware/errorHandlers';
1313
import config from '../config';
14+
import { log } from '../internal/utils';
1415

1516
// Create our express based server.
1617
const app = express();
@@ -43,14 +44,44 @@ app.use(config('bundles.client.webPath'), clientBundle);
4344
app.use(express.static(pathResolve(appRootDir.get(), config('publicAssetsPath'))));
4445

4546
// The React application middleware.
46-
app.get('*', reactApplication);
47+
app.get('*', (request, response) => {
48+
log({
49+
title: 'Request',
50+
level: 'special',
51+
message: `Received for "${request.url}"`,
52+
});
53+
54+
return reactApplication(request, response);
55+
});
4756

4857
// Error Handler middlewares.
4958
app.use(...errorHandlers);
5059

5160
// Create an http listener for our express app.
5261
const listener = app.listen(config('port'), () =>
53-
console.log(`Server listening on port ${config('port')}`));
62+
log({
63+
title: 'server',
64+
level: 'special',
65+
message: `✓
66+
67+
${config('welcomeMessage')}
68+
69+
${config('htmlPage.defaultTitle')} is ready!
70+
71+
with
72+
73+
Service Workers: ${config('serviceWorker.enabled')}
74+
Polyfills: ${config('polyfillIO.enabled')} (${config('polyfillIO.features').join(', ')})
75+
76+
Server is now listening on Port ${config('port')}
77+
You can access it in the browser at http://${config('host')}/${config('port')}
78+
Press Ctrl-C to stop.
79+
80+
81+
82+
`,
83+
}),
84+
);
5485

5586
// We export the listener as it will be handy for our development hot reloader,
5687
// or for exposing a general extension layer for application customisations.

server/middleware/errorHandlers.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
/* eslint-disable no-console */
22
/* eslint-disable no-unused-vars */
33

4+
const prettyError = require('pretty-error').start();
5+
6+
// Configure prettyError to simplify the stack trace:
7+
8+
// skip events.js and http.js and similar core node files
9+
prettyError.skipNodeFiles();
10+
11+
// skip all the trace lines about express` core and sub-modules
12+
prettyError.skipPackage('express');
13+
414
const errorHandlersMiddleware = [
515
/**
616
* 404 errors middleware.
@@ -21,8 +31,7 @@ const errorHandlersMiddleware = [
2131
*/
2232
function unexpectedErrorMiddleware(err, req, res, next) {
2333
if (err) {
24-
console.log(err);
25-
console.log(err.stack);
34+
console.log(prettyError.render(err));
2635
}
2736
res.status(500).send('Sorry, an unexpected error occurred.');
2837
},

server/middleware/reactApplication/index.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import config from '../../../config';
99

1010
import ServerHTML from './ServerHTML';
1111
import DemoApp from '../../../shared/components/DemoApp';
12+
import { log } from '../../../internal/utils';
1213

1314
/**
1415
* React application middleware, supports server side rendering.
@@ -26,7 +27,11 @@ export default function reactApplicationMiddleware(request, response) {
2627
if (config('disableSSR')) {
2728
if (process.env.BUILD_FLAG_IS_DEV === 'true') {
2829
// eslint-disable-next-line no-console
29-
console.log('==> Handling react route without SSR');
30+
log({
31+
title: 'Server',
32+
level: 'info',
33+
message: `Handling react route without SSR: ${request.url}`,
34+
});
3035
}
3136
// SSR is disabled so we will return an "empty" html page and
3237
// rely on the client to initialize and render the react application.
@@ -78,10 +83,10 @@ export default function reactApplicationMiddleware(request, response) {
7883
.status(
7984
reactRouterContext.missed
8085
? // If the renderResult contains a "missed" match then we set a 404 code.
81-
// Our App component will handle the rendering of an Error404 view.
82-
404
86+
// Our App component will handle the rendering of an Error404 view.
87+
404
8388
: // Otherwise everything is all good and we send a 200 OK status.
84-
200,
89+
200,
8590
)
8691
.send(`<!DOCTYPE html>${html}`);
8792
});

0 commit comments

Comments
 (0)