Query data from any source and display it on your New Relic dashboard with custom visualizations.
In this guide, you learn how to:
- Use the
nr1
CLI to generate a default visualization. - Run your visualization locally where you can quickly test and iterate.
- Publish your visualization to the New Relic app catalog.
- Add your visualization to a dashboard.
Before you begin
If you haven't already:
- Create a New Relic account.
- Install Node.js.
- Complete the steps in the
nr1
quick start to install and configure the CLI.
Create a new visualization
Use nr1
to generate the boilerplate for a new visualization.
import React from 'react';import PropTypes from 'prop-types';import { Radar, RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis,} from 'recharts';import {Card, CardBody, HeadingText, NrqlQuery, Spinner, AutoSizer} from 'nr1';
export default class MyAwesomeVisualizationVisualization extends React.Component { // Custom props you wish to be configurable in the UI must also be defined in // the nr1.json file for the visualization. See docs for more details. static propTypes = { /** * A fill color to override the default fill color. This is an example of * a custom chart configuration. */ fill: PropTypes.string,
/** * A stroke color to override the default stroke color. This is an example of * a custom chart configuration. */ stroke: PropTypes.string, /** * An array of objects consisting of a nrql `query` and `accountId`. * This should be a standard prop for any NRQL based visualizations. */ nrqlQueries: PropTypes.arrayOf( PropTypes.shape({ accountId: PropTypes.number, query: PropTypes.string, }) ), };
/** * Restructure the data for a non-time-series, facet-based NRQL query into a * form accepted by the Recharts library's RadarChart. * (https://recharts.org/api/RadarChart). */ transformData = (rawData) => { return rawData.map((entry) => ({ name: entry.metadata.name, // Only grabbing the first data value because this is not time-series data. value: entry.data[0].y, })); };
/** * Format the given axis tick's numeric value into a string for display. */ formatTick = (value) => { return value.toLocaleString(); };
render() { const {nrqlQueries, stroke, fill} = this.props;
const nrqlQueryPropsAvailable = nrqlQueries && nrqlQueries[0] && nrqlQueries[0].accountId && nrqlQueries[0].query;
if (!nrqlQueryPropsAvailable) { return <EmptyState />; }
return ( <AutoSizer> {({width, height}) => ( <NrqlQuery query={nrqlQueries[0].query} accountId={parseInt(nrqlQueries[0].accountId)} pollInterval={NrqlQuery.AUTO_POLL_INTERVAL} > {({data, loading, error}) => { if (loading) { return <Spinner />; }
if (error) { return <ErrorState />; }
const transformedData = this.transformData(data);
return ( <RadarChart width={width} height={height} data={transformedData} > <PolarGrid /> <PolarAngleAxis dataKey="name" /> <PolarRadiusAxis tickFormatter={this.formatTick} /> <Radar dataKey="value" stroke={stroke || '#51C9B7'} fill={fill || '#51C9B7'} fillOpacity={0.6} /> </RadarChart> ); }} </NrqlQuery> )} </AutoSizer> ); }}
const EmptyState = () => ( <Card className="EmptyState"> <CardBody className="EmptyState-cardBody"> <HeadingText spacingType={[HeadingText.SPACING_TYPE.LARGE]} type={HeadingText.TYPE.HEADING_3} > Please provide at least one NRQL query & account ID pair </HeadingText> <HeadingText spacingType={[HeadingText.SPACING_TYPE.MEDIUM]} type={HeadingText.TYPE.HEADING_4} > An example NRQL query you can try is: </HeadingText> <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code> </CardBody> </Card>);
const ErrorState = () => ( <Card className="ErrorState"> <CardBody className="ErrorState-cardBody"> <HeadingText className="ErrorState-headingText" spacingType={[HeadingText.SPACING_TYPE.LARGE]} type={HeadingText.TYPE.HEADING_3} > Oops! Something went wrong. </HeadingText> </CardBody> </Card>);
Ensure you're working with the latest version of the New Relic One CLI:
$nr1 update
Create a visualization, called my-awesome-visualization
, in a Nerdpack, called my-awesome-nerdpack
:
$nr1 create --type visualization --name my-awesome-visualization✔ You are attempting to create a nerdlet outside of a nerdpack. We will create a nerdpack for you. What would you like to name it? ... my-awesome-nerdpack✔ nerdpack created successfully! nerdpack my-awesome-nerdpack is available at "./my-awesome-nerdpack"✔ visualization created successfully! visualization my-awesome-visualization is available at "./my-awesome-nerdpack/visualizations/my-awesome-visualization"
Tip
If you receive a RequestError
for a self-signed certificate when you run nr1 create
, you may need to add a certificate to Node's certificate chain. Read more about this and other advanced configurations in Enable advanced configurations for your Nerdpack.
As a result, you have a new visualizations/my-awesome-visualization
directory in my-awesome-nerdpack
:
$ls my-awesome-nerdpack/visualizations/my-awesome-visualizationindex.js nr1.json styles.scss
The top-level visualizations
directory holds all of your Nerdpack's visualizations. The visualization you created is called my-awesome-visualization
, and it has its own directory. The files in this directory provide an example visualization, a RadarChart
populated by a basic NRQL query.
Files
nr1.json
provides metadata for your visualization. Theconfiguration
key in this metadata defines the prop-input fields to be shown in the UI. To learn more about the options available under theconfiguration
key, check out the Configure your custom visualization.index.js
defines the React component that receives the props defined innr1.json
and renders your visualization. You can install and import any JavaScript libraries you find useful. The example component imports Recharts, a library that wraps D3 submodules for easy-to-compose visualizations.styles.scss
defines the Sass styles for your visualization.
Serve your visualization locally
Serve your visualization locally, and view it in Apps > Custom Visualizations. There, you can quickly test changes to your code.
From the root directory of your Nerdpack, start a local Node server:
$cd my-awesome-nerdpack$nr1 nerdpack:serve
While it's running, your local server recognizes changes to certain files, such as index.js
and automatically refreshes your visualization. However, it doesn't recognize changes to nr1.json
or styles.scss
. Therefore, some changes, such as those to the definition of the configuration
field in nr1.json
, won't be reflected in your visualization until you restart your server. To see changes to those files, stop the server, with CTRL+C
, and start it back up with nr1 nerdpack:serve
.
Open the link to your visualization that's shown in the terminal when the Node server starts:
Visualizations:⁎ my-awesome-visualization https://one.nr/012ab3cd4Ef
Update the fields under Configure visualization properties, and watch your visualization update automatically:
To add more of these properties, update the configuration
field in nr1.json
, and restart your local server.
Configuring these properties is one way to update your visualization. Changing your React code is another.
In index.js
, change your component's Radar.fillOpacity
:
import React from 'react';import PropTypes from 'prop-types';import { Radar, RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis,} from 'recharts';import {Card, CardBody, HeadingText, NrqlQuery, Spinner, AutoSizer} from 'nr1';
export default class MyAwesomeVisualizationVisualization extends React.Component { // Custom props you wish to be configurable in the UI must also be defined in // the nr1.json file for the visualization. See docs for more details. static propTypes = { /** * A fill color to override the default fill color. This is an example of * a custom chart configuration. */ fill: PropTypes.string,
/** * A stroke color to override the default stroke color. This is an example of * a custom chart configuration. */ stroke: PropTypes.string, /** * An array of objects consisting of a nrql `query` and `accountId`. * This should be a standard prop for any NRQL based visualizations. */ nrqlQueries: PropTypes.arrayOf( PropTypes.shape({ accountId: PropTypes.number, query: PropTypes.string, }) ), };
/** * Restructure the data for a non-time-series, facet-based NRQL query into a * form accepted by the Recharts library's RadarChart. * (https://recharts.org/api/RadarChart). */ transformData = (rawData) => { return rawData.map((entry) => ({ name: entry.metadata.name, // Only grabbing the first data value because this is not time-series data. value: entry.data[0].y, })); };
/** * Format the given axis tick's numeric value into a string for display. */ formatTick = (value) => { return value.toLocaleString(); };
render() { const {nrqlQueries, stroke, fill} = this.props;
const nrqlQueryPropsAvailable = nrqlQueries && nrqlQueries[0] && nrqlQueries[0].accountId && nrqlQueries[0].query;
if (!nrqlQueryPropsAvailable) { return <EmptyState />; }
return ( <AutoSizer> {({width, height}) => ( <NrqlQuery query={nrqlQueries[0].query} accountId={parseInt(nrqlQueries[0].accountId)} pollInterval={NrqlQuery.AUTO_POLL_INTERVAL} > {({data, loading, error}) => { if (loading) { return <Spinner />; }
if (error) { return <ErrorState />; }
const transformedData = this.transformData(data);
return ( <RadarChart width={width} height={height} data={transformedData} > <PolarGrid /> <PolarAngleAxis dataKey="name" /> <PolarRadiusAxis tickFormatter={this.formatTick} /> <Radar dataKey="value" stroke={stroke || '#51C9B7'} fill={fill || '#51C9B7'} fillOpacity={1.0} /> </RadarChart> ); }} </NrqlQuery> )} </AutoSizer> ); }}
const EmptyState = () => ( <Card className="EmptyState"> <CardBody className="EmptyState-cardBody"> <HeadingText spacingType={[HeadingText.SPACING_TYPE.LARGE]} type={HeadingText.TYPE.HEADING_3} > Please provide at least one NRQL query & account ID pair </HeadingText> <HeadingText spacingType={[HeadingText.SPACING_TYPE.MEDIUM]} type={HeadingText.TYPE.HEADING_4} > An example NRQL query you can try is: </HeadingText> <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code> </CardBody> </Card>);
const ErrorState = () => ( <Card className="ErrorState"> <CardBody className="ErrorState-cardBody"> <HeadingText className="ErrorState-headingText" spacingType={[HeadingText.SPACING_TYPE.LARGE]} type={HeadingText.TYPE.HEADING_3} > Oops! Something went wrong. </HeadingText> </CardBody> </Card>);
Look at your visualization in the New Relic platform to see the change.
Now you've seen how to:
- Serve your visualization locally
- View it in New Relic platform
- Update the visualization with configurable properties and code changes
Once you've developed and configured a chart to show your data in an effective way, you can save that instance of the chart, complete with your configurations and the data or query, in a dashboard. However, you can't do this with a locally served visualization. You need to publish your visualization, first.
Publish and use your visualization
To add an instance of your visualization to a dashboard, you first need to publish your Nerdpack.
Publish your Nerdpack from its root directory:
$nr1 nerdpack:publish
Look for a success message in your output:
✔ Nerdpack published successfully!✔ Tagged 5f4c2af8-3b27-40b5-954c-356d1ef88dd0 version 1.0.0 as STABLE.
This means that your Nerdpack was published to the New Relic app catalog that you can find under Apps.
Subscribe to your Nerdpack:
$nr1 nerdpack:subscribeSubscribed account 3014918 to the nerdpack 5f4c2af8-3b27-40b5-954c-356d1ef88dd0 on the STABLE channel.
Now, you're subscribed to your Nerdpack and can build an instance of a visualization in New Relic.
Once again, open the Apps page at New Relic:
Here, you don't need to use the ?nerdpacks=local
query string because you're looking for a visualization that you've published and subscribed to, rather than one that is locally served.
Go to Custom Visualizations.
Find and click your published visualization.
You may have to refresh your browser page if you can't find your visualization. Notice that this new tile no longer has a / Local label. This is because you're looking at the visualization you published and subscribed to in the previous steps. If you're still serving your Nerdpack locally, you might see two tiles here, one with the label and one without it.
Configure your visualization the same way you did when it was locally served.
Click Add to dashboard. Follow the prompts to add your visualization to a dashboard.
From the homepage, go to Dashboards and select the dashboard you added your visualization to, and see your visualization in it.
Summary
Congratulations on building your first visualization! In this guide, you learned how to:
- Create a visualization
- Serve your visualization locally
- Iterate on visualization code changes and customizations in Custom Visualizations
- Publish your visualization
- Subscribe to your visualization
- Add your visualization to a dashboard
Additional resources
- New Relic quick tips video: Dashboards and Custom Visualizations (6 minutes)
- New Relic NerdBytes video: Configuring custom visualizations for dashboards (7 minutes)
- New Relic Changelog live stream: Custom Data Visualizations on New Relic (30 minutes)