mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-10 04:49:02 +08:00
code cleanup, updated in global date time component
This commit is contained in:
parent
72f2ac0fea
commit
e1fd9cec65
@ -19,7 +19,6 @@ export const updateTimeInterval = (interval:string, datetimeRange?:[number,numbe
|
||||
|
||||
let maxTime: number = 0;
|
||||
let minTime: number = 0;
|
||||
console.log('interval', interval, typeof(interval))
|
||||
// if interval string is custom, then datetimRange should be present and max & min time should be
|
||||
// set directly based on that. Assuming datetimeRange values are in ms, and minTime is 0th element
|
||||
|
||||
@ -28,13 +27,11 @@ export const updateTimeInterval = (interval:string, datetimeRange?:[number,numbe
|
||||
|
||||
maxTime=Date.now()*1000000; // in nano sec
|
||||
minTime=(Date.now()-15*60*1000)*1000000;
|
||||
console.log('max time 15 in case',maxTime)
|
||||
break;
|
||||
|
||||
case '30min':
|
||||
maxTime=Date.now()*1000000; // in nano sec
|
||||
minTime=(Date.now()-30*60*1000)*1000000;
|
||||
console.log('max time in 30 min case',maxTime)
|
||||
break;
|
||||
|
||||
case '1hr':
|
||||
|
@ -62,7 +62,6 @@ export interface getFilteredTraceMetricsAction{
|
||||
export const getServicesList = (globalTime: GlobalTime) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string = 'services?start='+globalTime.minTime+'&end='+globalTime.maxTime;
|
||||
console.log(request_string);
|
||||
const response = await metricsAPI.get<servicesListItem[]>(request_string);
|
||||
|
||||
dispatch<getServicesListAction>({
|
||||
|
@ -26,7 +26,6 @@ export interface updateTraceFiltersAction {
|
||||
}
|
||||
|
||||
export const updateTraceFilters = (traceFilters: TraceFilters) => {
|
||||
console.log('in update trace filters',traceFilters)
|
||||
return {
|
||||
type: ActionTypes.updateTraceFilters,
|
||||
payload: traceFilters,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export default axios.create({
|
||||
// baseURL: 'http://104.211.113.204:8080/api/v1/',
|
||||
// baseURL: process.env.REACT_APP_QUERY_SERVICE_URL,
|
||||
baseURL: 'http://localhost:3000/api/v1/',
|
||||
// console.log('in metrics API', process.env.QUERY_SERVICE_URL)
|
||||
baseURL: 'http://104.211.113.204:8080/api/v1/',
|
||||
|
||||
// baseURL: 'http://localhost:3000/api/v1/',
|
||||
|
||||
}
|
||||
);
|
@ -3,14 +3,9 @@ import axios from 'axios';
|
||||
|
||||
export default axios.create({
|
||||
// baseURL: 'http://104.211.113.204:8080/api/v1/'
|
||||
// baseURL: process.env.QUERY_SERVICE_URL,
|
||||
// console.log('in traces API', process.env.QUERY_SERVICE_URL)
|
||||
baseURL: 'http://localhost:3000/api/v1/',
|
||||
|
||||
baseURL: 'http://localhost:3000/api/v1/', // toggle to this before pushing
|
||||
|
||||
|
||||
});
|
||||
|
||||
//individual trace format
|
||||
//https://api.signoz.io/api/traces/146754946da0552e
|
||||
|
||||
//http://104.211.113.204:8080/api/v1/traces/000000000000000053a5b7a93bc5e08a
|
@ -45,7 +45,6 @@ const App = () => {
|
||||
|
||||
|
||||
const onCollapse = (): void => {
|
||||
// console.log(collapsed);
|
||||
setCollapsed(!collapsed);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Modal, Col, Row, DatePicker, TimePicker} from 'antd';
|
||||
import { Store } from 'antd/lib/form/interface';
|
||||
import { Modal, DatePicker} from 'antd';
|
||||
import {DateTimeRangeType} from '../actions'
|
||||
import { Moment } from 'moment'
|
||||
import moment from 'moment';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
@ -23,14 +24,17 @@ const CustomDateTimeModal: React.FC<CustomDateTimeModalProps> = ({ //destructuri
|
||||
const [customDateTimeRange, setCustomDateTimeRange]=useState<DateTimeRangeType>();
|
||||
|
||||
function handleRangePickerOk(date_time: DateTimeRangeType) {
|
||||
console.log('onhandleRangePickerOk: ', date_time?date_time[0]?.toDate():null,date_time?date_time[1]?.toDate():null );
|
||||
setCustomDateTimeRange(date_time);
|
||||
}
|
||||
function disabledDate(current:Moment){
|
||||
|
||||
// function handleApplyDateTimeModal (){
|
||||
// if (customDateTimeRange !== null && customDateTimeRange !== undefined && customDateTimeRange[0] !== null && customDateTimeRange[1] !== null )
|
||||
// console.log('in handleApplyDateTimeModal', customDateTimeRange[0].toDate(),customDateTimeRange[1].toDate())
|
||||
// }
|
||||
if (current > moment()){
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@ -39,27 +43,11 @@ const CustomDateTimeModal: React.FC<CustomDateTimeModalProps> = ({ //destructuri
|
||||
okText="Apply"
|
||||
cancelText="Cancel"
|
||||
onCancel={onCancel}
|
||||
// style={{ position: "absolute", top: 60, left: parseInt(`${positionleft}`) }} //get position as a prop from parent component, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
|
||||
style={{ position: "absolute", top: 60, right: 40 }}
|
||||
onOk={() => onCreate(customDateTimeRange?customDateTimeRange:null)}
|
||||
>
|
||||
|
||||
<RangePicker onOk={handleRangePickerOk} showTime />
|
||||
{/* <RangePicker renderExtraFooter={() => 'extra footer'} showTime /> */}
|
||||
{/* <Row>
|
||||
<Col span={6}> <DatePicker />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<TimePicker />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
|
||||
<DatePicker />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<TimePicker />
|
||||
</Col>
|
||||
</Row> */}
|
||||
<RangePicker disabledDate={disabledDate} onOk={handleRangePickerOk} showTime />
|
||||
|
||||
</Modal>
|
||||
);
|
||||
|
@ -13,12 +13,6 @@ import FormItem from 'antd/lib/form/FormItem';
|
||||
import {DateTimeRangeType} from '../actions'
|
||||
|
||||
|
||||
import {
|
||||
|
||||
RedoOutlined,
|
||||
|
||||
} from '@ant-design/icons';
|
||||
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -30,8 +24,6 @@ interface DateTimeSelectorProps extends RouteComponentProps<any> {
|
||||
currentpath?:string;
|
||||
updateTimeInterval: Function;
|
||||
globalTime: GlobalTime;
|
||||
// urlTime:string;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -43,11 +35,9 @@ const _DateTimeSelector = (props:DateTimeSelectorProps) => {
|
||||
|
||||
const [form_dtselector] = Form.useForm();
|
||||
|
||||
console.log('props in DateTimeSelector',props)
|
||||
|
||||
const handleOnSelect = (value:string) =>
|
||||
{
|
||||
console.log(value);
|
||||
if (value === 'custom')
|
||||
{
|
||||
setCustomDTPickerVisible(true);
|
||||
@ -58,8 +48,6 @@ const _DateTimeSelector = (props:DateTimeSelectorProps) => {
|
||||
search: '?time='+value,
|
||||
}) //pass time in URL query param for all choices except custom in datetime picker
|
||||
props.updateTimeInterval(value);
|
||||
// console.log('in handle on select urlTime',props.urlTime)
|
||||
// console.log('global time', props.globalTime.maxTime,props.globalTime.minTime)
|
||||
setTimeInterval(value);
|
||||
setRefreshButtonHidden(false); // for normal intervals, show refresh button
|
||||
}
|
||||
@ -68,14 +56,13 @@ const _DateTimeSelector = (props:DateTimeSelectorProps) => {
|
||||
//function called on clicking apply in customDateTimeModal
|
||||
const handleOk = (dateTimeRange:DateTimeRangeType) =>
|
||||
{
|
||||
console.log('in handleOk of DateTimeSelector',dateTimeRange);
|
||||
// pass values in ms [minTime, maxTime]
|
||||
if (dateTimeRange!== null && dateTimeRange!== undefined && dateTimeRange[0]!== null && dateTimeRange[1]!== null )
|
||||
{
|
||||
props.updateTimeInterval('custom',[dateTimeRange[0].valueOf(),dateTimeRange[1].valueOf()])
|
||||
//setting globaltime
|
||||
setRefreshButtonHidden(true);
|
||||
form_dtselector.setFieldsValue({interval:(dateTimeRange[0].valueOf().toString()+'-'+dateTimeRange[1].valueOf().toString()) ,})
|
||||
form_dtselector.setFieldsValue({interval:(dateTimeRange[0].format("YYYY/MM/DD HH:mm")+'-'+dateTimeRange[1].format("YYYY/MM/DD HH:mm")) ,})
|
||||
}
|
||||
setCustomDTPickerVisible(false);
|
||||
}
|
||||
@ -97,7 +84,6 @@ const _DateTimeSelector = (props:DateTimeSelectorProps) => {
|
||||
|
||||
const handleRefresh = () =>
|
||||
{
|
||||
console.log('refreshing time interval', timeInterval)
|
||||
props.updateTimeInterval(timeInterval);
|
||||
}
|
||||
if (props.location.pathname.startsWith('/usage-explorer')) {
|
||||
@ -110,14 +96,14 @@ const _DateTimeSelector = (props:DateTimeSelectorProps) => {
|
||||
<Space>
|
||||
<Form form={form_dtselector} layout='inline' initialValues={{ interval:'15min', }} style={{marginTop: 10, marginBottom:10}}>
|
||||
<FormItem name='interval'>
|
||||
<Select style={{ width: 300 }} onSelect={handleOnSelect} >
|
||||
<Select onSelect={handleOnSelect} >
|
||||
<Option value="custom">Custom</Option>
|
||||
<Option value="15min">15 min</Option>
|
||||
<Option value="30min">30 min</Option>
|
||||
<Option value="1hr">1 hour</Option>
|
||||
<Option value="6hr">6 hour</Option>
|
||||
<Option value="1day">1 day</Option>
|
||||
<Option value="1week">1 week</Option>
|
||||
<Option value="15min">Last 15 min</Option>
|
||||
<Option value="30min">Last 30 min</Option>
|
||||
<Option value="1hr">Last 1 hour</Option>
|
||||
<Option value="6hr">Last 6 hour</Option>
|
||||
<Option value="1day">Last 1 day</Option>
|
||||
<Option value="1week">Last 1 week</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
@ -140,14 +126,11 @@ const _DateTimeSelector = (props:DateTimeSelectorProps) => {
|
||||
}
|
||||
|
||||
}
|
||||
//const mapStateToProps = (state: StoreState, ownProps: RouteComponentProps<any> -- ownProps is of type RouteComponentProps<any>
|
||||
const mapStateToProps = (state: StoreState ): { globalTime: GlobalTime} => {
|
||||
|
||||
return { globalTime : state.globalTime };
|
||||
// Check if we should pass as urltime or how do we handle this
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
|
||||
export const DateTimeSelector = connect(mapStateToProps, {
|
||||
updateTimeInterval: updateTimeInterval,
|
||||
|
@ -14,9 +14,6 @@ const breadcrumbNameMap :any = { // PNOTE - TO DO - Remove any and do typecheck
|
||||
'/traces': 'Traces',
|
||||
'/service-map': 'Service Map',
|
||||
'/usage-explorer': 'Usage Explorer',
|
||||
// only top level things should be mapped here, rest should be taken dynamically from url
|
||||
// Does this work if url has 2 levels of dynamic parameters? - Currently we have only 1 level
|
||||
// this structure ignores query params like time -- which is good
|
||||
};
|
||||
|
||||
|
||||
@ -57,21 +54,4 @@ const ShowBreadcrumbs = withRouter(props => {
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// const ShowBreadcrumbs = () => {
|
||||
|
||||
// return (
|
||||
// <Breadcrumb style={{ margin: '16px 0' , fontSize: 12 }}>
|
||||
// <Breadcrumb.Item>
|
||||
// <Link to="/">Home</Link></Breadcrumb.Item>
|
||||
// <Breadcrumb.Item><Link to="/application">Application</Link></Breadcrumb.Item>
|
||||
// </Breadcrumb>
|
||||
// //programmatically populate it with links
|
||||
// );
|
||||
|
||||
// }
|
||||
|
||||
export default ShowBreadcrumbs;
|
@ -14,7 +14,7 @@ zIndex:10;
|
||||
position:absolute;
|
||||
top:${props => props.ycoordinate}px;
|
||||
left:${props => props.xcoordinate}px;
|
||||
font-size:10px;
|
||||
font-size:12px;
|
||||
border-radius:2px;
|
||||
`;
|
||||
|
||||
@ -32,8 +32,6 @@ padding-right:4px;
|
||||
// PNOTE - Check if this should be the case
|
||||
const theme = 'dark';
|
||||
|
||||
|
||||
|
||||
interface ErrorRateChartProps extends RouteComponentProps<any> {
|
||||
data : metricItem[],
|
||||
}
|
||||
@ -47,7 +45,6 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps>{
|
||||
|
||||
constructor(props: ErrorRateChartProps) {
|
||||
super(props);
|
||||
console.log('React CreatRef', React.createRef());
|
||||
this.chartRef = React.createRef();
|
||||
}
|
||||
|
||||
@ -64,25 +61,11 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps>{
|
||||
|
||||
onClickhandler = async(e:any,event:any) => {
|
||||
|
||||
|
||||
//PNOTE - e has all key values from mouse event, event has only reference to handler functions
|
||||
// PNOTE - https://github.com/emn178/angular2-chartjs/issues/29 - for listening only to element points
|
||||
// var firstPoin = this.chart.current.getElementAtEvent(e)
|
||||
|
||||
console.log('chartref',this.chartRef.current.chartInstance);
|
||||
|
||||
var firstPoint;
|
||||
if(this.chartRef){
|
||||
firstPoint = this.chartRef.current.chartInstance.getElementAtEvent(e)[0];
|
||||
}
|
||||
|
||||
console.log('firstPoint', firstPoint);
|
||||
|
||||
|
||||
// if (firstPoint) {
|
||||
// var label = myChart.data.labels[firstPoint._index];
|
||||
// var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
|
||||
// }
|
||||
if (firstPoint)
|
||||
{// PNOTE - TODO - Is await needed in this expression?
|
||||
await this.setState({
|
||||
@ -92,19 +75,13 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps>{
|
||||
// graphInfo:{...event}
|
||||
})
|
||||
}
|
||||
// console.log(this.state.graphInfo.payload.timestamp)
|
||||
//this.props.applicationTimeStamp(e.payload.x)
|
||||
// this.props.history.push('/traces?timestamp=' + e.payload.timestamp + '&service=' + this.props.service.name)
|
||||
}
|
||||
|
||||
gotoTracesHandler=()=>{
|
||||
console.log('in gotoTraces handler')
|
||||
this.props.history.push('/traces')
|
||||
// this.props.history.push('/traces?timestamp=' + this.state.graphInfo.payload.timestamp + '&service=' + this.props.service.name)
|
||||
}
|
||||
|
||||
gotoAlertsHandler=()=>{
|
||||
console.log('in gotoAlerts handler')
|
||||
this.props.history.push('/service-map')
|
||||
// PNOTE - Keeping service map for now, will replace with alerts when alert page is made
|
||||
}
|
||||
@ -147,25 +124,20 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps>{
|
||||
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
bodyFontSize: 10,
|
||||
titleFontSize: 10,
|
||||
bodyFontSize: 12,
|
||||
titleFontSize: 12,
|
||||
|
||||
callbacks: {
|
||||
label: function(tooltipItem, data) {
|
||||
|
||||
if (typeof(tooltipItem.yLabel) === 'number')
|
||||
{
|
||||
return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel.toFixed(3);
|
||||
return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel.toFixed(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
// return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel!.Fixed(3);
|
||||
// not able to do toFixed(3) in typescript as string|number type is not working with toFixed(3) function for
|
||||
// as toFixed() function only works with numbers
|
||||
// using type of check gives issues in 'label' variable name
|
||||
//!That's the non-null assertion operator. It is a way to tell the compiler "this expression cannot be null or undefined here, so don't complain about the possibility of it being null or undefined." Sometimes the type checker is unable to make that determination itself.
|
||||
|
||||
},
|
||||
},
|
||||
@ -214,26 +186,15 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps>{
|
||||
}
|
||||
|
||||
GraphTracePopUp = () => {
|
||||
console.log('state in GraphTracePopPup',this.state);
|
||||
|
||||
if (this.state.showpopUp){
|
||||
return(
|
||||
|
||||
// <div className='applicationpopup' style={{top:`${this.state.ycoordinate}px`,zIndex:10,position:'absolute',left:`${this.state.xcoordinate}px`,backgroundColor:'white',border:'1px solid grey'}}>
|
||||
// <p style={{color:'black'}} onClick={this.gotoTracesHandler}>View Traces</p>
|
||||
// <p style={{color:'black'}}> Set Alerts</p>
|
||||
// </div>
|
||||
// <ChartPopUpUnique>
|
||||
// <p style={{color:'black'}} onClick={this.gotoTracesHandler}>View Traces</p>
|
||||
// <p style={{color:'black'}}> Set Alerts</p>
|
||||
// </ChartPopUpUnique>
|
||||
|
||||
<ChartPopUpUnique xcoordinate={this.state.xcoordinate} ycoordinate={this.state.ycoordinate}>
|
||||
<PopUpElements onClick={this.gotoTracesHandler}>View Traces</PopUpElements>
|
||||
<PopUpElements onClick={this.gotoAlertsHandler}>Set Alerts</PopUpElements>
|
||||
</ChartPopUpUnique>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
else
|
||||
@ -245,18 +206,6 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps>{
|
||||
render(){
|
||||
|
||||
const ndata = this.props.data;
|
||||
// console.log("in chartJS line render function")
|
||||
// console.log(ndata);
|
||||
|
||||
// const data_charts = data.map( s => ({label:s.ts, value:parseFloat(s.val)}) );
|
||||
// if(this.chartRef.ctx)
|
||||
// {
|
||||
// var gradient = this.chartRef.ctx.createLinearGradient(0, 0, 0, 400);
|
||||
// gradient.addColorStop(0, 'rgba(250,174,50,1)');
|
||||
// gradient.addColorStop(1, 'rgba(250,174,50,0)');
|
||||
// }
|
||||
|
||||
|
||||
|
||||
const data_chartJS = (canvas:any) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
@ -267,9 +216,6 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps>{
|
||||
datasets: [{
|
||||
label: 'Errors per sec',
|
||||
data: ndata.map(s => s.errorRate),
|
||||
// backgroundColor:'#000000',
|
||||
// fill: true,
|
||||
// backgroundColor: gradient,
|
||||
pointRadius: 0.5,
|
||||
borderColor: 'rgba(227, 74, 51,1)', // Can also add transparency in border color
|
||||
borderWidth: 2,
|
||||
|
@ -14,38 +14,14 @@ interface GenericVisualizationsProps {
|
||||
}
|
||||
|
||||
const GenericVisualizations = (props: GenericVisualizationsProps) => {
|
||||
// const [serviceName, setServiceName] = useState('Frontend'); //default value of service name
|
||||
|
||||
const data = {
|
||||
labels: props.data.map(s => new Date(s.timestamp/1000000)),
|
||||
datasets: [{
|
||||
data: props.data.map(s => s.value),
|
||||
// label: "Africa",
|
||||
borderColor: 'rgba(250,174,50,1)',// for line chart
|
||||
backgroundColor: props.chartType==='bar'?'rgba(250,174,50,1)':'', // for bar chart, don't assign backgroundcolor if its not a bar chart, may be relevant for area graph though
|
||||
},
|
||||
// {
|
||||
// data: [282,350,411,502,635,809,947,1402,3700,5267,282,350,411,502,635,809,947,1402,3700,5267],
|
||||
// label: "Asia",
|
||||
// borderColor: 'rgba(227, 74, 51, 1.0)',
|
||||
// backgroundColor: props.chartType==='bar'?'rgba(227, 74, 51, 1.0)':'',
|
||||
// },
|
||||
//{
|
||||
// data: [168,170,178,190,203,276,408,547,675,734],
|
||||
// label: "Europe",
|
||||
// borderColor: "#3cba9f",
|
||||
// fill: false
|
||||
// }, {
|
||||
// data: [40,20,10,16,24,38,74,167,508,784],
|
||||
// label: "Latin America",
|
||||
// borderColor: "#e8c3b9",
|
||||
// fill: false
|
||||
// }, {
|
||||
// data: [6,3,2,2,7,26,82,172,312,433],
|
||||
// label: "North America",
|
||||
// borderColor: "#c45850",
|
||||
// fill: false
|
||||
// }
|
||||
]
|
||||
};
|
||||
|
||||
@ -66,10 +42,6 @@ const GenericVisualizations = (props: GenericVisualizationsProps) => {
|
||||
}],
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
// time: {
|
||||
// unit: 'second'
|
||||
// },
|
||||
//PNOTE - How to enable distribution == linear?
|
||||
// distribution: 'linear',
|
||||
//'linear': data are spread according to their time (distances can vary)
|
||||
// From https://www.chartjs.org/docs/latest/axes/cartesian/time.html
|
||||
|
@ -14,7 +14,7 @@ zIndex:10;
|
||||
position:absolute;
|
||||
top:${props => props.ycoordinate}px;
|
||||
left:${props => props.xcoordinate}px;
|
||||
font-size:10px;
|
||||
font-size:12px;
|
||||
border-radius:2px;
|
||||
`;
|
||||
|
||||
@ -29,40 +29,12 @@ padding-right:4px;
|
||||
`;
|
||||
|
||||
|
||||
// const data_charts = {
|
||||
// labels: ['1', '2', '3', '4', '5', '6'],
|
||||
// datasets: [
|
||||
// {
|
||||
// // label: '# of Votes',
|
||||
// data: [12, 19, 3, 5, 2, 3],
|
||||
// fill: false,
|
||||
// backgroundColor: 'rgb(255, 99, 132)',
|
||||
// borderColor: 'rgba(255, 99, 132, 0.2)',
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
|
||||
// const onClickHandler = (e) => {
|
||||
// console.log("ChartJS chart clicked");
|
||||
// console.log(e);
|
||||
// };
|
||||
|
||||
// export interface ApiData {
|
||||
// 0: number, // has epoch timestamp
|
||||
// 1: string, // has value of the metric as a string
|
||||
// }
|
||||
|
||||
const theme = 'dark';
|
||||
|
||||
// PNOTE - accessing history object in typescript - https://stackoverflow.com/questions/49342390/typescript-how-to-add-type-check-for-history-object-in-react
|
||||
// withRouter is used to pass on history object as prop - https://stackoverflow.com/questions/43107912/how-to-access-history-object-in-new-react-router-v4
|
||||
|
||||
|
||||
interface LatencyLineChartProps extends RouteComponentProps<any> {
|
||||
data : metricItem[],
|
||||
// chartRef: any,
|
||||
// chartReference :ChartJSLineChart,
|
||||
// data passed to ChartJSLineChart component is an array if json objects
|
||||
popupClickHandler: Function,
|
||||
}
|
||||
|
||||
interface LatencyLineChart {
|
||||
@ -74,86 +46,60 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
|
||||
constructor(props: LatencyLineChartProps) {
|
||||
super(props);
|
||||
console.log('React CreatRef', React.createRef());
|
||||
this.chartRef = React.createRef();
|
||||
}
|
||||
|
||||
|
||||
|
||||
state = {
|
||||
// data: props.data,
|
||||
xcoordinate:0,
|
||||
ycoordinate:0,
|
||||
showpopUp:false,
|
||||
firstpoint_ts:0,
|
||||
// graphInfo:{}
|
||||
}
|
||||
|
||||
|
||||
onClickhandler = async(e:any,event:any) => {
|
||||
|
||||
console.log('e graph', e)
|
||||
// console.log('event graph',event)
|
||||
//PNOTE - e has all key values from mouse event, event has only reference to handler functions
|
||||
// PNOTE - https://github.com/emn178/angular2-chartjs/issues/29 - for listening only to element points
|
||||
// var firstPoin = this.chart.current.getElementAtEvent(e)
|
||||
|
||||
console.log('chartref',this.chartRef.current.chartInstance);
|
||||
|
||||
var firstPoint;
|
||||
if(this.chartRef){
|
||||
firstPoint = this.chartRef.current.chartInstance.getElementAtEvent(e)[0];
|
||||
}
|
||||
|
||||
console.log('firstPoint', firstPoint);
|
||||
|
||||
|
||||
// if (firstPoint) {
|
||||
// var label = myChart.data.labels[firstPoint._index];
|
||||
// var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
|
||||
// }
|
||||
if (firstPoint)
|
||||
{// PNOTE - TODO - Is await needed in this expression?
|
||||
await this.setState({
|
||||
{
|
||||
this.setState({
|
||||
xcoordinate:e.offsetX+20,
|
||||
ycoordinate:e.offsetY,
|
||||
showpopUp:true,
|
||||
firstpoint_ts:this.props.data[firstPoint._index].timestamp,
|
||||
// graphInfo:{...event}
|
||||
})
|
||||
}
|
||||
// console.log(this.state.graphInfo.payload.timestamp)
|
||||
//this.props.applicationTimeStamp(e.payload.x)
|
||||
// this.props.history.push('/traces?timestamp=' + e.payload.timestamp + '&service=' + this.props.service.name)
|
||||
else
|
||||
{
|
||||
// if clicked outside of the graph line, then firstpoint is undefined -> close popup.
|
||||
// Only works for clicking in the same chart - as click handler only detects clicks in that chart
|
||||
this.setState({
|
||||
|
||||
showpopUp:false,
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
gotoTracesHandler=()=>{
|
||||
console.log('in gotoTraces handler')
|
||||
gotoTracesHandler=(xc:any)=>{
|
||||
this.props.history.push('/traces')
|
||||
// this.props.history.push('/traces?timestamp=' + this.state.graphInfo.payload.timestamp + '&service=' + this.props.service.name)
|
||||
}
|
||||
|
||||
gotoAlertsHandler=()=>{
|
||||
console.log('in gotoAlerts handler')
|
||||
this.props.history.push('/service-map')
|
||||
// PNOTE - Keeping service map for now, will replace with alerts when alert page is made
|
||||
}
|
||||
|
||||
options_charts: ChartOptions = {
|
||||
|
||||
// onClick: function(evt, element) {
|
||||
// // console.log(evt);
|
||||
// },
|
||||
|
||||
//- PNOTE - TO DO -- element is of type ChartElement, how to define its type
|
||||
// https://gitlab.com/signoz-frontend/sample-project/-/blob/darkthemechanges/src/Components/Application/Graphs/SimpleLineChart.js
|
||||
// Code for popup
|
||||
// onClick: function(evt, element :any[]) {
|
||||
// if (element.length > 0) {
|
||||
// var ind = element[0]._index;
|
||||
// console.log(element)
|
||||
// alert(ind);
|
||||
// }
|
||||
// },
|
||||
|
||||
onClick: this.onClickhandler,
|
||||
|
||||
maintainAspectRatio: true,
|
||||
@ -168,8 +114,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
fontFamily: 'Arial',
|
||||
fontStyle: 'regular',
|
||||
fontColor:theme === 'dark'? 'rgb(200, 200, 200)':'rgb(20, 20, 20)' ,
|
||||
|
||||
|
||||
},
|
||||
|
||||
legend: {
|
||||
@ -189,26 +133,20 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
bodyFontSize: 10,
|
||||
titleFontSize: 10,
|
||||
bodyFontSize: 12,
|
||||
titleFontSize: 12,
|
||||
|
||||
callbacks: {
|
||||
label: function(tooltipItem, data) {
|
||||
|
||||
if (typeof(tooltipItem.yLabel) === 'number')
|
||||
{
|
||||
return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel.toFixed(3);
|
||||
return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel.toFixed(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
// return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel!.Fixed(3);
|
||||
// not able to do toFixed(3) in typescript as string|number type is not working with toFixed(3) function for
|
||||
// as toFixed() function only works with numbers
|
||||
// using type of check gives issues in 'label' variable name
|
||||
//!That's the non-null assertion operator. It is a way to tell the compiler "this expression cannot be null or undefined here, so don't complain about the possibility of it being null or undefined." Sometimes the type checker is unable to make that determination itself.
|
||||
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -224,12 +162,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
maxTicksLimit: 6,
|
||||
},
|
||||
|
||||
// scaleLabel: {
|
||||
// display: true,
|
||||
// labelString: 'latency in ms',
|
||||
// fontSize: 6,
|
||||
// padding: 4,
|
||||
// },
|
||||
gridLines: {
|
||||
// You can change the color, the dash effect, the main axe color, etc.
|
||||
borderDash: [1, 4],
|
||||
@ -258,22 +190,11 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
}
|
||||
|
||||
GraphTracePopUp = () => {
|
||||
console.log('state in GraphTracePopPup',this.state);
|
||||
|
||||
if (this.state.showpopUp){
|
||||
return(
|
||||
|
||||
// <div className='applicationpopup' style={{top:`${this.state.ycoordinate}px`,zIndex:10,position:'absolute',left:`${this.state.xcoordinate}px`,backgroundColor:'white',border:'1px solid grey'}}>
|
||||
// <p style={{color:'black'}} onClick={this.gotoTracesHandler}>View Traces</p>
|
||||
// <p style={{color:'black'}}> Set Alerts</p>
|
||||
// </div>
|
||||
// <ChartPopUpUnique>
|
||||
// <p style={{color:'black'}} onClick={this.gotoTracesHandler}>View Traces</p>
|
||||
// <p style={{color:'black'}}> Set Alerts</p>
|
||||
// </ChartPopUpUnique>
|
||||
|
||||
<ChartPopUpUnique xcoordinate={this.state.xcoordinate} ycoordinate={this.state.ycoordinate}>
|
||||
<PopUpElements onClick={this.gotoTracesHandler}>View Traces</PopUpElements>
|
||||
<PopUpElements onClick={() => this.props.popupClickHandler(this.state.firstpoint_ts)}>View Traces</PopUpElements>
|
||||
<PopUpElements onClick={this.gotoAlertsHandler}>Set Alerts</PopUpElements>
|
||||
</ChartPopUpUnique>
|
||||
|
||||
@ -289,18 +210,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
render(){
|
||||
|
||||
const ndata = this.props.data;
|
||||
// console.log("in chartJS line render function")
|
||||
// console.log(ndata);
|
||||
|
||||
// const data_charts = data.map( s => ({label:s.ts, value:parseFloat(s.val)}) );
|
||||
// if(this.chartRef.ctx)
|
||||
// {
|
||||
// var gradient = this.chartRef.ctx.createLinearGradient(0, 0, 0, 400);
|
||||
// gradient.addColorStop(0, 'rgba(250,174,50,1)');
|
||||
// gradient.addColorStop(1, 'rgba(250,174,50,0)');
|
||||
// }
|
||||
|
||||
|
||||
|
||||
const data_chartJS = (canvas:any) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
@ -311,9 +220,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
datasets: [{
|
||||
label: 'p99 Latency',
|
||||
data: ndata.map(s => s.p99/1000000), //converting latency from nano sec to ms
|
||||
// backgroundColor:'#000000',
|
||||
// fill: true,
|
||||
// backgroundColor: gradient,
|
||||
pointRadius: 0.5,
|
||||
borderColor: 'rgba(250,174,50,1)', // Can also add transparency in border color
|
||||
borderWidth: 2,
|
||||
@ -321,9 +227,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
{
|
||||
label: 'p90 Latency',
|
||||
data: ndata.map(s => s.p90/1000000), //converting latency from nano sec to ms
|
||||
// backgroundColor:'#dd0000',
|
||||
// fill: true,
|
||||
// backgroundColor: 'rgba(227, 74, 51, 1.0)',
|
||||
pointRadius: 0.5,
|
||||
borderColor: 'rgba(227, 74, 51, 1.0)',
|
||||
borderWidth: 2,
|
||||
@ -331,9 +234,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps>{
|
||||
{
|
||||
label: 'p50 Latency',
|
||||
data: ndata.map(s => s.p50/1000000), //converting latency from nano sec to ms
|
||||
// backgroundColor:'#dd0000',
|
||||
// fill: true,
|
||||
// backgroundColor: 'rgba(227, 74, 51, 1.0)',
|
||||
pointRadius: 0.5,
|
||||
borderColor: 'rgba(57, 255, 20, 1.0)',
|
||||
borderWidth: 2,
|
||||
|
@ -14,7 +14,7 @@ zIndex:10;
|
||||
position:absolute;
|
||||
top:${props => props.ycoordinate}px;
|
||||
left:${props => props.xcoordinate}px;
|
||||
font-size:10px;
|
||||
font-size:12px;
|
||||
border-radius:2px;
|
||||
`;
|
||||
|
||||
@ -29,40 +29,10 @@ padding-right:4px;
|
||||
`;
|
||||
|
||||
|
||||
// const data_charts = {
|
||||
// labels: ['1', '2', '3', '4', '5', '6'],
|
||||
// datasets: [
|
||||
// {
|
||||
// // label: '# of Votes',
|
||||
// data: [12, 19, 3, 5, 2, 3],
|
||||
// fill: false,
|
||||
// backgroundColor: 'rgb(255, 99, 132)',
|
||||
// borderColor: 'rgba(255, 99, 132, 0.2)',
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
|
||||
// const onClickHandler = (e) => {
|
||||
// console.log("ChartJS chart clicked");
|
||||
// console.log(e);
|
||||
// };
|
||||
|
||||
// export interface ApiData {
|
||||
// 0: number, // has epoch timestamp
|
||||
// 1: string, // has value of the metric as a string
|
||||
// }
|
||||
|
||||
const theme = 'dark';
|
||||
|
||||
// PNOTE - accessing history object in typescript - https://stackoverflow.com/questions/49342390/typescript-how-to-add-type-check-for-history-object-in-react
|
||||
// withRouter is used to pass on history object as prop - https://stackoverflow.com/questions/43107912/how-to-access-history-object-in-new-react-router-v4
|
||||
|
||||
|
||||
interface RequestRateChartProps extends RouteComponentProps<any> {
|
||||
data : metricItem[],
|
||||
// chartRef: any,
|
||||
// chartReference :ChartJSLineChart,
|
||||
// data passed to ChartJSLineChart component is an array if json objects
|
||||
}
|
||||
|
||||
interface RequestRateChart {
|
||||
@ -74,14 +44,10 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
|
||||
constructor(props: RequestRateChartProps) {
|
||||
super(props);
|
||||
console.log('React CreatRef', React.createRef());
|
||||
this.chartRef = React.createRef();
|
||||
}
|
||||
|
||||
|
||||
|
||||
state = {
|
||||
// data: props.data,
|
||||
xcoordinate:0,
|
||||
ycoordinate:0,
|
||||
showpopUp:false,
|
||||
@ -91,26 +57,11 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
|
||||
onClickhandler = async(e:any,event:any) => {
|
||||
|
||||
console.log('e graph', e)
|
||||
// console.log('event graph',event)
|
||||
//PNOTE - e has all key values from mouse event, event has only reference to handler functions
|
||||
// PNOTE - https://github.com/emn178/angular2-chartjs/issues/29 - for listening only to element points
|
||||
// var firstPoin = this.chart.current.getElementAtEvent(e)
|
||||
|
||||
console.log('chartref',this.chartRef.current.chartInstance);
|
||||
|
||||
var firstPoint;
|
||||
if(this.chartRef){
|
||||
firstPoint = this.chartRef.current.chartInstance.getElementAtEvent(e)[0];
|
||||
}
|
||||
|
||||
console.log('firstPoint', firstPoint);
|
||||
|
||||
|
||||
// if (firstPoint) {
|
||||
// var label = myChart.data.labels[firstPoint._index];
|
||||
// var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
|
||||
// }
|
||||
if (firstPoint)
|
||||
{// PNOTE - TODO - Is await needed in this expression?
|
||||
await this.setState({
|
||||
@ -120,40 +71,20 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
// graphInfo:{...event}
|
||||
})
|
||||
}
|
||||
// console.log(this.state.graphInfo.payload.timestamp)
|
||||
//this.props.applicationTimeStamp(e.payload.x)
|
||||
// this.props.history.push('/traces?timestamp=' + e.payload.timestamp + '&service=' + this.props.service.name)
|
||||
|
||||
}
|
||||
|
||||
gotoTracesHandler=()=>{
|
||||
console.log('in gotoTraces handler')
|
||||
this.props.history.push('/traces')
|
||||
// this.props.history.push('/traces?timestamp=' + this.state.graphInfo.payload.timestamp + '&service=' + this.props.service.name)
|
||||
}
|
||||
|
||||
gotoAlertsHandler=()=>{
|
||||
console.log('in gotoAlerts handler')
|
||||
this.props.history.push('/service-map')
|
||||
// PNOTE - Keeping service map for now, will replace with alerts when alert page is made
|
||||
}
|
||||
|
||||
options_charts: ChartOptions = {
|
||||
|
||||
// onClick: function(evt, element) {
|
||||
// // console.log(evt);
|
||||
// },
|
||||
|
||||
//- PNOTE - TO DO -- element is of type ChartElement, how to define its type
|
||||
// https://gitlab.com/signoz-frontend/sample-project/-/blob/darkthemechanges/src/Components/Application/Graphs/SimpleLineChart.js
|
||||
// Code for popup
|
||||
// onClick: function(evt, element :any[]) {
|
||||
// if (element.length > 0) {
|
||||
// var ind = element[0]._index;
|
||||
// console.log(element)
|
||||
// alert(ind);
|
||||
// }
|
||||
// },
|
||||
|
||||
onClick: this.onClickhandler,
|
||||
|
||||
maintainAspectRatio: true,
|
||||
@ -168,8 +99,6 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
fontFamily: 'Arial',
|
||||
fontStyle: 'regular',
|
||||
fontColor:theme === 'dark'? 'rgb(200, 200, 200)':'rgb(20, 20, 20)' ,
|
||||
|
||||
|
||||
},
|
||||
|
||||
legend: {
|
||||
@ -182,32 +111,25 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
fontSize: 10,
|
||||
boxWidth : 10,
|
||||
usePointStyle : true,
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
bodyFontSize: 10,
|
||||
titleFontSize: 10,
|
||||
bodyFontSize: 12,
|
||||
titleFontSize: 12,
|
||||
|
||||
callbacks: {
|
||||
label: function(tooltipItem, data) {
|
||||
|
||||
if (typeof(tooltipItem.yLabel) === 'number')
|
||||
{
|
||||
return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel.toFixed(3);
|
||||
return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel.toFixed(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
// return data.datasets![tooltipItem.datasetIndex!].label +' : '+ tooltipItem.yLabel!.Fixed(3);
|
||||
// not able to do toFixed(3) in typescript as string|number type is not working with toFixed(3) function for
|
||||
// as toFixed() function only works with numbers
|
||||
// using type of check gives issues in 'label' variable name
|
||||
//!That's the non-null assertion operator. It is a way to tell the compiler "this expression cannot be null or undefined here, so don't complain about the possibility of it being null or undefined." Sometimes the type checker is unable to make that determination itself.
|
||||
|
||||
},
|
||||
},
|
||||
@ -224,12 +146,7 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
maxTicksLimit: 6,
|
||||
},
|
||||
|
||||
// scaleLabel: {
|
||||
// display: true,
|
||||
// labelString: 'latency in ms',
|
||||
// fontSize: 6,
|
||||
// padding: 4,
|
||||
// },
|
||||
|
||||
gridLines: {
|
||||
// You can change the color, the dash effect, the main axe color, etc.
|
||||
borderDash: [1, 4],
|
||||
@ -256,26 +173,13 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
}
|
||||
|
||||
GraphTracePopUp = () => {
|
||||
console.log('state in GraphTracePopPup',this.state);
|
||||
|
||||
if (this.state.showpopUp){
|
||||
return(
|
||||
|
||||
// <div className='applicationpopup' style={{top:`${this.state.ycoordinate}px`,zIndex:10,position:'absolute',left:`${this.state.xcoordinate}px`,backgroundColor:'white',border:'1px solid grey'}}>
|
||||
// <p style={{color:'black'}} onClick={this.gotoTracesHandler}>View Traces</p>
|
||||
// <p style={{color:'black'}}> Set Alerts</p>
|
||||
// </div>
|
||||
// <ChartPopUpUnique>
|
||||
// <p style={{color:'black'}} onClick={this.gotoTracesHandler}>View Traces</p>
|
||||
// <p style={{color:'black'}}> Set Alerts</p>
|
||||
// </ChartPopUpUnique>
|
||||
|
||||
<ChartPopUpUnique xcoordinate={this.state.xcoordinate} ycoordinate={this.state.ycoordinate}>
|
||||
<PopUpElements onClick={this.gotoTracesHandler}>View Traces</PopUpElements>
|
||||
<PopUpElements onClick={this.gotoAlertsHandler}>Set Alerts</PopUpElements>
|
||||
</ChartPopUpUnique>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
else
|
||||
@ -287,18 +191,6 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
render(){
|
||||
|
||||
const ndata = this.props.data;
|
||||
// console.log("in chartJS line render function")
|
||||
// console.log(ndata);
|
||||
|
||||
// const data_charts = data.map( s => ({label:s.ts, value:parseFloat(s.val)}) );
|
||||
// if(this.chartRef.ctx)
|
||||
// {
|
||||
// var gradient = this.chartRef.ctx.createLinearGradient(0, 0, 0, 400);
|
||||
// gradient.addColorStop(0, 'rgba(250,174,50,1)');
|
||||
// gradient.addColorStop(1, 'rgba(250,174,50,0)');
|
||||
// }
|
||||
|
||||
|
||||
|
||||
const data_chartJS = (canvas:any) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
@ -309,19 +201,14 @@ class RequestRateChart extends React.Component<RequestRateChartProps>{
|
||||
datasets: [{
|
||||
label: 'Request per sec',
|
||||
data: ndata.map(s => s.callRate),
|
||||
// backgroundColor:'#000000',
|
||||
// fill: true,
|
||||
// backgroundColor: gradient,
|
||||
pointRadius: 0.5,
|
||||
borderColor: 'rgba(250,174,50,1)', // Can also add transparency in border color
|
||||
borderWidth: 2,
|
||||
},
|
||||
|
||||
]}
|
||||
|
||||
};
|
||||
|
||||
|
||||
return(
|
||||
<div>
|
||||
{this.GraphTracePopUp()}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React,{useEffect} from 'react';
|
||||
import { Tabs, Card, Row, Col} from 'antd';
|
||||
import { connect } from 'react-redux';
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useParams, RouteComponentProps } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
|
||||
|
||||
import { getServicesMetrics, metricItem, getTopEndpoints, topEndpointListItem, GlobalTime } from '../../actions';
|
||||
import { getServicesMetrics, metricItem, getTopEndpoints, topEndpointListItem, GlobalTime, updateTimeInterval } from '../../actions';
|
||||
import { StoreState } from '../../reducers'
|
||||
import LatencyLineChart from "./LatencyLineChart"
|
||||
import RequestRateChart from './RequestRateChart'
|
||||
@ -13,25 +13,30 @@ import TopEndpointsTable from './TopEndpointsTable';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
interface ServicesMetricsProps {
|
||||
interface ServicesMetricsProps extends RouteComponentProps<any>{
|
||||
serviceMetrics: metricItem[],
|
||||
getServicesMetrics: Function,
|
||||
topEndpointsList: topEndpointListItem[],
|
||||
getTopEndpoints: Function,
|
||||
globalTime: GlobalTime,
|
||||
updateTimeInterval: Function,
|
||||
}
|
||||
|
||||
|
||||
const _ServiceMetrics = (props: ServicesMetricsProps) => {
|
||||
|
||||
const params = useParams<{ servicename?: string; }>();
|
||||
console.log('service name',params.servicename);
|
||||
|
||||
useEffect( () => {
|
||||
props.getServicesMetrics(params.servicename,props.globalTime);
|
||||
props.getTopEndpoints(params.servicename,props.globalTime);
|
||||
}, [props.globalTime,params.servicename]);
|
||||
|
||||
const onTracePopupClick = (timestamp:number) => {
|
||||
|
||||
props.updateTimeInterval('custom',[(timestamp/1000000)-5*60*1000,(timestamp/1000000)])// updateTimeInterval takes second range in ms -- give -5 min to selected time,
|
||||
props.history.push('/traces')
|
||||
}
|
||||
return (
|
||||
<Tabs defaultActiveKey="1">
|
||||
<TabPane tab="Application Metrics" key="1">
|
||||
@ -39,7 +44,7 @@ const _ServiceMetrics = (props: ServicesMetricsProps) => {
|
||||
<Row gutter={32} style={{ margin: 20 }}>
|
||||
<Col span={12} >
|
||||
<Card bodyStyle={{padding:10}}>
|
||||
<LatencyLineChart data={props.serviceMetrics} />
|
||||
<LatencyLineChart data={props.serviceMetrics} popupClickHandler={onTracePopupClick} />
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
@ -88,11 +93,11 @@ const mapStateToProps = (state: StoreState): { serviceMetrics: metricItem[], top
|
||||
|
||||
return { serviceMetrics : state.serviceMetrics, topEndpointsList: state.topEndpointsList, globalTime:state.globalTime};
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
export const ServiceMetrics = connect(mapStateToProps, {
|
||||
export const ServiceMetrics = withRouter(connect(mapStateToProps, {
|
||||
getServicesMetrics: getServicesMetrics,
|
||||
getTopEndpoints: getTopEndpoints,
|
||||
})(_ServiceMetrics);
|
||||
updateTimeInterval: updateTimeInterval,
|
||||
|
||||
})(_ServiceMetrics));
|
||||
|
||||
|
@ -24,10 +24,6 @@ padding-right:40px;
|
||||
.ant-table tfoot>tr>td, .ant-table tfoot>tr>th, .ant-table-tbody>tr>td, .ant-table-thead>tr>th { padding: 10px; };
|
||||
`;
|
||||
|
||||
//styling antd with styled components - https://codesandbox.io/s/8x1r670rxj
|
||||
|
||||
|
||||
|
||||
|
||||
const columns = [
|
||||
|
||||
@ -69,7 +65,6 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
|
||||
const search = useLocation().search;
|
||||
const time_interval = new URLSearchParams(search).get('time');
|
||||
console.log(time_interval)
|
||||
|
||||
useEffect( () => {
|
||||
props.getServicesList(props.globalTime);
|
||||
@ -79,7 +74,6 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
return(
|
||||
|
||||
<Wrapper>
|
||||
{console.log(props.servicesList)}
|
||||
<Table dataSource={props.servicesList} columns={columns} pagination={false} />
|
||||
</Wrapper>
|
||||
|
||||
@ -88,11 +82,8 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState): { servicesList: servicesListItem[], globalTime: GlobalTime } => {
|
||||
// console.log(state);
|
||||
return { servicesList : state.servicesList, globalTime:state.globalTime};
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
export const ServicesTable = connect(mapStateToProps, {
|
||||
getServicesList: getServicesList,
|
||||
|
@ -26,9 +26,7 @@ const TopEndpointsTable = (props: TopEndpointsTableProps) => {
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
// sorter: (a:any, b:any) => a.startTime - b.startTime,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
//PNOTE - TO DO - Change this to API link if available
|
||||
|
||||
render: (text :string) => <NavLink to={'/' + text}>{text}</NavLink>,
|
||||
|
||||
},
|
||||
@ -61,21 +59,15 @@ const TopEndpointsTable = (props: TopEndpointsTableProps) => {
|
||||
dataIndex: 'numCalls',
|
||||
key: 'numCalls',
|
||||
sorter: (a:any, b:any) => a.numCalls - b.numCalls,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
// render: (value: number) => value.toFixed(2),
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
return(
|
||||
<Wrapper>
|
||||
<h6> Top Endpoints</h6>
|
||||
<Table dataSource={props.data} columns={columns} pagination={false} />
|
||||
</Wrapper>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default TopEndpointsTable;
|
@ -6,7 +6,6 @@ const ServiceMap = () => {
|
||||
return (
|
||||
|
||||
<div>
|
||||
{/* <div> Service Map </div> */}
|
||||
<ServiceGraph />
|
||||
</div>
|
||||
|
||||
|
@ -15,7 +15,6 @@ interface FilterStateDisplayProps {
|
||||
const _FilterStateDisplay = (props: FilterStateDisplayProps) => {
|
||||
|
||||
function handleCloseTag(value:string) {
|
||||
console.log('on close tag', value)
|
||||
if (value==='service')
|
||||
props.updateTraceFilters({...props.traceFilters,service:''})
|
||||
if (value==='operation')
|
||||
@ -28,7 +27,6 @@ const _FilterStateDisplay = (props: FilterStateDisplayProps) => {
|
||||
}
|
||||
|
||||
function handleCloseTagElement(item:TagItem){
|
||||
console.log('tag item closed in handle closeTagElement', item)
|
||||
props.updateTraceFilters({...props.traceFilters,tags:props.traceFilters.tags?.filter(elem => elem !== item)})
|
||||
|
||||
}
|
||||
@ -56,7 +54,6 @@ const _FilterStateDisplay = (props: FilterStateDisplayProps) => {
|
||||
onClose={e => {handleCloseTag('maxLatency');}}>
|
||||
maxLatency:{(parseInt(props.traceFilters.latency!.max)/1000000).toString()}ms
|
||||
</Tag> }
|
||||
{console.log('tagfilters before showing on card',props.traceFilters.tags)}
|
||||
{props.traceFilters.tags === undefined? null: props.traceFilters.tags.map( item => (
|
||||
<Tag style={{fontSize:14, padding: 8}} closable
|
||||
onClose={e => {handleCloseTagElement(item);}}>
|
||||
|
@ -2,11 +2,6 @@ import React from 'react';
|
||||
import { Modal, Form, InputNumber, Col, Row} from 'antd';
|
||||
import { Store } from 'antd/lib/form/interface';
|
||||
|
||||
// interface Values {
|
||||
// title: string;
|
||||
// description: string;
|
||||
// modifier: string;
|
||||
// }
|
||||
|
||||
interface LatencyModalFormProps {
|
||||
visible: boolean;
|
||||
@ -32,7 +27,6 @@ const LatencyModalForm: React.FC<LatencyModalFormProps> = ({
|
||||
.validateFields()
|
||||
.then(values => {
|
||||
form.resetFields();
|
||||
// onCreate({title:"hello",description:'good',modifier:'public'});
|
||||
onCreate(values); // giving error for values
|
||||
})
|
||||
.catch(info => {
|
||||
|
@ -17,7 +17,6 @@ interface SelectedSpanDetailsProps {
|
||||
const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => {
|
||||
|
||||
const callback = (key:any) => {
|
||||
console.log(key);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -67,7 +67,6 @@ interface TraceCustomVisualizationsProps {
|
||||
const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
|
||||
const [selectedEntity, setSelectedEntity] = useState('calls');
|
||||
// const [defaultOption, setDefaultOption]=useState('count');
|
||||
const [selectedAggOption, setSelectedAggOption] = useState('count');
|
||||
const [selectedStep, setSelectedStep] = useState('60');
|
||||
// Step should be multiples of 60, 60 -> 1 min
|
||||
@ -98,40 +97,27 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
function handleChange(value:string) {
|
||||
console.log(value);
|
||||
// console.log(value);
|
||||
}
|
||||
|
||||
// function handleChangeEntity(value:string) {
|
||||
// // console.log(value);
|
||||
// // setSelectedEntity(value);
|
||||
// setDefaultOption(aggregation_options.filter((item) => item.linked_entity === selectedEntity)[0].default_selected)
|
||||
// }
|
||||
|
||||
function handleFinish(value:string) {
|
||||
console.log(value);
|
||||
// console.log(value);
|
||||
}
|
||||
|
||||
|
||||
// PNOTE - Can also use 'coordinate' option in antd Select for implementing this - https://ant.design/components/select/
|
||||
const handleFormValuesChange = (changedValues:any) => {
|
||||
const formFieldName = Object.keys(changedValues)[0];
|
||||
// console.log('Object keys',Object.keys(changedValues) );
|
||||
if (formFieldName === 'entity') {
|
||||
|
||||
|
||||
// const a = selectedEntity; // why is selected entity not set instantly??
|
||||
|
||||
// setDefaultOption(aggregation_options.filter((item) => item.linked_entity === selectedEntity)[0].default_selected)
|
||||
const temp_entity = aggregation_options.filter((item) => item.linked_entity === changedValues[formFieldName])[0];
|
||||
|
||||
form.setFieldsValue( {
|
||||
// agg_options : aggregation_options.filter((item) => item.linked_entity === selectedEntity)[0].default_selected,
|
||||
agg_options : temp_entity.default_selected.title,
|
||||
// PNOTE - TO DO Check if this has the same behaviour as selecting an option?
|
||||
})
|
||||
|
||||
let temp = form.getFieldsValue(['agg_options','entity']);
|
||||
console.log('custom metric field values',temp,temp.entity,temp.agg_options);
|
||||
|
||||
setSelectedEntity(temp.entity);
|
||||
setSelectedAggOption(temp.agg_options);
|
||||
@ -146,13 +132,6 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Make api calls here and display data
|
||||
// PNOTE - TO DO - API CALL location - may be through action creators and set states in redux store?
|
||||
|
||||
// PNOTE - Change this
|
||||
// API call via useEffects after monitoring traces
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -167,12 +146,10 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
form={form}
|
||||
onFinish={handleFinish}
|
||||
onValuesChange={handleFormValuesChange}
|
||||
// initialValues={ agg_options: 'Count'}
|
||||
initialValues={{ agg_options: 'Count', chart_style:'line', interval:'5m', group_by:'none' }}
|
||||
>
|
||||
<Space>
|
||||
<Form.Item name="entity">
|
||||
{/* <Select defaultValue={selectedEntity} style={{ width: 120 }} onChange={handleChangeEntity} allowClear> */}
|
||||
|
||||
<Select defaultValue={selectedEntity} style={{ width: 120 }} allowClear>
|
||||
{entity.map((item) => (
|
||||
@ -197,11 +174,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
{/* <Select defaultValue="count" style={{ width: 120 }} onChange={handleChange} allowClear>
|
||||
<Option value="count">Count</Option>
|
||||
<Option value="sume">Sum</Option>
|
||||
<Option value="rate">Rate</Option>
|
||||
</Select> */}
|
||||
|
||||
<Form.Item name="chart_style">
|
||||
<Select style={{ width: 120 }} onChange={handleChange} allowClear>
|
||||
<Option value="line">Line Chart</Option>
|
||||
@ -239,14 +212,10 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState): { filteredTraceMetrics: customMetricsItem[] , globalTime: GlobalTime, traceFilters: TraceFilters} => {
|
||||
// console.log(state);
|
||||
return { filteredTraceMetrics : state.filteredTraceMetrics, globalTime: state.globalTime,traceFilters:state.traceFilters };
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
|
||||
export const TraceCustomVisualizations = connect(mapStateToProps, {
|
||||
getFilteredTraceMetrics: getFilteredTraceMetrics,
|
||||
})(_TraceCustomVisualizations);
|
||||
|
||||
// export default TraceCustomVisualizations;
|
@ -7,14 +7,11 @@ import { TraceList } from './TraceList';
|
||||
|
||||
|
||||
const TraceDetail = () => {
|
||||
// const [serviceName, setServiceName] = useState('Frontend'); //default value of service name
|
||||
|
||||
return (
|
||||
|
||||
<div>
|
||||
{/* <div>Tracing Detail Page</div> */}
|
||||
<TraceFilter />
|
||||
{/* <TraceFilter servicename={serviceName} /> */}
|
||||
<TraceCustomVisualizations />
|
||||
<TraceList />
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React,{useEffect, useState} from 'react';
|
||||
import { Select, Button, Input, Tag, Card, Form, AutoComplete} from 'antd';
|
||||
import { Select, Button, Input, Form, AutoComplete} from 'antd';
|
||||
import { connect } from 'react-redux';
|
||||
import { Store } from 'antd/lib/form/interface';
|
||||
import styled from 'styled-components';
|
||||
@ -43,7 +43,6 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
|
||||
useEffect( () => {
|
||||
metricsAPI.get<string[]>('services/list').then(response => {
|
||||
// console.log(response.data);
|
||||
setServiceList( response.data );
|
||||
});
|
||||
}, []);
|
||||
@ -57,18 +56,9 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
request_string=request_string+'&tags='+encodeURIComponent(JSON.stringify(props.traceFilters.tags));
|
||||
|
||||
props.fetchTraces(props.globalTime, request_string)
|
||||
console.log('stringified traceFilters redux state',encodeURIComponent(JSON.stringify(props.traceFilters.tags)));
|
||||
}, [props.traceFilters,props.globalTime]);
|
||||
|
||||
|
||||
// useEffect( () => {
|
||||
|
||||
// tagKeyOptions.map(s => options.push({'value':s.tagKeys}));
|
||||
// console.log('tagoptions USeEffect',options)
|
||||
// }, [tagKeyOptions]);
|
||||
|
||||
// Use effects run in the order they are specified
|
||||
|
||||
useEffect ( () => {
|
||||
|
||||
let latencyButtonText = 'Latency';
|
||||
@ -115,17 +105,14 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
}
|
||||
|
||||
function handleChangeService(value:string) {
|
||||
console.log(value);
|
||||
let service_request='/service/'+value+'/operations';
|
||||
metricsAPI.get<string[]>(service_request).then(response => {
|
||||
console.log('operations',response.data);
|
||||
// form_basefilter.resetFields(['operation',])
|
||||
setOperationsList( response.data );
|
||||
});
|
||||
|
||||
let tagkeyoptions_request='tags?service='+value;
|
||||
metricsAPI.get<TagKeyOptionItem[]>(tagkeyoptions_request).then(response => {
|
||||
console.log('tag key options',response.data);
|
||||
setTagKeyOptions( response.data );
|
||||
});
|
||||
|
||||
@ -140,24 +127,14 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
|
||||
const onLatencyModalApply = (values: Store) => {
|
||||
setModalVisible(false);
|
||||
console.log('Received values of form: ', values);
|
||||
//Latency modal form returns null if the value entered is not a number or string etc or empty
|
||||
props.updateTraceFilters({...props.traceFilters,latency:{min:values.min?(parseInt(values.min)*1000000).toString():"", max:values.max?(parseInt(values.max)*1000000).toString():""}})
|
||||
// setLatencyFilterValues()
|
||||
|
||||
}
|
||||
|
||||
const onTagFormSubmit = (values:any) => {
|
||||
console.log(values);
|
||||
|
||||
// setTagKeyValueApplied(tagKeyValueApplied => [...tagKeyValueApplied, values.tag_key+' '+values.operator+' '+values.tag_value]);
|
||||
// making API calls with only tags data for testing, for last tagform submit
|
||||
// ideally all tags including service, operations, tags, latency selected should be in one state and used
|
||||
// to make API call and update trace list
|
||||
let request_tags= 'service=frontend&tags='+encodeURIComponent(JSON.stringify([{"key":values.tag_key,"value":values.tag_value,"operator":values.operator}]))
|
||||
// props.fetchTraces(request_tags)
|
||||
|
||||
// form field names are tag_key & tag_value
|
||||
// data structure has key, value & operator
|
||||
|
||||
if (props.traceFilters.tags){ // If there are existing tag filters present
|
||||
props.updateTraceFilters(
|
||||
@ -183,9 +160,6 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
}
|
||||
|
||||
const onTagClose = (value:string) => {
|
||||
console.log(value);
|
||||
// setJoinList(joinList.filter((e)=>(e !== name)))
|
||||
// removing closed tag from the tagKeyValueApplied array
|
||||
setTagKeyValueApplied(tagKeyValueApplied.filter( e => (e !== value)));
|
||||
|
||||
}
|
||||
@ -206,9 +180,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
|
||||
// PNOTE - Remove any
|
||||
const handleApplyFilterForm = (values:any) => {
|
||||
console.log('values are', values);
|
||||
console.log(typeof(values.service))
|
||||
console.log(typeof(values.operation))
|
||||
|
||||
let request_params: string ='';
|
||||
if (typeof values.service !== undefined && typeof(values.operation) !== undefined)
|
||||
{
|
||||
@ -224,12 +196,8 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
}
|
||||
|
||||
request_params=request_params+'&minDuration='+latencyFilterValues.min+'&maxDuration='+latencyFilterValues.max;
|
||||
console.log(request_params);
|
||||
|
||||
// props.fetchTraces(request_params)
|
||||
|
||||
// console.log(props.inputTag)
|
||||
// props.updateTagFilters([{key:props.inputTag, value: props.inputTag }]);
|
||||
setTagKeyValueApplied(tagKeyValueApplied => [...tagKeyValueApplied, 'service eq'+values.service, 'operation eq '+values.operation, 'maxduration eq '+ (parseInt(latencyFilterValues.max)/1000000).toString(), 'minduration eq '+(parseInt(latencyFilterValues.min)/1000000).toString()]);
|
||||
props.updateTraceFilters({'service':values.service,'operation':values.operation,'latency':latencyFilterValues})
|
||||
}
|
||||
@ -238,7 +206,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
return (
|
||||
<div>
|
||||
<div>Filter Traces</div>
|
||||
<div>{JSON.stringify(props.traceFilters)}</div>
|
||||
{/* <div>{JSON.stringify(props.traceFilters)}</div> */}
|
||||
|
||||
<Form form={form_basefilter} layout='inline' onFinish={handleApplyFilterForm} initialValues={{ service:'', operation:'',latency:'Latency',}} style={{marginTop: 10, marginBottom:10}}>
|
||||
<FormItem rules={[{ required: true }]} name='service'>
|
||||
@ -250,13 +218,6 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
<FormItem name='operation'>
|
||||
<Select showSearch style={{ width: 180 }} onChange={handleChangeOperation} placeholder='Select Operation' allowClear>
|
||||
{operationList.map( item => <Option value={item}>{item}</Option>)}
|
||||
{/* We need to URL encode before making API call on form submission */}
|
||||
{/* <Option value="HTTP%20GET">HTTP GET</Option>
|
||||
<Option value="HTTP%20GET%20%2Fdispatch">HTTP GET /dispatch</Option>
|
||||
<Option value="HTTP%20GET%3A%20%2Froute">HTTP GET: /route</Option>
|
||||
<Option value="%2Fdriver.DriverService%2FFindNearest">/driver.DriverService/FindNearest</Option>
|
||||
<Option value="HTTP%20GET%20%2Fcustomer">HTTP GET /customer</Option> */}
|
||||
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
@ -271,10 +232,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
|
||||
<FilterStateDisplay />
|
||||
|
||||
{/* <Card style={{padding: 6, marginTop: 10, marginBottom: 10}} bodyStyle={{padding: 6}}>
|
||||
<Tag style={{fontSize:14, padding: 8}} closable> status:200 </Tag><Tag style={{fontSize:14, padding: 8}} closable> customerid:123 </Tag>
|
||||
{tagKeyValueApplied.map( item => <Tag key={item} style={{fontSize:14, padding: 8}} onClose={() => onTagClose(item)} closable> {item} </Tag>)}
|
||||
</Card> */}
|
||||
|
||||
{/* // What will be the empty state of card when there is no Tag , it should show something */}
|
||||
|
||||
<InfoWrapper>Select Service to get Tag suggestions </InfoWrapper>
|
||||
@ -282,8 +240,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
<Form form={form} layout='inline' onFinish={onTagFormSubmit} initialValues={{operator:'equals'}} style={{marginTop: 10, marginBottom:10}}>
|
||||
|
||||
<FormItem rules={[{ required: true }]} name='tag_key'>
|
||||
{/* <Input style={{ width: 160, textAlign: 'center' }} placeholder="Tag Key" /> */}
|
||||
{/* Not using tag count data to show in options */}
|
||||
|
||||
|
||||
<AutoComplete
|
||||
options={tagKeyOptions.map((s) => { return ({'value' : s.tagKeys}) })}
|
||||
@ -296,14 +253,12 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
}
|
||||
placeholder="Tag Key"
|
||||
/>
|
||||
{/* // ! means that we are saying object can't be undefined */}
|
||||
</FormItem>
|
||||
|
||||
<FormItem name='operator'>
|
||||
<Select style={{ width: 120, textAlign: 'center' }}>
|
||||
<Option value="equals">EQUAL</Option>
|
||||
<Option value="contains">CONTAINS</Option>
|
||||
{/* <Option value="not-in">NOT IN</Option> */}
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
@ -329,7 +284,6 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState): { traceFilters: TraceFilters, globalTime: GlobalTime } => {
|
||||
// console.log(state);
|
||||
return { traceFilters: state.traceFilters, globalTime: state.globalTime };
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,6 @@ import * as d3Tip from 'd3-tip';
|
||||
|
||||
//import * as d3Tip from 'd3-tip';
|
||||
// PNOTE - uninstall @types/d3-tip. issues with importing d3-tip https://github.com/Caged/d3-tip/issues/181
|
||||
// import styled from 'styled-components';
|
||||
|
||||
import './TraceGraph.css'
|
||||
import { spanToTreeUtil } from '../../utils/spanToTree'
|
||||
@ -31,7 +30,6 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
const [clickedSpanTags,setClickedSpanTags]=useState([])
|
||||
|
||||
useEffect( () => {
|
||||
console.log('inside initial fetch trace for flamegraph')
|
||||
props.fetchTraceItem(params.id);
|
||||
}, []);
|
||||
|
||||
@ -45,29 +43,12 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
// if this monitoring of props.traceItem.data is removed then zoom on click doesn't work
|
||||
// Doesn't work if only do initial check, works if monitor an element - as it may get updated in sometime
|
||||
|
||||
// PNOTE - Is this being called multiple times?
|
||||
//PNOTE - Do we fetch trace data again based on id or do we call again using rest calls
|
||||
// d3-flame-graph repository -- https://github.com/spiermar/d3-flame-graph
|
||||
|
||||
// const tip = d3.tip().attr('class', 'd3-tip').html(function(d) { return d; });
|
||||
// const tip = d3Tip.default().attr('class', 'd3-flame-graph-tip').html(function(d:any) { console.log(d);return 'Name -> '+d.data.name+'<BR>Duration -> '+d.data.value});
|
||||
//https://stackoverflow.com/questions/5934928/javascript-return-value-for-tooltip -> How to display tooltip
|
||||
//const tip = d3Tip.default().attr('class', 'd3-tip').html(function(d:any) { console.log(d);return <FlamegraphTooltip>{d.data.name}</FlamegraphTooltip>});
|
||||
|
||||
// var tip = flamegraph.tooltip.defaultFlamegraphTooltip().html(function(d) { return "name: " + d.data.name + ", value: " + d.data.value; });
|
||||
const tip = d3Tip.default().attr('class', 'd3-tip').html(function(d:any) { return d.data.name+'<br>duration: '+d.data.value});
|
||||
// PNOTE - Used this example for tooltip styling
|
||||
|
||||
const onClick = (z:any) => {
|
||||
// props.tagsInfo(d.data.tags)
|
||||
// let new_tags = z.data.tags;
|
||||
// let new_tags = [{
|
||||
// key: 'Ankit',
|
||||
// type: 'testin',
|
||||
// value: 'Nothing',
|
||||
// }]
|
||||
// setClickedSpanTags(new_tags);
|
||||
// setNum(9);
|
||||
|
||||
setClickedSpanTags(z.data.tags);
|
||||
console.log(`Clicked on ${z.data.name}, id: "${z.id}"`);
|
||||
}
|
||||
@ -86,24 +67,6 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
// .title("Trace Flame graph")
|
||||
.differential(false)
|
||||
.selfValue(true); //sets span width based on value - which is mapped to duration
|
||||
//PNOTE
|
||||
// used inverted() instead of passing a function in Sort
|
||||
// .sort(function(a :pushDStree,b :pushDStree) :number{
|
||||
// if(a.startTime < b.startTime) return -1;
|
||||
// else return 1;
|
||||
// })
|
||||
//removed transition ease - easeCubic as it was giving type error. d3.easeCubic is the default transition easing function
|
||||
//Example to sort in reverse order
|
||||
//.sort(function(a,b){ return d3.descending(a.name, b.name);})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// PNOTE - filter based on traceid - trace should already be in redux-state, will redux-state become very big if all trace reponses are stored in it
|
||||
|
||||
//if tree
|
||||
// d3.select("#chart").datum(tree).call(chart)
|
||||
|
||||
const resetZoom = () => {
|
||||
chart.resetZoom();
|
||||
@ -136,11 +99,9 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState): { traceItem: spansWSameTraceIDResponse } => {
|
||||
// console.log(state);
|
||||
return { traceItem: state.traceItem };
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
|
||||
export const TraceGraph = connect(mapStateToProps, {
|
||||
fetchTraceItem: fetchTraceItem,
|
||||
|
@ -29,7 +29,6 @@ const _TraceGraphColumn = (props: TraceGraphColumnProps) => {
|
||||
sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (new Date(Math.round(value/1000))).toUTCString()
|
||||
|
||||
// render: (value: number) => (new Date(Math.round(value/1000))).toLocaleDateString()+' '+(new Date(Math.round(value/1000))).toLocaleTimeString()
|
||||
},
|
||||
{
|
||||
title: 'Duration (in ms)',
|
||||
@ -49,12 +48,6 @@ const _TraceGraphColumn = (props: TraceGraphColumnProps) => {
|
||||
|
||||
let dataSource :TableDataSourceItem[] = [];
|
||||
|
||||
// PNOTE - Define new array
|
||||
// if (props.traces.data.length > 0)
|
||||
// {
|
||||
// props.traces.data[0].spans.map((item: spanItem, index ) => dataSource.push({startTime: item.startTime, operationName: item.operationName , duration: item.duration, key:index.toString()}) );
|
||||
// }
|
||||
|
||||
if (props.traces[0].events.length > 0) {
|
||||
|
||||
props.traces[0].events.map((item: (number|string|string[]|pushDStree[])[], index ) => {
|
||||
@ -66,7 +59,6 @@ const _TraceGraphColumn = (props: TraceGraphColumnProps) => {
|
||||
return (
|
||||
|
||||
<div>
|
||||
{/* <div>Tracing Graph Column Page</div> */}
|
||||
<Table dataSource={dataSource} columns={columns} size="middle"/>;
|
||||
</div>
|
||||
);
|
||||
@ -74,10 +66,8 @@ const _TraceGraphColumn = (props: TraceGraphColumnProps) => {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState): { traces: traceResponseNew } => {
|
||||
// console.log(state);
|
||||
return { traces : state.traces };
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
|
||||
export const TraceGraphColumn = connect(mapStateToProps)(_TraceGraphColumn);
|
@ -51,7 +51,6 @@ const _TraceList = (props: TraceListProps) => {
|
||||
|
||||
// new Date() assumes input in milliseconds. Start Time stamp returned by druid api for span list is in ms
|
||||
|
||||
// render: (value: number) => (new Date(Math.round(value/1000))).toLocaleDateString()+' '+(new Date(Math.round(value/1000))).toLocaleTimeString()
|
||||
},
|
||||
{
|
||||
title: 'Duration (in ms)',
|
||||
@ -83,9 +82,7 @@ const _TraceList = (props: TraceListProps) => {
|
||||
if (typeof props.traces[0]!== 'undefined' && props.traces[0].events.length > 0) {
|
||||
//PNOTE - Template literal should be wrapped in curly braces for it to be evaluated
|
||||
|
||||
// return props.traces.data[0].spans.map((item: spanItem) => <div key={item.spanID}>Span ID is {item.spanID} --- Trace id is <NavLink to={`traces/${item.traceID}`}>{item.traceID}</NavLink></div>)
|
||||
//dataSource.push({spanid:{item.spanID}},traceid:{item.traceID}}
|
||||
//Populating dataSourceArray
|
||||
|
||||
props.traces[0].events.map((item: (number|string|string[]|pushDStree[])[], index ) => {
|
||||
if (typeof item[0] === 'number' && typeof item[4] === 'string' && typeof item[6] === 'string' && typeof item[1] === 'string' && typeof item[2] === 'string' )
|
||||
dataSource.push({startTime: item[0], operationName: item[4] , duration:parseInt(item[6]), spanid:item[1], traceid:item[2], key:index.toString()});
|
||||
@ -96,13 +93,11 @@ const _TraceList = (props: TraceListProps) => {
|
||||
return <Table dataSource={dataSource} columns={columns} size="middle"/>;
|
||||
} else
|
||||
{
|
||||
//return <Skeleton active />;
|
||||
return <div> No spans found for given filter!</div>
|
||||
}
|
||||
|
||||
};// end of renderTraces
|
||||
|
||||
// console.log(props.traces.data);
|
||||
return(
|
||||
<div>
|
||||
<div>List of traces with spanID</div>
|
||||
@ -110,23 +105,11 @@ const _TraceList = (props: TraceListProps) => {
|
||||
</div>
|
||||
)
|
||||
|
||||
// PNOTE - code snippet -
|
||||
// return props.traces.data.map((item) => {
|
||||
// return (
|
||||
// <div key={item.traceID}>
|
||||
// {item.traceID}
|
||||
// </div>
|
||||
// );
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState): { traces: traceResponseNew } => {
|
||||
// console.log(state);
|
||||
return { traces : state.traces };
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
export const TraceList = connect(mapStateToProps, {
|
||||
fetchTraces: fetchTraces,
|
||||
|
@ -62,7 +62,6 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
{/* <div>Usage Explorer </div> */}
|
||||
{/* PNOTE - TODO - Keep it in reponsive row column tab */}
|
||||
<Card style={{ width: "50%" , margin:20 }} bodyStyle={{padding:20 }}>
|
||||
<Bar data={data} options={options} />
|
||||
@ -73,11 +72,8 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState): { usageData: usageDataItem[], globalTime: GlobalTime } => {
|
||||
// console.log(state);
|
||||
return { usageData : state.usageDate, globalTime: state.globalTime };
|
||||
};
|
||||
// the name mapStateToProps is only a convention
|
||||
// take state and map it to props which are accessible inside this component
|
||||
|
||||
export const UsageExplorer = connect(mapStateToProps, {
|
||||
getUsageData: getUsageData,
|
||||
|
@ -13,7 +13,7 @@ import { reducers } from './reducers';
|
||||
const store = createStore(reducers, applyMiddleware(thunk))
|
||||
|
||||
const themes = {
|
||||
dark: `${process.env.PUBLIC_URL}/dark-theme.css`, // How is process.env.PUBLIC_URL defined? - even when we are not using gitlab ci
|
||||
dark: `${process.env.PUBLIC_URL}/dark-theme.css`,
|
||||
light: `${process.env.PUBLIC_URL}/light-theme.css`,
|
||||
};
|
||||
|
||||
|
@ -32,4 +32,3 @@ export const reducers = combineReducers<StoreState>({
|
||||
filteredTraceMetrics:filteredTraceMetricsReducer,
|
||||
});
|
||||
|
||||
//input state should ideally be in component state rather than redux application state
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { ActionTypes, TraceFilters, updateInputTagAction, updateTraceFiltersAction } from '../actions';
|
||||
|
||||
// does each reducer process individual states? Yes. Slice of the state
|
||||
export const traceFiltersReducer = (state:TraceFilters = {'service':'', 'tags':[],'operation':'','latency':{'min':'','max':''}}, action: updateTraceFiltersAction) => {
|
||||
|
||||
switch (action.type){
|
||||
|
@ -2,8 +2,6 @@ import { ActionTypes, Action, traceResponseNew, spanList, spansWSameTraceIDRespo
|
||||
|
||||
// PNOTE - Initializing is a must for state variable otherwise it gives an error in reducer
|
||||
var spanlistinstance :spanList ={ events: [], segmentID: '', columns: []} ;
|
||||
// let traceResponseNew_instance : traceResponseNew;
|
||||
// traceResponseNew_instance = [spanlistinstance];
|
||||
export const tracesReducer = (state: traceResponseNew = {"0": spanlistinstance} , action: Action) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.fetchTraces:
|
||||
|
@ -12,15 +12,12 @@ export const spanToTreeUtil = (spanlist :span[]) :pushDStree => {
|
||||
// let spans :spanItem[]= trace.spans;
|
||||
|
||||
if(spanlist){
|
||||
// console.log('spans',spans.length)
|
||||
//
|
||||
// console.log(processes)
|
||||
|
||||
// Create a dict with spanIDs as keys
|
||||
// PNOTE
|
||||
// Can we now assign different strings as id - Yes
|
||||
// https://stackoverflow.com/questions/15877362/declare-and-initialize-a-dictionary-in-typescript
|
||||
|
||||
// SPAN TREE processing is
|
||||
|
||||
let mapped_array : {[id: string] : span;} = {};
|
||||
|
||||
@ -28,7 +25,6 @@ export const spanToTreeUtil = (spanlist :span[]) :pushDStree => {
|
||||
mapped_array[spanlist[i][1]] = spanlist[i];
|
||||
mapped_array[spanlist[i][1]][10] = [];
|
||||
}
|
||||
// console.log('mapped_array',mapped_array)
|
||||
|
||||
for(let id in mapped_array){
|
||||
let child_span = mapped_array[id];
|
||||
@ -70,8 +66,6 @@ export const spanToTreeUtil = (spanlist :span[]) :pushDStree => {
|
||||
let references :RefItem[] = [];
|
||||
|
||||
refArray.forEach(element => {
|
||||
// element = element.replaceAll("=", ":")
|
||||
// let refObj = JSON.parse(element)
|
||||
element = element.replaceAll("{", "").replaceAll("}", "").replaceAll(" ", "")
|
||||
let arr = element.split(",")
|
||||
let refItem = {"traceID": "", "spanID": "", "refType": ""};
|
||||
|
Loading…
x
Reference in New Issue
Block a user