🏠 Home 

ICM Alert Helper

Adds some helpful copy/paste commands to use for alerts in ICM


Install this script?
// ==UserScript==
// @name         ICM Alert Helper
// @namespace    https://portal.microsofticm.com/
// @require http://code.jquery.com/jquery-latest.js
// @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.21.0/moment.min.js
// @version      1.0.0
// @description  Adds some helpful copy/paste commands to use for alerts in ICM
// @author       Naveen Kumar
// @match        https://portal.microsofticm.com/*
// @grant        none
// ==/UserScript==
(function() {
'use strict';
console.log("Loading OSP OnCall Helper User Script...");
// JQuery start
$(document).ready(function()
{
// Because this is a SPA, we have to check the HTML body every so often, we can't just listen to document.ready.
setInterval(ParsePage, 5000);
});
console.log("Loaded.");
})();
var loadedHelper = false;
var ParsePage = function(){
console.log("Checking...");
// if we already added a helper, then don't recheck
if( $('#helperTable').length)
{
// if it's currently visible, then leave it be.
if($('#helperTable').is(':visible'))
{
return;
}
else
{
// if it's not, then delete and try again
$('#helperText').remove()
}
}
if(loadedHelper)
{
return loadedHelper;
}
console.log("Parsing helper stuff...");
var elementsWithData = [];
// Find the element with data to parse
$('td').filter(function(i) {
var html = $(this).html();
if(_.includes(html, 'X-CalculatedBETarget') & _.includes(html, 'Date:'))
{
elementsWithData.push(html);
return true;
}
return false;
});
var divWithData = [];
// Find the element with data to parse
$('table tr').filter(function(i) {
var html = $(this).html();
if(_.includes(html, '<th>Scope</th>'))
{
console.log("FOUND SCOPE",$(this));
divWithData.push($(this).find('td:not(:empty):first').html());
return true;
}
return false;
});
var protocol = '';
var xCalculatedBETarget;
var beServerWithoutDomain;
var requestDate;
var xFEServer;
var dag;
// parse the data we need
if(!_.isEmpty(elementsWithData)) {
console.log("Found eligible alert for helper text.");
xCalculatedBETarget = ParseElementForData(elementsWithData[0], 'X-CalculatedBETarget', ':', '\n');
requestDate = ParseElementForData(elementsWithData[0], 'Date', ':', '\n');
xFEServer = ParseElementForData(elementsWithData[0], 'X-FEServer', ':', '\n');
protocol = TryDecideWhichProtocol(elementsWithData[0]);
if(!_.isEmpty(divWithData)) {
dag = _.trim(divWithData[0]);
}
console.log("xCalculatedBETarget: " + xCalculatedBETarget);
console.log("requestDate: " + requestDate);
console.log("protocol: " + protocol);
console.log('dag: ' + dag);
// generate and insert the helper HTML
console.log("Generating helper HTML...");
var helperHTML = GenerateHelperHTML(xCalculatedBETarget, xFEServer, dag, requestDate, protocol);
$(helperHTML).insertBefore('main-panel .widget-pannel').one();
$("#helperTable td").css({"padding":"5px"});
console.log("Added helper HTML.");
loadedHelper = true;
}
};
function ParseElementForData(element, headerText, beginning, end) {
var index = element.indexOf(headerText);
element = element.substring(index, element.length);
var indexOfBeginning = element.indexOf(beginning);
var indexOfNext = element.indexOf(end);
element = element.substring(indexOfBeginning+beginning.length, indexOfNext);
return _.trim(element);
}
function GenerateHelperHTML(xCalculatedBETarget, xFEServer, dag, requestDate, protocol) {
var beLogName = '';
var feLogName = '';
var beProcess = '';
switch (protocol) {
case Protocol.EWS:
beLogName = 'EWSLogsHourly';
feLogName = 'CafeEwsLogsHourly';
beProcess = 'MSExchangeServicesAppPool';
break;
case Protocol.REST:
beLogName = 'RestLogsNRTHourly';
feLogName = 'CafeRestLogsHourly2';
beProcess = 'MSExchangeRestAppPool';
break;
case Protocol.AUTODISCOVER:
beLogName = 'AutoDiscoverLogsHourly';
feLogName = 'CafeAutodiscoverLogs2';
beProcess = 'MSExchangeAutodiscoverAppPool';
break;
default:
beLogName = "<Insert Log Name>";
feLogName = '<Insert Log Name>';
beProcess = '<Insert Process Name>';
}
var beServer;
var forest;
if(xCalculatedBETarget.length > 0) {
var firstPeriodIndex = xCalculatedBETarget.indexOf('.');
if(firstPeriodIndex >= 0) {
beServer = xCalculatedBETarget.substring(0, firstPeriodIndex);
forest = xCalculatedBETarget.substring(firstPeriodIndex+1, xCalculatedBETarget.length);
}
}
var filterDateCurrentHour = moment(requestDate).utc().format('YYYYMMDDHH');
var filterDateOneHourAgo = moment(requestDate).utc().subtract({'hours': 1}).format('YYYYMMDDHH');
var filterDateForMeasurePerformance = moment(requestDate).utc().format('YYYY-MM-DDTHH:mm:ss');
var filterDateForEventLogStart = moment(requestDate).utc().subtract({'minutes': 20}).format('MM/DD/YYYY HH:mm:ss');
var filterDateForEventLogEnd = moment(requestDate).utc().add({'minutes': 20}).format('MM/DD/YYYY HH:mm:ss');
// General
var measurePerformance = 'Measure-Performance -Machine ' + beServer;
var measurePerformanceWithStartTime = 'Measure-Performance -Machine ' + beServer + ' -StartTimeUtc ' + filterDateForMeasurePerformance;
var measurePerformanceDag = 'Measure-Performance -Dag ' + dag;
// BE
var getBEMachineLogCurrentHour = 'Get-MachineLog -Target ' + beServer + ' -Log ' + beLogName + ' -Filter *' + filterDateCurrentHour + '* -TorusStreaming -Download';
var getBEMachineLogOneHourAgo = 'Get-MachineLog -Target ' + beServer + ' -Log ' + beLogName + ' -Filter *' + filterDateOneHourAgo + '* -TorusStreaming -Download';
var getThreadStackGrouping = 'Get-ThreadStackGrouping -Server ' + beServer + ' -Process ' + beProcess;
var getResponderThreadStacks = 'Get-MachineLog -Target ' + beServer + ' -Log EDSLogsDumps -Filter Responder_threadstacks* -Download';
var getEventLogsApplication = "Get-MachineEvent -Target " + beServer + " -EventLog Application -EventLevel NotInformation -FromDateUtc '" + filterDateForEventLogStart + "' -ToDateUtc '" + filterDateForEventLogEnd + "' | fl > eventsApplication_" + beServer + ".txt";
var getEventLogsWatson = "Get-MachineEvent -Target " + beServer + " -EventId 4999 -R###ltSize 50 -FromDateUtc '" + filterDateForEventLogStart + "' -ToDateUtc '" + filterDateForEventLogEnd + "' | fl > eventsWatson_" + beServer + ".txt";
// FE
var getFEMachineLogCurrentHour = 'Get-MachineLog -Target ' + xFEServer + ' -Log ' + feLogName + ' -Filter *' + filterDateCurrentHour + '* -TorusStreaming -Download';
var getFEMachineLogOneHourAgo = 'Get-MachineLog -Target ' + xFEServer + ' -Log ' + feLogName + ' -Filter *' + filterDateOneHourAgo + '* -TorusStreaming -Download';
// Actions
var elevatedRights = "Request-ElevatedAccess_V2.ps1 -Role CapacityServerAdmin -Reason 'Alert investigation for " + beServer + "' -DurationHours 24 -Forest " + forest;
var maintenanceMode = 'Request-MachineBeginMaintenance_V2.ps1 -TargetMachine ' + beServer + " -Reason 'Fixing machine for Alert'";
var recycleAppPool = 'Request-RecycleAppPool_V2.ps1 -Target ' + beServer + ' -AppPoolName ' + beProcess + " -Reason 'Recycling AppPool to recover availability'";
var SafeRebootMachine = 'Request-MachineSafeReboot_v2.ps1 -TargetMachine ' + beServer + " -Reason 'Fixing machine for Alert'";
var ForceRebootMachine = 'Request-SetMachinePowerStateV2.ps1 -TargetMachine ' + beServer + " -DesiredState restart -Reason 'Fixing machine for Alert'";
// <tr style="background-color:#BFE1F2"><td>Measure-Performance (entire DAG):</td><td>` +  WrapInInput(measurePerformanceDag) + `</td></tr>
var html = `
<table id="helperTable" style="border:dotted 1px; padding:3px; border-radius:16px;">
<tbody>
<tr><th>ICM OnCall Helper</th><th style="width:500px"></th></tr>
<tr><th>BE</th><th></th></tr>
<tr><td width="150px">X-CalculatedBETarget:</td><td>` + WrapInInput(xCalculatedBETarget) +  `</td></tr>
<tr style="background-color:#BFE1F2"><td>Measure-Performance (current):</td><td>` +  WrapInInput(measurePerformance) + `</td></tr>
<tr style="background-color:#BFE1F2"><td>Measure-Performance (at moment of request):</td><td>` +  WrapInInput(measurePerformanceWithStartTime) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get-MachineLog (Hour of request):</td><td>` +  WrapInInput(getBEMachineLogCurrentHour) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get-MachineLog: (Previous hour before request)</td><td>` +  WrapInInput(getBEMachineLogOneHourAgo) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get-ThreadStackGrouping:</td><td>` +  WrapInInput(getThreadStackGrouping) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get Responder ThreadStacks:</td><td>` +  WrapInInput(getResponderThreadStacks) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get-MachineEvent (Application Errors):</td><td>` +  WrapInInput(getEventLogsApplication) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get-MachineEvent (Watson Events):</td><td>` +  WrapInInput(getEventLogsWatson) + `</td></tr>
<tr style="background-color:#FFF0C6"><td>Request CapacityServerAdmin:</td><td>` + WrapInInput(elevatedRights) + `</td></tr>
<tr style="background-color:#FFF0C6"><td>Maintenance Mode:</td><td>` + WrapInInput(maintenanceMode) + `</td></tr>
<tr style="background-color:#FFF0C6"><td>Recycle App Pool:</td><td>` +  WrapInInput(recycleAppPool) + `</td></tr>
<tr style="background-color:#FFF0C6"><td>Safe Reboot Machine:</td><td>` +  WrapInInput(SafeRebootMachine) + `</td></tr>
<tr style="background-color:#FFF0C6"><td>Force Reboot Machine:</td><td>` +  WrapInInput(ForceRebootMachine) + `</td></tr>
<tr><th>FE</th><th></th></tr>
<tr><td>X-FEServer (if multiple servers, run for each):</td><td>` +  WrapInInput(xFEServer) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get-MachineLog (Hour of request):</td><td>` +  WrapInInput(getFEMachineLogCurrentHour) + `</td></tr>
<tr style="background-color:#D5C3F4"><td>Get-MachineLog: (Previous hour before request)</td><td>` +  WrapInInput(getFEMachineLogOneHourAgo) + `</td></tr>
</tbody></table>
`;
return html;
}
function WrapInInput(text) {
return '<input type="text" style="width:100%" value="' + text + '" onclick="this.select()">';
}
function AddHelperHTML(helperHTML) {
$('#helperText').remove();
$('div.sixteen').each(function() {
console.log("Found div.sixteen: ", $(this));
$(this).parent().append('<td id="helperText" style="display:none; margin:10px;">'+ helperHTML +'</td>');
});
$('#helperText').fadeIn(250);
}
var Protocol = {
EWS: 1,
REST: 2,
AUTODISCOVER: 3,
UNKNOWN: 4
};
function TryDecideWhichProtocol(html) {
console.log('html: ' + html);
if(html.indexOf("Ews_AM_Probe") >= 0 || html.indexOf("ActiveMonitoring.Ews") >= 0 || html.indexOf("Webservices.Ews") >= 0 || html.indexOf("EwsResponse") >= 0) {
return Protocol.EWS;
}
else if (html.indexOf("Rest_AM_Probe") >= 0 || html.indexOf("Webservices.Rest") >= 0) {
return Protocol.REST;
}
else if(html.indexOf("autodiscover.svc") >= 0 || html.indexOf("ActiveMonitoring.AutodiscoverV2") >= 0) {
return Protocol.AUTODISCOVER;
}
else {
return Protocol.UNKNOWN;
}
}