in utils/lib/ecs-logging-validate.js [105:231]
function ecsLoggingValidate (rec, opts) {
opts = opts || {}
const ignoreIndex = !!opts.ignoreIndex
let recObj
let recStr = null
if (typeof (rec) === 'string') {
recStr = rec
try {
recObj = JSON.parse(recStr)
} catch (parseErr) {
return parseErr
}
} else {
recObj = rec
}
const details = []
const addDetail = detail => {
if (ignoreIndex && detail.specKey === 'index') {
return
}
details.push(detail)
}
const spec = loadSpec()
const indexedNames = [] // to handle `field.index`
for (const [name, field] of Object.entries(spec.fields)) {
const specKeysToHandle = Object.assign({}, field)
delete specKeysToHandle.comment
delete specKeysToHandle.url
delete specKeysToHandle.default
const recVal = dottedLookup(recObj, name)
// field.required
if (recVal === undefined) {
if (field.required) {
addDetail({
message: `required field '${name}' is missing`,
specKey: 'required',
name: name,
spec: field
})
}
continue
}
delete specKeysToHandle.required
// field.top_level_field
if (field.top_level_field && !hasOwnProperty.call(recObj, name)) {
addDetail({
message: `field '${name}' is not a top-level field`,
specKey: 'top_level_field',
name: name,
spec: field
})
}
delete specKeysToHandle.top_level_field
// field.index
if (field.index !== undefined) {
indexedNames[field.index] = name
}
delete specKeysToHandle.index
// field.type
switch (field.type) {
case 'datetime':
// We'll use the approximation that if JavaScript's `new Date()` can
// handle it, that it roughly satisfies:
// https://www.elastic.co/guide/en/elasticsearch/reference/current/date.html
if (new Date(recVal).toString() === 'Invalid Date') {
addDetail({
message: `field '${name}' is not a valid '${field.type}'`,
specKey: 'type',
name: name,
spec: field
})
}
break
case 'string':
if (typeof (recVal) !== 'string') {
addDetail({
message: `field '${name}' is not a valid '${field.type}'`,
specKey: 'type',
name: name,
spec: field
})
}
break
default:
throw new Error(`unknown field type: ${field.type}`)
}
delete specKeysToHandle.type
if (Object.keys(specKeysToHandle).length !== 0) {
throw new Error('do not know how to handle these ecs-logging spec ' +
`fields from field '${name}': ${Object.keys(specKeysToHandle).join(', ')}`)
}
}
// field.index
if (indexedNames.length > 0 && recStr) {
let expected = ['{']
indexedNames.forEach(n => {
expected.push('"')
expected.push(n)
expected.push('":')
expected.push(JSON.stringify(dottedLookup(recObj, n)))
expected.push(',')
})
expected = expected.join('')
if (!recStr.startsWith(expected)) {
addDetail({
message: `the order of fields is not the expected: ${indexedNames.join(', ')}`,
specKey: 'index'
})
}
}
if (details.length === 0) {
return null
} else {
return new EcsLoggingValidationError(details)
}
}