Skip to content

Commit

Permalink
[Fleet] fix dynamic mapping missing time_series_metric (elastic#160417
Browse files Browse the repository at this point in the history
)

## Summary

Closes elastic#155004

Found a simplification of adding `time_series_metric` to
`dynamic_templates`.

I think tsdb enabled check is not needed similarly to
elastic#157047

To test:
- Install package by upload or local registry
[istio-0.3.3.zip](https://github.com/elastic/kibana/files/11849494/istio-0.3.3.zip)
- Check that the created `metrics-istio.istiod_metric`s index template
includes `time_series_metric`
```
"dynamic_templates": [
        {
          "istio.istiod.metrics.*.counter": {
            "path_match": "istio.istiod.metrics.*.counter",
            "mapping": {
              "time_series_metric": "counter",
              "type": "double"
            }
          }
        },
        {
```

(cherry picked from commit 863f6bd)
  • Loading branch information
juliaElastic committed Jun 23, 2023
1 parent c61a4d8 commit 85256a2
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ export function prepareTemplate({
dataStream.elasticsearch?.index_mode === 'time_series' ||
experimentalDataStreamFeature?.features.tsdb;

const validFields = processFields(fields, isIndexModeTimeSeries);
const validFields = processFields(fields);

const mappings = generateMappings(validFields);
const templateName = generateTemplateName(dataStream);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ function _generateMappings(
case 'boolean':
dynProperties = {
type: field.object_type,
time_series_metric: field.metric_type,
};
matchingType = field.object_type_mapping_type ?? field.object_type;
default:
Expand Down
47 changes: 3 additions & 44 deletions x-pack/plugins/fleet/server/services/epm/fields/field.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -672,15 +672,6 @@ describe('processFields', () => {
});

describe('processFieldsWithWildcard', () => {
const wildcardYml = `
- name: a.*.b
type: long
format: bytes
unit: byte
metric_type: gauge
description: |
Total swap memory.
`;
const wildcardWithObjectTypeYml = `
- name: a.*.b
type: long
Expand All @@ -703,11 +694,10 @@ describe('processFields', () => {
`;

const noWildcardFields: Field[] = safeLoad(noWildcardYml);
const wildcardFields: Field[] = safeLoad(wildcardYml);
const wildcardWithObjectTypeFields: Field[] = safeLoad(wildcardWithObjectTypeYml);

test('Does not add object type when object_type field when is alraedy defined and name has wildcard', () => {
expect(processFieldsWithWildcard(wildcardWithObjectTypeFields, false)).toMatchInlineSnapshot(`
test('Does not add object type when object_type field when is already defined and name has wildcard', () => {
expect(processFieldsWithWildcard(wildcardWithObjectTypeFields)).toMatchInlineSnapshot(`
[
{
"name": "a.*.b",
Expand All @@ -721,40 +711,9 @@ describe('processFields', () => {
]
`);
});
test('Replaces metric_type with time_series_metric field when tsds is enabled and name has wildcard', () => {
expect(processFieldsWithWildcard(wildcardFields, true)).toMatchInlineSnapshot(`
[
{
"name": "a.*.b",
"type": "object",
"format": "bytes",
"unit": "byte",
"description": "Total swap memory.\\n",
"object_type": "long",
"time_series_metric": "gauge"
}
]
`);
});

test('Returns metric_type input field when tsds is disabled', () => {
expect(processFieldsWithWildcard(wildcardFields, false)).toMatchInlineSnapshot(`
[
{
"name": "a.*.b",
"type": "object",
"format": "bytes",
"unit": "byte",
"metric_type": "gauge",
"description": "Total swap memory.\\n",
"object_type": "long"
}
]
`);
});

test('Returns input fields when name has no wildcard', () => {
expect(processFieldsWithWildcard(noWildcardFields, true)).toMatchInlineSnapshot(`
expect(processFieldsWithWildcard(noWildcardFields)).toMatchInlineSnapshot(`
[
{
"name": "test",
Expand Down
25 changes: 4 additions & 21 deletions x-pack/plugins/fleet/server/services/epm/fields/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

import { safeLoad } from 'js-yaml';
import { omit } from 'lodash';

import type { PackageInfo } from '../../../types';
import { getAssetsData } from '../packages/assets';
Expand Down Expand Up @@ -48,7 +47,6 @@ export interface Field {
// Meta fields
metric_type?: string;
unit?: string;
time_series_metric?: string;

// Kibana specific
analyzed?: boolean;
Expand Down Expand Up @@ -254,15 +252,11 @@ export const getField = (fields: Fields, pathNames: string[]): Field | undefined
return undefined;
};

export function processFieldsWithWildcard(
fields: Fields,
isIndexModeTimeSeries: boolean | undefined
): Fields {
export function processFieldsWithWildcard(fields: Fields): Fields {
const newFields: Fields = [];
for (const field of fields) {
const objectTypeField = processFieldWithoutObjectType(field);
const processedField = processFieldWithTimeSeries(objectTypeField, isIndexModeTimeSeries);
newFields.push({ ...processedField });
newFields.push({ ...objectTypeField });
}
return newFields;
}
Expand All @@ -277,19 +271,8 @@ export function processFieldWithoutObjectType(field: Field): Field {
}
}

export function processFieldWithTimeSeries(
field: Field,
isIndexModeTimeSeries: boolean | undefined
): Field {
if (isIndexModeTimeSeries && field.name.includes('*') && 'metric_type' in field) {
return { ...omit(field, 'metric_type'), type: 'object', time_series_metric: field.metric_type };
} else {
return { ...field };
}
}

export function processFields(fields: Fields, isIndexModeTimeSeries?: boolean): Fields {
const processedFields = processFieldsWithWildcard(fields, isIndexModeTimeSeries);
export function processFields(fields: Fields): Fields {
const processedFields = processFieldsWithWildcard(fields);
const expandedFields = expandFields(processedFields);
const dedupedFields = dedupFields(expandedFields);

Expand Down
1 change: 1 addition & 0 deletions x-pack/test/fleet_api_integration/apis/epm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ export default function loadTests({ loadTestFile, getService }) {
loadTestFile(require.resolve('./install_integration_in_multiple_spaces.ts'));
loadTestFile(require.resolve('./install_hidden_datastreams'));
loadTestFile(require.resolve('./bulk_get_assets'));
loadTestFile(require.resolve('./install_dynamic_template_metric'));
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../api_integration/ftr_provider_context';
import { skipIfNoDockerRegistry } from '../../helpers';
import { setupFleetAndAgents } from '../agents/services';

export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertest = getService('supertest');
const es = getService('es');

const deletePackage = async (name: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx');
};

describe('metric_type with dynamic_templates', async () => {
skipIfNoDockerRegistry(providerContext);
setupFleetAndAgents(providerContext);

after(async () => {
await deletePackage('istio', '0.3.3');
});

it('should install with metric_type added as time_series_metric', async function () {
const templateName = 'metrics-istio.istiod_metrics@package';

await supertest
.post(`/api/fleet/epm/packages/istio/0.3.3`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);

const { body: resp } = await es.transport.request<any>(
{
method: 'GET',
path: `/_component_template/${templateName}`,
},
{ meta: true }
);

const template = resp.component_templates[0].component_template;
const dynamicTemplates = template.template.mappings.dynamic_templates;
const mappingName = 'istio.istiod.metrics.*.counter';
const counter = dynamicTemplates.find((tmpl: any) => Object.keys(tmpl)[0] === mappingName);

expect(counter[mappingName].mapping.time_series_metric).to.eql('counter');
});
});
}
Binary file not shown.

0 comments on commit 85256a2

Please sign in to comment.