1- import * as _ from 'lodash-es' ;
2- import classNames from 'classnames' ;
3- import * as React from 'react' ;
41import {
52 PrometheusEndpoint ,
63 PrometheusLabels ,
@@ -22,28 +19,32 @@ import {
2219import {
2320 Alert ,
2421 Button ,
22+ Card ,
23+ CardBody ,
24+ CardHeader ,
2525 Checkbox ,
2626 Dropdown ,
2727 DropdownItem ,
2828 DropdownList ,
2929 EmptyState ,
3030 EmptyStateBody ,
3131 EmptyStateVariant ,
32- MenuToggle ,
33- MenuToggleElement ,
3432 InputGroup ,
35- TextInput ,
36- Title ,
3733 InputGroupItem ,
38- Card ,
39- CardHeader ,
40- Split ,
41- SplitItem ,
4234 Level ,
4335 LevelItem ,
44- CardBody ,
36+ MenuToggle ,
37+ MenuToggleElement ,
38+ Split ,
39+ SplitItem ,
40+ TextInput ,
41+ Title ,
42+ Tooltip ,
4543} from '@patternfly/react-core' ;
4644import { ChartLineIcon } from '@patternfly/react-icons' ;
45+ import classNames from 'classnames' ;
46+ import * as _ from 'lodash-es' ;
47+ import * as React from 'react' ;
4748import { useTranslation } from 'react-i18next' ;
4849import { useDispatch , useSelector } from 'react-redux' ;
4950
@@ -69,24 +70,24 @@ import { queryBrowserTheme } from './query-browser-theme';
6970import { PrometheusAPIError , TimeRange } from './types' ;
7071import { getTimeRanges } from './utils' ;
7172
72- import { getLegacyObserveState , getObserveState , usePerspective } from './hooks/usePerspective' ;
73- import { MonitoringState } from '../reducers/observe' ;
74- import { LoadingInline } from './console/console-shared/src/components/loading/LoadingInline' ;
73+ import { CustomDataSource } from '@openshift-console/dynamic-plugin-sdk/lib/extensions/dashboard-data-source' ;
7574import {
76- formatPrometheusDuration ,
77- parsePrometheusDuration ,
78- } from './console/console-shared/src/datetime/prometheus' ;
75+ chart_area_Opacity ,
76+ chart_axis_tick_Size ,
77+ t_chart_global_fill_color_200 ,
78+ } from '@patternfly/react-tokens' ;
79+ import { MonitoringState } from '../reducers/observe' ;
7980import withFallback from './console/console-shared/error/fallbacks/withFallback' ;
80- import { CustomDataSource } from '@openshift- console/dynamic-plugin-sdk/lib/extensions/dashboard-data-source ' ;
81+ import { LoadingInline } from './ console/console-shared/src/components/loading/LoadingInline ' ;
8182import {
8283 QueryBrowserTooltip ,
8384 valueFormatter ,
8485} from './console/console-shared/src/components/query-browser/QueryBrowserTooltip' ;
8586import {
86- chart_area_Opacity ,
87- chart_axis_tick_Size ,
88- t_chart_global_fill_color_200 ,
89- } from '@patternfly/react-tokens ' ;
87+ formatPrometheusDuration ,
88+ parsePrometheusDuration ,
89+ } from './console/console-shared/src/datetime/prometheus' ;
90+ import { getLegacyObserveState , getObserveState , usePerspective } from './hooks/usePerspective ' ;
9091import './query-browser.scss' ;
9192
9293const spans = [ '5m' , '15m' , '30m' , '1h' , '2h' , '6h' , '12h' , '1d' , '2d' , '1w' , '2w' ] ;
@@ -415,7 +416,9 @@ const formatSeriesValues = (
415416 samples : number ,
416417 span : number ,
417418 defaultEmptyValue : 0 | null ,
418- ) : GraphDataPoint [ ] => {
419+ createGaps : boolean ,
420+ ) : { points : GraphDataPoint [ ] ; hasDisconnectedValues : boolean } => {
421+ let hasDisconnectedValues = false ;
419422 const newValues = _ . map ( values , ( v ) => {
420423 const y = Number ( v [ 1 ] ) ;
421424 return {
@@ -424,19 +427,23 @@ const formatSeriesValues = (
424427 } ;
425428 } ) ;
426429
427- // The data may have missing values, so we fill those gaps with nulls so that the graph correctly
430+ // The data may have missing values, if disconnected is enabled,
431+ // we fill those gaps with nulls so that the graph correctly
428432 // shows the missing values as gaps in the line
429433 const start = Number ( _ . get ( newValues , '[0].x' ) ) ;
430434 const end = Number ( _ . get ( _ . last ( newValues ) , 'x' ) ) ;
431435 const step = span / samples ;
432436 _ . range ( start , end , step ) . forEach ( ( t , i ) => {
433437 const x = new Date ( t ) ;
434438 if ( _ . get ( newValues , [ i , 'x' ] ) > x ) {
435- newValues . splice ( i , 0 , { x, y : null } ) ;
439+ hasDisconnectedValues = true ;
440+ if ( createGaps ) {
441+ newValues . splice ( i , 0 , { x, y : null } ) ;
442+ }
436443 }
437444 } ) ;
438445
439- return newValues ;
446+ return { points : newValues , hasDisconnectedValues } ;
440447} ;
441448
442449// Try to limit the graph to this number of data points
@@ -581,6 +588,7 @@ const QueryBrowser_: React.FC<QueryBrowserProps> = ({
581588 queries,
582589 showLegend,
583590 showStackedControl = false ,
591+ showDisconnectedControl = true ,
584592 timespan,
585593 units,
586594 onDataChange,
@@ -626,6 +634,8 @@ const QueryBrowser_: React.FC<QueryBrowserProps> = ({
626634 const safeFetch = useSafeFetch ( ) ;
627635
628636 const [ isStacked , setIsStacked ] = React . useState ( isStack ) ;
637+ const [ showDisconnectedValues , setIsShowDisconnectedValues ] = React . useState ( false ) ;
638+ const [ isDisconnectedEnabled , setIsDisconnectedEnabled ] = React . useState ( true ) ;
629639
630640 const canStack = _ . sumBy ( graphData , 'length' ) <= maxStacks ;
631641
@@ -737,6 +747,8 @@ const QueryBrowser_: React.FC<QueryBrowserProps> = ({
737747 maxSamplesForSpan ,
738748 ) ;
739749
750+ let dataIsDisconnected = false ;
751+
740752 // Change `samples` if either
741753 // - It will change by a proportion greater than `samplesLeeway`
742754 // - It will change to the upper or lower limit of its allowed range
@@ -764,14 +776,26 @@ const QueryBrowser_: React.FC<QueryBrowserProps> = ({
764776 ) ;
765777 defaultEmptyValue = 0 ;
766778 }
767- return [ metric , formatSeriesValues ( values , samples , span , defaultEmptyValue ) ] ;
779+ const { points, hasDisconnectedValues } = formatSeriesValues (
780+ values ,
781+ samples ,
782+ span ,
783+ defaultEmptyValue ,
784+ showDisconnectedValues ,
785+ ) ;
786+
787+ dataIsDisconnected = hasDisconnectedValues ;
788+
789+ return [ metric , points ] ;
768790 }
769791 } ) ;
770792 } ,
771793 ) ;
772794 setGraphData ( newGraphData ) ;
773795 onDataChange ?.( newGraphData ) ;
774796
797+ setIsDisconnectedEnabled ( dataIsDisconnected ) ;
798+
775799 _ . each ( newResults , ( r , i ) =>
776800 dispatch ( queryBrowserPatchQuery ( i , { series : r ? _ . map ( r , 'metric' ) : undefined } ) ) ,
777801 ) ;
@@ -815,6 +839,7 @@ const QueryBrowser_: React.FC<QueryBrowserProps> = ({
815839 samples ,
816840 span ,
817841 lastRequestTime ,
842+ showDisconnectedValues ,
818843 ) ;
819844
820845 React . useLayoutEffect (
@@ -908,18 +933,52 @@ const QueryBrowser_: React.FC<QueryBrowserProps> = ({
908933 </ SplitItem >
909934 < SplitItem isFilled />
910935 < SplitItem >
911- { GraphLink && < GraphLink /> }
912- { canStack && showStackedControl && (
913- < Checkbox
914- id = "stacked"
915- isChecked = { isStacked }
916- data-checked-state = { isStacked }
917- label = { t ( 'Stacked' ) }
918- onChange = { ( _e , v ) =>
919- typeof _e === 'boolean' ? setIsStacked ( _e ) : setIsStacked ( v )
920- }
921- />
922- ) }
936+ < Split hasGutter >
937+ { GraphLink && (
938+ < SplitItem >
939+ < GraphLink />
940+ </ SplitItem >
941+ ) }
942+ { canStack && showStackedControl && (
943+ < SplitItem >
944+ < Checkbox
945+ id = "stacked"
946+ isChecked = { isStacked }
947+ data-checked-state = { isStacked }
948+ label = { t ( 'Stacked' ) }
949+ onChange = { ( _e , v ) =>
950+ typeof _e === 'boolean' ? setIsStacked ( _e ) : setIsStacked ( v )
951+ }
952+ />
953+ </ SplitItem >
954+ ) }
955+ { showDisconnectedControl && (
956+ < SplitItem >
957+ < Tooltip
958+ content = {
959+ < div >
960+ { isDisconnectedEnabled
961+ ? t ( 'Check to show gaps for missing data' )
962+ : t ( 'No gaps found in the data' ) }
963+ </ div >
964+ }
965+ >
966+ < Checkbox
967+ id = "disconnected"
968+ isChecked = { isDisconnectedEnabled && showDisconnectedValues }
969+ data-checked-state = { isDisconnectedEnabled && showDisconnectedValues }
970+ label = { t ( 'Disconnected' ) }
971+ onChange = { ( _e , v ) =>
972+ typeof _e === 'boolean'
973+ ? setIsShowDisconnectedValues ( _e )
974+ : setIsShowDisconnectedValues ( v )
975+ }
976+ isDisabled = { ! isDisconnectedEnabled }
977+ />
978+ </ Tooltip >
979+ </ SplitItem >
980+ ) }
981+ </ Split >
923982 </ SplitItem >
924983 </ Split >
925984 </ CardHeader >
@@ -1028,6 +1087,7 @@ export type QueryBrowserProps = {
10281087 queries : string [ ] ;
10291088 showLegend ?: boolean ;
10301089 showStackedControl ?: boolean ;
1090+ showDisconnectedControl ?: boolean ;
10311091 timespan ?: number ;
10321092 units ?: string ;
10331093 onDataChange ?: ( data : any ) => void ;
0 commit comments