| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 | Ext.define('PageAnalyzer.Console', {    extend: 'Ext.panel.Panel',    requires: [        'Ext.chart.*',        'Ext.grid.Panel',        'Ext.grid.feature.Grouping',        'Ext.layout.container.Border',        'PageAnalyzer.models.BasicTimeData'    ],    layout: 'border',    border: false,    initComponent: function () {        var me = this;        me.addEvents('rawdataupdate');        me.pathTpl = new Ext.XTemplate('{test} ({env} - {build})');        me.samples = [];        me.store = Ext.create('Ext.data.Store', {            model: 'PageAnalyzer.models.BasicTimeData',            sorters: [{ property: 'avgTime', direction: 'DESC' }],            groupField: 'path'        });        me.detailStore = Ext.create('Ext.data.Store', {            model: 'PageAnalyzer.models.BasicTimeData',            sorters: { property: 'avgTime', direction: 'DESC' }        });        me.singleSampleStore = Ext.create('Ext.data.Store', {            model: 'PageAnalyzer.models.BasicTimeData'        });        me.items = [            {                region: 'north',                title: 'Trend',                itemId: 'trendPanel',                layout: 'fit',                split: true,                collapsible: true,                collapsed: false,                flex: 4,                items: []            },            {                region: 'center',                title: 'Data',                flex: 4,                layout: 'border',                border: false,                items: [                    {                        region: 'center',                        xtype: 'tabpanel',                        tabPosition: 'bottom',                        flex: 5,                        items: [                            me.makeDataGrid({                                title: 'Grid',                                border: false                            }),                            {                                region: 'east',                                title: 'Raw',                                layout: 'fit',                                border: false,                                tbar: [                                    {                                        text: 'Load',                                        handler: me.onUpdateFromRawData,                                        scope: me                                    }                                ],                                items: [                                    {                                        xtype: 'textarea',                                        style: 'margin:0',                                        itemId: 'rawData',                                        emptyText: 'Raw data goes here...',                                        selectOnFocus: true                                    }                                ]                            },                            {                                title: 'Accumulators',                                xtype: 'textarea',                                style: 'margin:0',                                itemId: 'accumulatorCfg'                            }                        ]                    },                    me.makeDetailsChart({ region: 'east' })                ]            }        ];        me.callParent();    },    addSample: function (perfData) {        var me = this,            last = perfData;        if (Ext.isArray(perfData)) {            me.samples.push.apply(me.samples, perfData);            last = last[last.length-1];        } else {            // perfData = { env: '..', test: '..', build: '..', data: Ext.Perf.getData() }            me.samples.push(perfData);        }        me.update();        var rec = me.store.findRecord('path', me.makePath(last));        me.select(rec);    },    clearSamples: function() {        var me = this;        me.samples.length = 0;        me.update();    },    makeDataGrid: function (config) {        var me = this;        return Ext.apply({            xtype: 'grid',            store: me.store,            itemId: 'dataGrid',            flex: 5,            features: [                {                    ftype:'grouping',                    hideGroupedHeader: true                }            ],            columns: [                { text: 'Environment', dataIndex: 'environment', hidden: true },                { text: 'Build', dataIndex: 'build', hidden: true },                { text: 'Test', dataIndex: 'test', hidden: true },                { text: 'Path', dataIndex: 'path', sortable: true },                { text: 'Name', dataIndex: 'measure', sortable: true },                { text: 'Time', dataIndex: 'avgTime', sortable: true },                { text: 'Time/Call', dataIndex: 'avgTimePerCall', sortable: true },                { text: 'Samples', dataIndex: 'numSamples', sortable: true },                { text: 'Min Calls', dataIndex: 'minCalls', sortable: true },                { text: 'Max Calls', dataIndex: 'maxCalls', sortable: true }            ],            listeners: {                selectionchange: function (model, selection) {                    me.onSelect(selection[0]);                }            }        }, config);    },    makePath: function (perfData) {        return this.pathTpl.apply(perfData);    },    makeDetailsChart: function (config) {        var me = this;        return Ext.apply({            xtype: 'panel',            title: 'Details',            layout: 'fit',            flex: 3,            split: true,            collapsible: true,            preventHeader: true,            items: [{                xtype: 'chart',                store: me.detailStore,                itemId: 'measuresPieChart',                theme: 'Base:gradients',                series: [{                    type: 'pie',                    field: 'avgTime',                    label: {                        field: 'measure',                        display: 'rotate',                        font: '12px Arial'                    }                }]            }]        }, config);    },    makeTrendChart: function () {        var me = this,            panel = me.down('#trendPanel'),            builds = {},            trendData = [],            fields = [],            measures = {},            measureNames = [],            modelName,            chart;        panel.removeAll();        chart = {            xtype: 'chart',            style: 'background:#fff',            animate: false,            shadow: true,            flex: 5,            theme: 'Category1',            legend: {                position: 'right'            },            axes: [{                type: 'Numeric',                minimum: 0,                position: 'left',                fields: [],                title: 'Time (ms)',                minorTickSteps: 1,                grid: {                    odd: {                        opacity: 1,                        fill: '#ddd',                        stroke: '#bbb',                        'stroke-width': 0.5                    }                }            }, {                type: 'Category',                position: 'bottom',                fields: ['build'],                title: 'Build'            }],            series: []        };        me.store.each(function (r) {            var rd = r.data;            var build = builds[rd.build];            if (!build) {                builds[rd.build] = build = { build: rd.build };                trendData.push(build);            }            build[rd.measure] = rd.avgTime;            if (rd.measure in measures) {                return;            }            fields.push(measures[rd.measure] = { name: rd.measure, type: 'float' });            measureNames.push(rd.measure);            chart.series.push({                type: 'line',                highlight: {                    size: 7,                    radius: 7                },                axis: 'left',                xField: 'build',                yField: rd.measure,                markerConfig: {                    type: 'circle',                    size: 4,                    radius: 4,                    'stroke-width': 0                }            });        });        chart.axes[0].fields = measureNames;        measureNames.sort();        var name = 'Trend_' + measureNames.join('$');        name = name.replace(/\./g, '_');        modelName = 'PageAnalyzer.models.' + name;        var mfields = [{            name: 'build',            type: 'int'        }];        fields.push({name: 'build', type: 'int'});        if (!PageAnalyzer.models[name]) {            Ext.define(modelName, {                extend: 'Ext.data.Model',                fields: fields            });        }        chart.store = Ext.create('Ext.data.Store', {            model: modelName,            sorters: { property: 'build', direction: 'ASC' }        });        if (trendData.length == 1) {            trendData.unshift({                build: '0',                avgTime: null            });        }        chart.store.loadData(trendData);        chart.store.sort();        panel.add(chart);    },    onSelect: function (rec) {        var me = this,            records = [],            store = me.detailStore;        if (rec) {            me.store.each(function (r) {                if (r.data.path == rec.data.path) {                    records.push(r.copy());                }            });        }        store.removeAll();        if (records.length) {            store.add(records);            store.sort();        }    },    onUpdateFromRawData: function () {        var me = this,            rawData = me.down('#rawData').getValue();        me.samples = Ext.decode(rawData);        me.update();    },    select: function (rec) {        if (rec) {            var me = this,                grid = me.down('#dataGrid');            grid.getSelectionModel().select(rec);        }    },    update: function () {        var me = this,            map = {}, // map[env+test+build][measure] = record            json = Ext.encode(me.samples),            key,            measures,            measure,            records = [];        me.down('#rawData').setValue(json);        me.fireEvent('rawdataupdate', me, json, me.samples);        Ext.each(me.samples, function (perfData) {            key = me.makePath(perfData);            measures = map[key] || (map[key] = {});            Ext.Object.each(perfData.data, function (name, stats) {                measure = measures[name];                if (!measure) {                    measures[name] = measure = new PageAnalyzer.models.BasicTimeData({                                environment: perfData.env,                                build: perfData.build,                                test: perfData.test,                                path: key,                                measure: name                            });                }                records.push(measure);                measure.addSample(stats.pure.sum, stats.count);            });        });        me.store.removeAll();        me.store.add(records);        me.store.sort();        me.makeTrendChart();    },    setAccumulators: function (cfg) {        var me = this,            accData = Ext.JSON.encodeValue(cfg, '\n  ');        me.down('#accumulatorCfg').setValue(accData);    },    getAccumulators: function () {        var me = this,            accData = me.down('#accumulatorCfg').getValue();        if(!accData || accData == '')            return null;        return Ext.decode(accData, true);    }});
 |