Skip to content

Commit

Permalink
ISPN-16412 display failed caches
Browse files Browse the repository at this point in the history
  • Loading branch information
karesti committed Sep 12, 2024
1 parent 4dfc295 commit 0cecc4b
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 77 deletions.
97 changes: 67 additions & 30 deletions src/app/Caches/CacheMetrics.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React, { useEffect, useState } from 'react';
import React, { useState } from 'react';
import {
Button,
ButtonVariant,
Card,
CardBody,
CardTitle,
EmptyState,
EmptyStateActions,
EmptyStateBody,
EmptyStateFooter,
EmptyStateHeader,
EmptyStateIcon,
EmptyStateVariant,
Expand All @@ -20,7 +24,7 @@ import {
TextVariants
} from '@patternfly/react-core';
import displayUtils from '@services/displayUtils';
import { CubesIcon } from '@patternfly/react-icons';
import { CubesIcon, ExclamationCircleIcon } from '@patternfly/react-icons';
import { QueryMetrics } from '@app/Caches/Query/QueryMetrics';
import { DataDistributionChart } from './DataDistributionChart';
import { PopoverHelp } from '@app/Common/PopoverHelp';
Expand All @@ -32,32 +36,24 @@ import { ConsoleServices } from '@services/ConsoleServices';
import { useConnectedUser } from '@app/services/userManagementHook';
import { ConsoleACL } from '@services/securityService';
import { CacheLifecycle } from '@app/Caches/CacheLifecycle';
import { global_danger_color_200 } from '@patternfly/react-tokens';
import { Link } from 'react-router-dom';

const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
const { t } = useTranslation();
const { connectedUser } = useConnectedUser();
const { cache, error, loading } = useCacheDetail();
const [stats, setStats] = useState<CacheStats | undefined>(cache.stats);
const [displayQueryStats, setDisplayQueryStats] = useState<boolean>(false);
const [displayDataDistribution, setDisplayDataDistribution] = useState<boolean>(false);
const [memory, setMemory] = useState<string | undefined>(undefined);
const { t } = useTranslation();
const brandname = t('brandname.brandname');

useEffect(() => {
if (ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) {
// Data distribution is for admin only
setDisplayDataDistribution(true);
const loadMemory = cache.memory;
if (loadMemory) {
setMemory(loadMemory.storage_type == 'OFF_HEAP' ? StorageType.OFF_HEAP : StorageType.HEAP);
} else {
setMemory(StorageType.HEAP);
}
const [displayQueryStats, setDisplayQueryStats] = useState<boolean>(cache.queryable!);
const [displayDataDistribution, setDisplayDataDistribution] = useState<boolean>(
ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)
);
const memory = () => {
if (cache.memory) {
return cache.memory.storage_type == 'OFF_HEAP' ? StorageType.OFF_HEAP : StorageType.HEAP;
}

setStats(cache.stats);
setDisplayQueryStats(cache.queryable);
}, [cache, error]);
return StorageType.HEAP;
};

const buildOperationsPerformanceCard = () => {
if (!stats) {
Expand Down Expand Up @@ -180,7 +176,7 @@ const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
return '';
}
let content;
if (memory === StorageType.OFF_HEAP) {
if (memory() === StorageType.OFF_HEAP) {
content = (
<React.Fragment>
<TextListItem aria-label="view-cache-metrics-off-heap" component={TextListItemVariants.dt}>
Expand Down Expand Up @@ -242,18 +238,59 @@ const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
};

if (!props.display) {
return <span />;
return <></>;
}

if (loading && error.length == 0) {
return (
<Card>
<CardBody>
<EmptyState>
<EmptyStateHeader
titleText={t('common.loading')}
headingLevel="h4"
icon={<EmptyStateIcon icon={Spinner} />}
/>
</EmptyState>
</CardBody>
</Card>
);
}

if (!stats || loading) {
return <Spinner size={'xl'} />;
if (error.length > 0) {
return (
<Card>
<CardBody>
<EmptyState variant={EmptyStateVariant.sm}>
<EmptyStateHeader
titleText={<>{`An error occurred while retrieving stats ${props.cacheName}`}</>}
icon={<EmptyStateIcon icon={ExclamationCircleIcon} color={global_danger_color_200.value} />}
headingLevel="h2"
/>
<EmptyStateBody>{error}</EmptyStateBody>
<EmptyStateFooter>
<EmptyStateActions>
<Link
to={{
pathname: '/',
search: location.search
}}
>
<Button variant={ButtonVariant.secondary}>{t('common.actions.back')}</Button>
</Link>
</EmptyStateActions>
</EmptyStateFooter>
</EmptyState>
</CardBody>
</Card>
);
}

if (!stats.enabled) {
if (stats && !stats.enabled) {
return (
<EmptyState variant={EmptyStateVariant.sm}>
<EmptyStateHeader
titleText={<>{t('caches.cache-metrics.metrics-title')}</>}
titleText={t('caches.cache-metrics.metrics-title')}
icon={<EmptyStateIcon icon={CubesIcon} />}
headingLevel="h5"
/>
Expand All @@ -273,8 +310,8 @@ const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
<GridItem span={4}>{buildOperationsPerformanceCard()}</GridItem>
{displayDataDistribution && <GridItem span={8}> {buildDataDistribution()}</GridItem>}
<GridItem span={4}>
<CacheLifecycle stats={stats} />
<DataAccess cacheName={props.cacheName} stats={stats} />
<CacheLifecycle stats={stats!} />
<DataAccess cacheName={props.cacheName} stats={stats!} />
</GridItem>
<GridItem span={displayDataDistribution ? 12 : 8}>{buildQueryStats()}</GridItem>
</Grid>
Expand Down
61 changes: 52 additions & 9 deletions src/app/Caches/DetailCache.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { ThemeContext } from '@app/providers/ThemeProvider';
import { useNavigate } from 'react-router';
import { TracingEnabled } from '@app/Common/TracingEnabled';
import { AlertIcon } from '@patternfly/react-core/dist/js/components/Alert/AlertIcon';
import { Health } from '@app/Common/Health';

const DetailCache = (props: { cacheName: string }) => {
const cacheName = props.cacheName;
Expand All @@ -84,7 +85,11 @@ const DetailCache = (props: { cacheName: string }) => {
return;
}

if (cache.editable && ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)) {
if (
cache.started &&
cache.editable &&
ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)
) {
setActiveTabKey1(0);
} else if (ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) {
setActiveTabKey1(1);
Expand All @@ -94,7 +99,7 @@ const DetailCache = (props: { cacheName: string }) => {
}, [cache]);

const buildEntriesTabContent = () => {
if (!ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)) {
if (cache.started && !ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)) {
return '';
}

Expand Down Expand Up @@ -127,7 +132,7 @@ const DetailCache = (props: { cacheName: string }) => {
};

const entriesTabEnabled = (): boolean => {
return cache.editable && ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser);
return cache.editable! && ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser);
};

const buildDetailContent = () => {
Expand Down Expand Up @@ -177,7 +182,11 @@ const DetailCache = (props: { cacheName: string }) => {
if (activeTabKey1 == 1) {
return (
cache.configuration && (
<CacheConfiguration cacheName={cache.name} editable={cache.editable} config={cache.configuration.config} />
<CacheConfiguration
cacheName={cache.name}
editable={cache?.editable || true}
config={cache.configuration.config}
/>
)
);
}
Expand Down Expand Up @@ -208,11 +217,15 @@ const DetailCache = (props: { cacheName: string }) => {
};

const displayBackupsManagement = () => {
return cache?.features.hasRemoteBackup && ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser);
return (
cache &&
cache?.features?.hasRemoteBackup &&
ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)
);
};

const displayIndexManage = () => {
return cache?.features.indexed;
return cache && cache?.features?.indexed;
};

const buildBackupsManage = () => {
Expand Down Expand Up @@ -266,7 +279,7 @@ const DetailCache = (props: { cacheName: string }) => {
};

const buildTracing = () => {
if (!cacheManager || !cacheManager.tracing_enabled) return;
if (!cacheManager || !cacheManager.tracing_enabled || !cache || !cache.started) return;

return (
<DropdownItem
Expand Down Expand Up @@ -344,7 +357,7 @@ const DetailCache = (props: { cacheName: string }) => {
{cacheManager.tracing_enabled && (
<React.Fragment>
<ToolbarItem>
<TracingEnabled enabled={cache.tracing} />
<TracingEnabled enabled={cache.tracing!} />
</ToolbarItem>
<ToolbarItem variant="separator"></ToolbarItem>
</React.Fragment>
Expand Down Expand Up @@ -464,6 +477,36 @@ const DetailCache = (props: { cacheName: string }) => {
);
}

if (!cache.started) {
// cache is not ok
return (
<React.Fragment>
<Toolbar id="cache-detail-header">
<ToolbarContent>
<ToolbarGroup>
<ToolbarItem>
<Flex>
<FlexItem>
<TextContent>
<Text component={TextVariants.h1}>{cache.name}</Text>
</TextContent>
</FlexItem>
<FlexItem>
<Health health={cache.health} displayIcon={true} cacheName={cache.name} />
</FlexItem>
</Flex>
</ToolbarItem>
</ToolbarGroup>
{displayActions}
</ToolbarContent>
</Toolbar>
<Tabs isBox={false} activeKey={activeTabKey1} isSecondary={true} component={TabsComponent.nav}>
{displayConfiguration()}
</Tabs>
</React.Fragment>
);
}

return (
<React.Fragment>
<Toolbar id="cache-detail-header">
Expand All @@ -475,7 +518,7 @@ const DetailCache = (props: { cacheName: string }) => {
</TextContent>
</ToolbarItem>
<ToolbarItem>
<CacheTypeBadge cacheType={cache.type} small={true} cacheName={cache.name} />
<CacheTypeBadge cacheType={cache.type!} small={true} cacheName={cache.name} />
</ToolbarItem>
{buildFeaturesChip()}
</ToolbarGroup>
Expand Down
34 changes: 19 additions & 15 deletions src/app/Caches/Entries/CacheEntries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,23 @@ const CacheEntries = () => {
const { syntaxHighLighterTheme } = useContext(ThemeContext);

useEffect(() => {
if (cache.encoding.key == EncodingType.Protobuf) {
if (cache.encoding?.key == EncodingType.Protobuf) {
setSelectSearchOption(ContentType.string);
setKeyContentTypeToEdit(ContentType.string);
} else if (
cache.encoding.key == EncodingType.Java ||
cache.encoding.key == EncodingType.JBoss ||
cache.encoding.key == EncodingType.JavaSerialized
cache.encoding?.key == EncodingType.Java ||
cache.encoding?.key == EncodingType.JBoss ||
cache.encoding?.key == EncodingType.JavaSerialized
) {
setSelectSearchOption(ContentType.StringContentType);
setKeyContentTypeToEdit(ContentType.StringContentType);
} else if (cache.encoding.key == EncodingType.XML) {
} else if (cache.encoding?.key == EncodingType.XML) {
setSelectSearchOption(ContentType.XML);
setKeyContentTypeToEdit(ContentType.XML);
} else if (cache.encoding.key == EncodingType.JSON) {
} else if (cache.encoding?.key == EncodingType.JSON) {
setSelectSearchOption(ContentType.JSON);
setSelectSearchOption(ContentType.JSON);
} else if (cache.encoding.key == EncodingType.Text) {
} else if (cache.encoding?.key == EncodingType.Text) {
setSelectSearchOption(ContentType.StringContentType);
setSelectSearchOption(ContentType.StringContentType);
}
Expand Down Expand Up @@ -284,7 +284,7 @@ const CacheEntries = () => {
icon={<EmptyStateIcon icon={PlusCircleIcon} />}
headingLevel="h4"
/>
<EmptyStateBody>{infoEntries ? infoEntries : t('caches.entries.empty-cache-body')}</EmptyStateBody>
<EmptyStateBody>{infoEntries ? t(infoEntries) : t('caches.entries.empty-cache-body')}</EmptyStateBody>
<EmptyStateFooter>
<EmptyStateActions style={{ marginTop: global_spacer_sm.value }}>{addEntryAction()}</EmptyStateActions>
</EmptyStateFooter>
Expand All @@ -310,7 +310,7 @@ const CacheEntries = () => {
};

const keyContentTypeOptions = (): SelectOptionProps[] => {
return selectOptionPropsFromArray(CacheConfigUtils.getContentTypeOptions(cache.encoding.key as EncodingType));
return selectOptionPropsFromArray(CacheConfigUtils.getContentTypeOptions(cache.encoding?.key as EncodingType));
};

const searchEntryByKey = () => {
Expand Down Expand Up @@ -398,8 +398,8 @@ const CacheEntries = () => {
if (!ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cache.name, connectedUser)) {
return '';
}
const encodingKey = CacheConfigUtils.toEncoding(cache.encoding.key);
const encodingValue = CacheConfigUtils.toEncoding(cache.encoding.value);
const encodingKey = CacheConfigUtils.toEncoding(cache.encoding?.key);
const encodingValue = CacheConfigUtils.toEncoding(cache.encoding?.value);
if (
encodingKey == EncodingType.Java ||
encodingKey == EncodingType.JavaSerialized ||
Expand Down Expand Up @@ -435,6 +435,10 @@ const CacheEntries = () => {
return '';
};

if (!cache.started) {
// Don't display anything if the cache is not started
return <></>;
}
return (
<React.Fragment>
{encodingMessageDisplay()}
Expand Down Expand Up @@ -511,14 +515,14 @@ const CacheEntries = () => {
<Td dataLabel={columnNames.key}>
{displayHighlighted(
row.key,
cache.encoding.key as EncodingType,
cache.encoding?.key as EncodingType,
row.keyContentType as ContentType
)}
</Td>
<Td dataLabel={columnNames.value}>
{displayHighlighted(
row.value,
cache.encoding.value as EncodingType,
cache.encoding?.value as EncodingType,
row.valueContentType as ContentType
)}
</Td>
Expand All @@ -539,15 +543,15 @@ const CacheEntries = () => {
)}
<CreateOrUpdateEntryForm
cacheName={cache.name}
cacheEncoding={cache.encoding}
cacheEncoding={cache.encoding!}
keyToEdit={keyToEdit}
keyContentType={keyContentTypeToEdit}
isModalOpen={isCreateOrUpdateEntryFormOpen}
closeModal={closeCreateOrEditEntryFormModal}
/>
<DeleteEntry
cacheName={cache.name}
cacheEncoding={cache.encoding}
cacheEncoding={cache.encoding!}
entryKey={keyToDelete}
keyContentType={keyContentTypeToEdit}
isModalOpen={isDeleteEntryModalOpen}
Expand Down
Loading

0 comments on commit 0cecc4b

Please sign in to comment.