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
Add storage efficiency card on persistent dashboard. #6104
Add storage efficiency card on persistent dashboard. #6104
Conversation
@@ -87,6 +89,13 @@ export const CAPACITY_BREAKDOWN_QUERIES = { | |||
'max(ceph_pool_max_avail * on (pool_id) group_left(name)ceph_pool_metadata{name=~"(.*file.*)|(.*block.*)"})', | |||
}; | |||
|
|||
export const POOL_STORAGE_EFFICIENCY_QUERIES = { |
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.
FYI @openshift/openshift-team-monitoring
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.
nice, thank you!
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.
that is an incarnation of centralizing queries, correct?
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.
Ah no. The centralizing PR is #6128
|
||
import './storage-efficiency-card.scss'; | ||
|
||
const getGaugeValue = (data) => _.get(data, 'data.result[0].value[1]'); |
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.
types
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.
Can you move this to utils , so that we can reuse this in other cards ?
We wont miss the item this way during refactoring phase.
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.
ack
const savingsValue = Number(saved); | ||
if (saved) { | ||
const savedBytes = humanizeBinaryBytes(savingsValue).string; | ||
stats = savingsValue <= 0 ? 'No Savings' : savedBytes; |
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.
Will you ever get a negative value here ?
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.
Good catch, no, it can be 0 or more only
|
||
import './storage-efficiency-card.scss'; | ||
|
||
const getGaugeValue = (data) => _.get(data, 'data.result[0].value[1]'); |
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.
Can you move this to utils , so that we can reuse this in other cards ?
We wont miss the item this way during refactoring phase.
<div className="co-inventory-card__item"> | ||
<div className="ceph-storage-efficiency-card__row-title">{title}</div> | ||
<div className="ceph-storage-efficiency-card__row-status-item"> |
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.
Since these are rows for the ItemBody
and to make BEM naming align with the actual purpose
<div className="co-inventory-card__item"> | |
<div className="ceph-storage-efficiency-card__row-title">{title}</div> | |
<div className="ceph-storage-efficiency-card__row-status-item"> | |
<div className="co-inventory-card__row-item"> | |
<div className="ceph-storage-efficiency-card__row-item-title">{title}</div> | |
<div className="ceph-storage-efficiency-card__row-item-status"> |
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.
Also ItemBody
can be RowItem
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.
We have to keep co-inventory-card__row
class as it is becasue it is used across dashboard https://github.com/openshift/console/blob/master/frontend/packages/console-shared/src/components/dashboard/inventory-card/inventory-card.scss#L4.
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.
Sure, I missed in flow :D
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.
I dont find this naming right though.
@a2batic can you add screenshots? |
@a2batic We too want ot make it generic just like breakdown card. Instead of maintaining same copies for different plugins. |
67b74ce
to
ae36239
Compare
const compressionRatioProps = { | ||
ratio, | ||
isLoading: !poolCapacityRatioResult, | ||
error: !!poolCapacityRatioResultError, | ||
}; |
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.
const compressionRatioProps = { | |
ratio, | |
isLoading: !poolCapacityRatioResult, | |
error: !!poolCapacityRatioResultError, | |
}; | |
const compressionRatioProps = { | |
ratio, | |
isLoading: !poolCapacityRatioResult, | |
error: !!poolCapacityRatioResultError, | |
infotext: infotext | |
handler: getCompressionRatio, | |
}; |
const ItemBody: React.FC<ItemBodyProps> = React.memo( | ||
({ title, stats, infoText, isLoading, error }) => { | ||
let status: React.ReactElement; | ||
if (isLoading) { | ||
status = <div className="skeleton-text ceph-storage-efficiency-card__item-body--loading" />; | ||
} else if (error || !stats) { | ||
status = <span className="co-dashboard-text--small text-muted">Not available</span>; | ||
} else { | ||
status = <span className="ceph-storage-efficiency-card__item-text">{stats}</span>; | ||
} | ||
return ( | ||
<div className="co-inventory-card__item"> | ||
<div className="ceph-storage-efficiency-card__item-title">{title}</div> | ||
<div className="ceph-storage-efficiency-card__item-status"> | ||
{status} | ||
<FieldLevelHelp>{infoText}</FieldLevelHelp> | ||
</div> | ||
</div> | ||
); | ||
}, | ||
); |
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.
We can make this component more generic, renaming to StorageEfficiencyItem
and avoid using SavedItem
, CompressionItem
.
You can pass one handler
function to it to get the stats:
({ title, data, infoText, isLoading, error, handler }) => {
let status: React.ReactElement;
const stats = handler(data);
The handler will be your extracted logic for :
if (ratio) {
const capacityRatio = Number(ratio);
stats = capacityRatio === 0 ? '1:1' : `${Math.round(capacityRatio)}:1`;
}
if (ratio) {
const capacityRatio = Number(ratio);
stats = capacityRatio === 0 ? '1:1' : `${Math.round(capacityRatio)}:1`;
}
which you can pass as prop;
You can call directly StorageEfficiencyItem
as:
<DashboardCardBody className="co-dashboard-card__body--no-padding">
<StorageEfficiencyItem {...compressionRatioProps} />
<StorageEfficiencyItem {...savingsProps} />
</DashboardCardBody>
ae36239
to
3b953b7
Compare
export const EfficiencyItemBody: React.FC<EfficiencyItemBodyProps> = React.memo( | ||
({ title, stats, infoText, isLoading, error, handler }) => { | ||
let status: React.ReactElement; | ||
const metricStats = stats ? handler() : null; |
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.
As per the below suggestion:
const metricStats = stats ? handler() : null; |
const ratio = getGaugeValue(poolCapacityRatioResult); | ||
const saved = getGaugeValue(poolSavedResult); | ||
|
||
const compressionStats = () => { | ||
const capacityRatio = Number(ratio); | ||
return capacityRatio === 0 ? '1:1' : `${Math.round(capacityRatio)}:1`; | ||
}; | ||
|
||
const savingStats = () => { | ||
const savingsValue = Number(saved); | ||
const savedBytes = humanizeBinaryBytes(savingsValue).string; | ||
return savingsValue === 0 ? 'No Savings' : savedBytes; | ||
}; |
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.
When getGaugeValue(poolCapacityRatioResult)
returns undefined
.
Then you will have capacityRatio
and savingsValue
as 0
and it will render a text 1:1
and No savings
.
You dont want to show that , instead you want to have Not available
.
You can have :
const compressionStats = () => {
if (capacityRatio) {
const capacityRatio = Number(ratio);
return capacityRatio === 0 ? '1:1' : `${Math.round(capacityRatio)}:1`;
};
return capacityRatio;
};
const savingStats = () => {
if(savingsValue) {
const savingsValue = Number(saved);
const savedBytes = humanizeBinaryBytes(savingsValue).string;
return savingsValue === 0 ? 'No Savings' : savedBytes;
}
return savingsValue;
};
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.
@afreen23 if getGaugeValue(poolCapacityRatioResult)
returns undefined
, capacityRatio
and ratio
will be NaN
, becasue Number(undefined)
gives NaN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number.
Therefore, we dont need to put if, because I am checking for value to be 0 or not. wdyt?
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.
@a2batic you are missing my point here. What I pointed above is if capacityRatio
and savingsValue
wont be 0
and they will default to the text. Instead I would at least prefer to set for such cases Not available
.
An improvement over stats ? handler() : null;
, we can avoid explicitly setting null
and let the handler itself respond.
I am alright if you want to keep it that way.
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.
@afreen23, thanks for clarifying, I understand your point, only reasons to put it in element, So we dont have to check for every item in their respective functions.
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.
What about doing this way #6104 (review) ?
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.
ack
/retest |
/lgtm |
/lgtm cancel |
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.
Lets do this way
const savingsProps = { | ||
stats: saved, | ||
isLoading: !poolSavedResult, | ||
error: !!poolSavedResultError, |
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.
error: !!poolSavedResultError, | |
error: !!poolSavedResultError || !saved |
const compressionRatioProps = { | ||
stats: ratio, | ||
isLoading: !poolCapacityRatioResult, | ||
error: !!poolCapacityRatioResultError, |
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.
error: !!poolCapacityRatioResultError, | |
error: !!poolCapacityRatioResultError || !ratio |
} else if (error || !metricStats) { | ||
status = <span className="co-dashboard-text--small text-muted">Not available</span>; | ||
} else { | ||
status = <span className="ceph-storage-efficiency-card__item-text">{metricStats}</span>; |
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.
status = <span className="ceph-storage-efficiency-card__item-text">{metricStats}</span>; | |
status = <span className="ceph-storage-efficiency-card__item-text">{getStats()}</span>; |
const metricStats = stats ? handler() : null; | ||
if (isLoading) { | ||
status = <div className="skeleton-text ceph-storage-efficiency-card__item-body--loading" />; | ||
} else if (error || !metricStats) { |
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.
} else if (error || !metricStats) { | |
} else if (error) { |
import { FieldLevelHelp } from '@console/internal/components/utils'; | ||
|
||
export const EfficiencyItemBody: React.FC<EfficiencyItemBodyProps> = React.memo( | ||
({ title, stats, infoText, isLoading, error, handler }) => { |
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.
({ title, stats, infoText, isLoading, error, handler }) => { | |
({ title, stats, infoText, isLoading, error, getStats }) => { |
Signed-off-by: Kanika Murarka <kmurarka@redhat.com>
3b953b7
to
153341d
Compare
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: a2batic, afreen23, gnehapk The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Thanks James Espy, Paul Cuzner , for the providing the metrics.
Signed-off-by: Kanika Murarka kmurarka@redhat.com