-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[data views] More efficient telemetry collection #152298
Changes from 2 commits
03457cb
dc1c978
aa5b559
63d8836
9cb6a5f
bcc4ab8
e575341
cfa68df
eea5c03
518aea8
e025579
30af38c
c8c8f07
8142f67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,8 +8,13 @@ | |
|
||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; | ||
import { StartServicesAccessor } from '@kbn/core/server'; | ||
import { SavedObjectsClient } from '@kbn/core/server'; | ||
import { DataViewsContract } from '../common'; | ||
import { SavedObjectsClient, SavedObjectsCreatePointInTimeFinderOptions } from '@kbn/core/server'; | ||
import { | ||
DATA_VIEW_SAVED_OBJECT_TYPE, | ||
DataViewAttributes, | ||
FieldSpec, | ||
RuntimeField, | ||
} from '../common'; | ||
import { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from './types'; | ||
|
||
interface CountSummary { | ||
|
@@ -18,6 +23,8 @@ interface CountSummary { | |
avg?: number; | ||
} | ||
|
||
type DataViewFieldAttrs = Pick<DataViewAttributes, 'fields' | 'runtimeFieldMap'>; | ||
|
||
interface IndexPatternUsage { | ||
indexPatternsCount: number; | ||
indexPatternsWithScriptedFieldCount: number; | ||
|
@@ -57,17 +64,15 @@ export const updateMax = (currentMax: number | undefined, newVal: number): numbe | |
} | ||
}; | ||
|
||
export async function getIndexPatternTelemetry(indexPatterns: DataViewsContract) { | ||
const ids = await indexPatterns.getIds(); | ||
|
||
export async function getIndexPatternTelemetry(savedObjectsService: SavedObjectsClient) { | ||
const countSummaryDefaults: CountSummary = { | ||
min: undefined, | ||
max: undefined, | ||
avg: undefined, | ||
}; | ||
|
||
const results = { | ||
indexPatternsCount: ids.length, | ||
indexPatternsCount: 0, | ||
indexPatternsWithScriptedFieldCount: 0, | ||
indexPatternsWithRuntimeFieldCount: 0, | ||
scriptedFieldCount: 0, | ||
|
@@ -80,60 +85,74 @@ export async function getIndexPatternTelemetry(indexPatterns: DataViewsContract) | |
}, | ||
}; | ||
|
||
await ids.reduce(async (col, id) => { | ||
await col; | ||
const ip = await indexPatterns.get(id); | ||
const findOptions: SavedObjectsCreatePointInTimeFinderOptions = { | ||
type: DATA_VIEW_SAVED_OBJECT_TYPE, | ||
perPage: 1000, | ||
fields: ['attributes.fields', 'attributes.runtimeFieldMap'], | ||
}; | ||
|
||
const scriptedFields = ip.getScriptedFields(); | ||
const runtimeFields = ip.fields.filter((fld) => !!fld.runtimeField); | ||
const finder = savedObjectsService.createPointInTimeFinder<DataViewFieldAttrs>(findOptions); | ||
|
||
if (scriptedFields.length > 0) { | ||
// increment counts | ||
results.indexPatternsWithScriptedFieldCount++; | ||
results.scriptedFieldCount += scriptedFields.length; | ||
for await (const response of finder.find()) { | ||
const { saved_objects: savedObjects, total } = response; | ||
results.indexPatternsCount = total; | ||
|
||
// calc LoC | ||
results.perIndexPattern.scriptedFieldLineCount = minMaxAvgLoC( | ||
scriptedFields.map((fld) => fld.script || '') | ||
); | ||
|
||
// calc field counts | ||
results.perIndexPattern.scriptedFieldCount.min = updateMin( | ||
results.perIndexPattern.scriptedFieldCount.min, | ||
scriptedFields.length | ||
); | ||
results.perIndexPattern.scriptedFieldCount.max = updateMax( | ||
results.perIndexPattern.scriptedFieldCount.max, | ||
scriptedFields.length | ||
); | ||
results.perIndexPattern.scriptedFieldCount.avg = | ||
results.scriptedFieldCount / results.indexPatternsWithScriptedFieldCount; | ||
} | ||
|
||
if (runtimeFields.length > 0) { | ||
// increment counts | ||
results.indexPatternsWithRuntimeFieldCount++; | ||
results.runtimeFieldCount += runtimeFields.length; | ||
savedObjects.forEach((obj) => { | ||
const fields = JSON.parse(obj.attributes.fields) || []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the JSON.parse threw an exception locally, so it's recommendable to use a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I had failed to push a change. I also changed the default data view definition in the test not to have the attributes that are used as to provide test coverage. |
||
const runtimeFieldsMap = obj.attributes.runtimeFieldMap | ||
? JSON.parse(obj.attributes.runtimeFieldMap) || {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also a candidate for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mattkime Telemetry stats now work as excepted 👍 ... one think I still think worth to consider is using a |
||
: {}; | ||
const scriptedFields: FieldSpec[] = fields.filter((fld: FieldSpec) => !!fld.script); | ||
// to array | ||
const runtimeFields: RuntimeField[] = Object.values(runtimeFieldsMap); | ||
|
||
// calc LoC | ||
const runtimeFieldScripts = runtimeFields.map( | ||
(fld) => fld.runtimeField?.script?.source || '' | ||
); | ||
results.perIndexPattern.runtimeFieldLineCount = minMaxAvgLoC(runtimeFieldScripts); | ||
|
||
// calc field counts | ||
results.perIndexPattern.runtimeFieldCount.min = updateMin( | ||
results.perIndexPattern.runtimeFieldCount.min, | ||
runtimeFields.length | ||
); | ||
results.perIndexPattern.runtimeFieldCount.max = updateMax( | ||
results.perIndexPattern.runtimeFieldCount.max, | ||
runtimeFields.length | ||
); | ||
results.perIndexPattern.runtimeFieldCount.avg = | ||
results.runtimeFieldCount / results.indexPatternsWithRuntimeFieldCount; | ||
} | ||
}, Promise.resolve()); | ||
if (scriptedFields.length > 0) { | ||
// increment counts | ||
results.indexPatternsWithScriptedFieldCount++; | ||
results.scriptedFieldCount += scriptedFields.length; | ||
|
||
// calc LoC | ||
results.perIndexPattern.scriptedFieldLineCount = minMaxAvgLoC( | ||
scriptedFields.map((fld) => fld.script || '') | ||
); | ||
|
||
// calc field counts | ||
results.perIndexPattern.scriptedFieldCount.min = updateMin( | ||
results.perIndexPattern.scriptedFieldCount.min, | ||
scriptedFields.length | ||
); | ||
results.perIndexPattern.scriptedFieldCount.max = updateMax( | ||
results.perIndexPattern.scriptedFieldCount.max, | ||
scriptedFields.length | ||
); | ||
results.perIndexPattern.scriptedFieldCount.avg = | ||
results.scriptedFieldCount / results.indexPatternsWithScriptedFieldCount; | ||
} | ||
|
||
if (runtimeFields.length > 0) { | ||
// increment counts | ||
results.indexPatternsWithRuntimeFieldCount++; | ||
results.runtimeFieldCount += runtimeFields.length; | ||
|
||
// calc LoC | ||
const runtimeFieldScripts = runtimeFields.map((fld) => fld.script?.source || ''); | ||
results.perIndexPattern.runtimeFieldLineCount = minMaxAvgLoC(runtimeFieldScripts); | ||
|
||
// calc field counts | ||
results.perIndexPattern.runtimeFieldCount.min = updateMin( | ||
results.perIndexPattern.runtimeFieldCount.min, | ||
runtimeFields.length | ||
); | ||
results.perIndexPattern.runtimeFieldCount.max = updateMax( | ||
results.perIndexPattern.runtimeFieldCount.max, | ||
runtimeFields.length | ||
); | ||
results.perIndexPattern.runtimeFieldCount.avg = | ||
results.runtimeFieldCount / results.indexPatternsWithRuntimeFieldCount; | ||
} | ||
}); | ||
} | ||
|
||
return results; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. console.log here to see results. results are encrypted in the http response. You may need to restart kibana to run this multiple times. |
||
} | ||
|
@@ -153,14 +172,10 @@ export function registerIndexPatternsUsageCollector( | |
type: 'index-patterns', | ||
isReady: () => true, | ||
fetch: async () => { | ||
const [{ savedObjects, elasticsearch }, , { dataViewsServiceFactory }] = | ||
await getStartServices(); | ||
const indexPatternService = await dataViewsServiceFactory( | ||
new SavedObjectsClient(savedObjects.createInternalRepository()), | ||
elasticsearch.client.asInternalUser | ||
); | ||
|
||
return await getIndexPatternTelemetry(indexPatternService); | ||
const [{ savedObjects }] = await getStartServices(); | ||
|
||
const savedObjectsService = new SavedObjectsClient(savedObjects.createInternalRepository()); | ||
return await getIndexPatternTelemetry(savedObjectsService); | ||
}, | ||
schema: { | ||
indexPatternsCount: { type: 'long' }, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also call
finder.close()
or it's not required?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its not needed with the for loop.