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
|
# RequestEntry ctor
|
||||||
create_request_entry = None
|
create_request_entry = None
|
||||||
|
|
||||||
|
# Circular debug log
|
||||||
|
debug = None
|
||||||
|
|
||||||
|
|
||||||
def exit_daemon():
|
def exit_daemon():
|
||||||
"""
|
"""
|
||||||
|
@ -88,6 +88,7 @@ class LvmFlightRecorder(object):
|
|||||||
for c in reversed(self.queue):
|
for c in reversed(self.queue):
|
||||||
log_error(str(c))
|
log_error(str(c))
|
||||||
log_error("LVM dbus flight recorder END")
|
log_error("LVM dbus flight recorder END")
|
||||||
|
self.queue.clear()
|
||||||
|
|
||||||
|
|
||||||
cfg.flightrecorder = LvmFlightRecorder()
|
cfg.flightrecorder = LvmFlightRecorder()
|
||||||
@ -176,6 +177,7 @@ def call_lvm(command, debug=False, line_cb=None,
|
|||||||
return -errno.EINTR, "", "operation interrupted"
|
return -errno.EINTR, "", "operation interrupted"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# The actual method which gets called to invoke the lvm command, can vary
|
# The actual method which gets called to invoke the lvm command, can vary
|
||||||
# from forking a new process to using lvm shell
|
# from forking a new process to using lvm shell
|
||||||
_t_call = call_lvm
|
_t_call = call_lvm
|
||||||
|
@ -195,6 +195,7 @@ class StateUpdate(object):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
st = traceback.format_exc()
|
st = traceback.format_exc()
|
||||||
log_error("update_thread exception: \n%s" % st)
|
log_error("update_thread exception: \n%s" % st)
|
||||||
|
cfg.debug.dump()
|
||||||
cfg.flightrecorder.dump()
|
cfg.flightrecorder.dump()
|
||||||
exception_count += 1
|
exception_count += 1
|
||||||
if exception_count >= 5:
|
if exception_count >= 5:
|
||||||
|
@ -25,7 +25,7 @@ from .manager import Manager
|
|||||||
import traceback
|
import traceback
|
||||||
import queue
|
import queue
|
||||||
from . import udevwatch
|
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 argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -147,6 +147,9 @@ def main():
|
|||||||
# cmdhandler is for when we are running other code with a different main.
|
# cmdhandler is for when we are running other code with a different main.
|
||||||
cfg.flightrecorder = LvmFlightRecorder(cfg.args.fr_size)
|
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)
|
log_debug("Using lvm binary: %s" % cfg.LVM_CMD)
|
||||||
|
|
||||||
# We will dynamically add interfaces which support vdo if it
|
# We will dynamically add interfaces which support vdo if it
|
||||||
|
@ -137,6 +137,7 @@ class Manager(AutomatedProperties):
|
|||||||
"""
|
"""
|
||||||
Dump the flight recorder to syslog
|
Dump the flight recorder to syslog
|
||||||
"""
|
"""
|
||||||
|
cfg.debug.dump()
|
||||||
cfg.flightrecorder.dump()
|
cfg.flightrecorder.dump()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -76,6 +76,7 @@ class RequestEntry(object):
|
|||||||
# have gotten a job by the time we hit an error
|
# have gotten a job by the time we hit an error
|
||||||
# Lets get the stacktrace and set that to the error message
|
# Lets get the stacktrace and set that to the error message
|
||||||
st = traceback.format_exc()
|
st = traceback.format_exc()
|
||||||
|
cfg.debug.dump()
|
||||||
cfg.flightrecorder.dump()
|
cfg.flightrecorder.dump()
|
||||||
log_error("Exception returned to client: \n%s" % st)
|
log_error("Exception returned to client: \n%s" % st)
|
||||||
self.register_error(-1, str(e), e)
|
self.register_error(-1, str(e), e)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import xml.etree.ElementTree as Et
|
import xml.etree.ElementTree as Et
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
|
import collections
|
||||||
import ctypes
|
import ctypes
|
||||||
import errno
|
import errno
|
||||||
import fcntl
|
import fcntl
|
||||||
@ -282,8 +283,28 @@ def parse_tags(tags):
|
|||||||
return dbus.Array([], signature='s')
|
return dbus.Array([], signature='s')
|
||||||
|
|
||||||
|
|
||||||
def _common_log(msg, *attributes):
|
class DebugMessages(object):
|
||||||
cfg.stdout_lock.acquire()
|
|
||||||
|
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)
|
tid = ctypes.CDLL('libc.so.6').syscall(186)
|
||||||
|
|
||||||
if STDOUT_TTY:
|
if STDOUT_TTY:
|
||||||
@ -293,6 +314,12 @@ def _common_log(msg, *attributes):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
msg = "%d:%d - %s" % (os.getpid(), tid, msg)
|
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:
|
if STDOUT_TTY and attributes:
|
||||||
print(color(msg, *attributes))
|
print(color(msg, *attributes))
|
||||||
@ -309,6 +336,9 @@ def _common_log(msg, *attributes):
|
|||||||
def log_debug(msg, *attributes):
|
def log_debug(msg, *attributes):
|
||||||
if cfg.args and cfg.args.debug:
|
if cfg.args and cfg.args.debug:
|
||||||
_common_log(msg, *attributes)
|
_common_log(msg, *attributes)
|
||||||
|
else:
|
||||||
|
if cfg.debug:
|
||||||
|
cfg.debug.add(_format_log_entry(msg))
|
||||||
|
|
||||||
|
|
||||||
def log_error(msg, *attributes):
|
def log_error(msg, *attributes):
|
||||||
@ -348,13 +378,15 @@ def handler(signum):
|
|||||||
try:
|
try:
|
||||||
# signal 10
|
# signal 10
|
||||||
if signum == signal.SIGUSR1:
|
if signum == signal.SIGUSR1:
|
||||||
|
cfg.debug.dump()
|
||||||
dump_threads_stackframe()
|
dump_threads_stackframe()
|
||||||
# signal 12
|
# signal 12
|
||||||
elif signum == signal.SIGUSR2:
|
elif signum == signal.SIGUSR2:
|
||||||
|
cfg.debug.dump()
|
||||||
cfg.flightrecorder.dump()
|
cfg.flightrecorder.dump()
|
||||||
else:
|
else:
|
||||||
cfg.run.value = 0
|
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:
|
if cfg.loop is not None:
|
||||||
cfg.loop.quit()
|
cfg.loop.quit()
|
||||||
except:
|
except:
|
||||||
|
Loading…
Reference in New Issue
Block a user