Skip to content

Commit

Permalink
[Fleet] Add support for additional types for dynamic mappings
Browse files Browse the repository at this point in the history
Add support for fields that generate and dynamic mapping of the
following types:
- scaled_float
- half_float
- match_only_text
- aggregate_metric_double
- ip
- integer (mapped as long as in other cases)
- group (child fields are installed as dynamic mappings)

When the type is not known, an error is raised now
instead of silently ignoring the field definition.
  • Loading branch information
jsoriano committed Oct 13, 2023
1 parent eee0d4d commit 0855613
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,105 @@ describe('EPM template', () => {
expect(mappings).toEqual(runtimeFieldMapping);
});

it('tests processing scaled_float fields in a dynamic template', () => {
const textWithRuntimeFieldsLiteralYml = `
- name: numeric_labels
type: object
object_type: scaled_float
`;
const runtimeFieldMapping = {
properties: {},
dynamic_templates: [
{
'numeric_labels': {
match_mapping_type: '*',
path_match: 'numeric_labels.*',
mapping: {
type: 'scaled_float',
scaling_factor: 1000,
},
},
},
],
};
const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml);
const processedFields = processFields(fields);
const mappings = generateMappings(processedFields);
expect(mappings).toEqual(runtimeFieldMapping);
});

it('tests processing aggregate_metric_double fields in a dynamic template', () => {
const textWithRuntimeFieldsLiteralYml = `
- name: aggregate.*
type: aggregate_metric_double
metrics: ["min", "max", "sum", "value_count"]
default_metric: "max"
`;
const runtimeFieldMapping = {
properties: {},
dynamic_templates: [
{
'aggregate.*': {
match_mapping_type: '*',
path_match: 'aggregate.*',
mapping: {
type: 'aggregate_metric_double',
metrics: ["min", "max", "sum", "value_count"],
default_metric: "max"
},
},
},
],
};
const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml);
const processedFields = processFields(fields);
const mappings = generateMappings(processedFields);
expect(mappings).toEqual(runtimeFieldMapping);
});

it('tests processing groub sub fields in a dynamic template', () => {
const textWithRuntimeFieldsLiteralYml = `
- name: group.*.network
type: group
fields:
- name: bytes
type: integer
metric_type: counter
`;
const runtimeFieldMapping = {
properties: {},
dynamic_templates: [
{
'group.*.network.bytes': {
match_mapping_type: 'long',
path_match: 'group.*.network.bytes',
mapping: {
type: 'long',
time_series_metric: 'counter',
},
},
},
],
};
const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml);
const processedFields = processFields(fields);
const mappings = generateMappings(processedFields);
expect(mappings).toEqual(runtimeFieldMapping);
});

it('tests unexpected type for field as dynamic template fails', () => {
const textWithRuntimeFieldsLiteralYml = `
- name: labels.*
type: object
object_type: constant_keyword
`;
const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml);
expect(() => {
const processedFields = processFields(fields);
const mappings = generateMappings(processedFields);
}).toThrow();
});

it('tests priority and index pattern for data stream without dataset_is_prefix', () => {
const dataStreamDatasetIsPrefixUnset = {
type: 'metrics',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,8 @@ function _generateMappings(
case 'double':
case 'long':
case 'boolean':
dynProperties = {
type: field.object_type,
time_series_metric: field.metric_type,
};
dynProperties.type = field.object_type;
dynProperties.time_series_metric = field.metric_type;
matchingType = field.object_type_mapping_type ?? field.object_type;
default:
break;
Expand Down Expand Up @@ -258,27 +256,64 @@ function _generateMappings(
dynProperties = histogram(field);
matchingType = field.object_type_mapping_type ?? '*';
break;
case 'ip':
case 'keyword':
case 'match_only_text':
case 'text':
case 'wildcard':
dynProperties.type = field.object_type;
matchingType = field.object_type_mapping_type ?? 'string';
break;
case 'keyword':
case 'scaled_float':
dynProperties = scaledFloat(field);
matchingType = field.object_type_mapping_type ?? '*';
break;
case 'aggregate_metric_double':
dynProperties.type = field.object_type;
matchingType = field.object_type_mapping_type ?? 'string';
dynProperties.metrics = field.metrics;
dynProperties.default_metric = field.default_metric;
matchingType = field.object_type_mapping_type ?? '*';
break;
case 'byte':
case 'double':
case 'float':
case 'half_float':
dynProperties.type = field.object_type;
dynProperties.time_series_metric = field.metric_type;
matchingType = field.object_type_mapping_type ?? 'double';
break;
case 'byte':
case 'long':
case 'short':
dynProperties.type = field.object_type;
dynProperties.time_series_metric = field.metric_type;
matchingType = field.object_type_mapping_type ?? 'long';
break;
case 'integer':
// Map integers as long, as in other cases.
dynProperties.type = 'long';
dynProperties.time_series_metric = field.metric_type;
matchingType = field.object_type_mapping_type ?? 'long';
break;
case 'boolean':
dynProperties = {
type: field.object_type,
time_series_metric: field.metric_type,
};
dynProperties.type = field.object_type;
dynProperties.time_series_metric = field.metric_type;
matchingType = field.object_type_mapping_type ?? field.object_type;
default:
break;
case 'group':
const fields = field.fields.map((field) => ({
...field,
type: 'object',
object_type: field.object_type ?? field.type,
}))
_generateMappings(fields, {
...ctx,
groupFieldName: ctx.groupFieldName
? `${ctx.groupFieldName}.${field.name}`
: field.name,
});
break;
default:
throw new Error(`no dynamic mapping generated for field ${path} of type ${field.object_type}`);
}

if (dynProperties && matchingType) {
Expand Down

0 comments on commit 0855613

Please sign in to comment.