From 54fe0f47e428ef61a7d9e03df1dd217ecc86ed28 Mon Sep 17 00:00:00 2001 From: ste Date: Fri, 13 Jul 2018 15:20:46 +0100 Subject: [PATCH 1/6] GPII-3102: Removed windows component from metrics; it's a mix-in --- gpii/node_modules/eventLog/src/metrics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpii/node_modules/eventLog/src/metrics.js b/gpii/node_modules/eventLog/src/metrics.js index f476eea81..db5ecbb56 100644 --- a/gpii/node_modules/eventLog/src/metrics.js +++ b/gpii/node_modules/eventLog/src/metrics.js @@ -30,7 +30,7 @@ fluid.defaults("gpii.metrics", { checks: { windows: { contextValue: "{gpii.contexts.windows}", - gradeNames: "gpii.metrics.windows" + gradeNames: "gpii.windowsMetrics" } } } From f4cbacb0bf556b677f5045059268f919269b5b38 Mon Sep 17 00:00:00 2001 From: ste Date: Sat, 14 Jul 2018 22:00:49 +0100 Subject: [PATCH 2/6] GPII-3102: Monitoring preference changes. --- gpii/node_modules/eventLog/src/metrics.js | 61 ++++- gpii/node_modules/eventLog/test/all-tests.js | 22 ++ .../eventLog/test/metricsTests.js | 211 ++++++++++++++++++ tests/all-tests.js | 2 +- 4 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 gpii/node_modules/eventLog/test/all-tests.js create mode 100644 gpii/node_modules/eventLog/test/metricsTests.js diff --git a/gpii/node_modules/eventLog/src/metrics.js b/gpii/node_modules/eventLog/src/metrics.js index db5ecbb56..29bc36b6b 100644 --- a/gpii/node_modules/eventLog/src/metrics.js +++ b/gpii/node_modules/eventLog/src/metrics.js @@ -55,7 +55,12 @@ fluid.defaults("gpii.metrics", { } }, listeners: { - "{lifecycleManager}.events.onSessionStart": "{that}.events.onStartMetrics", + "{lifecycleManager}.events.onSessionStart": [{ + funcName: "gpii.metrics.sessionStarted", + args: [ "{that}", "{lifecycleManager}", "{arguments}.1"] + }, { + func: "{that}.events.onStartMetrics" + }], "{lifecycleManager}.events.onSessionStop": [{ namespace: "metrics.session", funcName: "gpii.metrics.sessionStopped", @@ -96,6 +101,60 @@ gpii.metrics.snapshotUpdate = function (that, sessionID, originalSettings) { }); }; +/** + * Handles the lifecycle.onSessionStarted event. + * + * Adds a listener to the new session's model to listen for changes to the preferences. + * + * @param {Component} that - The gpii.metrics instance. + * @param {Component} lifecycleManager - The lifecycleManager instance. + * @param {String} gpiiKey - The gpii key of the session. + */ +gpii.metrics.sessionStarted = function (that, lifecycleManager, gpiiKey) { + var session = lifecycleManager.getSession(gpiiKey); + session.applier.modelChanged.addListener("preferences.contexts", function (newValue, oldValue) { + var current = newValue && newValue[session.model.activeContextName]; + current = current && current.preferences; + var previous = oldValue && oldValue[session.model.activeContextName]; + previous = previous && previous.preferences; + + gpii.metrics.preferenceChanged(that, current, previous); + }); +}; + +/** + * Called when a preference has changed. (a change in the preferences field of the session's model.) + * + * @param {Comment} that - The gpii.metrics instance. + * @param {Object} current - The current preferences map for the active context. + * @param {Object} previous - The previous preferences map for the active context. + */ +gpii.metrics.preferenceChanged = function (that, current, previous) { + var diff = { changeMap: {}, changes: 0, unchanged: 0}; + var same = fluid.model.diff(previous, current, diff); + if (!same) { + var changedPreferences; + if (fluid.isPlainObject(diff.changeMap)) { + changedPreferences = {}; + fluid.each(diff.changeMap, function (value, key) { + if (value === "ADD") { + changedPreferences[key] = current[key]; + } + }); + } else if (diff.changeMap === "ADD") { + // Everything is new + changedPreferences = current; + } + + fluid.each(changedPreferences, function (value, name) { + that.logMetric("preference", { + name: name, + value: value + }); + }); + } +}; + /** * Removes the logged solution IDs for the session. * @param {Component} that - The gpii.metrics instance. diff --git a/gpii/node_modules/eventLog/test/all-tests.js b/gpii/node_modules/eventLog/test/all-tests.js new file mode 100644 index 000000000..53071131e --- /dev/null +++ b/gpii/node_modules/eventLog/test/all-tests.js @@ -0,0 +1,22 @@ +/* + * Event log and metrics tests. + * + * Copyright 2017 Raising the Floor - International + * + * Licensed under the New BSD license. You may not use this file except in + * compliance with this License. + * + * The R&D leading to these results received funding from the + * Department of Education - Grant H421A150005 (GPII-APCP). However, + * these results do not necessarily represent the policy of the + * Department of Education, and you should not assume endorsement by the + * Federal Government. + * + * You may obtain a copy of the License at + * https://github.com/GPII/universal/blob/master/LICENSE.txt + */ + +"use strict"; + +//require("./EventLogTests.js"); +require("./metricsTests.js"); diff --git a/gpii/node_modules/eventLog/test/metricsTests.js b/gpii/node_modules/eventLog/test/metricsTests.js new file mode 100644 index 000000000..74d85931b --- /dev/null +++ b/gpii/node_modules/eventLog/test/metricsTests.js @@ -0,0 +1,211 @@ +/* + * Metrics Tests + * + * Copyright 2017 Raising the Floor - International + * + * Licensed under the New BSD license. You may not use this file except in + * compliance with this License. + * + * The R&D leading to these results received funding from the + * Department of Education - Grant H421A150005 (GPII-APCP). However, + * these results do not necessarily represent the policy of the + * Department of Education, and you should not assume endorsement by the + * Federal Government. + * + * You may obtain a copy of the License at + * https://github.com/GPII/universal/blob/master/LICENSE.txt + */ + +"use strict"; + +var fluid = require("infusion"); + +var jqUnit = fluid.require("node-jqunit"); +var gpii = fluid.registerNamespace("gpii"); +fluid.registerNamespace("gpii.tests.metrics"); + +require("../index.js"); + +var teardowns = []; + +jqUnit.module("gpii.tests.metrics", { + teardown: function () { + while (teardowns.length) { + teardowns.pop()(); + } + } +}); + +// Tests ensure preferenceChanged logs added and changed preferences. +gpii.tests.metrics.preferenceChangedTestData = fluid.freezeRecursive({ + "unchanged 1/1": { + previous: { + pref1: "value1" + }, + current: { + pref1: "value1" + }, + expect: [] + }, + "unchanged 2/2": { + previous: { + pref1: "value1", + pref2: "value2" + }, + current: { + pref1: "value1", + pref2: "value2" + }, + expect: [] + }, + "changed 1/1": { + previous: { + pref1: "value1" + }, + current: { + pref1: "changed value1" + }, + expect: { + name: "pref1", + value: "changed value1" + } + }, + "changed 2/2": { + previous: { + pref1: "value1", + pref2: "value2" + }, + current: { + pref1: "changed value1", + pref2: "changed value2" + }, + expect: [{ + name: "pref1", + value: "changed value1" + }, { + name: "pref2", + value: "changed value2" + }] + }, + "changed 2/3": { + previous: { + pref1: "value1", + pref2: "value2", + pref3: "value3" + }, + current: { + pref1: "changed value1", + pref2: "changed value2", + pref3: "value3" + }, + expect: [{ + name: "pref1", + value: "changed value1" + }, { + name: "pref2", + value: "changed value2" + }] + }, + "add 1+1": { + previous: { + pref1: "value1" + }, + current: { + pref1: "value1", + pref2: "new value2" + }, + expect: [{ + name: "pref2", + value: "new value2" + }] + }, + "add+change": { + previous: { + pref1: "value1" + }, + current: { + pref1: "changed value1", + pref2: "new value2" + }, + expect: [{ + name: "pref1", + value: "changed value1" + }, { + name: "pref2", + value: "new value2" + }] + }, + "remove 1-1": { + previous: { + pref1: "value1" + }, + current: { + }, + expect: [] + }, + "remove 2-1": { + previous: { + pref1: "value1", + pref2: "value2" + }, + current: { + pref2: "value2" + }, + expect: [] + }, + "remove+change+static+add": { + previous: { + pref1: "value1", + pref2: "value2", + pref3: "value3" + }, + current: { + pref2: "changed value2", + pref3: "value3", + pref4: "new value4" + }, + expect: [{ + name: "pref2", + value: "changed value2" + }, { + name: "pref4", + value: "new value4" + }] + } +}); + +fluid.defaults("gpii.tests.metricsWrapper", { + gradeNames: ["fluid.component", "gpii.metrics", "gpii.eventLog", "gpii.lifecycleManager"], + listeners: { + "onStartMetrics.application": null, + "onStartMetrics.input": null, + "onStopMetrics.application": null, + "onStopMetrics.input": null + } +}); + + +jqUnit.test("preferenceChanged", function () { + + var tests = gpii.tests.metrics.preferenceChangedTestData; + + var logValues; + + var metrics = gpii.tests.metricsWrapper({ + invokers: { + "logMetric": function (metric, data) { + logValues.push(data); + } + } + }); + + fluid.each(tests, function (test) { + logValues = []; + + gpii.metrics.preferenceChanged(metrics, test.current, test.previous); + + jqUnit.assertDeepEq("preferenceChanged should have logged the expected value.", + fluid.makeArray(test.expect), logValues); + }); + +}); diff --git a/tests/all-tests.js b/tests/all-tests.js index 365302463..5d91dbda9 100644 --- a/tests/all-tests.js +++ b/tests/all-tests.js @@ -61,7 +61,7 @@ var testIncludes = [ "../gpii/node_modules/accessRequester/test/AccessRequesterTests.js", "../gpii/node_modules/canopyMatchMaker/test/CanopyMatchMakerTests.js", "../gpii/node_modules/contextManager/test/ContextManagerTests.js", - "../gpii/node_modules/eventLog/test/EventLogTests.js", + "../gpii/node_modules/eventLog/test/all-tests.js", "../gpii/node_modules/flatMatchMaker/test/FlatMatchMakerTests.js", "../gpii/node_modules/flowManager/test/SaveTests.js", "../gpii/node_modules/flowManager/test/BrowserChannelTests.js", From c3bbc8373020edbacf423bd5a34e6d86696a8a81 Mon Sep 17 00:00:00 2001 From: ste Date: Sun, 15 Jul 2018 21:20:46 +0100 Subject: [PATCH 3/6] GPII-3102: Logging time in local time (with UTC offset) --- gpii/node_modules/eventLog/src/eventLog.js | 8 +++++--- package.json | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/gpii/node_modules/eventLog/src/eventLog.js b/gpii/node_modules/eventLog/src/eventLog.js index 1b72e1ef1..219389441 100644 --- a/gpii/node_modules/eventLog/src/eventLog.js +++ b/gpii/node_modules/eventLog/src/eventLog.js @@ -22,7 +22,8 @@ var fluid = require("infusion"); var fs = require("fs"), - path = require("path"); + path = require("path"), + moment = require("moment"); var gpii = fluid.registerNamespace("gpii"), $ = fluid.registerNamespace("jQuery"); @@ -99,10 +100,11 @@ fluid.defaults("gpii.eventLog", { }); /* - * Returns the actual Date and time + * Returns the actual date and time, as a string, in ISO 8601 format with the localtime + offset from UTC. + * eg: '2018-07-13T13:03:03.863+01:00' */ gpii.eventLog.getTimestamp = function () { - return new Date(); + return moment().toISOString(true); }; /** diff --git a/package.json b/package.json index c3d0b82eb..2089e1092 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "json5": "1.0.1", "kettle": "1.7.3", "mkdirp": "0.5.1", + "moment": "2.22.2", "ndef": "0.2.0", "nock": "9.3.0", "node-jqunit": "1.1.8", From 414f01fd6b45f45218b5ee200fbf3b8f9147723e Mon Sep 17 00:00:00 2001 From: ste Date: Mon, 16 Jul 2018 14:32:24 +0100 Subject: [PATCH 4/6] GPII-3102: Reinstated event tests --- gpii/node_modules/eventLog/test/all-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpii/node_modules/eventLog/test/all-tests.js b/gpii/node_modules/eventLog/test/all-tests.js index 53071131e..8f276e0ce 100644 --- a/gpii/node_modules/eventLog/test/all-tests.js +++ b/gpii/node_modules/eventLog/test/all-tests.js @@ -18,5 +18,5 @@ "use strict"; -//require("./EventLogTests.js"); +require("./EventLogTests.js"); require("./metricsTests.js"); From c5a7bf6bfb49f95f97a2b07dd1f0c677e1d74cc8 Mon Sep 17 00:00:00 2001 From: ste Date: Wed, 18 Jul 2018 11:35:25 +0100 Subject: [PATCH 5/6] GPII-3102: Logging start/stop once. --- gpii/node_modules/eventLog/src/eventLog.js | 30 ++++++++++++++++------ gpii/node_modules/eventLog/src/metrics.js | 2 +- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/gpii/node_modules/eventLog/src/eventLog.js b/gpii/node_modules/eventLog/src/eventLog.js index 219389441..e10a252e4 100644 --- a/gpii/node_modules/eventLog/src/eventLog.js +++ b/gpii/node_modules/eventLog/src/eventLog.js @@ -44,7 +44,10 @@ fluid.defaults("gpii.eventLog", { } }, invokers: { - logEvent: "gpii.eventLog.log", + logEvent: { + funcName: "gpii.eventLog.log", // moduleName, event, data, level + args: ["{that}", "{arguments}.0", "{arguments}.1", "{arguments}.2", "{arguments}.3"] + }, logError: "gpii.eventLog.logError", getGpiiSettingsDir: "{settingsDir}.getGpiiSettingsDir", getLogFile: "gpii.eventLog.getLogFile" @@ -61,18 +64,17 @@ fluid.defaults("gpii.eventLog", { args: ["{that}"] }, "onCreate.log": { - func: "{that}.logEvent", - args: ["{that}", "gpii", "Start", {}] + func: "gpii.eventLog.logStartStop", + args: ["{that}", "start"] }, "onDestroy.log": { - func: "{that}.logEvent", - args: [ "{that}", "gpii", "Stop", {}] + func: "gpii.eventLog.logStartStop", + args: ["{that}", "stop"] }, "{lifecycleManager}.events.onSessionStart": { namespace: "eventLog", func: "{that}.logEvent", args: [ - "{that}", "lifecycle", "SessionStart", { @@ -86,7 +88,6 @@ fluid.defaults("gpii.eventLog", { namespace: "eventLog", func: "{that}.logEvent", args: [ - "{that}", "lifecycle", "SessionStop", { @@ -99,14 +100,27 @@ fluid.defaults("gpii.eventLog", { } }); -/* +/** * Returns the actual date and time, as a string, in ISO 8601 format with the localtime + offset from UTC. * eg: '2018-07-13T13:03:03.863+01:00' + * @return {String} The current date, in ISO-8601 format with localtime and UTC offset. */ gpii.eventLog.getTimestamp = function () { return moment().toISOString(true); }; +/** + * Logs the start or stop of GPII, without duplication. + * @param {Component} that - The gpii.eventLog instance. + * @param {String} state - "start" or "stop". + */ +gpii.eventLog.logStartStop = function (that, state) { + if (state !== gpii.eventLog.logStartStop.currentState) { + gpii.eventLog.logStartStop.currentState = state; + that.logEvent("gpii", state); + } +}; + /** * Creates an object for the log. Everything in this object is what will be logged, and the "time" field will be added * later when it is actually logged. diff --git a/gpii/node_modules/eventLog/src/metrics.js b/gpii/node_modules/eventLog/src/metrics.js index 29bc36b6b..32b2d4b66 100644 --- a/gpii/node_modules/eventLog/src/metrics.js +++ b/gpii/node_modules/eventLog/src/metrics.js @@ -38,7 +38,7 @@ fluid.defaults("gpii.metrics", { invokers: { logMetric: { func: "{eventLog}.logEvent", - args: ["{eventLog}", "metrics", "{arguments}.0", "{arguments}.1"] + args: ["metrics", "{arguments}.0", "{arguments}.1"] // event, data } }, members: { From 1fb4b2cc5368d5174d21ada7ba205a7ba6a21e5a Mon Sep 17 00:00:00 2001 From: ste Date: Wed, 25 Jul 2018 16:51:10 +0100 Subject: [PATCH 6/6] GPII-3102: Fixed letter case in test. --- gpii/node_modules/eventLog/test/EventLogTests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpii/node_modules/eventLog/test/EventLogTests.js b/gpii/node_modules/eventLog/test/EventLogTests.js index 07217af74..62e5daf27 100644 --- a/gpii/node_modules/eventLog/test/EventLogTests.js +++ b/gpii/node_modules/eventLog/test/EventLogTests.js @@ -81,7 +81,7 @@ gpii.tests.eventLog.testDefs = fluid.freezeRecursive(fluid.transform([ expected: { "level": "INFO", "module": "gpii", - "event": "Start" + "event": "start" } }, {