Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[APM] Agent remote config: validation for Java agent configs #63956

Merged
merged 18 commits into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,87 @@ describe('durationRt', () => {
});

describe('getDurationRt', () => {
const customDurationRt = getDurationRt({ min: -1 });
describe('it should not accept', () => {
[undefined, null, '', 0, 'foo', true, false, '100', 's', 'm', '-2ms'].map(
input => {
describe('must be at least 1m', () => {
const customDurationRt = getDurationRt({ min: '1m' });
describe('it should not accept', () => {
[
undefined,
null,
'',
0,
'foo',
true,
false,
'0m',
'-1m',
'1ms',
'1s'
].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeFalsy();
});
});
});
describe('it should accept', () => {
['1m', '2m', '1000m'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBe(false);
expect(isRight(customDurationRt.decode(input))).toBeTruthy();
});
}
);
});
});
});

describe('it should accept', () => {
['1000ms', '2s', '3m', '1s', '-1s', '0ms'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBe(true);
describe('must be between 1ms and 1s', () => {
const customDurationRt = getDurationRt({ min: '1ms', max: '1s' });

describe('it should not accept', () => {
[
undefined,
null,
'',
0,
'foo',
true,
false,
'-1s',
'0s',
'2s',
'1001ms',
'0ms',
'-1ms',
'0m',
'1m'
].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeFalsy();
});
});
});
describe('it should accept', () => {
['1s', '1ms', '50ms', '1000ms'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeTruthy();
});
});
});
});
describe('must be max 1m', () => {
const customDurationRt = getDurationRt({ max: '1m' });

describe('it should not accept', () => {
[undefined, null, '', 0, 'foo', true, false, '2m', '61s', '60001ms'].map(
input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeFalsy();
});
}
);
});
describe('it should accept', () => {
['1m', '0m', '-1m', '60s', '6000ms', '1ms', '1s'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeTruthy();
});
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,35 @@

import * as t from 'io-ts';
import { either } from 'fp-ts/lib/Either';
import moment, { unitOfTime } from 'moment';
import { amountAndUnitToObject } from '../amount_and_unit';

export const DURATION_UNITS = ['ms', 's', 'm'];

export function getDurationRt({ min }: { min: number }) {
function getDuration({ amount, unit }: { amount: string; unit: string }) {
return moment.duration(parseInt(amount, 10), unit as unitOfTime.Base);
}

export function getDurationRt({ min, max }: { min?: string; max?: string }) {
return new t.Type<string, string, unknown>(
'durationRt',
t.string.is,
(input, context) => {
return either.chain(t.string.validate(input, context), inputAsString => {
const { amount, unit } = amountAndUnitToObject(inputAsString);
const amountAsInt = parseInt(amount, 10);
const inputDuration = getDuration({ amount, unit });
const minDuration = min
? getDuration(amountAndUnitToObject(min))
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved
: inputDuration;
const maxDuration = max
? getDuration(amountAndUnitToObject(max))
: inputDuration;

const isValidUnit = DURATION_UNITS.includes(unit);
const isValid = amountAsInt >= min && isValidUnit;
const isValidAmount =
inputDuration >= minDuration && inputDuration <= maxDuration;

return isValid
return isValidUnit && isValidAmount
? t.success(inputAsString)
: t.failure(
input,
Expand All @@ -34,4 +47,4 @@ export function getDurationRt({ min }: { min: number }) {
);
}

export const durationRt = getDurationRt({ min: 1 });
export const durationRt = getDurationRt({ min: '1ms' });

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export const generalSettings: RawSettingDefinition[] = [
{
key: 'span_frames_min_duration',
type: 'duration',
validation: getDurationRt({ min: -1 }),
validation: getDurationRt({ min: '-1ms' }),
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved
defaultValue: '5ms',
label: i18n.translate('xpack.apm.agentConfig.spanFramesMinDuration.label', {
defaultMessage: 'Span frames minimum duration'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { i18n } from '@kbn/i18n';
import { RawSettingDefinition } from './types';
import { getDurationRt } from '../runtime_types/duration_rt';

export const javaSettings: RawSettingDefinition[] = [
// ENABLE_LOG_CORRELATION
Expand Down Expand Up @@ -99,7 +100,12 @@ export const javaSettings: RawSettingDefinition[] = [
'The minimal time required in order to determine whether the system is either currently under stress, or that the stress detected previously has been relieved. All measurements during this time must be consistent in comparison to the relevant threshold in order to detect a change of stress state. Must be at least `1m`.'
}
),
includeAgents: ['java']
includeAgents: ['java'],
validation: getDurationRt({ min: '1m' }),
validationError: i18n.translate(
'xpack.apm.agentConfig.stressMonitorCpuDurationThreshold.errorText',
{ defaultMessage: "Must be at least '1m'" }
)
},
{
key: 'stress_monitor_system_cpu_stress_threshold',
Expand Down Expand Up @@ -176,7 +182,12 @@ export const javaSettings: RawSettingDefinition[] = [
'The frequency at which stack traces are gathered within a profiling session. The lower you set it, the more accurate the durations will be. This comes at the expense of higher overhead and more spans for potentially irrelevant operations. The minimal duration of a profiling-inferred span is the same as the value of this setting.'
}
),
includeAgents: ['java']
includeAgents: ['java'],
validation: getDurationRt({ min: '1ms', max: '1s' }),
validationError: i18n.translate(
'xpack.apm.agentConfig.profilingInferredSpansSamplingInterval.errorText',
{ defaultMessage: "Must be between '1ms' and '1s'" }
)
},
{
key: 'profiling_inferred_spans_min_duration',
Expand Down