Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -8,7 +8,7 @@ import createContainer from 'constate-latest';
import { useMemo, useCallback, useEffect } from 'react';

import { callGetMlModuleAPI } from './api/ml_get_module';
import { bucketSpan } from '../../../../common/log_analysis';
import { bucketSpan, getJobId } from '../../../../common/log_analysis';
import { useTrackedPromise } from '../../../utils/use_tracked_promise';
import { callJobsSummaryAPI } from './api/ml_get_jobs_summary_api';
import { callSetupMlModuleAPI, SetupMlModuleResponsePayload } from './api/ml_setup_module_api';
Expand Down Expand Up @@ -138,6 +138,12 @@ export const useLogAnalysisJobs = ({
fetchModuleDefinition();
}, [fetchModuleDefinition]);

const jobIds = useMemo(() => {
return {
'log-entry-rate': getJobId(spaceId, sourceId, 'log-entry-rate'),
};
}, [sourceId, spaceId]);

return {
fetchJobStatus,
isLoadingSetupStatus,
Expand All @@ -149,6 +155,7 @@ export const useLogAnalysisJobs = ({
viewSetupForReconfiguration,
viewSetupForUpdate,
viewResults,
jobIds,
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import numeral from '@elastic/numeral';
import { FormattedMessage } from '@kbn/i18n/react';
import moment from 'moment';
import React, { useCallback, useContext, useMemo, useState } from 'react';
import euiStyled from '../../../../../../common/eui_styled_components';
import { TimeRange } from '../../../../common/http_api/shared/time_range';
import { bucketSpan } from '../../../../common/log_analysis';
import euiStyled from '../../../../../../common/eui_styled_components';
import { LoadingPage } from '../../../components/loading_page';
import {
LogAnalysisJobs,
Expand Down Expand Up @@ -134,6 +134,7 @@ export const AnalysisResultsContent = ({
setupStatus,
viewSetupForReconfiguration,
viewSetupForUpdate,
jobIds,
} = useContext(LogAnalysisJobs.Context);

useInterval(() => {
Expand Down Expand Up @@ -214,6 +215,7 @@ export const AnalysisResultsContent = ({
setTimeRange={handleChartTimeRangeChange}
setupStatus={setupStatus}
timeRange={queryTimeRange}
jobId={jobIds['log-entry-rate']}
/>
</EuiPanel>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import url from 'url';
import { EuiButton } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import chrome from 'ui/chrome';
import { QueryString } from 'ui/utils/query_string';
import { encode } from 'rison-node';
import { TimeRange } from '../../../../../common/http_api/shared/time_range';

export const AnalyzeInMlButton: React.FunctionComponent<{
jobId: string;
partition?: string;
timeRange: TimeRange;
}> = ({ jobId, partition, timeRange }) => {
const pathname = chrome.addBasePath('/app/ml');
const buttonLabel = (
<FormattedMessage
id="xpack.infra.logs.analysis.analyzeInMlButtonLabel"
defaultMessage="Analyze in ML"
/>
);
return partition ? (
<EuiButton
fill={false}
href={getPartitionSpecificSingleMetricViewerLink(pathname, jobId, partition, timeRange)}
>
{buttonLabel}
</EuiButton>
) : (
<EuiButton fill={true} href={getOverallAnomalyExplorerLink(pathname, jobId, timeRange)}>
{buttonLabel}
</EuiButton>
);
};

const getOverallAnomalyExplorerLink = (pathname: string, jobId: string, timeRange: TimeRange) => {
const { from, to } = convertTimeRangeToParams(timeRange);

const _g = encode({
ml: {
jobIds: [jobId],
},
time: {
from,
to,
},
});

const hash = `/explorer?${QueryString.encode({ _g })}`;

return url.format({
pathname,
hash,
});
};

const getPartitionSpecificSingleMetricViewerLink = (
pathname: string,
jobId: string,
partition: string,
timeRange: TimeRange
) => {
const { from, to } = convertTimeRangeToParams(timeRange);

const _g = encode({
ml: {
jobIds: [jobId],
},
time: {
from,
to,
mode: 'absolute',
},
});

const _a = encode({
mlTimeSeriesExplorer: {
entities: { 'event.dataset': partition },
},
});

const hash = `/timeseriesexplorer?${QueryString.encode({ _g, _a })}`;

return url.format({
pathname,
hash,
});
};

const convertTimeRangeToParams = (timeRange: TimeRange): { from: string; to: string } => {
return {
from: new Date(timeRange.startTime).toISOString(),
to: new Date(timeRange.endTime).toISOString(),
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import numeral from '@elastic/numeral';
import { EuiFlexGroup, EuiFlexItem, EuiStat } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiStat, EuiSpacer } from '@elastic/eui';
import { AnomaliesChart } from './chart';
import { GetLogEntryRateSuccessResponsePayload } from '../../../../../../common/http_api/log_analysis/results/log_entry_rate';
import { TimeRange } from '../../../../../../common/http_api/shared/time_range';
Expand All @@ -17,14 +17,16 @@ import {
formatAnomalyScore,
getTotalNumberOfLogEntriesForPartition,
} from '../helpers/data_formatters';
import { AnalyzeInMlButton } from '../analyze_in_ml_button';

export const AnomaliesTableExpandedRow: React.FunctionComponent<{
partitionId: string;
topAnomalyScore: number;
results: GetLogEntryRateSuccessResponsePayload['data'];
setTimeRange: (timeRange: TimeRange) => void;
timeRange: TimeRange;
}> = ({ results, timeRange, setTimeRange, topAnomalyScore, partitionId }) => {
jobId: string;
}> = ({ results, timeRange, setTimeRange, topAnomalyScore, partitionId, jobId }) => {
const logEntryRateSeries = useMemo(
() =>
results && results.histogramBuckets
Expand Down Expand Up @@ -83,6 +85,12 @@ export const AnomaliesTableExpandedRow: React.FunctionComponent<{
)}
reverse
/>
<EuiSpacer size="s" />
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<AnalyzeInMlButton jobId={jobId} timeRange={timeRange} partition={partitionId} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import {
EuiButton,
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
Expand All @@ -16,7 +15,6 @@ import {
} from '@elastic/eui';
import numeral from '@elastic/numeral';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { useMemo } from 'react';

import euiStyled from '../../../../../../../../common/eui_styled_components';
Expand All @@ -32,6 +30,7 @@ import {
import { AnomaliesChart } from './chart';
import { AnomaliesTable } from './table';
import { LogAnalysisJobProblemIndicator } from '../../../../../components/logging/log_analysis_job_status';
import { AnalyzeInMlButton } from '../analyze_in_ml_button';

export const AnomaliesResults: React.FunctionComponent<{
isLoading: boolean;
Expand All @@ -42,6 +41,7 @@ export const AnomaliesResults: React.FunctionComponent<{
timeRange: TimeRange;
viewSetupForReconfiguration: () => void;
viewSetupForUpdate: () => void;
jobId: string;
}> = ({
isLoading,
jobStatus,
Expand All @@ -51,6 +51,7 @@ export const AnomaliesResults: React.FunctionComponent<{
timeRange,
viewSetupForReconfiguration,
viewSetupForUpdate,
jobId,
}) => {
const title = i18n.translate('xpack.infra.logs.analysis.anomaliesSectionTitle', {
defaultMessage: 'Anomalies',
Expand Down Expand Up @@ -105,12 +106,7 @@ export const AnomaliesResults: React.FunctionComponent<{
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton fill>
<FormattedMessage
id="xpack.infra.logs.analysis.analyzeInMlButtonLabel"
defaultMessage="Analyze in ML"
/>
</EuiButton>
<AnalyzeInMlButton jobId={jobId} timeRange={timeRange} />
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
Expand Down Expand Up @@ -193,7 +189,12 @@ export const AnomaliesResults: React.FunctionComponent<{
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="l" />
<AnomaliesTable results={results} setTimeRange={setTimeRange} timeRange={timeRange} />
<AnomaliesTable
results={results}
setTimeRange={setTimeRange}
timeRange={timeRange}
jobId={jobId}
/>
</>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export const AnomaliesTable: React.FunctionComponent<{
results: GetLogEntryRateSuccessResponsePayload['data'];
setTimeRange: (timeRange: TimeRange) => void;
timeRange: TimeRange;
}> = ({ results, timeRange, setTimeRange }) => {
jobId: string;
}> = ({ results, timeRange, setTimeRange, jobId }) => {
const tableItems: TableItem[] = useMemo(() => {
return Object.entries(getTopAnomalyScoresByPartition(results)).map(([key, value]) => {
return {
Expand Down Expand Up @@ -112,6 +113,7 @@ export const AnomaliesTable: React.FunctionComponent<{
topAnomalyScore={item.topAnomalyScore}
setTimeRange={setTimeRange}
timeRange={timeRange}
jobId={jobId}
/>
),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ import { npSetup } from 'ui/new_platform';
*/
export const useKibanaInjectedVar = (name: string, defaultValue?: unknown) => {
const injectedMetadata = npSetup.core.injectedMetadata;

return injectedMetadata.getInjectedVar(name, defaultValue);
};