diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
commit | 47e6e7c84f008a53061e661f31ae96629bc694ef (patch) | |
tree | 648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/windows | |
download | pcp-debian.tar.gz |
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/windows')
-rw-r--r-- | src/pmdas/windows/GNUmakefile | 81 | ||||
-rw-r--r-- | src/pmdas/windows/README | 171 | ||||
-rw-r--r-- | src/pmdas/windows/error.c | 130 | ||||
-rw-r--r-- | src/pmdas/windows/fetch.c | 209 | ||||
-rw-r--r-- | src/pmdas/windows/help | 65 | ||||
-rw-r--r-- | src/pmdas/windows/helptext.c | 84 | ||||
-rw-r--r-- | src/pmdas/windows/hypnotoad.h | 104 | ||||
-rw-r--r-- | src/pmdas/windows/instance.c | 376 | ||||
-rw-r--r-- | src/pmdas/windows/open.c | 769 | ||||
-rw-r--r-- | src/pmdas/windows/pdhlist.c | 85 | ||||
-rw-r--r-- | src/pmdas/windows/pdhmatch.sh | 192 | ||||
-rw-r--r-- | src/pmdas/windows/pmda.c | 1601 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.disk | 52 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.filesys | 6 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.hinv | 7 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.kernel | 48 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.mem | 61 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.network | 42 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.pmda | 4 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.process | 59 | ||||
-rw-r--r-- | src/pmdas/windows/pmns.sqlserver | 147 | ||||
-rw-r--r-- | src/pmdas/windows/root | 29 |
22 files changed, 4322 insertions, 0 deletions
diff --git a/src/pmdas/windows/GNUmakefile b/src/pmdas/windows/GNUmakefile new file mode 100644 index 0000000..aef7163 --- /dev/null +++ b/src/pmdas/windows/GNUmakefile @@ -0,0 +1,81 @@ +# +# Copyright (c) 2008-2009 Aconex. All Rights Reserved. +# Copyright (c) 2000,2003,2004 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs +WINDIR = $(TOPDIR)/src/win32ctl + +IAM = windows +DOMAIN = WINDOWS +CFILES = pmda.c error.c open.c instance.c fetch.c helptext.c +HFILES = hypnotoad.h +LCFLAGS = -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0500 \ + -I$(WINDIR)/include +LLDFLAGS = -L$(WINDIR)/lib +LLDLIBS = $(PCP_PMDALIB) -lpcp_pdh +PMNS = pmns.disk pmns.kernel pmns.mem pmns.network \ + pmns.sqlserver pmns.filesys pmns.hinv pmns.pmda \ + pmns.process +LSRCFILES = $(PMNS) root help README pdhlist.c pdhmatch.sh +PMDADIR = $(PCP_PMDAS_DIR)/$(IAM) +LIBTARGET = pmda_windows.dll +EXTRATARGETS = pdhlist.exe help.dir help.pag + +LDIRT = root_windows domain.h $(IAM).log pmda$(IAM) \ + $(EXTRATARGETS) pdhlist.o + +CONF_LINE = "windows 79 dso windows_init $(PCP_PMDAS_DIR)/windows/pmda_windows.dll" + +default: build-me + +include $(BUILDRULES) + +ifeq "$(TARGET_OS)" "mingw" +build-me: root_windows $(LSRCFILES) $(LIBTARGET) $(EXTRATARGETS) + @if [ `grep -c $(CONF_LINE) ../pmcd.conf` -eq 0 ]; then \ + echo $(CONF_LINE) >> ../pmcd.conf ; \ + fi + +install: build-me + $(INSTALL) -m 755 -d $(PMDADIR) + $(INSTALL) -m 755 pdhlist.exe $(LIBTARGET) $(PMDADIR) + $(INSTALL) -m 644 README root $(PMNS) $(PMDADIR) + $(INSTALL) -m 644 domain.h help.dir help.pag help $(PMDADIR) + $(INSTALL) -m 644 root_windows $(PCP_VAR_DIR)/pmns/root_windows +else +build-me: +install: +endif + +help.dir help.pag : help root_windows + $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/newhelp/newhelp -n root_windows -v 2 -o help < help + +default_pcp: default + +install_pcp: install + +root_windows: ../../pmns/stdpmid $(PMNS) + rm -f root_windows + sed -e 's;<stdpmid>;"../../pmns/stdpmid";' <root \ + | $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/pmcpp/pmcpp \ + | sed -e '/^#/d' -e '/^$$/d' >root_windows + +domain.h: ../../pmns/stdpmid + $(DOMAIN_MAKERULE) + +$(OBJECTS): hypnotoad.h domain.h + +pdhlist.exe: pdhlist.o error.o + $(CCF) -o pdhlist.exe pdhlist.o error.o $(LLDFLAGS) -lpcp_pdh diff --git a/src/pmdas/windows/README b/src/pmdas/windows/README new file mode 100644 index 0000000..a6847e7 --- /dev/null +++ b/src/pmdas/windows/README @@ -0,0 +1,171 @@ +Windows PMDA +============ + +This PMDA collects performance data from a Microsoft Windows kernel. + +Metrics +======= + +The help text is exported from the kernel via the PDH (Performance +Data Helper) APIs. To view the help text, install the PMDA, then +the following command will list all the available metrics and their +explanatory "help" text: + + $ pminfo -fT kernel disk mem network filesys sqlserver hinv pmda process + +Installation +============ + + + # cd $PCP_PMDAS_DIR/windows + + + Check that there is no clash in the Performance Metrics Domain + defined in ./domain.h and the other PMDAs currently in use (see + $PCP_PMCDCONF_PATH). If there is, edit ./domain.h to choose another + domain number. + + + Then simply use + + # ./Install + + and choose both the "collector" and "monitor" installation + configuration options -- everything else is automated. + +De-installation +=============== + + + Simply use + + # cd $PCP_PMDAS_DIR/windows + # ./Remove + +Troubleshooting +=============== + + + After installing or restarting the agent, the PMCD log file + ($PCP_LOG_DIR/pmcd/pmcd.log) and the PMDA log file + ($PCP_LOG_DIR/pmcd/windows.log) should be checked for any warnings + or errors. + +Adding New Metrics +================== + +The following steps should be followed when adding new metrics ... this +assumes the MinGW gcc compiler is being used. + +a. Make sure you know what you've currently got, so on the target system + $ ./pdhlist | ./pdhmatch >status-quo + +b. Pick the Pdh paths you're interested in (drop the hostname prefix, + add the (*/*#*) or * patterns as appropriate. Beware that metrics + with multiple instances are reported multiple times ... for example + + SQLServer:Cache Manager\Cache Hit Ratio + SQLServer:Cache Manager(_Total)\Cache Hit Ratio + SQLServer:Cache Manager(*/*#*)\Cache Hit Ratio + + of these, the first pattern must not be used ... use the second one + if you want the "over all instances" totals, and the last one gives + the per instance metrics. + +c. Choose a PMID ... use the next unused number in sequence ... check + metricdesc[] in pmda.c, you want the PMDA_PMID(0,x) macro from the + last entry in the table, and the number you're after is x+1 (x+1 = + 81 for my example). + +d. Choose a name and where to put the new metric in the namespace ... + edit the appropriate pmns.* file (let's assume you're adding to one + of the existing Pdh groups, rather than creating a new one which is + more complicated), adding an appropriate entry using x+1 from above + for the last component of the PMID. Something like this in + pmns.sqlserver + + sqlserver { + ... + cache_mgr // new line + } + + ... + + // all new lines from here down + + sqlserver.cache_mgr { + all + percache + } + + sqlserver.cache_mgr.all { + cache_hit_ratio WINDOWS:0:81 + } + + sqlserver.cache_mgr.cache { + cache_hit_ratio WINDOWS:0:82 + } + + + Write the modified pmns file. + + Check you've got it right with + + $ pminfo -m -n root sqlserver.cache_mgr + sqlserver.cache_mgr.all.cache_hit_ratio PMID: 79.0.81 + sqlserver.cache_mgr.cache.cache_hit_ratio PMID: 79.0.82 + +e. Metric semantics ... you'll need a complete metricdesc[i] + initializer from pmda.c ... pick one that is similar, copy, paste + at the end of the table initialization and update PMDA_PMID(0,y) + with x+1 from step a. + + To help with "similar" here are some examples: + + kernel.all.cpu.user - unsigned 64-bit counter in units of microseconds + + network.interface.in.bytes - unsigned 32-bit counter in units of + bytes with one value per network interface + + mem.available - unsigned 64-bit instantaneous value in units of + Mbytes + + sqlserver.buf_mgr.cache_hit_ratio - floating point value + representing a cache hit ratio, returned in the range 0.0 to + 1.0 + + Be careful with '\' in the Pdh patterns. Replace them with '\\' in the + string initializer used here. + + My new metrics are cache hit ratios + + /* sqlserver.cache_mgr.all.cache_hit_ratio */ + { { PMDA_PMID(0,81), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(_Total)\\Cache Hit Ratio" + }, + /* sqlserver.cache_mgr.cache.cache_hit_ratio */ + { { PMDA_PMID(0,82), PM_TYPE_FLOAT, SQL_CACHE_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(*/*#*)\\Cache Hit Ratio" + }, + +f. If you've added a new instance domain (SQL_CACHE_INDOM in the case + above, this needs to be handled): + i. add a new header #define line (use the next ordinal number), e.g. + #define SQL_CACHE_INDOM 5 + ii. add a new entry to indomtab[] in pmda.c, e.g. + { SQL_CACHE_INDOM, 0, NULL }, + iii. add a new entry to indomtab[] in instance.c, e.g. + SQL_CACHE_INDOM, + iv. add new code in the switch of check_instance() in instance.c + to parse the Pdh instance name to extract a PCP instance name + and assign an instance number ... it is strongly suggested + that you study the ones already there, steal and modify the + one that is closest to your new instance + +g. Make and upgrade (assuming you're on the target machine and not + interested in packaging) + + $ make + $ su + # /etc/pcp stop + # make install + # cd $PCP_VAR_DIR/pmdas/windows + # ./Install + diff --git a/src/pmdas/windows/error.c b/src/pmdas/windows/error.c new file mode 100644 index 0000000..9961d78 --- /dev/null +++ b/src/pmdas/windows/error.c @@ -0,0 +1,130 @@ +/* + * Error code -> message map comes from + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/pdh_error_codes.asp + * + * Copyright (c) 2008 Aconex. All Rights Reserved. + * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "hypnotoad.h" + +static struct { + int code; + char *msg; +} errtab[] = { + { PDH_CSTATUS_VALID_DATA, "The returned data is valid." }, + { PDH_CSTATUS_NEW_DATA, "The return data value is valid and different from the last sample." }, + { PDH_CSTATUS_NO_MACHINE, "Unable to connect to specified machine or machine is off line." }, + { PDH_CSTATUS_NO_INSTANCE, "The specified instance is not present." }, + { PDH_MORE_DATA, "There is more data to return than would fit in the supplied buffer. Allocate a larger buffer and call the function again." }, + { PDH_CSTATUS_ITEM_NOT_VALIDATED, "The data item has been added to the query but has not been validated nor accessed. No other status information on this data item is available." }, + { PDH_RETRY, "The selected operation should be retried." }, + { PDH_NO_DATA, "No data to return." }, + { PDH_CALC_NEGATIVE_DENOMINATOR, "A counter with a negative denominator value was detected." }, + { PDH_CALC_NEGATIVE_TIMEBASE, "A counter with a negative time base value was detected." }, + { PDH_CALC_NEGATIVE_VALUE, "A counter with a negative value was detected." }, + { PDH_DIALOG_CANCELLED, "The user canceled the dialog box." }, + { PDH_END_OF_LOG_FILE, "The end of the log file was reached." }, + { PDH_ASYNC_QUERY_TIMEOUT, "Time out while waiting for asynchronous counter collection thread to end." }, + { PDH_CANNOT_SET_DEFAULT_REALTIME_DATASOURCE, "Cannot change set default real-time data source. There are real-time query sessions collecting counter data." }, + { PDH_CSTATUS_NO_OBJECT, "The specified object is not found on the system." }, + { PDH_CSTATUS_NO_COUNTER, "The specified counter could not be found." }, + { PDH_CSTATUS_INVALID_DATA, "The returned data is not valid." }, + { PDH_MEMORY_ALLOCATION_FAILURE, "A PDH function could not allocate enough temporary memory to complete the operation. Close some applications or extend the page file and retry the function." }, + { PDH_INVALID_HANDLE, "The handle is not a valid PDH object." }, + { PDH_INVALID_ARGUMENT, "A required argument is missing or incorrect." }, + { PDH_FUNCTION_NOT_FOUND, "Unable to find the specified function." }, + { PDH_CSTATUS_NO_COUNTERNAME, "No counter was specified." }, + { PDH_CSTATUS_BAD_COUNTERNAME, "Unable to parse the counter path. Check the format and syntax of the specified path." }, + { PDH_INVALID_BUFFER, "The buffer passed by the caller is invalid." }, + { PDH_INSUFFICIENT_BUFFER, "The requested data is larger than the buffer supplied. Unable to return the requested data." }, + { PDH_CANNOT_CONNECT_MACHINE, "Unable to connect to the requested machine." }, + { PDH_INVALID_PATH, "The specified counter path could not be interpreted." }, + { PDH_INVALID_INSTANCE, "The instance name could not be read from the specified counter path." }, + { PDH_INVALID_DATA, "The data is not valid." }, + { PDH_NO_DIALOG_DATA, "The dialog box data block was missing or invalid." }, + { PDH_CANNOT_READ_NAME_STRINGS, "Unable to read the counter and/or explain text from the specified machine." }, + { PDH_LOG_FILE_CREATE_ERROR, "Unable to create the specified log file." }, + { PDH_LOG_FILE_OPEN_ERROR, "Unable to open the specified log file." }, + { PDH_LOG_TYPE_NOT_FOUND, "The specified log file type has not been installed on this system." }, + { PDH_NO_MORE_DATA, "No more data is available." }, + { PDH_ENTRY_NOT_IN_LOG_FILE, "The specified record was not found in the log file." }, + { PDH_DATA_SOURCE_IS_LOG_FILE, "The specified data source is a log file." }, + { PDH_DATA_SOURCE_IS_REAL_TIME, "The specified data source is the current activity." }, + { PDH_UNABLE_READ_LOG_HEADER, "The log file header could not be read." }, + { PDH_FILE_NOT_FOUND, "Unable to find the specified file." }, + { PDH_FILE_ALREADY_EXISTS, "There is already a file with the specified file name." }, + { PDH_NOT_IMPLEMENTED, "The function referenced has not been implemented." }, + { PDH_STRING_NOT_FOUND, "Unable to find the specified string in the list of performance name and explain text strings." }, + { PDH_UNABLE_MAP_NAME_FILES, "Unable to map to the performance counter name data files. The data will be read from the registry and stored locally." }, + { PDH_UNKNOWN_LOG_FORMAT, "The format of the specified log file is not recognized by the PDH DLL." }, + { PDH_UNKNOWN_LOGSVC_COMMAND, "The specified Log Service command value is not recognized." }, + { PDH_LOGSVC_QUERY_NOT_FOUND, "The specified Query from the Log Service could not be found or could not be opened." }, + { PDH_LOGSVC_NOT_OPENED, "The Performance Data Log Service key could not be opened. This may be due to insufficient privilege or because the service has not been installed." }, + { PDH_WBEM_ERROR, "An error occurred while accessing the WBEM data store." }, + { PDH_ACCESS_DENIED, "Unable to access the desired machine or service. Check the permissions and authentication of the log service or the interactive user session against those on the machine or service being monitored." }, + { PDH_LOG_FILE_TOO_SMALL, "The maximum log file size specified is too small to log the selected counters. No data will be recorded in this log file. Specify a smaller set of counters to log or a larger file size and retry this call." }, + { PDH_INVALID_DATASOURCE, "Cannot connect to ODBC DataSource Name." }, + { PDH_INVALID_SQLDB, "SQL Database does not contain a valid set of tables for Perfmon; use PdhCreateSQLTables." }, + { PDH_NO_COUNTERS, "No counters were found for this Perfmon SQL Log Set." }, + { PDH_SQL_ALLOC_FAILED, "Call to SQLAllocStmt failed with %1." }, + { PDH_SQL_ALLOCCON_FAILED, "Call to SQLAllocConnect failed with %1." }, + { PDH_SQL_EXEC_DIRECT_FAILED, "Call to SQLExecDirect failed with %1." }, + { PDH_SQL_FETCH_FAILED, "Call to SQLFetch failed with %1." }, + { PDH_SQL_ROWCOUNT_FAILED, "Call to SQLRowCount failed with %1." }, + { PDH_SQL_MORE_RESULTS_FAILED, "Call to SQLMoreResults failed with %1." }, + { PDH_SQL_CONNECT_FAILED, "Call to SQLConnect failed with %1." }, + { PDH_SQL_BIND_FAILED, "Call to SQLBindCol failed with %1." }, + { PDH_CANNOT_CONNECT_WMI_SERVER, "Unable to connect to the WMI server on requested machine." }, + { PDH_PLA_COLLECTION_ALREADY_RUNNING, "Collection %1s is already running." }, + { PDH_PLA_ERROR_SCHEDULE_OVERLAP, "The specified start time is after the end time." }, + { PDH_PLA_COLLECTION_NOT_FOUND, "Collection %1 does not exist." }, + { PDH_PLA_ERROR_SCHEDULE_ELAPSED, "The specified end time has already elapsed." }, + { PDH_PLA_ERROR_NOSTART, "Collection %1 did not start check the application event log for any errors." }, + { PDH_PLA_ERROR_ALREADY_EXISTS, "Collection %1 already exists." }, + { PDH_PLA_ERROR_TYPE_MISMATCH, "There is a mismatch in the settings type." }, + { PDH_PLA_ERROR_FILEPATH, "The information specified does not resolve to a valid path name." }, + { PDH_PLA_SERVICE_ERROR, "The 'Performance Logs & Alerts' service did not respond." }, + { PDH_PLA_VALIDATION_ERROR, "The information passed is not valid." }, + { PDH_PLA_VALIDATION_WARNING, "The information passed is not valid." }, + { PDH_PLA_ERROR_NAME_TOO_LONG, "The name supplied is too long." }, + { PDH_INVALID_SQL_LOG_FORMAT, "SQL log format is incorrect. Correct format is 'SQL:<DSN-name>!<LogSet-Name>'." }, + { PDH_COUNTER_ALREADY_IN_QUERY, "Performance counter in PdhAddCounter call has already been added in the performance query. This counter is ignored." }, + { PDH_BINARY_LOG_CORRUPT, "Unable to read counter information and data from input binary log files." }, + { PDH_LOG_SAMPLE_TOO_SMALL, "At least one of the input binary log files contain fewer than two data samples." }, + { PDH_OS_LATER_VERSION, "The version of the operating system on the computer named %1 is later than that on the local computer. This operation is not available from the local computer." }, + { PDH_OS_EARLIER_VERSION, "supports %2 or later. Check the operating system version on the computer named %3." }, + { PDH_INCORRECT_APPEND_TIME, "The output file must contain earlier data than the file to be appended." }, + { PDH_UNMATCHED_APPEND_COUNTER, "Both files must have identical counters in order to append." }, + { PDH_SQL_ALTER_DETAIL_FAILED, "Cannot alter CounterDetail table layout in SQL database." }, + { PDH_QUERY_PERF_DATA_TIMEOUT, "System is busy. Timeout when collecting counter data. Please retry later or increase the CollectTime registry value." } +}; + +static int sz_errtab = sizeof(errtab) / sizeof(errtab[0]); +static char *buf = "eh? 0x........"; + +char *pdherrstr(int code) +{ + int i; + + for (i = 0; i < sz_errtab; i++) { + if (code == errtab[i].code) + return errtab[i].msg; + } + sprintf(buf, "eh? 0x%08x", code); + return buf; +} diff --git a/src/pmdas/windows/fetch.c b/src/pmdas/windows/fetch.c new file mode 100644 index 0000000..cc43955 --- /dev/null +++ b/src/pmdas/windows/fetch.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2008-2010 Aconex. All Rights Reserved. + * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "hypnotoad.h" + +MEMORYSTATUSEX windows_memstat; + +void +windows_fetch_memstat(void) +{ + ZeroMemory(&windows_memstat, sizeof(MEMORYSTATUSEX)); + windows_memstat.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&windows_memstat); +} + +/* + * Instantiate a value for a single metric-instance pair + */ +int +windows_collect_metric(pdh_metric_t *mp, LPSTR pat, pdh_value_t *vp) +{ + PDH_STATUS pdhsts; + PDH_HQUERY queryhdl = NULL; + PDH_HCOUNTER counthdl = NULL; + int sts = -1; + + if (mp->flags & M_NOVALUES) + return sts; + + pdhsts = PdhOpenQueryA(NULL, 0, &queryhdl); + if (pdhsts != ERROR_SUCCESS) { + __pmNotifyErr(LOG_ERR, "windows_open: PdhOpenQueryA failed: %s\n", + pdherrstr(pdhsts)); + return sts; + } + + pdhsts = PdhAddCounterA(queryhdl, pat, vp->inst, &counthdl); + if (pdhsts != ERROR_SUCCESS) { + __pmNotifyErr(LOG_ERR, "windows_open: Warning: PdhAddCounterA " + "@ pmid=%s pat=\"%s\": %s\n", + pmIDStr(mp->desc.pmid), pat, pdherrstr(pdhsts)); + PdhCloseQuery(queryhdl); + return sts; + } + + pdhsts = PdhCollectQueryData(queryhdl); + if (pdhsts != ERROR_SUCCESS) { + if ((vp->flags & V_ERROR_SEEN) == 0) { + __pmNotifyErr(LOG_ERR, "pdh_fetch: Error: PdhCollectQueryData " + "failed for metric %s pat %s: %s\n", + pmIDStr(mp->desc.pmid), pat, pdherrstr(pdhsts)); + vp->flags |= V_ERROR_SEEN; + } + } else if ((mp->ctype == PERF_ELAPSED_TIME) || + mp->ctype == PERF_LARGE_RAW_FRACTION) { + PDH_FMT_COUNTERVALUE fmt; + DWORD type; + + if (mp->ctype == PERF_ELAPSED_TIME) + type = PDH_FMT_LARGE; + else /* PERF_LARGE_RAW_FRACTION */ + type = PDH_FMT_DOUBLE; + + pdhsts = PdhGetFormattedCounterValue(counthdl, type, NULL, &fmt); + if (pdhsts != ERROR_SUCCESS) { + __pmNotifyErr(LOG_ERR, "Error: PdhGetFormattedCounterValue " + "failed for metric %s inst %d: %s\n", + pmIDStr(mp->desc.pmid), vp->inst, pdherrstr(pdhsts)); + vp->flags = V_NONE; /* no values for you! */ + } else if (mp->ctype == PERF_ELAPSED_TIME) { + vp->atom.ull = fmt.largeValue; + sts = 0; + } else { /* PERF_LARGE_RAW_FRACTION */ + vp->atom.d = fmt.doubleValue; + sts = 0; + } + } else { + PDH_RAW_COUNTER raw; + + pdhsts = PdhGetRawCounterValue(counthdl, NULL, &raw); + if (pdhsts != ERROR_SUCCESS) { + __pmNotifyErr(LOG_ERR, "pdh_fetch: Error: PdhGetRawCounterValue " + "failed for metric %s inst %d: %s\n", + pmIDStr(mp->desc.pmid), vp->inst, pdherrstr(pdhsts)); + vp->flags = V_NONE; /* no values for you! */ + } else { + switch (mp->ctype) { + case PERF_COUNTER_COUNTER: + case PERF_COUNTER_RAWCOUNT: + /* these counters are only 32-bit */ + vp->atom.ul = (__uint32_t)raw.FirstValue; + break; + + case PERF_100NSEC_TIMER: + case PERF_PRECISION_100NS_TIMER: + /* convert 100nsec units to usec */ + vp->atom.ull = raw.FirstValue / 10; + break; + + case PERF_RAW_FRACTION: + /* v1 / v2 as percentage */ + vp->atom.f = (float)raw.FirstValue / raw.SecondValue; + break; + + case PERF_COUNTER_BULK_COUNT: + case PERF_COUNTER_LARGE_RAWCOUNT: + default: + vp->atom.ull = raw.FirstValue; + } + sts = 0; + } + } + PdhRemoveCounter(counthdl); + PdhCloseQuery(queryhdl); + return sts; +} + +void +windows_collect_callback(pdh_metric_t *pmp, LPTSTR pat, pdh_value_t *pvp) +{ + windows_verify_callback(pmp, pat, pvp); + + if (!(pvp->flags & V_COLLECTED)) + if (windows_collect_metric(pmp, pat, pvp) == 0) + pvp->flags |= V_COLLECTED; +} + +/* + * Called before each PMDA fetch ... force value refreshes for + * requested metrics here; and special case any derived metrics. + */ +void +windows_fetch_refresh(int numpmid, pmID pmidlist[], pmdaExt *pmda) +{ + int i, j, extra_filesys = 0, extra_memstat = 0; + int extra_hinv_ncpu = -1, extra_hinv_ndisk = -1; + int extra_network = -1; + + for (i = 0; i < NUMINDOMS; i++) + windows_indom_reset[i] = 0; + + for (i = 0; i < metricdesc_sz; i++) + for (j = 0; j < metricdesc[i].num_vals; j++) + metricdesc[i].vals[j].flags = V_NONE; + + for (i = 0; i < numpmid; i++) { + __pmID_int *pmidp = (__pmID_int *)&pmidlist[i]; + int cluster = pmidp->cluster; + int item = pmidp->item; + + if (cluster == 1) + extra_memstat = 1; + else if (cluster != 0) + continue; + else if (item == 106) + extra_memstat = 1; + else if (item == 107 && extra_hinv_ncpu == -1) + extra_hinv_ncpu = 1; + else if (item == 108 && extra_hinv_ndisk == -1) + extra_hinv_ndisk = 1; + else if (item >= 117 && item <= 119) + extra_filesys = 1; + else if (item >= 236 && item <= 237 && extra_network == -1) + extra_network = 1; + else { + if (item >= 4 && item <= 7) + extra_hinv_ncpu = 0; + else if ((item >= 21 && item <= 26) || item == 68 || + (item >= 217 && item <= 219) || item == 101 || + (item >= 226 && item <= 231) || item == 133) + extra_hinv_ndisk = 0; + else if (item == 235) + extra_network = 0; + + windows_visit_metric(&metricdesc[item], windows_collect_callback); + } + } + + if (extra_memstat) + windows_fetch_memstat(); + if (extra_hinv_ncpu == 1) + windows_visit_metric(&metricdesc[4], NULL); + if (extra_hinv_ndisk == 1) + windows_visit_metric(&metricdesc[21], NULL); + if (extra_filesys) { + windows_visit_metric(&metricdesc[120], windows_collect_callback); + windows_visit_metric(&metricdesc[121], windows_collect_callback); + } + if (extra_network == 1) + windows_visit_metric(&metricdesc[235], windows_collect_callback); + + for (i = 0; i < NUMINDOMS; i++) { + /* Do we want to persist this instance domain to disk? */ + if (windows_indom_reset[i] && windows_indom_fixed(i)) + pmdaCacheOp(INDOM(pmda->e_domain, i), PMDA_CACHE_SAVE); + } +} diff --git a/src/pmdas/windows/help b/src/pmdas/windows/help new file mode 100644 index 0000000..b58a1ea --- /dev/null +++ b/src/pmdas/windows/help @@ -0,0 +1,65 @@ +# +# Copyright (c) 2010 Aconex. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Windows PMDA help file in the ASCII format. Only metrics which are +# not using PDH regular expressions for extraction should be contained +# here - the rest have their help text auto-generated by Windows PDH. +# +# lines beginning with a # are ignored +# lines beginning @ introduce a new entry of the form +# @ metric_name oneline-text +# help test goes +# here over multiple lines +# ... +# +# the metric_name is decoded against the default PMNS -- as a special case, +# a name of the form NNN.MM (for numeric NNN and MM) is interpreted as an +# instance domain identification, and the text describes the instance domain +# +# blank lines before the @ line are ignored +# +@ kernel.uname.release release level of the running kernel +@ kernel.uname.version version level (build number) and build date of the running kernel +@ kernel.uname.sysname name of the implementation of the operating system +@ kernel.uname.machine name of the hardware type the system is running on +@ kernel.uname.nodename host name of this node on the network +@ kernel.uname.distro Windows distribution name +The Windows distribution name, from the GetVersionEx Win32 API. + +@ network.interface.speed interface speed in megabytes per second +The linespeed on the network interface, as reported by the kernel, +scaled from Megabits/second to Megabytes/second. +See also network.interface.baudrate for the bytes/second value. + +@ network.interface.baudrate interface speed in bytes per second +The linespeed on the network interface, as reported by the kernel, +scaled from bits/second and divided by 8 to convert to bytes/second. +See also network.interface.speed for the Megabytes/second value. + +@ pmda.uname identity and type of current system +Identity and type of current system. + +See also the kernel.uname.* metrics + +@ pmda.version build version of Windows PMDA + +@ hinv.physmem total system memory metric +@ hinv.pagesize Memory page size +The memory page size of the running kernel in bytes. +@ hinv.ncpu number of CPUs in the system +@ hinv.ndisk number of disks in the syste (excluding floppy drives) +@ hinv.nfilesys number of (local) file systems currently mounted + +@ filesys.capacity Total capacity of mounted filesystem (Kbytes) +@ filesys.used Total space used on mounted filesystem (Kbytes) +@ filesys.free Total space free on mounted filesystem (Kbytes) diff --git a/src/pmdas/windows/helptext.c b/src/pmdas/windows/helptext.c new file mode 100644 index 0000000..d1876e1 --- /dev/null +++ b/src/pmdas/windows/helptext.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2008-2009 Aconex. All Rights Reserved. + * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <ctype.h> +#include "hypnotoad.h" + +static char *text; /* filled in by iterator callback routine */ +static char texts[MAX_M_TEXT_LEN]; /* static callback buffer */ + +/* + * Replace backslashes in the help string returned from Pdh APIs. + * Everything done "in-place" so no change to size of the string. + */ +static char * +windows_fmt(char *text) +{ + char *p; + int n; + + for (p = text, n = 0; p && *p != '\0'; p++, n++) { + if (!isprint((int)*p)) /* toss any dodgey characters */ + *p = '?'; + else if (*p == '\r') /* remove Windows line ending */ + *p = '\n'; + if (n < 70 || !isspace((int)*p)) /* very simple line wrapping */ + continue; + *p = '\n'; + n = 0; + } + return text; +} + +static void +windows_helptext_metric(pdh_metric_t *mp, PDH_COUNTER_INFO_A *infop) +{ + text = infop->szExplainText; +} + +static void +windows_helptext_callback(pdh_metric_t *pmp, LPSTR pat, pdh_value_t *pvp) +{ + windows_inform_metric(pmp, pat, pvp, TRUE, windows_helptext_metric); +} + +int +windows_help(int ident, int type, char **buf, pmdaExt *pmda) +{ + pmID pmid = (pmID)ident; + int i; + + if ((type & PM_TEXT_PMID) != PM_TEXT_PMID) + return pmdaText(ident, type, buf, pmda); + + for (i = 0; i < metricdesc_sz; i++) + if (pmid == metricdesc[i].desc.pmid) + break; + if (i == metricdesc_sz) + return PM_ERR_PMID; + + if (type & PM_TEXT_ONELINE) { + if (metricdesc[i].pat[0] == '\0') + return pmdaText(ident, type, buf, pmda); + *buf = windows_fmt(strncpy(texts, &metricdesc[i].pat[0], sizeof(texts))); + } else { + text = NULL; + windows_visit_metric(&metricdesc[i], windows_helptext_callback); + if (!text) + return pmdaText(ident, type, buf, pmda); + *buf = windows_fmt(strncpy(texts, text, sizeof(texts))); + } + return 0; +} diff --git a/src/pmdas/windows/hypnotoad.h b/src/pmdas/windows/hypnotoad.h new file mode 100644 index 0000000..ea75430 --- /dev/null +++ b/src/pmdas/windows/hypnotoad.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008-2010 Aconex. All Rights Reserved. + * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#ifndef HYPNOTOAD_H +#define HYPNOTOAD_H + +#include "pmapi.h" +#include "impl.h" +#include "pmda.h" +#include "pdh.h" +#include "pdhmsg.h" +#include "domain.h" + +#define MAX_M_PATH_LEN 80 /* pattern passed to PdhExpandCounterPath */ +#define MAX_M_TEXT_LEN 512 /* longest long-text string that we allow */ +#define INDOM(x,y) (((x)<<22)|(y)) /* pmdaCache interfaces use indom */ + +enum { + DISK_INDOM, + CPU_INDOM, + NETIF_INDOM, + FILESYS_INDOM, + SQL_LOCK_INDOM, + SQL_CACHE_INDOM, + SQL_DB_INDOM, + PROCESS_INDOM, + THREAD_INDOM, + SQL_USER_INDOM, + NUMINDOMS +}; + +typedef enum { + V_NONE, + V_ERROR_SEEN = 0x1, + V_COLLECTED = 0x2, /* if PdhGetRawCounterValue was successful */ +} pdh_valueflags_t; + +typedef struct { + int inst; /* PM_IN_NULL or instance identifier */ + pdh_valueflags_t flags; + pmAtomValue atom; +} pdh_value_t; + +typedef enum { + M_NONE, + M_EXPANDED = 0x1, /* pattern has been expanded */ + M_REDO = 0x2, /* redo pattern expansion on each fetch */ + M_NOVALUES = 0x4, /* setup failed, don't bother with the fetch */ + M_OPTIONAL = 0x8, /* optional component, no values is expected */ + M_VERIFIED = 0x10, /* has this metrics semantics been checked */ + M_AUTO64 = 0x20, /* allow auto-modification on 64/32bit type */ +} pdh_metricflag_t; + +typedef struct { + pmDesc desc; /* metric descriptor */ + pdh_metricflag_t flags; /* state of this metric */ + int ctype; /* PDH counter type */ + int num_alloc; /* high water allocation mark */ + int num_vals; /* one or more metric values */ + pdh_value_t *vals; + char pat[MAX_M_PATH_LEN]; /* for PdhExpandCounterPath */ +} pdh_metric_t; + +extern pdh_metric_t metricdesc[]; +extern int metricdesc_sz; + +extern char *windows_uname; +extern char *windows_build; +extern char *windows_machine; +extern int windows_indom_setup[]; +extern int windows_indom_reset[]; +extern unsigned long windows_pagesize; +extern MEMORYSTATUSEX windows_memstat; +extern void windows_fetch_memstat(void); + +extern void windows_open(int); +extern int windows_indom_fixed(int); +extern char *pdherrstr(int); + +typedef void (*pdh_metric_inform_t)(pdh_metric_t *, PDH_COUNTER_INFO_A *); +typedef void (*pdh_metric_visitor_t)(pdh_metric_t *, LPSTR, pdh_value_t *); +extern int windows_visit_metric(pdh_metric_t *, pdh_metric_visitor_t); +extern int windows_inform_metric(pdh_metric_t *, LPTSTR, pdh_value_t *, + BOOLEAN, pdh_metric_inform_t); + +extern void windows_instance_refresh(pmInDom); +extern int windows_lookup_instance(char *, pdh_metric_t *); +extern void windows_fetch_refresh(int numpmid, pmID pmidlist[], pmdaExt *); +extern void windows_verify_callback(pdh_metric_t *, LPSTR, pdh_value_t *); + +extern int windows_help(int, int, char **, pmdaExt *); + +#endif /* HYPNOTOAD_H */ diff --git a/src/pmdas/windows/instance.c b/src/pmdas/windows/instance.c new file mode 100644 index 0000000..fbbb083 --- /dev/null +++ b/src/pmdas/windows/instance.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2008-2010 Aconex. All Rights Reserved. + * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * Parts of this file contributed by Ken McDonell + * (kenj At internode DoT on DoT net) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include "hypnotoad.h" +#include <ctype.h> + +int +windows_indom_fixed(int serial) +{ + return (serial != PROCESS_INDOM && serial != THREAD_INDOM); +} + +void +windows_instance_refresh(pmInDom indom) +{ + int i, index, setup; + + index = pmInDom_serial(indom); + windows_indom_reset[index] = 0; + setup = windows_indom_setup[index]; + + for (i = 0; i < metricdesc_sz; i++) { + pdh_metric_t *mp = &metricdesc[i]; + + if (indom != mp->desc.indom || mp->pat[0] != '\\') + continue; + if (!setup || (mp->flags & M_REDO)) + windows_visit_metric(mp, NULL); + break; + } + + /* Do we want to persist this instance domain to disk? */ + if (windows_indom_reset[index] && windows_indom_fixed(index)) + pmdaCacheOp(indom, PMDA_CACHE_SAVE); +} + +int +windows_lookup_instance(char *path, pdh_metric_t *mp) +{ + __pmInDom_int *ip; + static void *seen = (void *)0xfeedbabe; + void *sp; + char *p, *q, *name = NULL; + int sts, ok = 0; + + if (mp->desc.indom == PM_INDOM_NULL) + return PM_IN_NULL; + + ip = (__pmInDom_int *)&mp->desc.indom; + switch (ip->serial) { + /* + * Examples: + * \\WINBUILD\PhysicalDisk(0 C:)\Disk Reads/sec + * \\SOMEHOST\PhysicalDisk(0 C: D: E:)\Disk Transfers/sec + * \\WINBUILD\PhysicalDisk(_Total)\Disk Write Bytes/sec + */ + case DISK_INDOM: + p = strchr(path, '('); // skip hostname and metric name + if (p != NULL) { + p++; + if (strncmp(p, "_Total)", 7) == 0) { + /* + * The totals get enumerated in the per disk path + * expansion, just skip 'em here + */ + return -1; + } + while (isascii((int)*p) && isdigit((int)*p)) p++; + if (*p == ' ') { + p++; + q = strchr(p, ')'); + if (q != NULL) { + name = (char *)malloc(q - p + 1); + if (name != NULL) { + strncpy(name, p, q - p); + name[q - p] = '\0'; + ok = 1; + } + else { + __pmNotifyErr(LOG_ERR, "windows_check_instance: " + "Error: DISK_INDOM malloc[%d] failed " + "path=%s\n", q - p + 1, path); + return -1; + } + /* + * If more than one drive letter maps to the same + * logical disk (e.g. mirrored root),, the name + * contains spaces, e.g. + * "C: D:" ... replace ' ' by '_' to play by the + * PCP rules for instance names + */ + for (p = name; *p; p++) { + if (*p == ' ') *p = '_'; + } + } + } + } + /* + * expecting something like ...\PhysicalDisk(N name)... + * we will just have to ignore this one! (might be due + * to: http://support.microsoft.com/kb/974878 - fail as + * entries like "17" and "17#1" are not useable anyway) + */ + if (!ok) { + if (pmDebug & DBG_TRACE_LIBPMDA) + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "unrecognized disk instance: %s\n", path); + free(name); + return -1; + } + break; + + /* + * Examples: + * \\WINBUILD\Processor(0)\% User Time + * \\WINBUILD\Processor(_Total)\Interrupts/sec + */ + case CPU_INDOM: + p = strchr(path, '('); // skip hostname and metric name + if (p != NULL) { + p++; + if (strncmp(p, "_Total)", 7) == 0) { + /* + * The totals get enumerated in the per cpu path + * expansion, just skip 'em here + */ + return -1; + } + int inst = atoi(p); + name = (char *)malloc(8); // "cpuNNNN" + if (name != NULL) + sprintf(name, "cpu%d", inst); + ok = 1; + } + /* + * expecting something like ...\Processor(N)... + * don't know what to do with this one! + */ + if (!ok) { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "unrecognized cpu instance: %s\n", path); + free(name); + return -1; + } + break; + + /* + * Examples: + * \\WINNT\Network Interface(MS TCP Loopback interface)\Bytes Total/sec + */ + case NETIF_INDOM: + p = strchr(path, '('); // skip hostname and metric name + if (p != NULL) { + p++; + q = strchr(p, ')'); + if (q != NULL) { + name = (char *)malloc(q - p + 1); + if (name != NULL) { + strncpy(name, p, q - p); + name[q - p] = '\0'; + ok = 1; + } + else { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "malloc[%d] failed for NETIF_INDOM " + "path=%s\n", q - p + 1, path); + return -1; + } + /* + * The network interface names have many spaces and are + * not unique up to the first space by any means. So, + * replace ' 's to play by the PCP instance name rules. + */ + for (p = name; *p; p++) { + if (*p == ' ') *p = '_'; + } + } + } + /* + * expecting something like ...\Network Interface(...)... + * don't know what to do with this one! + */ + if (!ok) { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "unrecognized network interface instance: %s\n", path); + free(name); + return -1; + } + break; + + /* + * Examples: + * \\TOWER\LogicalDisk(C:)\% Free Space + */ + case FILESYS_INDOM: + p = strchr(path, '('); // skip hostname and metric name + if (p != NULL) { + p++; + if (strncmp(p, "_Total)", 7) == 0) { + /* + * The totals value makes no semantic sense, + * just skip it here + */ + return -1; + } + while (isascii((int)*p) && isdigit((int)*p)) + p++; + if (*p == ' ') + p++; + q = strchr(p, ')'); + if (q != NULL) { + name = (char *)malloc(q - p + 1); + if (name != NULL) { + strncpy(name, p, q - p); + name[q - p] = '\0'; + ok = 1; + } + else { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "malloc[%d] failed for LDISK_INDOM path=%s\n", + q - p + 1, path); + return -1; + } + } + } + /* + * expecting something like ...\LogicalDisk(C:)... + * don't know what to do with this one! + */ + if (!ok) { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "unrecognized logical disk instance: %s\n", path); + free(name); + return -1; + } + break; + + /* + * SQLServer instance domains all have similar syntax + * + * Examples: + * \\TOWER\SQLServer:Locks(Table)\Average Wait Time (ms) + * \\TOWER\SQLServer:Cache Manager(Cursors)\Cache Hit Ratio + * \\TOWER\SQLServer:Databases(ACONEX_SYS)\Transactions/sec + */ + case SQL_LOCK_INDOM: + case SQL_CACHE_INDOM: + case SQL_DB_INDOM: + case SQL_USER_INDOM: + p = strchr(path, '('); // skip hostname and metric name + if (p != NULL) { + p++; + if (strncmp(p, "_Total)", 7) == 0) { + /* + * The totals are done as independent metrics, + * just skip them here + */ + return -1; + } + q = strchr(p, ')'); + if (q != NULL) { + name = (char *)malloc(q - p + 1); + if (name != NULL) { + strncpy(name, p, q - p); + name[q - p] = '\0'; + ok = 1; + } + else { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "malloc[%d] failed, SQL_INDOM path=%s\n", + q - p + 1, path); + return -1; + } + + /* + * The user counter names have many spaces and are + * not unique up to the first space by any means. So, + * replace ' 's to play by the PCP instance name rules. + */ + if (ip->serial == SQL_USER_INDOM) { + for (p = name; *p; p++) + if (*p == ' ') *p = '_'; + } + } + } + /* + * expecting something like ... \SQLServer:...(...)\... + * don't know what to do with this one! + */ + if (!ok) { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "unrecognized SQLServer instance: %s\n", path); + free(name); + return -1; + } + break; + + /* + * Per-process and per-thread instance domain + * + * Examples: + * \\TOWER\Process(svchost#6)\% Processor Time + * \\TOWER\Thread(svchost/1#1)\% Processor Time + * \\TOWER\Thread(Idle/0)\ID Process + * \\TOWER\Thread(Idle/0)\ID Thread + */ + case PROCESS_INDOM: + case THREAD_INDOM: + p = strchr(path, '('); // skip hostname and Process/Thread + if (p != NULL) { + p++; + if ((strncmp(p, "_Total)", 7) == 0) || + (strncmp(p, "_Total/", 7) == 0)) { + /* + * The totals are done as independent metrics, + * just skip them here + */ + return -1; + } + q = strchr(p, ')'); + if (q != NULL) { + name = (char *)malloc(q - p + 1); + if (name != NULL) { + strncpy(name, p, q - p); + name[q - p] = '\0'; + ok = 1; + } + else { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "malloc[%d] failed, process/thread path=%s\n", + q - p + 1, path); + return -1; + } + } + } + /* + * expecting something like ... \Process(...)\... + * don't know what to do with this one! + */ + if (!ok) { + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "unrecognized process/thread name: %s\n", path); + free(name); + return -1; + } + break; + + default: + __pmNotifyErr(LOG_ERR, "windows_check_instance: Error: " + "pmInDom %s is unknown for metric %s\n", + pmInDomStr(mp->desc.indom), pmIDStr(mp->desc.pmid)); + return -1; + } + + sts = pmdaCacheLookupName(mp->desc.indom, name, &ok, &sp); + if (sts != PMDA_CACHE_ACTIVE) { + if (sp != seen) /* new instance, never seen before, mark it */ + windows_indom_reset[pmInDom_serial(mp->desc.indom)] = 1; + ok = pmdaCacheStore(mp->desc.indom, PMDA_CACHE_ADD, name, seen); + } + free(name); + return ok; +} diff --git a/src/pmdas/windows/open.c b/src/pmdas/windows/open.c new file mode 100644 index 0000000..65be00d --- /dev/null +++ b/src/pmdas/windows/open.c @@ -0,0 +1,769 @@ +/* + * Copyright (c) 2008-2010 Aconex. All Rights Reserved. + * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * Parts of this file contributed by Ken McDonell + * (kenj At internode DoT on DoT net) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "hypnotoad.h" +#include <winbase.h> + +#define roundup(x,y) ((((x) + ((y) - 1)) / (y)) * (y)) + +char *windows_uname; +char *windows_build; +char *windows_machine; +unsigned long windows_pagesize; +int windows_indom_setup[NUMINDOMS]; /* initial setup done on instance */ +int windows_indom_reset[NUMINDOMS]; /* instances changed on refresh */ + +/* + * This block of functionality is required to map counter types from + * their Windows semantics to equivalent PCP semantics. + */ + +static struct { + int type; + char *desc; +} ctypetab[] = { + { PERF_100NSEC_MULTI_TIMER, "PERF_100NSEC_MULTI_TIMER" }, + { PERF_100NSEC_MULTI_TIMER_INV, "PERF_100NSEC_MULTI_TIMER_INV" }, + { PERF_100NSEC_TIMER, "PERF_100NSEC_TIMER" }, + { PERF_100NSEC_TIMER_INV, "PERF_100NSEC_TIMER_INV" }, + { PERF_AVERAGE_BASE, "PERF_AVERAGE_BASE" }, + { PERF_AVERAGE_BULK, "PERF_AVERAGE_BULK" }, + { PERF_AVERAGE_TIMER, "PERF_AVERAGE_TIMER" }, + { PERF_COUNTER_100NS_QUEUELEN_TYPE, "PERF_COUNTER_100NS_QUEUELEN_TYPE" }, + { PERF_COUNTER_BULK_COUNT, "PERF_COUNTER_BULK_COUNT" }, + { PERF_COUNTER_COUNTER, "PERF_COUNTER_COUNTER" }, + { PERF_COUNTER_DELTA, "PERF_COUNTER_DELTA" }, + { PERF_COUNTER_LARGE_DELTA, "PERF_COUNTER_LARGE_DELTA" }, + { PERF_COUNTER_LARGE_QUEUELEN_TYPE, "PERF_COUNTER_LARGE_QUEUELEN_TYPE" }, + { PERF_COUNTER_LARGE_RAWCOUNT, "PERF_COUNTER_LARGE_RAWCOUNT" }, + { PERF_COUNTER_LARGE_RAWCOUNT_HEX, "PERF_COUNTER_LARGE_RAWCOUNT_HEX" }, + { PERF_COUNTER_MULTI_BASE, "PERF_COUNTER_MULTI_BASE" }, + { PERF_COUNTER_MULTI_TIMER, "PERF_COUNTER_MULTI_TIMER" }, + { PERF_COUNTER_MULTI_TIMER_INV, "PERF_COUNTER_MULTI_TIMER_INV" }, + { PERF_COUNTER_NODATA, "PERF_COUNTER_NODATA" }, + { PERF_COUNTER_QUEUELEN_TYPE, "PERF_COUNTER_QUEUELEN_TYPE" }, + { PERF_COUNTER_RAWCOUNT, "PERF_COUNTER_RAWCOUNT" }, + { PERF_COUNTER_RAWCOUNT_HEX, "PERF_COUNTER_RAWCOUNT_HEX" }, + { PERF_COUNTER_TEXT, "PERF_COUNTER_TEXT" }, + { PERF_COUNTER_TIMER, "PERF_COUNTER_TIMER" }, + { PERF_COUNTER_TIMER_INV, "PERF_COUNTER_TIMER_INV" }, + { PERF_ELAPSED_TIME, "PERF_ELAPSED_TIME" }, + { PERF_LARGE_RAW_BASE, "PERF_LARGE_RAW_BASE" }, + { PERF_OBJ_TIME_TIMER, "PERF_OBJ_TIME_TIMER" }, + { PERF_PRECISION_100NS_TIMER, "PERF_PRECISION_100NS_TIMER" }, + { PERF_PRECISION_OBJECT_TIMER, "PERF_PRECISION_OBJECT_TIMER" }, + { PERF_PRECISION_SYSTEM_TIMER, "PERF_PRECISION_SYSTEM_TIMER" }, + { PERF_RAW_BASE, "PERF_RAW_BASE" }, + { PERF_RAW_FRACTION, "PERF_RAW_FRACTION" }, + { PERF_LARGE_RAW_FRACTION, "PERF_LARGE_RAW_FRACTION" }, + { PERF_SAMPLE_BASE, "PERF_SAMPLE_BASE" }, + { PERF_SAMPLE_COUNTER, "PERF_SAMPLE_COUNTER" }, + { PERF_SAMPLE_FRACTION, "PERF_SAMPLE_FRACTION" } +}; + +static int ctypetab_sz = sizeof(ctypetab) / sizeof(ctypetab[0]); + +static char * +decode_ctype(DWORD ctype) +{ + static char unknown[20]; + int i; + + for (i = 0; i < ctypetab_sz; i++) + if (ctype == ctypetab[i].type) + return ctypetab[i].desc; + sprintf(unknown, "0x%08x unknown", (int)ctype); + return unknown; +} + +static char * +string_append(char *name, char *suff) +{ + if (name == NULL) { + name = (char *)strdup(suff); + } + else { + name = (char *)realloc(name, strlen(name)+strlen(suff)+1); + strcat(name, suff); + } + return name; +} + +static char * +_semstr(int sem) +{ + static char msg[20]; + if (sem == PM_SEM_COUNTER) + return "COUNTER"; + else if (sem == PM_SEM_INSTANT) + return "INSTANT"; + else if (sem == PM_SEM_DISCRETE) + return "DISCRETE"; + else { + sprintf(msg, "UNKNOWN! (%d)", sem); + return msg; + } +} + +static char * +_typestr(int type) +{ + static char msg[20]; + if (type == PM_TYPE_32) + return "PM_TYPE_32"; + else if (type == PM_TYPE_U32) + return "PM_TYPE_U32"; + else if (type == PM_TYPE_64) + return "PM_TYPE_64"; + else if (type == PM_TYPE_U64) + return "PM_TYPE_U64"; + else if (type == PM_TYPE_FLOAT) + return "PM_TYPE_FLOAT"; + else if (type == PM_TYPE_DOUBLE) + return "PM_TYPE_DOUBLE"; + else { + sprintf(msg, "UNKNOWN! (%d)", type); + return msg; + } +} + +#if 0 // debugging +static char * +_ctypestr(int ctype) +{ + if (ctype == PERF_COUNTER_COUNTER) + return "PERF_COUNTER_COUNTER"; + else if (ctype == PERF_RAW_FRACTION) + return "PERF_RAW_FRACTION"; + else if (ctype == PERF_LARGE_RAW_FRACTION) + return "PERF_LARGE_RAW_FRACTION"; + else if (ctype == PERF_COUNTER_LARGE_RAWCOUNT_HEX) + return "PERF_COUNTER_LARGE_RAWCOUNT_HEX"; + else if (ctype == PERF_COUNTER_LARGE_RAWCOUNT) + return "PERF_COUNTER_LARGE_RAWCOUNT"; + else if (ctype == PERF_PRECISION_100NS_TIMER) + return "PERF_PRECISION_100NS_TIMER"; + else if (ctype == PERF_100NSEC_TIMER) + return "PERF_100NSEC_TIMER"; + else if (ctype == PERF_COUNTER_BULK_COUNT) + return "PERF_COUNTER_BULK_COUNT"; + else if (ctype == PERF_COUNTER_RAWCOUNT_HEX) + return "PERF_COUNTER_RAWCOUNT_HEX"; + else if (ctype == PERF_COUNTER_RAWCOUNT) + return "PERF_COUNTER_RAWCOUNT"; + else if (ctype == PERF_COUNTER_COUNTER) + return "PERF_COUNTER_COUNTER"; + else + return "UNKNOWN"; +} +#endif + +/* + * Based on documentation from ... + * http://msdn.microsoft.com/library/default.asp? + * url=/library/en-us/sysinfo/base/osversioninfoex_str.asp + */ +static void +windows_format_uname(OSVERSIONINFOEX osv) +{ + char tbuf[80]; + char *name = NULL; + + switch (osv.dwPlatformId) { + case VER_PLATFORM_WIN32_NT: + if (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 1) { + if (osv.wProductType == VER_NT_WORKSTATION) + name = string_append(name, "Windows 7"); + else + name = string_append(name, "Windows Server 2008 R2"); + } + else if (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0) { + if (osv.wProductType == VER_NT_WORKSTATION) + name = string_append(name, "Windows Vista"); + else + name = string_append(name, "Windows Server 2008"); + } + else if (osv.dwMajorVersion == 5 && osv.dwMinorVersion == 2) + name = string_append(name, "Windows Server 2003"); + else if (osv.dwMajorVersion == 5 && osv.dwMinorVersion == 1) + name = string_append(name, "Windows XP"); + else if (osv.dwMajorVersion == 5 && osv.dwMinorVersion == 0) + name = string_append(name, "Windows 2000"); + else if (osv.dwMajorVersion <= 4) + name = string_append(name, "Windows NT"); + else { + sprintf(tbuf, "Windows Unknown (%ld.%ld)", + osv.dwMajorVersion, osv.dwMinorVersion); + name = string_append(name, tbuf); + } + + /* service pack and build number etc */ + if (osv.szCSDVersion[0] != '\0') { + name = string_append(name, " "); + name = string_append(name, osv.szCSDVersion); + } + sprintf(tbuf, " Build %ld", osv.dwBuildNumber & 0xFFFF); + windows_build = name + strlen(name) + 1; + windows_uname = string_append(name, tbuf); + break; + + default: + windows_uname = "Windows - Platform Unknown"; + windows_build = "Unknown Build"; + break; + } +} + +void +windows_setup_globals(void) +{ + SYSTEM_INFO sysinfo; + OSVERSIONINFOEX osversion; + + ZeroMemory(&sysinfo, sizeof(SYSTEM_INFO)); + GetSystemInfo(&sysinfo); + windows_pagesize = sysinfo.dwPageSize; + + switch (sysinfo.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: + windows_machine = "x86_64"; + break; + case PROCESSOR_ARCHITECTURE_IA64: + windows_machine = "ia64"; + break; + case PROCESSOR_ARCHITECTURE_INTEL: + windows_machine = "i686"; + break; + default: + windows_machine = "Unknown"; + break; + } + + ZeroMemory(&osversion, sizeof(OSVERSIONINFOEX)); + osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + GetVersionEx((OSVERSIONINFO *)&osversion); + windows_format_uname(osversion); +} + +static void +windows_verify_metric(pdh_metric_t *mp, PDH_COUNTER_INFO_A *infop) +{ + char *ctr_type; + + mp->ctype = infop->dwType; + + switch (mp->ctype) { + /* + * Pdh metric sematics ... from WinPerf.h + * + * SIZE + * DWORD 32-bit + * LARGE 64-bit + * ZERO no support here + * VARIABLE_LEN no support here + * + * TYPE + * NUMBER PM_SEM_INSTANT + * HEX display in hex (no support here) + * DECIMAL display as decimal + * DEC_1000 display as value / 1000 + * (no support here) + * COUNTER PM_SEM_COUNTER + * VALUE display value (no support here) + * RATE time rate converted + * FRACTION divide value by BASE + * BASE used for FRACTION + * QUEUELEN magic internal queuelen() routines + * (you're joking, right?) + * HISTOGRAM counter begins or ends a histo (?) + * (definitely no support here) + * PRECISION divide counter by private clock (?) + * (definitely no support here) + * TEXT no support here + * ZERO no support here + */ + + /* + * Known 32-bit counters + */ + case PERF_COUNTER_COUNTER: + /* 32-bit PM_SEM_COUNTER */ + if (mp->desc.type != PM_TYPE_32 && mp->desc.type != PM_TYPE_U32) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, + "windows_open: PERF_COUNTER_COUNTER: " + "metric %s: rewrite type from %s to PM_TYPE_U32\n", + pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_U32; + } + if (mp->desc.sem != PM_SEM_COUNTER) { + __pmNotifyErr(LOG_ERR, "windows_open: PERF_COUNTER_COUNTER: " + "metric %s: semantics %s (expected %s)\n", + pmIDStr(mp->desc.pmid), _semstr(mp->desc.sem), + _semstr(PM_SEM_COUNTER)); + } + break; + + case PERF_COUNTER_RAWCOUNT: + case PERF_COUNTER_RAWCOUNT_HEX: + if (mp->ctype == PERF_COUNTER_RAWCOUNT) + ctr_type = "PERF_COUNTER_RAWCOUNT"; + else + ctr_type = "PERF_COUNTER_RAWCOUNT_HEX"; + /* 32-bit PM_SEM_INSTANT or PM_SEM_DISCRETE */ + if (mp->desc.type != PM_TYPE_32 && mp->desc.type != PM_TYPE_U32) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, + "windows_open: Warning: %s: metric %s: " + "rewrite type from %s to PM_TYPE_U32\n", + ctr_type, pmIDStr(mp->desc.pmid), + _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_U32; + } + break; + + /* + * Known 64-bit counters + */ + case PERF_COUNTER_BULK_COUNT: + /* 64-bit PM_SEM_COUNTER */ + if (mp->desc.type != PM_TYPE_64 && mp->desc.type != PM_TYPE_U64) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, + "windows_open: PERF_COUNTER_BULK_COUNT:" + " metric %s: rewrite type from %s to PM_TYPE_U64\n", + pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_U64; + } + if (mp->desc.sem != PM_SEM_COUNTER) { + __pmNotifyErr(LOG_ERR, "windows_open: PERF_COUNTER_BULK_COUNT:" + " metric %s: semantics %s (expected %s)\n", + pmIDStr(mp->desc.pmid), _semstr(mp->desc.sem), + _semstr(PM_SEM_COUNTER)); + mp->desc.sem = PM_SEM_COUNTER; + } + break; + + case PERF_100NSEC_TIMER: + case PERF_PRECISION_100NS_TIMER: + if (mp->ctype == PERF_100NSEC_TIMER) + ctr_type = "PERF_100NSEC_TIMER"; + else + ctr_type = "PERF_PRECISION_100NS_TIMER"; + /* + * 64-bit PM_SEM_COUNTER, units are 100's of nanosecs, + * we shall export 'em as microseconds + */ + if (mp->desc.type != PM_TYPE_64 && mp->desc.type != PM_TYPE_U64) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s: " + "metric %s: rewrite type from %s to PM_TYPE_U64\n", + ctr_type, pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_U64; + } + if (mp->desc.sem != PM_SEM_COUNTER) { + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s: " + "metric %s: semantics %s (expected %s)\n", + ctr_type, pmIDStr(mp->desc.pmid), _semstr(mp->desc.sem), + _semstr(PM_SEM_COUNTER)); + mp->desc.sem = PM_SEM_COUNTER; + } + if (mp->desc.units.dimSpace != 0 || + mp->desc.units.dimTime != 1 || + mp->desc.units.dimCount != 0 || + mp->desc.units.scaleTime != PM_TIME_USEC) { + pmUnits units = mp->desc.units; + mp->desc.units.dimSpace = mp->desc.units.dimCount = 0; + mp->desc.units.scaleSpace = mp->desc.units.scaleCount = 0; + mp->desc.units.dimTime = 1; + mp->desc.units.scaleTime = PM_TIME_USEC; + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s: " + "metric %s: rewrite dimension and scale from %s to %s", + ctr_type, pmIDStr(mp->desc.pmid), pmUnitsStr(&units), + pmUnitsStr(&mp->desc.units)); + } + break; + + case PERF_COUNTER_LARGE_RAWCOUNT: + case PERF_COUNTER_LARGE_RAWCOUNT_HEX: + /* 64-bit PM_SEM_INSTANT or PM_SEM_DISCRETE */ + if (mp->desc.type != PM_TYPE_64 && + mp->desc.type != PM_TYPE_U64) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, "windows_open: Warning: " + "PERF_COUNTER_LARGE_RAWCOUNT: metric %s: " + "rewrite type from %s to PM_TYPE_U64\n", + pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_U64; + } + break; + + case PERF_RAW_FRACTION: + /* Float PM_SEM_INSTANT or PM_SEM_DISCRETE */ + if (mp->desc.type != PM_TYPE_FLOAT) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, "windows_open: Warning: " + "PERF_RAW_FRACTION: metric %s: " + "rewrite type from %s to PM_TYPE_FLOAT\n", + pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_FLOAT; + } + break; + + case PERF_LARGE_RAW_FRACTION: + /* Double PM_SEM_INSTANT or PM_SEM_DISCRETE */ + if (mp->desc.type != PM_TYPE_DOUBLE) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, "windows_open: Warning: " + "PERF_LARGE_RAW_FRACTION: metric %s: " + "rewrite type from %s to PM_TYPE_DOUBLE\n", + pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_DOUBLE; + } + break; + + case PERF_AVERAGE_BULK: + case PERF_AVERAGE_TIMER: + if (mp->ctype == PERF_AVERAGE_BULK) + ctr_type = "PERF_AVERAGE_BULK"; + else + ctr_type = "PERF_AVERAGE_TIMER"; + /* 64-bit PM_SEM_INSTANT or PM_SEM_DISCRETE */ + if (mp->desc.sem != PM_SEM_INSTANT && mp->desc.sem != PM_SEM_DISCRETE) { + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s: " + "metric %s: semantics %s (expected %s)\n", + ctr_type, pmIDStr(mp->desc.pmid), + _semstr(mp->desc.sem), _semstr(PM_SEM_INSTANT)); + mp->desc.sem = PM_SEM_INSTANT; + } + if (mp->desc.type != PM_TYPE_64 && mp->desc.type != PM_TYPE_U64) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s " + "metric %s: rewrite type from %s to PM_TYPE_U64\n", + ctr_type, pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_U64; + } + break; + + case PERF_SAMPLE_COUNTER: + ctr_type = "PERF_SAMPLE_COUNTER"; + /* floating point PM_SEM_INSTANT or PM_SEM_DISCRETE */ + if (mp->desc.sem != PM_SEM_INSTANT && mp->desc.sem != PM_SEM_DISCRETE) { + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s: " + "metric %s: semantics %s (expected %s)\n", + ctr_type, pmIDStr(mp->desc.pmid), + _semstr(mp->desc.sem), _semstr(PM_SEM_INSTANT)); + mp->desc.sem = PM_SEM_INSTANT; + } + if (mp->desc.type != PM_TYPE_FLOAT && mp->desc.type != PM_TYPE_DOUBLE) { + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s " + "metric %s: rewrite type from %s to PM_TYPE_FLOAT\n", + ctr_type, pmIDStr(mp->desc.pmid), _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_FLOAT; + } + break; + + case PERF_ELAPSED_TIME: + ctr_type = "PERF_ELAPSED_TIME"; + if (mp->desc.units.dimSpace != 0 || + mp->desc.units.dimTime != 1 || + mp->desc.units.dimCount != 0) { + pmUnits units = mp->desc.units; + mp->desc.units.dimSpace = mp->desc.units.dimCount = 0; + mp->desc.units.scaleSpace = mp->desc.units.scaleCount = 0; + mp->desc.units.dimTime = 1; + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s: " + "metric %s: rewrite dimension and scale from %s to %s", + ctr_type, pmIDStr(mp->desc.pmid), pmUnitsStr(&units), + pmUnitsStr(&mp->desc.units)); + } + if (mp->desc.type != PM_TYPE_64 && mp->desc.type != PM_TYPE_U64) { + if (!(mp->flags & M_AUTO64)) + __pmNotifyErr(LOG_ERR, "windows_open: Warning: %s " + "metric %s: rewrite type from %s to PM_TYPE_U64\n", + ctr_type, pmIDStr(mp->desc.pmid), + _typestr(mp->desc.type)); + mp->desc.type = PM_TYPE_U64; + } + break; + + default: + __pmNotifyErr(LOG_ERR, "windows_open: Warning: metric %s: " + "unexpected counter type: %s\n", + pmIDStr(mp->desc.pmid), decode_ctype(infop->dwType)); + } + mp->flags |= M_EXPANDED; +} + +int +windows_inform_metric(pdh_metric_t *pmp, LPTSTR p, pdh_value_t *pvp, + BOOLEAN getExplainText, pdh_metric_inform_t informer) +{ + int sts = -1; + PDH_STATUS pdhsts; + PDH_HQUERY queryhdl = NULL; + PDH_HCOUNTER counterhdl = NULL; + DWORD result_sz; + static DWORD info_sz = 0; + static LPSTR info = NULL; + + pdhsts = PdhOpenQueryA(NULL, 0, &queryhdl); + if (pdhsts != ERROR_SUCCESS) { + __pmNotifyErr(LOG_ERR, "windows_open: PdhOpenQueryA failed: %s\n", + pdherrstr(pdhsts)); + return sts; + } + + pdhsts = PdhAddCounterA(queryhdl, p, pvp->inst, &counterhdl); + if (pdhsts != ERROR_SUCCESS) { + __pmNotifyErr(LOG_ERR, "windows_open: Warning: PdhAddCounterA " + "@ pmid=%s pat=\"%s\": %s\n", + pmIDStr(pmp->desc.pmid), p, pdherrstr(pdhsts)); + PdhCloseQuery(queryhdl); + return sts; + } + + /* + * check PCP metric semantics against PDH info + */ + if (info_sz == 0) { + /* + * We've observed an initial call to PdhGetCounterInfoA() + * hang with a zero sized buffer ... pander to this with + * an initial buffer allocation ... (size is a 100% guess). + */ + info_sz = 256; + if ((info = (LPSTR)malloc(info_sz)) == NULL) { + __pmNotifyErr(LOG_ERR, "windows_open: PdhGetCounterInfoA " + "malloc (%d) failed @ metric %s: ", + (int)info_sz, pmIDStr(pmp->desc.pmid)); + goto done; + } + } + result_sz = info_sz; + pdhsts = PdhGetCounterInfoA(counterhdl, getExplainText, &result_sz, + (PDH_COUNTER_INFO_A *)info); + if (pdhsts == PDH_MORE_DATA) { + info_sz = result_sz; + if ((info = (LPSTR)realloc(info, info_sz)) == NULL) { + __pmNotifyErr(LOG_ERR, "windows_open: PdhGetCounterInfoA " + "realloc (%d) failed @ metric %s: ", + (int)info_sz, pmIDStr(pmp->desc.pmid)); + goto done; + } + pdhsts = PdhGetCounterInfoA(counterhdl, getExplainText, &result_sz, + (PDH_COUNTER_INFO_A *)info); + } + if (pdhsts != ERROR_SUCCESS) { + __pmNotifyErr(LOG_ERR, "windows_open: PdhGetCounterInfoA " + "failed @ metric %s: %s\n", + pmIDStr(pmp->desc.pmid), pdherrstr(pdhsts)); + goto done; + } + else { + informer(pmp, (PDH_COUNTER_INFO_A *)info); + sts = 0; + } + +done: + PdhRemoveCounter(counterhdl); + PdhCloseQuery(queryhdl); + return sts; +} + +void +windows_verify_callback(pdh_metric_t *pmp, LPSTR pat, pdh_value_t *pvp) +{ + int v; + + if (!(pmp->flags & M_VERIFIED)) { + v = windows_inform_metric(pmp, pat, pvp, FALSE, windows_verify_metric); + if (v == 0) + pmp->flags |= M_VERIFIED; + } +} + + +/* + * General purpose metric regex iterator, call out on each instance + */ +int +windows_visit_metric(pdh_metric_t *pmp, pdh_metric_visitor_t visitor) +{ + size_t size; + int index = 0; + PDH_STATUS pdhsts; + DWORD result_sz; + static DWORD pattern_sz = 0; + static LPSTR pattern = NULL; + LPSTR p; + + if (pmp->desc.indom != PM_INDOM_NULL) { + index = pmInDom_serial(pmp->desc.indom); + pmdaCacheOp(pmp->desc.indom, PMDA_CACHE_INACTIVE); + } + + pmp->flags &= ~(M_EXPANDED|M_NOVALUES); + memset(pmp->vals, 0, pmp->num_alloc * sizeof(pdh_value_t)); + pmp->num_vals = 0; + + result_sz = 0; + pdhsts = PdhExpandCounterPathA(pmp->pat, NULL, &result_sz); + if (pdhsts == PDH_MORE_DATA) { + if (result_sz >= pattern_sz) { + pattern_sz = roundup(result_sz, 64); + if ((pattern = (LPSTR)realloc(pattern, pattern_sz)) == NULL) { + __pmNotifyErr(LOG_ERR, "windows_open: PdhExpandCounterPathA " + "realloc (%ld) failed @ metric %s: ", + pattern_sz, pmIDStr(pmp->desc.pmid)); + return -1; + } + } + result_sz = pattern_sz; + pdhsts = PdhExpandCounterPathA(pmp->pat, pattern, &result_sz); + } + if (pdhsts != PDH_CSTATUS_VALID_DATA) { + if (pmp->pat[0] != '\\') { + /* + * Skip metrics that are derived and do not have an explicit + * PDH API retrieval needed ... do nothing here. + */ + ; + } + else if (pmp->flags & M_OPTIONAL) { + pmp->flags |= M_NOVALUES; + return 0; + } + else { + __pmNotifyErr(LOG_ERR, "windows_open: PdhExpandCounterPathA " + "failed @ metric pmid=%s pattern=\"%s\": %s\n", + pmIDStr(pmp->desc.pmid), pmp->pat, pdherrstr(pdhsts)); + } + pmp->flags |= M_NOVALUES; + return -1; + } + + /* + * PdhExpandCounterPathA is apparently busted ... the length + * returned includes one byte _after_ the last NULL byte + * string terminator, but the final byte is apparently + * not being set ... force the issue + */ + pattern[result_sz-1] = '\0'; + for (p = pattern; *p; p += lstrlen(p) + 1) { + pdh_value_t *pvp; + + pmp->num_vals++; + if (pmp->num_vals > pmp->num_alloc) { + size = pmp->num_vals * sizeof(pdh_value_t); + if ((pmp->vals = (pdh_value_t *)realloc(pmp->vals, size)) == NULL) { + __pmNotifyErr(LOG_ERR, "windows_open: Error: values realloc " + "(%d x %d) failed @ metric %s [%s]: ", + pmp->num_vals, sizeof(pdh_value_t), + pmIDStr(pmp->desc.pmid), p); + pmp->num_alloc = 0; + return -1; + } + pmp->num_alloc = pmp->num_vals; + } + + pvp = &pmp->vals[pmp->num_vals-1]; + if (pmp->desc.indom == PM_INDOM_NULL) { + /* singular instance */ + pvp->inst = PM_IN_NULL; + if (pmp->num_vals > 1) { + char *q; + int k; + + /* + * report only once per pattern + */ + __pmNotifyErr(LOG_ERR, "windows_open: Warning: singular " + "metric %s has more than one instance ...\n", + pmIDStr(pmp->desc.pmid)); + fprintf(stderr, " pattern: \"%s\"\n", pmp->pat); + for (k = 0, q = pattern; *q; q += lstrlen(q) + 1, k++) + fprintf(stderr, " match[%d]: \"%s\"\n", k, q); + fprintf(stderr, "... skip this counter\n"); + + /* next realloc() will be a NOP */ + pmp->num_vals--; + + /* no more we can do here, onto next metric-pattern */ + break; + } + } + else { + /* + * if metric has instance domain, parse pattern using + * indom type to extract instance name and number, and + * add into indom cache data structures as needed. + */ + if ((pvp->inst = windows_lookup_instance(p, pmp)) < 0) { + /* + * error reported in windows_check_instance() ... + * we cannot return any values for this instance if + * we don't recognize the name ... skip this one, + * the next realloc() (if any) will be a NOP + */ + pmp->num_vals--; + + /* move onto next instance */ + continue; + } + windows_indom_setup[index] = 1; + } + + if (visitor) + visitor(pmp, p, pvp); + } + + return 0; +} + +void +windows_open(int domain) +{ + int i; + + windows_setup_globals(); + + for (i = 0; i < NUMINDOMS; i++) { + if (windows_indom_fixed(i)) + pmdaCacheOp(INDOM(domain, i), PMDA_CACHE_LOAD); + windows_indom_reset[i] = 0; + } + + /* + * This initialisation can take a long time - we have many metrics + * now for Windows. Better to delay this until we need to do it, + * and then only for the metrics needed. However, we cannot delay + * for those metrics that may change descriptors depending on the + * type of platform (64/32 bit, kernel version, etc), so those we + * verify up-front. + */ + for (i = 0; i < metricdesc_sz; i++) { + if ((metricdesc[i].flags & M_AUTO64) || (pmDebug & DBG_TRACE_LIBPMDA)) + windows_visit_metric(&metricdesc[i], windows_verify_callback); + } + + for (i = 0; i < NUMINDOMS; i++) { + /* Do we want to persist this instance domain to disk? */ + if (windows_indom_reset[i] && windows_indom_fixed(i)) + pmdaCacheOp(INDOM(domain, i), PMDA_CACHE_SAVE); + } +} diff --git a/src/pmdas/windows/pdhlist.c b/src/pmdas/windows/pdhlist.c new file mode 100644 index 0000000..387f139 --- /dev/null +++ b/src/pmdas/windows/pdhlist.c @@ -0,0 +1,85 @@ +/* + * List Windows performance counters on the current platform. + * + * Copyright (c) 2006, Ken McDonell. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <windows.h> +#include <pdh.h> +#include <pdhmsg.h> +#include <stdio.h> +#include <stdlib.h> + +static int verbose; +extern char *pdherrstr(int); +#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + +void +expand(char *pat) +{ + LPTSTR ptr; + LPSTR buf = NULL; + DWORD bufsz = 0; + int i; + PDH_STATUS pdhsts; + + // Iterate because size grows in first couple of attempts! + for (i = 0; i < 5; i++) { + if (bufsz && (buf = (LPSTR)malloc(bufsz)) == NULL) { + fprintf(stderr, "malloc %ld failed for pattern: %s\n", bufsz, pat); + return; + } + if (verbose) + fprintf(stderr, "ExpandCounters pattern: %s\n", pat); + if ((pdhsts = PdhExpandCounterPathA(pat, buf, &bufsz)) == PDH_MORE_DATA) { + // bufsz has the required length (minus the last NULL) + bufsz = roundup(bufsz + 1, 64); + free(buf); + } + else + break; + } + + if (pdhsts == PDH_CSTATUS_VALID_DATA) { + // success, print all counters + ptr = buf; + while (*ptr) { + printf("%s\n", ptr); + ptr += strlen(ptr) + 1; + } + } + else { + fprintf(stderr, "PdhExpandCounterPathA failed: %s\n", pdherrstr(pdhsts)); + if (pdhsts == PDH_MORE_DATA) + fprintf(stderr, "still need to resize buffer to %ld\n", bufsz); + } + + fflush(stderr); + fflush(stdin); +} + +int +main(int argc, char **argv) +{ + int i; + + if (argc == 1) { + expand("\\*\\*"); + expand("\\*(*)\\*"); + return 0; + } + + for (i = 1; i < argc; i++) + expand(argv[i]); + return 0; +} diff --git a/src/pmdas/windows/pdhmatch.sh b/src/pmdas/windows/pdhmatch.sh new file mode 100644 index 0000000..33c2e98 --- /dev/null +++ b/src/pmdas/windows/pdhmatch.sh @@ -0,0 +1,192 @@ +#!/bin/sh +# +# take the output from pdhlist.exe +# - remove hostname +# - collapse known instance domains to a symbolic representation +# - match up against patterns in data.c +# + +#debug# tmp=/var/tmp/$$ +#debug# trap "rm -f $tmp.*; exit 0" 0 1 2 3 15 +tmp=`pwd`/tmp + +# Examples of instance domains to collapse from pdhlist.exe +# output +# +# SQLServer:Buffer Partition(0)\Free pages +# Job Object Details(Winlogon Job 0-57c89/logon.scr)\% User Time +# Job Object Details(Winlogon Job 0-57c89/_Total)\% User Time +# Job Object Details(WmiProviderSubSystemHostJob/wmiprvse)\% User Time +# Job Object Details(WmiProviderSubSystemHostJob/_Total)\% User Time +# [not] Job Object Details(_Total/_Total)\% User Time +# Job Object(WmiProviderSubSystemHostJob)\Current % User Mode Time +# [not] Job Object(_Total)\Current % User Mode Time +# Thread(Idle/0)\Context Switches/sec +# Thread(csrss/0#1)\Context Switches/sec +# LogicalDisk(C:)\% Free Space +# [not] LogicalDisk(_Total)\% Free Space +# Network Interface(Intel[R] PRO_1000 MT Dual Port Network # Connection _2)\Bytes Received/sec +# PhysicalDisk(0 C:)\% Disk Read Time +# [not] PhysicalDisk(_Total)\% Disk Read Time +# Print Queue(Canon LBP-3260 PCL6 on SCRIBE (from LUKE) in session 1)\Add Network Printer Calls +# [not] Print Queue(_Total)\Add Network Printer Calls +# Process(Idle)\% Privileged Time +# [not] Process(_Total)\% Privileged Time +# Processor(0)\% Idle Time +# [not] Processor(_Total)\% Idle Time +# RAS Port(LPT1)\Alignment Errors +# SQLServer:Databases(alice)\Active Transactions +# [not] SQLServer:Databases(_Total)\Active Transactions +# SQLServer:Locks(Database)\Average Wait Time (ms) +# [not] SQLServer:Locks(_Total)\Lock Requests/sec +# Server Work Queues(3)\Active Threads +# SQLServer:Cache Manager(Adhoc Sql Plans)\Cache Hit Ratio +# Terminal Services Session(Console)\% Privileged Time +# + +if [ $# -eq 1 ] +then + cat $1 +elif [ $# -eq 0 ] +then + cat +else + echo "Usage: $0 [output-file-from-pdhlist]" >&2 + exit 1 +fi \ +| dos2unix \ +| sed >$tmp.tmp \ + -e 's/^\\\\[^\]*\\//' \ + -e '/^SQLServer:Buffer Partition(/s/([0-9]*)\\/(<n>)\\/' \ + -e '/^Job Object Details(/{ +/(_Total\//!s/(.*\/_Total)\\/(<job>\/_Total)\\/ +/\/_Total)/!s/(.*\/.*)\\/(<job>\/<?>)\\/ +}' \ + -e '/^Job Object(/{ +/(_Total)/!s/(.*)\\/(<job>)\\/ +}' \ + -e '/^Thread(/{ +s/([^/]*\/[0-9]*)\\/(<name>\/<pid>)\\/ +s/([^/]*\/[0-9]*#[0-9]*)\\/(<name>\/<pid>#<tid>)\\/ +}' \ + -e '/^LogicalDisk(/s/([A-Z]:)\\/(<drive>)\\/' \ + -e '/^Network Interface(/s/([^)]*)\\/(<if>)\\/' \ + -e '/^PhysicalDisk(/s/([0-9][0-9]* [A-Z]:)\\/(<dev>)\\/' \ + -e '/^Print Queue(/{ +/(_Total)/!s/(.*)\\/(<queue>)\\/ +}' \ + -e '/^Process(/{ +/(_Total)/!s/(.*)\\/(<pname>)\\/ +}' \ + -e '/^Processor(/{ +/(_Total)/!s/(.*)\\/(<cpu>)\\/ +}' \ + -e '/^RAS Port(/s/(.*)\\/(<port>)\\/' \ + -e '/^SQLServer:Databases(/{ +/(_Total)/!s/(.*)\\/(<db>)\\/ +}' \ + -e '/^SQLServer:Locks(/{ +/(_Total)/!s/(.*)\\/(<type>)\\/ +}' \ + -e '/^Server Work Queues(/s/(.*)\\/(<queue>)\\/' \ + -e '/^SQLServer:Cache Manager(/s/(.*)\\/(<cache>)\\/' \ + -e '/^Terminal Services Session(/s/(.*)\\/(<tty>)\\/' + +# This step tries to deal with this class of cases ... +# pdhlist reports stuff like +# SQLServer:Locks\Average Wait Time (ms) +# SQLServer:Locks(_Total)\Average Wait Time (ms) +# SQLServer:Locks(*/*#*)\Average Wait Time (ms) +# but the first one is in fact bogus (only the second 2 forms +# can be looked up. +# +sed <$tmp.tmp \ + -e '/^.NET CLR Exceptions\\/d' \ + -e '/^.NET CLR Interop\\/d' \ + -e '/^.NET CLR Jit\\/d' \ + -e '/^.NET CLR Loading\\/d' \ + -e '/^.NET CLR LocksAndThreads\\/d' \ + -e '/^.NET CLR Memory\\/d' \ + -e '/^.NET CLR Remoting\\/d' \ + -e '/^.NET CLR Security\\/d' \ + -e '/^NBT Connection\\/d' \ + -e '/^Paging File\\/d' \ + -e '/^SQLServer:User Settable\\/d' \ + -e '/^Server Work Queues\\/d' \ + -e '/^SQLServer:Buffer Partition\\/d' \ + -e '/^Job Object Details\\/d' \ + -e '/^Job Object\\/d' \ + -e '/^Thread\\/d' \ + -e '/^LogicalDisk\\/d' \ + -e '/^Network Interface\\/d' \ + -e '/^PhysicalDisk\\/d' \ + -e '/^Print Queue\\/d' \ + -e '/^Process\\/d' \ + -e '/^Processor\\/d' \ + -e '/^RAS Port\\/d' \ + -e '/^SQLServer:Databases\\/d' \ + -e '/^SQLServer:Locks\\/d' \ +| LC_COLLATE=POSIX sort \ +| uniq >$tmp.munged + +# extract patterns from PMDA source +# +if [ -f data.c ] +then + sed -n <data.c \ + -e '/"\\\\/{ +s/"[ ]*$// +s/.*"// +s/\\\\/\\/g +s/^\\// +p +}' \ + | sed \ + -e '/^Network Interface(/s/(\*\/\*#\*)\\/(<if>)\\/' \ + -e '/^PhysicalDisk(/s/(\*\/\*#\*)\\/(<dev>)\\/' \ + -e '/^Processor(/s/(\*\/\*#\*)\\/(<cpu>)\\/' \ + -e '/^SQLServer:Locks(/s/(\*\/\*#\*)\\/(<type>)\\/' \ + -e '/^LogicalDisk(/s/(\*\/\*#\*)\\/(<drive>)\\/' \ + | LC_COLLATE=POSIX sort \ + | uniq >$tmp.pmda + +else + echo "Warning: no data.c, cannot match metrics up with PMDA patterns" >&2 + sed -e 's/^/? /' <$tmp.munged +fi + +# match 'em up +# + +comm -23 $tmp.pmda $tmp.munged >$tmp.tmp +if [ -s $tmp.tmp ] +then + echo "============================================" + echo "=== Warning: These current PMDA patterns do NOT match ANY metrics ..." + echo "============================================" + cat $tmp.tmp + echo +fi + +comm -12 $tmp.pmda $tmp.munged >$tmp.tmp +if [ -s $tmp.tmp ] +then + echo "============================================" + echo "=== Metrics supported in the current PMDA ..." + echo "============================================" + cat $tmp.tmp +else + echo "============================================" + echo "=== Warning: The current PMDA patterns match NO metric!" + echo "============================================" +fi + +comm -13 $tmp.pmda $tmp.munged >$tmp.tmp +if [ -s $tmp.tmp ] +then + echo + echo "============================================" + echo "=== Metrics NOT supported in the current PMDA" + echo "============================================" + cat $tmp.tmp +fi diff --git a/src/pmdas/windows/pmda.c b/src/pmdas/windows/pmda.c new file mode 100644 index 0000000..0c5009a --- /dev/null +++ b/src/pmdas/windows/pmda.c @@ -0,0 +1,1601 @@ +/* + * Windows PMDA + * + * Copyright (c) 2008-2010 Aconex. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include "hypnotoad.h" +#include <ctype.h> + +/* + * Array of all metrics - the PMID item field indexes this directly. + */ +pdh_metric_t metricdesc[] = { +/* kernel.all.cpu.user */ + { { PMDA_PMID(0,0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(_Total)\\% User Time" + }, +/* kernel.all.cpu.idle */ + { { PMDA_PMID(0,1), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(_Total)\\% Idle Time" + }, +/* kernel.all.cpu.sys */ + { { PMDA_PMID(0,2), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(_Total)\\% Privileged Time" + }, +/* kernel.all.cpu.intr */ + { { PMDA_PMID(0,3), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(_Total)\\% Interrupt Time" + }, +/* kernel.percpu.cpu.user */ + { { PMDA_PMID(0,4), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(*)\\% User Time" + }, +/* kernel.percpu.cpu.idle */ + { { PMDA_PMID(0,5), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(*)\\% Idle Time" + }, +/* kernel.percpu.cpu.sys */ + { { PMDA_PMID(0,6), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(*)\\% Privileged Time" + }, +/* kernel.percpu.cpu.intr */ + { { PMDA_PMID(0,7), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Processor(*)\\% Interrupt Time" + }, +/* kernel.num_processes */ + { { PMDA_PMID(0,8), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\System\\Processes" + }, +/* kernel.num_threads */ + { { PMDA_PMID(0,9), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\System\\Threads" + }, +/* kernel.all.pswitch */ + { { PMDA_PMID(0,10), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\System\\Context Switches/sec" + }, +/* kernel.all.file.read */ + { { PMDA_PMID(0,11), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\System\\File Read Operations/sec" + }, +/* kernel.all.file.write */ + { { PMDA_PMID(0,12), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\System\\File Write Operations/sec" + }, +/* kernel.all.file.read_bytes */ + { { PMDA_PMID(0,13), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\System\\File Read Bytes/sec" + }, +/* kernel.all.file.write_bytes */ + { { PMDA_PMID(0,14), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\System\\File Write Bytes/sec" + }, +/* disk.all.read */ + { { PMDA_PMID(0,15), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Disk Reads/sec" + }, +/* disk.all.write */ + { { PMDA_PMID(0,16), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Disk Writes/sec" + }, +/* disk.all.total */ + { { PMDA_PMID(0,17), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Disk Transfers/sec" + }, +/* disk.all.read_bytes */ + { { PMDA_PMID(0,18), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Disk Read Bytes/sec" + }, +/* disk.all.write_bytes */ + { { PMDA_PMID(0,19), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Disk Write Bytes/sec" + }, +/* disk.all.total_bytes */ + { { PMDA_PMID(0,20), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Disk Bytes/sec" + }, +/* disk.dev.read */ + { { PMDA_PMID(0,21), PM_TYPE_U32, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Disk Reads/sec" + }, +/* disk.dev.write */ + { { PMDA_PMID(0,22), PM_TYPE_U32, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Disk Writes/sec" + }, +/* disk.dev.total */ + { { PMDA_PMID(0,23), PM_TYPE_U32, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Disk Transfers/sec" + }, +/* disk.dev.read_bytes */ + { { PMDA_PMID(0,24), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Disk Read Bytes/sec" + }, +/* disk.dev.write_bytes */ + { { PMDA_PMID(0,25), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Disk Write Bytes/sec" + }, +/* disk.dev.total_bytes */ + { { PMDA_PMID(0,26), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Disk Bytes/sec" + }, +/* mem.page_faults */ + { { PMDA_PMID(0,27), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Page Faults/sec" + }, +/* mem.available */ + { { PMDA_PMID(0,28), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Available MBytes" + }, +/* mem.committed_bytes */ + { { PMDA_PMID(0,29), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Committed Bytes" + }, +/* mem.pool.paged_bytes */ + { { PMDA_PMID(0,30), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Pool Paged Bytes" + }, +/* mem.pool.non_paged_bytes */ + { { PMDA_PMID(0,31), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Pool Nonpaged Bytes" + }, +/* mem.cache.lazy_writes */ + { { PMDA_PMID(0,32), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Cache\\Lazy Write Flushes/sec" + }, +/* mem.cache.lazy_write_pages */ + { { PMDA_PMID(0,33), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Cache\\Lazy Write Pages/sec" + }, +/* mem.cache.mdl.read */ + { { PMDA_PMID(0,34), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Cache\\MDL Reads/sec" + }, +/* mem.cache.read_ahead */ + { { PMDA_PMID(0,35), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Cache\\Read Aheads/sec" + }, +/* mem.cache.mdl.sync_read */ + { { PMDA_PMID(0,36), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Cache\\Sync MDL Reads/sec" + }, +/* mem.cache.mdl.async_read */ + { { PMDA_PMID(0,37), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Cache\\Async MDL Reads/sec" + }, +/* network.interface.in.packets */ + { { PMDA_PMID(0,38), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Packets Received/sec" + }, +/* network.interface.in.bytes */ + { { PMDA_PMID(0,39), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0,0, PM_SPACE_BYTE, 0,0) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Bytes Received/sec" + }, +/* network.interface.in.errors */ + { { PMDA_PMID(0,40), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Packets Received Errors" + }, +/* network.interface.out.packets */ + { { PMDA_PMID(0,41), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Packets Sent/sec" + }, +/* network.interface.out.bytes */ + { { PMDA_PMID(0,42), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0,0, PM_SPACE_BYTE, 0,0) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Bytes Sent/sec" + }, +/* network.interface.out.errors */ + { { PMDA_PMID(0,43), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Packets Outbound Errors" + }, +/* network.interface.total.packets */ + { { PMDA_PMID(0,44), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_NONE | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Packets/sec" + }, +/* network.interface.total.bytes */ + { { PMDA_PMID(0,45), PM_TYPE_U64, NETIF_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, + M_NONE, 0, 0, 0, NULL, + "\\Network Interface(*)\\Bytes Total/sec" + }, +/* sqlserver.buf_mgr.cache_hit_ratio */ + { { PMDA_PMID(0,46), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Buffer cache hit ratio" + }, +/* sqlserver.buf_mgr.page_lookups */ + { { PMDA_PMID(0,47), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Page lookups/sec" + }, +/* sqlserver.buf_mgr.free_list_stalls */ + { { PMDA_PMID(0,48), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Free list stalls/sec" + }, +/* sqlserver.buf_mgr.free_pages */ + { { PMDA_PMID(0,49), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Free pages" + }, +/* sqlserver.buf_mgr.total_pages */ + { { PMDA_PMID(0,50), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Total pages" + }, +/* sqlserver.buf_mgr.target_pages */ + { { PMDA_PMID(0,51), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Target pages" + }, +/* sqlserver.buf_mgr.database_pages */ + { { PMDA_PMID(0,52), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Database pages" + }, +/* sqlserver.buf_mgr.reserved_pages */ + { { PMDA_PMID(0,53), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Reserved pages" + }, +/* sqlserver.buf_mgr.stolen_pages */ + { { PMDA_PMID(0,54), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Stolen pages" + }, +/* sqlserver.buf_mgr.lazy_writes */ + { { PMDA_PMID(0,55), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Lazy writes/sec" + }, +/* sqlserver.buf_mgr.readahead_pages */ + { { PMDA_PMID(0,56), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Readahead pages/sec" + }, +/* sqlserver.buf_mgr.procedure_cache_pages */ + { { PMDA_PMID(0,57), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Procedure cache pages" + }, +/* sqlserver.buf_mgr.page_reads */ + { { PMDA_PMID(0,58), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Page reads/sec" + }, +/* sqlserver.buf_mgr.page_writes */ + { { PMDA_PMID(0,59), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Page writes/sec" + }, +/* sqlserver.buf_mgr.checkpoint_pages */ + { { PMDA_PMID(0,60), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Checkpoint pages/sec" + }, +/* sqlserver.buf_mgr.awe.lookup_maps */ + { { PMDA_PMID(0,61), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\AWE lookup maps/sec" + }, +/* sqlserver.buf_mgr.awe.stolen_maps */ + { { PMDA_PMID(0,62), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\AWE stolen maps/sec" + }, +/* sqlserver.buf_mgr.awe.write_maps */ + { { PMDA_PMID(0,63), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\AWE write maps/sec" + }, +/* sqlserver.buf_mgr.awe.unmap_calls */ + { { PMDA_PMID(0,64), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\AWE unmap calls/sec" + }, +/* sqlserver.buf_mgr.awe.unmap_pages */ + { { PMDA_PMID(0,65), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\AWE unmap pages/sec" + }, +/* sqlserver.buf_mgr.page_life_expectancy */ + { { PMDA_PMID(0,66), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_SEC, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Buffer Manager\\Page life expectancy" + }, +/* filesys.full */ + { { PMDA_PMID(0,67), PM_TYPE_FLOAT, FILESYS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\LogicalDisk(*)\\% Free Space" + }, +/* disk.dev.idle */ + { { PMDA_PMID(0,68), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\% Idle Time" + }, +/* sqlserver.locks.all.requests */ + { { PMDA_PMID(0,69), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(_Total)\\Lock Requests/sec" + }, +/* sqlserver.locks.all.waits */ + { { PMDA_PMID(0,70), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(_Total)\\Lock Waits/sec" + }, +/* sqlserver.locks.all.deadlocks */ + { { PMDA_PMID(0,71), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(_Total)\\Number of Deadlocks/sec" + }, +/* sqlserver.locks.all.timeouts */ + { { PMDA_PMID(0,72), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(_Total)\\Lock Timeouts/sec" + }, +/* sqlserver.locks.all.wait_time */ + { { PMDA_PMID(0,73), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(_Total)\\Lock Wait Time (ms)" + }, +/* sqlserver.locks.all.avg_wait_time */ + { { PMDA_PMID(0,74), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(_Total)\\Average Wait Time (ms)" + }, +/* sqlserver.locks.region.requests */ + { { PMDA_PMID(0,75), PM_TYPE_U32, SQL_LOCK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(*)\\Lock Requests/sec" + }, +/* sqlserver.locks.region.waits */ + { { PMDA_PMID(0,76), PM_TYPE_U32, SQL_LOCK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(*)\\Lock Waits/sec" + }, +/* sqlserver.locks.region.deadlocks */ + { { PMDA_PMID(0,77), PM_TYPE_U32, SQL_LOCK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(*)\\Number of Deadlocks/sec" + }, +/* sqlserver.locks.region.timeouts */ + { { PMDA_PMID(0,78), PM_TYPE_U32, SQL_LOCK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(*)\\Lock Timeouts/sec" + }, +/* sqlserver.locks.region.wait_time */ + { { PMDA_PMID(0,79), PM_TYPE_U32, SQL_LOCK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(*)\\Lock Wait Time (ms)" + }, +/* sqlserver.locks.region.avg_wait */ + { { PMDA_PMID(0,80), PM_TYPE_FLOAT, SQL_LOCK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Locks(*)\\Average Wait Time (ms)" + }, +/* sqlserver.cache_mgr.all.cache_hit_ratio */ + { { PMDA_PMID(0,81), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(_Total)\\Cache Hit Ratio" + }, +/* sqlserver.cache_mgr.cache.cache_hit_ratio */ + { { PMDA_PMID(0,82), PM_TYPE_FLOAT, SQL_CACHE_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(*)\\Cache Hit Ratio" + }, +/* sqlserver.connections */ + { { PMDA_PMID(0,83), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:General Statistics\\User Connections" + }, +/* sqlserver.databases.all.transactions */ + { { PMDA_PMID(0,84), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(_Total)\\Transactions/sec" + }, +/* sqlserver.databases.db.transactions */ + { { PMDA_PMID(0,85), PM_TYPE_U32, SQL_DB_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(*)\\Transactions/sec" + }, +/* sqlserver.sql.batch_requests */ + { { PMDA_PMID(0,86), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:SQL Statistics\\Batch Requests/sec" + }, +/* sqlserver.latches.waits */ + { { PMDA_PMID(0,87), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Latches\\Latch Waits/sec" + }, +/* sqlserver.latches.wait_time */ + { { PMDA_PMID(0,88), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Latches\\Total Latch Wait Time (ms)" + }, +/* sqlserver.latches.avg_wait_time */ + { { PMDA_PMID(0,89), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Latches\\Average Latch Wait Time (ms)" + }, +/* sqlserver.databases.all.data_file_size */ + { { PMDA_PMID(0,90), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(_Total)\\Data File(s) Size (KB)" + }, +/* sqlserver.databases.all.log_file_size */ + { { PMDA_PMID(0,91), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(_Total)\\Log File(s) Size (KB)" + }, +/* sqlserver.databases.all.log_file_used */ + { { PMDA_PMID(0,92), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(_Total)\\Log File(s) Used Size (KB)" + }, +/* sqlserver.databases.db.data_file_size */ + { { PMDA_PMID(0,93), PM_TYPE_U32, SQL_DB_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(*)\\Data File(s) Size (KB)" + }, +/* sqlserver.databases.db.log_file_size */ + { { PMDA_PMID(0,94), PM_TYPE_U32, SQL_DB_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(*)\\Log File(s) Size (KB)" + }, +/* sqlserver.databases.db.log_file_used */ + { { PMDA_PMID(0,95), PM_TYPE_U32, SQL_DB_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(*)\\Log File(s) Used Size (KB)" + }, +/* sqlserver.sql.compilations */ + { { PMDA_PMID(0,96), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:SQL Statistics\\SQL Compilations/sec" + }, +/* sqlserver.sql.re_compilations */ + { { PMDA_PMID(0,97), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:SQL Statistics\\SQL Re-Compilations/sec" + }, +/* sqlserver.access.full_scans */ + { { PMDA_PMID(0,98), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Access Methods\\Full Scans/sec" + }, +/* sqlserver.access.pages_allocated */ + { { PMDA_PMID(0,99), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Access Methods\\Pages Allocated/sec" + }, +/* sqlserver.access.table_lock_escalations */ + { { PMDA_PMID(0,100), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Access Methods\\Table Lock Escalations/sec" + }, +/* disk.dev.queuelen */ + { { PMDA_PMID(0,101), PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Current Disk Queue Length" + }, +/* sqlserver.databases.all.log_flushes */ + { { PMDA_PMID(0,102), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(_Total)\\Log Flushes/sec" + }, +/* sqlserver.databases.db.log_flushes */ + { { PMDA_PMID(0,103), PM_TYPE_U32, SQL_DB_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(*)\\Log Flushes/sec" + }, +/* sqlserver.databases.all.log_bytes_flushed */ + { { PMDA_PMID(0,104), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(_Total)\\Log Bytes Flushed/sec" + }, +/* sqlserver.databases.db.log_bytes_flushed */ + { { PMDA_PMID(0,105), PM_TYPE_U32, SQL_DB_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(*)\\Log Bytes Flushed/sec" + }, +/* hinv.physmem */ + { { PMDA_PMID(0,106), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* hinv.ncpu */ + { { PMDA_PMID(0,107), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* hinv.ndisk */ + { { PMDA_PMID(0,108), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* kernel.uname.distro */ + { { PMDA_PMID(0,109), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* kernel.uname.release */ + { { PMDA_PMID(0,110), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* kernel.uname.version */ + { { PMDA_PMID(0,111), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* kernel.uname.sysname */ + { { PMDA_PMID(0,112), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* kernel.uname.machine */ + { { PMDA_PMID(0,113), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* kernel.uname.nodename */ + { { PMDA_PMID(0,114), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* pmda.uname */ + { { PMDA_PMID(0,115), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* pmda.version */ + { { PMDA_PMID(0,116), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_NONE, 0, 0, 0, NULL, "" + }, + +/* filesys.capacity */ + { { PMDA_PMID(0,117), PM_TYPE_U64, FILESYS_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, M_REDO, 0, 0, 0, NULL, "" + }, +/* filesys.used */ + { { PMDA_PMID(0,118), PM_TYPE_U64, FILESYS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, M_REDO, 0, 0, 0, NULL, "" + }, +/* filesys.free */ + { { PMDA_PMID(0,119), PM_TYPE_U64, FILESYS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, M_REDO, 0, 0, 0, NULL, "" + }, +/* dummy - filesys.free_space */ + { { PMDA_PMID(0,120), PM_TYPE_U32, FILESYS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_MBYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\LogicalDisk(*)\\Free Megabytes" + }, +/* dummy - filesys.free_percent */ + { { PMDA_PMID(0,121), PM_TYPE_FLOAT, FILESYS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\LogicalDisk(*)\\% Free Space" + }, +/* sqlserver.access.page_splits */ + { { PMDA_PMID(0,122), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Access Methods\\Page Splits/sec" + }, +/* network.tcp.activeopens */ + { { PMDA_PMID(0,123), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Connections Active" + }, +/* network.tcp.passiveopens */ + { { PMDA_PMID(0,124), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Connections Passive" + }, +/* network.tcp.attemptfails */ + { { PMDA_PMID(0,125), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Connection Failures" + }, +/* network.tcp.estabresets */ + { { PMDA_PMID(0,126), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Connections Reset" + }, +/* network.tcp.currestab */ + { { PMDA_PMID(0,127), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Connections Established" + }, +/* network.tcp.insegs */ + { { PMDA_PMID(0,128), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Segments Received/sec" + }, +/* network.tcp.outsegs */ + { { PMDA_PMID(0,129), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Segments Sent/sec" + }, +/* network.tcp.totalsegs */ + { { PMDA_PMID(0,130), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Segments/sec" + }, +/* network.tcp.retranssegs */ + { { PMDA_PMID(0,131), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\TCPv4\\Segments Retransmitted/sec" + }, + +/* disk.all.split_io */ + { { PMDA_PMID(0,132), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Split IO/Sec" + }, +/* disk.dev.split_io */ + { { PMDA_PMID(0,133), PM_TYPE_U32, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Split IO/Sec" + }, + +/* sqlserver.databases.all.active_transactions */ + { { PMDA_PMID(0,134), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(_Total)\\Active Transactions" + }, +/* sqlserver.databases.db.active_transactions */ + { { PMDA_PMID(0,135), PM_TYPE_U32, SQL_DB_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_REDO | M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Databases(*)\\Active Transactions" + }, + +/* mem.commit_limit */ + { { PMDA_PMID(0,136), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Commit Limit" + }, +/* mem.write_copies */ + { { PMDA_PMID(0,137), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Write Copies/sec" + }, +/* mem.transition_faults */ + { { PMDA_PMID(0,138), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Transition Faults/sec" + }, +/* mem.cache.faults */ + { { PMDA_PMID(0,139), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Cache Faults/sec" + }, +/* mem.demand_zero_faults */ + { { PMDA_PMID(0,140), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Demand Zero Faults/sec" + }, +/* mem.pages_total */ + { { PMDA_PMID(0,141), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Pages/sec" + }, +/* mem.page_reads */ + { { PMDA_PMID(0,142), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Page Reads/sec" + }, +/* mem.pages_output */ + { { PMDA_PMID(0,143), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Pages Output/sec" + }, +/* mem.page_writes */ + { { PMDA_PMID(0,144), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Page Writes/sec" + }, +/* mem.pool.paged_allocs */ + { { PMDA_PMID(0,145), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Pool Paged Allocs" + }, +/* mem.pool.nonpaged_allocs */ + { { PMDA_PMID(0,146), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Pool Nonpaged Allocs" + }, +/* mem.system.free_ptes */ + { { PMDA_PMID(0,147), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Free System Page Table Entries" + }, +/* mem.cache.bytes */ + { { PMDA_PMID(0,148), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Page Faults/sec" + }, +/* mem.cache.bytes_peak */ + { { PMDA_PMID(0,149), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Cache Bytes Peak" + }, +/* mem.pool.paged_resident_bytes */ + { { PMDA_PMID(0,150), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\Pool Paged Resident Bytes" + }, +/* mem.system.total_code_bytes */ + { { PMDA_PMID(0,151), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\System Code Total Bytes" + }, +/* mem.system.resident_code_bytes */ + { { PMDA_PMID(0,152), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_NONE, 0, 0, 0, NULL, + "\\Memory\\System Code Resident Bytes" + }, + +/* sqlserver.mem_mgr.connection_memory */ + { { PMDA_PMID(0,153), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Connection Memory (KB)" + }, +/* sqlserver.mem_mgr.granted_workspace */ + { { PMDA_PMID(0,154), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Granted Workspace Memory (KB)" + }, +/* sqlserver.mem_mgr.lock_memory */ + { { PMDA_PMID(0,155), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Lock Memory (KB)" + }, +/* sqlserver.mem_mgr.lock_blocks_allocated */ + { { PMDA_PMID(0,156), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Lock Blocks Allocated" + }, +/* sqlserver.mem_mgr.lock_owner_blocks_allocated */ + { { PMDA_PMID(0,157), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Lock Owner Blocks Allocated" + }, +/* sqlserver.mem_mgr.lock_blocks */ + { { PMDA_PMID(0,158), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Lock Blocks" + }, +/* sqlserver.mem_mgr.lock_owner_blocks */ + { { PMDA_PMID(0,159), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Lock Owner Blocks" + }, +/* sqlserver.mem_mgr.maximum_workspace_memory */ + { { PMDA_PMID(0,160), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Maximum Workspace Memory (KB)" + }, +/* sqlserver.mem_mgr.memory_grants_outstanding */ + { { PMDA_PMID(0,161), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Memory Grants Outstanding" + }, +/* sqlserver.mem_mgr.memory_grants_pending */ + { { PMDA_PMID(0,162), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Memory Grants Pending" + }, +/* sqlserver.mem_mgr.optimizer_memory */ + { { PMDA_PMID(0,163), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Optimizer Memory (KB)" + }, +/* sqlserver.mem_mgr.sql_cache_memory */ + { { PMDA_PMID(0,164), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\SQL Cache Memory (KB)" + }, +/* sqlserver.mem_mgr.target_server_memory */ + { { PMDA_PMID(0,165), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Target Server Memory(KB)" + }, +/* sqlserver.mem_mgr.total_server_memory */ + { { PMDA_PMID(0,166), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,PM_SPACE_KBYTE,0,0,0) + }, M_OPTIONAL | M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:Memory Manager\\Total Server Memory (KB)" + }, +/* sqlserver.cache_mgr.all.cache_pages */ + { { PMDA_PMID(0,167), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(_Total)\\Cache Pages" + }, +/* sqlserver.cache_mgr.all.cache_object_count */ + { { PMDA_PMID(0,168), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(_Total)\\Cache Object Counts" + }, +/* sqlserver.cache_mgr.all.cache_use */ + { { PMDA_PMID(0,169), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(_Total)\\Cache Use Counts/sec" + }, +/* sqlserver.cache_mgr.cache.cache_pages */ + { { PMDA_PMID(0,170), PM_TYPE_U32, SQL_CACHE_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(*)\\Cache Pages" + }, +/* sqlserver.cache_mgr.cache.cache_object_count */ + { { PMDA_PMID(0,171), PM_TYPE_32, SQL_CACHE_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(*)\\Cache Object Counts" + }, +/* sqlserver.cache_mgr.cache.cache_use */ + { { PMDA_PMID(0,172), PM_TYPE_U32, SQL_CACHE_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, M_OPTIONAL, 0, 0, 0, NULL, + "\\SQLServer:Cache Manager(*)\\Cache Use Counts/sec" + }, +/* process.count */ + { { PMDA_PMID(0,173), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\Objects\\Processes" + }, +/* process.psinfo.pid */ + { { PMDA_PMID(0,174), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\ID Process" + }, +/* process.psinfo.ppid */ + { { PMDA_PMID(0,175), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Creating Process ID" + }, +/* process.psinfo.cpu_time */ + { { PMDA_PMID(0,176), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Process(*)\\% Processor Time" + }, +/* process.psinfo.elapsed_time */ + { { PMDA_PMID(0,177), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Elapsed Time" + }, +/* process.psinfo.utime */ + { { PMDA_PMID(0,178), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\% User Time" + }, +/* process.psinfo.stime */ + { { PMDA_PMID(0,179), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\% Privileged Time" + }, +/* process.psinfo.nthreads */ + { { PMDA_PMID(0,180), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Thread Count" + }, +/* process.psinfo.priority_base */ + { { PMDA_PMID(0,181), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Priority Base" + }, +/* process.psinfo.nhandles */ + { { PMDA_PMID(0,182), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Handle Count" + }, +/* process.psinfo.page_faults */ + { { PMDA_PMID(0,183), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Page Faults/sec" + }, +/* process.memory.size */ + { { PMDA_PMID(0,184), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Pool Paged Bytes" + }, +/* process.memory.rss */ + { { PMDA_PMID(0,185), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Working Set" + }, +/* process.memory.rss_peak */ + { { PMDA_PMID(0,186), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Working Set Peak" + }, +/* process.memory.virtual */ + { { PMDA_PMID(0,187), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Virtual Bytes" + }, +/* process.memory.virtual_peak */ + { { PMDA_PMID(0,188), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Virtual Bytes Peak" + }, +/* process.memory.page_file */ + { { PMDA_PMID(0,189), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Page File Bytes" + }, +/* process.memory.page_file_peak */ + { { PMDA_PMID(0,190), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Page File Bytes Peak" + }, +/* process.memory.private */ + { { PMDA_PMID(0,191), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Private Bytes" + }, +/* process.memory.pool_paged */ + { { PMDA_PMID(0,192), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Pool Paged Bytes" + }, +/* process.memory.pool_nonpaged */ + { { PMDA_PMID(0,193), PM_TYPE_U32, PROCESS_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\Pool Nonpaged Bytes" + }, +/* process.io.reads */ + { { PMDA_PMID(0,194), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Read Operations/sec" + }, +/* process.io.writes */ + { { PMDA_PMID(0,195), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Write Operations/sec" + }, +/* process.io.data */ + { { PMDA_PMID(0,196), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Data Operations/sec" + }, +/* process.io.other */ + { { PMDA_PMID(0,197), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Other Operations/sec" + }, +/* process.io.read_bytes */ + { { PMDA_PMID(0,198), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Read Bytes/sec" + }, +/* process.io.write_bytes */ + { { PMDA_PMID(0,199), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Write Bytes/sec" + }, +/* process.io.data_bytes */ + { { PMDA_PMID(0,200), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Data Bytes/sec" + }, +/* process.io.other_bytes */ + { { PMDA_PMID(0,201), PM_TYPE_U64, PROCESS_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Process(*)\\IO Other Bytes/sec" + }, +/* process.thread.context_switches */ + { { PMDA_PMID(0,202), PM_TYPE_U32, THREAD_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\Context Switches/sec" + }, +/* process.thread.cpu_time */ + { { PMDA_PMID(0,203), PM_TYPE_U64, THREAD_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\% Processor Time" + }, +/* process.thread.utime */ + { { PMDA_PMID(0,204), PM_TYPE_U64, THREAD_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\% User Time" + }, +/* process.thread.stime */ + { { PMDA_PMID(0,205), PM_TYPE_U64, THREAD_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\% Privileged Time" + }, +/* process.thread.elapsed_time */ + { { PMDA_PMID(0,206), PM_TYPE_U64, THREAD_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\Elapsed Time" + }, +/* process.thread.priority */ + { { PMDA_PMID(0,207), PM_TYPE_U32, THREAD_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\Priority Current" + }, +/* process.thread.priority_base */ + { { PMDA_PMID(0,208), PM_TYPE_U32, THREAD_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\Priority Base" + }, +/* process.thread.start_address */ + { { PMDA_PMID(0,209), PM_TYPE_U32, THREAD_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\Start Address" + }, +/* process.thread.state */ + { { PMDA_PMID(0,210), PM_TYPE_U32, THREAD_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\Thread State" + }, +/* process.thread.wait_reason */ + { { PMDA_PMID(0,211), PM_TYPE_U32, THREAD_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\Thread Wait Reason" + }, +/* process.thread.process_id */ + { { PMDA_PMID(0,212), PM_TYPE_U32, THREAD_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\ID Process" + }, +/* process.thread.thread_id */ + { { PMDA_PMID(0,213), PM_TYPE_U32, THREAD_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\Thread(*)\\ID Thread" + }, + +/* disk.all.read_time */ + { { PMDA_PMID(0,214), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\% Disk Read Time" + }, +/* disk.all.write_time */ + { { PMDA_PMID(0,215), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\% Disk Write Time" + }, +/* disk.all.total_time */ + { { PMDA_PMID(0,216), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\% Disk Time" + }, +/* disk.dev.read_time */ + { { PMDA_PMID(0,217), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\% Disk Read Time" + }, +/* disk.dev.write_time */ + { { PMDA_PMID(0,218), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\% Disk Write Time" + }, +/* disk.dev.total_time */ + { { PMDA_PMID(0,219), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\% Disk Time" + }, +/* disk.all.average.read_bytes */ + { { PMDA_PMID(0,220), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Avg. Disk Bytes/Read" + }, +/* disk.all.average.write_bytes */ + { { PMDA_PMID(0,221), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Avg. Disk Bytes/Write" + }, +/* disk.all.average.total_bytes */ + { { PMDA_PMID(0,222), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Avg. Disk Bytes/Transfer" + }, +/* disk.all.average.read_time */ + { { PMDA_PMID(0,223), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Avg. Disk sec/Read" + }, +/* disk.all.average.write_time */ + { { PMDA_PMID(0,224), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Avg. Disk sec/Write" + }, +/* disk.all.average.total_time */ + { { PMDA_PMID(0,225), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_NONE, 0, 0, 0, NULL, + "\\PhysicalDisk(_Total)\\Avg. Disk sec/Transfer" + }, +/* disk.dev.average.read_bytes */ + { { PMDA_PMID(0,226), PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Avg. Disk Bytes/Read" + }, +/* disk.dev.write_bytes */ + { { PMDA_PMID(0,227), PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Avg. Disk Bytes/Write" + }, +/* disk.dev.total_bytes */ + { { PMDA_PMID(0,228), PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Avg. Disk Bytes/Transfer" + }, +/* disk.dev.average.read_time */ + { { PMDA_PMID(0,229), PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Avg. Disk sec/Read" + }, +/* disk.dev.average.write_time */ + { { PMDA_PMID(0,230), PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Avg. Disk sec/Write" + }, +/* disk.dev.average.total_time */ + { { PMDA_PMID(0,231), PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_USEC, 0) }, M_REDO, 0, 0, 0, NULL, + "\\PhysicalDisk(*)\\Avg. Disk sec/Transfer" + }, + +/* hinv.nfilesys */ + { { PMDA_PMID(0,232), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) }, M_NONE, 0, 0, 0, NULL, "" + }, +/* hinv.pagesize */ + { { PMDA_PMID(0,233), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_NONE, 0, 0, 0, NULL, "" + }, + +/* kernel.all.uptime */ + { { PMDA_PMID(0,234), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, M_REDO, 0, 0, 0, NULL, + "\\System\\System Up Time" + }, + +/* network.interface.bandwidth */ + { { PMDA_PMID(0,235), PM_TYPE_U32, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, -1, 0, 0, PM_TIME_SEC, 0) + }, M_REDO | M_AUTO64, 0, 0, 0, NULL, + "\\Network Interface(*)\\Current Bandwidth" + }, +/* network.interface.speed */ + { { PMDA_PMID(0,236), PM_TYPE_FLOAT, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, -1, 0, PM_SPACE_MBYTE, PM_TIME_SEC, 0) + }, M_REDO, 0, 0, 0, NULL, "" + }, +/* network.interface.baudrate */ + { { PMDA_PMID(0,237), PM_TYPE_U32, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, -1, 0, PM_SPACE_BYTE, PM_TIME_SEC, 0) + }, M_REDO, 0, 0, 0, NULL, "" + }, + +/* sqlserver.user_settable.query */ + { { PMDA_PMID(0,238), PM_TYPE_U32, SQL_USER_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, M_AUTO64, 0, 0, 0, NULL, + "\\SQLServer:User Settable(*)\\Query" + }, + +/* mem.physmem */ + { { PMDA_PMID(1,0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "The amount of actual physical memory" + }, +/* mem.freemem */ + { { PMDA_PMID(1,1), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "The amount of physical memory currently available" + }, +/* mem.util.load */ + { { PMDA_PMID(1,2), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 0, 0, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "Approximate percentage of physical memory in use" + }, +/* mem.util.used */ + { { PMDA_PMID(1,3), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "Amount of physical memory in use" + }, +/* mem.util.free */ + { { PMDA_PMID(1,4), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "Amount of physical memory currently available" + }, +/* swap.length */ + { { PMDA_PMID(1,5), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "The current committed memory limit for the system" + }, +/* swap.used */ + { { PMDA_PMID(1,6), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "The current committed memory for the system" + }, +/* swap.free */ + { { PMDA_PMID(1,7), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0) }, M_NONE, 0, 0, 0, NULL, + "The maximum amount of memory the system can commit" + }, +}; +int metricdesc_sz = sizeof(metricdesc) / sizeof(metricdesc[0]); + +static int +windows_instance(pmInDom indom, int inst, char *name, __pmInResult **result, pmdaExt *pmda) +{ + windows_instance_refresh(indom); + return pmdaInstance(indom, inst, name, result, pmda); +} + +static int +windows_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda) +{ + windows_fetch_refresh(numpmid, pmidlist, pmda); + return pmdaFetch(numpmid, pmidlist, resp, pmda); +} + +static pdh_value_t * +find_instance_value(unsigned int item, unsigned int inst) +{ + pdh_metric_t *mp = &metricdesc[item]; + int i; + + /* fast check for direct mapped instance ID */ + if (inst < mp->num_vals && mp->vals[inst].inst == inst) + return (mp->vals[inst].flags & V_COLLECTED) ? &mp->vals[inst] : NULL; + + /* scan iteratively through instance IDs looking for this one */ + for (i = 0; i < mp->num_vals; i++) { + if (mp->vals[i].inst != inst) + continue; + if (!(mp->vals[i].flags & V_COLLECTED)) + break; + return &mp->vals[i]; + } + return NULL; +} + +static int +filesys_fetch_callback(unsigned int item, unsigned int inst, pmAtomValue *atom) +{ + pdh_value_t *vp; + unsigned long long used, avail, capacity; + float used_space, free_space, free_percent; + + /* + * Special case handling for the derived filesystem metrics + * which map the PDH services semantics for some metrics to + * the usual metrics from other platforms. + * 67 filesys.full + * 117 filesys.capacity + * 118 filesys.used + * 119 filesys.free + * 120 dummy metric, metricdesc holds FreeMB + * 121 dummy metric, metricdesc holds %Free + */ + if (item == 67) { /* filesys.full, metricdesc holds %Free */ + vp = find_instance_value(item, inst); + if (!vp) + return 0; + atom->f = (1.0 - vp->atom.f) * 100.0; + return 1; + } + + vp = find_instance_value(120,inst); /* dummy, metricdesc holds FreeMB */ + if (!vp) + return 0; + free_space = ((float)vp->atom.ul); + + vp = find_instance_value(121,inst); /* dummy, metricdesc holds %Free */ + if (!vp) + return 0; + free_percent = vp->atom.f; + + used_space = (free_space / free_percent) - free_space; + used = 1024 * (unsigned long long)used_space; /* MB to KB */ + avail = 1024 * (unsigned long long)free_space; /* MB to KB */ + capacity = used + avail; + + if (item == 117) /* filesys.capacity */ + atom->ull = capacity; + else if (item == 118) /* filesys.used */ + atom->ull = used; + else if (item == 119) /* filesys.free */ + atom->ull = avail; + return 1; +} + +static int +network_fetch_callback(unsigned int item, unsigned int inst, pmAtomValue *atom) +{ + pdh_value_t *vp; + + /* + * Special case handling for the derived network bandwidth metrics + * 235 network.interface.bandwidth (base, no derived) + * 236 network.interface.speed (mbytes, float) + * 237 network.interface.baudrate (in bytes) + */ + vp = find_instance_value(235,inst); + if (!vp) + return 0; + if (item == 236) + atom->f = ((float)vp->atom.ull / 8 / 1024 / 1024); + else if (item == 237) + atom->ul = (vp->atom.ull / 8); + return 1; +} + +static int +memstat_fetch_callback(unsigned int item, unsigned int inst, pmAtomValue *atom) +{ + if (inst == PM_INDOM_NULL) { + switch (item) { + case 0: /* mem.physmem */ + atom->ull = windows_memstat.ullTotalPhys / 1024; + return 1; + case 1: /* mem.freemem */ + case 4: /* mem.util.free */ + atom->ull = windows_memstat.ullAvailPhys / 1024; + return 1; + case 2: /* mem.util.load */ + atom->ul = windows_memstat.dwMemoryLoad; + return 1; + case 3: /* mem.util.used */ + atom->ull = windows_memstat.ullTotalPhys; + atom->ull =- windows_memstat.ullAvailPhys; + atom->ull /= 1024; + return 1; + case 5: /* swap.length */ + atom->ull = windows_memstat.ullTotalPageFile / 1024; + return 1; + case 6: /* swap.used */ + atom->ull = windows_memstat.ullTotalPageFile; + atom->ull -= windows_memstat.ullAvailPageFile; + atom->ull /= 1024; + return 1; + case 7: /* swap.free */ + atom->ull = windows_memstat.ullAvailPageFile / 1024; + return 1; + } + } + return 0; +} + +static int +windows_fetch_callback(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) +{ + __pmID_int *pmidp = (__pmID_int *)&mdesc->m_desc.pmid; + pdh_value_t *vp; + + if (pmidp->cluster == 1) + return memstat_fetch_callback(pmidp->item, inst, atom); + + if (pmidp->cluster != 0 || pmidp->item > metricdesc_sz || + (pmidp->item == 120 || pmidp->item == 121)) /* dummies */ + return PM_ERR_PMID; + + /* + * Check if its one of the derived metrics, or one that doesn't use PDH + */ + switch (pmidp->item) { + case 106: /* hinv.physmem */ + atom->ul = (windows_memstat.ullTotalPhys / (1024 * 1024)); + return 1; + case 107: /* hinv.ncpu */ + atom->ul = pmdaCacheOp(INDOM(pmidp->domain, CPU_INDOM), + PMDA_CACHE_SIZE_ACTIVE); + return 1; + case 108: /* hinv.ndisk */ + atom->ul = pmdaCacheOp(INDOM(pmidp->domain, DISK_INDOM), + PMDA_CACHE_SIZE_ACTIVE); + return 1; + case 109: /* kernel.uname.distro */ + atom->cp = windows_uname; + return 1; + case 110: /* kernel.uname.release */ + atom->cp = windows_build; + return 1; + case 111: /* kernel.uname.version */ + atom->cp = windows_build; + return 1; + case 112: /* kernel.uname.sysname */ + atom->cp = "Windows"; + return 1; + case 113: /* kernel.uname.machine */ + atom->cp = windows_machine; + return 1; + case 114: /* kernel.uname.nodename */ + atom->cp = "?"; + return 1; + case 115: /* pmda.uname */ + atom->cp = windows_uname; + return 1; + case 116: /* pmda.version */ + atom->cp = pmGetConfig("PCP_VERSION"); + return 1; + case 67: case 117: case 118: case 119: + return filesys_fetch_callback(pmidp->item, inst, atom); + case 232: /* hinv.nfilesys */ + atom->ul = pmdaCacheOp(INDOM(pmidp->domain, FILESYS_INDOM), + PMDA_CACHE_SIZE_ACTIVE); + return 1; + case 233: /* hinv.pagesize */ + atom->ul = windows_pagesize; + return 1; + case 236: case 237: + return network_fetch_callback(pmidp->item, inst, atom); + } + + /* + * All other (most) metrics will go through this path + */ + vp = find_instance_value(pmidp->item, inst); + if (!vp) + return 0; + *atom = vp->atom; + return 1; +} + +/* + * Initialise the agent. + */ +void +windows_init(pmdaInterface *dp) +{ + static pmdaMetric *metrictab; + char helppath[MAXPATHLEN]; + int metrictab_sz = metricdesc_sz; + int i, sep = __pmPathSeparator(); + + snprintf(helppath, sizeof(helppath), "%s%c" "windows" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDSO(dp, PMDA_INTERFACE_3, "windows DSO", helppath); + if (dp->status != 0) + return; + + /* Create the PMDA's metrictab[] version of the per-metric table */ + metrictab = (pmdaMetric *)malloc(metrictab_sz * sizeof(pmdaMetric)); + if (metrictab == NULL) { + fprintf(stderr, "Error: malloc metrictab [%d] failed: %s\n", + metrictab_sz * sizeof(pmdaMetric), osstrerror()); + return; + } + + /* rewrite pmid & indom, now that we know what the domain number is */ + for (i = 0; i < metrictab_sz; i++) { + pdh_metric_t *mp = &metricdesc[i]; + pmID pmid = mp->desc.pmid; + mp->desc.pmid = pmid_build(dp->domain, pmid_cluster(pmid), pmid_item(pmid)); + if (mp->desc.indom != PM_INDOM_NULL) + mp->desc.indom = INDOM(dp->domain, mp->desc.indom); + } + + windows_open(dp->domain); + + /* write the metrictab entry for this metric, descriptor now setup */ + for (i = 0; i < metrictab_sz; i++) { + metrictab[i].m_desc = metricdesc[i].desc; + metrictab[i].m_user = NULL; + } + + dp->version.two.fetch = windows_fetch; + dp->version.two.instance = windows_instance; + dp->version.two.text = windows_help; + pmdaSetFetchCallBack(dp, windows_fetch_callback); + pmdaInit(dp, NULL, 0, metrictab, metrictab_sz); +} diff --git a/src/pmdas/windows/pmns.disk b/src/pmdas/windows/pmns.disk new file mode 100644 index 0000000..9849740 --- /dev/null +++ b/src/pmdas/windows/pmns.disk @@ -0,0 +1,52 @@ +disk { + all + dev +} + +disk.all { + read WINDOWS:0:15 + write WINDOWS:0:16 + total WINDOWS:0:17 + split_io WINDOWS:0:132 + read_bytes WINDOWS:0:18 + write_bytes WINDOWS:0:19 + total_bytes WINDOWS:0:20 + read_time WINDOWS:0:214 + write_time WINDOWS:0:215 + total_time WINDOWS:0:216 + average +} + +disk.dev { + read WINDOWS:0:21 + write WINDOWS:0:22 + total WINDOWS:0:23 + split_io WINDOWS:0:133 + read_bytes WINDOWS:0:24 + write_bytes WINDOWS:0:25 + total_bytes WINDOWS:0:26 + idle WINDOWS:0:68 + queue_len WINDOWS:0:101 + read_time WINDOWS:0:217 + write_time WINDOWS:0:218 + total_time WINDOWS:0:219 + average +} + +disk.all.average { + read_bytes WINDOWS:0:220 + write_bytes WINDOWS:0:221 + total_bytes WINDOWS:0:222 + read_time WINDOWS:0:223 + write_time WINDOWS:0:224 + total_time WINDOWS:0:225 +} + +disk.dev.average { + read_bytes WINDOWS:0:226 + write_bytes WINDOWS:0:227 + total_bytes WINDOWS:0:228 + read_time WINDOWS:0:229 + write_time WINDOWS:0:230 + total_time WINDOWS:0:231 +} diff --git a/src/pmdas/windows/pmns.filesys b/src/pmdas/windows/pmns.filesys new file mode 100644 index 0000000..20137c3 --- /dev/null +++ b/src/pmdas/windows/pmns.filesys @@ -0,0 +1,6 @@ +filesys { + full WINDOWS:0:67 + capacity WINDOWS:0:117 + used WINDOWS:0:118 + free WINDOWS:0:119 +} diff --git a/src/pmdas/windows/pmns.hinv b/src/pmdas/windows/pmns.hinv new file mode 100644 index 0000000..d5cd0d0 --- /dev/null +++ b/src/pmdas/windows/pmns.hinv @@ -0,0 +1,7 @@ +hinv { + physmem WINDOWS:0:106 + ncpu WINDOWS:0:107 + ndisk WINDOWS:0:108 + nfilesys WINDOWS:0:232 + pagesize WINDOWS:0:233 +} diff --git a/src/pmdas/windows/pmns.kernel b/src/pmdas/windows/pmns.kernel new file mode 100644 index 0000000..631e397 --- /dev/null +++ b/src/pmdas/windows/pmns.kernel @@ -0,0 +1,48 @@ +kernel { + all + percpu + num_processes WINDOWS:0:8 + num_threads WINDOWS:0:9 + uname +} + +kernel.all { + cpu + file + pswitch WINDOWS:0:10 + uptime WINDOWS:0:234 +} + +kernel.all.cpu { + user WINDOWS:0:0 + idle WINDOWS:0:1 + sys WINDOWS:0:2 + intr WINDOWS:0:3 +} + +kernel.percpu { + cpu +} + +kernel.percpu.cpu { + user WINDOWS:0:4 + idle WINDOWS:0:5 + sys WINDOWS:0:6 + intr WINDOWS:0:7 +} + +kernel.all.file { + read WINDOWS:0:11 + write WINDOWS:0:12 + read_bytes WINDOWS:0:13 + write_bytes WINDOWS:0:14 +} + +kernel.uname { + distro WINDOWS:0:109 + release WINDOWS:0:110 + version WINDOWS:0:111 + sysname WINDOWS:0:112 + machine WINDOWS:0:113 + nodename WINDOWS:0:114 +} diff --git a/src/pmdas/windows/pmns.mem b/src/pmdas/windows/pmns.mem new file mode 100644 index 0000000..be71ec6 --- /dev/null +++ b/src/pmdas/windows/pmns.mem @@ -0,0 +1,61 @@ +mem { + page_faults WINDOWS:0:27 + available WINDOWS:0:28 + committed_bytes WINDOWS:0:29 + pool + cache + commit_limit WINDOWS:0:136 + write_copies WINDOWS:0:137 + transition_faults WINDOWS:0:138 + demand_zero_faults WINDOWS:0:140 + pages_total WINDOWS:0:141 + page_reads WINDOWS:0:142 + pages_output WINDOWS:0:143 + page_writes WINDOWS:0:144 + system + physmem WINDOWS:1:0 + freemem WINDOWS:1:1 + util +} + +mem.util { + load WINDOWS:1:2 + used WINDOWS:1:3 + free WINDOWS:1:4 +} + +swap { + length WINDOWS:1:5 + used WINDOWS:1:6 + free WINDOWS:1:7 +} + +mem.pool { + paged_bytes WINDOWS:0:30 + non_paged_bytes WINDOWS:0:31 + paged_allocs WINDOWS:0:145 + nonpaged_allocs WINDOWS:0:146 + paged_resident_bytes WINDOWS:0:150 +} + +mem.cache { + read_ahead WINDOWS:0:35 + lazy_writes WINDOWS:0:32 + lazy_write_pages WINDOWS:0:33 + mdl + faults WINDOWS:0:139 + bytes WINDOWS:0:148 + bytes_peak WINDOWS:0:149 +} + +mem.cache.mdl { + read WINDOWS:0:34 + sync_read WINDOWS:0:36 + async_read WINDOWS:0:37 +} + +mem.system { + free_ptes WINDOWS:0:147 + total_code_bytes WINDOWS:0:151 + resident_code_bytes WINDOWS:0:152 +} diff --git a/src/pmdas/windows/pmns.network b/src/pmdas/windows/pmns.network new file mode 100644 index 0000000..7439944 --- /dev/null +++ b/src/pmdas/windows/pmns.network @@ -0,0 +1,42 @@ +network { + interface + tcp +} + +network.interface { + in + out + total + bandwidth WINDOWS:0:235 + speed WINDOWS:0:236 + baudrate WINDOWS:0:237 +} + +network.interface.in { + packets WINDOWS:0:38 + bytes WINDOWS:0:39 + errors WINDOWS:0:40 +} + +network.interface.out { + packets WINDOWS:0:41 + bytes WINDOWS:0:42 + errors WINDOWS:0:43 +} + +network.interface.total { + packets WINDOWS:0:44 + bytes WINDOWS:0:45 +} + +network.tcp { + activeopens WINDOWS:0:123 + passiveopens WINDOWS:0:124 + attemptfails WINDOWS:0:125 + estabresets WINDOWS:0:126 + currestab WINDOWS:0:127 + insegs WINDOWS:0:128 + outsegs WINDOWS:0:129 + totalsegs WINDOWS:0:130 + retranssegs WINDOWS:0:131 +} diff --git a/src/pmdas/windows/pmns.pmda b/src/pmdas/windows/pmns.pmda new file mode 100644 index 0000000..2eb3323 --- /dev/null +++ b/src/pmdas/windows/pmns.pmda @@ -0,0 +1,4 @@ +pmda { + uname WINDOWS:0:115 + version WINDOWS:0:116 +} diff --git a/src/pmdas/windows/pmns.process b/src/pmdas/windows/pmns.process new file mode 100644 index 0000000..a03999a --- /dev/null +++ b/src/pmdas/windows/pmns.process @@ -0,0 +1,59 @@ +process { + count WINDOWS:0:173 + psinfo + memory + io + thread +} + +process.psinfo { + pid WINDOWS:0:174 + ppid WINDOWS:0:175 + cpu_time WINDOWS:0:176 + elapsed_time WINDOWS:0:177 + utime WINDOWS:0:178 + stime WINDOWS:0:179 + nthreads WINDOWS:0:180 + priority_base WINDOWS:0:181 + nhandles WINDOWS:0:182 + page_faults WINDOWS:0:183 +} + +process.memory { + size WINDOWS:0:184 + rss WINDOWS:0:185 + rss_peak WINDOWS:0:186 + virtual WINDOWS:0:187 + virtual_peak WINDOWS:0:188 + page_file WINDOWS:0:189 + page_file_peak WINDOWS:0:190 + private WINDOWS:0:191 + pool_paged WINDOWS:0:192 + pool_nonpaged WINDOWS:0:193 +} + +process.io { + reads WINDOWS:0:194 + writes WINDOWS:0:195 + data WINDOWS:0:196 + other WINDOWS:0:197 + read_bytes WINDOWS:0:198 + write_bytes WINDOWS:0:199 + data_bytes WINDOWS:0:200 + other_bytes WINDOWS:0:201 +} + +process.thread { + context_switches WINDOWS:0:202 + cpu_time WINDOWS:0:203 + utime WINDOWS:0:204 + stime WINDOWS:0:205 + elapsed_time WINDOWS:0:206 + priority WINDOWS:0:207 + priority_base WINDOWS:0:208 + start_address WINDOWS:0:209 + state WINDOWS:0:210 + wait_reason WINDOWS:0:211 + process_id WINDOWS:0:212 + thread_id WINDOWS:0:213 +} diff --git a/src/pmdas/windows/pmns.sqlserver b/src/pmdas/windows/pmns.sqlserver new file mode 100644 index 0000000..ac29095 --- /dev/null +++ b/src/pmdas/windows/pmns.sqlserver @@ -0,0 +1,147 @@ +sqlserver { + access + buf_mgr + cache_mgr + databases + latches + locks + sql + connections WINDOWS:0:83 + mem_mgr + user_settable +} + +sqlserver.buf_mgr { + cache_hit_ratio WINDOWS:0:46 + page_lookups WINDOWS:0:47 + free_list_stalls WINDOWS:0:48 + free_pages WINDOWS:0:49 + total_pages WINDOWS:0:50 + target_pages WINDOWS:0:51 + database_pages WINDOWS:0:52 + reserved_pages WINDOWS:0:53 + stolen_pages WINDOWS:0:54 + lazy_writes WINDOWS:0:55 + readahead_pages WINDOWS:0:56 + procedure_cache_pages WINDOWS:0:57 + page_reads WINDOWS:0:58 + page_writes WINDOWS:0:59 + checkpoint_pages WINDOWS:0:60 + awe + page_life_expectancy WINDOWS:0:66 +} + +sqlserver.buf_mgr.awe { + lookup_maps WINDOWS:0:61 + stolen_maps WINDOWS:0:62 + write_maps WINDOWS:0:63 + unmap_calls WINDOWS:0:64 + unmap_pages WINDOWS:0:65 +} + +sqlserver.locks { + all + region +} + +sqlserver.locks.all { + requests WINDOWS:0:69 + waits WINDOWS:0:70 + deadlocks WINDOWS:0:71 + timeouts WINDOWS:0:72 + wait_time WINDOWS:0:73 + avg_wait_time WINDOWS:0:74 +} + +sqlserver.locks.region { + requests WINDOWS:0:75 + waits WINDOWS:0:76 + deadlocks WINDOWS:0:77 + timeouts WINDOWS:0:78 + wait_time WINDOWS:0:79 + avg_wait_time WINDOWS:0:80 +} + +sqlserver.cache_mgr { + all + cache +} + +sqlserver.cache_mgr.all { + cache_hit_ratio WINDOWS:0:81 + cache_pages WINDOWS:0:167 + cache_object_count WINDOWS:0:168 + cache_use WINDOWS:0:169 +} + +sqlserver.cache_mgr.cache { + cache_hit_ratio WINDOWS:0:82 + cache_pages WINDOWS:0:170 + cache_object_count WINDOWS:0:171 + cache_use WINDOWS:0:172 +} + +sqlserver.databases { + all + db +} + +sqlserver.databases.all { + transactions WINDOWS:0:84 + log_flushes WINDOWS:0:102 + log_bytes_flushed WINDOWS:0:104 + data_file_size WINDOWS:0:90 + log_file_size WINDOWS:0:91 + log_file_used WINDOWS:0:92 + active_transactions WINDOWS:0:134 +} + +sqlserver.databases.db { + transactions WINDOWS:0:85 + log_flushes WINDOWS:0:103 + log_bytes_flushed WINDOWS:0:105 + data_file_size WINDOWS:0:93 + log_file_size WINDOWS:0:94 + log_file_used WINDOWS:0:95 + active_transactions WINDOWS:0:135 +} + +sqlserver.latches { + waits WINDOWS:0:87 + wait_time WINDOWS:0:88 + avg_wait_time WINDOWS:0:89 +} + +sqlserver.sql { + batch_requests WINDOWS:0:86 + compilations WINDOWS:0:96 + re_compilations WINDOWS:0:97 +} + +sqlserver.access { + full_scans WINDOWS:0:98 + pages_allocated WINDOWS:0:99 + table_lock_escalations WINDOWS:0:100 + page_splits WINDOWS:0:122 +} + +sqlserver.mem_mgr { + connection_memory WINDOWS:0:153 + granted_workspace WINDOWS:0:154 + lock_memory WINDOWS:0:155 + lock_blocks_allocated WINDOWS:0:156 + lock_owner_blocks_allocated WINDOWS:0:157 + lock_blocks WINDOWS:0:158 + lock_owner_blocks WINDOWS:0:159 + maximum_workspace_memory WINDOWS:0:160 + memory_grants_outstanding WINDOWS:0:161 + memory_grants_pending WINDOWS:0:162 + optimizer_memory WINDOWS:0:163 + sql_cache_memory WINDOWS:0:164 + target_server_memory WINDOWS:0:165 + total_server_memory WINDOWS:0:166 +} + +sqlserver.user_settable { + query WINDOWS:0:238 +} diff --git a/src/pmdas/windows/root b/src/pmdas/windows/root new file mode 100644 index 0000000..2b4e3dc --- /dev/null +++ b/src/pmdas/windows/root @@ -0,0 +1,29 @@ +/* + * fake "root" for validating the local PMNS subtree + */ + +#include <stdpmid> + +root { + hinv + kernel + disk + filesys + mem + swap + network + sqlserver + pmda + process +} + +#include "pmns.hinv" +#include "pmns.kernel" +#include "pmns.disk" +#include "pmns.filesys" +#include "pmns.mem" +#include "pmns.network" +#include "pmns.sqlserver" +#include "pmns.pmda" +#include "pmns.process" + |