diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx
index 83d4760259d9bb..aa66febc5b7c43 100644
--- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx
+++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx
@@ -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';
@@ -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,
@@ -149,6 +155,7 @@ export const useLogAnalysisJobs = ({
viewSetupForReconfiguration,
viewSetupForUpdate,
viewResults,
+ jobIds,
};
};
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
index 33037aac9afe54..e846d4e9e4ac5e 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
@@ -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,
@@ -134,6 +134,7 @@ export const AnalysisResultsContent = ({
setupStatus,
viewSetupForReconfiguration,
viewSetupForUpdate,
+ jobIds,
} = useContext(LogAnalysisJobs.Context);
useInterval(() => {
@@ -214,6 +215,7 @@ export const AnalysisResultsContent = ({
setTimeRange={handleChartTimeRangeChange}
setupStatus={setupStatus}
timeRange={queryTimeRange}
+ jobId={jobIds['log-entry-rate']}
/>
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx
new file mode 100644
index 00000000000000..852ce20e37d418
--- /dev/null
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx
@@ -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 = (
+
+ );
+ return partition ? (
+
+ {buttonLabel}
+
+ ) : (
+
+ {buttonLabel}
+
+ );
+};
+
+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(),
+ };
+};
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/expanded_row.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/expanded_row.tsx
index a6f2ca71068c27..43cfbb306717d1 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/expanded_row.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/expanded_row.tsx
@@ -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';
@@ -17,6 +17,7 @@ import {
formatAnomalyScore,
getTotalNumberOfLogEntriesForPartition,
} from '../helpers/data_formatters';
+import { AnalyzeInMlButton } from '../analyze_in_ml_button';
export const AnomaliesTableExpandedRow: React.FunctionComponent<{
partitionId: string;
@@ -24,7 +25,8 @@ export const AnomaliesTableExpandedRow: React.FunctionComponent<{
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
@@ -83,6 +85,12 @@ export const AnomaliesTableExpandedRow: React.FunctionComponent<{
)}
reverse
/>
+
+
+
+
+
+
);
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
index 1bba8995f0c76a..5aa5891d7981d6 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
@@ -5,7 +5,6 @@
*/
import {
- EuiButton,
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
@@ -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';
@@ -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;
@@ -42,6 +41,7 @@ export const AnomaliesResults: React.FunctionComponent<{
timeRange: TimeRange;
viewSetupForReconfiguration: () => void;
viewSetupForUpdate: () => void;
+ jobId: string;
}> = ({
isLoading,
jobStatus,
@@ -51,6 +51,7 @@ export const AnomaliesResults: React.FunctionComponent<{
timeRange,
viewSetupForReconfiguration,
viewSetupForUpdate,
+ jobId,
}) => {
const title = i18n.translate('xpack.infra.logs.analysis.anomaliesSectionTitle', {
defaultMessage: 'Anomalies',
@@ -105,12 +106,7 @@ export const AnomaliesResults: React.FunctionComponent<{
-
-
-
+
@@ -193,7 +189,12 @@ export const AnomaliesResults: React.FunctionComponent<{
-
+
>
)}
>
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx
index 2a8ac44d09083b..88ffcae6e9dea1 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx
@@ -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 {
@@ -112,6 +113,7 @@ export const AnomaliesTable: React.FunctionComponent<{
topAnomalyScore={item.topAnomalyScore}
setTimeRange={setTimeRange}
timeRange={timeRange}
+ jobId={jobId}
/>
),
};
diff --git a/x-pack/legacy/plugins/infra/public/utils/use_kibana_injected_var.ts b/x-pack/legacy/plugins/infra/public/utils/use_kibana_injected_var.ts
index bcd36f72bef076..4afcb4fd884303 100644
--- a/x-pack/legacy/plugins/infra/public/utils/use_kibana_injected_var.ts
+++ b/x-pack/legacy/plugins/infra/public/utils/use_kibana_injected_var.ts
@@ -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);
};