extras: Add NFS-specific log analyzer tool
Most of the time, a NFS request and the reply are separated by hundreds of lines of other debugging output most of which is not always relevant for NFS debugging. This script synthesizes the full glusterfs log into the parts relevant for NFS while bringing together the NFS requests with there replies on one line. Min log-level required for this script to be useful is DEBUG. Only works for NFS translator. Signed-off-by: Shehjar Tikoo <shehjart@gluster.com> Signed-off-by: Anand V. Avati <avati@dev.gluster.com> BUG: 913 (NFS-specific log analyzer tool) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=913
This commit is contained in:
parent
2848a53f53
commit
7c9df49689
143
extras/gnfs-loganalyse.py
Normal file
143
extras/gnfs-loganalyse.py
Normal file
@ -0,0 +1,143 @@
|
||||
#!/bin/python
|
||||
"""
|
||||
Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
|
||||
This file is part of GlusterFS.
|
||||
|
||||
GlusterFS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
GlusterFS 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
|
||||
|
||||
class NFSRequest:
|
||||
def __init__ (self, logline, linecount):
|
||||
self.calllinecount = 0
|
||||
self.xid = ""
|
||||
self.op = ""
|
||||
self.opdata = ""
|
||||
self.replydata = ""
|
||||
self.replylinecount = 0
|
||||
|
||||
tokens = logline.strip ().split (" ")
|
||||
if "XID:" not in tokens:
|
||||
return None
|
||||
|
||||
if "args:" not in tokens:
|
||||
return None
|
||||
|
||||
self.calllinecount = linecount
|
||||
|
||||
xididx = tokens.index ("XID:")
|
||||
self.xid = tokens [xididx+1].strip(",")
|
||||
|
||||
opidx = tokens.index ("args:")
|
||||
self.op = tokens [opidx-1].strip (":")
|
||||
self.opdata = " ".join(tokens [opidx+1:])
|
||||
|
||||
|
||||
def getXID (self):
|
||||
return self.xid
|
||||
|
||||
def setReply (self, logline, linecount):
|
||||
tokens = logline.strip ().split (" ")
|
||||
statidx = tokens.index ("NFS:")
|
||||
self.replydata = " ".join (tokens [statidx+1:])
|
||||
self.replylinecount = linecount
|
||||
|
||||
def dump (self):
|
||||
print "ReqLine: " + str(self.calllinecount) + " XID: " + self.xid + " " + self.op + " ARGS: " + self.opdata + " RepLine: " + str(self.replylinecount) + " " + self.replydata
|
||||
|
||||
class NFSLogAnalyzer:
|
||||
|
||||
def __init__ (self):
|
||||
self.xid_request_map = {}
|
||||
self.orphan_replies = {}
|
||||
self.CALL = 1
|
||||
self.REPLY = 2
|
||||
|
||||
def handle_call_line (self, logline, linecount):
|
||||
newreq = NFSRequest (logline, linecount)
|
||||
xid = newreq.getXID ()
|
||||
self.xid_request_map [xid] = newreq
|
||||
|
||||
def handle_reply_line (self, logline, linecount):
|
||||
tokens = logline.strip ().split (" ")
|
||||
|
||||
xididx = tokens.index ("XID:")
|
||||
xid = tokens [xididx + 1].strip(",")
|
||||
if xid not in self.xid_request_map.keys ():
|
||||
self.orphan_replies [xid] = logline
|
||||
else:
|
||||
self.xid_request_map [xid].setReply (logline, linecount)
|
||||
|
||||
def analyzeLine (self, logline, linecount):
|
||||
tokens = logline.strip ().split (" ")
|
||||
msgtype = 0
|
||||
|
||||
if "XID:" not in tokens:
|
||||
return
|
||||
|
||||
if "args:" in tokens:
|
||||
msgtype = self.CALL
|
||||
elif "NFS:" in tokens:
|
||||
msgtype = self.REPLY
|
||||
|
||||
if msgtype == self.CALL:
|
||||
self.handle_call_line (logline, linecount)
|
||||
elif msgtype == self.REPLY:
|
||||
self.handle_reply_line (logline, linecount)
|
||||
|
||||
def getStats (self):
|
||||
rcount = len (self.xid_request_map.keys ())
|
||||
orphancount = len (self.orphan_replies.keys ())
|
||||
print "Requests: " + str(rcount) + ", Orphans: " + str(orphancount)
|
||||
|
||||
def dump (self):
|
||||
self.getStats ()
|
||||
for rq in self.xid_request_map.values ():
|
||||
rq.dump ()
|
||||
|
||||
|
||||
|
||||
|
||||
linecount = 0
|
||||
la = NFSLogAnalyzer ()
|
||||
|
||||
progmsgcount = 1000
|
||||
dumpinterval = 2000000
|
||||
|
||||
if "--progress" in sys.argv:
|
||||
idx = sys.argv.index ("--progress")
|
||||
progmsgcount = int(sys.argv[idx+1])
|
||||
|
||||
|
||||
if "--dump" in sys.argv:
|
||||
idx = sys.argv.index ("--dump")
|
||||
dumpinterval = int(sys.argv[idx+1])
|
||||
|
||||
for line in sys.stdin:
|
||||
linecount = linecount + 1
|
||||
if linecount % dumpinterval == 0:
|
||||
sys.stderr.write ("Dumping data..\n")
|
||||
la.dump ()
|
||||
la = NFSLogAnalyzer ()
|
||||
|
||||
if linecount % progmsgcount == 0:
|
||||
sys.stderr.write ("Integrating line: "+ str(linecount) + "\n")
|
||||
la.analyzeLine (line, linecount)
|
||||
|
||||
la.dump ()
|
Loading…
x
Reference in New Issue
Block a user