Skip to content
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] Analytics Package #41113

Merged
merged 55 commits into from
Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
810f94a
kbn-analytics
Bamieh Jul 5, 2019
1983529
kbn-analytics
Bamieh Jul 6, 2019
b41e18b
expose provider
Bamieh Jul 10, 2019
932a189
add logger
Bamieh Jul 11, 2019
bc8e470
performance and stats reporters
Bamieh Jul 14, 2019
3dff33d
merge master
Bamieh Jul 15, 2019
77d6cad
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 15, 2019
32fcbe4
finalize ui stats metric
Bamieh Jul 15, 2019
ea44a6c
functional tests
Bamieh Jul 15, 2019
1d4a663
remove readme file for now
Bamieh Jul 15, 2019
69006f9
update readme
Bamieh Jul 15, 2019
1c4a0d0
add types file into to tsconfigs
Bamieh Jul 15, 2019
ccd7d69
Update packages/kbn-analytics/src/report.ts
Bamieh Jul 15, 2019
6bc1caf
fix typechecks
Bamieh Jul 15, 2019
4c46ff0
Merge branch 'telemetry/move_ui_metric' of github.com:Bamieh/kibana i…
Bamieh Jul 15, 2019
75bd6ba
use enum instead of strings for metric types
Bamieh Jul 16, 2019
5a0b833
getUiStatsReporter -> createUiStatsReporter
Bamieh Jul 16, 2019
44b0ec4
fix special typo in README
Bamieh Jul 16, 2019
aa434f6
remove unused stop method
Bamieh Jul 16, 2019
1665a22
fix tests
Bamieh Jul 16, 2019
121fcd3
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 16, 2019
321cceb
josh meeting fixes
Bamieh Jul 17, 2019
920b222
default debug to false
Bamieh Jul 17, 2019
b3baca6
use chrome.getInjected
Bamieh Jul 17, 2019
eabe9e3
add METRIC_TYPE to jest module mocks
Bamieh Jul 17, 2019
210b8a3
mock create fn
Bamieh Jul 17, 2019
131e829
handle enabled:false
Bamieh Jul 17, 2019
7a5db03
init ui_metric in test setup env
Bamieh Jul 17, 2019
c128c7b
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 17, 2019
8bd4ef4
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 17, 2019
3dfd554
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 17, 2019
ee3fc7d
regenerator runtime
Bamieh Jul 17, 2019
331f900
transform-regenerator
Bamieh Jul 17, 2019
4d86435
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 18, 2019
1efc619
update lock file
Bamieh Jul 18, 2019
257ebea
update babel configs
Bamieh Jul 18, 2019
94de087
runtime dep
Bamieh Jul 18, 2019
12626e2
add regenerator
Bamieh Jul 18, 2019
2e76e78
babel configs
Bamieh Jul 19, 2019
6925b29
fix conflicts
Bamieh Jul 19, 2019
e1b7cde
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 20, 2019
1996c25
use env-preset
Bamieh Jul 20, 2019
9d63270
merge conflicts
Bamieh Jul 20, 2019
a0780e4
fix workpad telemetry tests
Bamieh Jul 20, 2019
4a20e69
regeneratorRuntime attempt to fix number 30000
Bamieh Jul 20, 2019
d42a807
env targets
Bamieh Jul 20, 2019
c564076
remove module config
Bamieh Jul 21, 2019
1987e8d
try again
Bamieh Jul 21, 2019
0278589
try without regenerator
Bamieh Jul 21, 2019
5c52b30
use kbn/babel-preset/webpack_preset only
Bamieh Jul 21, 2019
487677e
runtime
Bamieh Jul 21, 2019
79fd372
just use typescript
Bamieh Jul 21, 2019
fb18982
update tsconfig
Bamieh Jul 21, 2019
eb60ea8
Caches trackers by app value for infra useTrackMetric hook
jasonrhodes Jul 23, 2019
e02e22a
Merge branch 'master' of github.com:elastic/kibana into telemetry/mov…
Bamieh Jul 23, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/kbn-analytics/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["@babel/typescript", "@kbn/babel-preset/webpack_preset"],
"plugins": ["@babel/plugin-proposal-export-default-from"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
* under the License.
*/

export { registerUiMetricUsageCollector } from './collector';
export * from './src';
24 changes: 24 additions & 0 deletions packages/kbn-analytics/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@kbn/analytics",
"private": true,
"version": "1.0.0",
"description": "Kibana Analytics tool",
"main": "target/index.js",
"types": "./index.d.ts",
"author": "Ahmad Bamieh <[email protected]>",
"license": "Apache-2.0",
"scripts": {
"build": "babel src --config-file ./.babelrc --out-dir target --delete-dir-on-start --extensions .ts,.js,.tsx",
"kbn:bootstrap": "yarn build --quiet",
"kbn:watch": "yarn build --watch"
},
"devDependencies": {
"@babel/cli": "7.4.4",
"@babel/plugin-proposal-export-default-from": "^7.2.0",
"babel-plugin-add-module-exports": "1.0.2",
"typescript": "3.5.1"
},
"dependencies": {
"@kbn/dev-utils": "1.0.0"
}
}
22 changes: 22 additions & 0 deletions packages/kbn-analytics/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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.
*/

export { createReporter, ReportHTTP, Reporter, ReporterConfig } from './reporter';
export { UiStatsMetricType } from './metrics';
export { Report, ReportManager } from './report';
31 changes: 31 additions & 0 deletions packages/kbn-analytics/src/metrics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { UiStatsMetric, UiStatsMetricType } from './ui_stats';

export {
UiStatsMetric,
createUiStatsMetric,
UiStatsMetricReport,
UiStatsMetricType,
} from './ui_stats';
export { Stats } from './stats';

export type Metric = UiStatsMetric<UiStatsMetricType>;
export type MetricType = Metric['type'];
25 changes: 25 additions & 0 deletions packages/kbn-analytics/src/metrics/stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.
*/

export interface Stats {
min: number;
max: number;
sum: number;
avg: number;
}
52 changes: 52 additions & 0 deletions packages/kbn-analytics/src/metrics/ui_stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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 { Stats } from './stats';

export type UiStatsMetricType = 'click' | 'loaded' | 'count';
export interface UiStatsMetricConfig<T extends UiStatsMetricType> {
type: T;
appName: string;
eventName: string;
count?: number;
}

export interface UiStatsMetric<T extends UiStatsMetricType = UiStatsMetricType> {
type: T;
appName: string;
eventName: string;
count: number;
}

export function createUiStatsMetric<T extends UiStatsMetricType>({
type,
appName,
eventName,
count = 1,
}: UiStatsMetricConfig<T>): UiStatsMetric<T> {
return { type, appName, eventName, count };
}

export interface UiStatsMetricReport {
key: string;
appName: string;
eventName: string;
type: UiStatsMetricType;
stats: Stats;
}
93 changes: 93 additions & 0 deletions packages/kbn-analytics/src/report.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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 { UnreachableCaseError } from './util';
import { Metric, Stats, UiStatsMetricReport } from './metrics';

export interface Report {
uiStatsMetrics: {
[key: string]: UiStatsMetricReport;
};
}

