├── iis-w3wp.xml ├── readme.md ├── w3wp-discovery.js ├── w3wp-wmi.js └── w3wp.conf /iis-w3wp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0 4 | 2013-04-21T14:46:23Z 5 | 6 | 7 | Windows servers 8 | 9 | 10 | 11 | 609 | 610 | 611 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Zabbix IIS 7 Worker Process Template 2 | ==================================== 3 | 4 | Zabbix open source monitoring solution allow create templates for specific applications. 5 | 6 | Zabbix Windows OS templates usually are combination from built-in performance counters 7 | with a reference to process name and optionaly PID. 8 | 9 | Monitoring IIS is little bit tricky because working processes is created and recycled in 10 | various conditions and thus change their PID numbers or gone forever. 11 | 12 | Solution 13 | -------- 14 | 15 | Use Zabbix Low-level discovery feature to find IIS 7 application pool names using *appcmd.exe*. 16 | 17 | Use WMI script for specified application name to find the PID and then the required performance counter. 18 | 19 | Installation 20 | ------------ 21 | 22 | Copy files to Zabbix Agent directory (C:\Program Files\Zabbix\) 23 | 24 | * w3wp.conf 25 | * w3wp-discovery.js 26 | * w3wp-wmi.js 27 | 28 | Append Zabbix Agent configuration file (zabbix_agentd.conf) with lines from file *w3wp.conf* 29 | or *Include* this file. 30 | 31 | Import Zabbix template (iis-w3wp.xml) and assign to a Windows IIS host. 32 | 33 | 34 | -------------------------------------------------------------------------------- /w3wp-discovery.js: -------------------------------------------------------------------------------- 1 | 2 | var WshShell = WScript.CreateObject("WScript.Shell"); 3 | var oExec = WshShell.Exec("%windir%\\system32\\inetsrv\\appcmd.exe list wp"); 4 | 5 | /* 6 | WP "4316" (applicationPool:xxx) 7 | WP "4080" (applicationPool:yyy) 8 | WP "3200" (applicationPool:zzz) 9 | */ 10 | 11 | var RE = /WP "(\d+)" \([^:]+:([^\)]+)\)/ 12 | 13 | print("{\n"); 14 | print("\t\"data\":"); 15 | print("\t["); 16 | 17 | var next = false; 18 | while (!oExec.StdOut.AtEndOfStream) { 19 | 20 | var line = oExec.StdOut.ReadLine(); 21 | var match = RE.exec(line) 22 | 23 | if (match) { 24 | 25 | if (next) print("\t,"); 26 | next = true; 27 | 28 | print("\t\t{\"{#WPNAME}\":\"" + match[2] + "\"}"); 29 | } 30 | } 31 | 32 | print("\t]"); 33 | print("}"); 34 | 35 | 36 | function print(text) { WScript.Echo(text); } -------------------------------------------------------------------------------- /w3wp-wmi.js: -------------------------------------------------------------------------------- 1 | 2 | if (WScript.Arguments.Count() != 2) WScript.Quit(1); 3 | 4 | var wpname = WScript.Arguments.Item(0); 5 | var counter = WScript.Arguments.Item(1); 6 | 7 | switch(counter) { 8 | case 'IODataOperationsPerSec': 9 | case 'IOOtherOperationsPerSec': 10 | case 'IOReadBytesPerSec': 11 | case 'IOReadOperationsPerSec': 12 | case 'IOWriteBytesPerSec': 13 | case 'IOWriteOperationsPerSec': 14 | case 'IODataBytesPerSec': 15 | case 'IOOtherBytesPerSec': 16 | case 'PageFaultsPerSec': 17 | WScript.Echo(PERF_COUNTER_BULK_COUNT(wpname, counter)); 18 | break; 19 | case 'HandleCount': 20 | case 'PageFileBytes': 21 | case 'PageFileBytesPeak': 22 | case 'PoolNonpagedBytes': 23 | case 'PoolPagedBytes': 24 | case 'PriorityBase': 25 | case 'PrivateBytes': 26 | case 'ThreadCount': 27 | case 'VirtualBytes': 28 | case 'VirtualBytesPeak': 29 | case 'WorkingSet': 30 | case 'WorkingSetPeak': 31 | WScript.Echo(PERF_COUNTER_RAWCOUNT(wpname, counter)); 32 | break; 33 | case 'PercentPrivilegedTime': 34 | case 'PercentProcessorTime': 35 | case 'PercentUserTime': 36 | WScript.Echo(PERF_100NSEC_TIMER(wpname, counter)); 37 | break 38 | default: 39 | WScript.Quit(1); 40 | } 41 | WScript.Quit(); 42 | 43 | // 44 | function PERF_COUNTER_RAWCOUNT(wpname, counter) { 45 | 46 | var pid = getPidByName(wpname); 47 | if (!pid) return 0; 48 | 49 | var data = getWmiProcess(pid, counter); 50 | if (data) 51 | return data[counter]; 52 | 53 | return 0; 54 | } 55 | 56 | // 57 | function PERF_COUNTER_BULK_COUNT(wpname, counter) { 58 | 59 | var pid = getPidByName(wpname); 60 | if (!pid) return 0; 61 | 62 | var wpdata2 = null 63 | var data = getWmiProcess(pid, "Frequency_Sys100NS,Timestamp_Sys100NS," + counter); 64 | if (data) 65 | wpdata2 = [pid, data.Timestamp_Sys100NS, data[counter], data.Frequency_Sys100NS]; 66 | 67 | filePath = getTempPath(wpname + '_' + counter); 68 | 69 | var wpdata1 = null; 70 | if (existsFile(filePath)) 71 | wpdata1 = readFile(filePath).split(" "); 72 | 73 | writeFile(filePath, wpdata2.join(" ")); 74 | 75 | if (wpdata2 && wpdata1 && wpdata2[0] == wpdata1[0]) { 76 | var d = (wpdata2[1] - wpdata1[1]) / wpdata2[3]; 77 | var n = wpdata2[2] - wpdata1[2]; 78 | return (n/d).toFixed(0); 79 | } 80 | return 0; 81 | } 82 | 83 | // 84 | function PERF_100NSEC_TIMER(wpname, counter) { 85 | 86 | var pid = getPidByName(wpname); 87 | if (!pid) return 0; 88 | 89 | var wpdata2 = null 90 | var data = getWmiProcess(pid, "Timestamp_Sys100NS," + counter); 91 | if (data) 92 | wpdata2 = [pid, data.Timestamp_Sys100NS, data[counter]]; 93 | 94 | filePath = getTempPath(wpname + '_' + counter); 95 | 96 | var wpdata1 = null; 97 | if (existsFile(filePath)) 98 | wpdata1 = readFile(filePath).split(" "); 99 | 100 | writeFile(filePath, wpdata2.join(" ")); 101 | 102 | if (wpdata2 && wpdata1 && wpdata2[0] == wpdata1[0]) { 103 | var d = wpdata2[1] - wpdata1[1]; 104 | var n = wpdata2[2] - wpdata1[2]; 105 | return (100 * n/d).toFixed(0); 106 | } 107 | return 0; 108 | } 109 | 110 | // 111 | function getTempPath(name) { 112 | var fso = WScript.CreateObject("Scripting.FileSystemObject"); 113 | var tmp = fso.GetSpecialFolder(2).path 114 | return fso.buildPath(tmp, name); 115 | } 116 | 117 | // 118 | function existsFile(path) { 119 | var fso = WScript.CreateObject("Scripting.FileSystemObject"); 120 | return fso.fileExists(path); 121 | } 122 | 123 | // 124 | function readFile(path) { 125 | var fso = WScript.CreateObject("Scripting.FileSystemObject"); 126 | var ts = fso.OpenTextFile(path, 1); 127 | text = ts.readAll(); 128 | ts.close(); 129 | return text; 130 | } 131 | 132 | // 133 | function writeFile(path, text) { 134 | var fso = WScript.CreateObject("Scripting.FileSystemObject"); 135 | var ts = fso.CreateTextFile(path); 136 | ts.Write(text); 137 | ts.Close(); 138 | } 139 | 140 | // 141 | function getWmiProcess(pid, counters) { 142 | var wmi = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2"); 143 | var wql = "select " + counters +" from Win32_PerfRawData_PerfProc_Process where IDProcess=" + pid; 144 | for (var e = new Enumerator(wmi.ExecQuery(wql)); !e.atEnd(); e.moveNext()) 145 | return e.item(); 146 | } 147 | 148 | // 149 | function getPidByName(wpname) { 150 | var RE = /WP "(\d+)" \([^:]+:([^\)]+)\)/ 151 | var WshShell = WScript.CreateObject("WScript.Shell"); 152 | var oExec = WshShell.Exec("%windir%\\system32\\inetsrv\\appcmd.exe list wp"); 153 | while (!oExec.StdOut.AtEndOfStream) { 154 | var line = oExec.StdOut.ReadLine(); 155 | var match = RE.exec(line) 156 | if (match && match[2] == wpname) 157 | return match[1]; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /w3wp.conf: -------------------------------------------------------------------------------- 1 | UserParameter=w3wp.discovery,cscript /Nologo "C:\Program Files\Zabbix\w3wp-discovery.js" 2 | UserParameter=w3wp.wmi[*],cscript /Nologo "C:\Program Files\Zabbix\w3wp-wmi.js" "$1" "$2" --------------------------------------------------------------------------------