mirror of https://github.com/linkerd/linkerd2.git
Make TabbedMetricsTable in charge of fetching timeseries (#89)
* Make TabbedMetricsTable in charge of fetching timeseries All of the parent components in charge of fetching timeseries data don't actually use them, but pass them to this table. It would simplify a lot of the parents if this component handled the ts fetching too. This introduces a urlsForResource helper in ApiHelpers to allow us to consolidate url generating in the app to one place. It also associates the appropriate groupBy for various fetches. Signed-off-by: Risha Mars <mars@buoyant.io>
This commit is contained in:
parent
a7306113d2
commit
fa49de6ff4
|
@ -1,5 +1,4 @@
|
|||
import _ from 'lodash';
|
||||
import { ApiHelpers } from './util/ApiHelpers.js';
|
||||
import BarChart from './BarChart.jsx';
|
||||
import ConduitSpinner from "./ConduitSpinner.jsx";
|
||||
import ErrorBanner from './ErrorBanner.jsx';
|
||||
|
@ -11,6 +10,7 @@ import { rowGutter } from './util/Utils.js';
|
|||
import StatPane from './StatPane.jsx';
|
||||
import TabbedMetricsTable from './TabbedMetricsTable.jsx';
|
||||
import UpstreamDownstream from './UpstreamDownstream.jsx';
|
||||
import { ApiHelpers, urlsForResource } from './util/ApiHelpers.js';
|
||||
import { Col, Row } from 'antd';
|
||||
import { emptyMetric, getPodsByDeployment, processRollupMetrics, processTimeseriesMetrics } from './util/MetricUtils.js';
|
||||
import './../../css/deployment.css';
|
||||
|
@ -50,12 +50,9 @@ export default class Deployment extends React.Component {
|
|||
metricsWindow: "10m",
|
||||
deploy: deployment,
|
||||
metrics:[],
|
||||
timeseriesByPod: {},
|
||||
pods: [],
|
||||
upstreamMetrics: [],
|
||||
upstreamTsByDeploy: {},
|
||||
downstreamMetrics: [],
|
||||
downstreamTsByDeploy: {},
|
||||
pendingRequests: false,
|
||||
loaded: false,
|
||||
error: ''
|
||||
|
@ -68,35 +65,26 @@ export default class Deployment extends React.Component {
|
|||
}
|
||||
this.setState({ pendingRequests: true });
|
||||
|
||||
let metricsUrl = `${this.props.pathPrefix}/api/metrics?window=${this.state.metricsWindow}` ;
|
||||
let deployMetricsUrl = `${metricsUrl}×eries=true&target_deploy=${this.state.deploy}`;
|
||||
let podRollupUrl = `${metricsUrl}&aggregation=target_pod&target_deploy=${this.state.deploy}`;
|
||||
let podTimeseriesUrl = `${podRollupUrl}×eries=true`;
|
||||
let upstreamRollupUrl = `${metricsUrl}&aggregation=source_deploy&target_deploy=${this.state.deploy}`;
|
||||
let upstreamTimeseriesUrl = `${upstreamRollupUrl}×eries=true`;
|
||||
let downstreamRollupUrl = `${metricsUrl}&aggregation=target_deploy&source_deploy=${this.state.deploy}`;
|
||||
let downstreamTimeseriesUrl = `${downstreamRollupUrl}×eries=true`;
|
||||
let urls = urlsForResource(this.props.pathPrefix, this.state.metricsWindow);
|
||||
|
||||
let deployMetricsUrl = urls["deployment"].url(this.state.deploy).ts;
|
||||
let podRollupUrl = urls["pod"].url(this.state.deploy).rollup;
|
||||
let upstreamRollupUrl = urls["upstream_deployment"].url(this.state.deploy).rollup;
|
||||
let downstreamRollupUrl = urls["downstream_deployment"].url(this.state.deploy).rollup;
|
||||
|
||||
let deployFetch = this.api.fetch(deployMetricsUrl);
|
||||
let podListFetch = this.api.fetchPods();
|
||||
let podRollupFetch = this.api.fetch(podRollupUrl);
|
||||
let podTsFetch = this.api.fetch(podTimeseriesUrl);
|
||||
let upstreamFetch = this.api.fetch(upstreamRollupUrl);
|
||||
let upstreamTsFetch = this.api.fetch(upstreamTimeseriesUrl);
|
||||
let downstreamFetch = this.api.fetch(downstreamRollupUrl);
|
||||
let downstreamTsFetch = this.api.fetch(downstreamTimeseriesUrl);
|
||||
|
||||
// expose serverPromise for testing
|
||||
this.serverPromise = Promise.all([deployFetch, podRollupFetch, podTsFetch, upstreamFetch, upstreamTsFetch, downstreamFetch, downstreamTsFetch, podListFetch])
|
||||
.then(([deployMetrics, podRollup, podTimeseries, upstreamRollup, upstreamTimeseries, downstreamRollup, downstreamTimeseries, podList]) => {
|
||||
this.serverPromise = Promise.all([deployFetch, podRollupFetch, upstreamFetch, downstreamFetch, podListFetch])
|
||||
.then(([deployMetrics, podRollup, upstreamRollup, downstreamRollup, podList]) => {
|
||||
let tsByDeploy = processTimeseriesMetrics(deployMetrics.metrics, "targetDeploy");
|
||||
let podMetrics = processRollupMetrics(podRollup.metrics, "targetPod");
|
||||
let podTs = processTimeseriesMetrics(podTimeseries.metrics, "targetPod");
|
||||
|
||||
let upstreamMetrics = processRollupMetrics(upstreamRollup.metrics, "sourceDeploy");
|
||||
let upstreamTsByDeploy = processTimeseriesMetrics(upstreamTimeseries.metrics, "sourceDeploy");
|
||||
let downstreamMetrics = processRollupMetrics(downstreamRollup.metrics, "targetDeploy");
|
||||
let downstreamTsByDeploy = processTimeseriesMetrics(downstreamTimeseries.metrics, "targetDeploy");
|
||||
|
||||
let deploy = _.find(getPodsByDeployment(podList.pods), ["name", this.state.deploy]);
|
||||
let totalRequestRate = _.sumBy(podMetrics, "requestRate");
|
||||
|
@ -104,14 +92,11 @@ export default class Deployment extends React.Component {
|
|||
|
||||
this.setState({
|
||||
metrics: podMetrics,
|
||||
timeseriesByPod: podTs,
|
||||
pods: deploy.pods,
|
||||
added: deploy.added,
|
||||
deployTs: _.get(tsByDeploy, this.state.deploy, {}),
|
||||
upstreamMetrics: upstreamMetrics,
|
||||
upstreamTsByDeploy: upstreamTsByDeploy,
|
||||
downstreamMetrics: downstreamMetrics,
|
||||
downstreamTsByDeploy: downstreamTsByDeploy,
|
||||
lastUpdated: Date.now(),
|
||||
pendingRequests: false,
|
||||
loaded: true,
|
||||
|
@ -156,12 +141,12 @@ export default class Deployment extends React.Component {
|
|||
this.renderMidsection(),
|
||||
<UpstreamDownstream
|
||||
key="deploy-upstream-downstream"
|
||||
entity="deployment"
|
||||
resource="deployment"
|
||||
entity={this.state.deploy}
|
||||
lastUpdated={this.state.lastUpdated}
|
||||
upstreamMetrics={this.state.upstreamMetrics}
|
||||
upstreamTsByEntity={this.state.upstreamTsByDeploy}
|
||||
downstreamMetrics={this.state.downstreamMetrics}
|
||||
downstreamTsByEntity={this.state.downstreamTsByDeploy}
|
||||
metricsWindow={this.state.metricsWindow}
|
||||
pathPrefix={this.props.pathPrefix} />
|
||||
];
|
||||
}
|
||||
|
@ -194,10 +179,11 @@ export default class Deployment extends React.Component {
|
|||
}
|
||||
<TabbedMetricsTable
|
||||
resource="pod"
|
||||
lastUpdated={this.state.lastUpdated}
|
||||
entity={this.state.deploy}
|
||||
metrics={podTableData}
|
||||
timeseries={this.state.timeseriesByPod}
|
||||
pathPrefix={this.props.pathPrefix} />
|
||||
lastUpdated={this.state.lastUpdated}
|
||||
pathPrefix={this.props.pathPrefix}
|
||||
metricsWindow={this.state.metricsWindow} />
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import _ from 'lodash';
|
||||
import { ApiHelpers } from './util/ApiHelpers.js';
|
||||
import CallToAction from './CallToAction.jsx';
|
||||
import ConduitSpinner from "./ConduitSpinner.jsx";
|
||||
import DeploymentSummary from './DeploymentSummary.jsx';
|
||||
|
@ -7,6 +6,7 @@ import ErrorBanner from './ErrorBanner.jsx';
|
|||
import React from 'react';
|
||||
import { rowGutter } from './util/Utils.js';
|
||||
import TabbedMetricsTable from './TabbedMetricsTable.jsx';
|
||||
import { ApiHelpers, urlsForResource } from './util/ApiHelpers.js';
|
||||
import { Col, Row } from 'antd';
|
||||
import { emptyMetric, getPodsByDeployment, processRollupMetrics, processTimeseriesMetrics } from './util/MetricUtils.js';
|
||||
import './../../css/deployments.css';
|
||||
|
@ -78,49 +78,34 @@ export default class Deployments extends React.Component {
|
|||
}
|
||||
|
||||
loadTimeseriesFromServer(meshDeployMetrics, combinedMetrics) {
|
||||
// fetch only the timeseries for the 3 deployments we display at the top of the page
|
||||
let limitSparklineData = _.size(meshDeployMetrics) > maxTsToFetch;
|
||||
let rollupPath = `${this.props.pathPrefix}/api/metrics?window=${this.state.metricsWindow}`;
|
||||
let timeseriesPath = `${rollupPath}×eries=true`;
|
||||
|
||||
let updatedState = {
|
||||
metrics: combinedMetrics,
|
||||
limitSparklineData: limitSparklineData,
|
||||
loaded: true,
|
||||
pendingRequests: false,
|
||||
error: ''
|
||||
};
|
||||
let resourceInfo = urlsForResource(this.props.pathPrefix, this.state.metricsWindow)["deployment"];
|
||||
let leastHealthyDeployments = this.getLeastHealthyDeployments(meshDeployMetrics);
|
||||
|
||||
if (limitSparklineData) {
|
||||
// don't fetch timeseries for every deploy
|
||||
let leastHealthyDeployments = this.getLeastHealthyDeployments(meshDeployMetrics);
|
||||
let tsPromises = _.map(leastHealthyDeployments, dep => {
|
||||
let tsPathForDeploy = resourceInfo.url(dep.name).ts;
|
||||
return this.api.fetch(tsPathForDeploy);
|
||||
});
|
||||
|
||||
let tsPromises = _.map(leastHealthyDeployments, dep => {
|
||||
let tsPathForDeploy = `${timeseriesPath}&target_deploy=${dep.name}`;
|
||||
return this.api.fetch(tsPathForDeploy);
|
||||
});
|
||||
Promise.all(tsPromises)
|
||||
.then(tsMetrics => {
|
||||
let leastHealthyTs = _.reduce(tsMetrics, (mem, ea) => {
|
||||
mem = mem.concat(ea.metrics);
|
||||
return mem;
|
||||
}, []);
|
||||
let tsByDeploy = processTimeseriesMetrics(leastHealthyTs, "targetDeploy");
|
||||
this.setState(_.merge({}, updatedState, {
|
||||
timeseriesByDeploy: tsByDeploy,
|
||||
lastUpdated: Date.now(),
|
||||
}));
|
||||
}).catch(this.handleApiError);
|
||||
} else {
|
||||
// fetch timeseries for all deploys
|
||||
this.api.fetch(timeseriesPath)
|
||||
.then(ts => {
|
||||
let tsByDeploy = processTimeseriesMetrics(ts.metrics, "targetDeploy");
|
||||
this.setState(_.merge({}, updatedState, {
|
||||
timeseriesByDeploy: tsByDeploy,
|
||||
lastUpdated: Date.now()
|
||||
}));
|
||||
}).catch(this.handleApiError);
|
||||
}
|
||||
Promise.all(tsPromises)
|
||||
.then(tsMetrics => {
|
||||
let leastHealthyTs = _.reduce(tsMetrics, (mem, ea) => {
|
||||
mem = mem.concat(ea.metrics);
|
||||
return mem;
|
||||
}, []);
|
||||
let tsByDeploy = processTimeseriesMetrics(leastHealthyTs, resourceInfo.groupBy);
|
||||
this.setState({
|
||||
timeseriesByDeploy: tsByDeploy,
|
||||
lastUpdated: Date.now(),
|
||||
metrics: combinedMetrics,
|
||||
limitSparklineData: limitSparklineData,
|
||||
loaded: true,
|
||||
pendingRequests: false,
|
||||
error: ''
|
||||
});
|
||||
}).catch(this.handleApiError);
|
||||
}
|
||||
|
||||
handleApiError(e) {
|
||||
|
@ -164,8 +149,8 @@ export default class Deployments extends React.Component {
|
|||
resource="deployment"
|
||||
lastUpdated={this.state.lastUpdated}
|
||||
metrics={this.state.metrics}
|
||||
timeseries={this.state.timeseriesByDeploy}
|
||||
hideSparklines={this.state.limitSparklineData}
|
||||
metricsWindow={this.state.metricsWindow}
|
||||
pathPrefix={this.props.pathPrefix} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import _ from 'lodash';
|
||||
import { ApiHelpers } from './util/ApiHelpers.js';
|
||||
import ConduitSpinner from "./ConduitSpinner.jsx";
|
||||
import ErrorBanner from './ErrorBanner.jsx';
|
||||
import HealthPane from './HealthPane.jsx';
|
||||
import React from 'react';
|
||||
import StatPane from './StatPane.jsx';
|
||||
import UpstreamDownstream from './UpstreamDownstream.jsx';
|
||||
import { ApiHelpers, urlsForResource } from './util/ApiHelpers.js';
|
||||
import { processRollupMetrics, processTimeseriesMetrics } from './util/MetricUtils.js';
|
||||
import 'whatwg-fetch';
|
||||
|
||||
|
@ -43,9 +43,7 @@ export default class PodDetail extends React.Component {
|
|||
metricsWindow: "10m",
|
||||
pod: pod,
|
||||
upstreamMetrics: [],
|
||||
upstreamTsByPod: {},
|
||||
downstreamMetrics: [],
|
||||
downstreamTsByPod: {},
|
||||
podTs: {},
|
||||
pendingRequests: false,
|
||||
loaded: false,
|
||||
|
@ -59,38 +57,31 @@ export default class PodDetail extends React.Component {
|
|||
}
|
||||
this.setState({ pendingRequests: true });
|
||||
|
||||
let metricsUrl = `${this.props.pathPrefix}/api/metrics?window=${this.state.metricsWindow}` ;
|
||||
let podMetricsUrl = `${metricsUrl}×eries=true&target_pod=${this.state.pod}`;
|
||||
let urls = urlsForResource(this.props.pathPrefix, this.state.metricsWindow);
|
||||
|
||||
let upstreamRollupUrl = `${metricsUrl}&aggregation=source_pod&target_pod=${this.state.pod}`;
|
||||
let upstreamTimeseriesUrl = `${upstreamRollupUrl}×eries=true`;
|
||||
let downstreamRollupUrl = `${metricsUrl}&aggregation=target_pod&source_pod=${this.state.pod}`;
|
||||
let downstreamTimeseriesUrl = `${downstreamRollupUrl}×eries=true`;
|
||||
let metricsUrl = urls["deployment"].url().rollup;
|
||||
let podMetricsUrl = `${metricsUrl}×eries=true&target_pod=${this.state.pod}`;
|
||||
let upstreamRollupUrl = urls["upstream_pod"].url(this.state.pod).rollup;
|
||||
let downstreamRollupUrl = urls["downstream_pod"].url(this.state.pod).rollup;
|
||||
|
||||
let podFetch = this.api.fetch(podMetricsUrl);
|
||||
let upstreamFetch = this.api.fetch(upstreamRollupUrl);
|
||||
let upstreamTsFetch = this.api.fetch(upstreamTimeseriesUrl);
|
||||
let downstreamFetch = this.api.fetch(downstreamRollupUrl);
|
||||
let downstreamTsFetch = this.api.fetch(downstreamTimeseriesUrl);
|
||||
|
||||
Promise.all([podFetch, upstreamFetch, upstreamTsFetch, downstreamFetch, downstreamTsFetch])
|
||||
.then(([podMetrics, upstreamRollup, upstreamTimeseries, downstreamRollup, downstreamTimeseries]) => {
|
||||
Promise.all([podFetch, upstreamFetch, downstreamFetch])
|
||||
.then(([podMetrics, upstreamRollup, downstreamRollup]) => {
|
||||
let podTs = processTimeseriesMetrics(podMetrics.metrics, "targetPod");
|
||||
let podTimeseries = _.get(podTs, this.state.pod, {});
|
||||
|
||||
let upstreamMetrics = processRollupMetrics(upstreamRollup.metrics, "sourcePod");
|
||||
let upstreamTsByPod = processTimeseriesMetrics(upstreamTimeseries.metrics, "sourcePod");
|
||||
let downstreamMetrics = processRollupMetrics(downstreamRollup.metrics, "targetPod");
|
||||
let downstreamTsByPod = processTimeseriesMetrics(downstreamTimeseries.metrics, "targetPod");
|
||||
|
||||
this.setState({
|
||||
pendingRequests: false,
|
||||
lastUpdated: Date.now(),
|
||||
podTs: podTimeseries,
|
||||
upstreamMetrics: upstreamMetrics,
|
||||
upstreamTsByPod: upstreamTsByPod,
|
||||
downstreamMetrics: downstreamMetrics,
|
||||
downstreamTsByPod: downstreamTsByPod,
|
||||
loaded: true,
|
||||
error: ''
|
||||
});
|
||||
|
@ -122,12 +113,12 @@ export default class PodDetail extends React.Component {
|
|||
timeseries={this.state.podTs} />,
|
||||
<UpstreamDownstream
|
||||
key="pod-upstream-downstream"
|
||||
entity="pod"
|
||||
resource="pod"
|
||||
entity={this.state.pod}
|
||||
lastUpdated={this.state.lastUpdated}
|
||||
upstreamMetrics={this.state.upstreamMetrics}
|
||||
upstreamTsByEntity={this.state.upstreamTsByPod}
|
||||
downstreamMetrics={this.state.downstreamMetrics}
|
||||
downstreamTsByEntity={this.state.downstreamTsByPod}
|
||||
metricsWindow={this.state.metricsWindow}
|
||||
pathPrefix={this.props.pathPrefix} />
|
||||
];
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ import _ from 'lodash';
|
|||
import LineGraph from './LineGraph.jsx';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Percentage from './util/Percentage.js';
|
||||
import { processTimeseriesMetrics } from './util/MetricUtils.js';
|
||||
import React from 'react';
|
||||
import { ApiHelpers, urlsForResource } from './util/ApiHelpers.js';
|
||||
import { metricToFormatter, toClassName } from './util/Utils.js';
|
||||
import { Table, Tabs } from 'antd';
|
||||
|
||||
|
@ -92,7 +94,64 @@ const nameToDataKey = {
|
|||
successRate: "SUCCESS_RATE",
|
||||
latency: "LATENCY"
|
||||
};
|
||||
|
||||
export default class TabbedMetricsTable extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.api = ApiHelpers(this.props.pathPrefix);
|
||||
this.handleApiError = this.handleApiError.bind(this);
|
||||
this.loadFromServer = this.loadFromServer.bind(this);
|
||||
|
||||
let tsHelper = urlsForResource(this.props.pathPrefix, this.props.metricsWindow)[this.props.resource];
|
||||
|
||||
this.state = {
|
||||
timeseries: {},
|
||||
groupBy: tsHelper.groupBy,
|
||||
metricsUrl: tsHelper.url(this.props.entity),
|
||||
error: '',
|
||||
lastUpdated: this.props.lastUpdated,
|
||||
metricsWindow: "10s",
|
||||
pollingInterval: 10000,
|
||||
pendingRequests: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.hideSparklines) {
|
||||
this.loadFromServer();
|
||||
this.timerId = window.setInterval(this.loadFromServer, this.state.pollingInterval);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.clearInterval(this.timerId);
|
||||
}
|
||||
|
||||
loadFromServer() {
|
||||
if (this.state.pendingRequests) {
|
||||
return; // don't make more requests if the ones we sent haven't completed
|
||||
}
|
||||
this.setState({ pendingRequests: true });
|
||||
|
||||
this.api.fetch(this.state.metricsUrl.ts)
|
||||
.then(tsResp => {
|
||||
let tsByEntity = processTimeseriesMetrics(tsResp.metrics, this.state.groupBy);
|
||||
this.setState({
|
||||
timeseries: tsByEntity,
|
||||
pendingRequests: false,
|
||||
error: ''
|
||||
});
|
||||
})
|
||||
.catch(this.handleApiError);
|
||||
}
|
||||
|
||||
handleApiError(e) {
|
||||
this.setState({
|
||||
pendingRequests: false,
|
||||
error: `Error getting data from server: ${e.message}`
|
||||
});
|
||||
}
|
||||
|
||||
getSparklineColumn(metricName) {
|
||||
return {
|
||||
title: "10 minute history",
|
||||
|
@ -101,9 +160,9 @@ export default class TabbedMetricsTable extends React.Component {
|
|||
render: d => {
|
||||
let tsData;
|
||||
if (metricName === "latency") {
|
||||
tsData = _.get(this.props.timeseries, [d.name, "LATENCY", "P99"], []);
|
||||
tsData = _.get(this.state.timeseries, [d.name, "LATENCY", "P99"], []);
|
||||
} else {
|
||||
tsData = _.get(this.props.timeseries, [d.name, nameToDataKey[metricName]], []);
|
||||
tsData = _.get(this.state.timeseries, [d.name, nameToDataKey[metricName]], []);
|
||||
}
|
||||
|
||||
return (<LineGraph
|
||||
|
|
|
@ -4,6 +4,7 @@ import { rowGutter } from './util/Utils.js';
|
|||
import TabbedMetricsTable from './TabbedMetricsTable.jsx';
|
||||
import { Col, Row } from 'antd';
|
||||
|
||||
const maxTsToFetch = 15;
|
||||
export default class UpstreamDownstreamTables extends React.Component {
|
||||
render() {
|
||||
let numUpstreams = _.size(this.props.upstreamMetrics);
|
||||
|
@ -16,14 +17,16 @@ export default class UpstreamDownstreamTables extends React.Component {
|
|||
<div className="upstream-downstream-list">
|
||||
<div className="border-container border-neutral subsection-header">
|
||||
<div className="border-container-content subsection-header">
|
||||
Upstream {this.props.entity}s: {numUpstreams}
|
||||
Upstream {this.props.resource}s: {numUpstreams}
|
||||
</div>
|
||||
</div>
|
||||
<TabbedMetricsTable
|
||||
resource={`upstream_${this.props.entity}`}
|
||||
resource={`upstream_${this.props.resource}`}
|
||||
entity={this.props.entity}
|
||||
hideSparklines={numUpstreams > maxTsToFetch}
|
||||
lastUpdated={this.props.lastUpdated}
|
||||
metrics={this.props.upstreamMetrics}
|
||||
timeseries={this.props.upstreamTsByEntity}
|
||||
metricsWindow={this.props.metricsWindow}
|
||||
pathPrefix={this.props.pathPrefix} />
|
||||
</div>
|
||||
}
|
||||
|
@ -32,14 +35,16 @@ export default class UpstreamDownstreamTables extends React.Component {
|
|||
<div className="upstream-downstream-list">
|
||||
<div className="border-container border-neutral subsection-header">
|
||||
<div className="border-container-content subsection-header">
|
||||
Downstream {this.props.entity}s: {numDownstreams}
|
||||
Downstream {this.props.resource}s: {numDownstreams}
|
||||
</div>
|
||||
</div>
|
||||
<TabbedMetricsTable
|
||||
resource={`downstream_${this.props.entity}`}
|
||||
resource={`downstream_${this.props.resource}`}
|
||||
entity={this.props.entity}
|
||||
hideSparklines={numDownstreams > maxTsToFetch}
|
||||
lastUpdated={this.props.lastUpdated}
|
||||
metrics={this.props.downstreamMetrics}
|
||||
timeseries={this.props.downstreamTsByEntity}
|
||||
metricsWindow={this.props.metricsWindow}
|
||||
pathPrefix={this.props.pathPrefix} />
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -23,3 +23,86 @@ export const ApiHelpers = pathPrefix => {
|
|||
fetchPods
|
||||
};
|
||||
};
|
||||
|
||||
export const urlsForResource = (pathPrefix, metricsWindow) => {
|
||||
/*
|
||||
Timeseries fetches used in the TabbedMetricsTable
|
||||
Rollup fetches used throughout app
|
||||
*/
|
||||
let metricsUrl = `${pathPrefix}/api/metrics?window=${metricsWindow}`;
|
||||
|
||||
return {
|
||||
// all deploys (default), or a given deploy if specified
|
||||
"deployment": {
|
||||
groupBy: "targetDeploy",
|
||||
url: (deploy = null) => {
|
||||
let timeseriesUrl = !deploy ? `${metricsUrl}×eries=true` :
|
||||
`${metricsUrl}×eries=true&target_deploy=${deploy}`;
|
||||
return {
|
||||
ts: timeseriesUrl,
|
||||
rollup: metricsUrl
|
||||
};
|
||||
}
|
||||
},
|
||||
"pod": {
|
||||
// all pods of a given deploy
|
||||
groupBy: "targetPod",
|
||||
url: deploy => {
|
||||
let podRollupUrl = `${metricsUrl}&aggregation=target_pod&target_deploy=${deploy}`;
|
||||
let podTimeseriesUrl = `${podRollupUrl}×eries=true`;
|
||||
return {
|
||||
ts: podTimeseriesUrl,
|
||||
rollup: podRollupUrl
|
||||
};
|
||||
}
|
||||
},
|
||||
"upstream_deployment": {
|
||||
// all upstreams of a given deploy
|
||||
groupBy: "sourceDeploy",
|
||||
url: deploy => {
|
||||
let upstreamRollupUrl = `${metricsUrl}&aggregation=source_deploy&target_deploy=${deploy}`;
|
||||
let upstreamTimeseriesUrl = `${upstreamRollupUrl}×eries=true`;
|
||||
return {
|
||||
ts: upstreamTimeseriesUrl,
|
||||
rollup: upstreamRollupUrl
|
||||
};
|
||||
}
|
||||
},
|
||||
"downstream_deployment": {
|
||||
// all downstreams of a given deploy
|
||||
groupBy: "targetDeploy",
|
||||
url: deploy => {
|
||||
let downstreamRollupUrl = `${metricsUrl}&aggregation=target_deploy&source_deploy=${deploy}`;
|
||||
let downstreamTimeseriesUrl = `${downstreamRollupUrl}×eries=true`;
|
||||
return {
|
||||
ts: downstreamTimeseriesUrl,
|
||||
rollup: downstreamRollupUrl
|
||||
};
|
||||
}
|
||||
},
|
||||
"upstream_pod": {
|
||||
groupBy: "sourcePod",
|
||||
url: pod => {
|
||||
let upstreamRollupUrl = `${metricsUrl}&aggregation=source_pod&target_pod=${pod}`;
|
||||
let upstreamTimeseriesUrl = `${upstreamRollupUrl}×eries=true`;
|
||||
|
||||
return {
|
||||
ts: upstreamTimeseriesUrl,
|
||||
rollup: upstreamRollupUrl
|
||||
};
|
||||
}
|
||||
},
|
||||
"downstream_pod": {
|
||||
groupBy: "targetPod",
|
||||
url: pod => {
|
||||
let downstreamRollupUrl = `${metricsUrl}&aggregation=target_pod&source_pod=${pod}`;
|
||||
let downstreamTimeseriesUrl = `${downstreamRollupUrl}×eries=true`;
|
||||
|
||||
return {
|
||||
ts: downstreamTimeseriesUrl,
|
||||
rollup: downstreamRollupUrl
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue