-
Notifications
You must be signed in to change notification settings - Fork 192
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove discover - Implement embeddable dashboard on statistics module (…
…#6542) * Migrated visualizations to embeddables * Changed searchbar and node selector * Cleaned dashboard obsolete code * Added selectedNodeFilter * Integrated new data source on statistics * Fixed statistics index without data. * Added apiName filter * Fixed nodeName filter when a node is selected in cluster mode * Added No results message, fixed allow agents filters on request and cleaned obsolete code * Changed condition of apiName filter, validation of statistics-data-source-repository and abstracted behavior between DashboardListenerEngineStatistics and DashboardAnalysisEngineStatistics * Deleted unused use-build-statistics-visualizations hook * Fixed information message depending on active tab * Added withUserAuthorizationPrompt to add protection with the user permissions check * remove(statistics): unused message definitions * Deleted unused index.ts file on cluster integration-files visualizations --------- Co-authored-by: Antonio David Gutiérrez <antonio.gutierrez@wazuh.com>
- Loading branch information
Showing
22 changed files
with
4,162 additions
and
3,517 deletions.
There are no files selected for viewing
438 changes: 235 additions & 203 deletions
438
...s/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts
Large diffs are not rendered by default.
Oops, something went wrong.
2 changes: 2 additions & 0 deletions
2
plugins/main/public/components/common/data-source/pattern/statistics/index.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,2 @@ | ||
export * from './statistics-data-source-repository'; | ||
export * from './statistics-data-source'; |
55 changes: 55 additions & 0 deletions
55
...lic/components/common/data-source/pattern/statistics/statistics-data-source-repository.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,55 @@ | ||
import { PatternDataSourceRepository } from '../pattern-data-source-repository'; | ||
import { tParsedIndexPattern } from '../../index'; | ||
import { StatisticsDataSource } from './statistics-data-source'; | ||
|
||
export class StatisticsDataSourceRepository extends PatternDataSourceRepository { | ||
constructor() { | ||
super(); | ||
} | ||
|
||
async get(id: string) { | ||
const dataSource = await super.get(id); | ||
if (this.validate(dataSource)) { | ||
return dataSource; | ||
} else { | ||
throw new Error('Statistics index pattern not found'); | ||
} | ||
} | ||
|
||
async getAll() { | ||
const indexs = await super.getAll(); | ||
return indexs.filter(this.validate); | ||
} | ||
|
||
validate(dataSource): boolean { | ||
// check if the dataSource has the id or the title have the statistics word | ||
const fieldsToCheck = ['id', 'attributes.title']; | ||
/* Keep in mind that the identifier is compared with id and title since it is currently not defined that the id is the only one that validates. But this can generate a problem in which the title matches more than one index. */ | ||
const STATISTICS_PATTERN_IDENTIFIER = | ||
StatisticsDataSource.getIdentifierDataSourcePattern(); | ||
// must check in the object and the attributes | ||
for (const field of fieldsToCheck) { | ||
if ( | ||
dataSource[field] && | ||
dataSource[field].toLowerCase().includes(STATISTICS_PATTERN_IDENTIFIER) | ||
) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
getDefault() { | ||
console.warn( | ||
'getDefault not implemented for statistics data source repository', | ||
); | ||
return Promise.resolve(null); | ||
} | ||
|
||
setDefault(_dataSource: tParsedIndexPattern) { | ||
console.warn( | ||
'setDefault not implemented for statistics data source repository', | ||
); | ||
return; | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
...ns/main/public/components/common/data-source/pattern/statistics/statistics-data-source.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,50 @@ | ||
import { AppState } from '../../../../../react-services'; | ||
import { tFilter } from '../../index'; | ||
import { PatternDataSource } from '../pattern-data-source'; | ||
import store from '../../../../../redux/store'; | ||
|
||
export class StatisticsDataSource extends PatternDataSource { | ||
constructor(id: string, title: string) { | ||
super(id, title); | ||
} | ||
|
||
static getIdentifierDataSourcePattern(): string { | ||
// Return Statistics Identifier Index Pattern | ||
const appConfig = store.getState().appConfig; | ||
return `${appConfig.data['cron.prefix']}-${appConfig.data['cron.statistics.index.name']}-*`; | ||
} | ||
|
||
getFetchFilters(): tFilter[] { | ||
return [...this.getAPIFilter()]; | ||
} | ||
|
||
getAPIFilter(): tFilter[] { | ||
const currentApi = AppState.getCurrentAPI(); | ||
const parsedCurrentApi = currentApi ? JSON.parse(currentApi) : undefined; | ||
const apiNameFilter = { | ||
meta: { | ||
removable: false, | ||
index: this.id, | ||
negate: false, | ||
disabled: false, | ||
alias: null, | ||
type: 'phrase', | ||
key: null, | ||
value: null, | ||
params: { | ||
query: null, | ||
type: 'phrase', | ||
}, | ||
}, | ||
query: { | ||
match_phrase: { | ||
apiName: parsedCurrentApi?.id, | ||
}, | ||
}, | ||
$state: { | ||
store: 'appState', | ||
}, | ||
}; | ||
return [apiNameFilter]; | ||
} | ||
} |
199 changes: 199 additions & 0 deletions
199
...ublic/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.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,199 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import { getPlugins } from '../../../../kibana-services'; | ||
import { I18nProvider } from '@osd/i18n/react'; | ||
import useSearchBar from '../../../common/search-bar/use-search-bar'; | ||
import { | ||
EuiFlexItem, | ||
EuiFlexGroup, | ||
EuiSelect, | ||
EuiSpacer, | ||
EuiCallOut, | ||
EuiPanel, | ||
} from '@elastic/eui'; | ||
import { | ||
PatternDataSource, | ||
tFilter, | ||
tParsedIndexPattern, | ||
useDataSource, | ||
} from '../../../common/data-source'; | ||
import { IndexPattern } from '../../../../../../../src/plugins/data/public'; | ||
import { SearchResponse } from '../../../../../../../src/core/server'; | ||
import { | ||
StatisticsDataSource, | ||
StatisticsDataSourceRepository, | ||
} from '../../../common/data-source/pattern/statistics'; | ||
import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; | ||
import { | ||
ErrorFactory, | ||
ErrorHandler, | ||
HttpError, | ||
} from '../../../../react-services/error-management'; | ||
import { DiscoverNoResults } from '../../../common/no-results/no-results'; | ||
import { DashboardAnalysisEngineStatistics } from './dashboard_analysis_engine'; | ||
import { DashboardListenerEngineStatistics } from './dashboard_listener_engine'; | ||
|
||
const SearchBar = getPlugins().data.ui.SearchBar; | ||
|
||
interface DashboardTabsPanelsProps { | ||
selectedTab: string; | ||
loadingNode: boolean; | ||
isClusterMode: boolean; | ||
clusterNodes: any[]; | ||
clusterNodeSelected: any; | ||
onSelectNode: (event: any) => void; | ||
} | ||
|
||
export const DashboardTabsPanels = ({ | ||
selectedTab, | ||
loadingNode, | ||
isClusterMode, | ||
clusterNodes, | ||
clusterNodeSelected, | ||
onSelectNode, | ||
}: DashboardTabsPanelsProps) => { | ||
const { | ||
filters, | ||
fetchFilters, | ||
dataSource, | ||
fetchData, | ||
setFilters, | ||
isLoading: isDataSourceLoading, | ||
} = useDataSource<tParsedIndexPattern, PatternDataSource>({ | ||
DataSource: StatisticsDataSource, | ||
repository: new StatisticsDataSourceRepository(), | ||
}); | ||
|
||
const [results, setResults] = useState<SearchResponse>({} as SearchResponse); | ||
|
||
const infoMessage = { | ||
remoted: | ||
'Remoted statistics are cumulative, this means that the information shown is since the data exists.', | ||
analysisd: | ||
"Analysisd statistics refer to the data stored from the period indicated in the variable 'analysisd.state_interval'.", | ||
}; | ||
|
||
const { searchBarProps } = useSearchBar({ | ||
indexPattern: dataSource?.indexPattern as IndexPattern, | ||
filters, | ||
setFilters, | ||
}); | ||
|
||
const { query, dateRangeFrom, dateRangeTo } = searchBarProps; | ||
|
||
useEffect(() => { | ||
if (isDataSourceLoading) { | ||
return; | ||
} | ||
fetchData({ | ||
query, | ||
dateRange: { | ||
from: dateRangeFrom, | ||
to: dateRangeTo, | ||
}, | ||
}) | ||
.then(results => { | ||
setResults(results); | ||
}) | ||
.catch(error => { | ||
const searchError = ErrorFactory.create(HttpError, { | ||
error, | ||
message: 'Error fetching statistics', | ||
}); | ||
ErrorHandler.handleError(searchError); | ||
}); | ||
}, [ | ||
JSON.stringify(fetchFilters), | ||
JSON.stringify(query), | ||
dateRangeFrom, | ||
dateRangeTo, | ||
]); | ||
|
||
const selectedNodeFilter: tFilter = { | ||
meta: { | ||
removable: false, | ||
index: dataSource?.id, | ||
negate: false, | ||
disabled: false, | ||
alias: null, | ||
type: 'phrase', | ||
key: null, | ||
value: null, | ||
params: { | ||
query: null, | ||
type: 'phrase', | ||
}, | ||
}, | ||
query: { | ||
match: { | ||
nodeName: clusterNodeSelected, | ||
}, | ||
}, | ||
$state: { | ||
store: 'appState', | ||
}, | ||
}; | ||
return ( | ||
<I18nProvider> | ||
{isDataSourceLoading && !dataSource ? ( | ||
<LoadingSpinner /> | ||
) : ( | ||
<EuiFlexGroup alignItems='center' justifyContent='flexEnd'> | ||
{!!(clusterNodes && clusterNodes.length && clusterNodeSelected) && ( | ||
<EuiFlexItem grow={false}> | ||
<EuiSelect | ||
id='selectNode' | ||
options={clusterNodes} | ||
value={clusterNodeSelected} | ||
onChange={onSelectNode} | ||
aria-label='Select node' | ||
/> | ||
</EuiFlexItem> | ||
)} | ||
<SearchBar | ||
appName='statistics-searchbar' | ||
{...searchBarProps} | ||
showDatePicker={true} | ||
showQueryInput={false} | ||
showQueryBar={true} | ||
showFilterBar={false} | ||
/> | ||
</EuiFlexGroup> | ||
)} | ||
|
||
<EuiSpacer size={'m'} /> | ||
<EuiPanel hasBorder={false} hasShadow={false} color='transparent'> | ||
<EuiCallOut title={infoMessage[selectedTab]} iconType='iInCircle' /> | ||
</EuiPanel> | ||
{dataSource && results?.hits?.total === 0 ? <DiscoverNoResults /> : null} | ||
{!isDataSourceLoading && dataSource && results?.hits?.total > 0 ? ( | ||
<> | ||
{selectedTab === 'remoted' && !loadingNode && ( | ||
<div> | ||
<DashboardListenerEngineStatistics | ||
indexPatternId={dataSource?.id} | ||
searchBarProps={searchBarProps} | ||
filters={ | ||
clusterNodeSelected !== 'all' | ||
? [...fetchFilters, selectedNodeFilter] | ||
: [...(fetchFilters ?? [])] | ||
} | ||
/> | ||
</div> | ||
)} | ||
{selectedTab === 'analysisd' && !loadingNode && ( | ||
<DashboardAnalysisEngineStatistics | ||
isClusterMode={isClusterMode} | ||
indexPatternId={dataSource?.id} | ||
searchBarProps={searchBarProps} | ||
filters={ | ||
clusterNodeSelected !== 'all' | ||
? [...fetchFilters, selectedNodeFilter] | ||
: [...(fetchFilters ?? [])] | ||
} | ||
/> | ||
)} | ||
</> | ||
) : null} | ||
</I18nProvider> | ||
); | ||
}; |
58 changes: 58 additions & 0 deletions
58
...components/overview/server-management-statistics/dashboards/dashboard_analysis_engine.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,58 @@ | ||
import React from 'react'; | ||
import { getPlugins } from '../../../../kibana-services'; | ||
import { ViewMode } from '../../../../../../../src/plugins/embeddable/public'; | ||
import { withErrorBoundary } from '../../../common/hocs/error-boundary/with-error-boundary'; | ||
import { getDashboardPanelsAnalysisEngine } from './dashboard_panels_analysis_engine'; | ||
import { tFilter } from '../../../common/data-source'; | ||
import './statistics_dashboard.scss'; | ||
|
||
const plugins = getPlugins(); | ||
|
||
const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; | ||
|
||
interface DashboardStatisticsProps { | ||
isClusterMode: boolean; | ||
indexPatternId: string; | ||
filters: tFilter[]; | ||
searchBarProps: any; | ||
} | ||
|
||
const DashboardStatistics: React.FC<DashboardStatisticsProps> = ({ | ||
isClusterMode, | ||
indexPatternId, | ||
filters, | ||
searchBarProps, | ||
}) => { | ||
return ( | ||
<div className='server-management-statistics-dashboard-responsive'> | ||
<DashboardByRenderer | ||
input={{ | ||
viewMode: ViewMode.VIEW, | ||
panels: getDashboardPanelsAnalysisEngine( | ||
indexPatternId, | ||
isClusterMode, | ||
), | ||
isFullScreenMode: false, | ||
filters: filters, | ||
useMargins: true, | ||
id: 'analysis-engine-statistics-dashboard', | ||
timeRange: { | ||
from: searchBarProps.dateRangeFrom, | ||
to: searchBarProps.dateRangeTo, | ||
}, | ||
title: 'Analysis Engine Statistics dashboard', | ||
description: 'Dashboard of the Analysis Engine Statistics', | ||
query: searchBarProps.query, | ||
refreshConfig: { | ||
pause: false, | ||
value: 15, | ||
}, | ||
hidePanelTitles: false, | ||
}} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export const DashboardAnalysisEngineStatistics = | ||
withErrorBoundary(DashboardStatistics); |
Oops, something went wrong.