Exemplo n.º 1
0
    def collect_counters(self):
        counters, instances = win32pdh.EnumObjectItems(
            None, self._machine_name, self.class_name, win32pdh.PERF_DETAIL_WIZARD
        )
        if self._instance_name is None and len(instances) > 0:
            all_instances = set()
            for inst in instances:
                path = self._make_counter_path(self._machine_name, self._counter_name, inst, counters)
                if not path:
                    continue
                all_instances.add(inst)

                try:
                    if inst not in self.counterdict:
                        self.logger.debug('Adding instance `%s`', inst)
                        self.counterdict[inst] = win32pdh.AddCounter(self.hq, path)
                except:  # noqa: E722, B001
                    self.logger.fatal(
                        "Failed to create counter.  No instances of %s\\%s" % (self.class_name, self._counter_name)
                    )

            expired_instances = set(self.counterdict) - all_instances
            for inst in expired_instances:
                self.logger.debug('Removing expired instance `%s`', inst)
                del self.counterdict[inst]
        else:
            if self._instance_name is not None:
                # check to see that it's valid
                if len(instances) <= 0:
                    self.logger.error(
                        "%s doesn't seem to be a multi-instance counter, but asked for specific instance %s",
                        self.class_name,
                        self._instance_name,
                    )
                    raise AttributeError("%s is not a multi-instance counter" % self.class_name)
                if self._instance_name not in instances:
                    self.logger.error("%s is not a counter instance in %s", self._instance_name, self.class_name)
                    raise AttributeError("%s is not an instance of %s" % (self._instance_name, self.class_name))

            path = self._make_counter_path(self._machine_name, self._counter_name, self._instance_name, counters)
            if not path:
                self.logger.warning("Empty path returned")
            elif win32pdh.ValidatePath(path) != 0:
                # Multi-instance counter with no instances presently
                pass
            else:
                try:
                    if SINGLE_INSTANCE_KEY not in self.counterdict:
                        self.logger.debug('Adding single instance for path `%s`', path)
                        self.counterdict[SINGLE_INSTANCE_KEY] = win32pdh.AddCounter(self.hq, path)
                except:  # noqa: E722, B001
                    self.logger.fatal(
                        "Failed to create counter.  No instances of %s\\%s" % (self.class_name, self._counter_name)
                    )
                    raise
                self._is_single_instance = True
Exemplo n.º 2
0
    def build_counter(obj, instance, instance_index, counter):
        r"""
        Makes a fully resolved counter path. Counter names are formatted like
        this:

        ``\Processor(*)\% Processor Time``

        The above breaks down like this:

            obj = 'Processor'
            instance = '*'
            counter = '% Processor Time'

        Args:

            obj (str):
                The top level object

            instance (str):
                The instance of the object

            instance_index (int):
                The index of the instance. Can usually be 0

            counter (str):
                The name of the counter

        Returns:
            Counter: A Counter object with the path if valid

        Raises:
            CommandExecutionError: If the path is invalid
        """
        path = win32pdh.MakeCounterPath(
            (None, obj, instance, None, instance_index, counter), 0
        )
        if win32pdh.ValidatePath(path) == 0:
            return Counter(path, obj, instance, instance_index, counter)
        raise CommandExecutionError("Invalid counter specified: {0}".format(path))
