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

[Fleet] Request diagnostics #142369

Merged
merged 41 commits into from
Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
0ec98c2
request diagnostics action API
juliaElastic Sep 30, 2022
af2e1d6
agent diagnostics action UI
juliaElastic Sep 30, 2022
7a47627
call diagnostics api when clicking button, added modal
juliaElastic Oct 3, 2022
03e6ab6
showing diagnostics uploads list with mock data
juliaElastic Oct 4, 2022
6cc9d88
Merge branch 'main' into feat/request-diagnostics
juliaElastic Oct 5, 2022
478c3d5
bulk request diagnostics
juliaElastic Oct 5, 2022
c559655
query action status to show diagnostics status
juliaElastic Oct 5, 2022
f36b539
fix for failed status display
juliaElastic Oct 5, 2022
c0dcc51
changed implementation to query files index in /uploads API
juliaElastic Oct 5, 2022
46b9000
Merge branch 'main' into feat/request-diagnostics
juliaElastic Oct 5, 2022
383c4bf
Merge branch 'main' into feat/request-diagnostics
kibanamachine Oct 5, 2022
e795a39
implemented file download
juliaElastic Oct 6, 2022
ed1a5d1
changed implementation to add downlaod headers for file
juliaElastic Oct 6, 2022
d537961
added toast when a diagnostics became ready
juliaElastic Oct 6, 2022
f165ee7
added tests on request diagnostics and uploads
juliaElastic Oct 7, 2022
a15ba47
fixed checks
juliaElastic Oct 7, 2022
4b7c5c5
fix checks
juliaElastic Oct 7, 2022
30e16aa
Merge branch 'main' into feat/request-diagnostics
kibanamachine Oct 10, 2022
6684a78
returning always octet stream when downloading file
juliaElastic Oct 10, 2022
63202fc
Merge branch 'main' into feat/request-diagnostics
kibanamachine Oct 12, 2022
6944bc2
Merge branch 'main' into feat/request-diagnostics
kibanamachine Oct 17, 2022
099b1d2
Merge branch 'main' into feat/request-diagnostics
kibanamachine Oct 19, 2022
fc1192b
Merge branch 'main' into feat/request-diagnostics
kibanamachine Oct 24, 2022
8c3d5d6
Merge branch 'main' into feat/request-diagnostics
juliaElastic Oct 31, 2022
e19e68c
Merge branch 'main' into feat/request-diagnostics
kibanamachine Oct 31, 2022
ccdca4a
Merge branch 'main' into feat/request-diagnostics
kibanamachine Nov 2, 2022
26ad93c
Merge branch 'main' into feat/request-diagnostics
kibanamachine Nov 2, 2022
02c6b5a
Merge branch 'main' into feat/request-diagnostics
juliaElastic Nov 2, 2022
f758d96
Update tsconfig.json
juliaElastic Nov 2, 2022
e61a15d
Merge branch 'main' into feat/request-diagnostics
kibanamachine Nov 7, 2022
22ad451
fixed test
juliaElastic Nov 7, 2022
0b56f04
Merge branch 'main' into feat/request-diagnostics
juliaElastic Nov 7, 2022
b164e02
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine Nov 7, 2022
448f0fa
Merge branch 'main' into feat/request-diagnostics
juliaElastic Nov 8, 2022
a486196
added feature flag to hide request diagnostics action
juliaElastic Nov 8, 2022
c0755cf
fixed checks
juliaElastic Nov 8, 2022
b3123fa
fixed test
juliaElastic Nov 8, 2022
820edee
removed mock data and changed the query to return diagnostic files
juliaElastic Nov 8, 2022
3cfaf2e
Merge branch 'main' into feat/request-diagnostics
juliaElastic Nov 8, 2022
d622ed3
fixed integration test
juliaElastic Nov 9, 2022
89888ae
added error handling, extracted index names as constants
juliaElastic Nov 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
} from '../../../hooks';
import { WithHeaderLayout } from '../../../layouts';

import { ExperimentalFeaturesService } from '../../../services';

import { AgentRefreshContext } from './hooks';
import {
AgentLogs,
Expand Down Expand Up @@ -66,6 +68,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => {
navigateToApp(routeState.onDoneNavigateTo[0], routeState.onDoneNavigateTo[1]);
}
}, [routeState, navigateToApp]);
const { showRequestDiagnostics } = ExperimentalFeaturesService.get();

const host = agentData?.item?.local_metadata?.host;

Expand Down Expand Up @@ -135,7 +138,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => {
);

