strong-arc
Version:
A visual suite for the StrongLoop API Platform
927 lines (837 loc) • 28.9 kB
JavaScript
Tracing.controller('TracingMainController', [
'$scope',
'$log',
'$timeout',
'$interval',
'$location',
'growl',
'MSFormat',
'TracingServices',
'ManagerServices',
'PMHostService',
'TraceEnhance',
'$state',
function($scope, $log, $timeout, $interval, $location, growl, msFormat, TracingServices, ManagerServices, PMHostService, TraceEnhance, $state) {
var loadTracingProcessesAttemptCount = 0;
$scope.pm = {};
$scope.killProcessPoll = true;
$scope.pidCycleCheckCollection = [];
$scope.tracingProcessCycleActive = false;
$scope.showTraceToggle = true;
$scope.targetProcessCount = 0;
$scope.tracingOnOffCycleMessage = 'starting';
$scope.systemFeedback = []; // FEEDBACK
$scope.managerHosts = []; // $location.host()
$scope.selectedPMHost = {};
$scope.processes = [];
$scope.selectedProcess = {};
$scope.tracingCtx = {};
$scope.showTimelineLoading = true;
$scope.showTransactionHistoryLoading = true;
$scope.isShowTraceSequenceLoader = false;
$scope.transactionHistoryRenderToggle = false;
// timeseries nav buttons
$scope.isFirstPFKey = false; // no key is pre selected during init
$scope.isLastPFKey = false; // assume there is more than 1 record
$scope.tracingOnOff = [
{ id: 'off', label: 'Off', activeId: 'isTracingOn' },
{ id: 'on', label: 'On', activeId: 'isTracingOn' }
];
$scope.sysTime = {ticker:20};
var updateInterval;
$scope.tracingUpdateInterval = 20;
$scope.startTicker = function() {
$scope.sysTime.ticker = 20;
$scope.startTimer();
};
$scope.restartTicker = function() {
$scope.sysTime.ticker = 20;
$scope.startTimer();
};
$scope.startTimer = function() {
// cancel the previous interval if it wasn't cleaned up
$scope.stopTimer();
updateInterval = $interval(function() {
// make sure we have a valid process to work with
if ($scope.tracingCtx.currentProcess.pid) {
$scope.sysTime.ticker--;
if ($scope.sysTime.ticker < 1) {
$scope.sysTime.ticker = $scope.tracingUpdateInterval;
$scope.refreshTimelineProcess();
}
}
else {
$scope.stopTimer();
}
}, 1000);
$scope.isTimerRunning = true;
};
$scope.stopTimer = function() {
if (updateInterval !== null) {
$interval.cancel(updateInterval);
updateInterval = null;
$scope.isTimerRunning = false;
}
};
/*
*
* INIT
*
* */
$scope.init = function() {
$scope.resetTracingCtx();
// check if user has a valid metrics license
TracingServices.validateLicense()
.then(function(isValid) {
if (!isValid) {
$log.warn('invalid tracing license');
$scope.showTimelineLoading = false;
$scope.showTransactionHistoryLoading = false;
$scope.isShowTraceSequenceLoader = false;
return;
}
$scope.managerHosts = ManagerServices.getManagerHosts(function(hosts) {
$scope.$apply(function() {
$scope.managerHosts = hosts;
if ($scope.managerHosts && $scope.managerHosts.length > 0) {
if (!$scope.selectedPMHost.host) {
$scope.selectedPMHost = $scope.managerHosts[0];
}
$scope.main();
}
else {
TracingServices.alertNoHosts();
$scope.selectedPMHost = {
error: 'no PM Hosts available',
errorType: 'NOHOSTS',
status: {
isProblem: true,
problem: {
title:'No PM Hosts available',
description:'You need to add a PM Host via the Process Manager view'
}
}
};
$scope.showTimelineLoading = false;
}
});
});
})
.catch(function(error) {
$log.warn('exception validating tracing license (controller)');
return;
});
};
function processTracingProcesses(argProcesses) {
if (!argProcesses || argProcesses.length === 0) {
$log.warn('no processes');
return [];
}
}
/*
used to track any lazy tracing processes
during stop then start tracing
* */
var totalUnlicensedPids = [];
var totalIterations = 0;
// to trigger growl messages as count changes
var prevTracingPidCount = 0;
var restarting = false;
/*
* polls itself until
* - either all setSize pids come up with tracing enabled
* - or 35 (magic nubmer) iterations pass with
* -- pm instance.tracingEnabled = true
* -- but no processes with isTracing = true;
* */
$scope.loadTracingProcesses = function(pmInstance) {
totalIterations++;
pmInstance.processes(function(err, rawProcesses) {
if (err) {
$log.warn('bad get processes: ' + err.message);
return [];
}
if (!rawProcesses || rawProcesses.length === 0) {
$log.warn('no processes');
return [];
}
// remove supervisor process
var processes = rawProcesses.filter(function(proc) {
return (proc.workerId !== 0);
});
/*
* we have processes but they need to be filtered
* */
var filteredProcesses = [];
// interim test to check if processes come up without tracing on
// would indicate license hasn't been pushed or pm is not returning
// tracing enabled pids
// keep track of all 'active' (no stopTime) pids with isTracing=false
var nonTracingActivePids = [];
processes.map(function(process) {
if (!process.stopTime && !process.isTracing) {
nonTracingActivePids.push(process);
totalUnlicensedPids.push(process);
}
});
// filter out dead and non-tracig pids
filteredProcesses = processes.filter(function(process){
return (!process.stopTime && process.isTracing);
});
// tracing pids are starting to come up
if (filteredProcesses.length > 0) {
/*
show correct state in case old pids are still
being shut down by pm
pm will shut down old pids before spooling up the
tracing pids
*/
$scope.tracingOnOffCycleMessage = 'starting';
restarting = false;
loop1:
for (var i = 0;i < filteredProcesses.length;i++) {
var fproc = filteredProcesses[i];
loop2:
for (var k = 0;k < $scope.pidCycleCheckCollection.length;k++) {
var staleWorkderId = $scope.pidCycleCheckCollection[k];
// still some stale pids to shut down
if (staleWorkderId === fproc.workerId) {
$scope.tracingOnOffCycleMessage = 'restarting';
growl.addWarnMessage('shutting down existing processes');
restarting = true;
break loop1;
}
}
}
}
/*
* safety valve in case a tracing enabled pm never returns
* pids with tracing turned on
* - may be licensing
* */
$scope.killProcessPoll = false;
if ((totalIterations > 40) && (filteredProcesses.length === 0)) {
$scope.killProcessPoll = true;
$scope.tracingProcessCycleActive = false;
$scope.showTransactionHistoryLoading = false;
$scope.isShowTraceSequenceLoader = false;
$scope.showTimelineLoading = false;
$scope.transactionHistoryRenderToggle = false;
$scope.pidCycleCheckCollection = [];
$scope.processes = [];
TracingServices.alertUnlicensedPMHost();
}
/*
*
* Note to self - account for 0 processes with a setSize greater than 0
* - when app is stopped eg.
*
* */
PMHostService.getFirstPMInstance($scope.selectedPMHost, function(err, instance) {
if (err) {
$log.warn('bad pm reload', err);
return;
}
$scope.targetProcessCount = instance.setSize;
if ($scope.targetProcessCount > 0) {
$scope.startTicker();
// processes are still coming up
var fpLen = filteredProcesses.length;
if (fpLen !== $scope.targetProcessCount) {
if (!restarting) {
if (prevTracingPidCount !== fpLen) {
// show progress via growl each time the process count changes
growl.addSuccessMessage('starting process: ' + (fpLen + 1));
prevTracingPidCount = fpLen;
loadTracingProcessesAttemptCount = 0;
}
}
if (fpLen === 1 && ($scope.processes.length === 0)) {
$scope.tracingCtx.currentProcess = filteredProcesses[0]; //default
$scope.selectedProcess = filteredProcesses[0];
$scope.tracingCtx.currentProcesses = filteredProcesses;
$scope.startTicker();
$scope.refreshTimelineProcess();
}
$scope.processes = filteredProcesses;
$timeout(function () {
if (!$scope.killProcessPoll) {
$scope.loadTracingProcesses(instance);
loadTracingProcessesAttemptCount++;
if (loadTracingProcessesAttemptCount > 40) {
$scope.killProcessPoll = true;
$scope.tracingProcessCycleActive = false;
$scope.showTransactionHistoryLoading = false;
$scope.isShowTraceSequenceLoader = false;
$scope.showTimelineLoading = false;
$scope.transactionHistoryRenderToggle = false;
$scope.pidCycleCheckCollection = [];
TracingServices.alertProcessLoadProblem();
loadTracingProcessesAttemptCount = 0;
}
}
}, 1000);
}
// all processes are up and tracing
else {
var firstProcess = filteredProcesses[0];
loadTracingProcessesAttemptCount = 0;
firstProcess.isActive = true;
$scope.tracingCtx.currentProcess = firstProcess; //default
$scope.selectedProcess = firstProcess;
$scope.processes = filteredProcesses;
$scope.tracingCtx.currentProcesses = filteredProcesses;
$scope.tracingProcessCycleActive = false;
$scope.killProcessPoll = true;
$scope.pidCycleCheckCollection = [];
growl.addSuccessMessage('All processes are up and tracing');
$scope.refreshTimelineProcess();
}
}
// pm process setSize = 0
else {
$scope.processes = [];
$scope.tracingCtx.currentProcesses = [];
$scope.killProcessPoll = true;
$scope.tracingProcessCycleActive = false;
$scope.showTransactionHistoryLoading = false;
$scope.isShowTraceSequenceLoader = false;
$scope.showTimelineLoading = false;
$scope.transactionHistoryRenderToggle = false;
$scope.pidCycleCheckCollection = [];
}
});
});
};
$scope.setTracingOnOffToggle = function(value) {
if (value == 'on') {
$scope.isTracingOn = 'on';
$scope.tracingOnOff[0].isActive = false;
$scope.tracingOnOff[1].isActive = true;
}
else if (value === 'off') {
$scope.isTracingOn = 'off';
$scope.tracingOnOff[0].isActive = true;
$scope.tracingOnOff[1].isActive = false;
}
};
/*
*
* MAIN
*
* */
$scope.main = function() {
if (!$scope.selectedPMHost.host) {
// set notification banner?
$log.warn('tracing main: no host selected');
return;
}
var appContext = {
name: '',
version: ''
};
if ($scope.selectedPMHost.app && $scope.selectedPMHost.app.name) {
appContext.name = $scope.selectedPMHost.app.name;
appContext.version = $scope.selectedPMHost.app.version;
}
$scope.selectedPMHost = ManagerServices.processHostStatus($scope.selectedPMHost, appContext);
if ($scope.selectedPMHost.error) {
$scope.showTimelineLoading = false;
TracingServices.alertNoProcesses();
return;
}
// make sure selected host is working
PMHostService.getFirstPMInstance($scope.selectedPMHost, function(err, instance) {
if (err) {
$log.warn('error getting first pm instance: ' + err.message);
$scope.$apply(function() {
$scope.resetTracingCtx();
TracingServices.alertNoProcesses();
});
$scope.showTraceToggle = false;
$scope.showTimelineLoading = false;
return;
}
if ($scope.selectedPMHost.status.isProblem) {
$scope.setTracingOnOffToggle('off');
$scope.showTraceToggle = false;
$scope.showTimelineLoading = false;
$scope.resetTracingCtx();
return;
}
$scope.showTraceToggle = true;
$scope.tracingCtx.currentPMInstance = instance;
$scope.tracingCtx.currentPMHost = $scope.selectedPMHost;
$scope.tracingCtx.currentBreadcrumbs[0] = {
instance: $scope.tracingCtx.currentPMInstance,
label: $scope.tracingCtx.currentPMInstance.applicationName
};
$scope.$apply(function() {
$scope.processes = [];
});
if ($scope.tracingCtx.currentPMInstance.tracingEnabled) {
$scope.$apply(function() {
$scope.setTracingOnOffToggle('on');
totalUnlicensedPids = [];
totalIterations = 0;
$scope.loadTracingProcesses($scope.tracingCtx.currentPMInstance);
});
}
else {
$scope.$apply(function() {
$scope.setTracingOnOffToggle('off');
$scope.showTimelineLoading = false;
});
}
});
};
/*
* reset main context variables
* */
$scope.resetTracingCtx = function() {
$scope.tracingCtx = {
currentPFKey: '',
selectedManagerHost: {},
currentPMHost: {},
currentPMInstance: {},
currentTraceToggleBool: false,
currentTimelineTimestamp: '',
currentTimelineDuration: 0,
currentTimelineKeyCollection: [],
mappedTransactions: [],
currentTrace: {},
currentTraceSequenceId: '',
currentManagerHost: {},
currentBreadcrumbs: [],
currentWaterfallKey: '',
currentWaterfalls: [], // when navigating trace sequence waterfalls
currentWaterfall: {},
currentFunction: {},
currentProcesses: [],
currentProcess: {},
currentPids: [],
currentTimeline: [],
currentTransactionKeys: [],
currentTransactionHistoryCollection: [],
currentApp: {name: ''}
};
$scope.processes = [];
};
/*
*
*
*
* UPDATE TIMELINE DATA
*
*
* */
function updateTimelineData(timeline) {
var self = this;
self.timeline = timeline;
$scope.tracingCtx.currentTimelineKeyCollection = [];
self.timeline.map(function(trace) {
var t = trace;
$scope.tracingCtx.currentTimelineKeyCollection.push(trace.__data.pfkey);
});
$scope.$apply(function() {
$scope.tracingCtx.currentTimeline = self.timeline;
$scope.tracingCtx.currentTimelineDuration = msFormat($scope.getCurrentTimelineDuration());
});
}
/*
*
* REFRESH TIMELINE PROCESS
*
* */
$scope.refreshTimelineProcess = function() {
$scope.tracingCtx.currentProcess.getTimeline(function(err, rawResponse) {
$scope.showTimelineLoading = false;
if (err) {
$log.warn('bad get timeline: ', err);
return;
}
if (!rawResponse) {
$log.warn('get timeline undefined');
$scope.resetTracingCtx();
TracingServices.alertNoProcesses();
return;
}
$scope.tracingCtx.currentPFKey = '';
$scope.tracingCtx.timelineStart = 0;
/*
*
* process the response
*
* */
var convertedTimeSeries = TracingServices.convertTimeseries(rawResponse);
updateTimelineData(convertedTimeSeries);
});
};
/*
HELPERS
*
* GET TIMESTAMP FOR KEY
*
* */
$scope.getTimestampForPFKey = function(pfKey) {
if ($scope.tracingCtx && $scope.tracingCtx.currentTimeline.length) {
for (var i = 0;i < $scope.tracingCtx.currentTimeline.length;i++) {
var instance = $scope.tracingCtx.currentTimeline[i];
if (instance.__data && (instance.__data.pfkey === pfKey)) {
return instance._t;
}
}
return 0;
}
return 0;
};
/*
*
* GET TIMELINE DURATION
*
* */
$scope.getCurrentTimelineDuration = function() {
if (!$scope.tracingCtx.currentTimeline) {
return 0;
}
var dataPointCount = $scope.tracingCtx.currentTimeline.length;
if (dataPointCount > 0) {
return $scope.tracingCtx.currentTimeline[dataPointCount - 1].__data['p_ut'];
}
return 0;
};
/*
DATA MODEL CHANGERS
*
* CHANGE PM HOST
*
*
* */
// from the host selector in tracing header
$scope.changePMHost = function(host) {
if (host.host && host.port) {
$scope.resetTracingCtx();
$scope.selectedPMHost = host;
$scope.tracingCtx.currentManagerHost = $scope.selectedPMHost;
// establish current process count
$scope.targetProcessCount = 0;
if ($scope.tracingCtx.currentManagerHost.processes && $scope.tracingCtx.currentManagerHost.processes.pids) {
var netProcesses = $scope.tracingCtx.currentManagerHost.processes.pids.filter(function(process){
return (!process.stopTime && (process.workerId !== 0));
});
$scope.targetProcessCount = netProcesses.length;
}
$scope.main();
}
};
$scope.updateHost = function(host) {
$scope.changePMHost(host);
};
$scope.$watch('selectedPMHost', function(newVal, oldVal) {
if (newVal && newVal !== oldVal) {
$scope.changePMHost(newVal);
}
});
$scope.updateProcessSelection = function(selection) {
if (selection.length) {
selection[0].isActive = true;
$scope.activeProcess = selection[0];
$scope.setActiveProcess($scope.activeProcess);
}
};
$scope.goToAddPM = function() {
$state.go('process-manager');
};
/*
*
* SET ACTIVE PID
*
* */
$scope.setActiveProcess = function(process) {
$scope.showTimelineLoading = true;
$scope.tracingCtx.currentTimeline = [];
$scope.tracingCtx.currentTransactionKeys = [];
$scope.tracingCtx.currentTransactionHistoryCollection = [];
$scope.tracingCtx.currentWaterfallKey = '';
$scope.tracingCtx.currentTrace = {};
$scope.tracingCtx.currentTraceSequenceId = '';
$scope.tracingCtx.currentProcess = process;
if ($scope.tracingCtx.currentProcess) {
$scope.refreshTimelineProcess();
}
};
/*
*
* Tracing On/Off
*
* */
$scope.turnTracingOn = function() {
$scope.tracingCtx.currentPMInstance.processes = [];
$scope.processes = [];
$scope.tracingCtx.currentTimeline = [];
$scope.tracingProcessCycleActive = true;
$scope.tracingOnOffCycleMessage = 'starting';
$scope.tracingCtx.currentPMInstance.tracingStart(function(err, response) {
if (err) {
$log.warn('bad start tracing: ' + err);
return;
}
$scope.main();
});
};
$scope.turnTracingOff = function() {
if ($scope.tracingCtx.currentPMInstance.tracingEnabled) {
$scope.pidCycleCheckCollection = [];
$scope.processes.map(function(process) {
$scope.pidCycleCheckCollection.push(process.workerId);
});
$scope.tracingCtx.currentPMInstance.processes = [];
$scope.processes = [];
$scope.tracingCtx.currentTimeline = [];
$scope.tracingProcessCycleActive = true;
$scope.tracingOnOffCycleMessage = 'stopping';
$scope.tracingCtx.currentPMInstance.tracingStop(function(err, response) {
if (err) {
$log.warn('bad stop tracing: ' + err);
return;
}
// give it time to stop the processes
$timeout(function() {
$scope.main();
$scope.tracingProcessCycleActive = false;
}, 20);
});
$scope.resetTracingCtx();
}
};
/*
*
* SET PF KEY
*
* */
$scope.setCurrentPFKey = function(key) {
$scope.tracingCtx.currentTrace = {};
$scope.tracingCtx.currentPFKey = key;
$scope.tracingCtx.currentWaterfallKey = '';
$scope.tracingCtx.currentTraceSequenceId = '';
};
function getPFKeyIndex(key) {
return $scope.tracingCtx.currentTimelineKeyCollection.indexOf(key) || 0;
}
function setPrevNextDisabled(key) {
var currIndex = getPFKeyIndex(key);
var isLastRecord = false;
var isFirstRecord = false;
var isMoreThanOne = false;
if ($scope.tracingCtx.currentTimelineKeyCollection.length > 1) {
isMoreThanOne = true;
}
if (currIndex === 0) {
isFirstRecord = true;
}
// last record
if (currIndex === ($scope.tracingCtx.currentTimelineKeyCollection.length - 1)) {
isLastRecord = true;
}
$timeout(function() {
$scope.isFirstPFKey = isFirstRecord;
$scope.isLastPFKey = isLastRecord;
});
}
/*
* PREV KEY
* */
$scope.prevPFKey = function() {
if ($scope.tracingCtx.currentTimelineKeyCollection) {
var currIndex = getPFKeyIndex($scope.tracingCtx.currentPFKey);
if (currIndex !== 0) {
// we are good to change
currIndex--;
setPrevNextDisabled($scope.tracingCtx.currentPFKey);
$scope.tracingCtx.currentPFKey = $scope.tracingCtx.currentTimelineKeyCollection[currIndex];
$scope.tracingCtx.currentWaterfallKey = '';
}
}
};
/*
* NEXT KEY
* */
$scope.nextPFKey = function() {
if ($scope.tracingCtx.currentTimelineKeyCollection) {
var currIndex = getPFKeyIndex($scope.tracingCtx.currentPFKey);
if (currIndex < ($scope.tracingCtx.currentTimelineKeyCollection.length - 1)) {
// we are good to change
currIndex++;
setPrevNextDisabled($scope.tracingCtx.currentPFKey);
$scope.tracingCtx.currentPFKey = $scope.tracingCtx.currentTimelineKeyCollection[currIndex];
$scope.tracingCtx.currentWaterfallKey = '';
}
}
};
/*
*
* TRANSACTION HISTORY
*
* */
$scope.updateTransactionHistory = function() {
$scope.tracingCtx.currentTransactionHistoryCollection = [];
$scope.tracingCtx.currentProcess.getMetaTransactions(function(err, response) {
$scope.showTransactionHistoryLoading = false;
if (err) {
$log.warn('bad get meta transactions: ' + err.message);
return;
}
$scope.tracingCtx.currentTransactionKeys = response;
/*
the current context list of transactions
we need to iterate over them and create a deeper object than the simple one used by transaction-list component
trasObj = {
key: transaction,
history: {object based on api call}
};
*/
// isolate the transactions for this pid
// iterate over the transaction keys
var keyLen = $scope.tracingCtx.currentTransactionKeys.length;
$scope.tracingCtx.currentTransactionKeys.map(function(transaction) {
/*
*
* Transaction History
*
* - TODO expensive so should only do it on demand
*
* */
$scope.tracingCtx.currentProcess.getTransaction(encodeURIComponent(transaction),
function (err, history) {
if (err) {
$log.warn('bad get history: ' + err.message);
}
transObj = {
history: history,
key: transaction
};
$scope.tracingCtx.currentTransactionHistoryCollection.push(transObj);
if ($scope.tracingCtx.currentTransactionHistoryCollection.length === keyLen) {
$scope.$apply(function() {
$scope.transactionHistoryRenderToggle = !$scope.transactionHistoryRenderToggle;
});
}
});
});
});
};
/*
*
* NAV
*
* BACK TO TIMELINE
*
*
* */
$scope.backToTimeline = function() {
$scope.tracingCtx.currentPFKey = '';
$scope.tracingCtx.currentTrace = {};
$scope.tracingCtx.currentWaterfallKey = '';
$scope.tracingCtx.currentTraceSequenceId = '';
$scope.startTicker();
};
/*
*
* BACK TO TRACE
*
* */
$scope.backToTrace = function() {
$scope.tracingCtx.currentWaterfallKey = '';
$scope.tracingCtx.currentTraceSequenceId = '';
$scope.tracingCtx.currentTraceSequenceId = '';
$scope.stopTimer();
};
/*
*
* CLOSE TRACE VIEW
* need a better way to do this
* */
$scope.closeTraceView = function() {
$scope.tracingCtx.currentTrace = {};
$scope.tracingCtx.currentPFKey = '';
$scope.tracingCtx.currentWaterfallKey = '';
$scope.tracingCtx.currentTraceSequenceId = '';
$scope.stopTimer();
};
/*
* TIMESTAMP FORMAT
* */
$scope.tsText = function(ts){
return moment(ts).fromNow() +' (' + moment(ts).format('ddd, MMM Do YYYY, h:mm:ss a') + ')'
};
// Watches $watch
/*
*
* PF KEY WATCH
*
* if we get a key then load the trace file
* set currentTrace
* toggle currentTraceToggleBool
* - watch target for directives
* - instead of comparing the trace data object
*
* */
$scope.$watch('tracingCtx.currentPFKey', function(newKey, oldVal) {
if (newKey) {
setPrevNextDisabled(newKey);
$scope.isShowTraceSequenceLoader = true;
$scope.tracingCtx.currentTrace = {};
$scope.tracingCtx.currentTraceSequenceId = '';
$timeout(function() {
$scope.tracingCtx.currentProcess.getTrace(newKey, function(err, trace) {
if (err) {
$log.warn('bad get trace: ' + err.message);
return {};
}
$timeout(function() {
var obj = JSON.parse(trace);
var TE = TraceEnhance(obj);
$scope.tracingCtx.currentTrace = TE;
$scope.stopTimer();
// too expensive to compare the trace
$scope.$apply(function () {
$scope.tracingCtx.currentTraceToggleBool = !$scope.tracingCtx.currentTraceToggleBool;
});
}, 20);
});
}, 100);
}
else {
$scope.startTicker();
}
}, true);
$scope.$watch('processes', function(newProcesses, oldProcesses) {
$scope.updateProcesses(newProcesses);
});
$scope.updateProcesses = function(newProcesses) {
$scope.processes = newProcesses;
};
$scope.$watch('tracingOnOff', function(newVal, oldVal) {
if ($scope.tracingCtx.currentPMInstance.tracingStop) {
// on switch activated
if (newVal[1].isActive) {
if (!$scope.tracingCtx.currentPMInstance.tracingEnabled) {
$scope.turnTracingOn();
}
}
else {
$scope.turnTracingOff();
}
}
}, true);
window.onresize = function() {
window.setScrollView('.tracing-content-container');
};
/*
*
* INIT
*
* */
$scope.init();
}
]);