activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rajdav...@apache.org
Subject svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
Date Mon, 13 Aug 2007 16:03:27 GMT
Author: rajdavies
Date: Mon Aug 13 09:03:25 2007
New Revision: 565392

URL: http://svn.apache.org/viewvc?view=rev&rev=565392
Log:
Added the log analyser tool to svn - for http://issues.apache.org/activemq/browse/AMQ-1361

Added:
    activemq/trunk/log_analyzer_tool/
    activemq/trunk/log_analyzer_tool/Main.py   (with props)
    activemq/trunk/log_analyzer_tool/README.txt   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/
    activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelText.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelText.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/TabbedPanel.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/TabbedPanel.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/ViewClientsPanel.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/ViewClientsPanel.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/ViewConnectionsPanel.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/ViewConnectionsPanel.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/ViewFilesPanel.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/ViewFilesPanel.pyc   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/__init__.py   (with props)
    activemq/trunk/log_analyzer_tool/loganalyzergui/__init__.pyc   (with props)
    activemq/trunk/log_analyzer_tool/run.bat   (with props)
    activemq/trunk/log_analyzer_tool/run.sh   (with props)
    activemq/trunk/log_analyzer_tool/screenshots/
    activemq/trunk/log_analyzer_tool/screenshots/1.png   (with props)
    activemq/trunk/log_analyzer_tool/screenshots/2.png   (with props)
    activemq/trunk/log_analyzer_tool/screenshots/3.png   (with props)
    activemq/trunk/log_analyzer_tool/screenshots/4.png   (with props)
    activemq/trunk/log_analyzer_tool/screenshots/5.png   (with props)