const headerTabs = useMemo(() => {
return [
const tabs = [
{
id: 'details',
name: i18n.translate('xpack.fleet.agentDetails.subTabs.detailsTab', {
Expand All @@ -152,16 +155,19 @@ export const AgentDetailsPage: React.FunctionComponent = () => {
href: getHref('agent_details_logs', { agentId, tabId: 'logs' }),
isSelected: tabId === 'logs',
},
{
];
if (showRequestDiagnostics) {
tabs.push({
id: 'diagnostics',
name: i18n.translate('xpack.fleet.agentDetails.subTabs.diagnosticsTab', {
defaultMessage: 'Diagnostics',
}),
href: getHref('agent_details_diagnostics', { agentId, tabId: 'diagnostics' }),
isSelected: tabId === 'diagnostics',
},
];
}, [getHref, agentId, tabId]);
});
}
return tabs;
}, [getHref, agentId, tabId, showRequestDiagnostics]);

return (
<AgentRefreshContext.Provider
Expand Down
105 changes: 66 additions & 39 deletions x-pack/plugins/fleet/server/services/agents/uploads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,67 +15,56 @@ import type { ResponseHeaders } from '@kbn/core-http-server';

import type { AgentDiagnostics } from '../../../common/types/models';
import { appContextService } from '../app_context';
import { AGENT_ACTIONS_INDEX, agentRouteService } from '../../../common';
import {
AGENT_ACTIONS_INDEX,
agentRouteService,
AGENT_ACTIONS_RESULTS_INDEX,
} from '../../../common';

import { SO_SEARCH_LIMIT } from '../../constants';

export async function getAgentUploads(
esClient: ElasticsearchClient,
agentId: string
): Promise<AgentDiagnostics[]> {
// TODO filter agentId
const filesMetadata = await esClient.search({
index: '.fleet-agent-files',
size: 20,
});
const files = filesMetadata.hits.hits.map((hit) => ({
...(hit._source as any).file,
id: hit._id,
}));
const getFile = async (fileId: string) => {
if (!fileId) return;
const file = await esClient.get({
index: '.fleet-agent-files',
id: fileId,
});
return {
id: file._id,
...(file._source as any)?.file,
};
};

const actions = await _getRequestDiagnosticsActions(esClient, agentId);

const result = actions.map((action, index) => {
let file = files.find((item) => item.action_id === action.actionId);
// TODO mock, remove when files contain actionId
if (index === actions.length - 1) {
file = files[0];
}
const results = [];
for (const action of actions) {
const file = await getFile(action.fileId);
const fileName = file?.name ?? `${moment(action.timestamp!).format('YYYY-MM-DD HH:mm:ss')}.zip`;
const filePath = file ? agentRouteService.getAgentFileDownloadLink(file.id, file.name) : '';
return {
const result = {
actionId: action.actionId,
id: file?.id ?? action.actionId,
status: file?.Status ?? 'IN_PROGRESS',
name: fileName,
createTime: action.timestamp!,
filePath,
};
});

// TODO mock failed value
if (result.length > 0) {
result.push({
...result[0],
id: 'failed1',
status: 'FAILED',
});

// TODO mock simulating last in progress action turning ready if taken in last 10s
const diag = result.find((item) => item.status === 'IN_PROGRESS');
if (diag && new Date(diag.createTime).getTime() > Date.now() - 10000) {
diag.status = 'READY';
}
results.push(result);
}

return result;
return results;
}

async function _getRequestDiagnosticsActions(
esClient: ElasticsearchClient,
agentId: string
): Promise<Array<{ actionId: string; timestamp?: string }>> {
const res = await esClient.search<any>({
): Promise<Array<{ actionId: string; timestamp?: string; fileId: string }>> {
const agentActionRes = await esClient.search<any>({
index: AGENT_ACTIONS_INDEX,
ignore_unavailable: true,
size: SO_SEARCH_LIMIT,
Expand All @@ -97,10 +86,48 @@ async function _getRequestDiagnosticsActions(
},
});

return res.hits.hits.map((hit) => ({
actionId: hit._source?.action_id as string,
timestamp: hit._source?.['@timestamp'],
}));
const agentActionIds = agentActionRes.hits.hits.map((hit) => hit._source?.action_id as string);

if (agentActionIds.length === 0) {
return [];
}

try {
const actionResults = await esClient.search<any>({
index: AGENT_ACTIONS_RESULTS_INDEX,
ignore_unavailable: true,
size: SO_SEARCH_LIMIT,
query: {
bool: {
must: [
{
terms: {
action_id: agentActionIds,
},
},
{
term: {
agent_id: agentId,
},
},
],
},
},
});
return actionResults.hits.hits.map((hit) => ({
actionId: hit._source?.action_id as string,
timestamp: hit._source?.['@timestamp'],
fileId: hit._source?.data?.file_id as string,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

taking the file_id from action results, this part is not yet implemented, asked here: elastic/elastic-agent#1631 (comment)

}));
} catch (err) {
if (err.statusCode === 404) {
// .fleet-actions-results does not yet exist
appContextService.getLogger().debug(err);
return [];
} else {
throw err;
}
}
}

export async function getAgentUploadFile(
Expand Down