mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 02:54:21 +08:00
feat(@angular-devkit/core): analytics interfaces and basic implementations
This is a preliminary analytics interface. It is meant to be used by every other subsystem where useful, but can be replaced by implementations.
This commit is contained in:
parent
7eb4bab00f
commit
15d7aea2b7
52
packages/angular_devkit/core/src/analytics/api.ts
Normal file
52
packages/angular_devkit/core/src/analytics/api.ts
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
export interface CustomDimensionsAndMetricsOptions {
|
||||
dimensions?: (boolean | number | string)[];
|
||||
metrics?: (boolean | number | string)[];
|
||||
}
|
||||
|
||||
export interface EventOptions extends CustomDimensionsAndMetricsOptions {
|
||||
label?: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export interface ScreenviewOptions extends CustomDimensionsAndMetricsOptions {
|
||||
appVersion?: string;
|
||||
appId?: string;
|
||||
appInstallerId?: string;
|
||||
}
|
||||
|
||||
export interface PageviewOptions extends CustomDimensionsAndMetricsOptions {
|
||||
hostname?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface TimingOptions extends CustomDimensionsAndMetricsOptions {
|
||||
label?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for managing analytics. This is highly platform dependent, and mostly matches
|
||||
* Google Analytics. The reason the interface is here is to remove the dependency to an
|
||||
* implementation from most other places.
|
||||
*
|
||||
* The methods exported from this interface more or less match those needed by us in the
|
||||
* universal analytics package, see https://unpkg.com/@types/universal-analytics@0.4.2/index.d.ts
|
||||
* for typings. We mostly named arguments to make it easier to follow, but didn't change or
|
||||
* add any semantics to those methods. They're mapping GA and u-a one for one.
|
||||
*
|
||||
* The Angular CLI (or any other kind of backend) should forward it to some compatible backend.
|
||||
*/
|
||||
export interface Analytics {
|
||||
event(category: string, action: string, options?: EventOptions): void;
|
||||
screenview(screenName: string, appName: string, options?: ScreenviewOptions): void;
|
||||
pageview(path: string, options?: PageviewOptions): void;
|
||||
timing(category: string, variable: string, time: string | number, options?: TimingOptions): void;
|
||||
|
||||
flush(): Promise<void>;
|
||||
}
|
131
packages/angular_devkit/core/src/analytics/forwarder.ts
Normal file
131
packages/angular_devkit/core/src/analytics/forwarder.ts
Normal file
@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import { JsonObject } from '../json';
|
||||
import { Analytics, EventOptions, PageviewOptions, ScreenviewOptions, TimingOptions } from './api';
|
||||
|
||||
|
||||
export enum AnalyticsReportKind {
|
||||
Event = 'event',
|
||||
Screenview = 'screenview',
|
||||
Pageview = 'pageview',
|
||||
Timing = 'timing',
|
||||
}
|
||||
|
||||
export interface AnalyticsReportBase extends JsonObject {
|
||||
kind: AnalyticsReportKind;
|
||||
}
|
||||
|
||||
export interface AnalyticsReportEvent extends AnalyticsReportBase {
|
||||
kind: AnalyticsReportKind.Event;
|
||||
options: JsonObject & EventOptions;
|
||||
category: string;
|
||||
action: string;
|
||||
}
|
||||
export interface AnalyticsReportScreenview extends AnalyticsReportBase {
|
||||
kind: AnalyticsReportKind.Screenview;
|
||||
options: JsonObject & ScreenviewOptions;
|
||||
screenName: string;
|
||||
appName: string;
|
||||
}
|
||||
export interface AnalyticsReportPageview extends AnalyticsReportBase {
|
||||
kind: AnalyticsReportKind.Pageview;
|
||||
options: JsonObject & PageviewOptions;
|
||||
path: string;
|
||||
}
|
||||
export interface AnalyticsReportTiming extends AnalyticsReportBase {
|
||||
kind: AnalyticsReportKind.Timing;
|
||||
options: JsonObject & TimingOptions;
|
||||
category: string;
|
||||
variable: string;
|
||||
time: string | number;
|
||||
}
|
||||
|
||||
export type AnalyticsReport =
|
||||
AnalyticsReportEvent
|
||||
| AnalyticsReportScreenview
|
||||
| AnalyticsReportPageview
|
||||
| AnalyticsReportTiming
|
||||
;
|
||||
|
||||
/**
|
||||
* A function that can forward analytics along some stream. AnalyticsReport is already a
|
||||
* JsonObject descendant, but we force it here so the user knows it's safe to serialize.
|
||||
*/
|
||||
export type AnalyticsForwarderFn = (report: JsonObject & AnalyticsReport) => void;
|
||||
|
||||
/**
|
||||
* A class that follows the Analytics interface and forwards analytic reports (JavaScript objects).
|
||||
* AnalyticsReporter is the counterpart which takes analytic reports and report them to another
|
||||
* Analytics interface.
|
||||
*/
|
||||
export class ForwardingAnalytics implements Analytics {
|
||||
constructor(protected _fn: AnalyticsForwarderFn) {}
|
||||
|
||||
event(category: string, action: string, options?: EventOptions) {
|
||||
this._fn({
|
||||
kind: AnalyticsReportKind.Event,
|
||||
category,
|
||||
action,
|
||||
options: { ...options } as JsonObject,
|
||||
});
|
||||
}
|
||||
screenview(screenName: string, appName: string, options?: ScreenviewOptions) {
|
||||
this._fn({
|
||||
kind: AnalyticsReportKind.Screenview,
|
||||
screenName,
|
||||
appName,
|
||||
options: { ...options } as JsonObject,
|
||||
});
|
||||
}
|
||||
pageview(path: string, options?: PageviewOptions) {
|
||||
this._fn({
|
||||
kind: AnalyticsReportKind.Pageview,
|
||||
path,
|
||||
options: { ...options } as JsonObject,
|
||||
});
|
||||
}
|
||||
timing(category: string, variable: string, time: string | number, options?: TimingOptions): void {
|
||||
this._fn({
|
||||
kind: AnalyticsReportKind.Timing,
|
||||
category,
|
||||
variable,
|
||||
time,
|
||||
options: { ...options } as JsonObject,
|
||||
});
|
||||
}
|
||||
|
||||
// We do not support flushing.
|
||||
flush() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AnalyticsReporter {
|
||||
constructor(protected _analytics: Analytics) {}
|
||||
|
||||
report(report: AnalyticsReport) {
|
||||
switch (report.kind) {
|
||||
case AnalyticsReportKind.Event:
|
||||
this._analytics.event(report.category, report.action, report.options);
|
||||
break;
|
||||
case AnalyticsReportKind.Screenview:
|
||||
this._analytics.screenview(report.screenName, report.appName, report.options);
|
||||
break;
|
||||
case AnalyticsReportKind.Pageview:
|
||||
this._analytics.pageview(report.path, report.options);
|
||||
break;
|
||||
case AnalyticsReportKind.Timing:
|
||||
this._analytics.timing(report.category, report.variable, report.time, report.options);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('Unexpected analytics report: ' + JSON.stringify(report));
|
||||
}
|
||||
}
|
||||
}
|
12
packages/angular_devkit/core/src/analytics/index.ts
Normal file
12
packages/angular_devkit/core/src/analytics/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
export * from './api';
|
||||
export * from './forwarder';
|
||||
export * from './logging';
|
||||
export * from './multi';
|
||||
export * from './noop';
|
34
packages/angular_devkit/core/src/analytics/logging.ts
Normal file
34
packages/angular_devkit/core/src/analytics/logging.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import { Logger } from '../logger';
|
||||
import { Analytics, EventOptions, PageviewOptions, ScreenviewOptions, TimingOptions } from './api';
|
||||
|
||||
/**
|
||||
* Analytics implementation that logs analytics events to a logger. This should be used for
|
||||
* debugging mainly.
|
||||
*/
|
||||
export class LoggingAnalytics implements Analytics {
|
||||
constructor(protected _logger: Logger) {}
|
||||
|
||||
event(category: string, action: string, options?: EventOptions): void {
|
||||
this._logger.info('event ' + JSON.stringify({ category, action, ...options }));
|
||||
}
|
||||
screenview(screenName: string, appName: string, options?: ScreenviewOptions): void {
|
||||
this._logger.info('screenview ' + JSON.stringify({ screenName, appName, ...options }));
|
||||
}
|
||||
pageview(path: string, options?: PageviewOptions): void {
|
||||
this._logger.info('pageview ' + JSON.stringify({ path, ...options }));
|
||||
}
|
||||
timing(category: string, variable: string, time: string | number, options?: TimingOptions): void {
|
||||
this._logger.info('timing ' + JSON.stringify({ category, variable, time, ...options }));
|
||||
}
|
||||
|
||||
flush(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
38
packages/angular_devkit/core/src/analytics/multi.ts
Normal file
38
packages/angular_devkit/core/src/analytics/multi.ts
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import { Analytics, EventOptions, PageviewOptions, ScreenviewOptions, TimingOptions } from './api';
|
||||
|
||||
/**
|
||||
* Analytics implementation that reports to multiple analytics backend.
|
||||
*/
|
||||
export class MultiAnalytics implements Analytics {
|
||||
constructor(protected _backends: Analytics[] = []) {}
|
||||
|
||||
push(...backend: Analytics[]) {
|
||||
this._backends.push(...backend);
|
||||
}
|
||||
|
||||
event(category: string, action: string, options?: EventOptions): void {
|
||||
this._backends.forEach(be => be.event(category, action, options));
|
||||
}
|
||||
screenview(screenName: string, appName: string, options?: ScreenviewOptions): void {
|
||||
this._backends.forEach(be => be.screenview(screenName, appName, options));
|
||||
}
|
||||
pageview(path: string, options?: PageviewOptions): void {
|
||||
this._backends.forEach(be => be.pageview(path, options));
|
||||
}
|
||||
timing(category: string, variable: string, time: string | number, options?: TimingOptions): void {
|
||||
this._backends.forEach(be => be.timing(category, variable, time, options));
|
||||
}
|
||||
|
||||
|
||||
flush(): Promise<void> {
|
||||
return Promise.all(this._backends.map(x => x.flush())).then(() => {});
|
||||
}
|
||||
}
|
19
packages/angular_devkit/core/src/analytics/noop.ts
Normal file
19
packages/angular_devkit/core/src/analytics/noop.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import { Analytics } from './api';
|
||||
|
||||
/**
|
||||
* Analytics implementation that does nothing.
|
||||
*/
|
||||
export class NoopAnalytics implements Analytics {
|
||||
event() {}
|
||||
screenview() {}
|
||||
pageview() {}
|
||||
timing() {}
|
||||
flush(): Promise<void> { return Promise.resolve(); }
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as analytics from './analytics';
|
||||
import * as experimental from './experimental';
|
||||
import * as json from './json/index';
|
||||
import * as logging from './logger/index';
|
||||
@ -16,6 +17,7 @@ export * from './utils/index';
|
||||
export * from './virtual-fs/index';
|
||||
|
||||
export {
|
||||
analytics,
|
||||
experimental,
|
||||
json,
|
||||
logging,
|
||||
|
Loading…
x
Reference in New Issue
Block a user