diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e9ae4fb --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,136 @@ +# **How to contribute to newrelic browser exporter** + +#### Table of Contents + +[Project structure](#project-structure) + * [application](#application) + * [plugins](#plugins) + +[How to set up a new metric](#How-to-set-up-a-new-metric) + +[Tests](#tests) + +## **Project structure** + +### **application**: +``` +─ src/ + ├── app/ + │ ├── routes/ + │ │ └── metrics.js + │ ├── router.js + │ └── server.js + └── index.js +``` + +**[src/app/routes/metrics.js](https://github.com/ContaAzul/newrelic_browser_exporter/blob/master/src/app/routes/metrics.js)** - It represents the `/metrics` route, which outputs the metrics from `register.metrics()` as a string in a Prometheus like format that can be consumed by a [Prometheus Client](https://github.com/siimon/prom-client#register). + +**[src/app/router.js](https://github.com/ContaAzul/newrelic_browser_exporter/blob/master/src/app/router.js)** - It registers all application routes. + +**[src/app/server.js](https://github.com/ContaAzul/newrelic_browser_exporter/blob/master/src/app/server.js)** - Contains the code to start and configure the application. + +**[src/index.js](https://github.com/ContaAzul/newrelic_browser_exporter/blob/master/src/index.js)** - It starts the application. + +### **plugins**: +``` +─ src/ + └── plugins/ + ├── newrelic_browser/ + │ ├── javascriptErrorsPercent/ + │ └── api-request.js + └── prometheus/ + └── charts/ + ├── default.js + └── gauge.js +``` + +**[newrelic_browser/](https://github.com/ContaAzul/newrelic_browser_exporter/tree/master/src/plugins/newrelic_browser)** - This plugin is responsible for pulling data from New Relic's API([api-request.js](https://github.com/ContaAzul/newrelic_browser_exporter/blob/master/src/plugins/newrelic_browser/api-request.js)) and exporting it as Prometheus charts. + +**[prometheus](https://github.com/ContaAzul/newrelic_browser_exporter/tree/master/src/plugins/prometheus)** - Contains the metric types used to create new Prometheus charts and exports the global Prometheus `registry`. To know which metrics are supported by Prometheus, see [metric types](https://prometheus.io/docs/concepts/metric_types/). + + +## **How to set up a new metric** + +Create a new folder inside `newrelic_browser` plugin. Inside this folder create a new file that must have a public method called `collectData` which must return a new `Promise`. The public method initializes and returns the chart: + +```js +// javascriptErrorsPercent.js +const GaugeChart = require('../../prometheus/charts/gauge'); +let JSErrorsGauge; + +const collectData = () => new Promise((resolve, reject) => { + if (!JSErrorsGauge) { + JSErrorsGauge = new GaugeChart({ + name: 'newrelic_browser_javascript_errors_percent', + help: 'return a percentage of pageviews with javascript errors', + }); + } + + ... +} + +module.exports = { + collectData, +}; +``` + +Please take a look at [Prometheus best practices](https://prometheus.io/docs/practices/naming/) to learn how to set up a chart's configurations properly. + +After configuring the chart, it is necessary to set up parameters such as `name` and `value` to retrieve specific metrics from [New Relic's API](https://rpm.newrelic.com/api/explore/applications/metric_data) + +```js +// javascriptErrorsPercent.js +const collectData = () => new Promise((resolve, reject) => { + ... + + const names = 'EndUser/errors'; + const values = 'error_percentage'; + + ... +} +``` + +Now that all parameters are set up, a request to New Relic's API can be done by calling `browser.collectData()`: + +```js +// javascriptErrorsPercent.js +const browser = require('../api-request'); + +const collectData = () => new Promise((resolve, reject) => { + //... + + browser + .collectData(names, values) + .then(response => { + onSuccess(response, resolve); + }) + .catch(reject); + +} +//... +``` + +A callback method should set the metrics collected from New Relic's API into the chart. Please, see prometheus [base units](https://prometheus.io/docs/practices/naming/#base-units) to know how to set values into charts according Prometheus patterns. + +```js +// javascriptErrorsPercent.js +function onSuccess(response, resolve) { + const percentage = JSON.parse(response) + .metric_data.metrics[0] + .timeslices[0] + .values + .error_percentage / 100; + + JSErrorsGauge.setValues(Number(percentage.toFixed(8))); + resolve(); +} +//... + +``` + +After setting values to the chart and resolving the `Promise`, New Relic's metrics are avaliable as Prometheus metrics in the `/metrics` endpoint. + +## **Tests** +Tests are written using [jest](https://jestjs.io/). In **most cases** new test scenarios are necessary for the new developed code. + +Run tests using `jest` or `npm test` commands. To see coverage, run `jest --coverage`. diff --git a/README.md b/README.md index fc3af32..b3beeda 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,23 @@ You will need [API_KEY](https://docs.newrelic.com/docs/apis/getting-started/intr ### **With docker:** To run: -``` +```cmd docker run -p 9595:9595 -e "API_KEY=****" -e "APP_ID=****" caninjas/newrelic_browser_exporter ``` ### **From source:** Clone this repo and go to newrelic_browser_exporter folder: -``` +```cmd > git clone git@github.com:ContaAzul/newrelic_browser_exporter.git > cd newrelic_browser_exporter ``` Install dependencies with ```npm install``` command and run with: -``` +```cmd npm start APP_ID='****' API_KEY='****' ``` Metrics will be exposed in ```localhost:9595/metrics``` + +Would you like to help? See [contributing](https://github.com/ContaAzul/newrelic_browser_exporter/blob/master/CONTRIBUTING.md). + diff --git a/src/plugins/newrelic_browser/javascriptErrorsPercent/javascriptErrorsPercent.js b/src/plugins/newrelic_browser/javascriptErrorsPercent/javascriptErrorsPercent.js index c410817..e9d2b85 100644 --- a/src/plugins/newrelic_browser/javascriptErrorsPercent/javascriptErrorsPercent.js +++ b/src/plugins/newrelic_browser/javascriptErrorsPercent/javascriptErrorsPercent.js @@ -24,6 +24,7 @@ const collectData = () => new Promise((resolve, reject) => { const names = 'EndUser/errors'; const values = 'error_percentage'; + browser .collectData(names, values) .then((response) => {