• /
  • EnglishEspañol日本語한국어Português
  • Log inStart now

Your first custom visualization

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 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>
);
visualizations/my-awesome-visualization/index.js

Ensure you're working with the latest version of the New Relic One CLI:

bash
$
nr1 update

Create a visualization, called my-awesome-visualization, in a Nerdpack, called my-awesome-nerdpack:

bash
$
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:

bash
$
ls my-awesome-nerdpack/visualizations/my-awesome-visualization
index.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. The configuration key in this metadata defines the prop-input fields to be shown in the UI. To learn more about the options available under the configuration key, check out the Configure your custom visualization.
  • index.js defines the React component that receives the props defined in nr1.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:

bash
$
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:

bash
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>
);
visualizations/my-awesome-visualization/index.js

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:

bash
$
nr1 nerdpack:publish

Look for a success message in your output:

bash
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:

bash
$
nr1 nerdpack:subscribe
Subscribed 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.

  1. Go to Custom Visualizations.

  2. 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.

  3. Configure your visualization the same way you did when it was locally served.

  4. Click Add to dashboard. Follow the prompts to add your visualization to a dashboard.

  5. 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

Copyright © 2024 New Relic Inc.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.