Code Monkey home page Code Monkey logo

vip-go-node's Introduction

VIP Go Node Helpers

This package provides modules to help run Node.js applications on VIP Go.

Install

npm install --save @automattic/vip-go

Modules

The following is a list of modules included in this package:

  • server: a server that wraps your request handler or express app behind an easy to use interface
  • logger: a ready to use logger for your node applications with Kibana integration out of the box
  • newrelic: New Relic integration for applications on VIP Go
  • redis: a helper library to instantiate a Redis client compatible with VIP Go

Usage

const { server, logger, newrelic, redis } = require( '@automattic/vip-go' );

Please refer the documentation for each module (server | logger | newrelic) | redis) to learn more about how to use it.

New Relic is no longer a peer dependency of this module. Please remember to install New Relic separately if your app requires it.

Development

Using hooks

For development, we have some hooks running before each commit/push. To use them, execute the following command inside the repo after cloning it:

git config core.hooksPath hooks

Running tests

To run tests locally, make sure the Docker container is up and running:

docker-compose up

vip-go-node's People

Contributors

chriszarate avatar dependabot[bot] avatar elazzabi avatar gudmdharalds avatar joshbetz avatar mjangda avatar nickdaugherty avatar renovate-bot avatar renovate[bot] avatar saroshaga avatar simonwheatley avatar vaurdan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vip-go-node's Issues

CI Integration

We should wire up CI to run list + tests for all PRs and merges.

Discussion around removing winston

When we started this package, our first helper was the logger and thus, we introduced winston as a dependency to this package.

However, lot of our users are using the server or newrelic helpers and don't need winston

I suggest we move winston to a peerDependency or remove it all together and ask clients to install it explicitly

JSON log format should be fully JSON

I've noticed that the format for the JSON log is a mix of string text and JSON like so

// => The format is: <timestamp> <namespace> JSON
// => 2018-08-03T09:54:07.013Z application:application_type {"message":"This is a log from my application","level":"info","timestamp":"2018-08-03T09:54:07.013Z","app":"application","app_type":":application_type" // etc // }

But for almost all examples of JSON logging for logstash I've seen, the format is always fully JSON.
See the example JSON logs for use with logstash here.

I think this makes sense as logstash would not need a custom parser to fish out the JSON part from the string text part. So to support better parsing and search on logstash, we should do the same as well.

See also Extracting fields and Wrangling Data

Transpile code before publishing to npm

Current behavior:

Generally, node_modules folder isn't transpiled and we do not transpile the code before publishing it on npm. This will create a mess for the users

Expected behavior:

Transpiled code pushed to npm

Steps to correct the bug:

Add a transpile step before publishing to npm

Add Redis helpers

In some internal apps, we have a helper library to instantiate a Redis client. This will be helpful to others as well and should be made available here. @nickdaugherty noted that we may want to update that lib to use ioredis instead though before opening it up for use.

We should also include some utility functions to get the host/port/password from the appropriate env vars so apps don't have to worry about those implementation details.

Dependency Dashboard

This issue provides visibility into Renovate updates and their statuses. Learn more

Rate Limited

These updates are currently rate limited. Click on a checkbox below to force their creation now.

  • Update dependency express to v4.17.3
  • Update actions/checkout action to v3
  • Update actions/setup-node action to v3
  • Update dependency chalk to v5
  • Update dependency eslint to v8
  • Update dependency eslint-plugin-flowtype to v8
  • Update dependency execa to v6
  • Update dependency ioredis to v5

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.


  • Check this box to trigger a request for Renovate to run again on this repository

Readme for logger is missing Options part

There are some options not documented in the README: transport, cluster ...

We need a new part (called Options?) where we can provide extra information on those ^

Readme example / instructions for New Relic has an ancient npm version

Expected/Desired Behavior

  1. When following the instructions, I get no weird errors

Actual Behavior

When following the instructions, a node version complaint is issues because New Relic 4.x is not compatible with newer and supported versions of node.js

Steps to Reproduce the Problem

  1. yarn add newrelic@^4.8.0
  2. A message saying the engine node is incompatible with this module

(Optional) Additional notes

Generally, perhaps version requirements should be omitted from the readme unless absolutely necessary, and if so, kept up to date.

Add native support for Node Cluster in Logger

Node Cluster lets us run N workers for a Node app, for better fault tolerance and utilization of available CPU cores.

Our logger should natively detect when Cluster is being used and log information about the worker process, if applicable.

app_process: appProcess,

https://nodejs.org/api/cluster.html

Essentially:

const cluster = require( 'cluster' );

let appWorker = 'none';

if ( cluster.isMaster ) {
  appWorker = 'master';
} else if ( cluster.isWorker ) {
  appWorker = `worker_${ cluster.worker.id }`;
}

// ... add `app_worker: appWorker` to logged entry

Remove New Relic from peerDependencies

Since NR is an optional part of this module, we shouldn't add it to peerDependencies because that incorrectly indicates that it's required and throws an npm warning on every project using this repo w/o the NR piece.

The warnings aren't terrible, but there are build scripts out there (such as those that come out of the box with create-react-app, I believe) that treat any warnings as errors when building for production, so this package breaks builds on projects that aren't using New Relic.

Instead of enforcing it programmatically, we should ensure the docs make that clear. We already have custom error handling if newrelic isn't installed, here:

try {
newrelic = require( 'newrelic' );
} catch ( err ) {
throw new Error( `The 'newrelic' package could not be imported.
Please make sure the package is installed and available.
Details: ${ err.message }` );
}

Add X-Powered-By header

  • Add an X-Powered-By: WordPress.com VIP header to all requests served by the server module

  • Add a way to easily opt out for clients if they don't want the header

