2021-10-20 09:24:55 +05:30
import { ActiveElement , Chart , ChartData , ChartEvent } from 'chart.js' ;
import Graph from 'components/Graph' ;
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query' ;
import ROUTES from 'constants/routes' ;
import FullView from 'container/GridGraphLayout/Graph/FullView' ;
2021-11-17 16:32:43 +05:30
import convertToNanoSecondsToSecond from 'lib/convertToNanoSecondsToSecond' ;
2021-10-20 09:24:55 +05:30
import { colors } from 'lib/getRandomColor' ;
import history from 'lib/history' ;
import React , { useRef } from 'react' ;
2021-11-16 21:13:20 +05:30
import { useSelector } from 'react-redux' ;
2021-10-20 09:24:55 +05:30
import { useParams } from 'react-router-dom' ;
import { AppState } from 'store/reducers' ;
import { Widgets } from 'types/api/dashboard/getAll' ;
import MetricReducer from 'types/reducer/metrics' ;
import { Card , Col , GraphContainer , GraphTitle , Row } from '../styles' ;
import TopEndpointsTable from '../TopEndpointsTable' ;
import { Button } from './styles' ;
2021-11-16 21:13:20 +05:30
const Application = ( { getWidget } : DashboardProps ) : JSX . Element = > {
2021-10-20 09:24:55 +05:30
const { servicename } = useParams < { servicename? : string } > ( ) ;
const selectedTimeStamp = useRef ( 0 ) ;
const { topEndPoints , serviceOverview } = useSelector < AppState , MetricReducer > (
( state ) = > state . metrics ,
) ;
const onTracePopupClick = ( timestamp : number ) : void = > {
const currentTime = timestamp ;
const tPlusOne = timestamp + 1 * 60 * 1000 ;
const urlParams = new URLSearchParams ( ) ;
urlParams . set ( METRICS_PAGE_QUERY_PARAM . startTime , currentTime . toString ( ) ) ;
urlParams . set ( METRICS_PAGE_QUERY_PARAM . endTime , tPlusOne . toString ( ) ) ;
if ( servicename ) {
urlParams . set ( METRICS_PAGE_QUERY_PARAM . service , servicename ) ;
}
2021-11-16 21:13:20 +05:30
history . push ( ` ${ ROUTES . TRACE } ? ${ urlParams . toString ( ) } ` ) ;
2021-10-20 09:24:55 +05:30
} ;
const onClickhandler = async (
event : ChartEvent ,
elements : ActiveElement [ ] ,
chart : Chart ,
data : ChartData ,
from : string ,
) : Promise < void > = > {
if ( event . native ) {
const points = chart . getElementsAtEventForMode (
event . native ,
'nearest' ,
{ intersect : true } ,
true ,
) ;
const id = ` ${ from } _button ` ;
const buttonElement = document . getElementById ( id ) ;
if ( points . length !== 0 ) {
const firstPoint = points [ 0 ] ;
if ( data . labels ) {
const time = data ? . labels [ firstPoint . index ] as Date ;
if ( buttonElement ) {
buttonElement . style . display = 'block' ;
buttonElement . style . left = ` ${ firstPoint . element . x } px ` ;
buttonElement . style . top = ` ${ firstPoint . element . y } px ` ;
2021-11-16 21:13:20 +05:30
selectedTimeStamp . current = time . getTime ( ) ;
2021-10-20 09:24:55 +05:30
}
}
} else {
if ( buttonElement && buttonElement . style . display === 'block' ) {
buttonElement . style . display = 'none' ;
}
}
}
} ;
const onErrorTrackHandler = ( timestamp : number ) : void = > {
const currentTime = timestamp ;
const tPlusOne = timestamp + 1 * 60 * 1000 ;
const urlParams = new URLSearchParams ( ) ;
urlParams . set ( METRICS_PAGE_QUERY_PARAM . startTime , currentTime . toString ( ) ) ;
urlParams . set ( METRICS_PAGE_QUERY_PARAM . endTime , tPlusOne . toString ( ) ) ;
if ( servicename ) {
urlParams . set ( METRICS_PAGE_QUERY_PARAM . service , servicename ) ;
}
urlParams . set ( METRICS_PAGE_QUERY_PARAM . error , 'true' ) ;
2021-11-16 21:13:20 +05:30
history . push ( ` ${ ROUTES . TRACE } ? ${ urlParams . toString ( ) } ` ) ;
2021-10-20 09:24:55 +05:30
} ;
return (
< >
< Row gutter = { 24 } >
< Col span = { 12 } >
< Button
type = "default"
size = "small"
id = "Application_button"
onClick = { ( ) : void = > {
onTracePopupClick ( selectedTimeStamp . current ) ;
} }
>
View Traces
< / Button >
< Card >
< GraphTitle > Application latency in ms < / GraphTitle >
< GraphContainer >
< Graph
onClickHandler = { ( ChartEvent , activeElements , chart , data ) : void = > {
onClickhandler ( ChartEvent , activeElements , chart , data , 'Application' ) ;
} }
type = "line"
data = { {
datasets : [
{
2021-11-17 16:32:43 +05:30
data : serviceOverview.map ( ( e ) = >
parseFloat ( convertToNanoSecondsToSecond ( e . p99 ) ) ,
) ,
2021-10-20 09:24:55 +05:30
borderColor : colors [ 0 ] ,
label : 'p99 Latency' ,
showLine : true ,
borderWidth : 1.5 ,
spanGaps : true ,
pointRadius : 1.5 ,
} ,
{
2021-11-17 16:32:43 +05:30
data : serviceOverview.map ( ( e ) = >
parseFloat ( convertToNanoSecondsToSecond ( e . p95 ) ) ,
) ,
2021-10-20 09:24:55 +05:30
borderColor : colors [ 1 ] ,
label : 'p95 Latency' ,
showLine : true ,
borderWidth : 1.5 ,
spanGaps : true ,
pointRadius : 1.5 ,
} ,
{
2021-11-17 16:32:43 +05:30
data : serviceOverview.map ( ( e ) = >
parseFloat ( convertToNanoSecondsToSecond ( e . p50 ) ) ,
) ,
2021-10-20 09:24:55 +05:30
borderColor : colors [ 2 ] ,
label : 'p50 Latency' ,
showLine : true ,
borderWidth : 1.5 ,
spanGaps : true ,
pointRadius : 1.5 ,
} ,
] ,
labels : serviceOverview.map ( ( e ) = > {
2021-11-17 16:32:43 +05:30
return new Date (
parseFloat ( convertToNanoSecondsToSecond ( e . timestamp ) ) ,
) ;
2021-10-20 09:24:55 +05:30
} ) ,
} }
/ >
< / GraphContainer >
< / Card >
< / Col >
< Col span = { 12 } >
< Button
type = "default"
size = "small"
id = "Request_button"
onClick = { ( ) : void = > {
onTracePopupClick ( selectedTimeStamp . current ) ;
} }
>
View Traces
< / Button >
< Card >
< GraphTitle > Request per sec < / GraphTitle >
< GraphContainer >
< FullView
noDataGraph
fullViewOptions = { false }
onClickHandler = { ( event , element , chart , data ) : void = > {
onClickhandler ( event , element , chart , data , 'Request' ) ;
} }
widget = { getWidget ( [
{
query : ` sum(rate(signoz_latency_count{service_name=" ${ servicename } ", span_kind="SPAN_KIND_SERVER"}[2m])) ` ,
legend : 'Request per second' ,
} ,
] ) }
/ >
< / GraphContainer >
< / Card >
< / Col >
< / Row >
< Row gutter = { 24 } >
< Col span = { 12 } >
< Button
type = "default"
size = "small"
id = "Error_button"
onClick = { ( ) : void = > {
onErrorTrackHandler ( selectedTimeStamp . current ) ;
} }
>
View Traces
< / Button >
< Card >
< Card >
< GraphTitle > Error Percentage ( % ) < / GraphTitle >
< GraphContainer >
< FullView
noDataGraph
fullViewOptions = { false }
onClickHandler = { ( ChartEvent , activeElements , chart , data ) : void = > {
onClickhandler ( ChartEvent , activeElements , chart , data , 'Error' ) ;
} }
widget = { getWidget ( [
{
query : ` sum(rate(signoz_calls_total{service_name=" ${ servicename } ", span_kind="SPAN_KIND_SERVER", status_code="STATUS_CODE_ERROR"}[1m]) OR rate(signoz_calls_total{service_name=" ${ servicename } ", span_kind="SPAN_KIND_SERVER", http_status_code=~"5.."}[1m]) OR vector(0))*100/sum(rate(signoz_calls_total{service_name=" ${ servicename } ", span_kind="SPAN_KIND_SERVER"}[1m])) ` ,
legend : 'Error Percentage (%)' ,
} ,
] ) }
/ >
< / GraphContainer >
< / Card >
< / Card >
< / Col >
< Col span = { 12 } >
< Card >
< TopEndpointsTable data = { topEndPoints } / >
< / Card >
< / Col >
< / Row >
< / >
) ;
} ;
2021-11-16 21:13:20 +05:30
interface DashboardProps {
2021-10-20 09:24:55 +05:30
getWidget : ( query : Widgets [ 'query' ] ) = > Widgets ;
}
2021-11-16 21:13:20 +05:30
export default Application ;