Remove /api/_xpack/usage and /api/_kibana/v1/stats (#20800) (#21008)

/api/_xpack/usage was added as a target for 6.4.0 but it will not be
used. Instead, the /api/stats response will include usage info on
everything that gets registered with the usage service in
/src/server/usage

/api/_kibana/v1/stats is a GET API that was added in 6.2, during a point
where we thought providing usage stats through a public API would be OK
for capturing internally, with the benefit of having it be visible.

However, we've pivoted away from that idea because it doesn't line up
too well with the existing flow of data, where usage stats are combined
with the "Kibana stats" such as process uptime and number of requests.
We want to shift how we collect stats from Kibana, but it will be
gradual. It might be a while before we have an architecture that makes
sense for a standalone public API for the usage stats

This endpoint was never documented, and isn't used anywhere in the code.
It does incur a maintenance cost though.

Therefore, instead of waiting for a next major version to remove this
API, I'm removing it for 6.4. It will be marked in the release notes as
a breaking change. Since it was never documented, it should not provide
a problem.
This commit is contained in:
Tim Sullivan 2018-07-19 17:45:51 -07:00 committed by GitHub
parent 2f7e7c85b3
commit 9a6e665f2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 6 additions and 143 deletions

View file

@ -5,6 +5,6 @@
*/
export const name = 'kibana_stats';
export const description = 'Get the Kibana usage stats from the Kibana server';
export const description = 'Get the extended Kibana usage stats from the Kibana server';
export const method = 'GET';
export const path = '/api/_kibana/v1/stats';
export const path = '/api/stats?extended=true';

View file

@ -15,8 +15,6 @@ import { replaceInjectedVars } from './server/lib/replace_injected_vars';
import { setupXPackMain } from './server/lib/setup_xpack_main';
import {
xpackInfoRoute,
xpackUsageRoute,
kibanaStatsRoute,
telemetryRoute,
} from './server/routes/api/v1';
import {
@ -111,8 +109,6 @@ export const xpackMain = (kibana) => {
// register routes
xpackInfoRoute(server);
xpackUsageRoute(server); // To replace kibanaStatsRoute
kibanaStatsRoute(server); // Only used internally. Remove in the next major.
telemetryRoute(server);
}
});

View file

@ -5,6 +5,4 @@
*/
export { xpackInfoRoute } from './xpack_info';
export { kibanaStatsRoute } from './kibana_stats';
export { xpackUsageRoute } from './xpack_usage';
export { telemetryRoute } from './telemetry';

View file

@ -1,47 +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;
* you may not use this file except in compliance with the Elastic License.
*/
/*
* TODO: remove this API in 7.0
*/
import { wrap } from 'boom';
import { callClusterFactory } from '../../../lib/call_cluster_factory';
import { getKibanaUsageCollector } from '../../../../../monitoring/server/kibana_monitoring/collectors';
import { getReportingUsageCollector } from '../../../../../reporting/server/usage';
export function kibanaStatsRoute(server) {
server.route({
path: '/api/_kibana/v1/stats',
method: 'GET',
handler: async (req, reply) => {
const server = req.server;
// require that http authentication headers from req are used to read ES data
const callCluster = callClusterFactory(server).getCallClusterWithReq(req);
try {
const kibanaUsageCollector = getKibanaUsageCollector(server);
const reportingUsageCollector = getReportingUsageCollector(server);
const [ kibana, reporting ] = await Promise.all([
kibanaUsageCollector.fetch(callCluster),
reportingUsageCollector.fetch(callCluster),
]);
reply({
kibana,
reporting,
});
} catch(err) {
req.log(['error'], err);
if (err.isBoom) {
return reply(err);
}
reply(wrap(err, err.statusCode, err.message));
}
}
});
}

View file

@ -7,6 +7,5 @@
export default function ({ loadTestFile }) {
describe('xpack_main', () => {
loadTestFile(require.resolve('./telemetry'));
loadTestFile(require.resolve('./usage'));
});
}

View file

@ -1,12 +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;
* you may not use this file except in compliance with the Elastic License.
*/
export default function ({ loadTestFile }) {
describe('X-Pack Usage', () => {
loadTestFile(require.resolve('./usage'));
});
}

View file

@ -1,39 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import expect from 'expect.js';
export default function ({ getService }) {
const esArchiver = getService('esArchiver');
const usageAPI = getService('usageAPI');
describe('/api/_xpack/usage', () => {
before('load archives', async () => {
await esArchiver.load('../../../../test/functional/fixtures/es_archiver/dashboard/current/kibana');
});
after(async () => {
await esArchiver.unload('../../../../test/functional/fixtures/es_archiver/dashboard/current/kibana');
});
it('should reject without authentication headers passed', async () => {
const rejected = await usageAPI.getUsageStatsNoAuth();
expect(rejected).to.eql({ statusCode: 401, error: 'Unauthorized' });
});
it('should return xpack usage data', async () => {
const usage = await usageAPI.getUsageStats();
expect(usage.cluster_uuid).to.be.a('string');
expect(usage.kibana.dashboard.total).to.be(26);
expect(usage.kibana.visualization.total).to.be(47);
expect(usage.kibana.search.total).to.be(5);
expect(usage.kibana.index_pattern.total).to.be(3);
expect(usage.kibana.timelion_sheet.total).to.be(0);
expect(usage.kibana.graph_workspace.total).to.be(0);
});
});
}

View file

@ -12,26 +12,18 @@ export function UsageAPIProvider({ getService }) {
return {
async getUsageStatsNoAuth() {
const { body } = await supertestNoAuth
.get('/api/_xpack/usage')
.get('/api/stats?extended=true')
.set('kbn-xsrf', 'xxx')
.expect(401);
return body;
return body.usage;
},
async getUsageStats() {
const { body } = await supertest
.get('/api/_xpack/usage')
.get('/api/stats?extended=true')
.set('kbn-xsrf', 'xxx')
.expect(200);
return body;
},
async getUsageStatsFromDeprecatedPre64Endpoint() {
const { body } = await supertest
.get('/api/_kibana/v1/stats')
.set('kbn-xsrf', 'xxx')
.expect(200);
return body;
return body.usage;
},
};
}

View file

@ -123,29 +123,5 @@ export default function ({ getService }) {
reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'printable_pdf', 23);
});
});
/* Have to skip this test because the usage stats returned by the legacy
* endpoint aren't snake_cased in the legacy usage api. This will be
* completely removed in the next PR, when the legacy endpoint is removed
*/
describe.skip('deprecated API', () => {
it('shows correct stats', async () => {
const usage = await usageAPI.getUsageStatsFromDeprecatedPre64Endpoint();
reportingAPI.expectRecentPdfAppStats(usage, 'visualization', 2);
reportingAPI.expectRecentPdfAppStats(usage, 'dashboard', 2);
reportingAPI.expectRecentPdfLayoutStats(usage, 'preserve_layout', 2);
reportingAPI.expectRecentPdfLayoutStats(usage, 'print', 2);
reportingAPI.expectRecentJobTypeTotalStats(usage, 'csv', 1);
reportingAPI.expectRecentJobTypeTotalStats(usage, 'printable_pdf', 4);
reportingAPI.expectAllTimePdfAppStats(usage, 'visualization', 5);
reportingAPI.expectAllTimePdfAppStats(usage, 'dashboard', 5);
reportingAPI.expectAllTimePdfLayoutStats(usage, 'preserve_layout', 5);
reportingAPI.expectAllTimePdfLayoutStats(usage, 'print', 5);
reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'csv', 4);
reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'printable_pdf', 23);
});
});
});
}