• EnglishEspañol日本語한국어Português
  • EntrarComeçar agora

Esta tradução de máquina é fornecida para sua comodidade.

In the event of any inconsistency between the English version and the translated version, the English versionwill take priority. Please visit this page for more information.

Criar um problema

Personalize sua visualização com opções de configuração

Dica

Esta lição faz parte de um curso que ensina como construir uma visualização personalizada na plataforma New Relic.

Cada lição do curso se baseia na anterior, portanto, certifique-se de ter concluído a última lição, Visualizações personalizadas e o SDK da New Relic, antes de iniciar esta.

Comece aqui

Na lição anterior, você criou uma visualização personalizada que mostra os dados da consulta em um dos dois tipos de gráfico:

Você usou um SegmentedControl para alternar entre os dois tipos de gráfico na interface de visualização. Essa implementação ocupa espaço na visualização, mas oferece ao usuário a opção de alternar entre dois tipos de gráfico mesmo depois de criar uma instância do seu gráfico. Mas e se você só precisar selecionar uma opção uma vez, ao inicializar a visualização?

Nesta lição você aprenderá como adicionar uma opção de configuração à sua visualização que substitui o SegmentedControl.

Dica

Se você se perder no projeto de código e quiser ver como os arquivos devem ficar quando terminar cada lição, verifique o projeto do curso no Github.

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
{
"schemaType": "VISUALIZATION",
"id": "radar-or-treemap",
"displayName": "RadarOrTreemap",
"description": "",
"configuration": [
{
"name": "nrqlQueries",
"title": "NRQL Queries",
"type": "collection",
"items": [
{
"name": "accountId",
"title": "Account ID",
"description": "Account ID to be associated with the query",
"type": "account-id"
},
{
"name": "query",
"title": "Query",
"description": "NRQL query for visualization",
"type": "nrql"
}
]
},
{
"name": "fill",
"title": "Fill color",
"description": "A fill color to override the default fill color",
"type": "string"
},
{
"name": "stroke",
"title": "Stroke color",
"description": "A stroke color to override the default stroke color",
"type": "string"
}
]
}
visualizations/radar-or-treemap/nr1.json

Adicione uma nova opção de configuração

No arquivo nr1.json da sua visualização, adicione um objeto de configuração enum para selectedChart:

{
"schemaType": "VISUALIZATION",
"id": "radar-or-treemap",
"displayName": "RadarOrTreemap",
"description": "",
"configuration": [
{
"name": "selectedChart",
"title": "Select chart",
"description": "Select which chart to display",
"type": "enum",
"items": [
{
"title": "Radar",
"value": "radar"
},
{
"title": "Treemap",
"value": "treemap"
}
]
},
{
"name": "nrqlQueries",
"title": "NRQL Queries",
"type": "collection",
"items": [
{
"name": "accountId",
"title": "Account ID",
"description": "Account ID to be associated with the query",
"type": "account-id"
},
{
"name": "query",
"title": "Query",
"description": "NRQL query for visualization",
"type": "nrql"
}
]
},
{
"name": "fill",
"title": "Fill color",
"description": "A fill color to override the default fill color",
"type": "string"
},
{
"name": "stroke",
"title": "Stroke color",
"description": "A stroke color to override the default stroke color",
"type": "string"
}
]
}
visualizations/radar-or-treemap/nr1.json

Navegue até a raiz do seu Nerdpack em alternate-viz.

Sirva seu Nerdpack localmente:

bash
$
nr1 nerdpack:serve

Se você ainda estiver veiculando seu Nerdpack da última lição, será necessário interrompê-lo com CTRL-X e exibi-lo novamente para refletir as alterações em nr1.json.

Vá para https://one.newrelic.com/?nerdpacks=local. A string de consulta nerdpacks=local direciona a interface para carregar sua visualização do servidor local.

Abra a página Apps .

Vá para Custom Visualizations.

Em Custom Visualizations, encontre e clique na sua visualização.

Observe a nova opção do configuração Select chart.

A seleção de um tipo de gráfico não afeta sua visualização. Isso ocorre porque primeiro você precisa introduzir a propriedade selectedChart no componente de visualização. Em seguida, você usa selectedChart para determinar o tipo de gráfico a ser renderizado.

Substitua seu SegmentedControl pela propriedade configurável

Abra o arquivo index.js da sua visualização. Você trabalhará aqui durante o restante do guia.

Em render(), inclua selectedChart como uma constante obtida da desestruturação props e remova state do seu componente:

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,
})
),
};
/**
* 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, selectedChart } = 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>
<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

Agora que você está usando selectedChart nas opções de configuração em vez do componente state, você pode selecionar um gráfico no painel de configuração e observar a mudança na visualização. Infelizmente, há um bug. A opção de gráfico padrão é Radar, mas a renderização inicial mostra um Treemap.

Atualize sua expressão ternária para levar em conta o caso em que não há selectedChart:

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,
})
),
};
/**
* 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, selectedChart } = 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>
<SegmentedControlItem
value={CHART_TYPES.Radar}
label="Radar chart"
/>
<SegmentedControlItem
value={CHART_TYPES.Treemap}
label="Treemap chart"
/>
</SegmentedControl>
{!selectedChart || 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

Agora, seus dados serão renderizados em RadarChart caso você ainda não tenha configurado a opção.

Remover SegmentedControl de render():

import React from 'react';
import PropTypes from 'prop-types';
import {
Radar,
RadarChart,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
Treemap,
} from 'recharts';
import {
AutoSizer,
Card,
CardBody,
HeadingText,
NrqlQuery,
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,
})
),
};
/**
* 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, selectedChart } = 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>
{!selectedChart || 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

Sirva seu Nerdpack localmente e visualize-o no aplicativo Custom Visualizations no New Relic. Selecione um tipo de gráfico no dropdown na barra lateral de configuração e veja sua atualização de visualização para mostrar o tipo de gráfico correspondente.

Resumo

Parabéns por concluir esta lição! Você aprendeu como personalizar sua visualização usando a configuração nr1.json .

Curso

Esta lição faz parte de um curso que ensina como construir uma visualização personalizada na plataforma New Relic. Quando estiver pronto, passe para a próxima lição: Adicione visualizações personalizadas aos seus painéis.

Copyright © 2024 New Relic Inc.

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