attachment upload
authorhttps://me.yahoo.com/hanki_pank#f42c5 <Christof_Hanke@web>
Tue, 26 Oct 2010 08:53:02 +0000 (01:53 -0700)
committerOpenAFS Wiki <ikiwiki@openafs.org>
Tue, 26 Oct 2010 08:53:02 +0000 (01:53 -0700)
AFSLore/debugging/ClientTracing.py [new file with mode: 0644]

diff --git a/AFSLore/debugging/ClientTracing.py b/AFSLore/debugging/ClientTracing.py
new file mode 100644 (file)
index 0000000..f73b0e1
--- /dev/null
@@ -0,0 +1,234 @@
+#!/usr/bin/env python
+
+"""
+Small utility to continuous trace an afs-client in a files storing x mins and keep files if something has happened
+"""
+
+import subprocess, time, getopt, sys
+from multiprocessing import Process
+from shutil import copyfile
+import os, string
+
+Output="afsclient.trace"
+ProcessTableFilename="proctable"
+numTraceFiles=2
+TraceFileNames=[]
+FSTRACEBIN="/usr/sbin/fstrace"
+PSBIN="/bin/ps"
+KILLBIN="/bin/kill"
+TraceBufferSize=8192 # buffersize in k, needs to be big enough to store the data during Dumpinterval
+Dumpinterval = 1 # at what interval buffer should be dumped to file
+DumpProcs=[None, None]
+EventCheckInterval = 1 # interval for checking for an externalEvent
+RotationInterval=5 # 5 EventCheckInterval
+EventFile="./fstrace_trigger"
+verbose = False
+debug=False
+Mode="cont" 
+# available Modes
+# cont(inuous)
+# single 
+
+def setupFSTrace() :
+    if verbose : print "Clearing log"
+    try :
+        subprocess.check_call([FSTRACEBIN,"clear",  "cm"])
+    except subprocess.CalledProcessError:
+        print "Unable to run fstrace-binary at %s." % FSTRACEBIN
+        sys.exit(2)
+    if verbose : print "setting eventset cm active"
+    subprocess.check_call([FSTRACEBIN,"setset","cm","-active"])
+    if verbose :  print "Setting buffersize of log cmfx"
+    subprocess.check_call([FSTRACEBIN,"setlog","cmfx","-buffersize", "%s" % TraceBufferSize])
+    return 
+    
+def dumpFSTrace(FileName) :
+    subprocess.check_call([FSTRACEBIN,"dump","-follow","cmfx","-file",FileName, "-sleep", "%s" % Dumpinterval])
+    return
+
+def saveLogs(ProcessTable, TraceFileNo):
+    NowStr=time.strftime("%H:%M:%S_%d.%m-%Y", time.localtime())
+    for counter in range(numTraceFiles) :
+        thisTraceFileNo=(TraceFileNo+counter) % numTraceFiles
+        print "current TraceFileNo = %s" % TraceFileNo
+        if verbose : print "Saving log %s-%s to %s-%s-%s" %  (Output,thisTraceFileNo,  Output,counter,  NowStr)
+        copyfile("%s-%s" % (Output, thisTraceFileNo), "%s-%s-%s" % ( Output,counter,  NowStr))
+    # also save ProcessTable of this interval
+    if verbose : print "Saving ProcessTable to %s-%s" %  (ProcessTableFilename,NowStr)
+    f=file("%s-%s" % (ProcessTableFilename,NowStr), "w+")
+    _PIDs=ProcessTable.keys()
+    PIDs=[]
+    for pid in _PIDs :
+        PIDs.append(int(pid))
+    PIDs.sort()
+    for pid in PIDs :
+        f.write("%s %s %s\n" % (pid, ProcessTable["%s" % pid]["parentpid"],ProcessTable["%s" % pid]["cmd"]))
+    f.close()
+    return
+    
+def updateProcessTable():
+    ProcessTable={}
+    call=subprocess.Popen([PSBIN, "-eaf"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    line=call.stdout.readline() # ignore headerline
+    while 1:
+        line=call.stdout.readline()
+        if not line :break
+        tokens=line.split()
+        if len(tokens) < 8 : continue
+        pid=tokens[1]
+       parentpid=tokens[2]
+        cmd=string.join(tokens[7:], " ")
+        # we do make the assumption that a pid is not reused within a rotationinterval.
+        ProcessTable[pid] ={"cmd" : cmd}
+       ProcessTable[pid]["parentpid"] = parentpid
+    return ProcessTable
+
+def getChildPid(pid,ProcessTable) :
+    kids=[]
+    for _pid in ProcessTable :
+       if ProcessTable[_pid]["parentpid"] == "%s" % pid :
+           kids.append(_pid)
+    pids=ProcessTable.keys()
+    pids.sort()
+    if 0 :
+        for p in pids :
+           print "%s : %s" % (p,ProcessTable[p])
+    return kids
+
+def killPid(pid,signal="TERM") :
+    rc=subprocess.call([KILLBIN, "-%s" % signal,pid])
+    return rc
+
+def main():
+    setupFSTrace()
+    TraceFileNo=0
+    FileName=TraceFileNames[TraceFileNo]
+    DumpProcNum=0
+    if debug : print "Spawning dump-process to %s" % FileName
+    DumpProcs[DumpProcNum] = Process(target=dumpFSTrace, args=(FileName,))
+    DumpProcs[DumpProcNum].start()
+    if Mode == "single" : # single-shot mode
+        while 1 :
+            if debug : print "Waiting for %s until next check for external Event." % EventCheckInterval
+            ProcessTable=updateProcessTable()
+            if externalEvent(EventFile) : 
+                DumpProcs[DumpProcNum].terminate()
+                ProcessTable=updateProcessTable()
+                if debug : 
+                      print "Killing childpids of %s : %s " % (DumpProcs[DumpProcNum].pid,getChildPid("%s" % DumpProcs[DumpProcNum].pid,ProcessTable))
+               for kid in getChildPid("%s" % DumpProcs[DumpProcNum].pid,ProcessTable) :
+                   killPid(kid)
+                saveLogs(ProcessTable)
+                break
+            time.sleep(EventCheckInterval)
+        sys.exit(0)
+    # continuous run
+    while 1 :
+        Waited=0
+        while Waited < RotationInterval :
+            if debug : print "Waiting for %s until next check for external Event." % EventCheckInterval
+            time.sleep(EventCheckInterval)
+            Waited += 1
+            ProcessTable=updateProcessTable()
+            if debug : 
+                print "Waitcount = %s" % Waited
+                print "RotationInterval %s" % RotationInterval 
+                print "ProcessTable :"
+                print len(ProcessTable)
+            if externalEvent(EventFile) :
+                saveLogs(ProcessTable, TraceFileNo)
+        if debug : print "Rotating Logs"
+        TraceFileNo = (TraceFileNo+1) % (numTraceFiles)
+        FileName=TraceFileNames[TraceFileNo]
+        newDumpProcNum= (DumpProcNum +1) % 2
+        if debug : print "Spawning next dump-process no %s to %s" % (newDumpProcNum, FileName)
+        DumpProcs[newDumpProcNum] = Process(target=dumpFSTrace, args=(FileName,))
+       DumpProcs[newDumpProcNum].start()
+        ProcessTable=updateProcessTable()
+        if debug : print "Terminating last dump-process %s" % DumpProcNum
+        DumpProcs[DumpProcNum].terminate()
+        if debug : 
+            print "Killing childpids of %s : %s " % (DumpProcs[DumpProcNum].pid,getChildPid("%s" % DumpProcs[DumpProcNum].pid,ProcessTable))
+       for kid in getChildPid("%s" % DumpProcs[DumpProcNum].pid,ProcessTable) :
+           if debug : print ProcessTable[kid]
+           killPid(kid)
+       if debug: print DumpProcs
+        DumpProcNum=newDumpProcNum
+    return
+    
+#
+# This function has to be replaced for new debugging cases
+#
+
+def externalEvent(EventFile):
+    if os.path.isfile(EventFile) :
+        os.unlink(EventFile)
+        if verbose : print "external event happened!"
+        return True
+    if debug : print "no external event"
+    return False
+
+def usage():
+    print "ClientTracing.py --dumpinterval=# --rotationinterval=# --buffersize=# --numfiles # --mode=[cont|single] --savemode=[lastonly|all] --verbose --debug"
+    print "--dumpinterval=# / secs : interval of fstrace in secs to dump information"
+    print "--eventcheckinterval=# / secs : How many secondes to wait between checking for an event" 
+    print "--Eventfile=<name> : file to check if an external event happened" 
+    print "--rotationinterval=# /units EventCheckInterval" 
+    print "--buffersize=# buffer of fstrace log in memory"
+    print "--numfiles # how many logfiles to write" 
+    print "--mode=[cont|single]" 
+    print 
+    print "An event is triggered by the existance of the file %s\n" % EventFile
+    print "You may also overwrite the function externalEvent()"
+
+
+if __name__ == "__main__" :
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "he:E:d:r:m:b:vdn:s:", ["help", "eventcheckinterval=","Eventfile=","dumpinterval=", "rotationinterval=", "mode=", "buffersize=","verbose", "debug","numfiles=", "savemode="])
+    except getopt.GetoptError, err:
+        # print help information and exit:
+        print str(err) # will print something like "option -a not recognized"
+        usage()
+        sys.exit(2)
+    for o, a in opts:
+        if o in ("-v", "--verbose"):
+            verbose = True
+        elif o in ("-d", "--debug") :
+            debug = True
+        elif o in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif o in ("-e", "--eventcheckinterval") :
+            EventCheckInterval = int(a)
+        elif o in ("-E", "--Eventfile") :
+            EventFile = int(a)
+        elif o in ("-d", "--dumpinterval") :
+            Dumpinterval = int(a)
+        elif o in ('-r', "--rotationinterval") :
+            RotationInterval = int(a)
+        elif o in ("-b", "--buffersize") :
+            TraceBufferSize=int(a)
+        elif o in ("-m", "--mode") :
+            Mode=a
+            if not Mode in ['cont','single']  :
+                print "mode takes only >cont< or >single< "
+                sys.exit(2)
+        elif o in ("-o", "--output") :
+            Output=a
+        elif o in ("-n", "--numfiles") :
+            numTraceFiles=int(a)
+        else :
+            print "Unknown option %s" % o
+            sys.exit(2)
+    for i in range(int(numTraceFiles)) :
+        TraceFileNames.append("%s-%s"% (Output, i))
+    
+    if verbose :
+        print "Buffersize: %s" % TraceBufferSize
+        print "Dumpinterval: %s" % Dumpinterval
+        print "number of Tracfiles : %s" % numTraceFiles
+        print "TraceFilenames: %s-#" % Output
+        print "Rotationinterval: %s" % RotationInterval
+        print "ProcessTableFilename=%s" % ProcessTableFilename
+        print "Mode: %s" % Mode
+    main()