mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
lvmdbusd: Add debug circular buffer
When the daemon isn't started with --debug we will keep a circular buffer of the past N number of debug messages which we will output when we encounter an issue.
This commit is contained in:
parent
f65f7da760
commit
b0c7220dbb
@ -97,6 +97,9 @@ flightrecorder = None
|
||||
# RequestEntry ctor
|
||||
create_request_entry = None
|
||||
|
||||
# Circular debug log
|
||||
debug = None
|
||||
|
||||
|
||||
def exit_daemon():
|
||||
"""
|
||||
|
@ -88,6 +88,7 @@ class LvmFlightRecorder(object):
|
||||
for c in reversed(self.queue):
|
||||
log_error(str(c))
|
||||
log_error("LVM dbus flight recorder END")
|
||||
self.queue.clear()
|
||||
|
||||
|
||||
cfg.flightrecorder = LvmFlightRecorder()
|
||||
@ -176,6 +177,7 @@ def call_lvm(command, debug=False, line_cb=None,
|
||||
return -errno.EINTR, "", "operation interrupted"
|
||||
|
||||
|
||||
|
||||
# The actual method which gets called to invoke the lvm command, can vary
|
||||
# from forking a new process to using lvm shell
|
||||
_t_call = call_lvm
|
||||
|
@ -195,6 +195,7 @@ class StateUpdate(object):
|
||||
except Exception as e:
|
||||
st = traceback.format_exc()
|
||||
log_error("update_thread exception: \n%s" % st)
|
||||
cfg.debug.dump()
|
||||
cfg.flightrecorder.dump()
|
||||
exception_count += 1
|
||||
if exception_count >= 5:
|
||||
|
@ -25,7 +25,7 @@ from .manager import Manager
|
||||
import traceback
|
||||
import queue
|
||||
from . import udevwatch
|
||||
from .utils import log_debug, log_error, log_msg
|
||||
from .utils import log_debug, log_error, log_msg, DebugMessages
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
@ -147,6 +147,9 @@ def main():
|
||||
# cmdhandler is for when we are running other code with a different main.
|
||||
cfg.flightrecorder = LvmFlightRecorder(cfg.args.fr_size)
|
||||
|
||||
# Create a circular buffer for debug logs
|
||||
cfg.debug = DebugMessages()
|
||||
|
||||
log_debug("Using lvm binary: %s" % cfg.LVM_CMD)
|
||||
|
||||
# We will dynamically add interfaces which support vdo if it
|
||||
|
@ -137,6 +137,7 @@ class Manager(AutomatedProperties):
|
||||
"""
|
||||
Dump the flight recorder to syslog
|
||||
"""
|
||||
cfg.debug.dump()
|
||||
cfg.flightrecorder.dump()
|
||||
|
||||
@staticmethod
|
||||
|
@ -76,6 +76,7 @@ class RequestEntry(object):
|
||||
# have gotten a job by the time we hit an error
|
||||
# Lets get the stacktrace and set that to the error message
|
||||
st = traceback.format_exc()
|
||||
cfg.debug.dump()
|
||||
cfg.flightrecorder.dump()
|
||||
log_error("Exception returned to client: \n%s" % st)
|
||||
self.register_error(-1, str(e), e)
|
||||
|
@ -10,6 +10,7 @@
|
||||
import xml.etree.ElementTree as Et
|
||||
import sys
|
||||
import inspect
|
||||
import collections
|
||||
import ctypes
|
||||
import errno
|
||||
import fcntl
|
||||
@ -282,8 +283,28 @@ def parse_tags(tags):
|
||||
return dbus.Array([], signature='s')
|
||||
|
||||
|
||||
def _common_log(msg, *attributes):
|
||||
cfg.stdout_lock.acquire()
|
||||
class DebugMessages(object):
|
||||
|
||||
def __init__(self, size=5000):
|
||||
self.queue = collections.deque(maxlen=size)
|
||||
self.lock = threading.RLock()
|
||||
|
||||
def add(self, message):
|
||||
with self.lock:
|
||||
self.queue.append(message)
|
||||
|
||||
def dump(self):
|
||||
if cfg.args and not cfg.args.debug:
|
||||
with self.lock:
|
||||
if len(self.queue):
|
||||
log_error("LVM dbus debug messages START last (%d max) messages" % self.queue.maxlen)
|
||||
for m in self.queue:
|
||||
print(m)
|
||||
log_error("LVM dbus debug messages END")
|
||||
self.queue.clear()
|
||||
|
||||
|
||||
def _format_log_entry(msg):
|
||||
tid = ctypes.CDLL('libc.so.6').syscall(186)
|
||||
|
||||
if STDOUT_TTY:
|
||||
@ -293,6 +314,12 @@ def _common_log(msg, *attributes):
|
||||
|
||||
else:
|
||||
msg = "%d:%d - %s" % (os.getpid(), tid, msg)
|
||||
return msg
|
||||
|
||||
|
||||
def _common_log(msg, *attributes):
|
||||
cfg.stdout_lock.acquire()
|
||||
msg = _format_log_entry(msg)
|
||||
|
||||
if STDOUT_TTY and attributes:
|
||||
print(color(msg, *attributes))
|
||||
@ -309,6 +336,9 @@ def _common_log(msg, *attributes):
|
||||
def log_debug(msg, *attributes):
|
||||
if cfg.args and cfg.args.debug:
|
||||
_common_log(msg, *attributes)
|
||||
else:
|
||||
if cfg.debug:
|
||||
cfg.debug.add(_format_log_entry(msg))
|
||||
|
||||
|
||||
def log_error(msg, *attributes):
|
||||
@ -348,13 +378,15 @@ def handler(signum):
|
||||
try:
|
||||
# signal 10
|
||||
if signum == signal.SIGUSR1:
|
||||
cfg.debug.dump()
|
||||
dump_threads_stackframe()
|
||||
# signal 12
|
||||
elif signum == signal.SIGUSR2:
|
||||
cfg.debug.dump()
|
||||
cfg.flightrecorder.dump()
|
||||
else:
|
||||
cfg.run.value = 0
|
||||
log_debug('Exiting daemon with signal %d' % signum)
|
||||
log_error('Exiting daemon with signal %d' % signum)
|
||||
if cfg.loop is not None:
|
||||
cfg.loop.quit()
|
||||
except:
|
||||
|
Loading…
Reference in New Issue
Block a user