mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Cases] Add telemetry for deprecated API (#126433)
This commit is contained in:
parent
3285eb187a
commit
c7f63f8f8d
8 changed files with 140 additions and 36 deletions
|
@ -7,7 +7,6 @@
|
|||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import { getWarningHeader, logDeprecatedEndpoint } from '../utils';
|
||||
import { CASE_COMMENTS_URL } from '../../../../common/constants';
|
||||
import { createCaseError } from '../../../common/error';
|
||||
import { createCasesRoute } from '../create_cases_route';
|
||||
|
@ -23,20 +22,12 @@ export const getAllCommentsRoute = createCasesRoute({
|
|||
case_id: schema.string(),
|
||||
}),
|
||||
},
|
||||
options: { deprecated: true },
|
||||
handler: async ({ context, request, response, logger, kibanaVersion }) => {
|
||||
try {
|
||||
logDeprecatedEndpoint(
|
||||
logger,
|
||||
request.headers,
|
||||
`The get all cases comments API '${CASE_COMMENTS_URL}' is deprecated.`
|
||||
);
|
||||
|
||||
const client = await context.cases.getCasesClient();
|
||||
|
||||
return response.ok({
|
||||
headers: {
|
||||
...getWarningHeader(kibanaVersion),
|
||||
},
|
||||
body: await client.attachments.getAll({
|
||||
caseID: request.params.case_id,
|
||||
}),
|
||||
|
|
|
@ -19,6 +19,7 @@ import { CasesRouter } from '../../types';
|
|||
import { createCasesRoute } from './create_cases_route';
|
||||
import { registerRoutes } from './register_routes';
|
||||
import { CaseRoute } from './types';
|
||||
import { extractWarningValueFromWarningHeader } from './utils';
|
||||
|
||||
describe('registerRoutes', () => {
|
||||
let router: jest.Mocked<CasesRouter>;
|
||||
|
@ -105,6 +106,7 @@ describe('registerRoutes', () => {
|
|||
{ headers },
|
||||
{ customError, badRequest }
|
||||
);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
@ -131,6 +133,26 @@ describe('registerRoutes', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const initAndSimulateDeprecationEndpoint = async (headers?: Record<string, unknown>) => {
|
||||
const { simulateRequest } = initApi([
|
||||
...routes,
|
||||
createCasesRoute({
|
||||
method: 'get',
|
||||
path: '/deprecated',
|
||||
options: { deprecated: true },
|
||||
handler: async () => response.ok(),
|
||||
}),
|
||||
]);
|
||||
|
||||
const res = await simulateRequest({
|
||||
method: 'get',
|
||||
path: '/deprecated',
|
||||
headers,
|
||||
});
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
router = httpServiceMock.createRouter();
|
||||
|
@ -245,6 +267,40 @@ describe('registerRoutes', () => {
|
|||
counterType: 'error',
|
||||
});
|
||||
});
|
||||
|
||||
it('increases the deprecation counters correctly', async () => {
|
||||
await initAndSimulateDeprecationEndpoint();
|
||||
|
||||
expect(telemetryUsageCounter.incrementCounter).toHaveBeenCalledWith({
|
||||
counterName: 'GET /deprecated',
|
||||
counterType: 'deprecated',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('deprecation', () => {
|
||||
it('logs the deprecation message if it is not a kibana request', async () => {
|
||||
await initAndSimulateDeprecationEndpoint();
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith('The endpoint GET /deprecated is deprecated.');
|
||||
});
|
||||
|
||||
it('does NOT log the deprecation message if it is a kibana request', async () => {
|
||||
await initAndSimulateDeprecationEndpoint({
|
||||
'kbn-version': '8.2.0',
|
||||
referer: 'https://example.com',
|
||||
});
|
||||
|
||||
expect(logger.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('adds the warning header', async () => {
|
||||
response.ok.mockReturnValue({ status: 200, options: {} });
|
||||
const res = await initAndSimulateDeprecationEndpoint();
|
||||
const warningHeader = res.options.headers.warning;
|
||||
const warningValue = extractWarningValueFromWarningHeader(warningHeader);
|
||||
expect(warningValue).toBe('Deprecated endpoint');
|
||||
});
|
||||
});
|
||||
|
||||
describe('errors', () => {
|
||||
|
|
|
@ -6,10 +6,18 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { RouteRegistrar } from 'kibana/server';
|
||||
import { Headers, RouteRegistrar } from 'kibana/server';
|
||||
import { CasesRequestHandlerContext } from '../../types';
|
||||
import { CaseRoute, RegisterRoutesDeps } from './types';
|
||||
import { escapeHatch, getIsKibanaRequest, wrapError } from './utils';
|
||||
import { RegisterRoutesDeps } from './types';
|
||||
import {
|
||||
escapeHatch,
|
||||
getIsKibanaRequest,
|
||||
getWarningHeader,
|
||||
logDeprecatedEndpoint,
|
||||
wrapError,
|
||||
} from './utils';
|
||||
|
||||
const getEndpoint = (method: string, path: string): string => `${method.toUpperCase()} ${path}`;
|
||||
|
||||
const increaseTelemetryCounters = ({
|
||||
telemetryUsageCounter,
|
||||
|
@ -24,7 +32,7 @@ const increaseTelemetryCounters = ({
|
|||
isKibanaRequest: boolean;
|
||||
isError?: boolean;
|
||||
}) => {
|
||||
const counterName = `${method.toUpperCase()} ${path}`;
|
||||
const counterName = getEndpoint(method, path);
|
||||
|
||||
telemetryUsageCounter.incrementCounter({
|
||||
counterName,
|
||||
|
@ -37,11 +45,36 @@ const increaseTelemetryCounters = ({
|
|||
});
|
||||
};
|
||||
|
||||
const logAndIncreaseDeprecationTelemetryCounters = ({
|
||||
logger,
|
||||
headers,
|
||||
method,
|
||||
path,
|
||||
telemetryUsageCounter,
|
||||
}: {
|
||||
logger: RegisterRoutesDeps['logger'];
|
||||
headers: Headers;
|
||||
method: string;
|
||||
path: string;
|
||||
telemetryUsageCounter?: Exclude<RegisterRoutesDeps['telemetryUsageCounter'], undefined>;
|
||||
}) => {
|
||||
const endpoint = getEndpoint(method, path);
|
||||
|
||||
logDeprecatedEndpoint(logger, headers, `The endpoint ${endpoint} is deprecated.`);
|
||||
|
||||
if (telemetryUsageCounter) {
|
||||
telemetryUsageCounter.incrementCounter({
|
||||
counterName: endpoint,
|
||||
counterType: 'deprecated',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const registerRoutes = (deps: RegisterRoutesDeps) => {
|
||||
const { router, routes, logger, kibanaVersion, telemetryUsageCounter } = deps;
|
||||
|
||||
routes.forEach((route) => {
|
||||
const { method, path, params, handler } = route as CaseRoute;
|
||||
const { method, path, params, options, handler } = route;
|
||||
|
||||
(router[method] as RouteRegistrar<typeof method, CasesRequestHandlerContext>)(
|
||||
{
|
||||
|
@ -53,6 +86,7 @@ export const registerRoutes = (deps: RegisterRoutesDeps) => {
|
|||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
let responseHeaders = {};
|
||||
const isKibanaRequest = getIsKibanaRequest(request.headers);
|
||||
|
||||
if (!context.cases) {
|
||||
|
@ -60,12 +94,32 @@ export const registerRoutes = (deps: RegisterRoutesDeps) => {
|
|||
}
|
||||
|
||||
try {
|
||||
if (options?.deprecated) {
|
||||
logAndIncreaseDeprecationTelemetryCounters({
|
||||
telemetryUsageCounter,
|
||||
logger,
|
||||
path,
|
||||
method,
|
||||
headers: request.headers,
|
||||
});
|
||||
|
||||
responseHeaders = {
|
||||
...responseHeaders,
|
||||
...getWarningHeader(kibanaVersion),
|
||||
};
|
||||
}
|
||||
|
||||
const res = await handler({ logger, context, request, response, kibanaVersion });
|
||||
|
||||
if (telemetryUsageCounter) {
|
||||
increaseTelemetryCounters({ telemetryUsageCounter, method, path, isKibanaRequest });
|
||||
}
|
||||
|
||||
res.options.headers = {
|
||||
...res.options.headers,
|
||||
...responseHeaders,
|
||||
};
|
||||
|
||||
return res;
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import { CaseRoute } from '../types';
|
||||
import { getWarningHeader, logDeprecatedEndpoint } from '../utils';
|
||||
|
||||
import { CasesStatusRequest } from '../../../../common/api';
|
||||
import { CASE_STATUS_URL } from '../../../../common/constants';
|
||||
|
@ -19,19 +18,11 @@ import { createCasesRoute } from '../create_cases_route';
|
|||
export const getStatusRoute: CaseRoute = createCasesRoute({
|
||||
method: 'get',
|
||||
path: CASE_STATUS_URL,
|
||||
options: { deprecated: true },
|
||||
handler: async ({ context, request, response, logger, kibanaVersion }) => {
|
||||
try {
|
||||
logDeprecatedEndpoint(
|
||||
logger,
|
||||
request.headers,
|
||||
`The get cases status API '${CASE_STATUS_URL}' is deprecated.`
|
||||
);
|
||||
|
||||
const client = await context.cases.getCasesClient();
|
||||
return response.ok({
|
||||
headers: {
|
||||
...getWarningHeader(kibanaVersion),
|
||||
},
|
||||
body: await client.metrics.getStatusTotalsByType(request.query as CasesStatusRequest),
|
||||
});
|
||||
} catch (error) {
|
||||
|
|
|
@ -44,5 +44,6 @@ export interface CaseRoute<P = unknown, Q = unknown, B = unknown> {
|
|||
method: 'get' | 'post' | 'put' | 'delete' | 'patch';
|
||||
path: string;
|
||||
params?: RouteValidatorConfig<P, Q, B>;
|
||||
options?: { deprecated?: boolean };
|
||||
handler: (args: CaseRouteHandlerArguments<P, Q, B>) => Promise<IKibanaResponse>;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import { getWarningHeader, logDeprecatedEndpoint } from '../utils';
|
||||
import { CASE_USER_ACTIONS_URL } from '../../../../common/constants';
|
||||
import { createCaseError } from '../../../common/error';
|
||||
import { createCasesRoute } from '../create_cases_route';
|
||||
|
@ -23,21 +22,13 @@ export const getUserActionsRoute = createCasesRoute({
|
|||
case_id: schema.string(),
|
||||
}),
|
||||
},
|
||||
options: { deprecated: true },
|
||||
handler: async ({ context, request, response, logger, kibanaVersion }) => {
|
||||
try {
|
||||
logDeprecatedEndpoint(
|
||||
logger,
|
||||
request.headers,
|
||||
`The get all cases user actions API '${CASE_USER_ACTIONS_URL}' is deprecated.`
|
||||
);
|
||||
|
||||
const casesClient = await context.cases.getCasesClient();
|
||||
const caseId = request.params.case_id;
|
||||
|
||||
return response.ok({
|
||||
headers: {
|
||||
...getWarningHeader(kibanaVersion),
|
||||
},
|
||||
body: await casesClient.userActions.getAll({ caseId }),
|
||||
});
|
||||
} catch (error) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { isBoom, boomify } from '@hapi/boom';
|
||||
import { loggingSystemMock } from '../../../../../../src/core/server/mocks';
|
||||
import { HTTPError } from '../../common/error';
|
||||
import { logDeprecatedEndpoint, wrapError } from './utils';
|
||||
import { extractWarningValueFromWarningHeader, logDeprecatedEndpoint, wrapError } from './utils';
|
||||
|
||||
describe('Utils', () => {
|
||||
describe('wrapError', () => {
|
||||
|
@ -75,4 +75,12 @@ describe('Utils', () => {
|
|||
expect(logger.warn).toHaveBeenCalledWith('test');
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractWarningValueFromWarningHeader', () => {
|
||||
it('extracts the warning value from a warning header correctly', () => {
|
||||
expect(extractWarningValueFromWarningHeader(`299 Kibana-8.1.0 "Deprecation endpoint"`)).toBe(
|
||||
'Deprecation endpoint'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -63,3 +63,15 @@ export const logDeprecatedEndpoint = (logger: Logger, headers: Headers, msg: str
|
|||
logger.warn(msg);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts the warning value a warning header that is formatted according to RFC 7234.
|
||||
* For example for the string 299 Kibana-8.1.0 "Deprecation endpoint", the return value is Deprecation endpoint.
|
||||
*
|
||||
*/
|
||||
export const extractWarningValueFromWarningHeader = (warningHeader: string) => {
|
||||
const firstQuote = warningHeader.indexOf('"');
|
||||
const lastQuote = warningHeader.length - 1;
|
||||
const warningValue = warningHeader.substring(firstQuote + 1, lastQuote);
|
||||
return warningValue;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue