def check_parallel_run(self): # TODO: other daemon run on nt if os.name == 'nt': logger.warning("The parallel daemon check is not available on nt") self.open_pidfile(write=True) return # First open the pid file in open mode self.open_pidfile() try: buf = self.fpid.readline().strip(' \r\n') if not buf: # pid file was void, cool return pid = int(buf) except Exception as err: logger.info("Stale pidfile exists at %s (%s). Reusing it." % (err, self.lock_path)) return try: os.kill(pid, 0) except Exception as err: # consider any exception as a stale pidfile. # this includes : # * PermissionError when a process with same pid exists but is executed by another user. # * ProcessLookupError: [Errno 3] No such process. logger.info("Stale pidfile exists (%s), Reusing it." % err) return logger.error("Valid previous daemon exists (pid=%s) Exiting." % pid) raise SystemExit(2)
def _parse_cgroup_file(self, stat_file): try: logger.debug("Opening cgroup file: %s" % stat_file) with open(stat_file) as fp: return dict(map(lambda x: x.split(), fp.read().splitlines())) except IOError: # It is possible that the container got stopped between the API call and now logger.info("Can't open %s. Theses metrics for this container are skipped." % stat_file) return None
def graphite_reaper(self): while True: graphite_queue = self.graphite_queue self.graphite_queue = [] if len(graphite_queue) > 0: logger.info("Graphite queue", len(graphite_queue)) for data in graphite_queue: T0 = time.time() self.grok_graphite_data(data) STATS.timer('ts.graphite.grok-graphite-data', (time.time() - T0)*1000) time.sleep(0.1)
def w(): tid = 0 if libc: tid = libc.syscall(186) # get the threadid when you are in it :) logger.info('THREAD launch (%s) with thread id (%d)' % (name, tid)) try: f(*args) except Exception, exp: output = cStringIO.StringIO() traceback.print_exc(file=output) logger.error("Thread %s is exiting on error. Back trace of this error: %s" % (name, output.getvalue())) output.close()
def w(is_essential): tid = 0 if libc: tid = libc.syscall(186) # get the threadid when you are in it :) logger.info("THREAD launch (%s) with thread id (%d)" % (name, tid)) try: f(*args) except Exception, exp: output = cStringIO.StringIO() traceback.print_exc(file=output) logger.error("Thread %s is exiting on error. Back trace of this error: %s" % (name, output.getvalue())) output.close() if is_essential: # Maybe the thread WAS an essential one (like http thread or something like this), if so # catch it and close the whole daemon logger.error( "The thread %s was an essential one, we are stopping the daemon do not be in an invalid state" % name ) pubsub.pub("interrupt")
def do_reaper_thread(self): while True: now = int(time.time()) m = divmod(now, 60)[0]*60 # current minute all_names = [] with self.data_lock: all_names = self.data.keys() logger.info("DOING reaper thread on %d elements" % len(all_names)) for name in all_names: # Grok all minute entries if name.startswith('min::'): e = self.data.get(name, None) # maybe some one delete the entry? should not be possible if e is None: continue ctime = e['ctime'] logger.debug("REAPER old data for ", name) # if the creation time of this structure is too old and # really for data, force to save the entry in KV entry if ctime < now - self.max_data_age and e['nb'] > 0: STATS.incr('reaper-old-data', 1) logger.debug("REAPER TOO OLD DATA FOR", name) # get the raw metric name _id = name[5:] self.archive_minute(e, _id) # the element was too old, so we can assume it won't be upadte again. Delete it's entry try: del self.data[name] except: pass ''' # and set a new minute, the next one n_minute = e['cur_min'] + 60 e = {'cur_min':n_minute, 'sum':0, 'min':None, 'max':None, 'values':[None for _ in xrange(60)], 'nb':0, 'ctime':now} self.data[name] = e ''' time.sleep(10)
def launch(self): logger.debug('getMongoDBStatus: start') if 'MongoDBServer' not in self.config or self.config['MongoDBServer'] == '': logger.debug('getMongoDBStatus: config not set') #return False logger.debug('getMongoDBStatus: config set') try: import pymongo from pymongo import Connection except ImportError: logger.error('Unable to import pymongo library') return False try: parsed = urlparse.urlparse(self.config.get('mongodb_server', 'mongodb://localhost')) mongoURI = '' # Can't use attributes on Python 2.4 if parsed[0] != 'mongodb': mongoURI = 'mongodb://' if parsed[2]: if parsed[0]: mongoURI = mongoURI + parsed[0] + ':' + parsed[2] else: mongoURI = mongoURI + parsed[2] else: mongoURI = self.config.get('mongodb_server', 'mongodb://localhost') logger.debug('-- mongoURI: %s', mongoURI) conn = Connection(mongoURI, slave_okay=True) logger.debug('Connected to MongoDB') except pymongo.errors.ConnectionFailure, exp: logger.info('Unable to connect to MongoDB server %s - Exception = %s' % (mongoURI, exp)) return False
self.containers[_id] = c def load_containers(self): if not self.con: return try: conts = get_json('/containers/json', local_socket='/var/run/docker.sock') except request_errors, exp: self.connect() return for c in conts: _id = c.get('Id') self.load_container(_id) logger.info("Loading docker container %s" % _id) logger.debug("Container data", self.containers[_id]) def load_images(self): if not self.con: return try: self.images = get_json('/images/json', local_socket='/var/run/docker.sock') except request_errors, exp: self.connect() return def compute_stats(self):
def unlink(self): logger.info("Unlinking lock file %s" % self.lock_path) try: os.unlink(self.lock_path) except Exception, e: logger.error("Got an error unlinking our pidfile: %s" % (e))
# halfway to daemonize.. os.setsid() try: pid = os.fork() except OSError, e: raise Exception, "%s [%d]" % (e.strerror, e.errno) if pid != 0: # we are the last step and the real daemon is actually correctly created at least. # we have still the last responsibility to write the pid of the daemon itself. self.write_pid(pid) os._exit(0) # <-- this was the son, the real daemon is the son-son self.fpid.close() del self.fpid self.pid = os.getpid() logger.info("Daemonization done: pid=%d" % self.pid) def do_daemon_init_and_start(self, is_daemon=False): self.change_to_workdir() self.check_parallel_run() # Force the debug level if the daemon is said to start with such level if self.debug_path: logger.setLevel('DEBUG') # If daemon fork() until we reach the final step if is_daemon: self.daemonize() else: self.write_pid()
except OSError, e: logger.debug('getMemoryUsage: sysinfo not available') except Exception, e: logger.error('getMemoryUsage: exception = %s', traceback.format_exc()) finally: if int(pythonVersion[1]) >= 6: try: proc.kill() except Exception, e: logger.debug('Process already terminated') if physFree == None: logger.info('getMemoryUsage: sysinfo not installed so falling back on sysctl. sysinfo provides more accurate memory info so is recommended. http://www.freshports.org/sysutils/sysinfo') try: try: logger.debug('getMemoryUsage: attempting Popen (sysctl)') proc = subprocess.Popen(['sysctl', '-n', 'hw.physmem'], stdout = subprocess.PIPE, close_fds = True) physTotal = proc.communicate()[0] if int(pythonVersion[1]) >= 6: try: proc.kill() except Exception, e: logger.debug('Process already terminated') logger.debug('getMemoryUsage: attempting Popen (vmstat)')