From: Brad Hubbard Date: Mon, 30 Apr 2018 03:05:13 +0000 (+1000) Subject: scripts: ceph_dump_log.py (initial commit) X-Git-Tag: v15.1.0~2776^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a35f3cb25c8720fa1ced352aad3fb72fe855be5f;p=ceph.git scripts: ceph_dump_log.py (initial commit) Signed-off-by: Brad Hubbard --- diff --git a/src/script/ceph_dump_log.py b/src/script/ceph_dump_log.py new file mode 100644 index 00000000000..5fb947d834b --- /dev/null +++ b/src/script/ceph_dump_log.py @@ -0,0 +1,92 @@ +# Copyright (C) 2018 Red Hat Inc. +# +# Authors: Sergio Lopez Pascual +# Brad Hubbard +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library Public License for more details. +# + +# By default ceph daemons and clients maintain a list of log_max_recent (default +# 10000) log entries at a high debug level. This script will attempt to dump out +# that log from a ceph::log::Log* passed to the ceph-dump-log function or, if no +# object is passed, default to the globally available 'g_ceph_context->_log' +# (thanks Kefu). This pointer may be obtained via the _log member of a +# CephContext object (i.e. *cct->_log) from any thread that contains such a +# CephContext. Normally, you will find a thread waiting in +# ceph::logging::Log::entry and the 'this' pointer from such a frame can also be +# passed to ceph-dump-log. + +import gdb +from datetime import datetime + +try: + # Python 2 forward compatibility + range = xrange +except NameError: + pass + +class CephDumpLog(gdb.Command): + def __init__(self): + super(CephDumpLog, self).__init__( + 'ceph-dump-log', + gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL, False) + + def invoke(self, args, from_tty): + arg_list = gdb.string_to_argv(args) + if len(arg_list) < 1: + log = gdb.parse_and_eval('g_ceph_context->_log') + else: + log = gdb.parse_and_eval(arg_list[0]) + + luminous_mimic = None + + try: + entry = log['m_recent']['m_head'] + size = log['m_recent']['m_len'] + luminous_mimic = True + except gdb.error: + entry = log['m_recent']['m_first'] + size = log['m_recent']['m_size'] + end = log['m_recent']['m_end'] + buff = log['m_recent']['m_buff'] + + for i in range(size): + if luminous_mimic: + try: # early luminous + stamp = int(str(entry['m_stamp']['tv']['tv_sec']) + str(entry['m_stamp']['tv']['tv_nsec'])) + logline = entry['m_streambuf']['m_buf'] + strlen = int(entry['m_streambuf']['m_buf_len']) + except gdb.error: # mimic + stamp = entry['m_stamp']['__d']['__r']['count'] + pptr = entry['m_data']['m_pptr'] + logline = entry['m_data']['m_buf'] + strlen = int(pptr - logline) + else: + stamp = entry['m_stamp']['__d']['__r']['count'] + logline = entry['str']['m_holder']['m_start'] + strlen = int(entry['str']['m_holder']['m_size']) + thread = entry['m_thread'] + prio = entry['m_prio'] + subsys = entry['m_subsys'] + dt = datetime.fromtimestamp(int(stamp) / 1e9) # Giving up some precision + gdb.write(dt.strftime('%Y-%m-%d %H:%M:%S.%f ')) + gdb.write("thread: {0:#x} priority: {1} subsystem: {2} ". + format(int(thread), prio, subsys)) + gdb.write(logline.string("ascii", errors='ignore')[0:strlen]) + gdb.write("\n") + if luminous_mimic: + entry = entry['m_next'].dereference() + else: + entry = entry + 1 + if entry >= end: + entry = buff + +CephDumpLog()