12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748 |
- import debug from 'debug';
- import React from 'react';
- import classNames from 'classnames';
- import PropTypes from 'prop-types';
- import { connect } from 'react-redux';
- import { Map as makeMap } from 'immutable';
- import { noop } from 'lodash';
- import { clickCloseDetails, clickShowTopologyForNode } from '../actions/request-actions';
- import { brightenColor, getNeutralColor, getNodeColorDark,getStatusColor,setNodeColor } from '../utils/color-utils';
- import { isGenericTable, isPropertyList } from '../utils/node-details-utils';
- import { resetDocumentTitle, setDocumentTitle } from '../utils/title-utils';
- import Overlay from './overlay';
- import MatchedText from './matched-text';
- import NodeDetailsControls from './node-details/node-details-controls';
- import NodeDetailsGenericTable from './node-details/node-details-generic-table';
- import NodeDetailsPropertyList from './node-details/node-details-property-list';
- import NodeDetailsHealth from './node-details/node-details-health';
- import f from './node-details/node-details-info';
- import NodeDetailsRelatives from './node-details/node-details-relatives';
- import NodeDetailsTable from './node-details/node-details-table';
- import Warning from './warning';
- import * as echarts from 'echarts'
- import axios from 'axios'
- import moment from 'moment'
- import { Table,Radio,Checkbox,Button, Drawer, Descriptions } from "antd";
- import "antd/dist/antd.css";
- import '../../styles/nodeDetail.less'
- import getToken from '../utils/get-token'
- const log = debug('scope:node-details');
- function getTruncationText(count) {
- return 'This section was too long to be handled efficiently and has been truncated'
- + ` (${count} extra entries not included). We are working to remove this limitation.`;
- }
- class NodeDetails extends React.Component {
- constructor(props, context) {
- super(props, context);
- this.state = {
- // baseUrl:'http://observe-server.cestong.com.cn', //本地调试使用
- // traceUrl:'http://observe-front.cestong.com.cn', //本地调试使用
- // coreBaseUrl: 'http://observe-front.cestong.com.cn/core', //本地调试使用
- coreBaseUrl:'',//上线时打开
- baseUrl:'/re', //上线时打开
- traceUrl:'',//上线时打开
- nodeData:{}, //节点基础信息
- AnalystData:{},//散点图
- queryParams:{
- start_time:Math.round((new Date().getTime())/1000 - (5*60)),
- end_time:Math.round(new Date().getTime()/1000),
- app_alias:'opentelemetry-demo',
- service_name:'frontend',
- percentile:0.5,
- sort_field:'Timestamp',
- sort_type: 'DESC'
- },
- traceData:[],
- livenessData:[],
- barData:[],
- tableData: [],
- bgColor:setNodeColor('R'),
- pagination: {
- pageIndex:1,
- pageSize:10,
- total:0,
- current:1,
- },
- pagination2: {
- page_num:1,
- page_size:10,
- total:0,
- current:1,
- },
- traceQuery:{
- only_exception:0,
- only_database:0,
- },
- timeoutId: null,
- messaging_stats: {
- topic_stats:[]
- },
- cloudTable: [],
- cloudTable2: [],
- cloudPagination: {
- page_num:1,
- page_size:10,
- total:0,
- current:1,
- }
- }
- }
- handleClickClose = (ev) => {
- ev.preventDefault();
- this.props.clickCloseDetails(this.props.nodeId);
- }
- handleShowTopologyForNode = (ev) => {
- ev.preventDefault();
- this.props.clickShowTopologyForNode(this.props.topologyId, this.props.nodeId);
- }
- componentDidMount() {
- let _this = this
- //上线时打开开始
- this.setQueryParams();//做为iframe嵌套时打开,上线时打开
- const traceURL = `http://${parent.location.hostname}`
- const coreBaseURL = `http://${parent.location.hostname}/core`
- this.setState({
- traceUrl:traceURL,
- coreBaseUrl:coreBaseURL
- },()=>{
- })
- //上线时打开结束
- // 接受父组件参数
- // window.top == window true 自己本身没有被嵌套
- if(window.top !== window){// false 被嵌套
- const data = JSON.parse(parent.localStorage.global_times)
- const queryParams = _this.state.queryParams
- queryParams.start_time = data.startTime
- queryParams.end_time = data.endTime
- _this.setState({
- queryParams: queryParams
- },()=>{
- });
- }
- window.addEventListener('message', function(event) {
- // 处理接收到的消息
- const data = event.data
- const queryParams = _this.state.queryParams
- if (data.eventType == 'globalTimesChange') {
- queryParams.start_time = data.data.startTime
- queryParams.end_time = data.data.endTime
- _this.setState({
- queryParams: queryParams
- },()=>{
- if (_this.props.shape == 'cylinder'){
- _this.getTableData(); //table
- _this.getBarData(); // 柱形图
- }
- if (_this.props.shape == 'dottedcylinder'){
- _this.getDottBasicsData() // dottedcylinder 基础信息
- }
- if (_this.props.shape == 'circle'){
- _this.getNodeBasic();
- _this.getNodeAnalyst();//获取散点图
- _this.getNodeLiveness(); // 折线图
- _this.getServiceSpans();
- }
- if (_this.props.shape == 'cloud'){
- _this.getCloudTableData()
- }
- });
- } else if (data.eventType == 'getLoginAuth') {
- _this.setState({
- getToken: data.data
- }, ()=>{})
- }
- }, false);
- }
- componentWillUnmount() {
- clearTimeout(this.timeoutId);
- }
- setQueryParams(){
- var strr = parent.location.href; //上线做为iframe嵌套时使用
- let param = this.parseQueryString(strr); //全链路需要的参数多,因此解析成对象形式
- const queryParams = this.state.queryParams;
- if(parseInt(param.start_time)!=0 && parseInt(param.end_time) !=0){ //上线时打开
- let newStartTime = parseInt(param.start_time); // 设置新的属性值
- let newEndTime = parseInt(param.end_time); // 设置新的属性值
- queryParams.start_time = newStartTime
- queryParams.end_time = newEndTime
- }
- const newAppAlias = param.app_alias
- queryParams.app_alias = newAppAlias
- this.setState({
- queryParams: queryParams
- },()=>{
- if (this.props.shape == 'cylinder'){
- this.getTableData(); //table
- this.getBarData(); // 柱形图
- }
- if (this.props.shape == 'dottedcylinder'){
- this.getDottBasicsData() // dottedcylinder 基础信息
- }
- if (this.props.shape == 'circle'){
- this.getNodeBasic();
- this.getNodeAnalyst();//获取散点图
- this.getNodeLiveness(); // 折线图
- this.getServiceSpans();
- }
- if (this.props.shape == 'cloud') {
- this.getCloudTableData()
- }
- });
- }
- //解析URL
- parseQueryString(url){
- var json = {};
- var arr = url.substr(url.indexOf('?') + 1).split('&');
- arr.forEach(item=>{
- var tmp = item.split('=');
- json[tmp[0]] = tmp[1];
- });
- return json;
- }
- componentWillUnmount() {
- resetDocumentTitle();
- }
- renderTools() {
- const showSwitchTopology = this.props.nodeId !== this.props.selectedNodeId;
- const topologyTitle = `View ${this.props.label} in ${this.props.topologyId}`;
- return (
- <div className="node-details-tools-wrapper">
- <div className="node-details-tools">
- {showSwitchTopology
- && (
- <i
- title={topologyTitle}
- className="fa fa-long-arrow-alt-left"
- onClick={this.handleShowTopologyForNode}>
- <span>
- Show in
- {/* <span>{this.props.topologyId.replace(/-/g, ' ')}</span> */}
- </span>
- </i>
- )
- }
- <i
- title="Close details"
- className="fa fa-times close-details"
- onClick={this.handleClickClose}
- />
- </div>
- </div>
- );
- }
- renderLoading() {
- const node = this.props.nodes.get(this.props.nodeId);
- const label = node ? node.get('label') : this.props.label;
- // NOTE: If we start the fa-spin animation before the node details panel has been
- // mounted, the spinner is displayed blurred the whole time in Chrome (possibly
- // caused by a bug having to do with animating the details panel).
- const spinnerClassName = classNames('fa fa-circle-notch', { 'fa-spin': this.props.mounted });
- const nodeColor = (node
- ? getNodeColorDark(node.get('rank'), label, node.get('pseudo'))
- : getNeutralColor());
- const tools = this.renderTools();
- const styles = {
- header: {
- backgroundColor: nodeColor
- }
- };
- return (
- <div className="node-details">
- {tools}
- <div className="node-details-header" style={styles.header}>
- <div className="node-details-header-wrapper">
- <h2 className="node-details-header-label truncate">
- {label}
- </h2>
- <div className="node-details-relatives truncate">
- Loading...
- </div>
- </div>
- </div>
- <div className="node-details-content" style="padding:0 12px">
- <div className="node-details-content-loading">
- <span className={spinnerClassName} />
- </div>
- </div>
- </div>
- );
- }
- renderNotAvailable() {
- const tools = this.renderTools();
- return (
- <div className="node-details">
- {tools}
- <div className="node-details-header node-details-header-notavailable">
- <div className="node-details-header-wrapper">
- <h2 className="node-details-header-label">
- {this.props.label}
- </h2>
- <div className="node-details-relatives truncate">
- n/a
- </div>
- </div>
- </div>
- <div className="node-details-content">
- <p className="node-details-content-info">
- <strong>{this.props.label}</strong>
- {' '}
- not found!
- </p>
- </div>
- <Overlay faded={this.props.transitioning} />
- </div>
- );
- }
- render() {
- // if (this.props.notFound) {
- // return this.renderNotAvailable();
- // }
- // if (this.props.details) {
- // return this.renderDetails();
- // }
- // return this.renderLoading();
- return this.renderNodeDetails();
- }
- renderDetails() {
- const {
- details, nodeControlStatus, nodeMatches = makeMap(), topologyId
- } = this.props;
- const showControls = details.controls && details.controls.length > 0;
- const nodeColor = getNodeColorDark(details.rank, details.label, details.pseudo);
- // const nodeColor= setNodeColor(details.color)
- const {error, pending} = nodeControlStatus ? nodeControlStatus.toJS() : {};
- const tools = this.renderTools();
- const styles = {
- controls: {
- backgroundColor: brightenColor(nodeColor)
- },
- header: {
- backgroundColor: nodeColor
- }
- };
- return (
- <div className="tour-step-anchor node-details">
- {tools}
- <div className="node-details-header" style={styles.header}>
- <div className="node-details-header-wrapper">
- <h2 className="node-details-header-label truncate" title={details.label}>
- <MatchedText text={details.label} match={nodeMatches.get('label')} />
- </h2>
- <div className="node-details-header-relatives">
- {details.parents && (
- <NodeDetailsRelatives
- matches={nodeMatches.get('parents')}
- relatives={details.parents} />
- )}
- </div>
- </div>
- </div>
- {showControls
- && (
- <div className="tour-step-anchor node-details-controls-wrapper" style={styles.controls}>
- <NodeDetailsControls
- nodeId={this.props.nodeId}
- controls={details.controls}
- pending={pending}
- error={error} />
- </div>
- )
- }
- <div className="node-details-content">
- {details.metrics
- && (
- <div className="node-details-content-section">
- <div className="node-details-content-section-header">Status</div>
- <NodeDetailsHealth
- metrics={details.metrics}
- topologyId={topologyId}
- />
- </div>
- )
- }
- {details.metadata
- && (
- <div className="node-details-content-section">
- <div className="node-details-content-section-header">Info</div>
- <NodeDetailsInfo rows={details.metadata} matches={nodeMatches.get('metadata')} />
- </div>
- )
- }
- {details.connections && details.connections.filter(cs => cs.connections.length > 0)
- .map(connections => (
- <div className="node-details-content-section" key={connections.id}>
- <NodeDetailsTable
- {...connections}
- nodes={connections.connections}
- nodeIdKey="nodeId"
- />
- </div>
- ))}
- {details.children && details.children.map(children => (
- <div className="node-details-content-section" key={children.topologyId}>
- <NodeDetailsTable {...children} />
- </div>
- ))}
- {details.tables && details.tables.length > 0 && details.tables.map((table) => {
- if (table.rows.length > 0) {
- return (
- <div className="node-details-content-section" key={table.id}>
- <div className="node-details-content-section-header">
- {table.label && table.label.length > 0 && table.label}
- {table.truncationCount > 0
- && (
- <span
- className="node-details-content-section-header-warning">
- <Warning text={getTruncationText(table.truncationCount)} />
- </span>
- )
- }
- </div>
- {this.renderTable(table)}
- </div>
- );
- }
- return null;
- })}
- {this.props.renderNodeDetailsExtras({ details, topologyId })}
- </div>
- <Overlay faded={this.props.transitioning} />
- </div>
- );
- }
- renderNodeDetails(){
- const {
- details, nodeControlStatus, nodeMatches = makeMap(), topologyId
- } = this.props;
- const node = this.props.nodes.get(this.props.nodeId);
- const label = node ? node.get('label') : this.props.label;
- // const nodeColor = getNodeColorDark(details.rank, details.label, details.pseudo);
- // const nodeColor= setNodeColor(details.color)
- const {error, pending} = nodeControlStatus ? nodeControlStatus.toJS() : {};
- const tools = this.renderTools();
- const styles = {
- controls: {
- // backgroundColor: brightenColor(nodeColor)
- },
- header: {
- // backgroundColor: '#5BB2FA'
- backgroundColor:this.state.bgColor
- }
- };
- const columns = [
- {
- title: 'TraceID',
- dataIndex: 'trace_id',
- key: 'trace_id',
- width:'20%',
- ellipsis:true,
- align:'center',
- // scopedSlots:{customRender:'trace_id'},
- render: (text,record) => <a target='_blank' href={`${this.state.traceUrl}/#/latency/index?traceId=${text}&app_alias=${this.state.queryParams.app_alias}&span_id=${record.span_id}&datetime=${Date.parse(record.datetime)/1000}`}>{text}</a>
- },
- {
- title: '方法',
- dataIndex: 'method',
- key: 'method',
- width:'15%',
- ellipsis:true,
- align:'center'
- },
- {
- title: '状态码',
- dataIndex: 'code',
- key: 'code',
- width:'15%',
- ellipsis:true,
- align:'center'
- },
- {
- title: '请求时长(ms)',
- dataIndex: 'duration',
- key: 'duration',
- width:'30%',
- ellipsis:true,
- align:'center',
- render:(text) => <span>{text.toFixed(2)}</span>
- },
- {
- title: '日期',
- dataIndex: 'datetime',
- key: 'datetime',
- width:'30%',
- ellipsis:true,
- align:'center',
- defaultSortOrder: 'descend',
- sorter:true
- },
- ]
- const colums2 = [
- {
- title: '服务名',
- dataIndex: 'service_name',
- key: 'service_name',
- ellipsis:true,
- align:'center',
- render: (text, record) => (
- <span>{record.service_name_cn? record.service_name_cn: record.service_name}</span>
- )
- },
- {
- title: '执行语句',
- dataIndex: 'query',
- key: 'query',
- width:'40%',
- ellipsis:true,
- align:'center',
- render: (text, record) => (
- <textarea value={record.query} disabled rows="2" />
- )
- },
- {
- title: '慢查询次数',
- dataIndex: 'slow_num',
- key: 'slow_num',
- ellipsis:true,
- align:'center'
- },
- {
- title: '错误数量',
- dataIndex: 'error_num',
- key: 'error_num',
- ellipsis:true,
- align:'center'
- }
- ]
- const cloudColums = [
- {
- title: '应用名称',
- dataIndex: 'app_name',
- align:'center',
- width: 200,
- key: 'app_name'
- },
- {
- title: '请求总数',
- width: 100,
- dataIndex: 'request_total',
- align:'center',
- key: 'request_total',
- },
- {
- title: '错误数',
- dataIndex: 'error_num',
- align:'center',
- width: 130,
- key: 'error_num',
- },
- {
- title: '平均延迟',
- dataIndex: 'duration_average',
- align:'center',
- key: 'duration_average',
- width: 130,
- render: (text, record) => (
- <span>{record.duration_average.toFixed(2)}</span>
- )
- },
- {
- title: '中位延迟',
- dataIndex: 'duration_median',
- align:'center',
- width: 140,
- key: 'duration_median',
- render: (text, record) => (
- <span>{record.duration_median.toFixed(2)}</span>
- )
- }
- ];
- const cloudColums2 = [
- {
- title: '应用名称',
- align:'center',
- dataIndex: 'name',
- width: 210,
- key: 'name'
- },
- {
- title: '请求总数',
- align:'center',
- width: 100,
- dataIndex: 'request_total',
- key: 'request_total',
- },
- {
- title: '错误数',
- align:'center',
- width: 140,
- dataIndex: 'error_num',
- key: 'error_num',
- },
- {
- title: '平均延迟',
- dataIndex: 'duration_average',
- align:'center',
- width: 130,
- key: 'duration_average',
- render: (text, record) => (
- <span>{record.duration_average.toFixed(2)}</span>
- )
- },
- {
- title: '中位延迟',
- dataIndex: 'duration_median',
- align:'center',
- width: 140,
- key: 'duration_median',
- render: (text, record) => (
- <span>{record.duration_median.toFixed(2)}</span>
- )
- }
- ];
- const expandedRowRender = (record) => {
- const columns = [
- {
- title: '服务名',
- dataIndex: 'service_name_cn',
- align:'center',
- width: 180,
- key: 'service_name_cn',
- },
- {
- title: '请求总数',
- dataIndex: 'request_total',
- align:'center',
- width: 114,
- key: 'request_total',
- },
- {
- title: '错误数',
- dataIndex: 'error_num',
- align:'center',
- width: 120,
- key: 'error_num',
- },
- {
- title: '平均延迟',
- dataIndex: 'duration_average',
- key: 'duration_average',
- align:'center',
- width: 130,
- render: (text, record) => (
- <span>{record.duration_average.toFixed(2)}</span>
- )
- },
- {
- title: '中位延迟',
- dataIndex: 'duration_median',
- key: 'duration_median',
- align:'center',
- width: 130,
- render: (text, record) => (
- <span>{record.duration_median.toFixed(2)}</span>
- )
- }
- ];
- return <Table columns={columns} rowKey={'service_name'} dataSource={record.service_list} pagination={false} size='small' />;
- };
- return (
- <Drawer placement="right"
- onClose={this.handleClickClose} visible={true}
- destroyOnClose={true}
- width="65%">
- <div className="tour-step-anchor node-details">
- {tools}
- <div className="node-details-header" style={styles.header}>
- <div className="node-details-header-wrapper">
- <h2 className="node-details-header-label truncate">
- {label}
- </h2>
- <div className="node-details-header-relatives">
- {this.state.nodeData.subtitle}
- </div>
- </div>
- </div>
- {/* {showControls
- && (
- <div className="tour-step-anchor node-details-controls-wrapper" style={styles.controls}>
- <NodeDetailsControls
- nodeId={this.props.nodeId}
- controls={details.controls}
- pending={pending}
- error={error} />
- </div>
- )
- } */}
- {
- this.props.shape == 'cylinder'&&
- <div className="node-details-content" >
- <div style={{marginTop:'16px'}}>
- <div className="node-details-content-section-header" style={{marginBottom:0}}>执行次数</div>
- <div id="chartContent" style={{width: '100%', height: '300px', borderRadius: '12px'}}></div>
- <div style={{paddingBottom:'20px'}}>
- <Table dataSource={this.state.tableData} columns={colums2} rowKey={'service_name'+ Math.random()} pagination={this.state.pagination2} onChange={this.handleTableChange2} size='small' >
- </Table>
- </div>
- </div>
- </div>
- }
- { this.props.shape == 'circle'&&
- (<div className="node-details-content">
- <div>
- <div className="node-details-content-section">
- <div className="node-details-content-section-header">基本信息</div>
- <div className='node-details-info'>
- <div style={{textAlign:'right'}}>
- {/* <Button size={size}>进入服务详情</Button> */}
- <Button size='small'><a target='_blank' style={{fontSize:'12px'}} href={`${this.state.traceUrl}/#/service/serviceDetail/index?app_alias=${this.state.queryParams.app_alias}&service_name=${label}`}>服务详情</a></Button>
- </div>
- </div>
- </div>
- {/* https://zhongdian.feishu.cn/docx/HkXSdrGa2ou84zxPvvycGX5Fn3b 中让去掉的 */}
- {/* <div className="node-details-content-section">
- <div className="node-details-content-section-header">状态</div>
- <div>
- <div className='node-details-info-field'>
- <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>可用性</div>
- <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>
- {this.state.nodeData.apdex?Math.floor(this.state.nodeData.apdex*100):0}
- </div>
- </div>
- <div className='node-details-info-field'>
- <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>成功率</div>
- <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.arc__success?(this.state.nodeData.arc__success*100).toFixed(2):0}%</div>
- </div>
- <div className='node-details-info-field'>
- <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>失败率</div>
- <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.arc__faild?(this.state.nodeData.arc__faild*100).toFixed(2):0}%</div>
- </div>
- <div className='node-details-info-field'>
- <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>接收数量</div>
- <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.receive?this.state.nodeData.receive:0}</div>
- </div>
- <div className='node-details-info-field'>
- <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>发送数量</div>
- <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.send?this.state.nodeData.send:0}</div>
- </div>
- </div>
- </div> */}
- <div className="node-details-content-section">
- <div className="node-details-content-section-header">调用次数</div>
- <div className='node-details-info'>
- {
- this.state.livenessData.length>0?
- (<div>
- <div id='box' className="echartsbox"></div>
- </div>)
- :(
- <div className='noData'>暂无数据</div>
- )
- }
- </div>
- </div>
- <div className="node-details-content-section">
- <div className="node-details-content-section-header">延迟比例</div>
- <div className='node-details-info' style={{marginTop: "-15px",position:'relative'}}>
- {
- (JSON.stringify(this.state.AnalystData)!="{}" && this.state.AnalystData.failed || this.state.AnalystData.success )?
- (<div>
- <div id='main' className="echartsbox" style={{height:'240px'}}></div>
- </div>)
- :(
- <div className='noData'>暂无数据</div>
- )
- }
- <div className='LatencySelect'>
- <Radio.Group onChange={this.onChange} value={this.state.queryParams.percentile} size="small">
- <Radio value={0.5}>50分位</Radio>
- {/* <Radio value={0.95}>p.95</Radio> */}
- <Radio value={0.99}>99分位</Radio>
- </Radio.Group>
- </div>
- </div>
- </div>
- <div className='node-details-content-section'>
- <div className="node-details-content-section-header">异常Trace</div>
- <div className='node-serch'>
- <Checkbox onChange={this.onChangeError}>仅异常</Checkbox>
- <Checkbox onChange={this.onChangeSql}>仅SQL</Checkbox>
- </div>
- <Table dataSource={this.state.traceData} columns={columns} rowKey='span_id' pagination={this.state.pagination} onChange={this.handleTableChange} size='small'>
- {/* <span slot='trace_id' slot-scope='text,record'>
- <template>
- <div>
- <a target='_blank' href={`${this.state.traceUrl}/#/latency/index?traceId=${record.trace_id}&app_alias=${this.state.queryParams.app_alias}&span_id=${record.span_id}`}>{record.trace_id}</a>
- </div>
- </template>
- </span> */}
- </Table>
- </div>
- </div>
- </div>)
- }
- {
- this.props.shape == 'dottedcylinder' && (
- <div className='ant-descriptions-header'>
- <Descriptions title="" >
- {/* <Descriptions.Item label="系统名称">{this.state.messaging_stats.name}</Descriptions.Item> */}
- <Descriptions.Item label="生产消息数量">{this.state.messaging_stats.produce_num || 0}</Descriptions.Item>
- <Descriptions.Item label="消费消息数量">{this.state.messaging_stats.consume_num || 0}</Descriptions.Item>
- <Descriptions.Item label="生产消息错误率">{this.state.messaging_stats.produce_error_rate?(this.state.messaging_stats.produce_error_rate*100).toFixed(2):0}</Descriptions.Item>
- <Descriptions.Item label="消费消息错误率">{this.state.messaging_stats.consume_error_rate?(this.state.messaging_stats.consume_error_rate*100).toFixed(2):0}</Descriptions.Item>
- <Descriptions.Item label="生产消息平均耗时">{this.state.messaging_stats.produce_duration_average?this.state.messaging_stats.produce_duration_average.toFixed(2):0}</Descriptions.Item>
- <Descriptions.Item label="消费消息耗时">{this.state.messaging_stats.consume_duration_average?this.state.messaging_stats.consume_duration_average.toFixed(2):0}</Descriptions.Item>
- <Descriptions.Item label="平均消息大小">{this.state.messaging_stats.message_size_average?this.state.messaging_stats.message_size_average.toFixed(2):0}</Descriptions.Item>
- <Descriptions.Item label="主题数量">{this.state.messaging_stats.topic_num || 0}</Descriptions.Item>
- </Descriptions>
- <div className="bisic-title">主题统计信息</div>
- <div>
- {this.state.messaging_stats && this.state.messaging_stats.topic_stats && this.state.messaging_stats.topic_stats.length > 0 && this.state.messaging_stats.topic_stats.map((item, index)=>{
- return <Descriptions key={index+item.name} >
- <Descriptions.Item label="主题名称" >{item.name || '--'}</Descriptions.Item>
- <Descriptions.Item label="生产消息数量">{item.produce_num || 0}</Descriptions.Item>
- <Descriptions.Item label="消费消息数量">{item.consume_num || 0}</Descriptions.Item>
- <Descriptions.Item label="生产消息错误率">{item.produce_error_rate ? (item.produce_error_rate*100).toFixed(2)+'%' :0}</Descriptions.Item>
- <Descriptions.Item label="消费消息错误率">{item.consume_error_rate?(item.consume_error_rate*!100).toFixed(2)+ '%' :0}</Descriptions.Item>
- <Descriptions.Item label="生产消息平均耗时">{item.produce_duration_average?item.produce_duration_average.toFixed(2):0}</Descriptions.Item>
- <Descriptions.Item label="消费消息耗时">{item.consume_duration_average?item.consume_duration_average.toFixed(2):0}</Descriptions.Item>
- <Descriptions.Item label="平均消息大小">{item.message_size_average?item.message_size_average.toFixed(2):0}</Descriptions.Item>
- </Descriptions>
- })}
- </div>
- </div>
- )
- }
- {
- this.props.shape == 'cloud' && (
- <div className="node-details-content" >
- <div style={{marginTop:'30px'}}>
- <div style={{width:'100%'}}>
- <h4>已知应用</h4>
- <Table dataSource={this.state.cloudTable}
- columns={cloudColums}
- rowKey={'app_alias'}
- expandedRowRender={(record) => expandedRowRender(record)}
- size='small' bordered pagination={false}>
- </Table>
- </div>
- <div style={{marginTop:'40px'}}>
- <h4>未知应用</h4>
- <div style={{paddingLeft: '80px'}}>
- <Table dataSource={this.state.cloudTable2}
- columns={cloudColums2}
- rowKey={`name`} size='small' bordered pagination={false}>
- </Table>
- </div>
- </div>
- </div>
- </div>)
- }
- </div>
- </Drawer>
- );
- }
- //获取基础信息
- getNodeBasic(){
- axios({
- url: `${this.state.baseUrl}/api/v1/apps_score/${this.state.queryParams.app_alias}/svr`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- source_service:this.props.id,
- start_time:this.state.queryParams.start_time,
- end_time:this.state.queryParams.end_time
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const newObj= ((res ||{}).data || {}).data || {}
- this.setState({
- nodeData:{...newObj}
- },()=>{
- if(JSON.stringify(this.state.nodeData)!="{}"){
- this.state.nodeData.apdex>=0.94?this.setState({bgColor:setNodeColor('G')})
- :(this.state.nodeData.apdex>=0.85&&this.state.nodeData.apdex<0.94)?this.setState({bgColor:setNodeColor('B')})
- :(this.state.nodeData.apdex>=0.7&&this.state.nodeData.apdex<0.85)?this.setState({bgColor:setNodeColor('DI')})
- :(this.state.nodeData.apdex>=0.5&&this.state.nodeData.apdex<0.7)?this.setState({bgColor:setNodeColor('Y')})
- :this.setState({bgColor:setNodeColor('R')})
- }else{
- this.setState({bgColor:setNodeColor('R')})
- }
- })
- }
- });
- }
- //获取散点图--延迟比例
- getNodeAnalyst(){
- axios({
- url: `${this.state.baseUrl}/api/v1/app/analyst/${this.state.queryParams.app_alias}/svr`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- source_service:this.props.id,
- start_time:this.state.queryParams.start_time,
- end_time:this.state.queryParams.end_time,
- percentile:this.state.queryParams.percentile
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const obj = ((res || {}).data ||{}).data || {}
- this.setState({
- AnalystData:{...obj}
- },()=>{
- if(JSON.stringify(this.state.AnalystData)!="{}"){
- if (this.state.AnalystData?.failed || this.state.AnalystData?.success) {
- this.initChart(this.state.AnalystData)
- }
- }
- })
- }
- });
- }
- // 散点图渲染
- initChart(tmpData) {
- let chart = echarts.getInstanceByDom(document.getElementById("main"));
- if (chart == null) {
- chart = echarts.init(document.getElementById("main"));
- }else {
- chart.dispose();
- chart = echarts.init(document.getElementById("main"));
- }
- let successData = tmpData.success && tmpData.success.map(item => new Date(item[0]).toLocaleString()) || []
- let failedData = tmpData.failed && tmpData.failed.map(item => new Date(item[0]).toLocaleString()) || []
- let option = {
- title: {
- text: '',
- subtext: '',
- textStyle:{
- fontSize:14
- },
- },
- grid: {
- top:'8%',
- left: '3%',
- right: '7%',
- bottom: '14%',
- containLabel: true
- },
- tooltip: {
- showDelay: 0,
- formatter: function (params) {
- let newParams = moment(params.data[0]).format('YYYY-MM-DD HH:mm:ss');
- let time = newParams+"<br/>"+ params.data[1]+"ms"
- return time;
- },
- axisPointer: {
- show: true,
- type: 'cross',
- lineStyle: {
- type: 'dashed',
- width: 1
- }
- }
- },
- toolbox: {
- show:true,
- showTitle: true,
- feature: {
- rect: {
- show: true,
- title: 'Trace选择'
- },
- brush: {
- type: ["rect"], // 开启矩形选择
- show: true,//是否显示 这里我们直接true
- iconStyle: {
- opacity: 0,//通过opacity设置为0隐藏图标
- },
- }
- },
- left:"40%", //组件离容器左侧的距离,'left', 'center', 'right','20%'
- top:"-3%", //组件离容器上侧的距离,'top', 'middle', 'bottom','20%'
- right:"auto", //组件离容器右侧的距离,'20%'
- bottom:"auto",
- },
- brush: {
- toolbox: ['rect'],
- xAxisIndex: 0,
- throttleType:'debounce',
- throttleDelay:600
- },
- legend: {
- data: ['成功', '失败'],
- left: 'center',
- bottom: 0,
- itemGap: 100,
- textStyle: {//文字颜色
- fontSize: 12,
- padding:[0,3],//文字与图形之间的左右间距
- rich:{
- labelName:{
- fontSize:14,
- color:'#333',
- fontWeight:500
- }
- }
- },
- formatter: function (params) {
- // 获取legend显示内容
- let data = tmpData;
- let sl,fl;
- if(data.success!=null){
- sl = tmpData.success.length;
- }else{
- sl = 0
- }
- if( data.failed!=null){
- fl = tmpData.failed.length;
- }else{
- fl = 0
- }
- var target;
- if(params == '成功'){
- target = sl;
- }else if(params == '失败'){
- target = fl;
- }
- return target != undefined?params +' '+`{labelName|${target}}`:params
- },
- },
- xAxis: [
- {
- type: 'time',
- data: [
- ...successData,
- ...failedData
- ],
- gridIndex:0,
- axisLabel: {
- show:true,
- rotate: 45, // 旋转标签,适用于标签较长的情况
- interval: 'auto',
- margin: 10, // 增加刻度标签间隔
- textStyle: {
- fontSize: 10,
- textAlign:'center'
- },
- formatter: function(params) {
- let newParams = moment(params).format('HH:mm:ss');
- let time = newParams
- return time;
- }
- },
- splitLine: {
- show: true
- },
- }
- ],
- yAxis: [
- {
- type: 'value',
- // scale: true,
- gridIndex:0,
- axisLabel: {
- formatter: '{value}'
- },
- axisLine:{
- show:true
- },
- axisTick:{
- show:true
- },
- splitLine: {
- show: true
- },
- data:[0,2500,5000,7500,10000],
- }
- ],
- series: [
- {
- name: '成功',
- type: 'scatter',
- emphasis: {
- focus: 'series'
- },
- //设置散点图样式
- itemStyle:{
- color:'#13ce66'
- },
- symbolSize:10,//设置散点的大小
- data:tmpData.success,
- markArea: {
- silent: true,
- itemStyle: {
- color: 'transparent',
- borderWidth: 0,
- borderType: 'dashed'
- },
- },
- },
- {
- name: '失败',
- type: 'scatter',
- emphasis: {
- focus: 'series'
- },
- itemStyle:{
- color:'#ff4949'
- },
- // prettier-ignore
- data:tmpData.failed,
- // data:[],
- markArea: {
- silent: true,
- itemStyle: {
- color: 'transparent',
- borderWidth: 0,
- borderType: 'dashed'
- },
- },
- }
- ]
- }
- chart.setOption(option,true)
- // 默认开启框选
- chart.dispatchAction({
- type: 'takeGlobalCursor',
- key: 'brush',
- brushOption: {
- brushType: 'rect' // 指定选框类型
- }
- })
- chart.off("brushSelected");
- //框选选择数据
- chart.on('brushSelected', (params) => {
- var brushComponent = params.batch[0];
- let successIndexList=[];
- let failIndexList =[];
- let successList=[];
- let failList=[];
- if(brushComponent.selected.length>1){
- successIndexList = brushComponent.selected[0].dataIndex
- failIndexList = brushComponent.selected[1].dataIndex
- }else{
- if(brushComponent.selected[0].seriesName !=undefined){
- if(brushComponent.selected[0].seriesName =="失败"){
- failIndexList = brushComponent.selected[0].dataIndex
- }else{
- successIndexList = brushComponent.selected[0].dataIndex
- }
- }
- }
- if(successIndexList.length>0){
- for(let i = 0;i<tmpData.success.length;i++){
- for(let j=0;j<successIndexList.length;j++){
- if(successIndexList[j] == i){
- successList.push(tmpData.success[i])
- }
- }
- }
- }
- if(failIndexList.length>0){
- for(let k=0;k<tmpData.failed.length;k++){
- for(let l=0;l<failIndexList.length;l++){
- if(failIndexList[l] == k){
- failList.push(tmpData.failed[k])
- }
- }
- }
- }
- let arr =successList.concat(failList);
- let dataRange={};
- if(arr.length>0){
- let timeArr =[];
- let valueArr=[];
- for(let m=0;m<arr.length;m++){
- timeArr.push(Math.round(Date.parse(arr[m][0])/1000));
- valueArr.push(arr[m][1]);
- }
- let minTime = Math.min(...timeArr);
- let maxTime = Math.max(...timeArr);
- let minValue = Math.min(...valueArr);
- let maxValue = Math.max(...valueArr)
- if(minTime == maxTime){
- minTime = minTime-1;
- maxTime = maxTime+1;
- }
- if(minValue == maxValue){
- minValue = minValue-1;
- maxValue = maxValue+1;
- }
- //看是否有成功节点
- if(successIndexList.length>0){
- dataRange = {
- start_time:minTime,
- end_time:maxTime,
- min_duration:minValue,
- max_duration:maxValue,
- failed:false,
- app_alias:this.state.queryParams.app_alias,
- service_name:this.props.id,
- }
- }else{
- dataRange = {
- start_time:minTime,
- end_time:maxTime,
- min_duration:minValue,
- max_duration:maxValue,
- failed:true,
- app_alias:this.state.queryParams.app_alias,
- service_name:this.props.id,
- }
- }
- let timeAndDuration = JSON.stringify(dataRange);
- // let href = this.$router.resolve({
- // path:'/latency/index',
- // query:{
- // data:timeAndDuration
- // }
- // })
- // window.open(window.location.origin+"/"+href.href,"_blank")
- let href = `${this.state.traceUrl}/#/latency/index?start_time=${dataRange.start_time}&end_time=${dataRange.end_time}&min_duration=${dataRange.min_duration}&max_duration=${dataRange.max_duration}&failed=${dataRange.failed}&app_alias=${this.state.queryParams.app_alias}&service_name=${this.props.id}`
- window.open(href,"_blank")
- this.timeoutId = setTimeout(()=>{
- chart.dispatchAction({
- type: 'brush',//选择action行为
- areas:[]//areas表示选框的集合,此时为空即可。
- });
- },500)
- }
- });
- window.addEventListener("resize",function (){
- chart.resize();
- });
- }
- //获取折线图
- // http://127.0.0.1:8000/api/v1/service/liveness?service_name={service_name}
- getNodeLiveness(){
- axios({
- url: `${this.state.baseUrl}/api/v1/service/liveness`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- service_name:this.props.id,
- start_time:this.state.queryParams.start_time,
- end_time:this.state.queryParams.end_time,
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const list = ((res || {}).data || {}).data || []
- this.setState({
- livenessData:[...list]
- },()=>{
- if(this.state.livenessData.length>0){
- this.initLiveness(this.state.livenessData);
- }
- })
- }
- });
- }
- //渲染折线图
- initLiveness(data){
- let liveChart = echarts.getInstanceByDom(document.getElementById("box"));
- if (liveChart == null) {
- liveChart = echarts.init(document.getElementById("box"));
- }else {
- liveChart.dispose();
- liveChart = echarts.init(document.getElementById("box"));
- }
- let option = {
- grid: {
- top:'5%',
- left: '1%',
- right: '1%',
- bottom: '5%',
- containLabel: true
- },
- tooltip: {
- showDelay: 0,
- formatter: function (params) {
- let newParams = moment(params.data[0]).format('YYYY-MM-DD HH:mm:ss');
- let time = newParams+"<br/>"+ params.data[1]+"ms"
- return time;
- },
- axisPointer: {
- show: true,
- type: 'cross',
- lineStyle: {
- type: 'dashed',
- width: 1
- }
- }
- },
- xAxis: {
- type: 'time',
- boundaryGap: false,
- // splitNumber: 3,
- axisLabel: {
- show:true,
- rotate: 45, // 旋转标签,适用于标签较长的情况
- interval: 'auto',
- margin: 10, // 增加刻度标签间隔
- textStyle: {
- fontSize: 10,
- textAlign:'center'
- },
- formatter: function(params) {
- let newParams = moment(params).format('HH:mm:ss');
- let time = newParams
- return time;
- }
- },
- splitLine: {
- show: true
- },
- },
- yAxis: {
- type: 'value',
- boundaryGap: [0, '30%']
- },
- visualMap: {
- type: 'piecewise',
- show: false,
- dimension: 0,
- seriesIndex: 0,
- pieces: [
- {
- gt: 1,
- lt: 3,
- color: 'rgba(0, 0, 180, 0.4)'
- },
- {
- gt: 5,
- lt: 7,
- color: 'rgba(0, 0, 180, 0.4)'
- }
- ]
- },
- series: [
- {
- type: 'line',
- smooth: 0.6,
- symbol: 'none',
- lineStyle: {
- color: '#5470C6',
- width: 1
- },
- markLine: {
- symbol: ['none', 'none'],
- label: { show: false },
- data: [{ xAxis: 1 }, { xAxis: 3 }, { xAxis: 5 }, { xAxis: 7 }]
- },
- areaStyle: {},
- data: data
- }
- ]
- };
- liveChart.setOption(option,true)
- }
- //获取异常trace列表 /api/v1/service/spans
- getServiceSpans(){
- this.setState({ loading: true });
- this.setState({
- traceData:[],
- pagination:{total:0}
- },()=>{
- })
- axios({
- url: `${this.state.baseUrl}/api/v1/service/spans`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- service_name:this.props.id,
- only_exception:this.state.traceQuery.only_exception, // 仅显示异常trace相关
- only_database:this.state.traceQuery.only_database,
- pageIndex:this.state.pagination.pageIndex,
- pageSize:this.state.pagination.pageSize,
- start_time:this.state.queryParams.start_time,
- end_time:this.state.queryParams.end_time,
- app_alias:this.state.queryParams.app_alias,
- sort_field:'Timestamp',
- sort_type: this.state.queryParams.sort_type
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const list = (((res || {}).data || {}).data || {}).list || []
- const total = (((res || {}).data || {}).data || {}).count || 0
- this.setState({
- traceData:[...list],
- pagination:{...this.state.pagination,total:total}
- },()=>{
- })
- }
- });
- }
- //获取table 数据
- getTableData(){
- this.setState({ loading: true });
- this.setState({
- tableData:[],
- pagination2:{total:0}
- },()=>{
- })
- axios({
- url: `${this.state.coreBaseUrl}/v1/system-component/reqlist`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- page_num:this.state.pagination2.page_num,
- page_size:this.state.pagination2.page_size,
- start_time:this.state.queryParams.start_time,
- end_time:this.state.queryParams.end_time,
- app_alias:this.state.queryParams.app_alias,
- component: this.props.id//
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const list = (((res || {}).data || {}).data || {}).list || []
- const total = (((res || {}).data || {}).data || {}).total || 0
- const page_num = (((res || {}).data || {}).data || {}).page_num || 1
- const page_size = (((res || {}).data || {}).data || {}).page_size || 10
- this.setState({
- tableData:[...list],
- pagination2:{page_num:page_num,page_size:page_size,total:total}
- },()=>{
- })
- }
- });
- }
- getBarData(){// 获取柱状图数据
- this.setState({ loading: true });
- this.setState({
- tableData:[],
- pagination2:{total:0}
- },()=>{
- })
- axios({
- url: `${this.state.coreBaseUrl}/v1/system-component/stats`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- start_time:this.state.queryParams.start_time,
- end_time:this.state.queryParams.end_time,
- app_alias:this.state.queryParams.app_alias,
- component: this.props.id //
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const list = res?.data?.data?.database_stats?.request_bar || []
- this.setState({
- barData:list
- },()=>{
- if(this.state.barData.length>0){
- setTimeout(()=>{
- this.initLineBar(this.state.barData);
- },0)
- }
- })
- }
- });
- }
- // 渲染调用统计 折线/柱形图
- initLineBar(data){
- let liveChart = echarts.getInstanceByDom(document.getElementById("chartContent"));
- let xAxisArr = data.map(item => item.start_time) || []
- let dataArr = data.map(item => item.total) || []
- if (liveChart == null) {
- liveChart = echarts.init(document.getElementById("chartContent"));
- } else {
- liveChart.dispose();
- liveChart = echarts.init(document.getElementById("chartContent"));
- }
- let option = {
- xAxis: {
- type: 'category',
- data: xAxisArr,
- axisLabel: {
- show:true,
- rotate: 45, // 旋转标签,适用于标签较长的情况
- interval: 'auto',
- margin: 10, // 增加刻度标签间隔
- textStyle: {
- fontSize: 10,
- textAlign:'center'
- },
- formatter: function(params) {
- let newParams = moment(params).format('HH:mm:ss');
- let time = newParams
- return time;
- }
- },
- },
- tooltip: {
- showDelay: 0,
- axisPointer: {
- show: true,
- type: 'cross',
- lineStyle: {
- type: 'dashed',
- width: 1
- }
- }
- },
- yAxis: {
- type: 'value'
- },
- series: [
- {
- data: dataArr,
- type: 'bar'
- }
- ]
- };
- liveChart.setOption(option,true)
- }
- handleTableChange=(pagination,filters, sorter, extra)=>{
- const {current} = pagination
- let sort = ''
- if(sorter && sorter.order == 'ascend'){
- sort = 'ASC'
- } else if(sorter && sorter.order == 'descend'){
- sort = 'DESC'
- }
- this.setState({
- pagination: {...this.state.pagination,pageIndex:current,current:current},
- queryParams:{...this.state.queryParams,sort_type:sort}
- },()=>{
- this.getServiceSpans();
- });
- }
- handleTableChange2=(pagination,filters, sorter, extra)=>{
- const {current} = pagination
- this.setState({
- pagination2: {...this.state.pagination2,page_num:current}
- },()=>{
- this.getTableData();
- });
- }
- //仅异常
- onChangeError = e =>{
- const only_exception = e.target.checked ? 1:0;
- const pageIndex = 1
- const current = 1
- this.setState({
- traceQuery:{...this.state.traceQuery,only_exception:only_exception},
- pagination: {...this.state.pagination,pageIndex:pageIndex,current:current},
- },()=>{
- this.getServiceSpans();
- });
- }
- //仅sql
- onChangeSql = e =>{
- const only_database = e.target.checked ? 1:0;
- const pageIndex = 1
- const current = 1
- this.setState({
- traceQuery:{...this.state.traceQuery,only_database:only_database},
- pagination: {...this.state.pagination,pageIndex:pageIndex,current:current},
- },()=>{
- this.getServiceSpans(this.props.source,this.props.target);
- });
- }
- //单选按钮
- onChange = e => {
- const percentile = e.target.value
- this.setState({
- queryParams:{...this.state.queryParams,percentile:percentile},
- AnalystData:[]
- },()=>{
- this.getNodeAnalyst();
- });
- };
- renderTable(table) {
- const { nodeMatches = makeMap() } = this.props;
- if (isGenericTable(table)) {
- return (
- <NodeDetailsGenericTable
- rows={table.rows}
- columns={table.columns}
- matches={nodeMatches.get('tables')}
- />
- );
- } if (isPropertyList(table)) {
- return (
- <NodeDetailsPropertyList
- rows={table.rows}
- controls={table.controls}
- matches={nodeMatches.get('property-lists')}
- />
- );
- }
- log(`Undefined type '${table.type}' for table ${table.id}`);
- return null;
- }
- componentDidUpdate() {
- this.updateTitle();
- }
- updateTitle() {
- setDocumentTitle(this.props.details && this.props.details.label);
- }
- //dottedcylinder 类型 -获取基础信息
- getDottBasicsData(){
- this.setState({ loading: true });
- this.setState({
- messaging_stats:{
- topic_stats:[]
- }
- },()=>{
- })
- axios({
- url: `${this.state.coreBaseUrl}/v1/system-component/stats`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- start_time:this.state.queryParams.start_time,
- end_time:this.state.queryParams.end_time,
- app_alias:this.state.queryParams.app_alias,
- component: this.props.id//
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const messaging_stats = (((res || {}).data || {}).data || {}).messaging_stats || {}
- this.setState({
- messaging_stats:messaging_stats
- },()=>{
- })
- }
- });
- }
- // cloud 类型-获取嵌套table
- getCloudTableData(){// 获取柱状图数据
- this.setState({ loading: true });
- this.setState({
- cloudTable:[],
- cloudTable2:[],
- },()=>{
- })
- axios({
- url: `${this.state.coreBaseUrl}/v1/service/related-apps`,
- method: "get",
- headers: { 'Authorization': getToken },
- params: {
- start_time: this.state.queryParams.start_time, //1727366400
- end_time:this.state.queryParams.end_time, // 1727415703
- app_alias:this.state.queryParams.app_alias,
- type: this.props.id //
- }
- }).then(res => {
- if(res && res.data.code == 200){
- const list = (((res || {}).data ||{}).data || {}).app_list || []
- const list2 = (((res ||{}).data ||{}).data ||{}).client_list || []
- this.setState({
- cloudTable:[...list],
- cloudTable2: [...list2]
- },()=>{
- })
- }
- });
- }
- }
- NodeDetails.propTypes = {
- renderNodeDetailsExtras: PropTypes.func,
- };
- NodeDetails.defaultProps = {
- renderNodeDetailsExtras: noop,
- };
- function mapStateToProps(state, ownProps) {
- const currentTopologyId = state.get('currentTopologyId');
- return {
- nodeMatches: state.getIn(['searchNodeMatches', currentTopologyId, ownProps.id]),
- nodes: state.get('nodes'),
- selectedNodeId: state.get('selectedNodeId'),
- transitioning: state.get('pausedAt') !== ownProps.timestamp,
- };
- }
- export default connect(
- mapStateToProps,
- { clickCloseDetails, clickShowTopologyForNode }
- )(NodeDetails);
|