Skip to content

Commit d25fb89

Browse files
hanslalexeagle
authored andcommitted
feat(@angular-devkit/architect): add analytics to builder context
It should be NoopAnalytics if no analytics are supported.
1 parent ecd25a7 commit d25fb89

4 files changed

Lines changed: 23 additions & 3 deletions

File tree

packages/angular_devkit/architect/src/api.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { experimental, json, logging } from '@angular-devkit/core';
8+
import { analytics, experimental, json, logging } from '@angular-devkit/core';
99
import { Observable, from } from 'rxjs';
1010
import { switchMap } from 'rxjs/operators';
1111
import { Schema as RealBuilderInput, Target as RealTarget } from './input-schema';
@@ -234,6 +234,12 @@ export interface BuilderContext {
234234
*/
235235
reportProgress(current: number, total?: number, status?: string): void;
236236

237+
/**
238+
* API to report analytics. This might be undefined if the feature is unsupported. This might
239+
* not be undefined, but the backend could also not report anything.
240+
*/
241+
readonly analytics: analytics.Analytics;
242+
237243
/**
238244
* Add teardown logic to this Context, so that when it's being stopped it will execute teardown.
239245
*/

packages/angular_devkit/architect/src/architect.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { experimental, json, logging } from '@angular-devkit/core';
8+
import { analytics, experimental, json, logging } from '@angular-devkit/core';
99
import { Observable, from, of } from 'rxjs';
1010
import { concatMap, first, map, shareReplay, switchMap } from 'rxjs/operators';
1111
import {
@@ -102,6 +102,7 @@ function _createJobHandlerFromBuilderInfo(
102102

103103
export interface ScheduleOptions {
104104
logger?: logging.Logger;
105+
analytics?: analytics.Analytics;
105106
}
106107

107108

@@ -347,6 +348,7 @@ export class Architect {
347348
logger: scheduleOptions.logger || new logging.NullLogger(),
348349
currentDirectory: this._host.getCurrentDirectory(),
349350
workspaceRoot: this._host.getWorkspaceRoot(),
351+
analytics: scheduleOptions.analytics,
350352
});
351353
}
352354
scheduleTarget(
@@ -359,6 +361,7 @@ export class Architect {
359361
logger: scheduleOptions.logger || new logging.NullLogger(),
360362
currentDirectory: this._host.getCurrentDirectory(),
361363
workspaceRoot: this._host.getWorkspaceRoot(),
364+
analytics: scheduleOptions.analytics,
362365
});
363366
}
364367
}

packages/angular_devkit/architect/src/create-builder.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { experimental, isPromise, json, logging } from '@angular-devkit/core';
8+
import { analytics, experimental, isPromise, json, logging } from '@angular-devkit/core';
99
import { Observable, Subscription, from, isObservable, of, throwError } from 'rxjs';
1010
import { tap } from 'rxjs/operators';
1111
import {
@@ -36,6 +36,7 @@ export function createBuilder<
3636
const scheduler = context.scheduler;
3737
const progressChannel = context.createChannel('progress');
3838
const logChannel = context.createChannel('log');
39+
const analyticsChannel = context.createChannel('analytics');
3940
let currentState: BuilderProgressState = BuilderProgressState.Stopped;
4041
const teardownLogics: Array<() => (PromiseLike<void> | void)> = [];
4142
let tearingDown = false;
@@ -181,6 +182,7 @@ export function createBuilder<
181182
progress({ state: currentState, current, total, status }, context);
182183
}
183184
},
185+
analytics: new analytics.ForwardingAnalytics(report => analyticsChannel.next(report)),
184186
addTeardown(teardown: () => (Promise<void> | void)): void {
185187
teardownLogics.push(teardown);
186188
},

packages/angular_devkit/architect/src/schedule-by-name.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { experimental, json, logging } from '@angular-devkit/core';
99
import { EMPTY, Subscription } from 'rxjs';
1010
import { catchError, first, ignoreElements, map, share, shareReplay, tap } from 'rxjs/operators';
11+
import { Analytics, AnalyticsReport, AnalyticsReporter } from '../../core/src/analytics';
1112
import {
1213
BuilderInfo,
1314
BuilderInput,
@@ -31,6 +32,7 @@ export async function scheduleByName(
3132
logger: logging.LoggerApi,
3233
workspaceRoot: string | Promise<string>,
3334
currentDirectory: string | Promise<string>,
35+
analytics?: Analytics,
3436
},
3537
): Promise<BuilderRun> {
3638
const childLoggerName = options.target ? `{${targetStringFromTarget(options.target)}}` : name;
@@ -88,6 +90,12 @@ export async function scheduleByName(
8890
shareReplay(),
8991
);
9092

93+
// If there's an analytics object, take the job channel and report it to the analytics.
94+
if (options.analytics) {
95+
const reporter = new AnalyticsReporter(options.analytics);
96+
job.getChannel<AnalyticsReport>('analytics')
97+
.subscribe(report => reporter.report(report));
98+
}
9199
// Start the builder.
92100
output.pipe(first()).subscribe({
93101
error() {},
@@ -121,6 +129,7 @@ export async function scheduleByTarget(
121129
logger: logging.LoggerApi,
122130
workspaceRoot: string | Promise<string>,
123131
currentDirectory: string | Promise<string>,
132+
analytics?: Analytics,
124133
},
125134
): Promise<BuilderRun> {
126135
return scheduleByName(`{${targetStringFromTarget(target)}}`, overrides, {

0 commit comments

Comments
 (0)