[Stack Monitoring] Collect metrics errors in health api (#148750)

Closes https://github.com/elastic/kibana/issues/140358

## Summary
This PR adds integration package errors to the `_health` endpoint. The
response should look similar to the metricbeat one we already have. The
difference will be that the package will use `data_stream.dataset`
instead of `metricset.name`

## Testing

1. Setup an integration
- Follow this
[guide](0e924730cc/docs/infra-obs-ui/stack-monitoring_integration-packages.md)
to install the package. ~~⚠️ Note that you need to have `metricset.name`
mapping to see the errors added in this
[PR](https://github.com/elastic/integrations/pull/4973)~~ - No need
anymore as we use `data_stream.dataset` for packages
2. Installing the package: 
- In this case, we want to enable metrics and set the Agent policy to
Elastic-Agent (elastic-package). To see an error I used the wrong host
URL (inside `Change Defaults`) when I was configuring the elasticsearch
integration:
 
<img width="1313" alt="image"
src="https://user-images.githubusercontent.com/14139027/212313537-f1f6f5b1-6e4d-40f2-8f78-9f0e5f48c434.png">

3. To see the package errors run `curl --user elastic:changeme
http://localhost:5602/ftw/api/monitoring/v1/_health` or open
http://localhost:5602/ftw/api/monitoring/v1/_health in a browser where
you are logged in in your kibana. (The port of the kibana is 5602 as
mentioned in the
[guide](0e924730cc/docs/infra-obs-ui/stack-monitoring_integration-packages.md (connecting-a-local-kibana))
this will be your local kibana running - I recommend to add the package
to the elastic package kibana running on 5601 and to run your local
kibana after the setup is complete)
 
Example response:
```
{
    "metricbeatErrors": {
        ...
    },
    "packageErrors": {
        "products": {
            "elasticsearch": {
                "elasticsearch.stack_monitoring.node": [
                    {
                        "message": "error making http request: Get \"http://localhost:9200/_nodes/_local\": dial tcp 127.0.0.1:9200: connect: connection refused",
                        "lastSeen": "2023-01-12T17:27:01.862Z"
                    }
                ],
                "elasticsearch.stack_monitoring.node_stats": [
                    {
                        "message": "error making http request: Get \"http://localhost:9200/_nodes/_local/stats\": dial tcp [::1]:9200: connect: cannot assign requested address",
                        "lastSeen": "2023-01-12T17:26:31.883Z"
                    }
                ],
                .....
            },
            "execution": {
                "timedOut": false,
                "errors": []
            }
        }
    }
}
```
This commit is contained in:
jennypavlova 2023-01-17 14:01:18 +01:00 committed by GitHub
parent 4bdf1d4b0c
commit 066ee1c9e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 1975 additions and 105 deletions

View file

@ -12,3 +12,4 @@ The response includes sections that can provide useful informations in a debuggi
- settings: a subset of the kibana.yml settings relevant to stack monitoring
- monitoredClusters: a representation of the monitoring documents available to the running kibana. It exposes which metricsets are collected by what collection mode and when was the last time it was ingested. The query groups the metricsets by products and can help identify missing documents that could explain why a page is not loading or crashing
- metricbeatErrors: a list of errors encountered by metricbeat processes when collecting data
- packageErrors: a list of errors encountered by integration package processes when collecting data

View file

@ -0,0 +1,141 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { buildErrors } from './build_errors';
import assert from 'assert';
describe(__filename, () => {
describe('buildErrors', () => {
test('Metricbeat: it should build an object containing dedup error messages per event.dataset', () => {
const metricbeatErrors = [
{
key: 'beat',
errors_by_dataset: {
buckets: [
{
key: 'state',
latest_docs: {
hits: {
hits: [
{
_source: {
'@timestamp': '2022-07-26T08:43:32.625Z',
error: {
message:
'error making http request: Get "http://host.docker.internal:5067/state": dial tcp 192.168.65.2:5067: connect: connection refused',
},
},
},
{
_source: {
'@timestamp': '2022-07-26T08:42:32.625Z',
error: {
message:
'error making http request: Get "http://host.docker.internal:5067/state": dial tcp 192.168.65.2:5067: connect: connection refused',
},
},
},
{
_source: {
'@timestamp': '2022-07-26T08:41:32.625Z',
error: {
message: 'Generic random error',
},
},
},
],
},
},
},
],
},
},
];
const monitoredClusters = buildErrors(metricbeatErrors);
assert.deepEqual(monitoredClusters, {
beat: {
state: [
{
lastSeen: '2022-07-26T08:43:32.625Z',
message:
'error making http request: Get "http://host.docker.internal:5067/state": dial tcp 192.168.65.2:5067: connect: connection refused',
},
{
lastSeen: '2022-07-26T08:41:32.625Z',
message: 'Generic random error',
},
],
},
});
});
test('Packages: it should build an object containing dedup error messages per event.dataset', () => {
const packageErrors = [
{
key: 'elasticsearch',
errors_by_dataset: {
buckets: [
{
key: 'state',
latest_docs: {
hits: {
hits: [
{
_source: {
'@timestamp': '2023-01-10T14:39:37.114Z',
error: {
message:
'error making http request: Get "https://localhost:9200/_nodes/_local": dial tcp [::1]:9200: connect: cannot assign requested address',
},
},
},
{
_source: {
'@timestamp': '2023-01-10T14:39:27.114Z',
error: {
message:
'error making http request: Get "https://localhost:9200/_nodes/_local": dial tcp [::1]:9200: connect: cannot assign requested address',
},
},
},
{
_source: {
'@timestamp': '2022-07-26T08:41:32.625Z',
error: {
message: 'Generic random error',
},
},
},
],
},
},
},
],
},
},
];
const monitoredClusters = buildErrors(packageErrors);
assert.deepEqual(monitoredClusters, {
elasticsearch: {
state: [
{
lastSeen: '2023-01-10T14:39:37.114Z',
message:
'error making http request: Get "https://localhost:9200/_nodes/_local": dial tcp [::1]:9200: connect: cannot assign requested address',
},
{
lastSeen: '2022-07-26T08:41:32.625Z',
message: 'Generic random error',
},
],
},
});
});
});
});

View file

@ -5,10 +5,10 @@
* 2.0.
*/
import type { MetricbeatMonitoredProduct } from '../types';
import type { MonitoredProduct } from '../types';
export type MetricbeatProducts = {
[product in MetricbeatMonitoredProduct]?: ErrorsByMetricset;
export type Products = {
[product in MonitoredProduct]?: ErrorsByMetricset;
};
interface ErrorsByMetricset {
@ -21,14 +21,14 @@ interface ErrorDetails {
}
/**
* builds a normalized representation of the metricbeat errors from the provided
* builds a normalized representation of the metricbeat and integration package errors from the provided
* query buckets with a product->metricset hierarchy where
* product: the monitored products (eg elasticsearch)
* metricset: the collected metricsets for a given entity
*
* example:
* {
* "product": {
* "products": {
* "logstash": {
* "node": {
* "message": "some error message",
@ -38,7 +38,7 @@ interface ErrorDetails {
* }
* }
*/
export const buildMetricbeatErrors = (modulesBucket: any[]): MetricbeatProducts => {
export const buildErrors = (modulesBucket: any[]): Products => {
return (modulesBucket ?? []).reduce((module, { key, errors_by_dataset: errorsByDataset }) => {
const datasets = buildMetricsets(errorsByDataset.buckets);
if (Object.keys(datasets).length === 0) {
@ -49,7 +49,7 @@ export const buildMetricbeatErrors = (modulesBucket: any[]): MetricbeatProducts
...module,
[key]: datasets,
};
}, {} as MetricbeatProducts);
}, {} as Products);
};
const buildMetricsets = (errorsByDataset: any[]): ErrorsByMetricset => {

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { MetricbeatMonitoredProduct, QueryOptions } from '../types';
import type { MetricbeatMonitoredProduct, PackagesMonitoredProduct, QueryOptions } from '../types';
const MAX_BUCKET_SIZE = 50;
@ -13,16 +13,20 @@ const MAX_BUCKET_SIZE = 50;
* Returns a nested aggregation of error messages per event.datasets.
* Each module (beats, kibana...) can contain one or multiple metricsets with error messages
*/
interface MetricbeatErrorsQueryOptions extends QueryOptions {
products: MetricbeatMonitoredProduct[];
interface ErrorsQueryOptions extends QueryOptions {
products: MetricbeatMonitoredProduct[] | PackagesMonitoredProduct[];
errorQueryType: 'metricbeatErrorsQuery' | 'packageErrorsQuery';
errorQueryIsDataStream?: boolean;
}
export const metricbeatErrorsQuery = ({
export const errorsQuery = ({
timeRange,
timeout,
products,
}: MetricbeatErrorsQueryOptions) => {
if (!timeRange) throw new Error('metricbeatErrorsQuery: missing timeRange parameter');
errorQueryType,
errorQueryIsDataStream,
}: ErrorsQueryOptions) => {
if (!timeRange) throw new Error(`${errorQueryType}: missing timeRange parameter`);
return {
timeout: `${timeout}s`,
query: {
@ -37,7 +41,8 @@ export const metricbeatErrorsQuery = ({
},
{
terms: {
'event.module': Object.values(products),
[errorQueryIsDataStream ? 'service.type' : 'event.module']:
Object.values(products),
},
},
{
@ -54,7 +59,7 @@ export const metricbeatErrorsQuery = ({
},
},
aggs: {
errors_aggregation: errorsAggregation,
errors_aggregation: errorsAggregation(errorQueryIsDataStream),
},
};
};
@ -82,11 +87,34 @@ const errorsByMetricset = {
},
};
const errorsAggregation = {
const errorsByDataStream = {
terms: {
field: 'event.module',
field: 'data_stream.dataset',
},
aggs: {
errors_by_dataset: errorsByMetricset,
latest_docs: {
top_hits: {
sort: [
{
'@timestamp': {
order: 'desc',
},
},
],
size: MAX_BUCKET_SIZE,
_source: {
includes: ['@timestamp', 'error', 'data_stream'],
},
},
},
},
};
const errorsAggregation = (errorQueryIsDataStream?: boolean) => ({
terms: {
field: errorQueryIsDataStream ? 'service.type' : 'event.module',
},
aggs: {
errors_by_dataset: errorQueryIsDataStream ? errorsByDataStream : errorsByMetricset,
},
});

View file

@ -8,13 +8,14 @@
import type { LegacyRequest, MonitoringCore } from '../../../../types';
import type { MonitoringConfig } from '../../../../config';
import { createValidationFunction } from '../../../../lib/create_route_validation_function';
import { getIndexPatterns } from '../../../../lib/cluster/get_index_patterns';
import { getIndexPatterns, getDsIndexPattern } from '../../../../lib/cluster/get_index_patterns';
import { getHealthRequestQueryRT } from '../../../../../common/http_api/_health';
import type { TimeRange } from '../../../../../common/http_api/shared';
import { fetchMonitoredClusters } from './monitored_clusters';
import { fetchMetricbeatErrors } from './metricbeat';
import type { FetchParameters } from './types';
import { fetchPackageErrors } from './package/fetch_package_errors';
const DEFAULT_QUERY_TIMERANGE = { min: 'now-15m', max: 'now' };
const DEFAULT_QUERY_TIMEOUT_SECONDS = 15;
@ -53,6 +54,14 @@ export function registerV1HealthRoute(server: MonitoringCore) {
getIndexPatterns({ config, moduleType: 'logstash' }),
getIndexPatterns({ config, moduleType: 'beats' }),
].join(',');
const metricsPackageIndex = [
getDsIndexPattern({ config, moduleType: 'elasticsearch' }),
getDsIndexPattern({ config, moduleType: 'kibana' }),
getDsIndexPattern({ config, moduleType: 'logstash' }),
getDsIndexPattern({ config, moduleType: 'beats' }),
].join(',');
const entSearchIndex = getIndexPatterns({ config, moduleType: 'enterprise_search' });
const monitoredClustersFn = () =>
@ -74,12 +83,22 @@ export function registerV1HealthRoute(server: MonitoringCore) {
return { error: err.message };
});
const [monitoredClusters, metricbeatErrors] = await Promise.all([
const packageErrorsFn = () =>
fetchPackageErrors({
...fetchArgs,
packageIndex: metricsPackageIndex,
}).catch((err: Error) => {
logger.error(`_health: failed to retrieve package data:\n${err.stack}`);
return { error: err.message };
});
const [monitoredClusters, metricbeatErrors, packageErrors] = await Promise.all([
monitoredClustersFn(),
metricbeatErrorsFn(),
packageErrorsFn(),
]);
return { monitoredClusters, metricbeatErrors, settings };
return { monitoredClusters, metricbeatErrors, packageErrors, settings };
},
});
}

View file

@ -1,77 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { buildMetricbeatErrors } from './build_metricbeat_errors';
import assert from 'assert';
describe(__filename, () => {
describe('buildMetricbeatErrors', () => {
test('it should build an object containing dedup error messages per event.dataset', () => {
const metricbeatErrors = [
{
key: 'beat',
errors_by_dataset: {
buckets: [
{
key: 'state',
latest_docs: {
hits: {
hits: [
{
_source: {
'@timestamp': '2022-07-26T08:43:32.625Z',
error: {
message:
'error making http request: Get "http://host.docker.internal:5067/state": dial tcp 192.168.65.2:5067: connect: connection refused',
},
},
},
{
_source: {
'@timestamp': '2022-07-26T08:42:32.625Z',
error: {
message:
'error making http request: Get "http://host.docker.internal:5067/state": dial tcp 192.168.65.2:5067: connect: connection refused',
},
},
},
{
_source: {
'@timestamp': '2022-07-26T08:41:32.625Z',
error: {
message: 'Generic random error',
},
},
},
],
},
},
},
],
},
},
];
const monitoredClusters = buildMetricbeatErrors(metricbeatErrors);
assert.deepEqual(monitoredClusters, {
beat: {
state: [
{
lastSeen: '2022-07-26T08:43:32.625Z',
message:
'error making http request: Get "http://host.docker.internal:5067/state": dial tcp 192.168.65.2:5067: connect: connection refused',
},
{
lastSeen: '2022-07-26T08:41:32.625Z',
message: 'Generic random error',
},
],
},
});
});
});
});

View file

@ -7,13 +7,13 @@
import { FetchParameters, FetchExecution, MonitoredProduct } from '../types';
import type { MetricbeatProducts } from './build_metricbeat_errors';
import type { Products } from '../errors_helpers/build_errors';
import { metricbeatErrorsQuery } from './metricbeat_errors_query';
import { buildMetricbeatErrors } from './build_metricbeat_errors';
import { errorsQuery } from '../errors_helpers/errors_query';
import { buildErrors } from '../errors_helpers/build_errors';
interface MetricbeatResponse {
products?: MetricbeatProducts;
products?: Products;
execution: FetchExecution;
}
@ -29,7 +29,7 @@ export const fetchMetricbeatErrors = async ({
const getMetricbeatErrors = async () => {
const { aggregations, timed_out: timedOut } = await search({
index: metricbeatIndex,
body: metricbeatErrorsQuery({
body: errorsQuery({
timeRange,
timeout,
products: [
@ -39,12 +39,13 @@ export const fetchMetricbeatErrors = async ({
MonitoredProduct.Kibana,
MonitoredProduct.Logstash,
],
errorQueryType: 'metricbeatErrorsQuery',
}),
size: 0,
ignore_unavailable: true,
});
const buckets = aggregations?.errors_aggregation?.buckets ?? [];
return { products: buildMetricbeatErrors(buckets), timedOut: Boolean(timedOut) };
return { products: buildErrors(buckets), timedOut: Boolean(timedOut) };
};
try {

View file

@ -0,0 +1,143 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import assert from 'assert';
import sinon from 'sinon';
import type { Logger } from '@kbn/core/server';
import { fetchPackageErrors } from './fetch_package_errors';
const getMockLogger = () =>
({
warn: sinon.spy(),
error: sinon.spy(),
} as unknown as Logger);
describe(__filename, () => {
describe('fetchPackageErrors', () => {
test('it fetch and build package errors response', async () => {
const response = {
aggregations: {
errors_aggregation: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'elasticsearch',
doc_count: 22,
errors_by_dataset: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'elasticsearch.stack_monitoring.pending_tasks',
doc_count: 22,
latest_docs: {
hits: {
total: {
value: 22,
relation: 'eq',
},
max_score: null,
hits: [
{
_index:
'.ds-metrics-elasticsearch.stack_monitoring.node-default-2023.01.10-000001',
_id: '-oAfnIUB94omKO-pWCeN',
_score: null,
_source: {
'@timestamp': '2023-01-10T14:39:37.114Z',
metricset: {
period: 10000,
name: 'node',
},
error: {
message:
'error making http request: Get "https://localhost:9200/_nodes/_local": dial tcp [::1]:9200: connect: cannot assign requested address',
},
},
},
],
},
},
},
{
key: 'elasticsearch.stack_monitoring.node',
doc_count: 22,
latest_docs: {
hits: {
total: {
value: 22,
relation: 'eq',
},
max_score: null,
hits: [
{
_index:
'.ds-metrics-elasticsearch.stack_monitoring.node-default-2023.01.10-000001',
_id: '-oAfnIUB94omKO-pWCeN',
_score: null,
_source: {
'@timestamp': '2023-01-10T14:39:37.156Z',
metricset: {
period: 10000,
name: 'node',
},
error: {
message:
'error making http request: Get "https://localhost:9200/_nodes/_local": dial tcp [::1]:9200: connect: cannot assign requested address',
},
},
},
],
},
},
},
],
},
},
],
},
},
};
const searchFn = jest.fn().mockResolvedValueOnce(response);
const monitoredClusters = await fetchPackageErrors({
timeout: 10,
timeRange: { min: 1673361577110, max: 1673361567118 },
packageIndex: 'metrics-*',
search: searchFn,
logger: getMockLogger(),
});
assert.deepEqual(monitoredClusters, {
execution: {
timedOut: false,
errors: [],
},
products: {
elasticsearch: {
'elasticsearch.stack_monitoring.node': [
{
message:
'error making http request: Get "https://localhost:9200/_nodes/_local": dial tcp [::1]:9200: connect: cannot assign requested address',
lastSeen: '2023-01-10T14:39:37.156Z',
},
],
'elasticsearch.stack_monitoring.pending_tasks': [
{
message:
'error making http request: Get "https://localhost:9200/_nodes/_local": dial tcp [::1]:9200: connect: cannot assign requested address',
lastSeen: '2023-01-10T14:39:37.114Z',
},
],
},
},
});
});
});
});

View file

@ -0,0 +1,69 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FetchParameters, FetchExecution, MonitoredProduct } from '../types';
import type { Products } from '../errors_helpers/build_errors';
import { errorsQuery } from '../errors_helpers/errors_query';
import { buildErrors } from '../errors_helpers/build_errors';
interface PackageResponse {
products?: Products;
execution: FetchExecution;
}
export const fetchPackageErrors = async ({
timeout,
timeRange,
search,
logger,
packageIndex,
}: FetchParameters & {
packageIndex: string;
}): Promise<PackageResponse> => {
const getPackageErrors = async () => {
const { aggregations, timed_out: timedOut } = await search({
index: packageIndex,
body: errorsQuery({
timeRange,
timeout,
products: [
MonitoredProduct.Beats,
MonitoredProduct.Elasticsearch,
MonitoredProduct.Kibana,
MonitoredProduct.Logstash,
],
errorQueryType: 'packageErrorsQuery',
errorQueryIsDataStream: true,
}),
size: 0,
ignore_unavailable: true,
});
const buckets = aggregations?.errors_aggregation?.buckets ?? [];
return { products: buildErrors(buckets), timedOut: Boolean(timedOut) };
};
try {
const { products, timedOut } = await getPackageErrors();
return {
products,
execution: {
timedOut,
errors: [],
},
};
} catch (err) {
logger.error(`fetchPackageErrors: failed to fetch:\n${err.stack}`);
return {
execution: {
timedOut: false,
errors: [err.message],
},
};
}
};

View file

@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export { fetchPackageErrors } from './fetch_package_errors';

View file

@ -18,6 +18,10 @@ export enum MonitoredProduct {
EnterpriseSearch = 'enterpriseSearch',
}
export type MetricbeatMonitoredProduct = Exclude<MonitoredProduct, MonitoredProduct.Cluster>;
export type PackagesMonitoredProduct = Exclude<
MetricbeatMonitoredProduct,
MonitoredProduct.EnterpriseSearch
>;
export type SearchFn = (params: any) => Promise<ElasticsearchResponse>;

View file

@ -12,5 +12,12 @@
"timedOut": false
},
"products": {}
},
"packageErrors": {
"execution": {
"errors": [],
"timedOut": false
},
"products": {}
}
}

View file

@ -122,5 +122,12 @@ export const esBeatsResponse = (date = moment().format('YYYY.MM.DD')) => {
},
},
},
packageErrors: {
execution: {
errors: [],
timedOut: false,
},
products: {},
},
};
};

