Add telemetry data for time to search in a project
MODIFY
lib/find.coffee
lib/find.coffee
@@ -9,6 +9,9 @@ FindView = require './find-view'
ProjectFindView = require './project-find-view'
ResultsModel = require './project/results-model'
ResultsPaneView = require './project/results-pane'
+ReporterProxy = require './reporter-proxy'
+
+metricsReporter = new ReporterProxy()
module.exports =
activate: ({findOptions, findHistory, replaceHistory, pathsHistory}={}) ->
@@ -28,7 +31,7 @@ module.exports =
@findOptions = new FindOptions(findOptions)
@findModel = new BufferSearch(@findOptions)
- @resultsModel = new ResultsModel(@findOptions)
+ @resultsModel = new ResultsModel(@findOptions, metricsReporter)
@subscriptions.add atom.workspace.getCenter().observeActivePaneItem (paneItem) =>
@subscriptions.delete @currentItemSub
@@ -132,6 +135,11 @@ module.exports =
'find-and-replace:select-skip': (event) ->
selectNextObjectForEditorElement(this).skipCurrentSelection()
+ consumeMetricsReporter: (service) ->
+ metricsReporter.setReporter(service)
+ new Disposable ->
+ metricsReporter.unsetReporter()
+
consumeElementIcons: (service) ->
getIconServices().setElementIcons service
new Disposable ->

MODIFY
lib/project/results-model.js
lib/project/results-model.js
@@ -27,7 +27,8 @@ class Result {
}
module.exports = class ResultsModel {
- constructor (findOptions) {
+ constructor (findOptions, metricsReporter) {
+ this.metricsReporter = metricsReporter
this.onContentsModified = this.onContentsModified.bind(this)
this.findOptions = findOptions
this.emitter = new Emitter()
@@ -172,6 +173,9 @@ module.exports = class ResultsModel {
const leadingContextLineCount = atom.config.get('find-and-replace.searchContextLineCountBefore')
const trailingContextLineCount = atom.config.get('find-and-replace.searchContextLineCountAfter')
+
+ const startTime = Date.now()
+
this.inProgressSearchPromise = atom.workspace.scan(
this.regex,
{
@@ -195,8 +199,11 @@ module.exports = class ResultsModel {
if (message === 'cancelled') {
this.emitter.emit('did-cancel-searching')
} else {
+ const resultsSummary = this.getResultsSummary()
+
+ this.metricsReporter.sendSearchEvent(Date.now() - startTime, resultsSummary.matchCount)
this.inProgressSearchPromise = null
- this.emitter.emit('did-finish-searching', this.getResultsSummary())
+ this.emitter.emit('did-finish-searching', resultsSummary)
}
})
}

ADD
lib/reporter-proxy.js
+module.exports = class ReporterProxy {
+ constructor () {
+ this.reporter = null
+ this.timingsQueue = []
+
+ this.eventType = 'find-and-replace-v1'
+ }
+
+ setReporter (reporter) {
+ this.reporter = reporter
+ let timingsEvent
+
+ while ((timingsEvent = this.timingsQueue.shift())) {
+ this.reporter.addTiming(this.eventType, timingsEvent[0], timingsEvent[1])
+ }
+ }
+
+ unsetReporter () {
+ delete this.reporter
+ }
+
+ sendSearchEvent (duration, numResults) {
+ const metadata = {
+ ec: 'time-to-search',
+ ev: numResults
+ }
+
+ this._addTiming(duration, metadata)
+ }
+
+ _addTiming (duration, metadata) {
+ if (this.reporter) {
+ this.reporter.addTiming(this.eventType, duration, metadata)
+ } else {
+ this.timingsQueue.push([duration, metadata])
+ }
+ }
+}

MODIFY
package-lock.json
package-lock.json
"integrity": "sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s=",
"dev": true
},
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
"element-resize-detector": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.1.12.tgz",
"batch-processor": "^1.0.0"
}
},
+ "es-abstract": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+ "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-keys": "^1.0.12"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
"etch": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/etch/-/etch-0.9.3.tgz",
"integrity": "sha1-2uxSmVv2E1A9a5K0H1Si6qEuMis="
},
+ "formatio": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz",
+ "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=",
+ "dev": true,
+ "requires": {
+ "samsam": "~1.1"
+ }
+ },
"fs-plus": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"path-is-absolute": "^1.0.0"
}
},
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
"ignore": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-generator-function": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
+ "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "lolex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz",
+ "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=",
+ "dev": true
+ },
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"minimist": "0.0.8"
}
},
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.entries": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
+ "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.12.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3"
+ }
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"glob": "^7.0.5"
}
},
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "samsam": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz",
+ "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=",
+ "dev": true
+ },
+ "sinon": {
+ "version": "1.17.4",
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.4.tgz",
+ "integrity": "sha1-Tk/02Esgre4TE482rLEyyhzXLIM=",
+ "dev": true,
+ "requires": {
+ "formatio": "1.1.1",
+ "lolex": "1.3.2",
+ "samsam": "1.1.2",
+ "util": ">=0.10.3 <1"
+ }
+ },
"strip-json-comments": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
"underscore": "~1.6.0"
}
},
+ "util": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz",
+ "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "object.entries": "^1.1.0",
+ "safe-buffer": "^5.1.2"
+ }
+ },
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",

MODIFY
package.json
package.json
},
"devDependencies": {
"coffeelint": "^1.9.7",
- "dedent": "^0.6.0"
+ "dedent": "^0.6.0",
+ "sinon": "1.17.4"
},
"consumedServices": {
"atom.file-icons": {
"versions": {
"1.0.0": "consumeElementIcons"
}
+ },
+ "metrics-reporter": {
+ "versions": {
+ "^1.1.0": "consumeMetricsReporter"
+ }
}
},
"providedServices": {

MODIFY
spec/results-model-spec.js
spec/results-model-spec.js
/** @babel */
const path = require("path");
+const sinon = require("sinon")
const ResultsModel = require("../lib/project/results-model");
const FindOptions = require("../lib/find-options");
-const {beforeEach, it, fit, ffit, fffit} = require('./async-spec-helpers')
describe("ResultsModel", () => {
- let editor, resultsModel;
+ let editor, resultsModel, reporterStub;
beforeEach(async () => {
atom.config.set("core.excludeVcsIgnoredPaths", false);
@@ -15,7 +15,10 @@ describe("ResultsModel", () => {
atom.project.setPaths([path.join(__dirname, "fixtures/project")]);
editor = await atom.workspace.open("sample.js");
- resultsModel = new ResultsModel(new FindOptions());
+ reporterStub = {
+ sendSearchEvent: sinon.spy()
+ }
+ resultsModel = new ResultsModel(new FindOptions(), reporterStub);
});
describe("searching for a pattern", () => {

Add telemetry data for time to search in a project