Exemplo n.º 3
0
def browse(counterset):
    """
    Explore performance counters.

    You'll need to install pywin32 manually beforehand.
    """
    # Leave imports in function to not add the dependencies
    import win32pdh

    if not counterset:
        echo_info('Searching for available countersets:')
        countersets = sorted(
            win32pdh.EnumObjects(None, None, win32pdh.PERF_DETAIL_WIZARD,
                                 True))
        for name in countersets:
            echo_info(name)

        return

    description_prefix = '    Description: '
    description_indent = ' ' * len(description_prefix)

    def display_counter(handle):
        counter_info = win32pdh.GetCounterInfo(handle, True)
        counter_description = counter_info[-1]

        counter_type = counter_info[0]
        if counter_type in COUNTER_TYPES:
            counter_type_name = COUNTER_TYPES[counter_type][0]
        else:
            counter_type_name = 'unknown'

        echo_info(f'--> {counter}')
        echo_info(f'    Type: {counter_type_name}')
        echo_info(description_prefix, nl=False)
        echo_info(
            textwrap.indent(textwrap.fill(counter_description),
                            description_indent).lstrip())

    query_handle = win32pdh.OpenQuery()

    try:
        header = f'<<< {counterset} >>>'
        echo_info(header)
        echo_info('-' * len(header))
        echo_info('')
        counters, instances = win32pdh.EnumObjectItems(
            None, None, counterset, win32pdh.PERF_DETAIL_WIZARD)
        counters.sort()

        if instances:
            header = 'Instances'
            echo_info(header)
            echo_info('=' * len(header))
            instance_index = defaultdict(int)
            for instance in instances:
                instance_index[instance] += 1
                echo_info(instance)
            echo_info('')

            header = 'Counters'
            echo_info(header)
            echo_info('=' * len(header))

            for counter in counters:
                for instance, num_instances in instance_index.items():
                    for index in range(num_instances):
                        path = win32pdh.MakeCounterPath(
                            (None, counterset, instance, None, index, counter))
                        counter_handle = win32pdh.AddCounter(
                            query_handle, path)
                        display_counter(counter_handle)

                        # Only need information from one instance
                        break
                    break
        else:
            header = 'Counters'
            echo_info(header)
            echo_info('=' * len(header))

            for counter in counters:
                path = win32pdh.MakeCounterPath(
                    (None, counterset, None, None, 0, counter))
                if win32pdh.ValidatePath(path) != 0:
                    echo_info(f'--> {counter}')
                    echo_info('    Error: no current instances')
                    continue

                counter_handle = win32pdh.AddCounter(query_handle, path)
                display_counter(counter_handle)
    finally:
        win32pdh.CloseQuery(query_handle)
