Skip to content

Commit 896e10f

Browse files
Merge pull request #1011 from magento-frontend/MAGETWO-59587
Story - MAGETWO-59587 Debugging and profiling tools for UI Components and Javascript modules
2 parents e517984 + 4dbe28e commit 896e10f

File tree

19 files changed

+1505
-34
lines changed

19 files changed

+1505
-34
lines changed

app/code/Magento/Ui/view/base/web/js/core/renderer/layout.js

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ define([
88
'jquery',
99
'mageUtils',
1010
'uiRegistry',
11-
'./types'
12-
], function (_, $, utils, registry, types) {
11+
'./types',
12+
'../../lib/logger/console-logger'
13+
], function (_, $, utils, registry, types, consoleLogger) {
1314
'use strict';
1415

1516
var templates = registry.create(),
@@ -70,7 +71,25 @@ define([
7071
* @returns {jQueryPromise}
7172
*/
7273
function loadDeps(node) {
73-
var loaded = $.Deferred();
74+
var loaded = $.Deferred(),
75+
loggerUtils = consoleLogger.utils;
76+
77+
if (node.deps) {
78+
consoleLogger.utils.asyncLog(
79+
loaded,
80+
{
81+
data: {
82+
component: node.name,
83+
deps: node.deps
84+
},
85+
messages: loggerUtils.createMessages(
86+
'depsStartRequesting',
87+
'depsFinishRequesting',
88+
'depsLoadingFail'
89+
)
90+
}
91+
);
92+
}
7493

7594
registry.get(node.deps, function (deps) {
7695
node.provider = node.extendProvider ? deps && deps.name : node.provider;
@@ -90,8 +109,19 @@ define([
90109
var loaded = $.Deferred(),
91110
source = node.component;
92111

112+
consoleLogger.info('componentStartLoading', {
113+
component: node.component
114+
});
115+
93116
require([source], function (constr) {
117+
consoleLogger.info('componentFinishLoading', {
118+
component: node.component
119+
});
94120
loaded.resolve(node, constr);
121+
}, function (err) {
122+
consoleLogger.error('componentLoadingFail', {
123+
component: node.component
124+
});
95125
});
96126

97127
return loaded.promise();
@@ -106,6 +136,11 @@ define([
106136
function initComponent(node, Constr) {
107137
var component = new Constr(_.omit(node, 'children'));
108138

139+
consoleLogger.info('componentStartInitialization', {
140+
component: node.component,
141+
componentName: node.name
142+
});
143+
109144
registry.set(node.name, component);
110145
}
111146

app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/scope.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,22 @@ define([
77
'ko',
88
'uiRegistry',
99
'mage/translate',
10-
'../template/renderer'
11-
], function (ko, registry, $t, renderer) {
10+
'../template/renderer',
11+
'jquery',
12+
'../../logger/console-logger'
13+
], function (ko, registry, $t, renderer, $, consoleLogger) {
1214
'use strict';
1315

1416
/**
1517
* Creates child context with passed component param as $data. Extends context with $t helper.
1618
* Applies bindings to descendant nodes.
1719
* @param {HTMLElement} el - element to apply bindings to.
1820
* @param {ko.bindingContext} bindingContext - instance of ko.bindingContext, passed to binding initially.
21+
* @param {Promise} promise - instance of jQuery promise
1922
* @param {Object} component - component instance to attach to new context
2023
*/
21-
function applyComponents(el, bindingContext, component) {
24+
function applyComponents(el, bindingContext, promise, component) {
25+
promise.resolve();
2226
component = bindingContext.createChildContext(component);
2327

2428
ko.utils.extend(component, {
@@ -53,9 +57,25 @@ define([
5357
*/
5458
update: function (el, valueAccessor, allBindings, viewModel, bindingContext) {
5559
var component = valueAccessor(),
56-
apply = applyComponents.bind(this, el, bindingContext);
60+
promise = $.Deferred(),
61+
apply = applyComponents.bind(this, el, bindingContext, promise),
62+
loggerUtils = consoleLogger.utils;
5763

5864
if (typeof component === 'string') {
65+
loggerUtils.asyncLog(
66+
promise,
67+
{
68+
data: {
69+
component: component
70+
},
71+
messages: loggerUtils.createMessages(
72+
'requestingComponent',
73+
'requestingComponentIsLoaded',
74+
'requestingComponentIsFailed'
75+
)
76+
}
77+
);
78+
5979
registry.get(component, apply);
6080
} else if (typeof component === 'function') {
6181
component(apply);

app/code/Magento/Ui/view/base/web/js/lib/knockout/template/engine.js

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ define([
66
'ko',
77
'underscore',
88
'./observable_source',
9-
'./renderer'
10-
], function (ko, _, Source, renderer) {
9+
'./renderer',
10+
'../../logger/console-logger'
11+
], function (ko, _, Source, renderer, consoleLogger) {
1112
'use strict';
1213

1314
var RemoteTemplateEngine,
@@ -36,9 +37,12 @@ define([
3637
* Caches template after it's unique name and renders in once.
3738
* If template name is not typeof string, delegates work to knockout.templateSources.anonymousTemplate.
3839
* @param {*} template
40+
* @param {HTMLElement} templateDocument - document
41+
* @param {Object} options - options, passed to template binding
42+
* @param {ko.bindingContext} bindingContext
3943
* @returns {TemplateSource} Object with methods 'nodes' and 'data'.
4044
*/
41-
RemoteTemplateEngine.prototype.makeTemplateSource = function (template) {
45+
RemoteTemplateEngine.prototype.makeTemplateSource = function (template, templateDocument, options, bindingContext) {
4246
var source,
4347
templateId;
4448

@@ -48,10 +52,32 @@ define([
4852

4953
if (!source) {
5054
source = new Source(template);
55+
source.requestedBy = bindingContext.$data.name;
5156
sources[templateId] = source;
5257

58+
consoleLogger.info('templateStartLoading', {
59+
template: templateId,
60+
component: bindingContext.$data.name
61+
});
62+
5363
renderer.render(template).done(function (rendered) {
64+
consoleLogger.info('templateLoadedFromServer', {
65+
template: templateId,
66+
component: bindingContext.$data.name
67+
});
5468
source.nodes(rendered);
69+
}).fail(function (err) {
70+
consoleLogger.error('templateLoadingFail', {
71+
template: templateId,
72+
component: bindingContext.$data.name
73+
});
74+
});
75+
}
76+
77+
if (source.requestedBy !== bindingContext.$data.name) {
78+
consoleLogger.info('templateLoadedFromCache', {
79+
template: templateId,
80+
component: bindingContext.$data.name
5581
});
5682
}
5783

@@ -87,7 +113,7 @@ define([
87113
* @return {Array} - array of html elements
88114
*/
89115
RemoteTemplateEngine.prototype.renderTemplate = function (template, bindingContext, options, templateDocument) {
90-
var templateSource = this.makeTemplateSource(template, templateDocument, options);
116+
var templateSource = this.makeTemplateSource(template, templateDocument, options, bindingContext);
91117

92118
return this.renderTemplateSource(templateSource, bindingContext, options);
93119
};

app/code/Magento/Ui/view/base/web/js/lib/knockout/template/loader.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,9 @@ define([
9292

9393
require([path], function (template) {
9494
template = removeLicense(template);
95-
9695
loading.resolve(template);
96+
}, function (err) {
97+
loading.reject(err);
9798
});
9899

99100
return loading.promise();
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
define([
2+
'./logger',
3+
'./entry-factory',
4+
'./console-output-handler',
5+
'./formatter',
6+
'./message-pool',
7+
'./levels-pool',
8+
'Magento_Ui/js/lib/core/storage/local',
9+
'underscore',
10+
'./logger-utils'
11+
], function (Logger, entryFactory, ConsoleHandler, Formatter, messagePoll, levelsPoll, storage, _, LoggerUtils) {
12+
'use strict';
13+
14+
var STORAGE_NAMESPACE = 'CONSOLE_LOGGER';
15+
16+
/**
17+
* Singleton Logger's sub-class instance of which is configured to display its
18+
* messages to the console. It also provides the support of predefined messages
19+
* and persists its display level.
20+
*/
21+
function ConsoleLogger() {
22+
var formatter = new Formatter(),
23+
consoleHandler = new ConsoleHandler(formatter),
24+
savedLevel = storage.get(STORAGE_NAMESPACE),
25+
utils = new LoggerUtils(this);
26+
27+
Logger.call(this, consoleHandler, entryFactory);
28+
29+
if (savedLevel) {
30+
this.displayLevel_ = savedLevel;
31+
}
32+
33+
this.utils = utils;
34+
this.messages = messagePoll;
35+
this.levels = levelsPoll.getLevels();
36+
}
37+
38+
_.extend(ConsoleLogger, Logger);
39+
40+
ConsoleLogger.prototype = Object.create(Logger.prototype);
41+
ConsoleLogger.prototype.constructor = ConsoleLogger;
42+
43+
/**
44+
* Overrides parent method to save the provided display level.
45+
*
46+
* @override
47+
*/
48+
ConsoleLogger.prototype.setDisplayLevel = function (level) {
49+
Logger.prototype.setDisplayLevel.call(this, level);
50+
51+
storage.set(STORAGE_NAMESPACE, level);
52+
};
53+
54+
/**
55+
* Adds the support of predefined messages.
56+
*
57+
* @protected
58+
* @override
59+
*/
60+
ConsoleLogger.prototype.createEntry_ = function (message, level, data) {
61+
var code;
62+
63+
if (messagePoll.hasMessage(message)) {
64+
data = data || {};
65+
code = message;
66+
message = messagePoll.getMessage(code);
67+
68+
data.messageCode = code;
69+
}
70+
71+
return Logger.prototype.createEntry_.call(this, message, level, data);
72+
};
73+
74+
return new ConsoleLogger();
75+
});
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
define([
6+
'./levels-pool'
7+
], function (logLevels) {
8+
'use strict';
9+
10+
var levels = logLevels.getLevels();
11+
12+
/**
13+
* @param {LogFormatter} formatter
14+
*/
15+
function ConsoleOutputHandler(formatter) {
16+
/**
17+
* @protected
18+
* @type {LogFormatter}
19+
*/
20+
this.formatter_ = formatter;
21+
}
22+
23+
/**
24+
* Display data of the provided entry to the console.
25+
*
26+
* @param {LogEntry} entry - Entry to be displayed.
27+
*/
28+
ConsoleOutputHandler.prototype.show = function (entry) {
29+
var displayString = this.formatter_.process(entry);
30+
31+
switch (entry.level) {
32+
case levels.ERROR:
33+
console.error(displayString);
34+
break;
35+
36+
case levels.WARN:
37+
console.warn(displayString);
38+
break;
39+
40+
case levels.INFO:
41+
console.info(displayString);
42+
break;
43+
44+
case levels.DEBUG:
45+
console.log(displayString);
46+
break;
47+
}
48+
};
49+
50+
/**
51+
* Displays the array of entries.
52+
*
53+
* @param {Array<LogEntry>} entries
54+
*/
55+
ConsoleOutputHandler.prototype.dump = function (entries) {
56+
entries.forEach(this.show, this);
57+
};
58+
59+
return ConsoleOutputHandler;
60+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
define([
6+
'./entry'
7+
], function (LogEntry) {
8+
'use strict';
9+
10+
return {
11+
/**
12+
* @param {String} message
13+
* @param {Number} level
14+
* @param {Object} [messageData]
15+
* @returns {LogEntry}
16+
*/
17+
createEntry: function (message, level, messageData) {
18+
return new LogEntry(message, level, messageData);
19+
}
20+
};
21+
});

0 commit comments

Comments
 (0)