-
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
[Telemetry] Report Kibana distro in local collectors + Usage Collectors in TS #55859
Changes from all commits
578defe
153627a
4ef2ad3
18553e4
c79009c
79b67c2
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 |
---|---|---|
|
@@ -17,7 +17,30 @@ | |
* under the License. | ||
*/ | ||
|
||
export class Collector { | ||
import { Logger } from 'kibana/server'; | ||
import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; | ||
|
||
export type CollectorFormatForBulkUpload<T, U> = (result: T) => { type: string; payload: U }; | ||
|
||
export interface CollectorOptions<T = unknown, U = T> { | ||
type: string; | ||
init?: Function; | ||
fetch: (callCluster: CallCluster) => Promise<T> | T; | ||
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. I believe
There is no need to pass generic 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.
If we do it optional, every fetch will need to check if Declaring your usageCollection.makeUsageCollector({
type: KIBANA_REPORTING_TYPE,
isReady,
fetch: () => ({ count: 1 }),
});
The reason for being at the interface level is so An example is |
||
/* | ||
* A hook for allowing the fetched data payload to be organized into a typed | ||
* data model for internal bulk upload. See defaultFormatterForBulkUpload for | ||
* a generic example. | ||
*/ | ||
formatForBulkUpload?: CollectorFormatForBulkUpload<T, U>; | ||
isReady: () => Promise<boolean> | boolean; | ||
} | ||
|
||
export class Collector<T = unknown, U = T> { | ||
public readonly type: CollectorOptions<T, U>['type']; | ||
public readonly init?: CollectorOptions<T, U>['init']; | ||
public readonly fetch: CollectorOptions<T, U>['fetch']; | ||
private readonly _formatForBulkUpload?: CollectorFormatForBulkUpload<T, U>; | ||
public readonly isReady: CollectorOptions<T, U>['isReady']; | ||
/* | ||
* @param {Object} logger - logger object | ||
* @param {String} options.type - property name as the key for the data | ||
|
@@ -27,8 +50,8 @@ export class Collector { | |
* @param {Function} options.rest - optional other properties | ||
*/ | ||
constructor( | ||
logger, | ||
{ type, init, fetch, formatForBulkUpload = null, isReady = null, ...options } = {} | ||
protected readonly log: Logger, | ||
{ type, init, fetch, formatForBulkUpload, isReady, ...options }: CollectorOptions<T, U> | ||
) { | ||
if (type === undefined) { | ||
throw new Error('Collector must be instantiated with a options.type string property'); | ||
|
@@ -42,41 +65,27 @@ export class Collector { | |
throw new Error('Collector must be instantiated with a options.fetch function property'); | ||
} | ||
|
||
this.log = logger; | ||
|
||
Object.assign(this, options); // spread in other properties and mutate "this" | ||
|
||
this.type = type; | ||
this.init = init; | ||
this.fetch = fetch; | ||
|
||
const defaultFormatterForBulkUpload = result => ({ type, payload: result }); | ||
this._formatForBulkUpload = formatForBulkUpload || defaultFormatterForBulkUpload; | ||
if (typeof isReady === 'function') { | ||
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. Lets keep this 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. Sure! I was relying on TS to ensure users will only provide a function here, but I'll add the safety check just in case anyone does it in a |
||
this.isReady = isReady; | ||
} | ||
this.isReady = typeof isReady === 'function' ? isReady : () => true; | ||
this._formatForBulkUpload = formatForBulkUpload; | ||
} | ||
|
||
/* | ||
* @param {Function} callCluster - callCluster function | ||
*/ | ||
fetchInternal(callCluster) { | ||
if (typeof callCluster !== 'function') { | ||
throw new Error('A `callCluster` function must be passed to the fetch methods of collectors'); | ||
public formatForBulkUpload(result: T) { | ||
if (this._formatForBulkUpload) { | ||
return this._formatForBulkUpload(result); | ||
} else { | ||
return this.defaultFormatterForBulkUpload(result); | ||
} | ||
return this.fetch(callCluster); | ||
} | ||
|
||
/* | ||
* A hook for allowing the fetched data payload to be organized into a typed | ||
* data model for internal bulk upload. See defaultFormatterForBulkUpload for | ||
* a generic example. | ||
*/ | ||
formatForBulkUpload(result) { | ||
return this._formatForBulkUpload(result); | ||
} | ||
|
||
isReady() { | ||
throw `isReady() must be implemented in ${this.type} collector`; | ||
protected defaultFormatterForBulkUpload(result: T) { | ||
return { | ||
type: this.type, | ||
payload: result, | ||
}; | ||
} | ||
} |
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.
I'm not sure i understand the difference between the previous code and the current one?
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.
The previous code was only mapping
os.platforms[].platform
andos.platformReleases[].platformRelease
.Now we are copying every element in
kibanaStats.os
(also includingdistro
anddistroRelease
), but following the convention ofos[keyName + "s"] = [ { [keyName]: value, count: 1 } ]
(os[KEY_IN_PLURAL] = Array<{ [KEY]: string, count: number }>
).I can try changing it to something more strict and map the 2 new missing fields (
distro
anddistroRelease
), but that will result in the next time we add something to theos
payload, we'll face this same issue again.