You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ra...@apache.org on 2007/08/13 18:03:27 UTC
svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool: ./
loganalyzerengine/ loganalyzergui/ screenshots/
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
Re: svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
Posted by Rob Davies <ra...@gmail.com>.
oops - read too quickly - will remove the *.pyc files only :)
On Aug 13, 2007, at 9:31 PM, Albert Strasheim wrote:
> Hello
>
> The *.pyc files probably shouldn't be in the repository.
>
> Regards,
>
> Albert
>
> ----- Original Message ----- From: <ra...@apache.org>
> To: <co...@activemq.apache.org>
> Sent: Monday, August 13, 2007 6:03 PM
> Subject: svn commit: r565392 [1/2] - in /activemq/trunk/
> log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
>
>
>> 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)
>
Re: svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
Posted by Rob Davies <ra...@gmail.com>.
ok - will remove - any suggestions on a good home ?
On Aug 13, 2007, at 9:31 PM, Albert Strasheim wrote:
> Hello
>
> The *.pyc files probably shouldn't be in the repository.
>
> Regards,
>
> Albert
>
> ----- Original Message ----- From: <ra...@apache.org>
> To: <co...@activemq.apache.org>
> Sent: Monday, August 13, 2007 6:03 PM
> Subject: svn commit: r565392 [1/2] - in /activemq/trunk/
> log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
>
>
>> 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)
>
Re: svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
Posted by Albert Strasheim <fu...@gmail.com>.
Hello
The *.pyc files probably shouldn't be in the repository.
Regards,
Albert
----- Original Message -----
From: <ra...@apache.org>
To: <co...@activemq.apache.org>
Sent: Monday, August 13, 2007 6:03 PM
Subject: svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool:
./ loganalyzerengine/ loganalyzergui/ screenshots/
> 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)
Re: svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
Posted by Hiram Chirino <hi...@hiramchirino.com>.
Apache Headers???
On 8/13/07, rajdavies@apache.org <ra...@apache.org> wrote:
> 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
>
>
>
--
Regards,
Hiram
Blog: http://hiramchirino.com