Added: activemq/trunk/log_analyzer_tool/Main.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/Main.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/Main.py (added)
+++ activemq/trunk/log_analyzer_tool/Main.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,14 @@
+"""
+Module Main
+"""
+from loganalyzergui.Application import Application
+
+def main():
+    """
+    Entrance point for the application
+    """
+    app = Application(0)
+    app.MainLoop()
+    
+if __name__ == '__main__':
+    main()
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/Main.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/README.txt
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/README.txt?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/README.txt (added)
+++ activemq/trunk/log_analyzer_tool/README.txt Mon Aug 13 09:03:25 2007
@@ -0,0 +1,64 @@
+Readme file for the LogAnalyzer application.
+
+1. Requirements:
+-Python 2.5.1 (http://www.python.org/download/releases/2.5.1/ or your favorite package)
+-wxPython 2.8.4 (http://www.wxpython.org/download.php or your favorite package)
+
+2. How to execute:
+Run 'python Main.py'.
+
+3. Some instructions:
+-This tool will analyze ActiveMQ log files that have been produced
+using the 'custom' transport log format. To analyze the files,
+put them in a directory, choose that directory and click 'Parse'.
+Please don't put any other kind of files in the same directory
+(sub-directories won't cause any problem, but the files inside
+them will not be analyzed).
+For example, imagine you have a setup with 4 machines: 1 has producers,
+2 are brokers, and 1 has consumers. As long as you have 1 JVM per machine,
+you should have 4 log files. Call the files p.log, b1.log, b2.log,
+and c.log, for example. Put the 4 files in the same directory,
+choose that directory and click the 'Parse' button.
+
+-The first tab of the tool shows incorrect situations at transport level:
+(i) Messages that were sent through a connection, but were not received
+at the other end.
+(ii) Messages that were received through a connection, but were not sent
+(probably you are missing the log file of the JVM that sent the message).
+(iii) Messages that are sent 2 times through the same connection.
+(iv) Messages that were sent 2 times by the same JVM, but through
+different connections.
+By clicking the 'Show results with short ids' checkbox, you can switch
+between the real connection / producer id used by ActiveMQ,
+or a unique integer assigned by the tool.
+Often it's easier to compare and browse with this integers than with
+the original id's which are often long strings.
+The 'Message id' column shows 2 things: the id of the producer that
+originally issued the message, and the 'Producer Sequence Id' of a message.
+These 2 items identify a message in a unique way.
+
+You can use the checkboxes to filter per type.
+You can also filter by a given connection (but then problems of type (iv)
+will not appear because they 'belong' to more than one connection).
+You can input a 'long id' (the original ActiveMQ id) or a 'short id'
+(a short integer assigned by the tool to each connection).
+
+-The second tab of the tool allows you to get a lot of information
+about a single message. Input the producer id of the original producer
+of the message, and the message's 'Producer Sequence Id'.
+You can choose to use the original ActiveMQ producer id (long id)
+or the short integer assigned to a producer by the tool.
+You can also use the 'Jump to Message Browsing' button of the 1st tab
+to see the information about the problems of a given message
+without having to copy the message id manually.
+In this tab you can also use the 'Show results with short ids' checkbox.
+
+-The third tab gives a summary of the clients (producer and consumers)
+which appear in the log files. Each client is identified by a short id,
+and belongs to a connection (whose 'short id' and 'long id' are shown).
+
+-The fourth tab gives a summary of the connections involved,
+and the clients that belong to them.
+
+-The fifth tab gives a summary of the log files analyzed,
+and the connections in each of the files.
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/trunk/log_analyzer_tool/README.txt
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,337 @@
+"""
+Module Connection
+"""
+import itertools
+
+class Connection(object):
+    """
+    This class represents an ActiveMQ Connection.
+    It also stores a collection of the connections
+    that have been read in the log files.
+    
+    A Connection's id is the ActiveMQConnection's id. Since this is usually a long
+    alphanumerical string, it is called 'longId'.
+    Each new Connection gets also assigned an integer 'shortId' automatically.
+    The function of this 'shortId' is to make understanding of displayed data easier.
+    
+    A Connection has 2 LogFile members, who represent:
+    -the log file of the JVM that initiates a connection.
+    -the log file of the JVM that receives a connection request.
+    
+    The purpose of every Connection is to store the following data:
+        
+        -messages sent through this connection, as a dictionary where the
+        key is a tuple (message, direction) and the value is
+        a list of timestamps. If the message was sent only one time (normal case),
+        the timestamp list will have 1 item only.
+        
+        -messages received through this connection, as a dictionary
+        analogous to the previous one.
+        
+        -messages sent but not received through this connection, as a list of
+        tuples (storedMessage, ntimes, timestamps).
+        'storedMessage' is a (message, direction) tuple
+        ntimes, an integer, is the number of times a message was sent but not received
+        timestamps is a list of timestamps of when the message was sent or received.
+        For a message to be in this list, ntimes must be >= 1.
+        
+        -messages received but not sent through this connection.
+        Analog to previous point.
+        
+        -messages sent more than 2 more times through this connection, as a list of
+        tuples (storedMessage, ntimes, timestamps).
+        'storedMessage' is a (message, direction) tuple
+        ntimes, an integer, is the number of times a message was sent.
+        timestamps is a list of timestamps of when the message was sent.
+        For a message to be in this list, ntimes must be >= 2.
+        
+        -messages received more than 2 more times through this connection.
+        Identical structure to the previous point.
+    
+    The 'direction' value is either True or False.
+    True represents that the message was sent from the JVM writing to the
+    'from' file, to the JVM writing to the 'to' file.
+    False represents the opposite.
+    """
+
+    #dictionary whose keys are connection ids, and whose values
+    #are Connection objects
+    connections = {}
+    nConnections = 0
+    connectionIdList = []
+    
+    def __init__(self, longId, fromFile = None, toFile = None):
+        """
+        Constructs a Connection object.
+        longId : string
+        fromFile: LogFile object
+        to: LogFile object
+        The ActiveMQConnection's id has to be provided.
+        Optionally, 2 LogFile objects can be provided.
+        The 'from' file is the log file of the JVM that initiates a connection.
+        The 'to' file is the log file of the JVM that receives a connection request.
+        
+        A new connection gets automatically a new 'shortId', which is an integer.
+        The longId gets also stored in a list of longIds.
+        
+        Returns a Connection object.
+        """
+        
+        self.longId = longId
+        self.fromFile = fromFile
+        self.toFile = toFile
+        
+        self.shortId = Connection.nConnections
+        Connection.connectionIdList.append(longId)
+        Connection.nConnections += 1
+
+        self.producers = set()
+        self.consumers = set()
+
+        self.sent = {}
+        self.received = {}
+
+        self.duplicateSent = None
+        self.duplicateReceived = None
+        self.sentButNotReceived = None
+        self.receivedButNotSent = None
+        
+        self.calculated = False
+
+    @classmethod
+    def clearData(cls):
+        """
+        Deletes all information read about connections.
+        
+        Returns nothing.
+        """
+        
+        cls.connections.clear()
+        cls.nConnections = 0
+        del cls.connectionIdList[:]
+        
+    @classmethod
+    def getConnectionByLongId(cls, longId):
+        """
+        Retrieves the connection whose id is 'longId'.
+        If there is no connection with this id, a new
+        one is created with this id.
+        
+        Returns a Connection object.
+        """
+        
+        if longId not in cls.connections:
+            cls.connections[longId] = Connection(longId)
+
+        return cls.connections[longId]
+    
+    @classmethod
+    def getConnectionByShortId(cls, shortId):
+        """
+        Retrieves the connection whose shortId is 'shortId'.
+        If there is no connection with this id, 
+        an IndexError exception will be thrown.
+        
+        Returns a Connection object.
+        Throws an IndexError if the short id does not exist.
+        """
+
+        return cls.connections[cls.connectionIdList[shortId]]
+    
+    @classmethod
+    def shortIdToLongId(cls, shortId):
+        """
+        Transforms a connection's short id to a long id.
+        Returns the long id.
+        Throws an IndexError if the short id does not exist.
+        """
+        return cls.connectionIdList[shortId]
+    
+    @classmethod
+    def longIdToShortId(cls, longId):
+        """
+        Transforms a connection's long id to a short id.
+        Returns the short id.
+        Throws an KeyError if the short id does not exist.
+        """
+        try:
+            return cls.connections[longId].shortId
+        except KeyError:
+            print longId
+            print cls.connections
+            raise
+
+    @classmethod
+    def setFrom(cls, longId, fromFile):
+        """
+        Sets the 'from' LogFile object for the connection whose id is 'longId'.
+        The 'from' file is the log file of the JVM that initiates a connection.
+        If there is not yet a connection whose id is 'longId', a new one is
+        created with this longId and this 'from' file.
+        
+        Returns nothing.
+        """
+        
+        if longId not in cls.connections:
+            cls.connections[longId] = Connection(longId, fromFile = fromFile)
+        else:
+            cls.connections[longId].fromFile = fromFile
+
+    @classmethod
+    def setTo(cls, longId, toFile):
+        """
+        Sets the 'to' LogFile object for the connection whose id is 'longId'.
+        The 'to' file is the log file of the JVM that receives a connection request.
+        If there is not yet a connection whose id is 'longId', a new one is
+        created with this longId and this 'to' file.
+        
+        Returns nothing.
+        """
+        
+        if longId not in cls.connections:
+            cls.connections[longId] = Connection(longId, toFile = toFile)
+        else:
+            cls.connections[longId].toFile = toFile
+
+
+
+    @classmethod
+    def exists(cls, longId):
+        """
+        Returns if there is a connection whose id is 'longId'
+        """
+        
+        return longId in cls.connections
+        
+
+
+    def addProducer(self, producer):
+        """
+        Adds a producer to the set of this connection's producers.
+        Returns nothing.
+        """
+        self.producers.add(producer)
+        
+    def addConsumer(self, consumer):
+        """
+        Adds a consumer to the set of this connection's consumers.
+        Returns nothing.
+        """
+        self.consumers.add(consumer)
+        
+    def addSentMessage(self, message, direction, timestamp):
+        """
+        Adds a message to the set of messages sent through this connection.
+            message: a Message object
+            direction: True if this message was sent from self.fromFile to self.to
+                       False if this message was sent from self.toFile to self.fromFile
+            timestamp: a string with the time this message was sent
+                       
+        If the message has already been sent in this direction, it gets added to the
+        collection of duplicate sent messages.
+        
+        Returns nothing.
+        """
+        
+        storedMessage = (message, direction)
+        
+        if storedMessage in self.sent:
+            self.sent[storedMessage].append(timestamp)
+        else:
+            self.sent[storedMessage] = [timestamp]
+            
+    def addReceivedMessage(self, message, direction, timestamp):
+        """
+        Adds a message to the set of messages received through this connection.
+            message: a message object
+            direction: True if this message was sent from self.fromFile to self.to
+                       False if this message was sent from self.toFile to self.fromFile
+            timestamp: a string with the time this message was sent
+                       
+        If the message has already been received in this direction, it gets added to the
+        collection of duplicate received messages.
+        
+        Returns nothing.
+        """
+        
+        storedMessage = (message, direction)
+        
+        if storedMessage in self.received:
+            self.received[storedMessage].append(timestamp)
+        else:
+            self.received[storedMessage] = [timestamp]
+            
+    def getErrors(self):
+        """
+        Processes the data previously gathered to find incorrect situations.
+        
+        Returns a 4-tuple with:
+            -collection of sent but not received messages, through this Connection.
+            This collection is a list of (storedMessage, ntimes, timestamps) tuples where:
+               *'storedMessage' is a (message, direction) tuple.
+               *'ntimes' is an integer, representing how many times the message was sent but not received.
+               *'timestamps' is a list of strings with the timestamps when this message was sent / received.
+               
+            -collection of received but not sent messages, through this Connection.
+            This collection is a list of (storedMessage, ntimes, timestamps) tuples where:
+               *'storedMessage' is a (message, direction) tuple.
+               *'ntimes' is an integer, representing how many times the message was received but not sent.
+               *'timestamps' is a list of strings with the timestamps when this message was sent / received.
+                              
+            -collection of duplicate sent messages, through this Connection.
+            This collection is a list of (message, timestamps) tuples where:
+               *'storedMessage' is a (shortId, commandId, direction) tuple.
+               *'ntimes' is an integer, representing how many times the message sent.
+               *'timestamps' is a list of strings with the timestamps when this message was sent.
+               
+            -collection of duplicate received messages, through this Connection.
+            This collection is a list of (message, timestamps) tuples where:
+               *'storedMessage' is a (message, direction) tuple.
+               *'ntimes' is an integer, representing how many times the message received.
+               *'timestamps' is a list of strings with the timestamps when this message was received.
+               
+        The data is only calculated once, and then successive calls of this method return always
+        the same erros unles self.calculated is set to False.
+        """
+        
+        if not self.calculated:
+            self.sentButNotReceived = []
+            for message, timestamps in self.sent.iteritems():
+                if message not in self.received:
+                    self.sentButNotReceived.append((message, len(timestamps), timestamps))
+                else:
+                    difference = len(timestamps) - len(self.received[message])
+                    if difference > 0:
+                        self.sentButNotReceived.append((message, difference,
+                                                        itertools.chain(timestamps, self.received[message])))
+            
+            self.receivedButNotSent = []
+            for message, timestamps in self.received.iteritems():
+                if message not in self.sent:
+                    self.receivedButNotSent.append((message, len(timestamps), timestamps))
+                else:
+                    difference = len(timestamps) - len(self.sent[message])
+                    if difference > 0:
+                        self.receivedButNotSent.append((message, difference,
+                                                        itertools.chain(timestamps, self.sent[message])))
+                        
+            self.duplicateSent = [(message, len(timestamps), timestamps)
+                                  for message, timestamps in self.sent.iteritems() if len(timestamps) > 1]
+            self.duplicateReceived  = [(message, len(timestamps), timestamps)
+                                       for message, timestamps in self.received.iteritems() if len(timestamps) > 1]
+            
+            self.sentButNotReceived.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
+            self.receivedButNotSent.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
+            self.duplicateSent.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
+            self.duplicateReceived.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
+            
+            self.calculated = True
+        
+        return self.sentButNotReceived, self.receivedButNotSent, self.duplicateSent, self.duplicateReceived      
+
+    def __str__(self):
+        """
+        Represents this Connection object as a string.
+        """
+        
+        return ''.join([self.longId, ' from:', str(self.fromFile), ' to:', str(self.toFile)])
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,76 @@
+"""
+Module Consumer
+"""
+
+class Consumer(object):
+    """
+    This class represents an ActiveMQ Consumer.
+    Each consumer is identified by its long id.
+    However each consumer also has a short id (an integer) to identify it more easily.
+    """
+    
+    nConsumers = 0
+    consumerIdList = []
+    consumers = {}
+    
+    def __init__(self, longId):
+        """
+        Constructor
+        """
+        
+        self.longId = longId
+        self.shortId = Consumer.nConsumers
+        
+        self.connectionId, sessionId, value = longId.rsplit(':', 2)
+        self.sessionId = int(sessionId)
+        self.value = int(value)
+        
+        Consumer.consumers[longId] = self
+        Consumer.consumerIdList.append(self.longId)
+        Consumer.nConsumers += 1
+    
+    @classmethod
+    def clearData(cls):
+        """
+        Deletes all information read about Consumers.
+        
+        Returns nothing.
+        """
+        
+        cls.consumers.clear()
+        cls.nConsumers = 0
+        del cls.consumerIdList[:]
+    
+    @classmethod
+    def getConsumerByLongId(cls, longId):
+        """
+        Returns a consumer given its long id.
+        If there is no consumer with this long id yet, it will be created.
+        """
+        
+        if longId not in cls.consumers:
+            cls.consumers[longId] = Consumer(longId)
+
+        return cls.consumers[longId]
+    
+    @classmethod
+    def shortIdToLongId(cls, shortId):
+        """
+        Transforms a consumer's short id to a long id.
+        
+        Returns a long id.
+        Throws an IndexError if the short id does not exist.
+        """
+        
+        return cls.consumerIdList[shortId]
+    
+    @classmethod
+    def longIdToShortId(cls, longId):
+        """
+        Transforms a consumer's long id to a short id.
+        
+        Returns a long id.
+        Throws an KeyError if the long id does not exist.
+        """
+        return cls.consumers[longId].shortId
+    

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,187 @@
+"""
+Module LogFile
+"""
+import os
+
+class LogFile(object):
+    """
+    Class that represents an ActiveMQ log file read by the application.
+    It also stores a list of all the LogFile objects.
+    
+    A LogFile object stores the following information:
+    -A list of 'outgoing' Connection objects that represent the connections
+    created by the JVM that writes this LogFile.
+    -A list of 'incoming' Connection objects that represent the connections
+    requests received by the JVM that writes this LogFile.
+    
+    -A dictionary of messages that were sent in this file.
+    The keys are Message objects and the values
+    are lists of timestamps of when the message was sent.
+    -A list of messages that were received in this file.
+    The keys are Message objects and the values
+    are lists of timestamps of when the message was received.
+    
+    -A list of messages that were sent in this file more than 1 time (duplicates)
+    The list is made of (message, ntimes, timestamps) tuples.
+    -A list of messages that were received in this file more than 1 time (duplicates),
+    analogous to the previous structure.
+    """
+    
+    logfiles = []
+    
+    def __init__(self, path):
+        """
+        Constructs a LogFile object.
+        path: a string with the path to the ActiveMQ log file.
+        """
+        
+        self.__path = os.path.abspath(path)
+        self.file = open(self.__path, 'r')
+        self.outgoing = []
+        self.incoming = []
+        
+        self.sent = {}
+        self.received = {}
+        
+        self.duplicateReceived = None
+        self.duplicateSent = None
+        
+        self.calculated = False
+        
+        LogFile.logfiles.append(self)
+       
+    @classmethod
+    def clearData(cls):
+        """
+        Class method erases all the LogFile objects stored in the LogFile class.
+        Returns nothing.
+        """
+        
+        del cls.logfiles[:]
+    
+    @classmethod
+    def closeFiles(cls):
+        """
+        Class method that closes all the LogFile objects stored in the LogFile class.
+        Returns nothing.
+        """
+        
+        for logFile in cls.logfiles:
+            logFile.file.close()
+
+
+
+    def addOutgoingConnection(self, con):
+        """
+        Adds an 'outgoing' Connection object to this LogFile.
+        Returns nothing.
+        """
+        
+        self.outgoing.append(con)
+
+    def addIncomingConnection(self, con):
+        """
+        Adds an 'incoming' Connection object to this LogFile.
+        Returns nothing.
+        """
+        
+        self.incoming.append(con)
+        
+    def addSentMessage(self, message, timestamp):
+        """
+        Adds a message to the set of messages that were sent thtough this file.
+        If a message gets sent 2 times, it gets added to the set of duplicate sent messages.
+        message: a Message object.
+        timestamp: a string with the time where this message was sent.
+        
+        Returns nothing.
+        """
+        
+        if message in self.sent:
+            self.sent[message].append(timestamp)
+        else:
+            self.sent[message] = [timestamp]
+        
+    def addReceivedMessage(self, message, timestamp):
+        """
+        Adds a message to the set of messages that were received in this file.
+        If a message gets sent 2 times, it gets added to the set of duplicate received messages.
+        message: a Message object.
+        timestamp: a string with the time where this message was sent.
+        
+        Returns nothing.
+        """
+        
+        #message = (shortProdId, prodSeqId, False)
+        if message in self.received:
+            self.received[message].append(timestamp)
+        else:
+            self.received[message] = [timestamp]
+            
+    def getErrors(self):
+        """
+        Returns a 2-tuple with:
+            -a list of (message, ntimes, timestamps) tuples, with the duplicate sent messages
+            that appear in more than one connection in this file.
+            'message' is a Message object.
+            'ntimes' is an integer stating how many times the message was sent ( always >= 2)
+            'timestamps' is a list of timestamps with the instants the message was sent.
+            
+            -a list of (message, ntimes, timestamps) tuples, with the duplicate received messages
+            that appear in more than one connection in this file.
+            Structure analogous to previous one.
+        
+        The data is only calculated once, and then successive calls of this method return always
+        the same erros unles self.calculated is set to False.
+        """
+        
+        if not self.calculated:
+            
+            duplicateSentTemp = [(message, len(timestamps), timestamps)
+                                 for message, timestamps in self.sent.iteritems() if len(timestamps) > 1]
+            self.duplicateSent = []
+            
+            for message, _, timestamps in duplicateSentTemp:
+                connections = []
+                for connection, direction in message.sendingConnections:
+                    if direction and connection.fromFile == self       \
+                    or not direction and connection.toFile == self:
+                        connections.append(connection)
+                if len(connections) > 1:
+                    self.duplicateSent.append((message, len(timestamps), timestamps))
+                    
+            duplicateReceivedTemp = [(message, len(timestamps), timestamps)
+                                      for message, timestamps in self.received.iteritems() if len(timestamps) > 1]
+            self.duplicateReceived = []
+            
+            for message, _, timestamps in duplicateReceivedTemp:
+                connections = []
+                for connection, direction in message.receivingConnections:
+                    if direction and connection.toFile == self       \
+                    or not direction and connection.fromFile == self:
+                        connections.append(connection)
+                if len(connections) > 1:
+                    self.duplicateReceived.append((message, len(timestamps), timestamps))
+                    
+            self.duplicateSent.sort(key = lambda message: (message[0].producer.shortId, message[0].prodSeqId))
+            self.duplicateReceived.sort(key = lambda message: (message[0].producer.shortId, message[0].prodSeqId))
+                    
+            self.calculated = True
+                  
+        return self.duplicateSent, self.duplicateReceived
+
+    def close(self):
+        """
+        Closes the underlying file.
+        Returns nothing.
+        """
+        
+        self.file.close()
+
+    def __str__(self):
+        """
+        Returns a string representation of this object.
+        """
+        
+        return self.__path
+    

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,188 @@
+"""
+Module LogParser
+"""
+import os, sys, time
+
+from LogFile import LogFile
+from Connection import Connection
+from Producer import Producer
+from Consumer import Consumer
+from Message import Message
+
+MESSAGE_TYPES = frozenset(['ActiveMQBytesMessage', 'ActiveMQTextMessage'])
+DISPATCH_MESSAGE = 'MessageDispatch'
+ADVISORY_TEXT = 'Advisory'
+CONSUMER_TEXT = 'toConsumer:'
+
+class LogParser(object):
+    """
+    This class is in charge of parsing the log files and storing the data
+    as Connection, LogFile and Message objects.
+    """
+    
+    instance = None
+    
+    @classmethod
+    def getInstance(cls):
+        """
+        Returns the sole instance of the class.
+        """
+        
+        if cls.instance is None:
+            cls.instance = LogParser()
+        return cls.instance
+    
+    @classmethod
+    def deleteInstance(cls):
+        """
+        Deletes the sole instance of the class
+        """
+        
+        cls.instance = None
+    
+    def parse (self, logFile):
+        """
+        Parses the information in a log file.
+        logFile should be a LogFile object.
+        
+        Returns nothing.
+        """
+        try:
+            for line in logFile.file:
+                loggedMessage = line.partition('$$ ')[2]
+                if loggedMessage != '':
+                    spacedStrings = loggedMessage.split()
+                    
+                    if spacedStrings[1] == 'ConnectionInfo':
+                        connectionId = spacedStrings[3]
+                        
+                        if spacedStrings[0] == 'SENDING:':
+                            logFile.addOutgoingConnection(Connection.getConnectionByLongId(connectionId))
+                            Connection.setFrom(connectionId, logFile)
+        
+                        elif spacedStrings[0] == 'RECEIVED:':
+                            logFile.addIncomingConnection(Connection.getConnectionByLongId(connectionId))
+                            Connection.setTo(connectionId, logFile)
+                            
+                        else:
+                            raise Exception('Exception: ConnectionInfo: not SENDING or RECEIVED')
+                    
+                    elif spacedStrings[1] in MESSAGE_TYPES or spacedStrings[1] == DISPATCH_MESSAGE:
+                        timestamp = line[0:23]
+                        commaValues = spacedStrings[3].split(',')
+                        
+                        messageId = commaValues[0]
+                        producerId = messageId[:messageId.rindex(':')]
+                        
+                        connection = Connection.getConnectionByLongId(commaValues[2]) #commaValues[2] = connectionId
+                        producer = Producer.getProducerByLongId(producerId)
+                        producerConnection = Connection.getConnectionByLongId(producerId.rsplit(':', 2)[0]) #producerConnectionId
+                        message = Message.getMessage(producer,
+                                                     int(messageId[messageId.rindex(':') + 1:]), #producerSequenceId
+                                                     commaValues[-1] == ADVISORY_TEXT)
+                        
+                        producerConnection.addProducer(producer)
+                        
+                        if spacedStrings[1] in MESSAGE_TYPES:
+                            
+                            if spacedStrings[0] == 'SENDING:':
+                                
+                                direction = (logFile == connection.fromFile)
+                                connection.addSentMessage(message, direction, timestamp)
+                                logFile.addSentMessage(message, timestamp)
+                                message.addSendingConnection(connection, direction, connection,
+                                                             int(commaValues[1]), timestamp) #commaValues[1] = commandId
+                                
+                            elif spacedStrings[0] == 'RECEIVED:':
+                                
+                                direction = (logFile == connection.toFile)
+                                connection.addReceivedMessage(message, direction, timestamp)
+                                logFile.addReceivedMessage(message, timestamp)
+                                message.addReceivingConnection(connection, direction, connection,
+                                                               int(commaValues[1]), timestamp) #commaValues[1] = commandId
+                        
+                        elif spacedStrings[1] == DISPATCH_MESSAGE:
+                            
+                            #additional parsing to get the consumer
+                            consumerId = spacedStrings[4][len(CONSUMER_TEXT):]
+                            consumer = Consumer.getConsumerByLongId(consumerId)
+                            consumerConnection = Connection.getConnectionByLongId(':'.join(consumerId.split(':')[:3]))
+                            consumerConnection.addConsumer(consumer)
+                        
+                            if spacedStrings[0] == 'SENDING:':
+                                
+                                direction = (logFile == connection.fromFile)
+                                consumerConnection.addSentMessage(message, direction, timestamp)
+                                logFile.addSentMessage(message, timestamp)
+                                message.addSendingConnection(consumerConnection, direction, connection,
+                                                             int(commaValues[1]), timestamp) #commaValues[1] = commandId
+                                
+                            elif spacedStrings[0] == 'RECEIVED:':
+                                
+                                direction = (logFile == connection.toFile)
+                                consumerConnection.addReceivedMessage(message, direction, timestamp)
+                                logFile.addReceivedMessage(message, timestamp)
+                                message.addReceivingConnection(consumerConnection, direction, connection,
+                                                               int(commaValues[1]), timestamp) #commaValues[1] = commandId
+        
+        except Exception:
+            print logFile, line
+            raise
+            
+            
+    def clearData(self):
+        """
+        Clears all the data parsed.
+        """
+        
+        Connection.clearData()
+        Producer.clearData()
+        Consumer.clearData()
+        Message.clearData()
+        LogFile.clearData()
+                        
+    def parseDirectory(self, directory):
+        """
+        Parses a directory of log files.
+        """
+        
+        self.clearData()
+        
+        fileNames = os.walk(directory).next()[2]
+        logFiles = [LogFile(directory + os.sep + fileName) for fileName in fileNames]
+        
+        for logFile in logFiles:
+            self.parse(logFile)
+            
+        LogFile.closeFiles()
+        
+def main():
+    """
+    Entrance point for the command line test.
+    """
+    
+    if len(sys.argv) != 2:
+        print 'Usage: python LogParser.py directory'
+    else:
+        startTime = time.time()
+        LogParser.getInstance().parseDirectory(sys.argv[1])
+        LogParser.deleteInstance()
+        print str(Message.messageCount) + ' messages parsed'
+        print 'in ' + str(time.time() - startTime) + ' seconds'
+        
+        print 'press a key'
+        sys.stdin.read(3)
+        
+        startTime = time.time()
+        for connection in Connection.connections.itervalues():
+            connection.getErrors()
+            
+        for logFile in LogFile.logfiles:
+            logFile.getErrors()
+
+        print 'additional: ' + str(time.time() - startTime) + ' seconds'
+        time.sleep(36000)
+    
+if __name__ == '__main__':
+    main()
+    
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,120 @@
+"""
+Module Message
+"""
+
+class Message(object):
+    """
+    Objects of this class represent ActiveMQ messages.
+    They are used to store the 'travel path' of every message.
+    This class also stores a collection of all the Message objects.
+    """
+    
+    messages = {}
+    messageCount = 0
+        
+    def __init__(self, producer, prodSeqId, advisory):
+        """
+        Constructs a message object, given a producer and producer sequence id.
+        """
+        
+        self.producer = producer
+        self.prodSeqId = prodSeqId
+        self.advisory = advisory
+        self.sendingConnections = {}
+        self.receivingConnections = {}
+        
+        Message.messageCount += 1
+    
+    @classmethod
+    def clearData(cls):
+        """
+        Deletes all the messages.
+        Returns nothing.
+        """
+        
+        cls.messages.clear()
+        cls.messageCount = 0
+    
+    @classmethod
+    def getMessage(cls, producer, prodSeqId, advisory = False):
+        """
+        Returns the Message object identified by (producer, prodSeqId)
+        where producer is a producer object and prodSeqId is a producer sequence id
+        message was first sent.
+        
+        If the Message object does not exist, it will be created.
+        Returns a Message object.
+        """
+        
+        messageId = (producer, prodSeqId)
+        
+        if messageId not in cls.messages:
+            cls.messages[messageId] = Message(producer, prodSeqId, advisory)
+        
+        return cls.messages[messageId]
+    
+    @classmethod
+    def exists(cls, producer, prodSeqId):
+        """
+        Returns if there is a Message object identified by (producer, prodSeqId)
+        """
+        
+        return (producer, prodSeqId) in cls.messages
+        
+    def addSendingConnection(self, connection, direction, mostRecentConId, commandId, timestamp):
+        """
+        Adds a connection to the set of connections through which this message was sent.
+        The 'direction' argument is True if the message was sent from the file
+        connection.fromFile to the file connection.toFile, and False otherwise.
+        'timestamp' is a string with the moment this message was sent trough the connection.
+        
+        Returns nothing.
+        """
+        
+        storedConnection = (connection, direction)
+        if storedConnection in self.sendingConnections:
+            self.sendingConnections[storedConnection].append((mostRecentConId, commandId, timestamp))
+        else:
+            self.sendingConnections[storedConnection] = [(mostRecentConId, commandId, timestamp)]
+        
+    def addReceivingConnection(self, connection, direction, mostRecentConId, commandId, timestamp):
+        """
+        Adds a connection to the set of connections where this message was received.
+        The 'direction' argument is True if the message was sent from the file
+        connection.fromFile to the file connection.toFile, and False otherwise.
+        'timestamp' is a string with the moment this message was received trough the connection.
+        
+        Returns nothing.
+        """
+        
+        storedConnection = (connection, direction)
+        if storedConnection in self.receivingConnections:
+            self.receivingConnections[storedConnection].append((mostRecentConId, commandId, timestamp))
+        else:
+            self.receivingConnections[storedConnection] = [(mostRecentConId, commandId, timestamp)]
+
+    def getFiles(self):
+        """
+        Returns a 2-tuple with the following 2 sets:
+            -set of LogFile objects where this message was sent.
+            -set of LogFile objects where this message was received.
+        """
+        
+        sendingFiles = set() 
+        receivingFiles = set()
+        
+        for connection, direction in self.sendingConnections:
+            
+            if direction:
+                sendingFiles.add(connection.fromFile)
+            else:
+                sendingFiles.add(connection.toFile)
+
+        for connection, direction in self.receivingConnections:
+                        
+            if direction:
+                receivingFiles.add(connection.toFile)
+            else:
+                receivingFiles.add(connection.fromFile)
+            
+        return sendingFiles, receivingFiles
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,94 @@
+"""
+Module Producer
+"""
+
+class Producer(object):
+    """
+    This class represents an ActiveMQ Producer.
+    Each producer is identified by its long id.
+    However each producer also has a short id (an integer) to identify it more easily.
+    """
+    
+    nProducers = 0
+    producerIdList = []
+    producers = {}
+    
+    def __init__(self, longId):
+        """
+        Constructor
+        """
+        
+        self.longId = longId
+        self.shortId = Producer.nProducers
+        
+        self.connectionId, sessionId, value = longId.rsplit(':', 2)
+        self.sessionId = int(sessionId)
+        self.value = int(value)
+        
+        Producer.producers[longId] = self
+        Producer.producerIdList.append(self.longId)
+        Producer.nProducers += 1
+    
+    @classmethod
+    def clearData(cls):
+        """
+        Deletes all information read about producers.
+        
+        Returns nothing.
+        """
+        
+        cls.producers.clear()
+        cls.nProducers = 0
+        del cls.producerIdList[:]
+    
+    @classmethod
+    def getProducerByLongId(cls, longId):
+        """
+        Returns a producer given its long id.
+        If there is no producer with this long id yet, it will be created.
+        """
+        
+        if longId not in cls.producers:
+            cls.producers[longId] = Producer(longId)
+
+        return cls.producers[longId]
+    
+    @classmethod
+    def getProducerByShortId(cls, shortId):
+        """
+        Returns a producer given its short id.
+        If there is no producer with thi short id yet, IndexError will be thrown.
+        """
+        
+        return cls.producers[cls.producerIdList[shortId]]
+    
+    @classmethod
+    def exists(cls, longid):
+        """
+        Returns if a producer with the given long id exists.
+        """
+        
+        return longid in cls.producers
+    
+    @classmethod
+    def shortIdToLongId(cls, shortId):
+        """
+        Transforms a producer's short id to a long id.
+        
+        Returns a long id.
+        Throws an IndexError if the short id does not exist.
+        """
+        
+        return cls.producerIdList[shortId]
+    
+    @classmethod
+    def longIdToShortId(cls, longId):
+        """
+        Transforms a producer's long id to a short id.
+        
+        Returns a long id.
+        Throws an KeyError if the long id does not exist.
+        """
+        return cls.producers[longId].shortId
+
+        
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py?view=auto&rev=565392
==============================================================================
    (empty)

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,71 @@
+"""
+Module Application
+"""
+import wx
+from DirectoryPanel import DirectoryPanel
+from TabbedPanel import TabbedPanel
+
+class MainPanel(wx.Panel):
+    """
+    Panel contained into the window of the application.
+    It contains a DirectoryPanel and a TabbedPanel.
+    
+    """
+    
+    def __init__(self, parent):
+        """
+        Constructor
+        """
+        
+        wx.Panel.__init__(self, parent, -1)
+        
+        self.tabbedPanel = TabbedPanel(self)
+        
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add(DirectoryPanel(self), 0, wx.EXPAND|wx.ALL, 5)
+        sizer.Add(self.tabbedPanel, 1, wx.EXPAND)
+        self.SetSizer(sizer)
+        
+    def logDataUpdated(self):
+        """
+        Method to be called when the parsed data has been updated.
+        The Panel will notify its children components.
+        """
+        
+        self.tabbedPanel.logDataUpdated()
+
+class MainFrame(wx.Frame):
+    """
+    This class represents the window of the application.
+    It contains a MainPanel object.
+    We need to add a wx.Panel to a wx.Frame to avoid
+    graphical problems in Windows.
+    """
+    
+    def __init__(self, parent):
+        """
+        Constructor
+        """
+        
+        wx.Frame.__init__(self, parent, 100, 
+                          'ActiveMQ Log Analyzer Tool', size=(1024,800))
+#        ib = wx.IconBundle()
+#        ib.AddIconFromFile("logparser.ico", wx.BITMAP_TYPE_ANY)
+#        self.SetIcons(ib)
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add(MainPanel(self), 1, wx.EXPAND)
+        self.SetSizer(sizer)
+        self.Centre()
+        self.Show(True)
+
+class Application(wx.App):
+    """
+    Main class of the application
+    """
+    
+    def OnInit(self):
+        """
+        To be executed when Application is launched
+        """
+        MainFrame(None)
+        return True

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,61 @@
+"""
+Module DirectoryPanel
+"""
+import wx
+import os
+
+from loganalyzerengine.LogParser import LogParser
+
+class DirectoryPanel(wx.Panel):
+    """
+    Panel to choose the directory with the log files to be parsed,
+    and launch the parsing / analyzing process.
+    """
+    
+    def __init__(self, parent):
+        """
+        Constructor
+        """
+        
+        wx.Panel.__init__(self, parent, -1)
+        self.mainPanel = parent
+        self.textctrl = wx.TextCtrl(self, -1, 'C:\logs')
+        
+        self.lastDirectoryOpen = ''
+        
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(wx.StaticText(self, -1, 'Directory'), 0, wx.CENTER|wx.RIGHT, 5)
+        sizer.Add(self.textctrl, 1, wx.CENTER|wx.RIGHT, 5)
+        sizer.Add(wx.Button(self, 100 , 'Choose'), 0, wx.CENTER|wx.RIGHT, 5)
+        sizer.Add(wx.Button(self, 101 , 'Parse'), 0, wx.CENTER)
+        
+        self.Bind(wx.EVT_BUTTON, self.OnChoose, id=100)
+        self.Bind(wx.EVT_BUTTON, self.OnParse, id=101)
+        
+        self.SetSizer(sizer)
+        
+    def OnChoose(self, event):
+        """
+        Action to be executed when the 'Choose' button is pressed.
+        """
+        
+        dialog = wx.DirDialog(self, defaultPath=self.lastDirectoryOpen)
+        if dialog.ShowModal() == wx.ID_OK:
+            self.textctrl.SetValue(dialog.GetPath())
+            self.lastDirectoryOpen = dialog.GetPath()
+        else:
+            wx.MessageDialog(self, 'Please choose an appropiate directory', style=wx.OK).ShowModal()
+        
+    def OnParse(self, event):
+        """
+        Action to be executed when the 'Parse' button is pressed.
+        """
+        
+        path = self.textctrl.GetValue()
+        if os.path.isdir(path):
+            LogParser.getInstance().parseDirectory(path)
+            self.mainPanel.logDataUpdated()
+            LogParser.deleteInstance()
+        else:
+            wx.MessageDialog(self, 'That directory does not exist', style=wx.OK).ShowModal()
+    
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,184 @@
+"""
+Module IncorrectSequenceList
+"""
+import wx
+from loganalyzerengine.Connection import Connection
+from loganalyzerengine.LogFile import LogFile
+
+def advisoryString(message):
+    """
+    Helper method
+    """
+ 
+    if message.advisory:
+        return ' (ADVISORY)'
+    else:
+        return ''
+        
+
+class IncorrectSequenceList(wx.ListCtrl):
+    """
+    List of the incorrect events detected after parsing the logs.
+    """
+    
+    def __init__(self, parent):
+        """
+        Constructor
+        """
+        
+        wx.ListCtrl.__init__(self, parent, -1, 
+                             style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_HRULES|wx.LC_VRULES)
+        
+        self.incorrectSequencePanel = parent
+        
+        self.datapresent = False
+        self.connectionForFilter = None
+        
+        self.InsertColumn(0, 'Type')
+        self.InsertColumn(1, 'Connection id / File')
+        self.InsertColumn(2, 'Message id (prod id | prod seq id)')
+        self.InsertColumn(3, 'ntimes')
+        self.InsertColumn(4, 'timestamps')
+        
+        self.SetColumnWidth(0, 150)
+        self.SetColumnWidth(1, 250)
+        self.SetColumnWidth(2, 300)
+        self.SetColumnWidth(3, 100)
+        self.SetColumnWidth(4, 300)
+        
+        
+    def logDataUpdated(self):
+        """
+        This method must be called to notify the list that the parsed data
+        has changed.
+        """
+
+        self.datapresent = True
+        self.updateList()
+        
+    def checkConnectionForFilter(self):
+        """
+        Returns True if the connection that was inputed by the user
+        to filter the events is valid.
+        self.connectionForFilter is a (string, boolean) tuple.
+        The boolean value is True if the string is a shortId, and False if it is a long id.
+        """
+        
+        if self.connectionForFilter is None:
+            return False
+        
+        if self.connectionForFilter[1]:
+            #shortId
+            return self.connectionForFilter[0].isdigit() and \
+                   int(self.connectionForFilter[0]) > -1 and \
+                   int(self.connectionForFilter[0]) < len(Connection.connectionIdList)
+        
+        else:
+            #longId
+            return self.connectionForFilter[0] in Connection.connections
+        
+    def updateList(self):
+        """
+        Updates the display of the list of incorrect events
+        """
+        
+        self.DeleteAllItems()
+        if self.datapresent:
+            options = self.incorrectSequencePanel.options
+            
+            row = 0
+            
+            # we construct a list of connection long ids to be displayed,
+            # depending on the filter desired
+            if self.checkConnectionForFilter():
+                if self.connectionForFilter[1]:
+                    #shortId
+                    connectionIds = [Connection.connectionIdList[int(self.connectionForFilter[0])]]
+                else:
+                    connectionIds = [self.connectionForFilter[0]]
+            else:
+                if self.connectionForFilter is None or self.connectionForFilter[0] == '':
+                    connectionIds = Connection.connections.keys()
+                else:
+                    connectionIds = []      
+                
+            # we display the problems tied to connections
+            showShortIDs = options['showShortIds']
+            
+            for longId in connectionIds:
+                
+                # we display long or short ids depending on the option chosen
+                connection = Connection.getConnectionByLongId(longId)
+                errors = connection.getErrors()
+                
+                if showShortIDs:
+                    printedConnectionId = connection.shortId
+                else:
+                    printedConnectionId = longId
+                
+                # sent but not received messages
+                if options['sentButNotReceived']:
+                    for storedMessage, n, timestamps in errors[0]:
+                        message = storedMessage[0]
+                        self.insertRow(row, 'sentButNotReceived' + advisoryString(message), printedConnectionId,
+                                       message.producer.shortId if showShortIDs else message.producer.longId,
+                                       message.prodSeqId, n, timestamps, wx.WHITE)
+                        row += 1
+                
+                # received but not sent messages
+                if options['receivedButNotSent']:
+                    for storedMessage, n, timestamps in errors[1]:
+                        message = storedMessage[0]
+                        self.insertRow(row, 'receivedButNotSent' + advisoryString(message), printedConnectionId,
+                                       message.producer.shortId if showShortIDs else message.producer.longId,
+                                       message.prodSeqId, n, timestamps, wx.WHITE)
+                        row += 1
+                
+                # duplicate sent or received messages through a connection
+                if options['duplicateInConnection']:
+                    for storedMessage, n, timestamps in errors[2]:
+                        message = storedMessage[0]
+                        self.insertRow(row, 'duplicateSentInConnection' + advisoryString(message), printedConnectionId,
+                                       message.producer.shortId if showShortIDs else message.producer.longId,
+                                       message.prodSeqId, n, timestamps, wx.WHITE)
+                        row += 1
+                        
+                    for storedMessage, n, timestamps in errors[3]:
+                        message = storedMessage[0]
+                        self.insertRow(row, 'duplicateReceivedInConnection' + advisoryString(message), printedConnectionId,
+                                       message.producer.shortId if showShortIDs else message.producer.longId,
+                                       message.prodSeqId, n, timestamps, wx.WHITE)
+                        row += 1
+            
+            # duplicate sent or received messages in the same log file.
+            # right now they are only shown when the connection filter is not used.
+            if options['duplicateInFile'] and not self.checkConnectionForFilter() and \
+            (self.connectionForFilter is None or self.connectionForFilter[0] == ''):
+                for logfile in LogFile.logfiles:
+                    errors = logfile.getErrors()
+                    
+                    for message, n, timestamps in errors[0]:
+                        self.insertRow(row, 'duplicateSentInFile' + advisoryString(message), str(logfile),
+                                       message.producer.shortId if showShortIDs else message.producer.longId,
+                                       message.prodSeqId, n, timestamps, wx.WHITE)
+                        row += 1
+                        
+                    for message, n, timestamps in errors[1]:
+                        self.insertRow(row, 'duplicateReceivedInFile' + advisoryString(message), str(logfile),
+                                       message.producer.shortId if showShortIDs else message.producer.longId,
+                                       message.prodSeqId, n, timestamps, wx.WHITE)
+                        row += 1
+            
+    def insertRow(self, rownumber, typeOfError, connectionId, producerId, producerSequenceId, n, timestamps, col):
+        """
+        Helper method to insert a row into the list
+        """
+        
+        self.InsertStringItem(rownumber, typeOfError)
+        self.SetStringItem(rownumber, 1, str(connectionId))
+        self.SetStringItem(rownumber, 2, str(producerId) + ' | ' + str(producerSequenceId))
+        self.SetStringItem(rownumber, 3, str(n))
+        self.SetStringItem(rownumber, 4, ' | '.join(timestamps))
+        self.SetItemBackgroundColour(rownumber, col)
+
+        
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,135 @@
+"""
+Module IncorrectSequencePanel
+"""
+import wx
+from IncorrectSequenceList import IncorrectSequenceList
+
+class IncorrectSequencePanel(wx.Panel):
+    """
+    This panel contains a list of incorrect events dectected by the parsing,
+    and many controls to filter which events appear.
+    Also the user can change if long ids (original ActiveMQConnection id strings, long)
+    or short ids (a different integer for each connection) is desired.
+    """
+    
+    def __init__(self, parent):
+        """
+        Constructor
+        """
+        
+        wx.Panel.__init__(self, parent, -1)
+        
+        self.parent = parent
+        self.options = {}
+        
+        self.incorrectSequenceList = IncorrectSequenceList(self)
+        self.showShortIds = wx.CheckBox(self, 100, 'Show results with short ids')
+        self.sentButNotReceived = wx.CheckBox(self, 101, 'Sent but not received')
+        self.receivedButNotSent = wx.CheckBox(self, 102, 'Received but not sent')
+        self.duplicateInConnection = wx.CheckBox(self, 103, 'Duplicate in connection')
+        self.duplicateInFile = wx.CheckBox(self, 104, 'Duplicate in log file')
+        self.connectionText = wx.TextCtrl(self, -1, '')
+        self.rbshortId = wx.RadioButton(self, -1, style=wx.RB_GROUP, label="Short id")
+        self.rblongId = wx.RadioButton(self, -1, label="Long id")
+        
+        self.showShortIds.SetValue(True)
+        self.sentButNotReceived.SetValue(True)
+        self.receivedButNotSent.SetValue(True)
+        self.duplicateInConnection.SetValue(True)
+        self.duplicateInFile.SetValue(True)
+        
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        
+        sizer2 = wx.GridSizer()
+        sizer2 = wx.GridSizer(2, 2, 5, 5)
+        sizer2.AddMany([self.sentButNotReceived,
+                        self.receivedButNotSent,
+                        self.duplicateInConnection,
+                        self.duplicateInFile
+                       ])
+        
+        sizer3 = wx.BoxSizer(wx.HORIZONTAL)
+        sizerrb = wx.BoxSizer(wx.VERTICAL)
+        sizerrb.Add(self.rbshortId, 0, wx.DOWN, 5)
+        sizerrb.Add(self.rblongId, 0)
+        sizer3.Add(wx.StaticText(self, -1, 'Filter by connection\n(leave blank to view all)'), 0, wx.CENTER|wx.RIGHT, 5)
+        sizer3.Add(self.connectionText, 1, wx.CENTER|wx.RIGHT, 5)
+        sizer3.Add(sizerrb, 0, wx.CENTER|wx.RIGHT, 5)
+        sizer3.Add(wx.Button(self, 105, 'Filter'), 0, wx.CENTER)
+        
+        sizer4 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer4.Add(sizer2, 0, wx.CENTER)
+        sizer4.Add(sizer3, 1, wx.EXPAND|wx.CENTER|wx.LEFT, 20)
+        
+        sizer.Add(sizer4, 0, wx.EXPAND|wx.ALL, 5)
+        
+        sizer5 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer5.Add(self.showShortIds, 0, wx.RIGHT|wx.CENTER, 5)
+        sizer5.Add(wx.Button(self, 106, 'Jump to Message Browsing'), 0, wx.CENTER)
+        
+        sizer.Add(sizer5, 0, wx.ALL, 5)
+        
+        sizer.Add(self.incorrectSequenceList, 1, wx.EXPAND)
+        
+        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=100)
+        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=101)
+        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=102)
+        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=103)
+        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=104)
+        self.Bind(wx.EVT_BUTTON, self.OnFilter, id=105)
+        self.Bind(wx.EVT_BUTTON, self.OnJump, id=106)
+        
+        self.parseOptions()
+        
+        self.SetSizer(sizer)
+        
+    def logDataUpdated(self):
+        """
+        This method must be called to notify the panel that the parsed data has been updated.
+        It will in turn notify the list.
+        """
+        
+        self.incorrectSequenceList.logDataUpdated()
+        
+    def parseOptions(self):
+        """
+        Stores the values of the various checkboxes into self.options.
+        """
+        
+        self.options['showShortIds'] = self.showShortIds.IsChecked()
+        self.options['sentButNotReceived'] = self.sentButNotReceived.IsChecked() 
+        self.options['receivedButNotSent'] = self.receivedButNotSent.IsChecked()
+        self.options['duplicateInConnection'] = self.duplicateInConnection.IsChecked()
+        self.options['duplicateInFile'] = self.duplicateInFile.IsChecked()
+    
+    def OptionsChanged(self, event):
+        """
+        Action to be executed every time one of the checkboxes is clicked.
+        It calls parseOptions() and then updates the display of incorrect events.
+        """
+        
+        self.parseOptions()
+        self.incorrectSequenceList.updateList()
+        
+    def OnFilter(self, event):
+        """
+        Action to be executed every time the button 'filter' is pressed.
+        """
+        
+        self.incorrectSequenceList.connectionForFilter = (self.connectionText.GetValue(), self.rbshortId.GetValue())
+        self.OptionsChanged(event)
+        
+    def OnJump(self, event):
+        """
+        Action to be executed when the 'jump' button is pressed.
+        """
+        
+        if self.incorrectSequenceList.GetFirstSelected() != -1:
+            connectionId, messageId = self.incorrectSequenceList.GetItem(self.incorrectSequenceList.GetFirstSelected(), 2).GetText().split(' | ')
+            self.parent.GetParent().browsingMessagesPanel.textctrl1.SetValue(connectionId)
+            self.parent.GetParent().browsingMessagesPanel.textctrl2.SetValue(messageId)
+            self.parent.GetParent().browsingMessagesPanel.rbshortId.SetValue(self.showShortIds.GetValue())
+            self.parent.GetParent().browsingMessagesPanel.rblongId.SetValue(not self.showShortIds.GetValue())
+            self.parent.GetParent().browsingMessagesPanel.displayMessageInfo(event)
+        
+            self.parent.SetSelection(1)
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py?view=auto&rev=565392
==============================================================================
--- activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py (added)
+++ activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py Mon Aug 13 09:03:25 2007
@@ -0,0 +1,66 @@
+"""
+Module MessageTravelPanel
+"""
+import wx
+from MessageTravelText import MessageTravelText
+
+class MessageTravelPanel(wx.Panel):
+    """
+    The function of this panel is to show the travel history of a message.
+    This means the connections that the message went through.
+    """
+    
+    def __init__(self, parent):
+        """
+        Constructor
+        """
+        
+        wx.Panel.__init__(self, parent, -1)
+        
+        self.rbshortId = wx.RadioButton(self, -1, style=wx.RB_GROUP, label="Short id")
+        self.rblongId = wx.RadioButton(self, -1, label="Long id")
+        self.textctrl1 = wx.TextCtrl(self, -1, '')
+        self.textctrl2 = wx.TextCtrl(self, -1, '')
+        self.chkshowshortId = wx.CheckBox(self, 100, 'Show result with short ids')
+        self.messageTravelPanel = MessageTravelText(self)
+        
+        self.chkshowshortId.SetValue(True)
+        
+        sizerrb = wx.BoxSizer(wx.VERTICAL)
+        sizerrb.Add(self.rbshortId, 0, wx.DOWN, 5)
+        sizerrb.Add(self.rblongId, 0)
+        
+        sizerinput = wx.BoxSizer(wx.HORIZONTAL)
+        sizerinput.Add(sizerrb, 0, wx.RIGHT, 5)
+        sizerinput.Add(wx.StaticText(self, -1, 'Producer id'), 0, wx.CENTER|wx.RIGHT, 5)
+        sizerinput.Add(self.textctrl1, 2, wx.CENTER|wx.RIGHT, 5)
+        sizerinput.Add(wx.StaticText(self, -1, 'Producer Sequence id'), 0, wx.CENTER|wx.RIGHT, 5)
+        sizerinput.Add(self.textctrl2, 1, wx.CENTER|wx.RIGHT, 5)
+        sizerinput.Add(wx.Button(self, 101 , 'Browse'), 0, wx.CENTER)
+        
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add(sizerinput, 0, wx.EXPAND|wx.ALL, 5)
+        sizer.Add(self.chkshowshortId, 0, wx.LEFT|wx.UP, 5)
+        sizer.Add(self.messageTravelPanel, 1, wx.EXPAND|wx.ALL, 5)
+        
+        self.Bind(wx.EVT_CHECKBOX, self.displayMessageInfo, id=100)
+        self.Bind(wx.EVT_BUTTON, self.displayMessageInfo, id=101)
+        
+        self.SetSizer(sizer)
+    
+    def displayMessageInfo(self, event):
+        """
+        Action to be executed when the 'Browse' button is pushed.
+        """
+        
+        self.messageTravelPanel.displayMessageInfo(self.textctrl1.GetValue(),
+                                                 self.textctrl2.GetValue(),
+                                                 self.rbshortId.GetValue())
+        
+    def logDataUpdated(self):
+        """
+        This method must be called to notify the panel that the parsed data has been updated.
+        It will in turn notify the message travel panel.
+        """
+        
+        self.messageTravelPanel.logDataUpdated()
\ No newline at end of file

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py
------------------------------------------------------------------------------
    svn:executable = *

Added: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc
URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc?view=auto&rev=565392
==============================================================================
Binary file - no diff available.

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc
------------------------------------------------------------------------------
    svn:executable = *

Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream



Mime
View raw message