Exemplo n.º 4
0
    def extract(self):
        def getQueryValue(data,key):
            if key in data:
                return data[key]
            else:
                return None

        paths = [   
                    ('cpu-total','Processor','_Total','% Processor Time'),
                    ('cpu-us','Processor','_Total','% User Time'),
                    ('cpu-sy','Processor','_Total','% Privileged Time'),
                    ('cpu-r','System',None,'Processor Queue Length'),
                    ('mem-free','Memory',None,'Available Mbytes'),
                    ('mem-pages-ps','Memory',None,'Pages/sec'),
                    ('disk-readtime','PhysicalDisk','_Total','% Disk Read Time'),
                    ('disk-writetime','PhysicalDisk','_Total','% Disk Write Time'),
                    ('disk-queue','PhysicalDisk','_Total','Current Disk Queue Length'),
                    ('disk-rbps','PhysicalDisk','_Total','Disk Read Bytes/sec'),
                    ('disk-wbps','PhysicalDisk','_Total','Disk Write Bytes/sec'),
                    ('disk-rps','PhysicalDisk','_Total','Disk Reads/sec'),
                    ('disk-wps','PhysicalDisk','_Total','Disk Writes/sec'),
                    ('sql-qps','SQLServer:SQL Statistics',None,'Batch Requests/sec'),
                    ('sql-tps','SQLServer:Databases','_Total','Transactions/sec'),
                    ('sql-connections','SQLServer:General Statistics',None,'User Connections'),
                    ('sql-fullscans','SQLServer:Access Methods',None,'Full Scans/sec'),
                    ('sql-targetmemory','SQLServer:Memory Manager',None,'Target Server Memory (KB)'),
                    ('sql-totalmemory','SQLServer:Memory Manager',None,'Total Server Memory (KB)'),
                    ('sql-dataspace','SQLServer:Databases','_Total','Data File(s) Size (KB)'),
                    ('sql-logspace','SQLServer:Databases','_Total','Log File(s) Size (KB)'),
                    ('sql-cachehitratio','SQLServer:Buffer Manager',None,'Buffer cache hit ratio'),
                    ('ws-bps','Web Service','_Total','Bytes Total/sec'),
                    ('ws-rps','Web Service','_Total','Total Method Requests/sec'),
                    ('ws-connections','Web Service','_Total','Current Connections')
                    #('ni-bps','Network Interface','_Total','Bytes Total/sec')                                    

                ]

        counters, instances = win32pdh.EnumObjectItems(None, None, 'Network Interface', win32pdh.PERF_DETAIL_WIZARD)
        #print instances            

        for i, n in enumerate(instances):
            paths.append( ('ni-bps' + str(i),'Network Interface',n,'Bytes Total/sec') )

        #print paths

        counters = {}

        base = win32pdh.OpenQuery()
        #print base

        for path in paths:
            counterPath = win32pdh.MakeCounterPath( (None,path[1],path[2], None, -1, path[3]) ) 
            
            if win32pdh.ValidatePath(counterPath) == 0:
                #print path
                counter = win32pdh.AddCounter(base, counterPath)
                #print counter
                counters[path[0]] = counter
            #else:
                #print path[0], '------path is not valid'

        # collect the data for the query object. We need to collect the query data
        # twice to be able to calculate the % Processor Time 
        win32pdh.CollectQueryData(base)
        set1 = self.getProcess()

        time.sleep(1)
        win32pdh.CollectQueryData(base)

        queryData = {}
        nibps = 0

        # Get the formatted value of the counter
        for key in counters.keys():
            if key.find('ni-bps') == 0:
                nibps += win32pdh.GetFormattedCounterValue(counters[key],win32pdh.PDH_FMT_LONG)[1]
            else: 
                queryData[key] = win32pdh.GetFormattedCounterValue(counters[key],win32pdh.PDH_FMT_LONG)[1]

        queryData['ni-bps'] = nibps

        win32pdh.CloseQuery(base)

        info = {}

        cpu = {}
        cpu["us"] = getQueryValue(queryData,"cpu-us")
        cpu["sy"] = getQueryValue(queryData,"cpu-sy")
        
        cpu["id"] = 100 - float(getQueryValue(queryData,"cpu-total"))
        cpu["r"] = getQueryValue(queryData,"cpu-r")

        memory = {}
        memory["free"] = getQueryValue(queryData,"mem-free")
        memory["pages-ps"] = getQueryValue(queryData,"mem-pages-ps")

        disk = {}
        disk["readtime"] = getQueryValue(queryData,"disk-readtime")
        disk["writetime"] = getQueryValue(queryData,"disk-writetime")
        disk["queue"] = getQueryValue(queryData,"disk-queue")
        disk["rbps"] = getQueryValue(queryData,"disk-rbps")
        disk["wbps"] = getQueryValue(queryData,"disk-wbps")
        disk["bps"] = disk["rbps"] + disk["wbps"]
        disk["rps"] = getQueryValue(queryData,"disk-rps")
        disk["wps"] = getQueryValue(queryData,"disk-wps")
        disk["iops"] = disk["rps"] + disk["wps"]

        
        freespace,disksize = self.getDiskSize()
        #print freespace,disksize
        if(disksize > 0):    
            disk["size"] = disksize/(1024*1024)
            disk["used"] = (disksize - freespace) / (1024*1024)
            disk["use"] = disk["used"] * 100 / disk["size"]
        
        if("sql-qps" in queryData):
            database = {}
            sqlserver = {}

            sqlserver["qps"] = getQueryValue(queryData,"sql-qps")
            sqlserver["tps"] = getQueryValue(queryData,"sql-tps")
            sqlserver["connections"] = getQueryValue(queryData,"sql-connections")
            sqlserver["fullscans"] = getQueryValue(queryData,"sql-fullscans")
            sqlserver["targetmemory"] = getQueryValue(queryData,"sql-targetmemory")
            sqlserver["totalmemory"] = getQueryValue(queryData,"sql-totalmemory")
            sqlserver["dataspace"] = getQueryValue(queryData,"sql-dataspace")
            sqlserver["logspace"] = getQueryValue(queryData,"sql-logspace")
            sqlserver["cachehitratio"] = getQueryValue(queryData,"sql-cachehitratio")
           
            database["sqlserver"] = sqlserver

            info["database"] = database


        webserver =  {}
        iis = {}

        
        if("ws-bps" in queryData):
            iis["bps"] = getQueryValue(queryData,"ws-bps")
            iis["rps"] = getQueryValue(queryData,"ws-rps")
            iis["connections"] = getQueryValue(queryData,"ws-connections")
        #iis["requestqueued"] = float(result[col+3]) #+  float(result[col+4])
    

        webserver['iis'] = iis
        info["webserver"] = webserver

        network = {}
        network["bps"] = getQueryValue(queryData,"ni-bps")

        process = []

        
        
        set2 = self.getProcess()
        

        #self.logger.debug(set1)
        #self.logger.debug(set2)
        
        totaltime = set2['total'] - set1['total']

        
        for s in set1:
            if s == 'total' :  continue
            
            if(set2.has_key(s)):
                proc = {}
                proc["pid"] = s

                if totaltime > 0:
                    proc["cpu"] = (sum(set2[s][0:2]) - sum(set1[s][0:2]) )* 100 / totaltime
                else:
                    proc["cpu"] = 0   

                proc["mem"] = set2[s][2]
                proc["mem2"] = set2[s][3]
                proc["name"] = set2[s][4]
                proc["command"] = set2[s][5]
                process.append(proc)
            
        process = sorted(process, key=lambda d: d["cpu"])
        if len(process) > 10:
            process = process[-11:]
            
        info["infoid"] = str(uuid.uuid1())
        info["machineid"] = str(uuid.getnode())
        info["timestamp"] =  time.strftime("%Y%m%d%H%M%S", time.localtime())
        info["os"] = "windows"
        info["appkey"] = self.AppKey
        info["cpu"] = cpu
        info["memory"] = memory
        info["disk"] = disk
        info["network"] = network
        info["process"] = process

        self.val["info"] = info
        #pythoncom.CoUninitialize()
        return self.val
