Add log analyser script.
authorCarl Hetherington <cth@carlh.net>
Wed, 4 Jun 2014 11:04:17 +0000 (12:04 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 4 Jun 2014 11:04:17 +0000 (12:04 +0100)
hacks/analog.py [new file with mode: 0644]

diff --git a/hacks/analog.py b/hacks/analog.py
new file mode 100644 (file)
index 0000000..473913d
--- /dev/null
@@ -0,0 +1,184 @@
+#!/usr/bin/python
+
+import sys
+import time
+import argparse
+import matplotlib.pyplot as plt
+
+parser = argparse.ArgumentParser()
+parser.add_argument('log_file')
+parser.add_argument('-q', '--queue', help='plot queue size', action='store_true')
+parser.add_argument('-e', '--encoder-threads', help='plot encoder thread activity', action='store_true')
+parser.add_argument('-f', '--plot-first-encoder', help='plot more detailed activity of the first encoder thread', action='store_true')
+parser.add_argument('--dump-first-encoder', help='dump activity of the first encoder thread', action='store_true')
+parser.add_argument('--from', help='time in seconds to start at', type=int, dest='from_time')
+parser.add_argument('--to', help='time in seconds to stop at', type=int, dest='to_time')
+args = parser.parse_args()
+
+def find_nth(haystack, needle, n):
+    start = haystack.find(needle)
+    while start >= 0 and n > 1:
+        start = haystack.find(needle, start+len(needle))
+        n -= 1
+    return start
+
+class Time:
+    def __init__(self, s, m = 0):
+        self.seconds = s
+        self.microseconds = m
+
+    def __str__(self):
+        return '%d:%d' % (self.seconds, self.microseconds)
+
+    def float_seconds(self):
+        return self.seconds + self.microseconds / 1000000.0
+
+    def __sub__(self, x):
+        m = self.microseconds - x.microseconds
+        if m < 0:
+            return Time(self.seconds - x.seconds - 1, m + 1000000)
+        else:
+            return Time(self.seconds - x.seconds, m)
+
+queue_size = []
+encoder_thread_events = dict()
+
+def add_encoder_thread_event(thread, time, event):
+    global encoder_thread_events
+    if thread in encoder_thread_events:
+        encoder_thread_events[thread].append((time, event))
+    else:
+        encoder_thread_events[thread] = [(time, event)]
+
+f = open(args.log_file)
+start = None
+while True:
+    l = f.readline()
+    if l == '':
+        break
+
+    l = l.strip()
+    p = l.split()
+
+    if len(p) == 0:
+        continue
+
+    if len(p[0].split(':')) == 2:
+        # s:us timestamp
+        x = p[0].split(':')
+        T = Time(int(x[0]), int(x[1]))
+        message = l[l.find(' ')+1:]
+    else:
+        # Date/time timestamp
+        s = find_nth(l, ':', 3)
+        T = Time(time.mktime(time.strptime(l[:s])))
+        message = l[s+2:]
+
+    if start is None:
+        start = T
+    else:
+        T = T - start
+
+    thread = None
+    if message.startswith('['):
+        thread = message.split()[0][1:-1]
+        message = message[message.find(' ')+1:]
+
+    if message.startswith('adding to queue of '):
+        queue_size.append((T, int(message.split()[4])))
+    elif message.startswith('encoder thread sleeps'):
+        add_encoder_thread_event(thread, T, 'sleep')
+    elif message.startswith('encoder thread wakes'):
+        add_encoder_thread_event(thread, T, 'wake')
+    elif message.startswith('encoder thread begins local encode'):
+        add_encoder_thread_event(thread, T, 'begin_encode')
+    elif message.startswith('MagickImageProxy begins read and decode'):
+        add_encoder_thread_event(thread, T, 'magick_begin_decode')
+    elif message.startswith('MagickImageProxy completes read and decode'):
+        add_encoder_thread_event(thread, T, 'magick_end_decode')
+    elif message.startswith('encoder thread finishes local encode'):
+        add_encoder_thread_event(thread, T, 'end_encode')
+
+if args.queue:
+    plt.figure()
+    x = []
+    y = []
+    for q in queue_size:
+        x.append(q[0].seconds)
+        y.append(q[1])
+
+    plt.plot(x, y)
+    plt.show()
+elif args.encoder_threads:
+    plt.figure()
+    N = len(encoder_thread_events)
+    n = 1
+    for thread, events in encoder_thread_events.iteritems():
+        plt.subplot(N, 1, n)
+        x = []
+        y = []
+        previous = 0
+        for e in events:
+            if args.from_time is not None and e[0].float_seconds() <= args.from_time:
+                continue
+            if args.to_time is not None and e[0].float_seconds() >= args.to_time:
+                continue
+            x.append(e[0].float_seconds())
+            x.append(e[0].float_seconds())
+            y.append(previous)
+            if e[1] == 'sleep':
+                y.append(0)
+            elif e[1] == 'wake':
+                y.append(1)
+            elif e[1] == 'begin_encode':
+                y.append(2)
+            elif e[1] == 'end_encode':
+                y.append(1)
+            elif e[1] == 'magick_begin_decode':
+                y.append(3)
+            elif e[1] == 'magick_end_decode':
+                y.append(2)
+
+            previous = y[-1]
+
+        plt.plot(x, y)
+        n += 1
+        break
+
+    plt.show()
+elif args.plot_first_encoder:
+    plt.figure()
+    N = len(encoder_thread_events)
+    n = 1
+    events = encoder_thread_events.itervalues().next()
+
+    N = 6
+    n = 1
+    for t in ['sleep', 'wake', 'begin_encode', 'magick_begin_decode', 'magick_end_decode', 'end_encode']:
+        plt.subplot(N, 1, n)
+        x = []
+        y = []
+        for e in events:
+            if args.from_time is not None and e[0].float_seconds() <= args.from_time:
+                continue
+            if args.to_time is not None and e[0].float_seconds() >= args.to_time:
+                continue
+            if e[1] == t:
+                x.append(e[0].float_seconds())
+                x.append(e[0].float_seconds())
+                x.append(e[0].float_seconds())
+                y.append(0)
+                y.append(1)
+                y.append(0)
+                
+        plt.plot(x, y)
+        plt.title(t)
+        n += 1
+
+    plt.show()
+elif args.dump_first_encoder:
+    events = encoder_thread_events.itervalues().next()
+    last = 0
+    for e in events:
+        print e[0].float_seconds(), (e[0].float_seconds() - last), e[1]
+        last = e[0].float_seconds()