| // Copyright 2015 The Chromium OS Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| /** | |
| * @fileoverview Class to handle file actions and trigger log processing. After | |
| * logs are processed, summary information is displayed in the document. | |
| */ | |
| 'use strict'; | |
| document.addEventListener('DOMContentLoaded', function() { | |
| var docNode = document.getElementById('file_name'); | |
| if (docNode) { | |
| docNode.addEventListener('change', parseFile); | |
| } else { | |
| console.log('Cannot add event listener, must be testing.'); | |
| } | |
| }); | |
| /** | |
| * Method to get the file name and trigger the file read. | |
| * | |
| * @private | |
| */ | |
| function parseFile() { | |
| var logFile = document.getElementById('file_name').files; | |
| if (logFile[0]) { | |
| console.log('got the file!: ' + logFile[0].name); | |
| readFile(logFile[0]); | |
| } else { | |
| console.log('file selection cancelled.'); | |
| } | |
| } | |
| /** | |
| * Method to open the selected file and break into a String[] for processing. | |
| * | |
| * @param {String} logFile Name of the file to open. | |
| * @private | |
| */ | |
| function readFile(logFile) { | |
| var logSummary = new LogSummary(); | |
| // clean up old log output | |
| cleanupForNewFile(); | |
| var fileReader = new FileReader(); | |
| fileReader.onloadend = function(processEvent) { | |
| if (processEvent.target.readyState == FileReader.DONE) { | |
| var logLines = this.result.split('\n'); | |
| var logText = logSummary.processLogLines(logLines); | |
| if (logText) { | |
| displayLogSummary(logSummary); | |
| displayServiceSummary(logSummary); | |
| displayLog(logText); | |
| } else { | |
| displayError(); | |
| } | |
| logLines = null; | |
| logText = null; | |
| } | |
| }; | |
| fileReader.readAsText(logFile); | |
| } | |
| /** | |
| * Method to clean up state between selected files. | |
| * | |
| * @private | |
| */ | |
| function cleanupForNewFile() { | |
| var oldManager = document.getElementsByClassName('managers'); | |
| while (oldManager[0].hasChildNodes()) { | |
| oldManager[0].removeChild(oldManager[0].lastChild); | |
| } | |
| } | |
| /** | |
| * Method to display log-level summary information after processing the log. | |
| * | |
| * @param {LogSummary} logSummary Object to hold state read from log. | |
| * @private | |
| */ | |
| function displayLogSummary(logSummary) { | |
| console.log('inside log summary!'); | |
| var manager = document.getElementsByClassName('managers'); | |
| var logHeader = document.createElement('h2'); | |
| logHeader.innerText = 'Log Summary'; | |
| manager[0].appendChild(logHeader); | |
| var timeInfo = document.createElement('p'); | |
| timeInfo.innerText = 'Total Log Time: ' + | |
| logHelper.formatElapsedMS( | |
| logSummary.logEndTime - logSummary.logStartTime); | |
| manager[0].appendChild(timeInfo); | |
| var activeServiceLabel = 'Active Service '; | |
| var managers = logSummary.managers; | |
| for (var i = 0; i < managers.length; i++) { | |
| var mInfo = document.createElement('p'); | |
| mInfo.innerText = 'Manager ' + managers[i].id + | |
| ' ' + | |
| logHelper.formatElapsedMS( | |
| managers[i].endTime - managers[i].startTime); | |
| var activeService = ''; | |
| var failures; | |
| for (var j = 0; j < managers[i].services.length; j++) { | |
| failures = ''; | |
| if (managers[i].services[j].isActive) { | |
| for (var z = 0; z < managers[i].services[j].states.length; z++) { | |
| if (z > 0) { | |
| activeService += '--> '; | |
| } | |
| activeService += managers[i].services[j].states[z].state + ' '; | |
| if (managers[i].services[j].states[z].state == 'Failure') { | |
| var temp = managers[i].services[j].states[z]; | |
| failures += ' [' + temp.failure + ']'; | |
| } | |
| } | |
| var stateInfo = document.createElement('p'); | |
| stateInfo.innerText = activeServiceLabel + | |
| managers[i].services[j].serviceId + ': ' + activeService; | |
| var connCountInfo = document.createElement('p'); | |
| connCountInfo.innerText = 'Connections: ' + | |
| managers[i].services[j].connections; | |
| stateInfo.appendChild(connCountInfo); | |
| activeService = ''; | |
| if (failures != '') { | |
| var failureInfo = document.createElement('p'); | |
| failureInfo.innerText = 'Failures: ' + failures; | |
| stateInfo.appendChild(failureInfo); | |
| } | |
| console.log('graphData check: ', managers[i].services[j].graphData); | |
| var xTime; | |
| var graphData = managers[i].services[j].graphData; | |
| for (var z = 0; z < graphData.length; z++) { | |
| if (graphData[z].x != 0) { | |
| xTime = Date.parse(graphData[z].x) - managers[i].startTime; | |
| } else { | |
| xTime = 0; | |
| } | |
| graphData[z].x = xTime; | |
| if (z + 1 == graphData.length) { | |
| graphData.push({'x': managers[i].endTime - managers[i].startTime, | |
| 'y': graphData[z].y}); | |
| z = z + 2; | |
| } | |
| } | |
| mInfo.appendChild(stateInfo); | |
| } | |
| } | |
| console.log('scanDetail check: ', managers[i].scanDetails); | |
| console.log('suspendDetail check: ', managers[i].suspendDetails); | |
| var suspendCount = managers[i].suspendDetails.length; | |
| if (suspendCount > 0) { | |
| // double check first and last suspend entries | |
| var suspendEntry = managers[i].suspendDetails[0]; | |
| if (suspendEntry.start == null) { | |
| suspendEntry.start = 0; | |
| } | |
| suspendEntry = managers[i].suspendDetails[suspendCount - 1]; | |
| if (suspendEntry.end == null) { | |
| suspendEntry.end = managers[i].endTime - managers[i].startTime; | |
| } | |
| } | |
| for (var x = 0; x < managers[i].suspendDetails.length; x++) { | |
| var checkDarkSuspends = managers[i].suspendDetails[x].darkSuspends; | |
| if (checkDarkSuspends) { | |
| console.log('darkSuspendCheck: ', checkDarkSuspends); | |
| for (var y = 0; y < checkDarkSuspends.length; y++) { | |
| if (checkDarkSuspends[y].start == null) { | |
| checkDarkSuspends[y].start = managers[i].suspendDetails[x].start; | |
| } | |
| if (checkDarkSuspends[y].end == null) { | |
| checkDarkSuspends[y].end = managers[i].suspendDetails[x].end; | |
| } | |
| } | |
| console.log('fixed darkSuspendCheck: ', checkDarkSuspends); | |
| } | |
| } | |
| stateGraph.createGraph(manager[0], managers[i]); | |
| manager[0].appendChild(mInfo); | |
| } | |
| } | |
| /** | |
| * Method to display an error message for a file that could not be processed. | |
| * | |
| * @private | |
| */ | |
| function displayError() { | |
| var manager = document.getElementsByClassName('managers'); | |
| var errorHeader = document.createElement('h2'); | |
| errorHeader.innerText = 'File format not recognized.'; | |
| manager[0].appendChild(errorHeader); | |
| } | |
| /** | |
| * Method to display individual service summaries with active states after | |
| * processing a netlog. | |
| * | |
| * @param {LogSummary} logSummary Object holding state from processing the log. | |
| * @private | |
| */ | |
| function displayServiceSummary(logSummary) { | |
| var managers = logSummary.managers; | |
| var manager = document.getElementsByClassName('managers'); | |
| var managerHeader = document.createElement('h2'); | |
| managerHeader.innerText = 'Managers'; | |
| var managerOL = document.createElement('ol'); | |
| manager[0].appendChild(managerHeader); | |
| var li; | |
| for (var i = 0; i < managers.length; i++) { | |
| li = document.createElement('li'); | |
| li.id = 'manager_' + managers[i].id; | |
| li.innerText = 'Manager ' + managers[i].id + | |
| ' logged time: ' + | |
| logHelper.formatElapsedMS( | |
| managers[i].endTime - managers[i].startTime) + | |
| 'ms' + | |
| ' total scans: ' + managers[i].scans + | |
| ' seen services: ' + managers[i].services.length; | |
| li.className = 'manager'; | |
| if (managers[i].notes && managers[i].notes.length > 0) { | |
| li.appendChild(displayNotes(logSummary, managers[i].notes)); | |
| } | |
| li.appendChild(displayServices(logSummary, managers[i].services)); | |
| managerOL.appendChild(li); | |
| } | |
| manager[0].appendChild(managerOL); | |
| } | |
| /** | |
| * Method to display the services observed in the netlog. | |
| * | |
| * @param {LogSummary} logSummary Object holding state from processing the log. | |
| * @param {Service[]} serviceList List of services to display. | |
| * @return {node} Document node element containing the service list. | |
| * @private | |
| */ | |
| function displayServices(logSummary, serviceList) { | |
| var serviceOL = document.createElement('ol'); | |
| for (var j = 0; j < serviceList.length; j++) { | |
| var sId = serviceList[j].serviceId; | |
| var serviceLI = document.createElement('li'); | |
| serviceLI.innerText = 'Service ' + sId; | |
| serviceLI.id = 'service_' + sId; | |
| serviceLI.className = 'service'; | |
| if (serviceList[j].notes && serviceList[j].notes.length > 0) { | |
| serviceLI.appendChild(displayNotes(logSummary, serviceList[j].notes)); | |
| } | |
| serviceLI.appendChild(displayServiceStates(logSummary, | |
| serviceList[j].states)); | |
| serviceOL.appendChild(serviceLI); | |
| } | |
| return serviceOL; | |
| } | |
| /** | |
| * Method to display individual service states and failure reasons (if any). | |
| * | |
| * @param {LogSummary} logSummary Object holding state from processing the log. | |
| * @param {Update[]} stateList Observed updates for a service. | |
| * @return {node} Document node element containing the list of service states. | |
| * @private | |
| */ | |
| function displayServiceStates(logSummary, stateList) { | |
| var stateOL = document.createElement('ol'); | |
| for (var z = 0; z < stateList.length; z++) { | |
| var stateLI = document.createElement('li'); | |
| var anchor = document.createElement('a'); | |
| var text = document.createElement('span'); | |
| anchor.href = '#' + stateList[z].time; | |
| anchor.innerText = '[' + stateList[z].time + ']'; | |
| text.innerText = ' [' + | |
| logHelper.formatElapsedMS( | |
| Date.parse(stateList[z].time) - logSummary.logStartTime) + '] ' + | |
| stateList[z].state; | |
| if (stateList[z].failure) { | |
| text.innerText += ' [' + stateList[z].failure + ']'; | |
| } | |
| stateLI.appendChild(anchor); | |
| stateLI.appendChild(text); | |
| if (stateList[z].notes && stateList[z].notes.length > 0) { | |
| stateLI.appendChild(displayNotes(logSummary, stateList[z].notes)); | |
| } | |
| stateOL.appendChild(stateLI); | |
| } | |
| return stateOL; | |
| } | |
| /** | |
| * Method to display individual notes for a service or manager. | |
| * | |
| * @param {LogSummary} logSummary Object holding state from processing the log. | |
| * @param {Update[]} noteList Observed notes. | |
| * @return {node} Document node containing the notes for a service or manager. | |
| * @private | |
| */ | |
| function displayNotes(logSummary, noteList) { | |
| if (noteList == null) { | |
| return; | |
| } | |
| var noteOL = document.createElement('ol'); | |
| noteOL.className = 'notes'; | |
| for (var n = 0; n < noteList.length; n++) { | |
| var noteLI = document.createElement('li'); | |
| var anchor = document.createElement('a'); | |
| var text = document.createElement('span'); | |
| anchor.href = '#' + noteList[n].time; | |
| anchor.innerText = '[' + noteList[n].time + ']'; | |
| text.innerText = ' [' + | |
| logHelper.formatElapsedMS( | |
| Date.parse(noteList[n].time) - logSummary.logStartTime) + '] ' + | |
| noteList[n].message; | |
| noteLI.appendChild(anchor); | |
| noteLI.appendChild(text); | |
| noteOL.appendChild(noteLI); | |
| } | |
| return noteOL; | |
| } | |
| /** | |
| * Method to display the log lines after the summary by appending a preformatted | |
| * (<pre>) element to the document. | |
| * | |
| * @param {String[]} logText Log lines to display. | |
| * @private | |
| */ | |
| function displayLog(logText) { | |
| if (!logText) { | |
| return; | |
| } | |
| var logTextHeader = document.createElement('h2'); | |
| logTextHeader.innerText = 'NetLog'; | |
| var logTextHolder; | |
| var logTextHolder2; | |
| var anchor; | |
| var mark; | |
| for (var i = 0; i < logText.length; i++) { | |
| mark = null; | |
| logTextHolder = document.createElement('pre'); | |
| logTextHolder2 = document.createElement('span'); | |
| logTextHolder2.class = 'inner-pre'; | |
| logTextHolder2.textContent += logText[i].text; | |
| if (logText[i].tag) { | |
| mark = document.createElement('mark'); | |
| mark.className = logText[i].type; | |
| anchor = document.createElement('a'); | |
| anchor.name = logText[i].tag; | |
| logTextHolder.appendChild(anchor); | |
| } | |
| if (mark) { | |
| mark.appendChild(logTextHolder2); | |
| logTextHolder.appendChild(mark); | |
| } else { | |
| logTextHolder.appendChild(logTextHolder2); | |
| } | |
| logTextHeader.appendChild(logTextHolder); | |
| } | |
| var manager = document.getElementsByClassName('managers'); | |
| manager[0].appendChild(logTextHeader); | |
| } | |