/*
* Copyright 2015 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This tool does display the message running on the message bus.
* @private
*/
Ext.define("Ametys.plugins.coreui.system.messagetracker.MessageTrackerTool",
{
extend: "Ametys.plugins.coreui.log.AbstractLogTool",
statics: {
/**
* This action find the unique instance of the message tracker tool, and removes all the entries
*/
removeAll: function()
{
var tool = Ametys.tool.ToolsManager.getTool("uitool-messagestracker");
if (tool != null)
{
tool.store.removeAll();
}
else
{
this.getLogger().error("Cannot remove entries from unexisting tool 'uitool-messsagestracker'");
}
}
},
/**
* @property {Ext.data.ArrayStore} store The store with the messages received
* @private
*/
constructor: function(config)
{
this.callParent(arguments);
this._messageTpl = new Ext.Template(
"<b>{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_ID}}</b> : {id}, - ",
"<b>{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_CREATIONDATE}}</b> : {creationDate}, - ",
"<b>{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_FIREDATE}}</b> : {fireDate}<br/>",
"<br/>",
"<b>{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_TYPE}}</b> : {type}<br/>",
"{parameters}",
"<br/>",
"<b>{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_TARGET}}</b> :<br/>",
"{targets}<br/>",
"<br/>",
"<div class=\"json-array json-closed\">",
"<span class=\"json-char\" onclick=\"Ametys.tool.ToolsManager.getTool('" + this.getId() + "').openTrace(this)\"></span> ",
"<b>{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_CALLSTACK}}</b><br/>",
"</div>"
);
Ametys.message.MessageBus.on('*', this.onMessage, this);
},
getStore: function()
{
this.store = Ext.create("Ext.data.ArrayStore",{
autoDestroy: true,
autoSync: true,
proxy: { type: 'memory' },
sorters: [{property: 'fireDate', direction:'DESC'}],
model: "Ametys.plugins.coreui.system.messagetracker.MessageTrackerTool.MessageEntry"
});
return this.store;
},
getColumns: function()
{
return [
{
stateId: 'grid-id',
header: "{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_ID}}",
width: 50,
sortable: true,
dataIndex: 'id',
hideable: false,
filter: {
type: 'number'
}
},
{
stateId: 'grid-creationdate',
header: "{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_CREATIONDATE}}",
width: 145,
sortable: true,
renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.ShortDateTime),
dataIndex: 'creationDate'
},
{
stateId: 'grid-firedate',
header: "{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_FIREDATE}}",
width: 145,
sortable: true,
renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.ShortDateTime),
dataIndex: 'fireDate'
},
{
stateId: 'grid-type',
header: "{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_TYPE}}",
width: 150,
sortable: true,
dataIndex: 'type',
filter: {
type: 'list'
}
},
{
stateId: 'grid-target',
header: "{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_TARGET}}",
flex: 1,
sortable: true,
dataIndex: 'target',
renderer: Ext.bind(this._targetRenderer, this)
}
];
},
getDetailsText: function(records)
{
var record = records[0];
var id = record.getId();
var type = record.get("type");
var parameters = Ext.JSON.prettyEncode(record.get("parameters"));
var targets = record.get("target");
var callstack = record.get("callstack");
return this._messageTpl.applyTemplate({
id: id,
creationDate: Ext.Date.format(record.get("creationDate"), Ext.Date.patterns.ShortDateTime),
fireDate: Ext.Date.format(record.get("fireDate"), Ext.Date.patterns.ShortDateTime),
type: type,
parameters: parameters ? parameters + "<br/>" : "",
targets: this._targetsToString(targets, false)
});
},
getType: function()
{
return Ametys.tool.Tool.TYPE_DEVELOPER;
},
/**
* The listener on all bus messages
* @param {Ametys.message.Message} message The message received
* @private
*/
onMessage: function(message)
{
var store = this.store;
try
{
var record = Ext.create("Ametys.plugins.coreui.system.messagetracker.MessageTrackerTool.MessageEntry", {
id: message.getNumber(),
creationDate: message.getCreationDate(),
fireDate: new Date(),
type: message.getType(),
parameters: message.getParameters(),
target: message.getTargets(),
callstack: message.getCallStack()
});
store.addSorted(record);
}
catch (e)
{
this.getLogger().error({
message: "Cannot create the message entry",
details: e
});
}
},
/**
* Load and display the stacktrace of the currently selected message
* @param {Object} span The dom element that triggered the open trace
*/
openTrace: function (span)
{
var parent = Ext.get(span.parentNode);
if (!parent.hasCls('json-closed'))
{
return;
}
parent.removeCls('json-closed');
parent.removeCls('json-array');
var records = this.grid.getSelectionModel().getSelection();
if (records.length > 0)
{
parent.child('b').setHtml("{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_CALLSTACK_LOADING}}");
var record = records[0];
var callstack = record.get("callstack");
var div = document.createElement('div');
Ext.get(div).setHtml(Ext.String.stacktraceToHTML(callstack, 4));
parent.appendChild(div);
Ametys.plugins.coreui.system.devmode.StacktraceHelper.unminifyStacktrace(callstack, Ext.bind(this._openTraceCb, this, [callstack, parent], true));
}
},
/**
* Callback after unminifying the stacktrace
* @param {String} response The unminified callstack, or null
* @param {String} originalCallstack The callstack before processing
* @param {Ext.dom.Element} domElement The element that displays the stacktrace
*/
_openTraceCb: function (response, originalCallstack, domElement)
{
domElement.child('b').setHtml("{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_COL_CALLSTACK}}");
if (response)
{
domElement.child('div').setHtml(Ext.String.stacktraceToHTML(response, 4));
}
},
/**
* @private
* Render the target in the grid
* @param {Ametys.message.MessageTarget[]} targets The targets to render
*/
_targetRenderer: function(targets)
{
return this._targetsToString(targets, true);
},
/**
* Converts '@link Ametys.message.MessageTarget} to a readable string
* @param {Ametys.message.MessageTarget[]} targets The message parameters to convert
* @param {Boolean} [shortVersion=false] When true return only the names (and not the parameters)
* @param {Number} [offset = 0] The offset to indent the text
* @private
*/
_targetsToString: function (targets, shortVersion, offset)
{
offset = offset || 0;
var s = "";
for (var i = 0; i < targets.length; i++)
{
var target = targets[i];
if (offset != 0 || i != 0)
{
s += "<br/>";
}
for (var j = 0; j < offset; j++)
{
s += "    ";
}
s += "<span style='font-weight: bold'>" + target.getId() + "</span>";
if (shortVersion !== true)
{
s += "<br/>" + Ext.JSON.prettyEncode(target.getParameters(), offset, null, 0);
}
s += this._targetsToString(target.getSubtargets(), shortVersion, offset + 1);
}
if (targets.length == 0 && offset == 0)
{
s = "<span style='color: #7f7f7f; font-style: italic;'>{{i18n PLUGINS_CORE_UI_TOOLS_MESSAGES_TRACKER_TOOL_NOTARGET}}</span>";
}
return s;
}
}
);