Skip to content

Commit

Permalink
feat(alerts/ui): improvements for filters and details (#224)
Browse files Browse the repository at this point in the history
* feat(alerts/ui): filtered Pills can now be paused and deactivated

* feat(alerts/ui): reduced opacity of deactivated pills

* feat(alerts/ui): protype which keeps order

* feat(alerts/ui): new logic to deactivate filters

* feat(alerts/ui): delete specific paused filters

* feat(alerts/ui): allows to reactivate Pills.

* fix(alerts/ui): del log

* fix(alerts/ui): active Filters are visibly removed.

* feat(alerts/ui): clear all button clears now also inactive Filters.

* fix(alerts/ui): reduce logs

* fix(alerts/ui): version inc and change to npm

* chore(alerts/ui): update comments and clean up

* feat(alerts/ui): Showing Recrating and Expiring in Detailview of Silences

* feat(alerts/ui): TopNav is now a prop given to appshell

* feat(alerts/ui): add pausedfilters

* feat(alerts/ui): del filterPills in store, keys for all maps

* feat(alerts/ui): changes

* feat: ignore paused filters when filtering alerts

* fix(alerts/ui): when rendering filter values Select, take only max 100 values to prevent app from crashing.

* feat(alerts/ui): added pausable pills

* chore(alerts/ui): clean up comments and unused variables

* feat(alerts/ui): pausedFilter added in URLstate

* feat(alerts/ui): silence expiring and creating are now debouncing for 200 ms

* feat(alerts/ui): showing expiring and expiring silences in alertdetailview

* fix(alerts/ui): all alerts are shown in the detail view

* feat(alerts/ui): MessageProvider in DetailView

* feat(alerts/ui): absolute position of the message in the alert details.

* fix(alerts/ui): make more areas of the rows clickable (for details).

* feat(alerts/ui): push new creating to the start of the list

* feat(alerts/ui): untangle potential problem  with setting arrays inside of immer

* chore(alerts/ui): remove console.log and add comments explaining debounce helper and its use

---------

Co-authored-by: D038721 <[email protected]>
  • Loading branch information
TilmanHaupt and edda authored Aug 26, 2024
1 parent a0777ea commit 6dc1682
Show file tree
Hide file tree
Showing 19 changed files with 387 additions and 149 deletions.
12 changes: 6 additions & 6 deletions alerts/ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions alerts/ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "supernova",
"version": "0.9.20",
"version": "0.10.00 ",
"author": "UI-Team",
"contributors": [
"Esther Schmitz",
Expand Down Expand Up @@ -102,7 +102,7 @@
"dependencies": {
"@cloudoperators/juno-communicator": "^2.2.11",
"@cloudoperators/juno-messages-provider": "^0.1.17",
"@cloudoperators/juno-ui-components": "^2.15.4",
"@cloudoperators/juno-ui-components": "^2.17.1",
"@cloudoperators/juno-url-state-provider-v1": "^1.3.2",
"@cloudoperators/juno-utils": "^1.1.12",
"react-error-boundary": "^4.0.13"
Expand Down
7 changes: 5 additions & 2 deletions alerts/ui/src/components/CustomAppShell.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ const CustomAppShell = ({ children }) => {
)

return (
<AppShell pageHeader={pageHeader} embedded={embedded}>
{topNavigation}
<AppShell
pageHeader={pageHeader}
embedded={embedded}
topNavigation={topNavigation}
>
{children}
</AppShell>
)
Expand Down
17 changes: 11 additions & 6 deletions alerts/ui/src/components/alerts/Alert.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ const Alert = ({ alert }, ref) => {
// Using the rowRef to check what was clicked
// if the click was not on the row itself or on the row's direct children (i.e. the cells)
// then we don't want to show the details because then the click was on a child of one of the cells
// an additional check is made for targets with className "interactive". If the target has this then the click
// an additional check is made for targets with className "interactive" and for targets where a parent has className "interactive".
// If either the target itself or one of its parents has the "interactive" class then the click
// handling should proceed even if the previous condition was true
// TODO: This is pretty hacky, we need to come up with a better solution for this
if (
e.target.parentNode !== rowRef.current &&
!e.target.classList.contains("interactive")
!e.target.classList.contains("interactive") &&
!e.target.closest(".interactive")
)
return

Expand All @@ -68,12 +71,12 @@ const Alert = ({ alert }, ref) => {
ref={rowRef}
onClick={(e) => handleShowDetails(e)}
>
<DataGridCell className="pl-0">
<DataGridCell className="pl-0 interactive">
<div className={cellSeverityClasses(alert.labels?.severity)}>
<AlertIcon ref={ref} severity={alert.labels?.severity} />
</div>
</DataGridCell>
<DataGridCell>
<DataGridCell className="interactive">
<AlertRegion
region={alert.labels?.region}
cluster={alert.labels?.cluster}
Expand All @@ -93,8 +96,10 @@ const Alert = ({ alert }, ref) => {
</div>
<AlertLabels alert={alert} />
</DataGridCell>
<DataGridCell>
<AlertTimestamp startTimestamp={alert.startsAt} />
<DataGridCell className="interactive">
<AlertTimestamp
startTimestamp={alert.startsAt}
/>
</DataGridCell>
<DataGridCell>
<AlertStatus alert={alert} />
Expand Down
161 changes: 84 additions & 77 deletions alerts/ui/src/components/alerts/AlertDetail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ import SilenceNew from "../silences/SilenceNew"
import AlertStatus from "./AlertStatus"
import AlertRegion from "./shared/AlertRegion"
import AlertSilences from "./AlertSilences"
import {
MessagesProvider,
Messages,
} from "@cloudoperators/juno-messages-provider"

const AlertDetail = () => {
const alertID = useShowDetailsFor()
Expand All @@ -63,86 +67,89 @@ const AlertDetail = () => {
size="large"
>
<PanelBody>
<Tabs>
<TabList>
<Tab>Details</Tab>
<Tab>Raw Data</Tab>
</TabList>
<TabPanel>
<Container px={false} py>
{!alert ? (
isAlertsLoading ? (
<Stack gap="2">
<span>Loading</span>
<Spinner variant="primary" />
</Stack>
<MessagesProvider>
<Messages className="pb-6 absolute" />
<Tabs>
<TabList>
<Tab>Details</Tab>
<Tab>Raw Data</Tab>
</TabList>
<TabPanel>
<Container px={false} py>
{!alert ? (
isAlertsLoading ? (
<Stack gap="2">
<span>Loading</span>
<Spinner variant="primary" />
</Stack>
) : (
"Not found - the alert is probably not firing at the moment"
)
) : (
"Not found - the alert is probably not firing at the moment"
)
) : (
<>
<DataGrid columns={2}>
<DataGridRow>
<DataGridHeadCell>Status</DataGridHeadCell>
<DataGridCell>
<AlertStatus alert={alert} />
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Firing Since</DataGridHeadCell>
<DataGridCell>
<AlertTimestamp startTimestamp={alert?.startsAt} />
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Service</DataGridHeadCell>
<DataGridCell>{alert?.labels?.service}</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Region</DataGridHeadCell>
<DataGridCell>
<AlertRegion
region={alert?.labels?.region}
cluster={alert?.labels?.cluster}
/>
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Description</DataGridHeadCell>
<DataGridCell>
<AlertDescription
description={alert?.annotations?.description}
/>
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Links</DataGridHeadCell>
<DataGridCell>
<AlertLinks alert={alert} />
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Labels</DataGridHeadCell>
<DataGridCell>
<AlertLabels alert={alert} showAll={true} />
</DataGridCell>
</DataGridRow>
</DataGrid>
<>
<DataGrid columns={2}>
<DataGridRow>
<DataGridHeadCell>Status</DataGridHeadCell>
<DataGridCell>
<AlertStatus alert={alert} />
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Firing Since</DataGridHeadCell>
<DataGridCell>
<AlertTimestamp startTimestamp={alert?.startsAt} />
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Service</DataGridHeadCell>
<DataGridCell>{alert?.labels?.service}</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Region</DataGridHeadCell>
<DataGridCell>
<AlertRegion
region={alert?.labels?.region}
cluster={alert?.labels?.cluster}
/>
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Description</DataGridHeadCell>
<DataGridCell>
<AlertDescription
description={alert?.annotations?.description}
/>
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Links</DataGridHeadCell>
<DataGridCell>
<AlertLinks alert={alert} />
</DataGridCell>
</DataGridRow>
<DataGridRow>
<DataGridHeadCell>Labels</DataGridHeadCell>
<DataGridCell>
<AlertLabels alert={alert} showAll={true} />
</DataGridCell>
</DataGridRow>
</DataGrid>

<AlertSilences alert={alert} />
</>
)}
</Container>
</TabPanel>
<AlertSilences alert={alert} />
</>
)}
</Container>
</TabPanel>

<TabPanel>
<Container px={false} py>
<CodeBlock>
<JsonViewer data={alert} expanded={true} />
</CodeBlock>
</Container>
</TabPanel>
</Tabs>
<TabPanel>
<Container px={false} py>
<CodeBlock>
{alert && <JsonViewer data={alert} expanded={true} />}
</CodeBlock>
</Container>
</TabPanel>
</Tabs>
</MessagesProvider>
</PanelBody>

<PanelFooter>
Expand Down
4 changes: 2 additions & 2 deletions alerts/ui/src/components/alerts/AlertStatus.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const AlertStatus = ({ alert }) => {
<div className="text-xs mt-2">
<Stack direction="vertical">
<span>Inhibited by:</span>
{alert.status.inhibitedBy.map((fingerprint) => (
<span>
{alert.status.inhibitedBy.map((fingerprint, index) => (
<span key={index}>
{getAlertByFingerprint(fingerprint)?.annotations?.summary}
</span>
))}
Expand Down
44 changes: 35 additions & 9 deletions alerts/ui/src/components/alerts/shared/AlertSilencesList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useMemo } from "react"
import React, { useEffect } from "react"
import { DateTime } from "luxon"
import constants from "../../../constants"
import ExpireSilence from "../../silences/ExpireSilence"
import RecreateSilence from "../../silences/RecreateSilence"

import {
Badge,
Expand All @@ -15,7 +17,10 @@ import {
DataGridRow,
} from "@cloudoperators/juno-ui-components"

import { useSilencesActions } from "../../../hooks/useAppStore"
import {
useSilencesActions,
useSilencesLocalItems,
} from "../../../hooks/useAppStore"

const badgeVariant = (state) => {
switch (state) {
Expand All @@ -31,31 +36,33 @@ const badgeVariant = (state) => {
const AlertSilencesList = ({ alert }) => {
const dateFormat = { ...DateTime.DATETIME_SHORT }
const timeFormat = { ...DateTime.TIME_24_WITH_SHORT_OFFSET }
const localItems = useSilencesLocalItems()

const { getSilencesForAlert } = useSilencesActions()
let silenceList = getSilencesForAlert(alert)

const formatDateTime = (timestamp) => {
const time = DateTime.fromISO(timestamp)
return time.toLocaleString(dateFormat)
}

const { getMappingSilences, getExpiredSilences } = useSilencesActions()

const activeSilences = getMappingSilences(alert)
const expiredSilences = getExpiredSilences(alert)
console.log("expiredSilences", expiredSilences)
const silenceList = activeSilences.concat(expiredSilences)
useEffect(() => {
silenceList = getSilencesForAlert(alert)
}, [localItems])

return (
<>
{silenceList.length > 0 && (
<>
<h2 className="text-xl font-bold mb-2 mt-8">Silences</h2>
<DataGrid columns={5}>
<DataGrid columns={6} minContentColumns={[5]}>
<DataGridRow>
<DataGridHeadCell>Status</DataGridHeadCell>
<DataGridHeadCell>Silence start</DataGridHeadCell>
<DataGridHeadCell>Silence end</DataGridHeadCell>
<DataGridHeadCell>Created by</DataGridHeadCell>
<DataGridHeadCell>Comment</DataGridHeadCell>
<DataGridHeadCell>Action</DataGridHeadCell>
</DataGridRow>
{silenceList.map((silence) => (
<DataGridRow key={silence.id}>
Expand All @@ -72,6 +79,25 @@ const AlertSilencesList = ({ alert }) => {
<DataGridCell className="break-all">
{silence.comment}
</DataGridCell>
<DataGridCell>
{
/// show the expire button if the silence is active or pending
// else show recreate button
silence?.status?.state === constants.SILENCE_ACTIVE ||
silence?.status?.state === constants.SILENCE_PENDING ||
silence?.status?.state === constants.SILENCE_CREATING ? (
<ExpireSilence
silence={silence}
fingerprint={alert.fingerprint}
/>
) : (
<RecreateSilence
silence={silence}
fingerprint={alert.fingerprint}
/>
)
}
</DataGridCell>
</DataGridRow>
))}
</DataGrid>
Expand Down
2 changes: 1 addition & 1 deletion alerts/ui/src/components/alerts/shared/AlertTimestamp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const AlertTimestamp = ({ startTimestamp }) => {
const daysFiring = DateTime.now().diff(startTime, "days")

return (
<Stack direction="vertical" gap="1" className="cursor-default">
<Stack direction="vertical" gap="1">
<div>{startTime.toLocaleString(dateFormat)}</div>
<div>{startTime.toLocaleString(timeFormat)}</div>
{daysFiring.days > 7 && (
Expand Down
Loading

0 comments on commit 6dc1682

Please sign in to comment.