Skip to content
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

[PR] Add agent synchronization statistics #3874

Merged
merged 12 commits into from
Sep 6, 2022
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ All notable changes to the Wazuh app project will be documented in this file.

## Wazuh v4.4.0 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4400

## Added
- Added agent synchronization status in the agent module. [#3874](https://github.com/wazuh/wazuh-kibana-app/pull/3874)

### Changed

- Changed the HTTP verb from `GET` to `POST` in the requests to login to the Wazuh API [#4103](https://github.com/wazuh/wazuh-kibana-app/pull/4103)
- Endpoint `/agents/summary/status` response was adapted. [#3874](https://github.com/wazuh/wazuh-kibana-app/pull/3874)

## Wazuh v4.3.5 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4306

Expand Down
21 changes: 21 additions & 0 deletions public/components/agents/agent-synced.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { EuiHealth } from "@elastic/eui";

interface SyncedProps {
synced: string;
}

export const AgentSynced = ({ synced }:SyncedProps) => {
const color = {
synced: 'success',
'not synced': 'subdued',
}[synced];

return (
<EuiHealth color={color}>
<span className={'hide-agent-status'}>
{synced}
</span>
</EuiHealth>
);
}
4 changes: 2 additions & 2 deletions public/controllers/agent/agents-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ export class AgentsPreviewController {
if (loc && loc.tab) {
this.submenuNavItem = loc.tab;
}
const summaryData = await WzRequest.apiReq('GET', '/agents/summary/status', {});
this.summary = summaryData.data.data;
const {data: {data: summaryData}} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
this.summary = summaryData.connection;
if (this.summary.total === 0) {
if (this.addingNewAgent === undefined) {
this.addNewAgent(true);
Expand Down
15 changes: 13 additions & 2 deletions public/controllers/agent/components/agents-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export const AgentsPreview = compose(
loading: false,
showAgentsEvolutionVisualization: false,
agentTableFilters: [],
agentStatusSummary: {}
agentStatusSummary: {},
agentConfiguration: {},
};
this.wazuhConfig = new WazuhConfig();
this.agentStatus = UI_ORDER_AGENT_STATUS.map(agentStatus => ({
Expand Down Expand Up @@ -110,7 +111,7 @@ export const AgentsPreview = compose(
async fetchAgentStatusDetailsData(){
try {
this.setState({ loading: true });
const {data: {data: agentStatusSummary}} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
const {data: {data: { connection: agentStatusSummary, configuration: agentConfiguration }}} = await WzRequest.apiReq('GET', '/agents/summary/status', {});

const {data: {data: {affected_items: [lastRegisteredAgent]}}} = await WzRequest.apiReq('GET', '/agents', {
params: { limit: 1, sort: '-dateAdd', q: 'id!=000' },
Expand All @@ -121,7 +122,9 @@ export const AgentsPreview = compose(
loading: false,
lastRegisteredAgent,
agentStatusSummary,
agentConfiguration,
agentsActiveCoverage: ((agentStatusSummary.active/agentStatusSummary.total)*100).toFixed(2),
agentsSynced: ((agentConfiguration.synced/agentConfiguration.total)*100).toFixed(2),
agentMostActive
});
} catch (error) {
Expand Down Expand Up @@ -216,6 +219,14 @@ export const AgentsPreview = compose(
className="white-space-nowrap"
/>
</EuiFlexItem>
<EuiFlexItem className="agents-link-item">
<EuiStat
title={`${this.state.agentsSynced}%`}
titleSize='s'
description="Agents Synced"
className="white-space-nowrap"
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup className="mt-0">
{this.state.lastRegisteredAgent && (
Expand Down
48 changes: 29 additions & 19 deletions public/controllers/agent/components/agents-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { API_NAME_AGENT_STATUS, UI_LOGGER_LEVELS, UI_ORDER_AGENT_STATUS } from '
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { AgentStatus } from '../../../components/agents/agent_status';
import { AgentSynced } from '../../../components/agents/agent-synced';

export const AgentsTable = withErrorBoundary(
class AgentsTable extends Component {
Expand Down Expand Up @@ -77,6 +78,13 @@ export const AgentsTable = withErrorBoundary(
operators: ['=', '!='],
values: UI_ORDER_AGENT_STATUS,
},
{
type: 'q',
label: 'synced',
description: 'Filter by agent synced configuration status',
operators: ['=', '!='],
values: ['true', 'false'],
},
{
type: 'q',
label: 'os.platform',
Expand Down Expand Up @@ -168,15 +176,15 @@ export const AgentsTable = withErrorBoundary(
async UNSAFE_componentWillMount() {
const managerVersion = await WzRequest.apiReq('GET', '/', {});
const totalAgent = await WzRequest.apiReq('GET', '/agents', {});
const agentActive = await WzRequest.apiReq('GET', '/agents/summary/status', {});
const {data: {data: {connection: agentActive}}} = await WzRequest.apiReq('GET', '/agents/summary/status', {});



this.setState({
managerVersion: managerVersion.data.data.api_version,
avaibleAgents: totalAgent.data.data.affected_items,
agentActive: agentActive.data.data.active + agentActive.data.data.disconnected,
agentActive: agentActive.active + agentActive.disconnected,
});
}
}

onTableChange = ({ page = {}, sort = {} }) => {
const { index: pageIndex, size: pageSize } = page;
Expand Down Expand Up @@ -330,6 +338,7 @@ export const AgentsTable = withErrorBoundary(
name: agent.name,
ip: agent.ip,
status: agent.status,
synced: agent.group_config_status,
group: checkField(agent.group),
os_name: agent,
version: agentVersion,
Expand Down Expand Up @@ -782,20 +791,20 @@ export const AgentsTable = withErrorBoundary(
field: 'name',
name: 'Name',
sortable: true,
width: '15%',
width: '10%',
truncateText: true,
},
{
field: 'ip',
name: 'IP',
width: '10%',
width: '8%',
truncateText: true,
sortable: true,
},
{
field: 'group',
name: 'Group(s)',
width: '20%',
width: '14%',
truncateText: true,
sortable: true,
render: (groups) => (groups !== '-' ? this.renderGroups(groups) : '-'),
Expand All @@ -804,14 +813,14 @@ export const AgentsTable = withErrorBoundary(
field: 'os_name',
name: 'OS',
sortable: true,
width: '15%',
width: '10%',
truncateText: true,
render: this.addIconPlatformRender,
},
{
field: 'node_name',
name: 'Cluster node',
width: '10%',
width: '8%',
truncateText: true,
sortable: true,
},
Expand All @@ -826,14 +835,14 @@ export const AgentsTable = withErrorBoundary(
{
field: 'dateAdd',
name: 'Registration date',
width: '10%',
width: '8%',
truncateText: true,
sortable: true,
},
{
field: 'lastKeepAlive',
name: 'Last keep alive',
width: '10%',
width: '8%',
truncateText: true,
sortable: true,
},
Expand All @@ -842,9 +851,17 @@ export const AgentsTable = withErrorBoundary(
name: 'Status',
truncateText: true,
sortable: true,
width: '15%',
width: '10%',
render: (status) => <AgentStatus status={status} labelProps={{className: 'hide-agent-status' }}/>,
},
{
field: 'synced',
name: 'Synced',
truncateText: true,
sortable: true,
width: '10%',
render: (synced) => <AgentSynced synced={synced}/>,
},
{
align: 'right',
width: '5%',
Expand Down Expand Up @@ -1014,11 +1031,6 @@ export const AgentsTable = withErrorBoundary(
},
};

const selection = {
selectable: (agent) => agent.id,
/* onSelectionChange: this.onSelectionChange */
};

return (
<EuiFlexGroup>
<EuiFlexItem>
Expand All @@ -1031,8 +1043,6 @@ export const AgentsTable = withErrorBoundary(
loading={isLoading}
rowProps={getRowProps}
cellProps={getCellProps}
/* isSelectable={false}
selection={selection} */
noItemsMessage="No agents found"
{...(pagination && { pagination })}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class WzStatusActionButtons extends Component {
this.props.updateLoadingStatus(true);
this.props.updateSelectedNode(node);

const [agentsCount, agentsCountByManagerNodes] = (await Promise.all([
const [{connection: agentsCount}, agentsCountByManagerNodes] = (await Promise.all([
this.statusHandler.agentsSummary(),
this.statusHandler.clusterAgentsCount()
])).map(response => response?.data?.data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class WzStatusOverview extends Component {
this.props.updateLoadingStatus(true);


const [agentsCount, clusterStatus, managerInfo, agentsCountByManagerNodes] = (await Promise.all([
const [{connection: agentsCount}, clusterStatus, managerInfo, agentsCountByManagerNodes] = (await Promise.all([
this.statusHandler.agentsSummary(),
this.statusHandler.clusterStatus(),
this.statusHandler.managerInfo(),
Expand Down
2 changes: 1 addition & 1 deletion public/controllers/overview/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ export class OverviewController {
*/
async getSummary() {
try {
const {data: { data }} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
const {data: { data: {connection: data} }} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
this.agentsCount = data;
this.welcomeCardsProps.agentsCountTotal = data.total;
this.agentsCoverity = data.total ? (data.active / data.total) * 100 : 0;
Expand Down