• /
  • EnglishEspañol日本語한국어Português
  • ログイン今すぐ開始

この機械翻訳は、参考として提供されています。

英語版と翻訳版に矛盾がある場合は、英語版が優先されます。詳細については、このページを参照してください。

問題を作成する

SDKコンポーネントを使用して視覚化をカスタマイズする

ヒント

このレッスンは、New Relic プラットフォームでカスタム視覚化を構築する方法を学習するコースの一部です。

New Relic のカスタム視覚化を使用すると、New Relic のデータベースからのデータでも外部ソースからのデータでも、New Relic プラットフォームが提供するチャートとは異なる独自の方法でデータを表示できます。

このレッスンでは、 RadarChartまたはTreemapの 2 つのグラフ タイプのいずれかでデータを表示する視覚化を構築します。 次に、New Relic One SDK からSegmentedControlコンポーネントを実装して、2 つのチャート タイプを切り替えることができるようになります。 最終的に、これにより、New Relic の基本機能では不可能な動的な方法でデータを自由に表示できるようになります。

ヒント

コード プロジェクトで迷ってしまったり、各レッスンを終えたときにファイルがどのようになっているかを確認したい場合は、Github のコース プロジェクトを確認してください。

あなたが始める前に

最後に、まだ行っていない場合は、次の操作を行います。

視覚化を作成する

最新バージョンの New Relic CLI を使用していることを確認してください。

bash
$
nr1 update

Nerdpack のalternate-vizに、 radar-or-treemapという視覚化を作成します。

bash
$
nr1 create --type visualization --name radar-or-treemap
You’re trying to create a visualization outside of a Nerdpack. We’ll create a Nerdpack for you—what do you want to name it? … alternate-viz
nerdpack created successfully!
nerdpack alternate-viz is available at "./alternate-viz"
visualization created successfully!
visualization radar-or-treemap is available at "./alternate-viz/visualizations/radar-or-treemap"

ヒント

nr1 createを実行したときに自己署名証明書のRequestErrorを受け取った場合は、Node の証明書チェーンに証明書を追加する必要がある可能性があります。

その結果、 alternate-vizの下に新しいvisualizations/radar-or-treemapディレクトリが作成されます。

bash
$
cd alternate-viz
$
ls visualizations/radar-or-treemap
index.js nr1.json styles.scss
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 RadarOrTreemapVisualization 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/radar-or-treemap/index.js

コンポーネントの状態を設定する

nr1が作成したデフォルトの視覚化テンプレートにコンポーネント状態を追加します。

alternate-viz/visualizations/radar-or-treemap/index.jsに移動します。 このレッスンの残りの時間はここで作業します。

CHART_TYPESという定数を追加します:

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';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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/radar-or-treemap/index.js

CHART_TYPES 視覚化で交互に使用する 2 つのグラフ タイプを列挙します。

コンポーネントのstateselectedChartを初期化します。

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';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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/radar-or-treemap/index.js

このstate値には、データを表示するグラフの種類が格納されます。

視覚化のグラフ タイプのオプションを列挙するオブジェクトを作成し、 state.selectedChartを初期化したので、2 つのグラフ タイプを切り替えるためのコントロール UI を実装する準備が整いました。

SegmentedControlコンポーネントを追加

state.selectedChart 視覚化のユーザーが実際にグラフの種類を選択できない限り、役に立ちません。 2 つのグラフ タイプを切り替えるには、 SegmentedControlSegmentedControlItem使用します。

nr1からSegmentedControlSegmentedControlItemインポートします:

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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/radar-or-treemap/index.js

render()で、 RadarChartReact.Fragmentでラップします。

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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 (
<React.Fragment>
<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>
</React.Fragment>
);
}}
</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/radar-or-treemap/index.js

これにより、同じrender()から複数のコンポーネントを返すことができます。

SegmentedControlと 2 つのSegmentedControlItemコンポーネントを追加します。各コンポーネントにはvaluelabelが含まれます。

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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 (
<React.Fragment>
<SegmentedControl
onChange={(event, value) => console.log(value)}
>
<SegmentedControlItem
value={CHART_TYPES.Radar}
label="Radar chart"
/>
<SegmentedControlItem
value={CHART_TYPES.Treemap}
label="Treemap chart"
/>
</SegmentedControl>
<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>
</React.Fragment>
);
}}
</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/radar-or-treemap/index.js

ここで、選択を変更すると、 SegmentedControlSegmentedControlItem.valueをコンソールに記録します。 SegmentedControlItemコンポーネントに定義した値は、前の手順で作成した 2 つのCHART_TYPESに対応します。

alternate-vizにある Nerdpack のルートに移動します。

Nerdpack を地元で提供しましょう:

bash
$
nr1 nerdpack:serve

Node サーバーの起動時にターミナルに表示される視覚化へのリンクを開きます。

bash
Visualizations:
radar-or-treemap https://one.nr/012ab3cd4Ef

アカウント ID とクエリを使用して視覚化を構成します。

チャートの処理に必要なデータがいくつかあるため、ビューの上部にSegmentedControlを含むRadarChartが表示されます。

SegmentedControl ログを確認するには、 browserのコンソールを参照してください。

コンポーネントのstateSegmentedControl

stateを更新するメソッドを追加し、そのメソッドを前のセクションで追加したSegmentedControlに接続します。

updateSelectedChart()というコンポーネント メソッドを追加します。

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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();
};
updateSelectedChart = (evt, value) => {
this.setState({ selectedChart: value })
};
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 (
<React.Fragment>
<SegmentedControl
onChange={(event, value) => console.log(value)}
>
<SegmentedControlItem
value={CHART_TYPES.Radar}
label="Radar chart"
/>
<SegmentedControlItem
value={CHART_TYPES.Treemap}
label="Treemap chart"
/>
</SegmentedControl>
<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>
</React.Fragment>
);
}}
</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/radar-or-treemap/index.js

