import collections from Qt import QtCore, QtGui from openpype.lib.log import PypeLogger class LogModel(QtGui.QStandardItemModel): COLUMNS = ( "process_name", "hostname", "hostip", "username", "system_name", "started" ) colums_mapping = { "process_name": "Process Name", "process_id": "Process Id", "hostname": "Hostname", "hostip": "Host IP", "username": "Username", "system_name": "System name", "started": "Started at" } process_keys = ( "process_id", "hostname", "hostip", "username", "system_name", "process_name" ) log_keys = ( "timestamp", "level", "thread", "threadName", "message", "loggerName", "fileName", "module", "method", "lineNumber" ) default_value = "- Not set -" ROLE_LOGS = QtCore.Qt.UserRole + 2 ROLE_PROCESS_ID = QtCore.Qt.UserRole + 3 def __init__(self, parent=None): super(LogModel, self).__init__(parent) self.log_by_process = None self.dbcon = None # Crash if connection is not possible to skip this module if not PypeLogger.initialized: PypeLogger.initialize() connection = PypeLogger.get_log_mongo_connection() if connection: PypeLogger.bootstrap_mongo_log() database = connection[PypeLogger.log_database_name] self.dbcon = database[PypeLogger.log_collection_name] def headerData(self, section, orientation, role): if ( role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal ): if section < len(self.COLUMNS): key = self.COLUMNS[section] return self.colums_mapping.get(key, key) super(LogModel, self).headerData(section, orientation, role) def add_process_logs(self, process_logs): items = [] first_item = True for key in self.COLUMNS: display_value = str(process_logs[key]) item = QtGui.QStandardItem(display_value) if first_item: first_item = False item.setData(process_logs["_logs"], self.ROLE_LOGS) item.setData(process_logs["process_id"], self.ROLE_PROCESS_ID) items.append(item) self.appendRow(items) def refresh(self): self.log_by_process = collections.defaultdict(list) self.process_info = {} self.clear() self.beginResetModel() if self.dbcon: result = self.dbcon.find({}) for item in result: process_id = item.get("process_id") # backwards (in)compatibility if not process_id: continue if process_id not in self.process_info: proc_dict = {"_logs": []} for key in self.process_keys: proc_dict[key] = ( item.get(key) or self.default_value ) self.process_info[process_id] = proc_dict log_item = {} for key in self.log_keys: log_item[key] = item.get(key) or self.default_value if "exception" in item: log_item["exception"] = item["exception"] self.process_info[process_id]["_logs"].append(log_item) for item in self.process_info.values(): item["_logs"] = sorted( item["_logs"], key=lambda item: item["timestamp"] ) item["started"] = item["_logs"][0]["timestamp"] self.add_process_logs(item) self.endResetModel() class LogsFilterProxy(QtCore.QSortFilterProxyModel): def __init__(self, *args, **kwargs): super(LogsFilterProxy, self).__init__(*args, **kwargs) self.col_usernames = None self.filter_usernames = set() def update_users_filter(self, users): self.filter_usernames = set() for user in users or tuple(): self.filter_usernames.add(user) self.invalidateFilter() def filterAcceptsRow(self, source_row, source_parent): if self.col_usernames is not None: index = self.sourceModel().index( source_row, self.col_usernames, source_parent ) user = index.data(QtCore.Qt.DisplayRole) if user not in self.filter_usernames: return False return True