Skip to content

Commit

Permalink
Instrument remaining routes
Browse files Browse the repository at this point in the history
  • Loading branch information
dgieselaar committed Feb 11, 2021
1 parent 6da51cc commit 927a4c4
Show file tree
Hide file tree
Showing 71 changed files with 3,680 additions and 3,345 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,80 +15,83 @@ import {
import { ProcessorEvent } from '../../../../common/processor_event';
import { rangeFilter } from '../../../../common/utils/range_filter';
import { AlertParams } from '../../../routes/alerts/chart_preview';
import { withApmSpan } from '../../../utils/with_apm_span';
import { getEnvironmentUiFilterES } from '../../helpers/convert_ui_filters/get_environment_ui_filter_es';
import { getBucketSize } from '../../helpers/get_bucket_size';
import { Setup, SetupTimeRange } from '../../helpers/setup_request';

export async function getTransactionDurationChartPreview({
export function getTransactionDurationChartPreview({
alertParams,
setup,
}: {
alertParams: AlertParams;
setup: Setup & SetupTimeRange;
}) {
const { apmEventClient, start, end } = setup;
const {
aggregationType,
environment,
serviceName,
transactionType,
} = alertParams;
return withApmSpan('get_transaction_duration_chart_preview', async () => {
const { apmEventClient, start, end } = setup;
const {
aggregationType,
environment,
serviceName,
transactionType,
} = alertParams;

const query = {
bool: {
filter: [
{ range: rangeFilter(start, end) },
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
...(serviceName ? [{ term: { [SERVICE_NAME]: serviceName } }] : []),
...(transactionType
? [{ term: { [TRANSACTION_TYPE]: transactionType } }]
: []),
...getEnvironmentUiFilterES(environment),
],
},
};
const query = {
bool: {
filter: [
{ range: rangeFilter(start, end) },
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
...(serviceName ? [{ term: { [SERVICE_NAME]: serviceName } }] : []),
...(transactionType
? [{ term: { [TRANSACTION_TYPE]: transactionType } }]
: []),
...getEnvironmentUiFilterES(environment),
],
},
};

const { intervalString } = getBucketSize({ start, end, numBuckets: 20 });
const { intervalString } = getBucketSize({ start, end, numBuckets: 20 });

const aggs = {
timeseries: {
date_histogram: {
field: '@timestamp',
fixed_interval: intervalString,
},
aggs: {
agg:
aggregationType === 'avg'
? { avg: { field: TRANSACTION_DURATION } }
: {
percentiles: {
field: TRANSACTION_DURATION,
percents: [aggregationType === '95th' ? 95 : 99],
const aggs = {
timeseries: {
date_histogram: {
field: '@timestamp',
fixed_interval: intervalString,
},
aggs: {
agg:
aggregationType === 'avg'
? { avg: { field: TRANSACTION_DURATION } }
: {
percentiles: {
field: TRANSACTION_DURATION,
percents: [aggregationType === '95th' ? 95 : 99],
},
},
},
},
},
},
};
const params = {
apm: { events: [ProcessorEvent.transaction] },
body: { size: 0, query, aggs },
};
const resp = await apmEventClient.search(params);
};
const params = {
apm: { events: [ProcessorEvent.transaction] },
body: { size: 0, query, aggs },
};
const resp = await apmEventClient.search(params);

if (!resp.aggregations) {
return [];
}
if (!resp.aggregations) {
return [];
}

return resp.aggregations.timeseries.buckets.map((bucket) => {
const percentilesKey = aggregationType === '95th' ? '95.0' : '99.0';
const x = bucket.key;
const y =
aggregationType === 'avg'
? (bucket.agg as MetricsAggregationResponsePart).value
: (bucket.agg as { values: Record<string, number | null> }).values[
percentilesKey
];
return resp.aggregations.timeseries.buckets.map((bucket) => {
const percentilesKey = aggregationType === '95th' ? '95.0' : '99.0';
const x = bucket.key;
const y =
aggregationType === 'avg'
? (bucket.agg as MetricsAggregationResponsePart).value
: (bucket.agg as { values: Record<string, number | null> }).values[
percentilesKey
];

return { x, y };
return { x, y };
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,56 +9,59 @@ import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames';
import { ProcessorEvent } from '../../../../common/processor_event';
import { rangeFilter } from '../../../../common/utils/range_filter';
import { AlertParams } from '../../../routes/alerts/chart_preview';
import { withApmSpan } from '../../../utils/with_apm_span';
import { getEnvironmentUiFilterES } from '../../helpers/convert_ui_filters/get_environment_ui_filter_es';
import { getBucketSize } from '../../helpers/get_bucket_size';
import { Setup, SetupTimeRange } from '../../helpers/setup_request';

export async function getTransactionErrorCountChartPreview({
export function getTransactionErrorCountChartPreview({
setup,
alertParams,
}: {
setup: Setup & SetupTimeRange;
alertParams: AlertParams;
}) {
const { apmEventClient, start, end } = setup;
const { serviceName, environment } = alertParams;
return withApmSpan('get_transaction_error_count_chart_preview', async () => {
const { apmEventClient, start, end } = setup;
const { serviceName, environment } = alertParams;

const query = {
bool: {
filter: [
{ range: rangeFilter(start, end) },
...(serviceName ? [{ term: { [SERVICE_NAME]: serviceName } }] : []),
...getEnvironmentUiFilterES(environment),
],
},
};
const query = {
bool: {
filter: [
{ range: rangeFilter(start, end) },
...(serviceName ? [{ term: { [SERVICE_NAME]: serviceName } }] : []),
...getEnvironmentUiFilterES(environment),
],
},
};

const { intervalString } = getBucketSize({ start, end, numBuckets: 20 });
const { intervalString } = getBucketSize({ start, end, numBuckets: 20 });

const aggs = {
timeseries: {
date_histogram: {
field: '@timestamp',
fixed_interval: intervalString,
const aggs = {
timeseries: {
date_histogram: {
field: '@timestamp',
fixed_interval: intervalString,
},
},
},
};
};

const params = {
apm: { events: [ProcessorEvent.error] },
body: { size: 0, query, aggs },
};
const params = {
apm: { events: [ProcessorEvent.error] },
body: { size: 0, query, aggs },
};

const resp = await apmEventClient.search(params);
const resp = await apmEventClient.search(params);

if (!resp.aggregations) {
return [];
}
if (!resp.aggregations) {
return [];
}

return resp.aggregations.timeseries.buckets.map((bucket) => {
return {
x: bucket.key,
y: bucket.doc_count,
};
return resp.aggregations.timeseries.buckets.map((bucket) => {
return {
x: bucket.key,
y: bucket.doc_count,
};
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from '../../../common/elasticsearch_fieldnames';
import { APM_ML_JOB_GROUP, ML_MODULE_ID_APM_TRANSACTION } from './constants';
import { getEnvironmentUiFilterES } from '../helpers/convert_ui_filters/get_environment_ui_filter_es';
import { withApmSpan } from '../../utils/with_apm_span';

export async function createAnomalyDetectionJobs(
setup: Setup,
Expand All @@ -30,32 +31,36 @@ export async function createAnomalyDetectionJobs(
throw Boom.notImplemented(ML_ERRORS.ML_NOT_AVAILABLE);
}

const mlCapabilities = await ml.mlSystem.mlCapabilities();
const mlCapabilities = await withApmSpan('get_ml_capabilites', () =>
ml.mlSystem.mlCapabilities()
);
if (!mlCapabilities.mlFeatureEnabledInSpace) {
throw Boom.forbidden(ML_ERRORS.ML_NOT_AVAILABLE_IN_SPACE);
}

logger.info(
`Creating ML anomaly detection jobs for environments: [${environments}].`
);

const indexPatternName = indices['apm_oss.transactionIndices'];
const responses = await Promise.all(
environments.map((environment) =>
createAnomalyDetectionJob({ ml, environment, indexPatternName })
)
);
const jobResponses = responses.flatMap((response) => response.jobs);
const failedJobs = jobResponses.filter(({ success }) => !success);
return withApmSpan('create_anomaly_detection_jobs', async () => {
logger.info(
`Creating ML anomaly detection jobs for environments: [${environments}].`
);

if (failedJobs.length > 0) {
const errors = failedJobs.map(({ id, error }) => ({ id, error }));
throw new Error(
`An error occurred while creating ML jobs: ${JSON.stringify(errors)}`
const indexPatternName = indices['apm_oss.transactionIndices'];
const responses = await Promise.all(
environments.map((environment) =>
createAnomalyDetectionJob({ ml, environment, indexPatternName })
)
);
}
const jobResponses = responses.flatMap((response) => response.jobs);
const failedJobs = jobResponses.filter(({ success }) => !success);

if (failedJobs.length > 0) {
const errors = failedJobs.map(({ id, error }) => ({ id, error }));
throw new Error(
`An error occurred while creating ML jobs: ${JSON.stringify(errors)}`
);
}

return jobResponses;
return jobResponses;
});
}

async function createAnomalyDetectionJob({
Expand All @@ -67,34 +72,36 @@ async function createAnomalyDetectionJob({
environment: string;
indexPatternName: string;
}) {
const randomToken = uuid().substr(-4);
return withApmSpan('create_anomaly_detection_job', async () => {
const randomToken = uuid().substr(-4);

return ml.modules.setup({
moduleId: ML_MODULE_ID_APM_TRANSACTION,
prefix: `${APM_ML_JOB_GROUP}-${snakeCase(environment)}-${randomToken}-`,
groups: [APM_ML_JOB_GROUP],
indexPatternName,
applyToAllSpaces: true,
query: {
bool: {
filter: [
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
{ exists: { field: TRANSACTION_DURATION } },
...getEnvironmentUiFilterES(environment),
],
return ml.modules.setup({
moduleId: ML_MODULE_ID_APM_TRANSACTION,
prefix: `${APM_ML_JOB_GROUP}-${snakeCase(environment)}-${randomToken}-`,
groups: [APM_ML_JOB_GROUP],
indexPatternName,
applyToAllSpaces: true,
query: {
bool: {
filter: [
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
{ exists: { field: TRANSACTION_DURATION } },
...getEnvironmentUiFilterES(environment),
],
},
},
},
startDatafeed: true,
jobOverrides: [
{
custom_settings: {
job_tags: {
environment,
// identifies this as an APM ML job & facilitates future migrations
apm_ml_version: 2,
startDatafeed: true,
jobOverrides: [
{
custom_settings: {
job_tags: {
environment,
// identifies this as an APM ML job & facilitates future migrations
apm_ml_version: 2,
},
},
},
},
],
],
});
});
}
Loading

0 comments on commit 927a4c4

Please sign in to comment.