blob: ce4c149d2a96b7623c39de75a98c41230596c6d0 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Row, Col, Select, Card, Form, Breadcrumb } from 'antd';
import { AppTopology } from 'components/Topology';
import { Line } from 'components/Charts';
import { Panel } from 'components/Page';
import RankList from 'components/RankList';
import ServiceInstanceLitePanel from 'components/ServiceInstanceLitePanel';
import ServiceInstance from './ServiceInstance';
import { getServiceInstanceId, redirect } from '../../utils/utils';
import { axisMY } from '../../utils/time';
const { Option } = Select;
const { Item: FormItem } = Form;
const middleColResponsiveProps = {
xs: 24,
sm: 24,
md: 12,
lg: 12,
xl: 12,
style: { marginTop: 8 },
};
@connect(state => ({
service: state.service,
duration: state.global.duration,
globalVariables: state.global.globalVariables,
}))
@Form.create({
mapPropsToFields(props) {
const { variables: { values, labels } } = props.service;
return {
serviceId: Form.createFormField({
value: { key: values.serviceId ? values.serviceId : '', label: labels.serviceId ? labels.serviceId : '' },
}),
};
},
})
export default class Service extends PureComponent {
componentDidMount() {
this.props.dispatch({
type: 'service/initOptions',
payload: { variables: this.props.globalVariables },
});
}
componentWillUpdate(nextProps) {
if (nextProps.globalVariables.duration === this.props.globalVariables.duration) {
return;
}
this.props.dispatch({
type: 'service/initOptions',
payload: { variables: nextProps.globalVariables },
});
}
handleSelect = (selected) => {
this.props.dispatch({
type: 'service/saveVariables',
payload: {
values: { serviceId: selected.key },
labels: { serviceId: selected.label },
},
});
}
handleChange = (variables) => {
const { data: { serviceInstanceInfo, showServiceInstance } } = this.props.service;
if (showServiceInstance) {
this.handleSelectServiceInstance(serviceInstanceInfo.key, serviceInstanceInfo);
} else {
this.props.dispatch({
type: 'service/fetchData',
payload: { variables, reducer: 'saveService' },
});
}
}
handleGoService = () => {
this.props.dispatch({
type: 'service/hideServiceInstance',
});
}
handleGoServiceInstance = () => {
this.props.dispatch({
type: 'service/showServiceInstance',
});
}
handleSelectServiceInstance = (serviceInstanceId, serviceInstanceInfo) => {
const { globalVariables: { duration } } = this.props;
this.props.dispatch({
type: 'service/fetchServiceInstance',
payload: { variables: { duration, serviceInstanceId }, serviceInstanceInfo },
});
}
renderApp = () => {
const { getFieldDecorator } = this.props.form;
const { variables: { values, options, labels }, data } = this.props.service;
return (
<div>
<Form layout="inline">
<FormItem>
{getFieldDecorator('serviceId')(
<Select
showSearch
optionFilterProp="children"
style={{ width: 200 }}
placeholder="Select a service"
labelInValue
onSelect={this.handleSelect.bind(this)}
>
{options.serviceId && options.serviceId.map(service =>
<Option key={service.key} value={service.key}>{service.label}</Option>)}
</Select>
)}
</FormItem>
</Form>
<Panel
variables={values}
globalVariables={this.props.globalVariables}
onChange={this.handleChange}
>
<Row gutter={0}>
<Col {...{ ...middleColResponsiveProps, xl: 16, lg: 12, md: 24 }}>
<Card
title="Service Map"
bordered={false}
bodyStyle={{ padding: 0 }}
>
<AppTopology
elements={data.getServiceTopology}
height={335}
layout={{
name: 'dagre',
rankDir: 'LR',
minLen: 4,
}}
/>
</Card>
</Col>
<Col {...{ ...middleColResponsiveProps, xl: 8, lg: 12, md: 24 }}>
<Card
bordered={false}
bodyStyle={{ padding: '10px 10px', height: 391 }}
>
<ServiceInstanceLitePanel
data={data}
serviceInstanceList={data.getServiceInstances}
duration={this.props.duration}
onSelectServiceInstance={this.handleSelectServiceInstance}
onMoreServiceInstance={this.handleGoServiceInstance}
/>
</Card>
</Col>
</Row>
<Row>
<Col {...{ ...middleColResponsiveProps, xl: 24, lg: 24, md: 24 }}>
<Card
title="Response Time"
bordered={false}
bodyStyle={{ padding: 5, height: 150}}
>
<Line
data={axisMY(this.props.duration, [{ title: 'p99', value: data.getP99}, { title: 'p95', value: data.getP95}
, { title: 'p90', value: data.getP90}, { title: 'p75', value: data.getP75}, { title: 'p50', value: data.getP50}])}
/>
</Card>
</Col>
</Row>
<Row gutter={8}>
<Col {...{ ...middleColResponsiveProps, xl: 12, lg: 12, md: 24 }}>
<Card
title="Running ServiceInstance"
bordered={false}
bodyStyle={{ padding: 5 }}
>
<RankList
data={data.getServiceInstanceThroughput}
renderValue={_ => `${_.value} cpm`}
color="#965fe466"
/>
</Card>
</Col>
<Col {...{ ...middleColResponsiveProps, xl: 12, lg: 12, md: 24 }}>
<Card
title="Slow Endpoint"
bordered={false}
bodyStyle={{ padding: '0px 10px' }}
>
<RankList
data={data.getSlowEndpoint}
renderValue={_ => `${_.value} ms`}
onClick={(key, item) => redirect(this.props.history, '/monitor/endpoint', { key,
label: item.label,
serviceId: values.serviceId,
serviceName: labels.serviceId })}
/>
</Card>
</Col>
</Row>
</Panel>
</div>
);
}
render() {
const { service, duration } = this.props;
const { variables, data } = service;
const { showServiceInstance, serviceInstanceInfo } = data;
return (
<Row type="flex" justify="start">
{showServiceInstance ? (
<Col span={showServiceInstance ? 24 : 0}>
<Breadcrumb>
<Breadcrumb.Item>
Service
</Breadcrumb.Item>
<Breadcrumb.Item>
<a onClick={this.handleGoService}>{variables.labels.serviceId}</a>
</Breadcrumb.Item>
<Breadcrumb.Item>{getServiceInstanceId(serviceInstanceInfo)}</Breadcrumb.Item>
</Breadcrumb>
<Panel
variables={variables.values}
globalVariables={this.props.globalVariables}
onChange={this.handleChange}
>
<ServiceInstance data={data} duration={duration} />
</Panel>
</Col>
) : null}
<Col span={showServiceInstance ? 0 : 24}>
{this.renderApp()}
</Col>
</Row>
);
}
}