Add tracking for all frontend API calls
Change-Id: If9da951fbaec2600ee5ca9bf0883cfdf92da51c5
diff --git a/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api.ts b/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api.ts
index 897be67..7a91c68 100644
--- a/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api.ts
@@ -16,6 +16,7 @@
*/
import {EventType, PluginApi} from '../../../api/plugin';
import {AdminPluginApi, MenuLink} from '../../../api/admin';
+import {appContext} from '../../../services/app-context';
/**
* GrAdminApi class.
@@ -26,15 +27,20 @@
// TODO(TS): maybe define as enum if its a limited set
private menuLinks: MenuLink[] = [];
+ private readonly reporting = appContext.reportingService;
+
constructor(private readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'admin', 'constructor');
this.plugin.on(EventType.ADMIN_MENU_LINKS, this);
}
addMenuLink(text: string, url: string, capability?: string) {
+ this.reporting.trackApi(this.plugin, 'admin', 'addMenuLink');
this.menuLinks.push({text, url, capability: capability || null});
}
getMenuLinks(): MenuLink[] {
+ this.reporting.trackApi(this.plugin, 'admin', 'getMenuLinks');
return this.menuLinks.slice(0);
}
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts
index e0b4ee9..ab2ce6a 100644
--- a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts
@@ -15,14 +15,20 @@
* limitations under the License.
*/
import {AttributeHelperPluginApi} from '../../../api/attribute-helper';
+import {PluginApi} from '../../../api/plugin';
+import {appContext} from '../../../services/app-context';
export class GrAttributeHelper implements AttributeHelperPluginApi {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private readonly _promises = new Map<string, Promise<any>>();
+ private readonly reporting = appContext.reportingService;
+
// TODO(TS): Change any to something more like HTMLElement.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- constructor(public element: any) {}
+ constructor(readonly plugin: PluginApi, public element: any) {
+ this.reporting.trackApi(this.plugin, 'attribute', 'constructor');
+ }
_getChangedEventName(name: string): string {
return name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() + '-changed';
@@ -52,6 +58,7 @@
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
bind(name: string, callback: (value: any) => void) {
+ this.reporting.trackApi(this.plugin, 'attribute', 'bind');
const attributeChangedEventName = this._getChangedEventName(name);
const changedHandler = (e: CustomEvent) =>
this._reportValue(callback, e.detail.value);
@@ -72,6 +79,7 @@
* to be initialized if it isn't defined.
*/
get(name: string): Promise<unknown> {
+ this.reporting.trackApi(this.plugin, 'attribute', 'get');
if (this._elementHasProperty(name)) {
return Promise.resolve(this.element[name]);
}
@@ -93,6 +101,7 @@
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
set(name: string, value: any) {
+ this.reporting.trackApi(this.plugin, 'attribute', 'set');
this.element[name] = value;
this.element.dispatchEvent(
new CustomEvent(this._getChangedEventName(name), {detail: {value}})
diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
index 7ea3be3..2d83012 100644
--- a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
+++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
@@ -17,7 +17,7 @@
import '../../../test/common-test-setup-karma.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {GrAttributeHelper} from './gr-attribute-helper.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
Polymer({
is: 'gr-attribute-helper-some-element',
@@ -31,13 +31,18 @@
const basicFixture = fixtureFromElement('gr-attribute-helper-some-element');
+const pluginApi = _testOnly_initGerritPluginApi();
+
suite('gr-attribute-helper tests', () => {
let element;
let instance;
setup(() => {
+ let plugin;
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
element = basicFixture.instantiate();
- instance = new GrAttributeHelper(element);
+ instance = plugin.attributeHelper(element);
});
test('resolved on value change from undefined', () => {
diff --git a/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts b/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts
index a03c5dc..bbb58fc 100644
--- a/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-change-metadata-api/gr-change-metadata-api.ts
@@ -17,15 +17,19 @@
import {PluginApi} from '../../../api/plugin';
import {ChangeMetadataPluginApi} from '../../../api/change-metadata';
import {HookApi} from '../../../api/hook';
+import {appContext} from '../../../services/app-context';
export class GrChangeMetadataApi implements ChangeMetadataPluginApi {
private hook: HookApi | null;
public plugin: PluginApi;
+ private readonly reporting = appContext.reportingService;
+
constructor(plugin: PluginApi) {
this.plugin = plugin;
this.hook = null;
+ this.reporting.trackApi(this.plugin, 'metadata', 'constructor');
}
_createHook() {
@@ -33,6 +37,7 @@
}
onLabelsChanged(callback: (value: unknown) => void) {
+ this.reporting.trackApi(this.plugin, 'metadata', 'onLabelsChanged');
if (!this.hook) {
this._createHook();
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-checks-api/gr-checks-api.ts b/polygerrit-ui/app/elements/plugins/gr-checks-api/gr-checks-api.ts
index 404fc71..39d3c8b 100644
--- a/polygerrit-ui/app/elements/plugins/gr-checks-api/gr-checks-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-checks-api/gr-checks-api.ts
@@ -43,13 +43,19 @@
private readonly checksService = appContext.checksService;
- constructor(readonly plugin: PluginApi) {}
+ private readonly reporting = appContext.reportingService;
+
+ constructor(readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'checks', 'constructor');
+ }
announceUpdate() {
+ this.reporting.trackApi(this.plugin, 'checks', 'announceUpdate');
this.checksService.reload(this.plugin.getPluginName());
}
register(provider: ChecksProvider, config?: ChecksApiConfig): void {
+ this.reporting.trackApi(this.plugin, 'checks', 'register');
if (this.state === State.REGISTERED)
throw new Error('Only one provider can be registered per plugin.');
this.state = State.REGISTERED;
diff --git a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts
index 4b34d56..0c2f412 100644
--- a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper.ts
@@ -18,6 +18,8 @@
EventHelperPluginApi,
UnsubscribeCallback,
} from '../../../api/event-helper';
+import {PluginApi} from '../../../api/plugin';
+import {appContext} from '../../../services/app-context';
export interface ListenOptions {
event?: string;
@@ -25,13 +27,18 @@
}
export class GrEventHelper implements EventHelperPluginApi {
- constructor(readonly element: HTMLElement) {}
+ private readonly reporting = appContext.reportingService;
+
+ constructor(readonly plugin: PluginApi, readonly element: HTMLElement) {
+ this.reporting.trackApi(this.plugin, 'event', 'constructor');
+ }
/**
* Add a callback to arbitrary event.
* The callback may return false to prevent event bubbling.
*/
on(event: string, callback: (event: Event) => boolean) {
+ this.reporting.trackApi(this.plugin, 'event', 'on');
return this._listen(this.element, callback, {event});
}
@@ -39,6 +46,7 @@
* Alias for @see onClick
*/
onTap(callback: (event: Event) => boolean) {
+ this.reporting.trackApi(this.plugin, 'event', 'onTap');
return this.onClick(callback);
}
@@ -47,6 +55,7 @@
* The callback may return false to prevent event bubbling.
*/
onClick(callback: (event: Event) => boolean) {
+ this.reporting.trackApi(this.plugin, 'event', 'onClick');
return this._listen(this.element, callback);
}
@@ -54,6 +63,7 @@
* Alias for @see captureClick
*/
captureTap(callback: (event: Event) => boolean) {
+ this.reporting.trackApi(this.plugin, 'event', 'captureTap');
return this.captureClick(callback);
}
@@ -64,6 +74,7 @@
* The callback may return false to cancel regular event listeners.
*/
captureClick(callback: (event: Event) => boolean) {
+ this.reporting.trackApi(this.plugin, 'event', 'captureClick');
const parent = this.element.parentElement!;
return this._listen(parent, callback, {capture: true});
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.js b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.js
index 25c0d43..547b575 100644
--- a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.js
+++ b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.js
@@ -17,8 +17,8 @@
import '../../../test/common-test-setup-karma.js';
import {addListener} from '@polymer/polymer/lib/utils/gestures.js';
-import {GrEventHelper} from './gr-event-helper.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
Polymer({
is: 'gr-event-helper-some-element',
@@ -33,13 +33,18 @@
const basicFixture = fixtureFromElement('gr-event-helper-some-element');
+const pluginApi = _testOnly_initGerritPluginApi();
+
suite('gr-event-helper tests', () => {
let element;
let instance;
setup(() => {
+ let plugin;
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
element = basicFixture.instantiate();
- instance = new GrEventHelper(element);
+ instance = plugin.eventHelper(element);
});
test('onTap()', done => {
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts
index dcabc80..13d18b5 100644
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface.ts
@@ -19,6 +19,7 @@
import {GrPluginPopup} from './gr-plugin-popup';
import {PluginApi} from '../../../api/plugin';
import {PopupPluginApi} from '../../../api/popup';
+import {appContext} from '../../../services/app-context';
interface CustomPolymerPluginEl extends HTMLElement {
plugin: PluginApi;
@@ -35,10 +36,14 @@
private popup: GrPluginPopup | null = null;
+ private readonly reporting = appContext.reportingService;
+
constructor(
readonly plugin: PluginApi,
private moduleName: string | null = null
- ) {}
+ ) {
+ this.reporting.trackApi(this.plugin, 'popup', 'constructor');
+ }
_getElement() {
// TODO(TS): maybe consider removing this if no one is using
@@ -52,6 +57,7 @@
* if it was provided with constructor.
*/
open(): Promise<PopupPluginApi> {
+ this.reporting.trackApi(this.plugin, 'popup', 'open');
if (!this.openingPromise) {
this.openingPromise = this.plugin
.hook('plugin-overlay')
@@ -76,6 +82,7 @@
* Hides the popup.
*/
close() {
+ this.reporting.trackApi(this.plugin, 'popup', 'close');
if (!this.popup) {
return;
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts
index 0418edb..51e9112 100644
--- a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api.ts
@@ -19,6 +19,7 @@
import {PluginApi} from '../../../api/plugin';
import {RepoCommandCallback, RepoPluginApi} from '../../../api/repo';
import {HookApi} from '../../../api/hook';
+import {appContext} from '../../../services/app-context';
/**
* Parameters provided on repo-command endpoint
@@ -31,7 +32,11 @@
export class GrRepoApi implements RepoPluginApi {
private hook?: HookApi;
- constructor(readonly plugin: PluginApi) {}
+ private readonly reporting = appContext.reportingService;
+
+ constructor(readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'repo', 'constructor');
+ }
// TODO(TS): should mark as public since used in gr-change-metadata-api
_createHook(title: string) {
@@ -43,6 +48,7 @@
}
createCommand(title: string, callback: RepoCommandCallback) {
+ this.reporting.trackApi(this.plugin, 'repo', 'createCommand');
if (this.hook) {
console.warn('Already set up.');
return this;
@@ -57,6 +63,7 @@
}
onTap(callback: (event: Event) => boolean) {
+ this.reporting.trackApi(this.plugin, 'repo', 'onTap');
if (!this.hook) {
console.warn('Call createCommand first.');
return this;
diff --git a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.ts b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.ts
index 4bdd40e..3f75c0a 100644
--- a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.ts
@@ -18,6 +18,7 @@
import '../../settings/gr-settings-view/gr-settings-menu-item';
import {PluginApi} from '../../../api/plugin';
import {SettingsPluginApi} from '../../../api/settings';
+import {appContext} from '../../../services/app-context';
export class GrSettingsApi implements SettingsPluginApi {
private _token: string;
@@ -26,27 +27,34 @@
private _moduleName?: string;
+ private readonly reporting = appContext.reportingService;
+
constructor(readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'settings', 'constructor');
// Generate default screen URL token, specific to plugin, and unique(ish).
this._token = plugin.getPluginName() + Math.random().toString(36).substr(5);
}
title(newTitle: string) {
+ this.reporting.trackApi(this.plugin, 'settings', 'title');
this._title = newTitle;
return this;
}
token(newToken: string) {
+ this.reporting.trackApi(this.plugin, 'settings', 'token');
this._token = newToken;
return this;
}
module(newModuleName: string) {
+ this.reporting.trackApi(this.plugin, 'settings', 'module');
this._moduleName = newModuleName;
return this;
}
build() {
+ this.reporting.trackApi(this.plugin, 'settings', 'build');
if (!this._moduleName) {
throw new Error('Settings screen custom element not defined!');
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api.ts b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api.ts
index a91b8d3..9a15bf5 100644
--- a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api.ts
@@ -15,6 +15,8 @@
* limitations under the License.
*/
import {StyleObject, StylesPluginApi} from '../../../api/styles';
+import {appContext} from '../../../services/app-context';
+import {PluginApi} from '../../../api/plugin';
/**
* @fileoverview We should consider dropping support for this API:
@@ -77,10 +79,17 @@
* TODO(TS): move to util
*/
export class GrStylesApi implements StylesPluginApi {
+ private readonly reporting = appContext.reportingService;
+
+ constructor(readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'styles', 'constructor');
+ }
+
/**
* Creates a new GrStyleObject with specified style properties.
*/
css(ruleStr: string) {
+ this.reporting.trackApi(this.plugin, 'styles', 'css');
return new GrStyleObject(ruleStr);
}
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api.ts b/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api.ts
index 894ec6c..c7be7f6 100644
--- a/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api.ts
@@ -18,14 +18,20 @@
import {GrCustomPluginHeader} from './gr-custom-plugin-header';
import {PluginApi} from '../../../api/plugin';
import {ThemePluginApi} from '../../../api/theme';
+import {appContext} from '../../../services/app-context';
/**
* Defines api for theme, can be used to set header logo and title.
*/
export class GrThemeApi implements ThemePluginApi {
- constructor(private readonly plugin: PluginApi) {}
+ private readonly reporting = appContext.reportingService;
+
+ constructor(private readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'theme', 'constructor');
+ }
setHeaderLogoAndTitle(logoUrl: string, title: string) {
+ this.reporting.trackApi(this.plugin, 'theme', 'setHeaderLogoAndTitle');
this.plugin.hook('header-title', {replace: true}).onAttached(element => {
const customHeader: GrCustomPluginHeader = document.createElement(
'gr-custom-plugin-header'
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts
index a3d038d..857d079 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.ts
@@ -41,10 +41,12 @@
private readonly reporting = appContext.reportingService;
constructor(private readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'annotation', 'constructor');
plugin.on(EventType.ANNOTATE_DIFF, this);
}
setLayer(annotationCallback: AnnotationCallback) {
+ this.reporting.trackApi(this.plugin, 'annotation', 'setLayer');
if (this.annotationCallback) {
console.warn('Overwriting an existing plugin annotation layer.');
}
@@ -55,6 +57,7 @@
setCoverageProvider(
coverageProvider: CoverageProvider
): GrAnnotationActionsInterface {
+ this.reporting.trackApi(this.plugin, 'annotation', 'setCoverageProvider');
if (this.coverageProvider) {
console.warn('Overwriting an existing coverage provider.');
}
@@ -74,6 +77,7 @@
checkboxLabel: string,
onAttached: (checkboxEl: Element | null) => void
) {
+ this.reporting.trackApi(this.plugin, 'annotation', 'enableToggleCheckbox');
this.plugin.hook('annotation-toggler').onAttached(element => {
if (!element.content) {
this.reporting.error(new Error('plugin endpoint without content.'));
@@ -104,6 +108,7 @@
}
notify(path: string, start: number, end: number, side: Side) {
+ this.reporting.trackApi(this.plugin, 'annotation', 'notify');
for (const annotationLayer of this.annotationLayers) {
// Notify only the annotation layer that is associated with the specified
// path.
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts
index a4c6974..15d4680 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api.ts
@@ -68,7 +68,10 @@
ActionType = ActionType;
+ private readonly reporting = appContext.reportingService;
+
constructor(public plugin: PluginApi, el?: GrChangeActionsElement) {
+ this.reporting.trackApi(this.plugin, 'actions', 'constructor');
this.setEl(el);
}
@@ -100,6 +103,7 @@
}
addPrimaryActionKey(key: PrimaryActionKey) {
+ this.reporting.trackApi(this.plugin, 'actions', 'addPrimaryActionKey');
const el = this.ensureEl();
if (el.primaryActionKeys.includes(key)) {
return;
@@ -109,63 +113,77 @@
}
removePrimaryActionKey(key: string) {
+ this.reporting.trackApi(this.plugin, 'actions', 'removePrimaryActionKey');
const el = this.ensureEl();
el.primaryActionKeys = el.primaryActionKeys.filter(k => k !== key);
}
hideQuickApproveAction() {
+ this.reporting.trackApi(this.plugin, 'actions', 'hideQuickApproveAction');
this.ensureEl().hideQuickApproveAction();
}
setActionOverflow(type: ActionType, key: string, overflow: boolean) {
+ this.reporting.trackApi(this.plugin, 'actions', 'setActionOverflow');
// TODO(TS): remove return, unclear why it was written
return this.ensureEl().setActionOverflow(type, key, overflow);
}
setActionPriority(type: ActionType, key: string, priority: ActionPriority) {
+ this.reporting.trackApi(this.plugin, 'actions', 'setActionPriority');
// TODO(TS): remove return, unclear why it was written
return this.ensureEl().setActionPriority(type, key, priority);
}
setActionHidden(type: ActionType, key: string, hidden: boolean) {
+ this.reporting.trackApi(this.plugin, 'actions', 'setActionHidden');
// TODO(TS): remove return, unclear why it was written
return this.ensureEl().setActionHidden(type, key, hidden);
}
add(type: ActionType, label: string): string {
+ this.reporting.trackApi(this.plugin, 'actions', 'add');
return this.ensureEl().addActionButton(type, label);
}
remove(key: string) {
+ this.reporting.trackApi(this.plugin, 'actions', 'remove');
// TODO(TS): remove return, unclear why it was written
return this.ensureEl().removeActionButton(key);
}
addTapListener(key: string, handler: EventListenerOrEventListenerObject) {
+ this.reporting.trackApi(this.plugin, 'actions', 'addTapListener');
this.ensureEl().addEventListener(key + '-tap', handler);
}
removeTapListener(key: string, handler: EventListenerOrEventListenerObject) {
+ this.reporting.trackApi(this.plugin, 'actions', 'removeTapListener');
this.ensureEl().removeEventListener(key + '-tap', handler);
}
setLabel(key: string, text: string) {
+ this.reporting.trackApi(this.plugin, 'actions', 'setLabel');
this.ensureEl().setActionButtonProp(key, 'label', text);
}
setTitle(key: string, text: string) {
+ this.reporting.trackApi(this.plugin, 'actions', 'setTitle');
this.ensureEl().setActionButtonProp(key, 'title', text);
}
setEnabled(key: string, enabled: boolean) {
+ this.reporting.trackApi(this.plugin, 'actions', 'setEnabled');
this.ensureEl().setActionButtonProp(key, 'enabled', enabled);
}
setIcon(key: string, icon: string) {
+ this.reporting.trackApi(this.plugin, 'actions', 'setIcon');
this.ensureEl().setActionButtonProp(key, 'icon', icon);
}
getActionDetails(action: string) {
+ this.reporting.trackApi(this.plugin, 'actions', 'getActionDetails');
const el = this.ensureEl();
return (
el.getActionDetails(action) ||
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts
index effebe1..de57794 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts
@@ -25,15 +25,20 @@
ReplyChangedCallback,
ValueChangedDetail,
} from '../../../api/change-reply';
+import {appContext} from '../../../services/app-context';
/**
* GrChangeReplyInterface, provides a set of handy methods on reply dialog.
*/
export class GrChangeReplyInterface implements ChangeReplyPluginApi {
+ private readonly reporting = appContext.reportingService;
+
constructor(
readonly plugin: PluginApi,
readonly sharedApiElement: JsApiService
- ) {}
+ ) {
+ this.reporting.trackApi(this.plugin, 'reply', 'constructor');
+ }
get _el(): GrReplyDialog {
return (this.sharedApiElement.getElement(
@@ -42,18 +47,22 @@
}
getLabelValue(label: string): string {
+ this.reporting.trackApi(this.plugin, 'reply', 'getLabelValue');
return this._el.getLabelValue(label);
}
setLabelValue(label: string, value: string) {
+ this.reporting.trackApi(this.plugin, 'reply', 'setLabelValue');
this._el.setLabelValue(label, value);
}
send(includeComments?: boolean) {
+ this.reporting.trackApi(this.plugin, 'reply', 'send');
this._el.send(includeComments);
}
addReplyTextChangedCallback(handler: ReplyChangedCallback) {
+ this.reporting.trackApi(this.plugin, 'reply', 'addReplyTextChangedCb');
const hookApi = this.plugin.hook('reply-text');
const registeredHandler = (e: Event) => {
const ce = e as CustomEvent<ValueChangedDetail>;
@@ -74,6 +83,7 @@
}
addLabelValuesChangedCallback(handler: LabelsChangedCallback) {
+ this.reporting.trackApi(this.plugin, 'reply', 'addLabelValuesChangedCb');
const hookApi = this.plugin.hook('reply-label-scores');
const registeredHandler = (e: Event) => {
const ce = e as CustomEvent<LabelsChangedDetail>;
@@ -95,6 +105,7 @@
}
showMessage(message: string) {
+ this.reporting.trackApi(this.plugin, 'reply', 'showMessage');
this._el.setPluginMessage(message);
}
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.ts
index cd35d4e..150c45a 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.ts
@@ -18,6 +18,7 @@
import {RequestPayload} from '../../../types/common';
import {appContext} from '../../../services/app-context';
import {ErrorCallback, RestPluginApi} from '../../../api/rest';
+import {PluginApi} from '../../../api/plugin';
async function getErrorMessage(response: Response): Promise<string> {
const text = await response.text();
@@ -36,33 +37,44 @@
export class GrPluginRestApi implements RestPluginApi {
private readonly restApi = appContext.restApiService;
- constructor(private readonly prefix = '') {}
+ private readonly reporting = appContext.reportingService;
+
+ constructor(readonly plugin: PluginApi, private readonly prefix = '') {
+ this.reporting.trackApi(this.plugin, 'rest', 'constructor');
+ }
getLoggedIn() {
+ this.reporting.trackApi(this.plugin, 'rest', 'getLoggedIn');
return this.restApi.getLoggedIn();
}
getVersion() {
+ this.reporting.trackApi(this.plugin, 'rest', 'getVersion');
return this.restApi.getVersion();
}
getConfig() {
+ this.reporting.trackApi(this.plugin, 'rest', 'getConfig');
return this.restApi.getConfig();
}
invalidateReposCache() {
+ this.reporting.trackApi(this.plugin, 'rest', 'invalidateReposCache');
this.restApi.invalidateReposCache();
}
getAccount() {
+ this.reporting.trackApi(this.plugin, 'rest', 'getAccount');
return this.restApi.getAccount();
}
getAccountCapabilities(capabilities: string[]) {
+ this.reporting.trackApi(this.plugin, 'rest', 'getAccountCapabilities');
return this.restApi.getAccountCapabilities(capabilities);
}
getRepos(filter: string, reposPerPage: number, offset?: number) {
+ this.reporting.trackApi(this.plugin, 'rest', 'getRepos');
return this.restApi.getRepos(filter, reposPerPage, offset);
}
@@ -100,6 +112,7 @@
errFn?: ErrorCallback,
contentType?: string
): Promise<Response | void> {
+ this.reporting.trackApi(this.plugin, 'rest', 'fetch');
return this.restApi.send(
method,
this.prefix + url,
@@ -119,6 +132,7 @@
errFn?: ErrorCallback,
contentType?: string
) {
+ this.reporting.trackApi(this.plugin, 'rest', 'send');
// Plugins typically don't want Gerrit to show error dialogs for failed
// requests. So we are defining a default errFn here, even if it is not
// explicitly set by the caller.
@@ -167,6 +181,7 @@
}
get(url: string) {
+ this.reporting.trackApi(this.plugin, 'rest', 'get');
return this.send(HttpMethod.GET, url);
}
@@ -176,6 +191,7 @@
errFn?: ErrorCallback,
contentType?: string
) {
+ this.reporting.trackApi(this.plugin, 'rest', 'post');
return this.send(HttpMethod.POST, url, payload, errFn, contentType);
}
@@ -185,10 +201,12 @@
errFn?: ErrorCallback,
contentType?: string
) {
+ this.reporting.trackApi(this.plugin, 'rest', 'put');
return this.send(HttpMethod.PUT, url, payload, errFn, contentType);
}
delete(url: string) {
+ this.reporting.trackApi(this.plugin, 'rest', 'delete');
return this.fetch(HttpMethod.DELETE, url).then(response => {
if (response.status !== 204) {
return response.text().then(text => {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
index e7843af..68fb96b 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
@@ -54,6 +54,7 @@
import {ChangeReplyPluginApi} from '../../../api/change-reply';
import {RestPluginApi} from '../../../api/rest';
import {HookApi, RegisterOptions} from '../../../api/hook';
+import {AttributeHelperPluginApi} from '../../../api/attribute-helper';
/**
* Plugin-provided custom components can affect content in extension
@@ -84,6 +85,8 @@
private readonly jsApi = appContext.jsApiService;
+ private readonly report = appContext.reportingService;
+
constructor(url?: string) {
this.domHooks = new GrDomHooksManager(this);
@@ -97,6 +100,7 @@
this._url = new URL(url);
this._name = getPluginNameFromUrl(this._url) ?? 'NULL';
+ this.report.trackApi(this, 'plugin', 'constructor');
}
getPluginName() {
@@ -104,6 +108,7 @@
}
registerStyleModule(endpoint: string, moduleName: string) {
+ this.report.trackApi(this, 'plugin', 'registerStyleModule');
getPluginEndpoints().registerModule(this, {
endpoint,
type: EndpointType.STYLE,
@@ -119,6 +124,7 @@
moduleName?: string,
options?: RegisterOptions
): HookApi {
+ this.report.trackApi(this, 'plugin', 'registerCustomComponent');
return this._registerCustomComponent(endpointName, moduleName, options);
}
@@ -133,6 +139,7 @@
moduleName?: string,
options?: RegisterOptions
): HookApi {
+ this.report.trackApi(this, 'plugin', 'registerDynamicCustomComponent');
const fullEndpointName = `${endpointName}-${this.getPluginName()}`;
return this._registerCustomComponent(
fullEndpointName,
@@ -169,19 +176,23 @@
* element for the first call.
*/
hook(endpointName: string, options?: RegisterOptions) {
+ this.report.trackApi(this, 'plugin', 'hook');
return this.registerCustomComponent(endpointName, undefined, options);
}
getServerInfo() {
+ this.report.trackApi(this, 'plugin', 'getServerInfo');
return appContext.restApiService.getConfig();
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
on(eventName: EventType, callback: (...args: any[]) => any) {
+ this.report.trackApi(this, 'plugin', 'on');
this.jsApi.addEventCallback(eventName, callback);
}
url(path?: string) {
+ this.report.trackApi(this, 'plugin', 'url');
if (!this._url) throw new Error('plugin url not set');
const relPath = '/plugins/' + this._name + (path || '/');
const sameOriginPath = window.location.origin + `${getBaseUrl()}${relPath}`;
@@ -200,6 +211,7 @@
}
screenUrl(screenName?: string) {
+ this.report.trackApi(this, 'plugin', 'screenUrl');
const origin = location.origin;
const base = getBaseUrl();
const tokenPart = screenName ? '/' + screenName : '';
@@ -216,21 +228,25 @@
}
get(url: string, callback?: SendCallback) {
+ this.report.trackApi(this, 'plugin', 'get');
console.warn('.get() is deprecated! Use .restApi().get()');
return this._send(HttpMethod.GET, url, callback);
}
post(url: string, payload: RequestPayload, callback?: SendCallback) {
+ this.report.trackApi(this, 'plugin', 'post');
console.warn('.post() is deprecated! Use .restApi().post()');
return this._send(HttpMethod.POST, url, callback, payload);
}
put(url: string, payload: RequestPayload, callback?: SendCallback) {
+ this.report.trackApi(this, 'plugin', 'put');
console.warn('.put() is deprecated! Use .restApi().put()');
return this._send(HttpMethod.PUT, url, callback, payload);
}
delete(url: string, callback?: SendCallback) {
+ this.report.trackApi(this, 'plugin', 'delete');
console.warn('.delete() is deprecated! Use plugin.restApi().delete()');
return this.restApi()
.delete(this.url(url))
@@ -286,19 +302,19 @@
}
styles(): StylesPluginApi {
- return new GrStylesApi();
+ return new GrStylesApi(this);
}
restApi(prefix?: string): RestPluginApi {
- return new GrPluginRestApi(prefix);
+ return new GrPluginRestApi(this, prefix);
}
- attributeHelper(element: HTMLElement) {
- return new GrAttributeHelper(element);
+ attributeHelper(element: HTMLElement): AttributeHelperPluginApi {
+ return new GrAttributeHelper(this, element);
}
eventHelper(element: HTMLElement): EventHelperPluginApi {
- return new GrEventHelper(element);
+ return new GrEventHelper(this, element);
}
popup(): Promise<PopupPluginApi>;
@@ -314,6 +330,7 @@
}
screen(screenName: string, moduleName?: string) {
+ this.report.trackApi(this, 'plugin', 'screen');
if (moduleName && typeof moduleName !== 'string') {
console.error(
'.screen(pattern, callback) deprecated, use ' +
@@ -328,6 +345,7 @@
}
_getScreenName(screenName: string) {
+ this.report.trackApi(this, 'plugin', '_getScreenName');
return `${this.getPluginName()}-screen-${screenName}`;
}
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-reporting-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-reporting-js-api.ts
index d4b51a8..205f0fe 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-reporting-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-reporting-js-api.ts
@@ -25,9 +25,12 @@
export class GrReportingJsApi implements ReportingPluginApi {
private readonly reporting = appContext.reportingService;
- constructor(private readonly plugin: PluginApi) {}
+ constructor(private readonly plugin: PluginApi) {
+ this.reporting.trackApi(this.plugin, 'reporting', 'constructor');
+ }
reportInteraction(eventName: string, details?: EventDetails) {
+ this.reporting.trackApi(this.plugin, 'reporting', 'reportInteraction');
this.reporting.reportInteraction(
`${this.plugin.getPluginName()}-${eventName}`,
details
@@ -35,6 +38,7 @@
}
reportLifeCycle(eventName: string, details?: EventDetails) {
+ this.reporting.trackApi(this.plugin, 'reporting', 'reportLifeCycle');
this.reporting.reportLifeCycle(
`${this.plugin.getPluginName()}-${eventName}`,
details
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts b/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts
index 4196513..1be1d63 100644
--- a/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts
+++ b/polygerrit-ui/app/services/gr-reporting/gr-reporting.ts
@@ -17,6 +17,7 @@
import {NumericChangeId} from '../../types/common';
import {EventDetails} from '../../api/reporting';
+import {PluginApi} from '../../api/plugin';
export type EventValue = string | number | {error?: Error};
@@ -97,6 +98,7 @@
* Every execution is only reported once per session.
*/
reportExecution(id: string, details: EventDetails): void;
+ trackApi(plugin: PluginApi, object: string, method: string): void;
reportInteraction(eventName: string, details?: EventDetails): void;
/**
* A draft interaction was started. Update the time-between-draft-actions
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts b/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts
index 631a4e0..e57670d 100644
--- a/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts
+++ b/polygerrit-ui/app/services/gr-reporting/gr-reporting_impl.ts
@@ -20,6 +20,7 @@
import {hasOwnProperty} from '../../utils/common-util';
import {NumericChangeId} from '../../types/common';
import {EventDetails} from '../../api/reporting';
+import {PluginApi} from '../../api/plugin';
// Latency reporting constants.
@@ -800,10 +801,18 @@
id,
undefined,
details,
- false
+ true // skip console log
);
}
+ trackApi(plugin: PluginApi, object: string, method: string) {
+ this.reportExecution('plugin-api', {
+ plugin: plugin.getPluginName(),
+ object,
+ method,
+ });
+ }
+
/**
* A draft interaction was started. Update the time-between-draft-actions
* timer.
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock.ts b/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock.ts
index 484ce45..7d66484 100644
--- a/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock.ts
+++ b/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock.ts
@@ -16,6 +16,7 @@
*/
import {ReportingService, Timer} from './gr-reporting';
import {EventDetails} from '../../api/reporting';
+import {PluginApi} from '../../api/plugin';
export class MockTimer implements Timer {
end(): this {
@@ -67,6 +68,9 @@
reportExecution: (id: string, details: EventDetails) => {
log(`reportExecution '${id}': ${JSON.stringify(details)}`);
},
+ trackApi: (plugin: PluginApi, object: string, method: string) => {
+ log(`trackApi '${plugin}', ${object}, ${method}`);
+ },
reportExtension: () => {},
reportInteraction: (eventName: string, details?: EventDetails) => {
log(`reportInteraction '${eventName}': ${JSON.stringify(details)}`);