Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #11311 from adobe/abose/HealthLogs1.4
Browse files Browse the repository at this point in the history
Health Data Logs for 1.4
  • Loading branch information
abose committed Jul 11, 2015
2 parents d1a5c5c + 90f9a38 commit 389d9e6
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 19 deletions.
3 changes: 3 additions & 0 deletions src/document/DocumentCommandHandlers.js
Expand Up @@ -44,6 +44,7 @@ define(function (require, exports, module) {
InMemoryFile = require("document/InMemoryFile"),
StringUtils = require("utils/StringUtils"),
Async = require("utils/Async"),
HealthLogger = require("utils/HealthLogger"),
Dialogs = require("widgets/Dialogs"),
DefaultDialogs = require("widgets/DefaultDialogs"),
Strings = require("strings"),
Expand Down Expand Up @@ -451,6 +452,7 @@ define(function (require, exports, module) {

_doOpenWithOptionalPath(fileInfo.path, silent, paneId, commandData && commandData.options)
.done(function (file) {
HealthLogger.fileOpened(fileInfo.path);
if (!commandData || !commandData.options || !commandData.options.noPaneActivate) {
MainViewManager.setActivePaneId(paneId);
}
Expand Down Expand Up @@ -528,6 +530,7 @@ define(function (require, exports, module) {
return handleFileOpen(commandData).done(function (file) {
var paneId = (commandData && commandData.paneId) || MainViewManager.ACTIVE_PANE;
MainViewManager.addToWorkingSet(paneId, file, commandData.index, commandData.forceRedraw);
HealthLogger.fileOpened(file.fullPath, true);
});
}

Expand Down
9 changes: 7 additions & 2 deletions src/extensions/default/HealthData/HealthDataManager.js
Expand Up @@ -28,6 +28,7 @@ define(function (require, exports, module) {
"use strict";

var AppInit = brackets.getModule("utils/AppInit"),
HealthLogger = brackets.getModule("utils/HealthLogger"),
PreferencesManager = brackets.getModule("preferences/PreferencesManager"),
UrlParams = brackets.getModule("utils/UrlParams").UrlParams,
Strings = brackets.getModule("strings"),
Expand Down Expand Up @@ -69,6 +70,7 @@ define(function (require, exports, module) {
oneTimeHealthData.osLanguage = brackets.app.language;
oneTimeHealthData.bracketsLanguage = brackets.getLocale();
oneTimeHealthData.bracketsVersion = brackets.metadata.version;
$.extend(oneTimeHealthData, HealthLogger.getAggregatedHealthData());

HealthDataUtils.getUserInstalledExtensions()
.done(function (userInstalledExtensions) {
Expand Down Expand Up @@ -123,7 +125,7 @@ define(function (require, exports, module) {
function checkHealthDataSend() {
var result = new $.Deferred(),
isHDTracking = prefs.get("healthDataTracking");

HealthLogger.setHealthLogsEnabled(isHDTracking);
window.clearTimeout(timeoutVar);
if (isHDTracking) {
var nextTimeToSend = PreferencesManager.getViewState("nextHealthDataSendTime"),
Expand All @@ -144,6 +146,9 @@ define(function (require, exports, module) {

sendHealthDataToServer()
.done(function () {
// We have already sent the health data, so can clear all health data
// Logged till now
HealthLogger.clearHealthData();
result.resolve();
})
.fail(function () {
Expand Down Expand Up @@ -182,4 +187,4 @@ define(function (require, exports, module) {

exports.getHealthData = getHealthData;
exports.checkHealthDataSend = checkHealthDataSend;
});
});
6 changes: 6 additions & 0 deletions src/extensions/default/HealthData/main.js
Expand Up @@ -28,10 +28,12 @@ define(function (require, exports, module) {
"use strict";

var AppInit = brackets.getModule("utils/AppInit"),
HealthLogger = brackets.getModule("utils/HealthLogger"),
Menus = brackets.getModule("command/Menus"),
CommandManager = brackets.getModule("command/CommandManager"),
Strings = brackets.getModule("strings"),
Commands = brackets.getModule("command/Commands"),
PreferencesManager = brackets.getModule("preferences/PreferencesManager"),

HealthDataNotification = require("HealthDataNotification"), // self-initializes to show first-launch notification
HealthDataManager = require("HealthDataManager"), // self-initializes timer to send data
Expand All @@ -58,10 +60,14 @@ define(function (require, exports, module) {
brackets.test.HealthDataManager = HealthDataManager;
brackets.test.HealthDataNotification = HealthDataNotification;
brackets.test.HealthDataPopup = HealthDataPopup;

var prefs = PreferencesManager.getExtensionPrefs("healthData");
HealthLogger.setHealthLogsEnabled(prefs.get("healthDataTracking"));
}

AppInit.appReady(function () {
initTest();
HealthLogger.init();
});

addCommand();
Expand Down
170 changes: 170 additions & 0 deletions src/utils/HealthLogger.js
@@ -0,0 +1,170 @@
/*
* Copyright (c) 2015 Adobe Systems Incorporated. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/

/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, $*/

/**
* Utilities functions related to Health Data logging
*/
define(function (require, exports, module) {
"use strict";

var PreferencesManager = require("preferences/PreferencesManager"),
LanguageManager = require("language/LanguageManager"),
FileUtils = require("file/FileUtils"),
PerfUtils = require("utils/PerfUtils"),

HEALTH_DATA_STATE_KEY = "HealthData.Logs",
logHealthData = true;

/**
* Init: creates the health log preference keys in the state.json file
*/
function init() {
PreferencesManager.stateManager.definePreference(HEALTH_DATA_STATE_KEY, "object", {});
}

/**
* All the logging functions should be disabled if this returns false
* @returns {boolean} true if health data can be logged
*/
function shouldLogHealthData() {
return logHealthData;
}

/**
* Return the Performance related data
* @returns {Object} Performance Data aggregated till now
*/
function getPerformanceData() {
return PerfUtils.getHealthReport();
}

/**
* Return all health data logged till now stored in the state prefs
* @returns {Object} Health Data aggregated till now
*/
function getStoredHealthData() {
return PreferencesManager.getViewState(HEALTH_DATA_STATE_KEY);
}

/**
* Return the aggregate of all health data logged till now from all sources
* @returns {Object} Health Data aggregated till now
*/
function getAggregatedHealthData() {
var healthData = getStoredHealthData();
$.extend(healthData, getPerformanceData());
return healthData;
}

/**
* Sets the health data
* @param {Object} dataObject The object to be stored as health data
*/
function setHealthData(dataObject) {
if (!shouldLogHealthData()) {
return;
}
PreferencesManager.setViewState(HEALTH_DATA_STATE_KEY, dataObject);
}

/**
* Returns health data logged for the given key
* @returns {Object} Health Data object for the key or undefined if no health data stored
*/
function getHealthDataLog(key) {
var healthData = getStoredHealthData();
return healthData[key];
}

/**
* Sets the health data for the given key
* @param {Object} dataObject The object to be stored as health data for the key
*/
function setHealthDataLog(key, dataObject) {
var healthData = getStoredHealthData();
healthData[key] = dataObject;
setHealthData(healthData);
}

/**
* Clears all the health data recorded till now
*/
function clearHealthData() {
PreferencesManager.setViewState(HEALTH_DATA_STATE_KEY, {});
//clear the performance related health data also
PerfUtils.clear();
}

/**
* Enable or disable health data logs
* @param {boolean} enabled true to enable health logs
*/
function setHealthLogsEnabled(enabled) {
logHealthData = enabled;
if (!enabled) {
clearHealthData();
}
}

/**
* Whenever a file is opened call this function. The function will record the number of times
* the standard file types have been opened. We only log the standard filetypes
* @param {String} filePath The path of the file to be registered
* @param {boolean} addedToWorkingSet set to true if extensions of files added to the
* working set needs to be logged
*/
function fileOpened(filePath, addedToWorkingSet) {
if (!shouldLogHealthData()) {
return;
}
var fileExtension = FileUtils.getFileExtension(filePath),
language = LanguageManager.getLanguageForPath(filePath),
healthData = getStoredHealthData(),
fileExtCountMap = [];
healthData.fileStats = healthData.fileStats || {
openedFileExt : {},
workingSetFileExt : {}
};
if (language.getId() !== "unknown") {
fileExtCountMap = addedToWorkingSet ? healthData.fileStats.workingSetFileExt : healthData.fileStats.openedFileExt;
if (!fileExtCountMap[fileExtension]) {
fileExtCountMap[fileExtension] = 0;
}
fileExtCountMap[fileExtension]++;
setHealthData(healthData);
}
}

// Define public API
exports.getHealthDataLog = getHealthDataLog;
exports.setHealthDataLog = setHealthDataLog;
exports.getAggregatedHealthData = getAggregatedHealthData;
exports.clearHealthData = clearHealthData;
exports.fileOpened = fileOpened;
exports.setHealthLogsEnabled = setHealthLogsEnabled;
exports.shouldLogHealthData = shouldLogHealthData;
exports.init = init;
});
84 changes: 67 additions & 17 deletions src/utils/PerfUtils.js
Expand Up @@ -30,7 +30,8 @@
define(function (require, exports, module) {
"use strict";

var _ = require("thirdparty/lodash");
var _ = require("thirdparty/lodash"),
StringUtils = require("utils/StringUtils");

// make sure the global brackets variable is loaded
require("utils/Global");
Expand Down Expand Up @@ -303,30 +304,53 @@ define(function (require, exports, module) {
}

/**
* Returns the performance data as a tab deliminted string
* @return {string}
* return single value, or comma separated values for an array or return aggregated values with
* <min value, average, max value, standard deviation>
* @param {Array} entry An array or a single value
* @param {Boolean} aggregateStats If set, the returned value will be aggregated in the form -
* <min(avg)max[standard deviation]>
* @returns {String} a single value, or comma separated values in an array or
* <min(avg)max[standard deviation]> if aggregateStats is set
*/
function getDelimitedPerfData() {
var getValue = function (entry) {
// return single value, or tab deliminted values for an array
if (Array.isArray(entry)) {
var i, values = "";

var getValueAsString = function (entry, aggregateStats) {
if (Array.isArray(entry)) {
var i, values = "", min = entry[0], max = entry[0], avg = 0, sum = 0, sd = 0;

for (i = 0; i < entry.length; i++) {
sum = sum + entry[i];
values += entry[i];
if (i < entry.length - 1) {
values += ", ";
}
}
if (aggregateStats) {
avg = Math.round(sum / entry.length);
sum = 0;
for (i = 0; i < entry.length; i++) {
values += entry[i];
if (i < entry.length - 1) {
values += ", ";
sum = sum + Math.pow((entry[i] - avg), 2);
if (entry[i] < min) {
min = entry[i];
} else if (entry[i] > max) {
max = entry[i];
}
}
return values;
} else {
return entry;
sd = Math.round(Math.sqrt(sum / entry.length));
return min + "(" + avg + ")" + max + "[" + sd + "]";
}
};
return values;
} else {
return entry;
}
};

/**
* Returns the performance data as a tab delimited string
* @return {string}
*/
function getDelimitedPerfData() {
var result = "";
_.forEach(perfData, function (entry, testName) {
result += getValue(entry) + "\t" + testName + "\n";
result += getValueAsString(entry) + "\t" + testName + "\n";
});

return result;
Expand All @@ -344,6 +368,31 @@ define(function (require, exports, module) {
return perfData[id];
}

/**
* Returns the Performance metrics to be logged for health report
* @returns {Object} An object with the helath data logs to be send
*/
function getHealthReport() {
var healthReport = {
projectLoadTimes : "",
fileOpenTimes : ""
};

_.forEach(perfData, function (entry, testName) {
if (StringUtils.startsWith(testName, "Application Startup")) {
healthReport.AppStartupTime = getValueAsString(entry);
} else if (StringUtils.startsWith(testName, "brackets module dependencies resolved")) {
healthReport.ModuleDepsResolved = getValueAsString(entry);
} else if (StringUtils.startsWith(testName, "Load Project")) {
healthReport.projectLoadTimes += ":" + getValueAsString(entry, true);
} else if (StringUtils.startsWith(testName, "Open File")) {
healthReport.fileOpenTimes += ":" + getValueAsString(entry, true);
}
});

return healthReport;
}

function searchData(regExp) {
var keys = Object.keys(perfData).filter(function (key) {
return regExp.test(key);
Expand Down Expand Up @@ -384,4 +433,5 @@ define(function (require, exports, module) {
exports.getDelimitedPerfData = getDelimitedPerfData;
exports.createPerfMeasurement = createPerfMeasurement;
exports.clear = clear;
exports.getHealthReport = getHealthReport;
});

0 comments on commit 389d9e6

Please sign in to comment.