[CalendarServer-changes] [5814] CalendarServer/trunk/contrib/tools/monitoranalysis.py

source_changes at macosforge.org source_changes at macosforge.org
Wed Jun 30 10:08:05 PDT 2010


Revision: 5814
          http://trac.macosforge.org/projects/calendarserver/changeset/5814
Author:   cdaboo at apple.com
Date:     2010-06-30 10:08:03 -0700 (Wed, 30 Jun 2010)
Log Message:
-----------
Tool to plot request monitor data.

Added Paths:
-----------
    CalendarServer/trunk/contrib/tools/monitoranalysis.py

Added: CalendarServer/trunk/contrib/tools/monitoranalysis.py
===================================================================
--- CalendarServer/trunk/contrib/tools/monitoranalysis.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/tools/monitoranalysis.py	2010-06-30 17:08:03 UTC (rev 5814)
@@ -0,0 +1,244 @@
+#!/usr/bin/env python
+##
+# Copyright (c) 2010 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+import matplotlib.pyplot as plt
+import getopt
+import sys
+import os
+
+dataset = []
+
+def analyze(fpath, startDate, endDate, title=None):
+    
+    print "Analyzing data for %s" % (fpath,)
+    data = []
+    with open(fpath) as f:
+        for line in f:
+            try:
+                if line.startswith("2010/0"):
+                    
+                    date = line[:10]
+                    if startDate and date < startDate or endDate and date > endDate:
+                        continue
+
+                    digits = line[11:13]
+                    if digits in ("05", "06"):
+                        for _ignore in range(3):
+                            f.next()
+                        continue
+                    datetime = line[:19]
+                    if "Listenq" in line:
+                        lqnon = line[len("2010/05/12 22:27:24 Listenq (ssl+non): "):].split("+", 1)[1]
+                    else:
+                        lqnon = line[len("2010/01/05 19:47:23 Listen queue: "):]
+                        
+                    lqnon = int(lqnon.split(" ", 1)[0])
+                    
+                    line = f.next()
+                    cpu = int(line[len("CPU idle %: "):].split(" ", 1)[0])
+                    
+                    line = f.next()
+                    reqs = int(float(line.split(" ", 1)[0]))
+    
+                    line = f.next()
+                    resp = line[len("Response time: average "):].split(" ", 1)[0]
+                    resp = int(float(resp)/10.0) * 10
+    
+                    if reqs <= 80:
+                        data.append((datetime, reqs, resp, lqnon, cpu))
+                    #print "%s %d %d %d %d" % (datetime, reqs, resp, lqnon, cpu)
+            except StopIteration:
+                break
+    
+    if not title:
+        if startDate and endDate:
+            title = "Between %s and %s" % (startDate, endDate,)
+        elif startDate:
+            title = "Since %s" % (startDate,)
+        elif endDate:
+            title = "Up to %s" % (endDate,)
+        else:
+            title = None 
+
+    dataset.append((title, data,))
+    
+    print "Stored %d data points" % (len(data),)
+
+def plotListenQBands(data, first, last):
+
+    x1 = []
+    y1 = []
+    x2 = []
+    y2 = []
+    x3 = []
+    y3 = []
+    for datetime, reqs, resp, lq, cpu in data:
+        if lq == 0:
+            x1.append(reqs)
+            y1.append(resp)
+        elif lq < 50:
+            x2.append(reqs)
+            y2.append(resp)
+        else:
+            x3.append(reqs)
+            y3.append(resp)
+    
+    plt.plot(x1, y1, "b+", x2, y2, "g+", x3, y3, "y+")
+    
+    if first:
+        plt.legend(('ListenQ at zero', 'ListenQ < 50', 'ListenQ >= 50'),
+               'upper right', shadow=True, fancybox=True)
+    if last:
+        plt.xlabel("Requests/second")
+    plt.ylabel("Av. Response Time (ms)")
+    plt.xlim(0, 80)
+    plt.ylim(0, 4000)
+
+def plotCPUBands(data, first, last):
+
+    x = [[], [], [], []]
+    y = [[], [], [], []]
+    for datetime, reqs, resp, lq, cpu in data:
+        if cpu > 75:
+            x[0].append(reqs)
+            y[0].append(resp)
+        elif cpu > 50:
+            x[1].append(reqs)
+            y[1].append(resp)
+        elif cpu > 25:
+            x[2].append(reqs)
+            y[2].append(resp)
+        else:
+            x[3].append(reqs)
+            y[3].append(resp)
+    
+    plt.plot(
+        x[0], y[0], "b+",
+        x[1], y[1], "g+",
+        x[2], y[2], "y+",
+        x[3], y[3], "m+",
+    )
+    
+    if first:
+        plt.legend(('CPU < 1/4', 'CPU < 1/2', 'CPU < 3/4', "CPU High"),
+               'upper right', shadow=True, fancybox=True)
+    if last:
+        plt.xlabel("Requests/second")
+    plt.ylabel("Av. Response Time (ms)")
+    plt.xlim(0, 80)
+    plt.ylim(0, 4000)
+
+def plot():
+    
+    print "Plotting data"
+    
+    plt.figure(1)
+
+    nplots = len(dataset)
+    subplot = nplots*100 + 20
+    
+    for ctr, item in enumerate(dataset):
+        
+        title, data = item
+        if not title:
+            title = "#%d" % (ctr+1,)
+
+        plt.subplot(subplot + 2*ctr + 1)
+        plotListenQBands(data, first=(ctr == 0), last=(ctr+1 == len(dataset)))
+        plt.title("ListenQ %s" % (title,))
+        
+        plt.subplot(subplot + 2*ctr + 2)
+        plotCPUBands(data, first=(ctr == 0), last=(ctr+1 == len(dataset)))
+        plt.title("CPU %s" % (title,))
+        
+    plt.show()
+
+def argPath(path):
+    fpath = os.path.expanduser(path)
+    if not fpath.startswith("/"):
+        fpath = os.path.join(pwd, fpath)
+    return fpath
+
+def expandDate(date):
+    return "%s/%s/%s" % (date[0:4], date[4:6], date[6:8],)
+
+def usage(error_msg=None):
+    if error_msg:
+        print error_msg
+
+    print """Usage: monitoranalysis [options] FILE+
+Options:
+    -h          Print this help and exit
+
+Arguments:
+    FILE      File names for the requests.log to analyze. A date
+              range can be specified by append a comma, then a
+              dash seperated pair of YYYYMMDD dates, e.g.:
+              ~/request.log,20100614-20100619. Multiple
+              ranges can be specified for multiple plots.
+
+Description:
+This utility will analyze the output of the request monitor tool and
+generate some pretty plots of data.
+"""
+
+    if error_msg:
+        raise ValueError(error_msg)
+    else:
+        sys.exit(0)
+
+if __name__ == "__main__":
+
+    options, args = getopt.getopt(sys.argv[1:], "h", [])
+
+    for option, value in options:
+        if option == "-h":
+            usage()
+        else:
+            usage("Unrecognized option: %s" % (option,))
+
+    # Process arguments
+    if len(args) == 0:
+        usage("Must have arguments")
+
+    pwd = os.getcwd()
+
+    for arg in args:
+        if "," in arg:
+            items = arg.split(",")
+            arg = items[0]
+            start = []
+            end = []
+            for daterange in items[1:]:
+                splits = daterange.split("-")
+                if len(splits) == 1:
+                    start.append(expandDate(splits[0]))
+                    end.append(None)
+                elif len(splits) == 2:
+                    start.append(expandDate(splits[0]))
+                    end.append(expandDate(splits[1]))
+                else:
+                    start.append(None)
+                    end.append(None)
+        else:
+            start = (None,)
+            end = (None,)
+        
+        for i in range(len(start)):
+            analyze(argPath(arg), start[i], end[i])
+
+    plot()


Property changes on: CalendarServer/trunk/contrib/tools/monitoranalysis.py
___________________________________________________________________
Added: svn:executable
   + *
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100630/58534950/attachment.html>


More information about the calendarserver-changes mailing list