Exemplo n.º 5
0
    def _configure_counters(self, available_counters, available_instances):
        if not available_counters:
            return

        if self.use_localized_counters:
            # https://docs.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhaddcountera
            # https://mhammond.github.io/pywin32/win32pdh__AddCounter_meth.html
            counter_selector = win32pdh.AddCounter
        else:
            # https://docs.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhaddenglishcountera
            # https://mhammond.github.io/pywin32/win32pdh__AddEnglishCounter_meth.html
            counter_selector = win32pdh.AddEnglishCounter

        if available_instances:
            counter_type = MultiCounter
            self.has_multiple_instances = True
        else:
            possible_path = construct_counter_path(
                machine_name=self.connection.server, object_name=self.name, counter_name=available_counters[0]
            )

            # https://docs.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhvalidatepatha
            # https://mhammond.github.io/pywin32/win32pdh__ValidatePath_meth.html
            if win32pdh.ValidatePath(possible_path) == 0:
                counter_type = SingleCounter
                self.has_multiple_instances = False
            # Multi-instance counter with no instances presently
            else:
                counter_type = MultiCounter
                self.has_multiple_instances = True

        tag_name = self.tag_name
        if self.has_multiple_instances:
            if not tag_name:
                tag_name = 'instance'
        else:
            if tag_name:
                self._log_multi_instance_option_defined('tag_name')
            if self.include_pattern is not None:
                self._log_multi_instance_option_defined('include')
            if self.exclude_pattern.pattern.count('|') > 0:
                self._log_multi_instance_option_defined('exclude')
            if (
                self.instance_count_total_metric
                or self.instance_count_monitored_metric
                or self.instance_count_unique_metric
            ):
                self._log_multi_instance_option_defined('instance_counts')

        custom_transformers = self.get_custom_transformers()
        counters = {}
        for i, entry in enumerate(self.counters_config, 1):
            if not isinstance(entry, dict):
                raise ConfigTypeError(
                    f'Entry #{i} of option `counters` for performance object `{self.name}` must be a mapping'
                )

            for counter_name, counter_config in entry.items():
                if isinstance(counter_config, str):
                    counter_config = {'name': counter_config}
                elif not isinstance(counter_config, dict):
                    raise ConfigTypeError(
                        f'Counter `{counter_name}` for performance object `{self.name}` must be a string or mapping'
                    )
                elif counter_name in counters:
                    raise ConfigValueError(
                        f'Counter `{counter_name}` for performance object `{self.name}` is already defined'
                    )

                if counter_type is SingleCounter:
                    counters[counter_name] = counter_type(
                        counter_name,
                        counter_config,
                        self.check,
                        self.connection,
                        self.name,
                        self.metric_prefix,
                        counter_selector,
                        self.tags,
                        custom_transformers.get(counter_name),
                    )
                else:
                    counters[counter_name] = counter_type(
                        counter_name,
                        counter_config,
                        self.check,
                        self.connection,
                        self.name,
                        self.metric_prefix,
                        counter_selector,
                        self.tags,
                        custom_transformers.get(counter_name),
                        tag_name,
                    )

        self.counters.extend(counters.values())