View file

@ -0,0 +1,49 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export const esPackageResponse = () => {
return {
monitoredClusters: {
clusters: {
standalone: {},
},
execution: {
timedOut: false,
errors: [],
},
},
metricbeatErrors: {
execution: {
errors: [],
timedOut: false,
},
products: {},
},
packageErrors: {
execution: {
errors: [],
timedOut: false,
},
products: {
elasticsearch: {
'elasticsearch.stack_monitoring.node_stats': [
{
lastSeen: '2023-01-13T15:11:40.458Z',
message:
'error making http request: Get "http://localhost:9200/_nodes/_local/stats": dial tcp [::1]:9200: connect: cannot assign requested address',
},
{
lastSeen: '2023-01-13T15:11:30.458Z',
message:
'error making http request: Get "http://localhost:9200/_nodes/_local/stats": dial tcp 127.0.0.1:9200: connect: connection refused',
},
],
},
},
},
};
};

View file

@ -12,7 +12,10 @@ import { getLifecycleMethods } from '../data_stream';
import emptyResponse from './fixtures/response_empty.json';
import { esBeatsResponse } from './fixtures/response_es_beats';
import { esPackageResponse } from './fixtures/response_es_package';
const ELASTICSEARCH_PACKAGE_ARCHIVE =
'x-pack/test/api_integration/apis/monitoring/es_archives/_health/elasticsearch_package_error';
const METRICBEAT_ARCHIVE =
'x-pack/test/api_integration/apis/monitoring/es_archives/_health/metricbeat_8';
export default function ({ getService }) {
@ -36,7 +39,7 @@ export default function ({ getService }) {
});
});
describe('with data', () => {
describe('with metricbeat data', () => {
const archives = [
'x-pack/test/api_integration/apis/monitoring/es_archives/_health/monitoring_es_8',
'x-pack/test/api_integration/apis/monitoring/es_archives/_health/monitoring_beats_8',
@ -82,5 +85,32 @@ export default function ({ getService }) {
});
});
});
describe('with integration package data', () => {
const timeRange = {
min: '2023-01-10T14:46:10.461Z',
max: '2023-01-15T22:30:00.000Z',
};
const archives = [ELASTICSEARCH_PACKAGE_ARCHIVE];
const { setup, tearDown } = getLifecycleMethods(getService);
before('load archive', () => {
return setup(archives);
});
after('unload archive', () => {
return tearDown([ELASTICSEARCH_PACKAGE_ARCHIVE]);
});
it('returns the state of the monitoring documents', async () => {
const { body } = await supertest
.get(`/api/monitoring/v1/_health?min=${timeRange.min}&max=${timeRange.max}`)
.set('kbn-xsrf', 'xxx')
.expect(200);
delete body.settings;
expect(body).to.eql(esPackageResponse());
});
});
});
}