Skip to content

Commit 4f5b60a

Browse files
committed
Fixes FTUE when APM node is present
1 parent 3c2c689 commit 4f5b60a

File tree

3 files changed

+78
-16
lines changed

3 files changed

+78
-16
lines changed

x-pack/legacy/plugins/siem/server/lib/source_status/elasticsearch_adapter.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,50 @@
66

77
import { FrameworkAdapter, FrameworkRequest } from '../framework';
88
import { SourceStatusAdapter } from './index';
9+
import { buildQuery } from './query.dsl';
10+
import { ApmServiceNameAgg } from './types';
11+
12+
const APM_INDEX_NAME = 'apm-*-transaction*';
913

1014
export class ElasticsearchSourceStatusAdapter implements SourceStatusAdapter {
1115
constructor(private readonly framework: FrameworkAdapter) {}
1216

13-
public async hasIndices(request: FrameworkRequest, indexNames: string | string[]) {
14-
return this.framework
15-
.callWithRequest(request, 'search', {
16-
index: indexNames,
17-
size: 0,
18-
terminate_after: 1,
19-
allow_no_indices: true,
20-
})
21-
.then(
22-
response => response._shards.total > 0,
23-
err => {
24-
if (err.status === 404) {
25-
return false;
26-
}
27-
throw err;
28-
}
17+
public async hasIndices(request: FrameworkRequest, indexNames: string[]) {
18+
// Note: Additional check necessary for APM-specific index. For details see: https://github.com/elastic/kibana/issues/56363
19+
// Only verify if APM data exists if indexNames includes `apm-*-transaction*` (default included apm index)
20+
const includesApmIndex = indexNames.includes(APM_INDEX_NAME);
21+
const hasApmDataReq = includesApmIndex
22+
? this.framework.callWithRequest<{}, ApmServiceNameAgg>(
23+
request,
24+
'search',
25+
buildQuery({ defaultIndex: [APM_INDEX_NAME] })
26+
)
27+
: Promise.resolve(undefined);
28+
29+
// Remove APM index if exists, and only query if length > 0 in case it's the only index provided
30+
const nonApmIndexNameArray = indexNames.filter(name => name !== APM_INDEX_NAME);
31+
const indexCheckReq =
32+
nonApmIndexNameArray.length > 0
33+
? this.framework.callWithRequest(request, 'search', {
34+
index: nonApmIndexNameArray,
35+
size: 0,
36+
terminate_after: 1,
37+
allow_no_indices: true,
38+
})
39+
: Promise.resolve(undefined);
40+
41+
try {
42+
const [apmResponse, indexCheckResponse] = await Promise.all([hasApmDataReq, indexCheckReq]);
43+
44+
return (
45+
(apmResponse?.aggregations?.total_service_names?.value ?? -1) > 0 ||
46+
(indexCheckResponse?._shards.total ?? -1) > 0
2947
);
48+
} catch (err) {
49+
if (err.status === 404) {
50+
return false;
51+
}
52+
throw err;
53+
}
3054
}
3155
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
const SERVICE_NAME = 'service.name';
8+
9+
export const buildQuery = ({ defaultIndex }: { defaultIndex: string[] }) => {
10+
return {
11+
allowNoIndices: true,
12+
index: defaultIndex,
13+
ignoreUnavailable: true,
14+
terminate_after: 1,
15+
body: {
16+
size: 0,
17+
aggs: {
18+
total_service_names: {
19+
cardinality: {
20+
field: SERVICE_NAME,
21+
},
22+
},
23+
},
24+
},
25+
track_total_hits: false,
26+
};
27+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export interface ApmServiceNameAgg {
8+
total_service_names: {
9+
value: number;
10+
};
11+
}

0 commit comments

Comments
 (0)