Source code for ruxit_mssql

"""
OneAgent MSSQL plugin
=====================

Gathers MSSQL stats.
The full description of stats is described at https://msdn.microsoft.com/en-us/en-en/library/ms190382(v=sql.110).aspx

MSSQL collect SQL server performance counters specified in JSON configuration using pywin32 which is a set of extension
modules that provides access to Windows API functions.

Plugin requires no configuration, database instance name is detected automatically from process snapshot.
"""

import collections
from ruxit.api.data import PluginMeasurement, PluginProperty
from ruxit.api.base_plugin import BasePlugin
import win32pdhquery, win32pdhutil, win32pdh
import logging

log = logging.getLogger(__name__)

CounterDesc = collections.namedtuple("CounterDesc", ["path", "handle", "timeseriesKey"])
"""
Namedtuple that is used for storing details about particular performance counter: whole path including object and metric name,
handle to counter and corresponding timeseries key.
"""

[docs]class MsSqlPlugin(BasePlugin): """ MSSQL plugin class. This plugin is stateful - initialize and close methods are defined in order to maintain one PDH query for the lifetime of the plugin. """
[docs] def initialize(self, **kwargs): """ Plugin initialization. This method includes opening PDH query, getting MSSQL instance name from snapshot and parsing plugin.json file in order to add all counters to query. """ self.q = win32pdh.OpenQuery() self.entity = kwargs["associated_entity"] self.timeseries = kwargs["json_config"]["metrics"] self.prefix = self.get_objectname_prefix() self.counters = [] self.add_counters()
[docs] def add_counters(self): """ Parses timeseries defined in plugin.json one by one and adds particular counters to query """ for metric in self.timeseries: path = metric['source']['query'] timeseriesKey = metric['timeseries']['key'] counter_path = '\\{prefix}:{pth}'.format(prefix=self.prefix, pth=path) try: counter_handle = win32pdh.AddCounter(self.q, counter_path) self.counters.append(CounterDesc(counter_path, counter_handle, timeseriesKey)) except: log.info(self, exc_info=1)
[docs] def get_objectname_prefix(self): """ Returns MSSQL performance counter object prefix depending on instance name provided in process snapshot. """ instance_name = self.entity.properties['mssql_instance_name'] if instance_name.upper() == 'MSSQLSERVER': return 'SQLServer' else: return 'MSSQL${instance_name}'.format(instance_name=instance_name)
[docs] def query(self, **kwargs): """ Performs collecting PDH data and sends results if valid. """ try: win32pdh.CollectQueryData(self.q) except: log.info(self, exc_info=1) for counter in self.counters: try: value = win32pdh.GetFormattedCounterValue(counter.handle, win32pdh.PDH_FMT_DOUBLE) if value[1] != -1: self.results_builder.add_absolute_result(PluginMeasurement( key=counter.timeseriesKey, value=value[1] )) except: log.info(self, exc_info=1)
[docs] def close(self, **kwargs): win32pdh.CloseQuery(self.q)