mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Add new telemetry events
Summary: Adds a handful of new telemetry events, and makes a few tweaks to allow for better organization of telemetry. Test Plan: Manual. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D4100
This commit is contained in:
@@ -24,6 +24,7 @@ import {DocPluginManager} from 'app/client/lib/DocPluginManager';
|
||||
import {ImportSourceElement} from 'app/client/lib/ImportSourceElement';
|
||||
import {makeT} from 'app/client/lib/localization';
|
||||
import {createSessionObs} from 'app/client/lib/sessionObs';
|
||||
import {logTelemetryEvent} from 'app/client/lib/telemetry';
|
||||
import {setTestState} from 'app/client/lib/testState';
|
||||
import {selectFiles} from 'app/client/lib/uploads';
|
||||
import {AppModel, reportError} from 'app/client/models/AppModel';
|
||||
@@ -62,7 +63,7 @@ import {DisposableWithEvents} from 'app/common/DisposableWithEvents';
|
||||
import {isSchemaAction, UserAction} from 'app/common/DocActions';
|
||||
import {OpenLocalDocResult} from 'app/common/DocListAPI';
|
||||
import {isList, isListType, isRefListType, RecalcWhen} from 'app/common/gristTypes';
|
||||
import {HashLink, IDocPage, isViewDocPage, SpecialDocPage, ViewDocPage} from 'app/common/gristUrls';
|
||||
import {HashLink, IDocPage, isViewDocPage, parseUrlId, SpecialDocPage, ViewDocPage} from 'app/common/gristUrls';
|
||||
import {undef, waitObs} from 'app/common/gutil';
|
||||
import {LocalPlugin} from "app/common/plugin";
|
||||
import {StringUnion} from 'app/common/StringUnion';
|
||||
@@ -400,6 +401,16 @@ export class GristDoc extends DisposableWithEvents {
|
||||
&& markAsSeen(this._seenDocTours, this.docId())
|
||||
);
|
||||
await startDocTour(this.docData, this.docComm, onFinishCB);
|
||||
if (this.docPageModel.isTemplate.get()) {
|
||||
const doc = this.docPageModel.currentDoc.get();
|
||||
if (!doc) { return; }
|
||||
|
||||
logTelemetryEvent('openedTemplateTour', {
|
||||
full: {
|
||||
templateId: parseUrlId(doc.urlId || doc.id).trunkId,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
startWelcomeTour(() => this._showGristTour.set(false));
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import {Document, NEW_DOCUMENT_CODE, Organization, UserAPI, Workspace} from 'app
|
||||
import {Holder, Observable, subscribe} from 'grainjs';
|
||||
import {Computed, Disposable, dom, DomArg, DomElementArg} from 'grainjs';
|
||||
import {makeT} from 'app/client/lib/localization';
|
||||
import {logTelemetryEvent} from 'app/client/lib/telemetry';
|
||||
|
||||
// tslint:disable:no-console
|
||||
|
||||
@@ -365,6 +366,14 @@ It also disables formulas. [{{error}}]", {error: err.message})
|
||||
await this.updateUrlNoReload(doc.urlId, doc.openMode);
|
||||
}
|
||||
|
||||
if (doc.isTemplate) {
|
||||
logTelemetryEvent('openedTemplate', {
|
||||
full: {
|
||||
templateId: parseUrlId(doc.urlId || doc.id).trunkId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this.currentDoc.set(doc);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ export class DocTutorial extends FloatingPopup {
|
||||
if (tableData) {
|
||||
this.autoDispose(tableData.tableActionEmitter.addListener(() => this._reloadSlides()));
|
||||
}
|
||||
|
||||
this._logTelemetryEvent('tutorialOpened');
|
||||
}
|
||||
|
||||
protected _buildTitle() {
|
||||
@@ -158,6 +160,24 @@ export class DocTutorial extends FloatingPopup {
|
||||
];
|
||||
}
|
||||
|
||||
private _logTelemetryEvent(event: 'tutorialOpened' | 'tutorialProgressChanged') {
|
||||
const currentSlideIndex = this._currentSlideIndex.get();
|
||||
const numSlides = this._slides.get()?.length;
|
||||
let percentComplete: number | undefined = undefined;
|
||||
if (numSlides !== undefined && numSlides > 0) {
|
||||
percentComplete = Math.floor(((currentSlideIndex + 1) / numSlides) * 100);
|
||||
}
|
||||
logTelemetryEvent(event, {
|
||||
full: {
|
||||
tutorialForkIdDigest: this._currentFork?.id,
|
||||
tutorialTrunkIdDigest: this._currentFork?.trunkId,
|
||||
lastSlideIndex: currentSlideIndex,
|
||||
numSlides,
|
||||
percentComplete,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async _loadSlides() {
|
||||
const tableId = 'GristDocTutorial';
|
||||
if (!this._docData.getTable(tableId)) {
|
||||
@@ -234,7 +254,6 @@ export class DocTutorial extends FloatingPopup {
|
||||
private async _saveCurrentSlidePosition() {
|
||||
const currentOptions = this._currentDoc?.options ?? {};
|
||||
const currentSlideIndex = this._currentSlideIndex.get();
|
||||
const numSlides = this._slides.get()?.length;
|
||||
await this._appModel.api.updateDoc(this._docId, {
|
||||
options: {
|
||||
...currentOptions,
|
||||
@@ -243,20 +262,7 @@ export class DocTutorial extends FloatingPopup {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let percentComplete: number | undefined = undefined;
|
||||
if (numSlides !== undefined && numSlides > 0) {
|
||||
percentComplete = Math.floor(((currentSlideIndex + 1) / numSlides) * 100);
|
||||
}
|
||||
logTelemetryEvent('tutorialProgressChanged', {
|
||||
full: {
|
||||
tutorialForkIdDigest: this._currentFork?.id,
|
||||
tutorialTrunkIdDigest: this._currentFork?.trunkId,
|
||||
lastSlideIndex: currentSlideIndex,
|
||||
numSlides,
|
||||
percentComplete,
|
||||
},
|
||||
});
|
||||
this._logTelemetryEvent('tutorialProgressChanged');
|
||||
}
|
||||
|
||||
private async _changeSlide(slideIndex: number) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {logTelemetryEvent} from 'app/client/lib/telemetry';
|
||||
import {AppModel} from 'app/client/models/AppModel';
|
||||
import {bigBasicButton, bigPrimaryButtonLink} from 'app/client/ui2018/buttons';
|
||||
import {testId, theme, vars} from 'app/client/ui2018/cssVars';
|
||||
@@ -93,7 +94,10 @@ export function showWelcomeCoachingCall(triggerElement: Element, appModel: AppMo
|
||||
cssPopupButtons(
|
||||
bigPrimaryButtonLink(
|
||||
'Schedule Call',
|
||||
dom.on('click', () => dismissPopup(false)),
|
||||
dom.on('click', () => {
|
||||
dismissPopup(false);
|
||||
logTelemetryEvent('clickedScheduleCoachingCall');
|
||||
}),
|
||||
{
|
||||
href: FREE_COACHING_CALL_URL,
|
||||
target: '_blank',
|
||||
|
||||
@@ -172,9 +172,16 @@ export class FormulaAssistant extends Disposable {
|
||||
this._triggerFinalize = bundleInfo.triggerFinalize;
|
||||
this.onDispose(() => {
|
||||
if (this._hasExpandedOnce) {
|
||||
const suggestionApplied = this._chat.conversationSuggestedFormulas.get()
|
||||
.includes(this._options.column.formula.peek());
|
||||
if (suggestionApplied) {
|
||||
this._logTelemetryEvent('assistantApplySuggestion', false, {
|
||||
conversationLength: this._chat.conversationLength.get(),
|
||||
conversationHistoryLength: this._chat.conversationHistoryLength.get(),
|
||||
});
|
||||
}
|
||||
this._logTelemetryEvent('assistantClose', false, {
|
||||
suggestionApplied: this._chat.conversationSuggestedFormulas.get()
|
||||
.includes(this._options.column.formula.peek()),
|
||||
suggestionApplied,
|
||||
conversationLength: this._chat.conversationLength.get(),
|
||||
conversationHistoryLength: this._chat.conversationHistoryLength.get(),
|
||||
});
|
||||
@@ -400,7 +407,9 @@ export class FormulaAssistant extends Disposable {
|
||||
*/
|
||||
private _cancel() {
|
||||
if (this._hasExpandedOnce) {
|
||||
this._logTelemetryEvent('assistantCancel', true);
|
||||
this._logTelemetryEvent('assistantCancel', true, {
|
||||
conversationLength: this._chat.conversationLength.get(),
|
||||
});
|
||||
}
|
||||
this._action = 'cancel';
|
||||
this._triggerFinalize();
|
||||
|
||||
Reference in New Issue
Block a user