kibana/test/api_integration/apis/stats/stats.js
Luke Elmers b6287708f6
Adds AGPL 3.0 license (#192025)
Updates files outside of x-pack to be triple-licensed under Elastic
License 2.0, AGPL 3.0, or SSPL 1.0.
2024-09-06 19:02:41 -06:00

251 lines
8.1 KiB
JavaScript

/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import expect from '@kbn/expect';
import { schema } from '@kbn/config-schema';
const processSchema = schema.object({
pid: schema.number(),
uptime_ms: schema.number(),
event_loop_delay: schema.number(),
event_loop_delay_histogram: schema.object({
min: schema.number(),
mean: schema.number(),
exceeds: schema.number(),
stddev: schema.number(),
max: schema.number(),
from_timestamp: schema.string(),
last_updated_at: schema.string(),
percentiles: schema.object({
50: schema.number(),
75: schema.number(),
95: schema.number(),
99: schema.number(),
}),
}),
event_loop_utilization: schema.object({
active: schema.number(),
idle: schema.number(),
utilization: schema.number(),
}),
memory: schema.object({
heap: schema.object({
total_bytes: schema.number(),
used_bytes: schema.number(),
size_limit: schema.number(),
}),
resident_set_size_bytes: schema.number(),
external_bytes: schema.number(),
array_buffers_bytes: schema.number(),
}),
});
const baseResponseSchema = schema.object({
last_updated: schema.string(),
collection_interval_ms: schema.number(),
usage: schema.object({}),
kibana: schema.object({
name: schema.string(),
uuid: schema.string(),
host: schema.string(),
index: schema.string(),
locale: schema.string(),
transport_address: schema.string(),
version: schema.string(),
snapshot: schema.boolean(),
status: schema.string(),
}),
process: processSchema,
processes: schema.arrayOf(processSchema),
os: schema.object({
platform: schema.string(),
platform_release: schema.string(),
distro: schema.maybe(schema.string()),
distro_release: schema.maybe(schema.string()),
memory: schema.object({
free_bytes: schema.number(),
used_bytes: schema.number(),
total_bytes: schema.number(),
}),
uptime_ms: schema.number(),
load: schema.object({
'1m': schema.number(),
'5m': schema.number(),
'15m': schema.number(),
}),
cpuacct: schema.maybe(
schema.object({
control_group: schema.string(),
usage_nanos: schema.number(),
})
),
cpu: schema.maybe(
schema.object({
control_group: schema.string(),
cfs_period_micros: schema.number(),
cfs_quota_micros: schema.number(),
stat: schema.object({
number_of_elapsed_periods: schema.number(),
number_of_times_throttled: schema.number(),
time_throttled_nanos: schema.number(),
}),
})
),
cgroup_memory: schema.maybe(
schema.object({
current_in_bytes: schema.number(),
swap_current_in_bytes: schema.number(),
})
),
}),
elasticsearch_client: schema.object({
total_active_sockets: schema.number(),
total_idle_sockets: schema.number(),
total_queued_requests: schema.number(),
}),
response_times: schema.object({
avg_ms: schema.maybe(schema.number()),
max_ms: schema.maybe(schema.number()),
}),
requests: schema.object({
total: schema.number(),
disconnects: schema.number(),
status_codes: schema.recordOf(schema.number(), schema.number()),
}),
concurrent_connections: schema.number(),
});
const legacyResponseSchema = baseResponseSchema.extends({
clusterUuid: schema.string(),
});
const statsResponseSchema = baseResponseSchema.extends({
cluster_uuid: schema.maybe(schema.string()),
});
const assertStatsAndMetrics = (body, legacy = false) => {
try {
if (legacy) {
legacyResponseSchema.validate(body);
} else {
statsResponseSchema.validate(body);
}
} catch (e) {
expect().fail(`Expected /api/stats response to match schema: ${e.message}`);
}
};
export default function ({ getService }) {
const supertest = getService('supertest');
const kibanaServer = getService('kibanaServer');
describe('kibana stats api', () => {
before(async () => {
await kibanaServer.importExport.load(
'test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json'
);
});
after(async () => {
await kibanaServer.importExport.unload(
'test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json'
);
});
describe('basic', () => {
it('should return the stats without cluster_uuid with no query string params', () => {
return supertest
.get('/api/stats')
.expect('Content-Type', /json/)
.expect(200)
.then(({ body }) => {
expect(body.cluster_uuid).to.be(undefined);
assertStatsAndMetrics(body);
});
});
it(`should return the stats without cluster_uuid with 'extended' query string param = false`, () => {
return supertest
.get('/api/stats?extended=false')
.expect('Content-Type', /json/)
.expect(200)
.then(({ body }) => {
expect(body.cluster_uuid).to.be(undefined);
assertStatsAndMetrics(body);
});
});
});
// TODO load an es archive and verify the counts in saved object usage info
describe('extended', () => {
it(`should return the stats, cluster_uuid, and usage with 'extended' query string param present`, () => {
return supertest
.get('/api/stats?extended')
.expect('Content-Type', /json/)
.expect(200)
.then(({ body }) => {
expect(body.cluster_uuid).to.be.a('string');
expect(body.usage).to.be.an('object'); // no usage collectors have been registered so usage is an empty object
expect(body.usage).to.eql({});
assertStatsAndMetrics(body);
});
});
it(`should return the stats, cluster_uuid, and usage with 'extended' query string param = true`, () => {
return supertest
.get('/api/stats?extended=true')
.expect('Content-Type', /json/)
.expect(200)
.then(({ body }) => {
expect(body.cluster_uuid).to.be.a('string');
expect(body.usage).to.be.an('object');
expect(body.usage).to.eql({});
assertStatsAndMetrics(body);
});
});
describe('legacy', () => {
it(`should return return the 'extended' data in the old format with 'legacy' query string param present`, () => {
return supertest
.get('/api/stats?extended&legacy')
.expect('Content-Type', /json/)
.expect(200)
.then(({ body }) => {
expect(body.clusterUuid).to.be.a('string');
expect(body.usage).to.be.an('object'); // no usage collectors have been registered so usage is an empty object
expect(body.usage).to.eql({});
assertStatsAndMetrics(body, true);
});
});
});
describe('exclude usage', () => {
it('should include an empty usage object from the API response', () => {
return supertest
.get('/api/stats?extended&exclude_usage')
.expect('Content-Type', /json/)
.expect(200)
.then(({ body }) => {
expect(body).to.have.property('usage');
expect(body.usage).to.eql({});
});
});
it('should include an empty usage object from the API response if `legacy` is provided', () => {
return supertest
.get('/api/stats?extended&exclude_usage&legacy')
.expect('Content-Type', /json/)
.expect(200)
.then(({ body }) => {
expect(body).to.have.property('usage');
expect(body.usage).to.eql({});
});
});
});
});
});
}