この新しいメソッドはvalue引数を受け取り、 state.selectedChartをその値に設定します。

SegmentedControl.onChangeupdateSelectedChart()に設定します:

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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();
};
updateSelectedChart = (evt, value) => {
this.setState({ selectedChart: value })
};
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 (
<React.Fragment>
<SegmentedControl
onChange={this.updateSelectedChart}
>
<SegmentedControlItem
value={CHART_TYPES.Radar}
label="Radar chart"
/>
<SegmentedControlItem
value={CHART_TYPES.Treemap}
label="Treemap chart"
/>
</SegmentedControl>
<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>
</React.Fragment>
);
}}
</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/radar-or-treemap/index.js

ここで、 SegmentedControlで選択内容を変更すると、その選択内容がstateに設定されます。

Treemapオプションを実装する

視覚化にTreemapを追加します。 このマップは既存のRadarChartの代替となります。

技術的詳細

このガイドでは、サードパーティのチャートにRechartsコンポーネントを使用しますが、New Relic の視覚化とアプリを構築するときに、現在の React バージョンと互換性のある他の JavaScript チャート ライブラリを使用することもできます。

rechartsからTreemapをインポートします:

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
Treemap,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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();
};
updateSelectedChart = (evt, value) => {
this.setState({ selectedChart: value })
};
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 (
<React.Fragment>
<SegmentedControl
onChange={this.updateSelectedChart}
>
<SegmentedControlItem
value={CHART_TYPES.Radar}
label="Radar chart"
/>
<SegmentedControlItem
value={CHART_TYPES.Treemap}
label="Treemap chart"
/>
</SegmentedControl>
<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>
</React.Fragment>
);
}}
</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/radar-or-treemap/index.js

これで、視覚化コンポーネントでTreemapを使用できるようになりました。

render()Treemapコンポーネントを追加します。

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
Treemap,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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();
};
updateSelectedChart = (evt, value) => {
this.setState({ selectedChart: value })
};
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 (
<React.Fragment>
<SegmentedControl
onChange={this.updateSelectedChart}
>
<SegmentedControlItem
value={CHART_TYPES.Radar}
label="Radar chart"
/>
<SegmentedControlItem
value={CHART_TYPES.Treemap}
label="Treemap chart"
/>
</SegmentedControl>
<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>
<Treemap
width={width}
height={height}
data={transformedData}
dataKey="value"
ratio={4 / 3}
stroke={stroke || '#000000'}
fill={fill || '#51C9B7'}
/>
</React.Fragment>
);
}}
</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/radar-or-treemap/index.js

ここでは、 heightwidthfillstrokeなどのいくつかのプロパティを使用して、新しいTreemapコンポーネントを定義しました。

Nerdpack をローカルで提供して、視覚化を表示しますSegmentedControlRadarChartビューの上部にありますが、下にスクロールすると新しいTreemapが表示されます。

コンポーネントのチャートを切り替える state

state.selectedChartを使用して、表示するグラフRadarChartまたはTreemapを決定します。

this.stateを分解して、別の定数としてselectedChartにアクセスします。 次に、 selectedChartCHART_TYPES.Radarを比較します。 同じ場合は、 RadarChartをレンダリングします。 それ以外の場合は、 Treemapをレンダリングします。

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
Treemap,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
SegmentedControl,
SegmentedControlItem,
Spinner,
} from 'nr1';
const CHART_TYPES = {
'Radar': 'radar',
'Treemap': 'treemap'
}
export default class RadarOrTreemapVisualization 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,
})
),
};
state = {
selectedChart: CHART_TYPES.Radar,
};
/**
* 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();
};
updateSelectedChart = (evt, value) => {
this.setState({ selectedChart: value })
};
render() {
const {nrqlQueries, stroke, fill} = this.props;
const {selectedChart} = this.state;
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 (
<React.Fragment>
<SegmentedControl
onChange={this.updateSelectedChart}
>
<SegmentedControlItem
value={CHART_TYPES.Radar}
label="Radar chart"
/>
<SegmentedControlItem
value={CHART_TYPES.Treemap}
label="Treemap chart"
/>
</SegmentedControl>
{selectedChart === CHART_TYPES.Radar ? (
<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>
) : (
<Treemap
width={width}
height={height}
data={transformedData}
dataKey="value"
ratio={4 / 3}
stroke={stroke || '#000000'}
fill={fill || '#51C9B7'}
/>
)}
</React.Fragment>
);
}}
</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/radar-or-treemap/index.js

ここでは、三項式を使用してRadarChartまたはTreemapをレンダリングしました。 レンダリングされるチャートは、 selectedChartの値によって決まります。

Nerdpack をローカルで提供して、視覚化を表示します

SegmentedControlからRadar chart [レーダーチャート]を選択します。

SegmentedControlからTreemap chart [ツリーマップ チャート]を選択します。

概要

おめでとう! このレッスンでは、次の方法を学習しました。

  • New Relic One SDKコンポーネントを使用して視覚化をカスタマイズする
  • 視覚化に新しいチャートタイプを追加する
  • 視覚化でユーザーインタラクションを作成する

ヒント

このレッスンは、New Relic プラットフォームでカスタム視覚化を構築する方法を学習するコースの一部です。 準備ができたら、次のレッスン「設定を使用して視覚化をカスタマイズする」に進んでください。

Copyright © 2024 New Relic株式会社。

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