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

[Fleet] Add support for additional types for dynamic mappings #168842

Merged
merged 11 commits into from
Oct 17, 2023
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':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some types that are not specified in the object_type field definition in package-spec: ip, wildcard, group or match_only_text

Should these be added too here?

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':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be added unsigned_long too ?
It is also an allowed object_type according to package-spec:
https://github.com/elastic/package-spec/blob/a4b0a7ff139c9b85e44602caeb83d93716c1f4d8/spec/integration/data_stream/fields/fields.spec.yml#L488

// 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((dynField) => ({
...dynField,
type: 'object',
object_type: dynField.object_type ?? dynField.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