From 58c82e3b0b67ee5aa6d9aab283f48d2f68dbdaf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Wisniewski?= <gregory@nexedi.com> Date: Tue, 22 Sep 2009 08:25:50 +0000 Subject: [PATCH] Add a packet logger for custom and fine-grained debugging messages. git-svn-id: https://svn.erp5.org/repos/neo/trunk@1297 71dcc9de-d417-0410-9af5-da40c76e7ee4 --- neo/connection.py | 17 +-- neo/logger.py | 311 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 313 insertions(+), 15 deletions(-) create mode 100644 neo/logger.py diff --git a/neo/connection.py b/neo/connection.py index 16335a30..f87e8f16 100644 --- a/neo/connection.py +++ b/neo/connection.py @@ -288,7 +288,7 @@ class Connection(BaseConnection): Process a pending packet. """ packet = self._dequeue() - self.logPacket('from', packet) + PACKET_LOGGER.log(self, packet, 'from') self.handler.packetReceived(self, packet) def pending(self): @@ -349,25 +349,12 @@ class Connection(BaseConnection): self.handler.connectionClosed(self) raise - def logPacket(self, direction, packet): - packet_type = packet.getType() - ip, port = self.getAddress() - if packet_type == protocol.ERROR: - code, message = packet.decode() - logging.debug('#0x%08x ERROR %-24s %s %s (%s:%d) %s', - packet.getId(), code, direction, dump(self.uuid), - ip, port, message) - else: - logging.debug('#0x%08x %-30s %s %s (%s:%d)', packet.getId(), - packet_type, direction, dump(self.uuid), - ip, port) - def _addPacket(self, packet): """Add a packet into the write buffer.""" if self.connector is None: return - self.logPacket(' to ', packet) + PACKET_LOGGER.log(self, packet, ' to ') try: self.write_buf += packet.encode() except PacketMalformedError, m: diff --git a/neo/logger.py b/neo/logger.py new file mode 100644 index 00000000..7080b526 --- /dev/null +++ b/neo/logger.py @@ -0,0 +1,311 @@ +# +# Copyright (C) 2006-2009 Nexedi SA +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +from neo import logging +from neo import protocol +from neo.util import dump + +class PacketLogger(object): + """ Logger at packet level (for debugging purpose) """ + + def __init__(self): + self.fetch_table = self.initFetchTable() + + def log(self, conn, packet, direction): + """This is a helper method to handle various packet types.""" + # default log message + type = packet.getType() + uuid = dump(conn.getUUID()) + ip, port = conn.getAddress() + logging.debug('#0x%08x %-30s %s %s (%s:%d)', packet.getId(), + type, direction, uuid, ip, port) + logger = self.fetch_table.get(type, None) + if logger is None: + logging.warning('No logger found for packet %s' % type) + return + # enhanced log + args = packet.decode() or () + log_message = logger(conn, packet, *args) + if log_message is not None: + logging.debug('#0x%08x %s', packet.getId(), log_message) + + + # Packet loggers + + def error(self, conn, packet, code, message): + return "%s (%s)" % (code, message) + + def requestNodeIdentification(self, conn, packet, node_type, + uuid, address, name): + pass + + def acceptNodeIdentification(self, conn, packet, node_type, + uuid, address, num_partitions, num_replicas, your_uuid): + pass + + def askPrimaryMaster(self, conn, packet): + pass + + def answerPrimaryMaster(self, conn, packet, primary_uuid, + known_master_list): + pass + + def announcePrimaryMaster(self, conn, packet): + pass + + def reelectPrimaryMaster(self, conn, packet): + pass + + def notifyNodeInformation(self, conn, packet, node_list): + pass + + def askLastIDs(self, conn, packet): + pass + + def answerLastIDs(self, conn, packet, loid, ltid, lptid): + pass + + def askPartitionTable(self, conn, packet, offset_list): + pass + + def answerPartitionTable(self, conn, packet, ptid, row_list): + pass + + def sendPartitionTable(self, conn, packet, ptid, row_list): + pass + + def notifyPartitionChanges(self, conn, packet, ptid, cell_list): + pass + + def startOperation(self, conn, packet): + pass + + def stopOperation(self, conn, packet): + pass + + def askUnfinishedTransactions(self, conn, packet): + pass + + def answerUnfinishedTransactions(self, conn, packet, tid_list): + pass + + def askObjectPresent(self, conn, packet, oid, tid): + pass + + def answerObjectPresent(self, conn, packet, oid, tid): + pass + + def deleteTransaction(self, conn, packet, tid): + pass + + def commitTransaction(self, conn, packet, tid): + pass + + def askBeginTransaction(self, conn, packet, tid): + pass + + def answerBeginTransaction(self, conn, packet, tid): + pass + + def askNewOIDs(self, conn, packet, num_oids): + pass + + def answerNewOIDs(self, conn, packet, num_oids): + pass + + def finishTransaction(self, conn, packet, oid_list, tid): + pass + + def notifyTransactionFinished(self, conn, packet, tid): + pass + + def lockInformation(self, conn, packet, tid): + pass + + def notifyInformationLocked(self, conn, packet, tid): + pass + + def invalidateObjects(self, conn, packet, oid_list, tid): + pass + + def unlockInformation(self, conn, packet, tid): + pass + + def askStoreObject(self, conn, packet, oid, serial, + compression, checksum, data, tid): + pass + + def answerStoreObject(self, conn, packet, status, oid): + pass + + def abortTransaction(self, conn, packet, tid): + pass + + def askStoreTransaction(self, conn, packet, tid, user, desc, + ext, oid_list): + pass + + def answerStoreTransaction(self, conn, packet, tid): + pass + + def askObject(self, conn, packet, oid, serial, tid): + pass + + def answerObject(self, conn, packet, oid, serial_start, + serial_end, compression, checksum, data): + pass + + def askTIDs(self, conn, packet, first, last, partition): + pass + + def answerTIDs(self, conn, packet, tid_list): + pass + + def askTransactionInformation(self, conn, packet, tid): + pass + + def answerTransactionInformation(self, conn, packet, tid, + user, desc, ext, oid_list): + pass + + def askObjectHistory(self, conn, packet, oid, first, last): + pass + + def answerObjectHistory(self, conn, packet, oid, history_list): + pass + + def askOIDs(self, conn, packet, first, last, partition): + pass + + def answerOIDs(self, conn, packet, oid_list): + pass + + def askPartitionList(self, conn, packet, min_offset, max_offset, uuid): + pass + + def answerPartitionList(self, conn, packet, ptid, row_list): + pass + + def askNodeList(self, conn, packet, offset_list): + pass + + def answerNodeList(self, conn, packet, node_list): + pass + + def setNodeState(self, conn, packet, uuid, state, modify_partition_table): + pass + + def answerNodeState(self, conn, packet, uuid, state): + pass + + def addPendingNodes(self, conn, packet, uuid_list): + pass + + def answerNewNodes(self, conn, packet, uuid_list): + pass + + def askNodeInformation(self, conn, packet): + pass + + def answerNodeInformation(self, conn, packet, node_list): + pass + + def askClusterState(self, conn, packet): + pass + + def answerClusterState(self, conn, packet, state): + pass + + def setClusterState(self, conn, packet, state): + pass + + def notifyClusterInformation(self, conn, packet, state): + pass + + def notifyLastOID(self, conn, packet, oid): + pass + + + # Fetch tables initialization + def initFetchTable(self): + d = {} + d[protocol.ERROR] = self.error + d[protocol.REQUEST_NODE_IDENTIFICATION] = self.requestNodeIdentification + d[protocol.ACCEPT_NODE_IDENTIFICATION] = self.acceptNodeIdentification + d[protocol.ASK_PRIMARY_MASTER] = self.askPrimaryMaster + d[protocol.ANSWER_PRIMARY_MASTER] = self.answerPrimaryMaster + d[protocol.ANNOUNCE_PRIMARY_MASTER] = self.announcePrimaryMaster + d[protocol.REELECT_PRIMARY_MASTER] = self.reelectPrimaryMaster + d[protocol.NOTIFY_NODE_INFORMATION] = self.notifyNodeInformation + d[protocol.ASK_LAST_IDS] = self.askLastIDs + d[protocol.ANSWER_LAST_IDS] = self.answerLastIDs + d[protocol.ASK_PARTITION_TABLE] = self.askPartitionTable + d[protocol.ANSWER_PARTITION_TABLE] = self.answerPartitionTable + d[protocol.SEND_PARTITION_TABLE] = self.sendPartitionTable + d[protocol.NOTIFY_PARTITION_CHANGES] = self.notifyPartitionChanges + d[protocol.START_OPERATION] = self.startOperation + d[protocol.STOP_OPERATION] = self.stopOperation + d[protocol.ASK_UNFINISHED_TRANSACTIONS] = self.askUnfinishedTransactions + d[protocol.ANSWER_UNFINISHED_TRANSACTIONS] = self.answerUnfinishedTransactions + d[protocol.ASK_OBJECT_PRESENT] = self.askObjectPresent + d[protocol.ANSWER_OBJECT_PRESENT] = self.answerObjectPresent + d[protocol.DELETE_TRANSACTION] = self.deleteTransaction + d[protocol.COMMIT_TRANSACTION] = self.commitTransaction + d[protocol.ASK_BEGIN_TRANSACTION] = self.askBeginTransaction + d[protocol.ANSWER_BEGIN_TRANSACTION] = self.answerBeginTransaction + d[protocol.FINISH_TRANSACTION] = self.finishTransaction + d[protocol.NOTIFY_TRANSACTION_FINISHED] = self.notifyTransactionFinished + d[protocol.LOCK_INFORMATION] = self.lockInformation + d[protocol.NOTIFY_INFORMATION_LOCKED] = self.notifyInformationLocked + d[protocol.INVALIDATE_OBJECTS] = self.invalidateObjects + d[protocol.UNLOCK_INFORMATION] = self.unlockInformation + d[protocol.ASK_NEW_OIDS] = self.askNewOIDs + d[protocol.ANSWER_NEW_OIDS] = self.answerNewOIDs + d[protocol.ASK_STORE_OBJECT] = self.askStoreObject + d[protocol.ANSWER_STORE_OBJECT] = self.answerStoreObject + d[protocol.ABORT_TRANSACTION] = self.abortTransaction + d[protocol.ASK_STORE_TRANSACTION] = self.askStoreTransaction + d[protocol.ANSWER_STORE_TRANSACTION] = self.answerStoreTransaction + d[protocol.ASK_OBJECT] = self.askObject + d[protocol.ANSWER_OBJECT] = self.answerObject + d[protocol.ASK_TIDS] = self.askTIDs + d[protocol.ANSWER_TIDS] = self.answerTIDs + d[protocol.ASK_TRANSACTION_INFORMATION] = self.askTransactionInformation + d[protocol.ANSWER_TRANSACTION_INFORMATION] = self.answerTransactionInformation + d[protocol.ASK_OBJECT_HISTORY] = self.askObjectHistory + d[protocol.ANSWER_OBJECT_HISTORY] = self.answerObjectHistory + d[protocol.ASK_OIDS] = self.askOIDs + d[protocol.ANSWER_OIDS] = self.answerOIDs + d[protocol.ASK_PARTITION_LIST] = self.askPartitionList + d[protocol.ANSWER_PARTITION_LIST] = self.answerPartitionList + d[protocol.ASK_NODE_LIST] = self.askNodeList + d[protocol.ANSWER_NODE_LIST] = self.answerNodeList + d[protocol.SET_NODE_STATE] = self.setNodeState + d[protocol.ANSWER_NODE_STATE] = self.answerNodeState + d[protocol.SET_CLUSTER_STATE] = self.setClusterState + d[protocol.ADD_PENDING_NODES] = self.addPendingNodes + d[protocol.ANSWER_NEW_NODES] = self.answerNewNodes + d[protocol.ASK_NODE_INFORMATION] = self.askNodeInformation + d[protocol.ANSWER_NODE_INFORMATION] = self.answerNodeInformation + d[protocol.ASK_CLUSTER_STATE] = self.askClusterState + d[protocol.ANSWER_CLUSTER_STATE] = self.answerClusterState + d[protocol.NOTIFY_CLUSTER_INFORMATION] = self.notifyClusterInformation + d[protocol.NOTIFY_LAST_OID] = self.notifyLastOID + return d + + +PACKET_LOGGER = PacketLogger() -- 2.30.9