export class ReportManager {
public report: Report;
constructor(report?: Report) {
this.report = report || ReportManager.createReport();
}
static createReport() {
return { uiStatsMetrics: {} };
}
public clearReport() {
this.report = ReportManager.createReport();
}
public isReportEmpty(): boolean {
return Object.keys(this.report.uiStatsMetrics).length === 0;
}
private increamentStats(count: number, stats?: Stats): Stats {
Bamieh marked this conversation as resolved.
Show resolved Hide resolved
const { min = 0, max = 0, sum = 0 } = stats || {};
const newMin = Math.min(min, count);
const newMax = Math.max(max, count);
const newAvg = newMin + newMax / 2;
const newSum = sum + count;

return {
min: newMin,
max: newMax,
avg: newAvg,
sum: newSum,
};
}
assignReports(newMetrics: Metric[]) {
newMetrics.forEach(newMetric => this.assignReport(this.report, newMetric));
}
static createMetricKey(metric: Metric): string {
switch (metric.type) {
case 'click':
Bamieh marked this conversation as resolved.
Show resolved Hide resolved
case 'loaded':
case 'count': {
const { appName, type, eventName } = metric;
return `${appName}-${type}-${eventName}`;
}
default:
throw new UnreachableCaseError(metric.type);
}
}
private assignReport(report: Report, metric: Metric) {
switch (metric.type) {
case 'loaded':
case 'count':
case 'click': {
const { appName, type, eventName, count } = metric;
const key = ReportManager.createMetricKey(metric);
const existingStats = (report.uiStatsMetrics[key] || {}).stats;
this.report.uiStatsMetrics[key] = {
key,
appName,
eventName,
type,
stats: this.increamentStats(count, existingStats),
};
return;
}
default:
throw new UnreachableCaseError(metric.type);
}
}
}
118 changes: 118 additions & 0 deletions packages/kbn-analytics/src/reporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* 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 { wrapArray, createLogger } from './util';
import { Metric, UiStatsMetric, createUiStatsMetric } from './metrics';

import { Storage, ReportStorageManager } from './storage';
import { Report, ReportManager } from './report';

export interface ReporterConfig {
http: ReportHTTP;
storage?: Storage;
checkInterval?: number;
debug?: boolean;
storageKey?: string;
}

export type ReportHTTP = (report: Report) => Promise<void>;

export class Reporter {
checkInterval: number;
private interval: any;
private http: ReportHTTP;
private reportManager: ReportManager;
private storageManager: ReportStorageManager;
private debug: boolean;

constructor(config: ReporterConfig) {
const { http, storage, debug, checkInterval = 10000, storageKey = 'analytics' } = config;

this.http = http;
this.checkInterval = checkInterval;
this.interval = null;
this.storageManager = new ReportStorageManager(storageKey, storage);
const storedReport = this.storageManager.get();
this.reportManager = new ReportManager(storedReport);
this.debug = debug;
}

private saveToReport(newMetrics: Metric[]) {
this.reportManager.assignReports(newMetrics);
this.storageManager.store(this.reportManager.report);
}

private flushReport() {
this.reportManager.clearReport();
this.storageManager.store(this.reportManager.report);
}

public start() {
if (!this.interval) {
this.interval = setTimeout(() => {
this.interval = null;
this.sendReports();
}, this.checkInterval);
}
}

public stop() {
Bamieh marked this conversation as resolved.
Show resolved Hide resolved
clearTimeout(this.interval);
}

private log(message: any) {
if (this.debug) {
// eslint-disable-next-line
console.debug(message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this suppose to be logging in Kibana development mode? How does one go about turning this off via the config object that's being passed in?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can override the default by adding ui_metric.debug:false in the kibana.yml file. Note that it defaults to true only if kibana is in development mode.

}
}

public reportUiStats(
appName: string,
type: UiStatsMetric['type'],
eventNames: string | string[],
count?: number
) {
const metrics = wrapArray(eventNames).map(eventName => {
if (this) this.log(`${type} Metric -> (${appName}:${eventName}):`);
const report = createUiStatsMetric({ type, appName, eventName, count });
this.log(report);
return report;
});
this.saveToReport(metrics);
}

public async sendReports() {
if (!this.reportManager.isReportEmpty()) {
try {
await this.http(this.reportManager.report);
this.flushReport();
} catch (err) {
this.log(`Error Sending Metrics Report ${err}`);
}
}
this.start();
}
}

export function createReporter(reportedConf: ReporterConfig) {
const reporter = new Reporter(reportedConf);
reporter.start();
return reporter;
}
Loading