-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Alerting] replace watcher http APIs used by index threshold Alerting (…
…#59475) Prior to this PR, the alerting UI used two HTTP endpoints provided by the Kibana watcher plugin, to list index and field names. There are now two HTTP endpoints in the alerting_builtins plugin which will be used instead. The code for the new endpoints was largely copied from the existing watcher endpoints, and the HTTP request/response bodies kept pretty much the same. resolves #53041
- Loading branch information
Showing
12 changed files
with
685 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/fields.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
// the business logic of this code is from watcher, in: | ||
// x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts | ||
|
||
import { schema, TypeOf } from '@kbn/config-schema'; | ||
import { | ||
IRouter, | ||
RequestHandlerContext, | ||
KibanaRequest, | ||
IKibanaResponse, | ||
KibanaResponseFactory, | ||
IScopedClusterClient, | ||
} from 'kibana/server'; | ||
import { Service } from '../../../types'; | ||
|
||
const bodySchema = schema.object({ | ||
indexPatterns: schema.arrayOf(schema.string()), | ||
}); | ||
|
||
type RequestBody = TypeOf<typeof bodySchema>; | ||
|
||
export function createFieldsRoute(service: Service, router: IRouter, baseRoute: string) { | ||
const path = `${baseRoute}/_fields`; | ||
service.logger.debug(`registering indexThreshold route POST ${path}`); | ||
router.post( | ||
{ | ||
path, | ||
validate: { | ||
body: bodySchema, | ||
}, | ||
}, | ||
handler | ||
); | ||
async function handler( | ||
ctx: RequestHandlerContext, | ||
req: KibanaRequest<any, any, RequestBody, any>, | ||
res: KibanaResponseFactory | ||
): Promise<IKibanaResponse> { | ||
service.logger.debug(`route ${path} request: ${JSON.stringify(req.body)}`); | ||
|
||
let rawFields: RawFields; | ||
|
||
// special test for no patterns, otherwise all are returned! | ||
if (req.body.indexPatterns.length === 0) { | ||
return res.ok({ body: { fields: [] } }); | ||
} | ||
|
||
try { | ||
rawFields = await getRawFields(ctx.core.elasticsearch.dataClient, req.body.indexPatterns); | ||
} catch (err) { | ||
service.logger.debug(`route ${path} error: ${err.message}`); | ||
return res.internalError({ body: 'error getting field data' }); | ||
} | ||
|
||
const result = { fields: getFieldsFromRawFields(rawFields) }; | ||
|
||
service.logger.debug(`route ${path} response: ${JSON.stringify(result)}`); | ||
return res.ok({ body: result }); | ||
} | ||
} | ||
|
||
// RawFields is a structure with the following shape: | ||
// { | ||
// "fields": { | ||
// "_routing": { "_routing": { "type": "_routing", "searchable": true, "aggregatable": false}}, | ||
// "host": { "keyword": { "type": "keyword", "searchable": true, "aggregatable": true}}, | ||
// ... | ||
// } | ||
interface RawFields { | ||
fields: Record<string, Record<string, RawField>>; | ||
} | ||
|
||
interface RawField { | ||
type: string; | ||
searchable: boolean; | ||
aggregatable: boolean; | ||
} | ||
|
||
interface Field { | ||
name: string; | ||
type: string; | ||
normalizedType: string; | ||
searchable: boolean; | ||
aggregatable: boolean; | ||
} | ||
|
||
async function getRawFields( | ||
dataClient: IScopedClusterClient, | ||
indexes: string[] | ||
): Promise<RawFields> { | ||
const params = { | ||
index: indexes, | ||
fields: ['*'], | ||
ignoreUnavailable: true, | ||
allowNoIndices: true, | ||
ignore: 404, | ||
}; | ||
const result = await dataClient.callAsCurrentUser('fieldCaps', params); | ||
return result as RawFields; | ||
} | ||
|
||
function getFieldsFromRawFields(rawFields: RawFields): Field[] { | ||
const result: Field[] = []; | ||
|
||
if (!rawFields || !rawFields.fields) { | ||
return []; | ||
} | ||
|
||
for (const name of Object.keys(rawFields.fields)) { | ||
const rawField = rawFields.fields[name]; | ||
const type = Object.keys(rawField)[0]; | ||
const values = rawField[type]; | ||
|
||
if (!type || type.startsWith('_')) continue; | ||
if (!values) continue; | ||
|
||
const normalizedType = normalizedFieldTypes[type] || type; | ||
const aggregatable = values.aggregatable; | ||
const searchable = values.searchable; | ||
|
||
result.push({ name, type, normalizedType, aggregatable, searchable }); | ||
} | ||
|
||
result.sort((a, b) => a.name.localeCompare(b.name)); | ||
return result; | ||
} | ||
|
||
const normalizedFieldTypes: Record<string, string> = { | ||
long: 'number', | ||
integer: 'number', | ||
short: 'number', | ||
byte: 'number', | ||
double: 'number', | ||
float: 'number', | ||
half_float: 'number', | ||
scaled_float: 'number', | ||
}; |
22 changes: 22 additions & 0 deletions
22
x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* 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 { Service, IRouter } from '../../../types'; | ||
import { createTimeSeriesQueryRoute } from './time_series_query'; | ||
import { createFieldsRoute } from './fields'; | ||
import { createIndicesRoute } from './indices'; | ||
|
||
interface RegisterRoutesParams { | ||
service: Service; | ||
router: IRouter; | ||
baseRoute: string; | ||
} | ||
export function registerRoutes(params: RegisterRoutesParams) { | ||
const { service, router, baseRoute } = params; | ||
createTimeSeriesQueryRoute(service, router, baseRoute); | ||
createFieldsRoute(service, router, baseRoute); | ||
createIndicesRoute(service, router, baseRoute); | ||
} |
Oops, something went wrong.