Skip to content

Commit

Permalink
[Usage Collection] [schema] lens (#77929)
Browse files Browse the repository at this point in the history
Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
afharo and elasticmachine authored Sep 24, 2020
1 parent 8ad53d5 commit 4d08763
Show file tree
Hide file tree
Showing 10 changed files with 528 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,9 @@ export const parsedWorkingCollector: ParsedUsageCollection = [
type: 'StringKeyword',
},
my_index_signature_prop: {
'': {
'@@INDEX@@': {
kind: SyntaxKind.NumberKeyword,
type: 'NumberKeyword',
},
'@@INDEX@@': {
kind: SyntaxKind.NumberKeyword,
type: 'NumberKeyword',
},
},
my_objects: {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 24 additions & 2 deletions packages/kbn-telemetry-tools/src/tools/serializer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ export function loadFixtureProgram(fixtureName: string) {
}

describe('getDescriptor', () => {
const usageInterfaces = new Map<string, ts.InterfaceDeclaration>();
const usageInterfaces = new Map<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>();
let tsProgram: ts.Program;
beforeAll(() => {
const { program, sourceFile } = loadFixtureProgram('constants');
tsProgram = program;
for (const node of traverseNodes(sourceFile)) {
if (ts.isInterfaceDeclaration(node)) {
if (ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) {
const interfaceName = node.name.getText();
usageInterfaces.set(interfaceName, node);
}
Expand Down Expand Up @@ -102,4 +102,26 @@ describe('getDescriptor', () => {
'Mapping does not support conflicting union types.'
);
});

it('serializes TypeAliasDeclaration', () => {
const usageInterface = usageInterfaces.get('TypeAliasWithUnion')!;
const descriptor = getDescriptor(usageInterface, tsProgram);
expect(descriptor).toEqual({
locale: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' },
prop1: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' },
prop2: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' },
prop3: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' },
prop4: { kind: ts.SyntaxKind.StringLiteral, type: 'StringLiteral' },
prop5: { kind: ts.SyntaxKind.FirstLiteralToken, type: 'FirstLiteralToken' },
});
});

it('serializes Record entries', () => {
const usageInterface = usageInterfaces.get('TypeAliasWithRecord')!;
const descriptor = getDescriptor(usageInterface, tsProgram);
expect(descriptor).toEqual({
locale: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' },
'@@INDEX@@': { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' },
});
});
});
27 changes: 24 additions & 3 deletions packages/kbn-telemetry-tools/src/tools/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,13 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor |
}
if (ts.isTypeLiteralNode(node) || ts.isInterfaceDeclaration(node)) {
return node.members.reduce((acc, m) => {
acc[m.name?.getText() || ''] = getDescriptor(m, program);
return acc;
}, {} as any);
const key = m.name?.getText();
if (key) {
return { ...acc, [key]: getDescriptor(m, program) };
} else {
return { ...acc, ...getDescriptor(m, program) };
}
}, {});
}

// If it's defined as signature { [key: string]: OtherInterface }
Expand Down Expand Up @@ -114,6 +118,10 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor |
if (symbolName === 'Date') {
return { kind: TelemetryKinds.Date, type: 'Date' };
}
// Support `Record<string, SOMETHING>`
if (symbolName === 'Record' && node.typeArguments![0].kind === ts.SyntaxKind.StringKeyword) {
return { '@@INDEX@@': getDescriptor(node.typeArguments![1], program) };
}
const declaration = (symbol?.getDeclarations() || [])[0];
if (declaration) {
return getDescriptor(declaration, program);
Expand Down Expand Up @@ -157,6 +165,19 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor |
return uniqueKinds[0];
}

// Support `type MyUsageType = SomethingElse`
if (ts.isTypeAliasDeclaration(node)) {
return getDescriptor(node.type, program);
}

// Support `&` unions
if (ts.isIntersectionTypeNode(node)) {
return node.types.reduce(
(acc, unionNode) => ({ ...acc, ...getDescriptor(unionNode, program) }),
{}
);
}

switch (node.kind) {
case ts.SyntaxKind.NumberKeyword:
case ts.SyntaxKind.BooleanKeyword:
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-telemetry-tools/src/tools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export function difference(actual: any, expected: any) {
function (result, value, key) {
if (key && /@@INDEX@@/.test(`${key}`)) {
// The type definition is an Index Signature, fuzzy searching for similar keys
const regexp = new RegExp(`${key}`.replace(/@@INDEX@@/g, '(.+)?'));
const regexp = new RegExp(`^${key}`.replace(/@@INDEX@@/g, '(.+)?'));
const keysInBase = Object.keys(base)
.map((k) => {
const match = k.match(regexp);
Expand Down
4 changes: 4 additions & 0 deletions src/fixtures/telemetry_collectors/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ export const externallyDefinedSchema: MakeSchemaFrom<{ locale: string }> = {
type: 'keyword',
},
};

export type TypeAliasWithUnion = Usage & WithUnion;

export type TypeAliasWithRecord = Usage & Record<string, number>;
1 change: 0 additions & 1 deletion x-pack/.telemetryrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"plugins/apm/server/lib/apm_telemetry/index.ts",
"plugins/canvas/server/collectors/collector.ts",
"plugins/infra/server/usage/usage_collector.ts",
"plugins/lens/server/usage/collectors.ts",
"plugins/reporting/server/usage/reporting_usage_collector.ts",
"plugins/maps/server/maps_telemetry/collectors/register.ts"
]
Expand Down
6 changes: 4 additions & 2 deletions x-pack/plugins/lens/server/usage/collectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { TaskManagerStartContract } from '../../../task_manager/server';

import { LensUsage, LensTelemetryState } from './types';
import { lensUsageSchema } from './schema';

export function registerLensUsageCollector(
usageCollection: UsageCollectionSetup,
Expand All @@ -20,9 +21,9 @@ export function registerLensUsageCollector(
// mark lensUsageCollector as ready to collect when the TaskManager is ready
isCollectorReady = true;
});
const lensUsageCollector = usageCollection.makeUsageCollector({
const lensUsageCollector = usageCollection.makeUsageCollector<LensUsage>({
type: 'lens',
fetch: async (): Promise<LensUsage> => {
async fetch() {
try {
const docs = await getLatestTaskState(await taskManager);
// get the accumulated state from the recurring task
Expand Down Expand Up @@ -55,6 +56,7 @@ export function registerLensUsageCollector(
}
},
isReady: () => isCollectorReady,
schema: lensUsageSchema,
});

usageCollection.registerCollector(lensUsageCollector);
Expand Down
83 changes: 83 additions & 0 deletions x-pack/plugins/lens/server/usage/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { MakeSchemaFrom } from 'src/plugins/usage_collection/server';
import { LensUsage } from './types';

const eventsSchema: MakeSchemaFrom<LensUsage['events_30_days']> = {
app_query_change: { type: 'long' },
indexpattern_field_info_click: { type: 'long' },
loaded: { type: 'long' },
app_filters_updated: { type: 'long' },
app_date_change: { type: 'long' },
save_failed: { type: 'long' },
loaded_404: { type: 'long' },
drop_total: { type: 'long' },
chart_switch: { type: 'long' },
suggestion_confirmed: { type: 'long' },
suggestion_clicked: { type: 'long' },
drop_onto_workspace: { type: 'long' },
drop_non_empty: { type: 'long' },
drop_empty: { type: 'long' },
indexpattern_changed: { type: 'long' },
indexpattern_filters_cleared: { type: 'long' },
indexpattern_type_filter_toggled: { type: 'long' },
indexpattern_existence_toggled: { type: 'long' },
indexpattern_show_all_fields_clicked: { type: 'long' },
drop_onto_dimension: { type: 'long' },
indexpattern_dimension_removed: { type: 'long' },
indexpattern_dimension_field_changed: { type: 'long' },
xy_change_layer_display: { type: 'long' },
xy_layer_removed: { type: 'long' },
xy_layer_added: { type: 'long' },
indexpattern_dimension_operation_terms: { type: 'long' },
indexpattern_dimension_operation_date_histogram: { type: 'long' },
indexpattern_dimension_operation_avg: { type: 'long' },
indexpattern_dimension_operation_min: { type: 'long' },
indexpattern_dimension_operation_max: { type: 'long' },
indexpattern_dimension_operation_sum: { type: 'long' },
indexpattern_dimension_operation_count: { type: 'long' },
indexpattern_dimension_operation_cardinality: { type: 'long' },
indexpattern_dimension_operation_filters: { type: 'long' },
};

const suggestionEventsSchema: MakeSchemaFrom<LensUsage['suggestion_events_30_days']> = {
back_to_current: { type: 'long' },
reload: { type: 'long' },
};

const savedSchema: MakeSchemaFrom<LensUsage['saved_overall']> = {
bar: { type: 'long' },
bar_horizontal: { type: 'long' },
line: { type: 'long' },
area: { type: 'long' },
bar_stacked: { type: 'long' },
bar_percentage_stacked: { type: 'long' },
bar_horizontal_stacked: { type: 'long' },
bar_horizontal_percentage_stacked: { type: 'long' },
area_stacked: { type: 'long' },
area_percentage_stacked: { type: 'long' },
lnsDatatable: { type: 'long' },
lnsPie: { type: 'long' },
lnsMetric: { type: 'long' },
};

export const lensUsageSchema: MakeSchemaFrom<LensUsage> = {
// LensClickUsage
events_30_days: eventsSchema,
events_90_days: eventsSchema,
suggestion_events_30_days: suggestionEventsSchema,
suggestion_events_90_days: suggestionEventsSchema,

// LensVisualizationUsage
saved_overall_total: { type: 'long' },
saved_30_days_total: { type: 'long' },
saved_90_days_total: { type: 'long' },

saved_overall: savedSchema,
saved_30_days: savedSchema,
saved_90_days: savedSchema,
};
Loading

0 comments on commit 4d08763

Please sign in to comment.