New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added top consumer to ceph storage plugin #2040
Merged
openshift-merge-robot
merged 1 commit into
openshift:master
from
cloudbehl:top-consumer
Jul 21, 2019
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
119 changes: 119 additions & 0 deletions
119
...omponents/dashboard-page/storage-dashboard/top-consumers-card/top-consumers-card-body.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import * as React from 'react'; | ||
import * as _ from 'lodash'; | ||
import { ChartLineIcon } from '@patternfly/react-icons'; | ||
import { | ||
Chart, | ||
ChartAxis, | ||
ChartGroup, | ||
ChartLegend, | ||
ChartLine, | ||
ChartThemeColor, | ||
ChartTooltip, | ||
ChartVoronoiContainer, | ||
} from '@patternfly/react-charts'; | ||
import { DataPoint, PrometheusResponse } from '@console/internal/components/graphs'; | ||
import { EmptyState, EmptyStateIcon, EmptyStateVariant, Title } from '@patternfly/react-core'; | ||
import { humanizeBinaryBytesWithoutB, LoadingInline } from '@console/internal/components/utils'; | ||
import { twentyFourHourTime } from '@console/internal/components/utils/datetime'; | ||
import { getGraphVectorStats, getMetricType } from './utils'; | ||
|
||
const chartPropsValue = { | ||
chartHeight: 175, | ||
}; | ||
|
||
const chartLegendPropsValue = { | ||
x: 10, | ||
y: 5, | ||
symbolSpacer: 7, | ||
height: 30, | ||
gutter: 10, | ||
}; | ||
|
||
const getYTickValues = (value: number): number[] => [ | ||
Math.floor(value / 4), | ||
Math.floor(value / 2), | ||
Math.floor((3 * value) / 4), | ||
Math.floor(value), | ||
Math.floor((5 * value) / 4), | ||
Math.floor((6 * value) / 4), | ||
]; | ||
|
||
export const TopConsumersBody: React.FC<TopConsumerBodyProps> = React.memo( | ||
({ topConsumerStats, metricType, sortByOption }) => { | ||
if (!topConsumerStats) { | ||
return <LoadingInline />; | ||
} | ||
const topConsumerStatsResult = _.get(topConsumerStats, 'data.result', []); | ||
if (topConsumerStatsResult.length) { | ||
const legends = topConsumerStatsResult.map((resource) => ({ | ||
name: getMetricType(resource, metricType), | ||
})); | ||
const resourceValues = _.flatMap(topConsumerStatsResult, (resource) => resource.values); | ||
const maxCapacity = _.maxBy(resourceValues, (value) => Number(value[1])); | ||
const maxCapacityConverted = humanizeBinaryBytesWithoutB(Number(maxCapacity[1])); | ||
const chartData = getGraphVectorStats( | ||
topConsumerStats, | ||
metricType, | ||
maxCapacityConverted.unit, | ||
); | ||
|
||
const chartLineList = chartData.map((data, i) => ( | ||
<ChartLine key={i} data={data as DataPoint[]} /> // eslint-disable-line react/no-array-index-key | ||
)); | ||
return ( | ||
<> | ||
<span className="text-secondary">{`${sortByOption}(${maxCapacityConverted.unit})`}</span> | ||
<Chart | ||
domain={{ y: [0, 1.5 * maxCapacityConverted.value] }} | ||
height={chartPropsValue.chartHeight} | ||
padding={{ top: 20, bottom: 20, left: 30, right: 20 }} | ||
containerComponent={ | ||
<ChartVoronoiContainer | ||
labels={(datum) => `${datum.y} ${maxCapacityConverted.unit}`} | ||
labelComponent={<ChartTooltip style={{ fontSize: 8, padding: 5 }} />} | ||
/> | ||
} | ||
themeColor={ChartThemeColor.multi} | ||
scale={{ x: 'time' }} | ||
> | ||
<ChartAxis | ||
tickFormat={(x) => twentyFourHourTime(x)} | ||
style={{ tickLabels: { fontSize: 8, padding: 5 } }} | ||
/> | ||
<ChartAxis | ||
dependentAxis | ||
tickValues={getYTickValues(maxCapacityConverted.value)} | ||
style={{ tickLabels: { fontSize: 8, padding: 5 }, grid: { stroke: '#4d525840' } }} | ||
/> | ||
<ChartGroup>{chartLineList}</ChartGroup> | ||
</Chart> | ||
<ChartLegend | ||
data={legends} | ||
themeColor={ChartThemeColor.multi} | ||
x={chartLegendPropsValue.x} | ||
y={chartLegendPropsValue.y} | ||
symbolSpacer={chartLegendPropsValue.symbolSpacer} | ||
height={chartLegendPropsValue.height} | ||
gutter={chartLegendPropsValue.gutter} | ||
orientation="horizontal" | ||
style={{ | ||
labels: { fontSize: 8 }, | ||
}} | ||
/> | ||
</> | ||
); | ||
} | ||
return ( | ||
<EmptyState className="graph-empty-state" variant={EmptyStateVariant.full}> | ||
<EmptyStateIcon size="sm" icon={ChartLineIcon} /> | ||
<Title size="sm">No Prometheus datapoints found.</Title> | ||
</EmptyState> | ||
); | ||
}, | ||
); | ||
|
||
type TopConsumerBodyProps = { | ||
topConsumerStats: PrometheusResponse[]; | ||
metricType?: string; | ||
sortByOption?: string; | ||
}; |
15 changes: 15 additions & 0 deletions
15
...rc/components/dashboard-page/storage-dashboard/top-consumers-card/top-consumers-card.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
@import '~@patternfly/patternfly/sass-utilities/colors'; | ||
|
||
.ceph-top-consumer-card__dropdown { | ||
border-bottom: 1px solid $pf-color-black-300; | ||
display: flex; | ||
padding-bottom: 0.6em; | ||
} | ||
|
||
.ceph-top-consumer-card__dropdown--left { | ||
padding-left: 0.3em; | ||
} | ||
|
||
.ceph-top-consumer-card__dropdown--right { | ||
padding-right: 0.3em; | ||
} |
97 changes: 97 additions & 0 deletions
97
...src/components/dashboard-page/storage-dashboard/top-consumers-card/top-consumers-card.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import * as React from 'react'; | ||
import * as _ from 'lodash'; | ||
import { DashboardCard } from '@console/internal/components/dashboard/dashboard-card/card'; | ||
import { DashboardCardBody } from '@console/internal/components/dashboard/dashboard-card/card-body'; | ||
import { DashboardCardHeader } from '@console/internal/components/dashboard/dashboard-card/card-header'; | ||
import { DashboardCardTitle } from '@console/internal/components/dashboard/dashboard-card/card-title'; | ||
import { Dropdown } from '@console/internal/components/utils/dropdown'; | ||
import { | ||
DashboardItemProps, | ||
withDashboardResources, | ||
} from '@console/internal/components/dashboards-page/with-dashboard-resources'; | ||
import { BY_REQUESTED, BY_USED, PODS, PROJECTS, STORAGE_CLASSES, VMS } from '../../../../constants'; | ||
import { TOP_CONSUMER_QUERIES, StorageDashboardQuery } from '../../../../constants/queries'; | ||
import { TopConsumersBody } from './top-consumers-card-body'; | ||
import './top-consumers-card.scss'; | ||
|
||
const TopConsumerResourceValue = { | ||
[PROJECTS]: 'PROJECTS_', | ||
[STORAGE_CLASSES]: 'STORAGE_CLASSES_', | ||
[PODS]: 'PODS_', | ||
[VMS]: 'VMS_', | ||
}; | ||
const TopConsumerSortByValue = { | ||
[BY_USED]: 'BY_USED', | ||
[BY_REQUESTED]: 'BY_REQUESTED', | ||
}; | ||
|
||
const TopConsumerResourceValueMapping = { | ||
Projects: 'namespace', | ||
'Storage Classes': 'storageclass', | ||
Pods: 'pod', | ||
}; | ||
|
||
const metricTypes = _.keys(TopConsumerResourceValue); | ||
const sortByTypes = _.keys(TopConsumerSortByValue); | ||
|
||
const metricTypesOptions = _.zipObject(metricTypes, metricTypes); | ||
const sortByOptions = _.zipObject(sortByTypes, sortByTypes); | ||
|
||
const TopConsumerCard: React.FC<DashboardItemProps> = ({ | ||
watchPrometheus, | ||
stopWatchPrometheusQuery, | ||
prometheusResults, | ||
}) => { | ||
const [metricType, setMetricType] = React.useState(metricTypes[0]); | ||
const [sortBy, setSortBy] = React.useState(sortByTypes[0]); | ||
React.useEffect(() => { | ||
const query = | ||
TOP_CONSUMER_QUERIES[ | ||
StorageDashboardQuery[TopConsumerResourceValue[metricType] + TopConsumerSortByValue[sortBy]] | ||
]; | ||
watchPrometheus(query); | ||
return () => stopWatchPrometheusQuery(query); | ||
}, [watchPrometheus, stopWatchPrometheusQuery, metricType, sortBy]); | ||
|
||
const topConsumerstats = prometheusResults.getIn([ | ||
TOP_CONSUMER_QUERIES[ | ||
StorageDashboardQuery[TopConsumerResourceValue[metricType] + TopConsumerSortByValue[sortBy]] | ||
], | ||
'result', | ||
]); | ||
|
||
return ( | ||
<DashboardCard> | ||
<DashboardCardHeader> | ||
<DashboardCardTitle>Top Consumers</DashboardCardTitle> | ||
<div className="ceph-top-consumer-card__dropdown"> | ||
<Dropdown | ||
className="btn-group ceph-top-consumer-card__dropdown--right" | ||
id="metric-type" | ||
items={metricTypesOptions} | ||
onChange={setMetricType} | ||
selectedKey={metricType} | ||
title={metricType} | ||
/> | ||
<Dropdown | ||
className="btn-group ceph-top-consumer-card__dropdown--left" | ||
id="sort-by" | ||
items={sortByOptions} | ||
onChange={setSortBy} | ||
selectedKey={sortBy} | ||
title={sortBy} | ||
/> | ||
</div> | ||
</DashboardCardHeader> | ||
<DashboardCardBody> | ||
<TopConsumersBody | ||
topConsumerStats={topConsumerstats} | ||
metricType={TopConsumerResourceValueMapping[metricType]} | ||
sortByOption={sortBy} | ||
/> | ||
</DashboardCardBody> | ||
</DashboardCard> | ||
); | ||
}; | ||
|
||
export default withDashboardResources(TopConsumerCard); |
18 changes: 18 additions & 0 deletions
18
...torage-plugin/src/components/dashboard-page/storage-dashboard/top-consumers-card/utils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import * as _ from 'lodash'; | ||
import { humanizeBinaryBytesWithoutB } from '@console/internal/components/utils'; | ||
import { PrometheusResponse, DataPoint } from '@console/internal/components/graphs'; | ||
|
||
export const getMetricType = (resource, metricType) => _.get(resource, ['metric', metricType], ''); | ||
|
||
export const getGraphVectorStats: GetStats = (response, metricType, unit) => { | ||
const result = _.get(response, 'data.result', []); | ||
return result.map((r) => { | ||
return r.values.map((arr) => ({ | ||
name: getMetricType(r, metricType), | ||
x: new Date(arr[0] * 1000), | ||
y: Number(humanizeBinaryBytesWithoutB(arr[1], unit).value), | ||
})); | ||
}); | ||
}; | ||
|
||
type GetStats = (response: PrometheusResponse[], metric?: string, unit?: string) => DataPoint[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
height of the card header is inconsistent with others. Take a look at these styles https://github.com/openshift/console/pull/1722/files#diff-163991d4c119db922a729100ce2bea7fR91
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, those dropdowns are actually not in header as yours are.
@andybraren @matthewcarleton any help on how to include these dropdowns into PF4 Card Header and keep header height consistent ?
See the difference between Capacity and Top Consumers header
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @rawagner I believe you can use the actions area for the card header provided. That should fix the spacing isssues. If not we may need to investigate further if there is unnecessary spacing added to other elements in there.