mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[APM] Add tests for service_map and critical_path endpoints to serverless integration tests suite (#186466)
closes [186450](https://github.com/elastic/kibana/issues/186450) ## Summary Add tests for aggregate critical path and service map endpoints to serverless test suite --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
8f01b66ef2
commit
4db61fa913
5 changed files with 248 additions and 0 deletions
|
@ -14,6 +14,7 @@ import { SamlToolsProvider } from './saml_tools';
|
|||
import { SvlCasesServiceProvider } from './svl_cases';
|
||||
import { SloApiProvider } from './slo_api';
|
||||
import { TransformProvider } from './transform';
|
||||
import { SynthtraceProvider } from './synthtrace';
|
||||
|
||||
export const services = {
|
||||
// deployment agnostic FTR services
|
||||
|
@ -26,6 +27,7 @@ export const services = {
|
|||
svlCases: SvlCasesServiceProvider,
|
||||
sloApi: SloApiProvider,
|
||||
transform: TransformProvider,
|
||||
synthtrace: SynthtraceProvider,
|
||||
};
|
||||
|
||||
export type InheritedFtrProviderContext = GenericFtrProviderContext<typeof services, {}>;
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 { Client } from '@elastic/elasticsearch';
|
||||
import {
|
||||
ApmSynthtraceEsClient,
|
||||
ApmSynthtraceKibanaClient,
|
||||
createLogger,
|
||||
LogLevel,
|
||||
} from '@kbn/apm-synthtrace';
|
||||
import url, { format, UrlObject } from 'url';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
async function getSynthtraceEsClient(client: Client, kibanaClient: ApmSynthtraceKibanaClient) {
|
||||
const kibanaVersion = await kibanaClient.fetchLatestApmPackageVersion();
|
||||
await kibanaClient.installApmPackage(kibanaVersion);
|
||||
|
||||
const esClient = new ApmSynthtraceEsClient({
|
||||
client,
|
||||
logger: createLogger(LogLevel.info),
|
||||
version: kibanaVersion,
|
||||
refreshAfterIndex: true,
|
||||
});
|
||||
|
||||
return esClient;
|
||||
}
|
||||
|
||||
function getSynthtraceKibanaClient(kibanaServerUrl: string) {
|
||||
const kibanaServerUrlWithAuth = url
|
||||
.format({
|
||||
...url.parse(kibanaServerUrl),
|
||||
})
|
||||
.slice(0, -1);
|
||||
|
||||
const kibanaClient = new ApmSynthtraceKibanaClient({
|
||||
target: kibanaServerUrlWithAuth,
|
||||
logger: createLogger(LogLevel.debug),
|
||||
});
|
||||
|
||||
return kibanaClient;
|
||||
}
|
||||
|
||||
export function SynthtraceProvider({ getService }: FtrProviderContext) {
|
||||
const es = getService('es');
|
||||
const config = getService('config');
|
||||
|
||||
const servers = config.get('servers');
|
||||
const kibanaServer = servers.kibana as UrlObject;
|
||||
const kibanaServerUrl = format(kibanaServer);
|
||||
const synthtraceKibanaClient = getSynthtraceKibanaClient(kibanaServerUrl);
|
||||
|
||||
return {
|
||||
createSynthtraceKibanaClient: getSynthtraceKibanaClient,
|
||||
async createSynthtraceEsClient() {
|
||||
return getSynthtraceEsClient(es, synthtraceKibanaClient);
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace';
|
||||
import expect from 'expect';
|
||||
import { serviceMap, timerange } from '@kbn/apm-synthtrace-client';
|
||||
import { Readable } from 'stream';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../shared/services';
|
||||
import { APMFtrContextProvider } from '../common/services';
|
||||
|
||||
export default function ({ getService }: APMFtrContextProvider) {
|
||||
const apmApiClient = getService('apmApiClient');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const synthtrace = getService('synthtrace');
|
||||
|
||||
const start = new Date('2024-06-01T00:00:00.000Z').getTime();
|
||||
const end = new Date('2024-06-01T00:01:00.000Z').getTime();
|
||||
|
||||
describe('APM Service maps', () => {
|
||||
let roleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
let synthtraceEsClient: ApmSynthtraceEsClient;
|
||||
|
||||
before(async () => {
|
||||
synthtraceEsClient = await synthtrace.createSynthtraceEsClient();
|
||||
|
||||
const events = timerange(start, end)
|
||||
.interval('10s')
|
||||
.rate(3)
|
||||
.generator(
|
||||
serviceMap({
|
||||
services: [
|
||||
{ 'frontend-rum': 'rum-js' },
|
||||
{ 'frontend-node': 'nodejs' },
|
||||
{ advertService: 'java' },
|
||||
],
|
||||
definePaths([rum, node, adv]) {
|
||||
return [
|
||||
[
|
||||
[rum, 'fetchAd'],
|
||||
[node, 'GET /nodejs/adTag'],
|
||||
[adv, 'APIRestController#getAd'],
|
||||
['elasticsearch', 'GET ad-*/_search'],
|
||||
],
|
||||
];
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
|
||||
|
||||
return synthtraceEsClient.index(Readable.from(Array.from(events)));
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
|
||||
return synthtraceEsClient.clean();
|
||||
});
|
||||
|
||||
it('returns service map elements', async () => {
|
||||
const response = await apmApiClient.slsUser({
|
||||
endpoint: 'GET /internal/apm/service-map',
|
||||
params: {
|
||||
query: {
|
||||
start: new Date(start).toISOString(),
|
||||
end: new Date(end).toISOString(),
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.elements.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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 expect from 'expect';
|
||||
import { apm, ApmFields, SynthtraceGenerator, timerange } from '@kbn/apm-synthtrace-client';
|
||||
import { compact, uniq } from 'lodash';
|
||||
import { Readable } from 'stream';
|
||||
import { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../shared/services';
|
||||
import { APMFtrContextProvider } from '../common/services';
|
||||
|
||||
export default function ({ getService }: APMFtrContextProvider) {
|
||||
const apmApiClient = getService('apmApiClient');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const synthtrace = getService('synthtrace');
|
||||
|
||||
const start = new Date('2022-01-01T00:00:00.000Z').getTime();
|
||||
const end = new Date('2022-01-01T00:15:00.000Z').getTime() - 1;
|
||||
|
||||
async function fetchAndBuildCriticalPathTree(
|
||||
synthtraceEsClient: ApmSynthtraceEsClient,
|
||||
options: {
|
||||
fn: () => SynthtraceGenerator<ApmFields>;
|
||||
roleAuthc: RoleCredentials;
|
||||
internalReqHeader: InternalRequestHeader;
|
||||
} & ({ serviceName: string; transactionName: string } | {})
|
||||
) {
|
||||
const { fn, roleAuthc, internalReqHeader } = options;
|
||||
|
||||
const generator = fn();
|
||||
|
||||
const unserialized = Array.from(generator);
|
||||
const serialized = unserialized.flatMap((event) => event.serialize());
|
||||
const traceIds = compact(uniq(serialized.map((event) => event['trace.id'])));
|
||||
|
||||
await synthtraceEsClient.index(Readable.from(unserialized));
|
||||
|
||||
return apmApiClient.slsUser({
|
||||
endpoint: 'POST /internal/apm/traces/aggregated_critical_path',
|
||||
params: {
|
||||
body: {
|
||||
start: new Date(start).toISOString(),
|
||||
end: new Date(end).toISOString(),
|
||||
traceIds,
|
||||
serviceName: 'serviceName' in options ? options.serviceName : null,
|
||||
transactionName: 'transactionName' in options ? options.transactionName : null,
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
}
|
||||
|
||||
describe('APM Aggregated critical path', () => {
|
||||
let roleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
let synthtraceEsClient: ApmSynthtraceEsClient;
|
||||
|
||||
before(async () => {
|
||||
synthtraceEsClient = await synthtrace.createSynthtraceEsClient();
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
|
||||
return synthtraceEsClient.clean();
|
||||
});
|
||||
|
||||
it('returns service map elements', async () => {
|
||||
const java = apm
|
||||
.service({ name: 'java', environment: 'production', agentName: 'java' })
|
||||
.instance('java');
|
||||
|
||||
const duration = 1000;
|
||||
const rate = 10;
|
||||
|
||||
const response = await fetchAndBuildCriticalPathTree(synthtraceEsClient, {
|
||||
fn: () =>
|
||||
timerange(start, end)
|
||||
.interval('15m')
|
||||
.rate(rate)
|
||||
.generator((timestamp) => {
|
||||
return java.transaction('GET /api').timestamp(timestamp).duration(duration);
|
||||
}),
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.criticalPath).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -12,6 +12,8 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
this.tags(['esGate']);
|
||||
|
||||
loadTestFile(require.resolve('./apm_api_integration/feature_flags.ts'));
|
||||
loadTestFile(require.resolve('./apm_api_integration/service_maps/service_maps'));
|
||||
loadTestFile(require.resolve('./apm_api_integration/traces/critical_path'));
|
||||
loadTestFile(require.resolve('./cases'));
|
||||
loadTestFile(require.resolve('./burn_rate_rule/burn_rate_rule'));
|
||||
loadTestFile(require.resolve('./es_query_rule/es_query_rule'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue