Index: /trunk/anuga_core/source/anuga/utilities/log_analyser.py
===================================================================
--- /trunk/anuga_core/source/anuga/utilities/log_analyser.py	(revision 8323)
+++ /trunk/anuga_core/source/anuga/utilities/log_analyser.py	(revision 8323)
@@ -0,0 +1,77 @@
+import sys
+import os
+import re
+import anuga.utilities.log as log
+import csv
+
+defaultOutputFile ='timing.csv'
+timingDelimiter = log.TimingDelimiter
+
+def analyse_log(path, output_file, log_file='anuga.log'):
+    """
+    path - the directory to look for log files in.
+    output_file - the file produced, with meta log info
+    log_file - the name of the log files
+     
+    Read log files and create a meta log file
+    
+    WARNING: if a 
+    """
+    log_pairs = build_log_info(path, log_file)
+    if log_pairs is not None:
+        write_meta_log(log_pairs, output_file)
+
+def build_log_info(path, log_file):
+    log_pairs = []
+    for (path, dirs, files) in os.walk(path):    
+        for file in files:
+            if log_file in file: 
+                dictResults = {}
+                for line in open(os.path.join(path,file)):
+                    if line.find(timingDelimiter)>-1:
+                        key_value = line.split(timingDelimiter)[1]
+                        # FIXME remove the magic comma
+                        key_value_list = key_value.split(',')
+                        key = key_value_list[0].strip()
+                        value =  key_value_list[1].strip()
+                        if key in dictResults:
+                            print "WARNING. Multiple values ignored."
+                        dictResults[key] = value
+                        #print "key", key 
+                        #print "value", value
+                log_pairs.append(dictResults)
+    return log_pairs
+  
+def write_meta_log(log_pairs, output_file):
+    """Write the info from the log files to a file"""
+    
+    all_keys = {} # values aren't needed, but are there
+    for log_p in log_pairs:
+        all_keys.update(log_p)
+    sorted_all_keys = sorted(all_keys.keys()) # sort the keys alphabetacally
+    
+    han = open(output_file, 'w')
+    writer = csv.DictWriter(han, delimiter=',', fieldnames=sorted_all_keys,
+                        extrasaction='ignore')
+    # Title 
+    writer.writerow(dict(zip(sorted_all_keys, sorted_all_keys)))
+    
+    for pair in log_pairs: # Write the main body
+        writer.writerow(pair)
+        
+    han.close()
+
+####################################################
+if __name__ == '__main__':
+    
+    path = sys.argv[1]
+
+    if len(sys.argv) < 3:
+        outputFile = open(defaultOutputFile, "a")
+    else:
+        outputFile = open(sys.argv[2], "a")
+
+    analyse_log(path, outputFile)
+
+    
+ 
Index: /trunk/anuga_core/source/anuga/utilities/test_log_analyser.py
===================================================================
--- /trunk/anuga_core/source/anuga/utilities/test_log_analyser.py	(revision 8323)
+++ /trunk/anuga_core/source/anuga/utilities/test_log_analyser.py	(revision 8323)
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+#
+
+# Warning, this will not update as the log format is updated.
+
+import os
+import unittest
+import tempfile
+from anuga.utilities.log import TimingDelimiter
+from log_analyser import analyse_log
+
+class logTestCase(unittest.TestCase):
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def log_lines(self, key, value):
+        
+        line = '2012-01-23 13:20:10,147 INFO   general_mesh:202 |'
+
+        #FIXME this logic is in the code somewhere.  So it 
+        # shouldn't be repeated here.
+        end_line = TimingDelimiter + ' ' + key + ', ' + \
+            value + '\n' 
+        return line + end_line
+
+    def test_log(self):
+        # create a dummy directory and log file
+        root_dir = tempfile.mkdtemp('test_log_analyser')
+        dir1 = tempfile.mkdtemp(dir=root_dir)
+        dir2 = tempfile.mkdtemp(dir=root_dir)
+        
+        log_file_name = 'anuga.log'
+        
+        # Create a fake log file
+        log_path_file1 = os.path.join(dir1, log_file_name)
+        handle = file(log_path_file1, 'w')
+        handle.write('yeah\n yeah\n ')
+        handle.write('2012-01-23 13:20:10,147 INFO   general_mesh:202 |\n')
+        #made_up = {'three':'3', 'five':'5', 'seven':'7'}
+        made_up1 = {'numTriangles':'1', 'startMeshTime':'2', 'finishMeshTime':'3', \
+                       'finishTime':'4', 'startMemory':'5', 'finishMemory':'6'}
+        for key, val in made_up1.iteritems():
+            handle.write(self.log_lines(key, val))
+        handle.close()
+        
+        # Create another fake log file
+        log_path_file2 = os.path.join(dir2, log_file_name)
+        handle = file(log_path_file2, 'w')
+        handle.write('yeah\n yeah\n ')
+        handle.write('2012-01-23 13:20:10,147 INFO   general_mesh:202 |\n')
+        #made_up = {'three':'3', 'five':'5', 'seven':'7'}
+        made_up2 = {'another':'1', 'startMeshTime':'2', 'finishMeshTime':'3', \
+                       'finishTime':'4', 'startMemory':'5', 'finishMemory':'6'}
+        for key, val in made_up2.iteritems():
+            handle.write(self.log_lines(key, val))
+        handle.close()
+
+        # output file
+        (handle, output_file) = tempfile.mkstemp('.csv','get_bridges_from_dic_')
+        os.close(handle)
+        output_file = 'yeah.csv'
+
+        analyse_log(root_dir, output_file, log_file_name)
+        
+        #FIXME check these results!!
+        
+        
+        os.remove(log_path_file1)
+        os.remove(log_path_file2)
+        os.rmdir(dir1)
+        os.rmdir(dir2)
+        os.rmdir(root_dir)
+
+
+
+
+################################################################################
+
+if __name__ == "__main__":
+    suite = unittest.makeSuite(logTestCase,'test')
+    runner = unittest.TextTestRunner() #verbosity=2)
+    runner.run(suite)
+    
