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 2 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,77 @@ 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('min/max amount validation', () => {
const customDurationRt = getDurationRt({ min: -1, max: 10 });
describe('it should not accept', () => {
['-2ms', '-3s', '11m'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeFalsy();
});
});
});
describe('it should accept', () => {
['-1ms', '0s', '1m', '10ms'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeTruthy();
});
});
});
});
describe('unit validation', () => {
const customDurationRt = getDurationRt({ unit: 'ms' });
describe('it should not accept', () => {
['-2s', '-3s', '11m'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(customDurationRt.decode(input))).toBeFalsy();
});
});
});
describe('it should accept', () => {
['-1ms', '0ms', '1ms', '10ms'].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 at least 1m', () => {
const customDurationRt = getDurationRt({ min: 1, unit: 'm' });
describe('it should not accept', () => {
['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))).toBeTruthy();
});
});
});
});

describe('must be between 1ms(1ms - 1000ms) and 1s', () => {
const customDurationRt = getDurationRt([
{ min: 1, max: 1, unit: 's' },
{ min: 1, max: 1000, unit: 'ms' }
]);

describe('it should not accept', () => {
['-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();
});
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,38 @@ import * as t from 'io-ts';
import { either } from 'fp-ts/lib/Either';
import { amountAndUnitToObject } from '../amount_and_unit';

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

export function getDurationRt({ min }: { min: number }) {
interface Criteria {
min?: number;
max?: number;
unit?: DurationUnit;
}
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved

function validateDuration(inputAsString: string, { min, max, unit }: Criteria) {
const { amount, unit: inputUnit } = amountAndUnitToObject(inputAsString);
const amountAsInt = parseInt(amount, 10);
const isValidUnit =
DURATION_UNITS.includes(inputUnit) && (unit ? unit === inputUnit : true);

const isValidAmount =
(min ? amountAsInt >= min : true) && (max ? amountAsInt <= max : true);

return isValidUnit && isValidAmount;
}

export function getDurationRt(criteria: Criteria | Criteria[]) {
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 isValidUnit = DURATION_UNITS.includes(unit);
const isValid = amountAsInt >= min && isValidUnit;
const isValid = Array.isArray(criteria)
? criteria
.map(_criteria => validateDuration(inputAsString, _criteria))
.some(result => result)
: validateDuration(inputAsString, criteria);

return isValid
? t.success(inputAsString)
Expand Down

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 @@ -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,14 @@ 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:
// must be at least 1m
getDurationRt({ min: 1, unit: 'm' }),
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 +184,16 @@ 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([
// must be between 1ms(1ms - 1000ms) and 1s
{ min: 1, max: 1, unit: 's' },
{ min: 1, max: 1000, unit: 'ms' }
]),
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved
validationError: i18n.translate(
'xpack.apm.agentConfig.profilingInferredSpansSamplingInterval.errorText',
{ defaultMessage: "Must be between '1ms' and '1s'" }
)
},
{
key: 'profiling_inferred_spans_min_duration',
Expand Down