Skip to content

Commit 3382155

Browse files
committed
feat(metrics): add designTimeMD bucket stream for markdown/GFM files
Generalize the design-mode dwell tracker into a small helper and run two instances: the existing overall designTime plus a new designTimeMD that only accrues while the active pane's file is markdown or GFM. The MD tracker starts on entering design mode if the active file is markdown, switches on/off via currentFileChange while in design mode, and flushes on exit alongside the main tracker.
1 parent 069bd24 commit 3382155

1 file changed

Lines changed: 83 additions & 21 deletions

File tree

src/view/CentralControlBar.js

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ define(function (require, exports, module) {
2424
const CommandManager = require("command/CommandManager");
2525
const Commands = require("command/Commands");
2626
const DocumentManager = require("document/DocumentManager");
27+
const LanguageManager = require("language/LanguageManager");
2728
const MainViewManager = require("view/MainViewManager");
2829
const Metrics = require("utils/Metrics");
2930
const Strings = require("strings");
@@ -229,39 +230,89 @@ define(function (require, exports, module) {
229230
// Track cumulative session time in design mode and emit a metric the
230231
// first time the total crosses each of these minute buckets. A
231232
// 5-minute ticker rolls the in-progress stretch into the aggregate;
232-
// an exit also flushes so a partial stretch isn't dropped.
233+
// an exit (or a switch away from a markdown file, for the MD stream)
234+
// also flushes so a partial stretch isn't dropped.
233235
const DESIGN_TIME_BUCKETS_MIN = [1, 5, 10, 15, 20, 30, 45, 60];
234236
const MS_PER_MIN = 60 * 1000;
235237
const DESIGN_TIME_TICK_MS = 5 * MS_PER_MIN;
236-
let _designModeTimeFrom = null;
237-
let _aggregateDesignMs = 0;
238-
let _lastDesignBucketEmittedIdx = -1;
239238

240-
function _emitCrossedDesignBuckets() {
241-
const minutes = Math.floor(_aggregateDesignMs / MS_PER_MIN);
239+
function _makeDesignTracker(metricName) {
240+
return {
241+
timeFrom: null,
242+
aggregateMs: 0,
243+
lastEmittedIdx: -1,
244+
metricName: metricName
245+
};
246+
}
247+
248+
function _emitCrossedBuckets(tracker) {
249+
const minutes = Math.floor(tracker.aggregateMs / MS_PER_MIN);
242250
// A single tick can cross more than one bucket (e.g. 0 → 5 min
243251
// crosses both 1M and 5M), so drain every bucket the aggregate
244252
// has now passed.
245-
let checkIndex = _lastDesignBucketEmittedIdx + 1;
253+
let checkIndex = tracker.lastEmittedIdx + 1;
246254
while (checkIndex < DESIGN_TIME_BUCKETS_MIN.length &&
247255
minutes >= DESIGN_TIME_BUCKETS_MIN[checkIndex]) {
248-
_lastDesignBucketEmittedIdx = checkIndex;
249-
Metrics.countEvent(Metrics.EVENT_TYPE.UI, "designTime",
256+
tracker.lastEmittedIdx = checkIndex;
257+
Metrics.countEvent(Metrics.EVENT_TYPE.UI, tracker.metricName,
250258
DESIGN_TIME_BUCKETS_MIN[checkIndex] + "M");
251259
checkIndex++;
252260
}
253261
}
254262

255-
function _onDesignTimeTick() {
256-
if (_designModeTimeFrom == null) {
263+
function _rollTracker(tracker) {
264+
if (tracker.timeFrom == null) {
257265
return;
258266
}
259267
const now = Date.now();
260-
_aggregateDesignMs += now - _designModeTimeFrom;
261-
_designModeTimeFrom = now;
262-
_emitCrossedDesignBuckets();
268+
tracker.aggregateMs += now - tracker.timeFrom;
269+
tracker.timeFrom = now;
270+
_emitCrossedBuckets(tracker);
271+
}
272+
273+
function _flushTracker(tracker) {
274+
if (tracker.timeFrom == null) {
275+
return;
276+
}
277+
tracker.aggregateMs += Date.now() - tracker.timeFrom;
278+
tracker.timeFrom = null;
279+
_emitCrossedBuckets(tracker);
263280
}
264-
setInterval(_onDesignTimeTick, DESIGN_TIME_TICK_MS);
281+
282+
// Overall design-mode dwell, plus a sub-stream that only accrues
283+
// while the active file is markdown / GFM.
284+
const _designTracker = _makeDesignTracker("designTime");
285+
const _mdDesignTracker = _makeDesignTracker("designTimeMD");
286+
287+
function _activeFileIsMarkdown() {
288+
const file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);
289+
if (!file || !file.fullPath) {
290+
return false;
291+
}
292+
const lang = LanguageManager.getLanguageForPath(file.fullPath);
293+
if (!lang) {
294+
return false;
295+
}
296+
const id = lang.getId();
297+
return id === "markdown" || id === "gfm";
298+
}
299+
300+
function _syncMdTrackerToActiveFile() {
301+
// Only ever runs while in design mode — the caller (the
302+
// currentFileChange handler) is a no-op otherwise.
303+
const isMd = _activeFileIsMarkdown();
304+
const wasTracking = _mdDesignTracker.timeFrom != null;
305+
if (isMd && !wasTracking) {
306+
_mdDesignTracker.timeFrom = Date.now();
307+
} else if (!isMd && wasTracking) {
308+
_flushTracker(_mdDesignTracker);
309+
}
310+
}
311+
312+
setInterval(function () {
313+
_rollTracker(_designTracker);
314+
_rollTracker(_mdDesignTracker);
315+
}, DESIGN_TIME_TICK_MS);
265316

266317
function _setEditorCollapsed(collapsed, opts) {
267318
const wantCollapsed = !!collapsed;
@@ -285,12 +336,15 @@ define(function (require, exports, module) {
285336
}
286337
editorCollapsed = wantCollapsed;
287338
if (editorCollapsed) {
288-
_designModeTimeFrom = Date.now();
289-
} else if (_designModeTimeFrom != null) {
290-
// Flush the in-progress stretch into the aggregate so the
339+
_designTracker.timeFrom = Date.now();
340+
if (_activeFileIsMarkdown()) {
341+
_mdDesignTracker.timeFrom = Date.now();
342+
}
343+
} else {
344+
// Flush the in-progress stretch into each aggregate so the
291345
// sliver between the last tick and this exit isn't dropped.
292-
_aggregateDesignMs += Date.now() - _designModeTimeFrom;
293-
_designModeTimeFrom = null;
346+
_flushTracker(_designTracker);
347+
_flushTracker(_mdDesignTracker);
294348
}
295349
$("body").toggleClass("ccb-editor-collapsed", editorCollapsed);
296350
const $collapseBtn = $("#ccbCollapseEditorBtn");
@@ -540,7 +594,15 @@ define(function (require, exports, module) {
540594

541595
_updateSidebarToggleIcon();
542596

543-
MainViewManager.on("currentFileChange.ccb", _updateFileLabel);
597+
MainViewManager.on("currentFileChange.ccb", function () {
598+
_updateFileLabel();
599+
// While in design mode, the MD-only timer should follow the
600+
// active file: start accruing on switch INTO markdown, flush
601+
// on switch OUT.
602+
if (editorCollapsed) {
603+
_syncMdTrackerToActiveFile();
604+
}
605+
});
544606
DocumentManager.on("dirtyFlagChange.ccb", _updateFileLabel);
545607
DocumentManager.on("pathDeleted.ccb fileNameChange.ccb", _updateFileLabel);
546608
_updateFileLabel();

0 commit comments

Comments
 (0)