-
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 2 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 = isReady; | ||
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, | ||
}; | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { KIBANA_STATS_TYPE } from '../../common/constants'; | ||
import { Collector } from './collector'; | ||
|
||
export class UsageCollector<T = unknown, U = { usage: { [key: string]: T } }> extends Collector< | ||
T, | ||
U | ||
> { | ||
protected defaultUsageFormatterForBulkUpload(result: T) { | ||
return { | ||
type: KIBANA_STATS_TYPE, | ||
payload: { | ||
usage: { | ||
[this.type]: 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.