fbnet/command_runner/counters.py (49 lines of code) (raw):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
import gc
import os
import re
import threading
from collections import defaultdict
import psutil
from .base_service import ServiceObj
from .command_session import CommandSession
class Counters(ServiceObj):
"""
A bare minimum counters implementation
"""
_proc = psutil.Process(os.getpid())
def __init__(self, service, name):
super().__init__(service, name)
self.initCounters()
@classmethod
def register_counters(cls, stats_mgr):
stats_mgr.register_counter("sessions", CommandSession.get_session_count)
stats_mgr.register_counter("gc.garbage", lambda: len(gc.garbage))
stats_mgr.register_counter("active_threads", threading.activeCount)
stats_mgr.register_counter(
"cpu_usage_permille", lambda: round(cls._getCpuUsage() * 10)
)
@classmethod
def _getCpuUsage(cls):
return cls._proc.cpu_percent(interval=0)
def initCounters(self):
self.counters = defaultdict(int)
def register_counter(self, name, value=0):
if name not in self.counters:
self.counters[name] = value
def add_stats_counter(self, name, stats_types):
# Currently this only support simple counter, stats parameter are
# ignored
self.logger.info("stats counter not supported: %s %r", name, stats_types)
self.resetCounter(name)
def incrementCounter(self, name):
self.counters[name] += 1
def incrementCounterBy(self, name, amount):
self.counters[name] += amount
def getCounter(self, name):
v = self.counters[name]
return v() if callable() else v
def resetCounter(self, name, value=0):
self.counters[name] = value
def getCounters(self):
retval = {}
for k, v in self.counters.items():
retval[k] = v() if callable(v) else v
return retval
def getRegexCounters(self, regex):
rex = re.compile(regex)
return {k: v for k, v in self.getCounters().items() if rex.match(k)}