Simple HTTP Server

Initially started this in #1 but noting requirements:

  • Should boot up the server at PORT.
  • Should accept requestHandler to allow someone to pass in their own server framework like express.
  • Should return the created server.
  • Should add a request handler for the /cache-healthcheck? path and return a 200 response.

Bonus: Should have cluster support (see src/server.js in public api codebase as an example).

Possible 'Headers already sent' errors

This was spotted when trying to migrate vip-ui to the server module.

Current behavior:

Our current matcher for the health check route will respond to the client and pass the request along. If the client is using a general matcher for routes, i.e. app.get('*'), this will trigger another HTTP response and cause an Headers already sent error

Desired behavior:

Respond with our matcher only

Steps to correct the bug:

Make the handler return after responding instead of passing the call

Using string interpolation in log messages seems to break logging

Example:

log.info( 'Testing string interpolation, %o', { some: 'fancy', object: { with: 'nested' } } );

The log file and logstash then get really confused and everything is jumbled. I haven't really dug into what's wrong here, but I think here is a good place to start looking:

// If formatting is used and a custom object is provided, winston
// will move the object to meta. Adding the info.meta helps flatten the object
return Object.assign( info, output, info.meta );

Dependency deprecation warning: babel-preset-es2015 (npm)

On registry https://registry.npmjs.org/, the "latest" version (v6.24.1) of dependency babel-preset-es2015 has the following deprecation notice:

๐Ÿ™Œ Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!

Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.

Please take the actions necessary to rename or substitute this deprecated package and commit to your base branch. If you wish to ignore this deprecation warning and continue using babel-preset-es2015 as-is, please add it to your ignoreDeps array in Renovate config before closing this issue, otherwise another issue will be recreated the next time Renovate runs.

Affected package file(s): package.json

Would you like to disable Renovate's deprecation warning issues? Add the following to your config:

"suppressNotifications": ["deprecationWarningIssues"]

Add preflight checks

Possibly a script (e.g. npx vip-go-preflight-checks) that can be run to verify that the app meets all the necessary requirements to work smoothly on VIP Go.

preflight-checks: Make a copy of the app

Rather than modifying the app in the current folder, make a copy of it (minus node_modules) and run the checks on that instead. This would avoid conflicts caused by the checks which can be frustrating or misleading.

preflight-checks: Add VIP_GO_APP_ID env var when running checks

Expected/Desired Behavior

On the VIP environment, there is a VIP_GO_APP_ID environment available, which some apps make use of to detect the environment (and conditionally run builds, etc).

We need to emulate production as closely as possible.

Actual Behavior

VIP_GO_APP_ID is not set, which means conditional logic in package.json and the apps themselves will behave differently in the preflight tests than they do in production.

Steps to Reproduce the Problem

  1. Have a package.json with a line like this: "build": "if [ -z $VIP_GO_APP_ID ]; then npm run webpack; else exit 0; fi",
  2. Run the preflight tests
  3. Note that the npm run webpack line tries to execute, when it wouldn't in production - this is the bug

Logging lib

Currently we're using the debug package across our apps. However, Node apps on Go require the logging format to be very specific which is a bit harder to do with debug. It also doesn't support error levels so we'd need to add a wrapper library to add that functionality.

We should extend winston (or a similar library) with a custom transport that pipes to stdOut and matches the expected output by our Logstash parser.

We should also have a separate transport for local use as well (since JSON isn't very easy to read :)).

The logs need to be formatted as JSON with a specific set of fields. This allows the log parser to actually pick them up and we can them access them via Kibana.

See src/logger/index.js in the happychat repo for an example of what the output should look like.

Default uncaughtException handler

If an app crashes with uncaughtException we need to make sure we log it.

If we add in cluster support (as noted in #4), the error message should include specifics around which worker caused the fatal.

Log debug messages to console outside prod

AFAICT the default Console transport for winston doesn't send debug level messages to the console - we should probably change that for local dev (?).

We should think about this more though - we could go with an approach like what the debug npm package does (read what to log from env var), or maybe have the log level in the env var.

HTTP: Add Cluster support

Via @nickdaugherty in #8 (comment)

Oh another consideration, and something we don't necessarily have to support in this PR, is using Node Cluster for more resilient and performant apps out of the box.

The library could abstract away and hide the details of setting up a clustered process, though maybe should only be enabled with an option since it requires the application to be written with multi process in mind.

For an example of how we're using Cluster on Go now (but sadly only using a single worker), see the public API repo.

Make newlic package a peer dependency

We shouldn't bother installing it if it's not being used. We should make the calling application handle the installation instead.

Things to do:

  • Switch to a peer dependency
  • If possible, gracefully fail with error if newrelic not installed
  • Update docs on how to install newrelic as a peer dependency

Prepare 0.2.0

All the code is ready to go. A couple left things to do:

  • Fix (New Relic) build issue on the Go side
  • Prepare changelog
  • Publish!

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Preset name not found within published preset config (monorepo:babel6). Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Add ability to easily purge a single URL

Expected/Desired Behavior

Add ability for apps to easily purge a URL from the VIP edge caches.

Something akin to the wpcom_vip_purge_edge_cache_for_url() PHP function.

Actual Behavior

Currently there is no support for purging a URL.

Steps to Reproduce the Problem

Only workaround for now is to have a Node app call a WP app and use the above PHP function, or for the Node app to make the PURGE request directly, once the correct URLs and args have been established.

Allow setting log transports globally

It would be nice to have a way to globally set the transports, (overridable per-instance).

The main use-case that comes up is tests - during CI tests the logs should probably be disabled, but currently there isn't a way to do that without adding conditional transports to every instance of the logger.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.