import _ from 'lodash'; import BarChart from './BarChart.jsx'; import ConduitSpinner from "./ConduitSpinner.jsx"; import ErrorBanner from './ErrorBanner.jsx'; import HealthPane from './HealthPane.jsx'; import { incompleteMeshMessage } from './util/CopyUtils.jsx'; import Metric from './Metric.jsx'; import React from 'react'; 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'; import 'whatwg-fetch'; export default class Deployment 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); this.state = this.initialState(this.props.location); } componentDidMount() { this.loadFromServer(); this.timerId = window.setInterval(this.loadFromServer, this.state.pollingInterval); } componentWillReceiveProps(nextProps) { window.scrollTo(0, 0); this.setState(this.initialState(nextProps.location), () => { this.loadFromServer(); }); } componentWillUnmount() { window.clearInterval(this.timerId); } initialState(location) { let urlParams = new URLSearchParams(location.search); let deployment = urlParams.get("deploy"); return { lastUpdated: 0, pollingInterval: 10000, metricsWindow: "10m", deploy: deployment, metrics: [], pods: [], upstreamMetrics: [], downstreamMetrics: [], pathMetrics: [], pendingRequests: false, loaded: false, error: '' }; } loadFromServer() { if (this.state.pendingRequests) { return; // don't make more requests if the ones we sent haven't completed } this.setState({ pendingRequests: 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 pathMetricsUrl = urls["path"].url(this.state.deploy).rollup; let deployFetch = this.api.fetch(deployMetricsUrl); let podListFetch = this.api.fetchPods(); let podRollupFetch = this.api.fetch(podRollupUrl); let upstreamFetch = this.api.fetch(upstreamRollupUrl); let downstreamFetch = this.api.fetch(downstreamRollupUrl); let pathsFetch = this.api.fetch(pathMetricsUrl); // expose serverPromise for testing this.serverPromise = Promise.all([deployFetch, podRollupFetch, upstreamFetch, downstreamFetch, podListFetch, pathsFetch]) .then(([deployMetrics, podRollup, upstreamRollup, downstreamRollup, podList, paths]) => { let tsByDeploy = processTimeseriesMetrics(deployMetrics.metrics, "targetDeploy"); let podMetrics = processRollupMetrics(podRollup.metrics, "targetPod"); let upstreamMetrics = processRollupMetrics(upstreamRollup.metrics, "sourceDeploy"); let downstreamMetrics = processRollupMetrics(downstreamRollup.metrics, "targetDeploy"); let pathMetrics = processRollupMetrics(paths.metrics, "path"); let deploy = _.find(getPodsByDeployment(podList.pods), ["name", this.state.deploy]); let totalRequestRate = _.sumBy(podMetrics, "requestRate"); _.each(podMetrics, datum => datum.totalRequests = totalRequestRate); this.setState({ metrics: podMetrics, pods: deploy.pods, added: deploy.added, deployTs: _.get(tsByDeploy, this.state.deploy, {}), upstreamMetrics: upstreamMetrics, downstreamMetrics: downstreamMetrics, pathMetrics: pathMetrics, lastUpdated: Date.now(), pendingRequests: false, loaded: true, error: '' }); }).catch(this.handleApiError); } handleApiError(e) { this.setState({ pendingRequests: false, error: `Error getting data from server: ${e.message}` }); } numUpstreams() { return _.size(this.state.upstreamMetrics); } numDownstreams() { return _.size(this.state.downstreamMetrics); } renderSections() { let srTs = _.get(this.state.deployTs, "SUCCESS_RATE", []); let currentSuccessRate = _.get(_.last(srTs), "value"); return [ , _.isEmpty(this.state.deployTs) ? null : , this.renderMidsection(), , this.renderPaths() ]; } renderMidsection() { let podTableData = this.state.metrics; if (_.isEmpty(this.state.metrics)) { podTableData = _.map(this.state.pods, po => emptyMetric(po.name)); } return (
Pod summary
{ _.isEmpty(this.state.metrics) ? null :
Request load by pod
}
Deployment details
); } renderPaths() { return _.size(this.state.pathMetrics) === 0 ? null :
Paths
; } renderDeploymentTitle() { return (

{this.state.deploy}

{ !this.state.added ? (

UNADDED

{incompleteMeshMessage(this.state.deploy)}
) : null }
); } render() { return (
{ !this.state.error ? null : } { !this.state.loaded ? :
Deployment detail
{this.renderDeploymentTitle()}
{this.renderSections()}
}
); } }