Sunday, May 19, 2019

Enabling PM2 logging configuration for a Node.js application

I'm working on an application where PM2 manages the node processes that are started with npm.  The default PM2 log configuration was being used, so my task was to configure PM2 logs for added functionality such as:  log location, log rotation, timestamps in logs, etc.  This article will only be talking about how to configure a base ecosystem.config.js file for the PM2 log configuration to be recognized.

Environment:
CentOS Linux release 7.3.1611 (Core)
pm2 version 3.2.3
npm version 6.4.1
node version v8.16.0

Originally, PM2 was managing the node processes with npm start scripts with the following commands:
HOST=cherryshoe-dev.com pm2 start npm --name cherryshoe-dev -- run startdev
HOST=cherryshoe.com NODE_ENV=production pm2 start npm --name cherryshoe -- start

The --name "cherryshoe-dev" or "cherryshoe" is the name of the PM2 app name that is started.
The "-- run startdev" and the "-- start" were indicating to call the npm script located in package.json.  i.e. scripts.startdev or scripts.start in the below json snippet.

package.json looked like:
  "scripts": {
    "start": "npm run server",
    "startdev": "concurrently \"npm run server\" \"npm run client\"",
    "server": "cross-env node --max-old-space-size=8192 ./bin/cherryshoeServer.js",
    "client": "node cherryshoe-client.js"
  }

To enable PM2 logging configuration, the ecosystem file had to be configured to call the custom npm scripts appropriately, depending on the environment.

// If you look at a default ecosystem.config.js, you'll see that
// an assumption is made that each npm start command is the same.  The app has
// different npm custom scripts defined in package.json to run depending
// on the environment - so because of this, decided to have multiple apps
// and to call them by "pm2 start --only <app-name>" to start.
module.exports = {
  apps : [
    // Local DEV app config
    {
      name: 'cherryshoe-dev',
      script: 'npm',
      // call custom start dev npm script from package.json
      args: 'run startdev',

      env: {
        NODE_ENV: 'development'
      }
    },
    // PROD app config
    {
      name: 'cherryshoe',
      script: 'npm',
      args: 'start',

      env: {
        NODE_ENV: 'production'
      }
    }
  ],
};

After this change, the command to have PM2 manage the start of the node process with npm became easier:
HOST=cherryshoe-dev.com pm2 start --only cherryshoe-dev
HOST=cherryshoe-dev.com pm2 start --only cherryshoe

The main differences between the original and the new way are:
1.  npm is now started with the ecosystem file with the "script" and "args" attributes in the ecosystem.config.js file.  Since the npm script startdev is custom, it needs to be prepended with "run" or "run-script"
2.  --name from the old command is now named within the ecosystem file
3.  to start a specific app vs starting all apps defined in the ecosystem.config.js file, the new start command now only has to add the "--only <app-name>" attribute
4.  NODE_ENV from the old command is now configured with the ecosystem file
5. Decided to have multiple apps and to call them by --only <app-name> to start, which can call different npm scripts to start for different environments

Additional notes:
1.  Additional app configs could be added to the ecosystem.config.js file for additional environments
2.  Don't need to specify path to ecosystem file if it's in the current directory as where you are running
3.  We could also make this even more generic and have the ecosystem.config.js be controlled by a tool like ansible to replace variables as needed for each environment, so we wouldn't have to have an app for development and a separate one for production.

These articles helped a lot:

1 comment:

I appreciate your time in leaving a comment!