Collect custom business data

lab

This procedure is part of a lab that teaches you how to get started with New Relic to monitor your application.

Each procedure in the lab builds upon the last, so make sure you've completed the last procedure, Explore your data using NRQL, before starting this one.

With your app instrumented with New Relic agents, you're collecting performance data from your application such as pageview, slow transactions and other. But you also want to collect business metrics from your application. For instance, you want to know how many orders your applications received in past 24 hours or what restaurants are popular. To achieve this, you need to collect custom business data from your application.

In this procedure, you instrument your app to collect custom business data and query it.

Record custom attributes

To collect custom data from your application, you need to add custom attributes to your application. You record these attributes with newrelic.addCustomAttribute() on server side.

Here, you record custom attributes to gather details about food orders.

Step 1 of 3

In the terminal window that's running your development server, press <CTRL-C>.

You should see your server shut down. Now you can add some dependencies and update your app logic.

Step 2 of 3

In server/index.js, update the code to add custom attributes on your server side.

var newrelic = require('newrelic');
var express = require('express');
var fs = require('fs');
var open = require('open');
var logger = require('morgan');
var bodyParser = require('body-parser');
var RestaurantRecord = require('./model').Restaurant;
var MemoryStorage = require('./storage').Memory;
var API_URL = '/api/restaurant';
var API_URL_ID = API_URL + '/:id';
var API_URL_ORDER = '/api/order';
var API_URL_VALIDATION = '/api/validation';
var removeMenuItems = function(restaurant) {
var clone = {};
Object.getOwnPropertyNames(restaurant).forEach(function(key) {
if (key !== 'menuItems') {
clone[key] = restaurant[key];
}
});
return clone;
};
exports.start = function(PORT, STATIC_DIR, DATA_FILE) {
var app = express();
var storage = new MemoryStorage();
// log requests
app.use(logger('combined'));
// serve static files for demo client
app.use(express.static(STATIC_DIR));
// parse body into req.body
app.use(bodyParser.json());
// API
app.get(API_URL, function(req, res, next) {
return res.status(200).send(storage.getAll().map(removeMenuItems));
});
app.post(API_URL, function(req, res, next) {
var restaurant = new RestaurantRecord(req.body);
var errors = [];
if (restaurant.validate(errors)) {
storage.add(restaurant);
return res.status(201).send(restaurant);
}
return res.status(400).send({error: errors});
});
app.post(API_URL_ORDER, function(req, res, next) {
console.log(req.body);
var itemName, restaurant;
var itemCount = 0;
var orderTotal = 0;
req.body.forEach(function(item) {
itemName = item.name
restaurant = item.restaurant
itemCount += item.count;
orderTotal += item.price * item.count;
});
newrelic.addCustomAttributes({
'itemName': itemName,
'restaurant': restaurant,
'itemCount': itemCount,
'orderTotal': orderTotal
});
return res.status(201).send({ orderId: Date.now()});
});
app.post(API_URL_VALIDATION, function(req, res, next) {
if (req.body.ccnum.length <= 15) {
let err = new Error('payments.js, cardNumber is invalid');
newrelic.noticeError(err);
console.log(err)
return res.status(400).send(err);
}
return res.status(200).send();
});
app.get(API_URL_ID, function(req, res, next) {
var restaurant = storage.getById(req.params.id);
if (restaurant) {
return res.status(200).send(restaurant);
}
return res.status(400).send({error: 'No restaurant with id "' + req.params.id + '"!'});
});
app.put(API_URL_ID, function(req, res, next) {
var restaurant = storage.getById(req.params.id);
var errors = [];
if (restaurant) {
restaurant.update(req.body);
return res.status(200).send(restaurant);
}
restaurant = new RestaurantRecord(req.body);
if (restaurant.validate(errors)) {
storage.add(restaurant);
return res.status(201).send(restaurant);
}
return res.status(400).send({error: errors});
});
app.delete(API_URL_ID, function(req, res, next) {
if (storage.deleteById(req.params.id)) {
return res.status(204).send(null);
}
return res.status(400).send({error: 'No restaurant with id "' + req.params.id + '"!'});
});
// start the server
// read the data from json and start the server
fs.readFile(DATA_FILE, function(err, data) {
JSON.parse(data).forEach(function(restaurant) {
storage.add(new RestaurantRecord(restaurant));
});
app.listen(PORT, function() {
open('http://localhost:' + PORT + '/');
});
});
};
server/index.js

Here, you add the item name, restaurant name, item count, and order total as custom attributes by calling newrelic.addCustomAttributes(). These custom attributes add metadata to your transaction event. You record them as a part of your transaction event so there is no overhead.

Step 3 of 3

Now that you've instrumented your application to record custom data, it's time to restart your local server.

bash
$
npm run build
$
npm run newstart

Restart your load generator, as well.

bash
$
python simulator.py

Important

Make sure you're running these commands in the correct terminal windows. If you no longer have those windows, follow the steps in the setup procedure.

You're now recording custom data from your application. Next, you query this data to get business insights and create a custom dashboard.

lab

This procedure is part of a lab that teaches you how to get started with New Relic to monitor your application. Now that you're collecting custom data, query your custom data.