def initHosts(self, hosts, hostKPIs, srvcKPIs): kpis_sql = sql.kpis_info if not self.connection: log('no db connection...') return log('init hosts: %s' % str(hosts)) log('init hosts, hostKPIs: %s' % str(hostKPIs)) log('init hosts, srvcKPIs: %s' % str(srvcKPIs)) sql_string = sql.hosts_info t0 = time.time() rows = db.execute_query(self.connection, sql_string, []) if cfg('hostmapping'): for i in range(0, len(rows)): hm = cfg('hostmapping') pm = cfg('portmapping') hosts.append({ 'host': rows[i][0].replace(hm[0], hm[1]), 'port': rows[i][1].replace(pm[0], pm[1]), 'from': rows[i][2], 'to': rows[i][3] }) else: for i in range(0, len(rows)): hosts.append({ 'host': rows[i][0], 'port': rows[i][1], 'from': rows[i][2], 'to': rows[i][3] }) rows = db.execute_query(self.connection, kpis_sql, []) kpiDescriptions.initKPIDescriptions(rows, hostKPIs, srvcKPIs) t1 = time.time() try: dpDBCustom.scanKPIsN(hostKPIs, srvcKPIs, kpiDescriptions.kpiStylesNN) except Exception as e: log('[e] error loading custom kpis') log('[e] fix or delete the problemmatic yaml for proper connect') raise e t2 = time.time() kpiDescriptions.clarifyGroups() log('hostsInit time: %s/%s' % (str(round(t1 - t0, 3)), str(round(t2 - t1, 3))))
def menuDummy(self): self.chartArea.dp = dpDummy.dataProvider() # generated data if cfg('saveKPIs', True): self.chartArea.initDP(self.layout['kpis']) else: self.chartArea.initDP()
def clarifyGroups(): ''' gives pre-defined names to most useful groups ''' thread_kpis = [ 'active_thread_count', 'waiting_thread_count', 'total_thread_count', 'active_sql_executor_count', 'waiting_sql_executor_count', 'total_sql_executor_count' ] def update_hardcoded(kpis, kpiList, grp): for kpi in kpis: if kpis[kpi]['name'] in kpiList: kpis[kpi]['group'] = grp def update(grpIdx, grpName): if grpIdx == grpName: return for h in kpiStylesNN: for kpi in kpiStylesNN[h]: if kpiStylesNN[h][kpi]['group'] == grpIdx: kpiStylesNN[h][kpi]['group'] = grpName def updateDunit(grpIdx, dUnit): for h in kpiStylesNN: for kpi in kpiStylesNN[h]: if kpiStylesNN[h][kpi]['group'] == grpIdx: kpiStylesNN[h][kpi]['dUnit'] = dUnit for h in kpiStylesNN: if 'cpu' in kpiStylesNN[h]: update(kpiStylesNN[h]['cpu']['group'], 'cpu') if 'memory_used' in kpiStylesNN[h]: update(kpiStylesNN[h]['memory_used']['group'], 'mem') if cfg('experimental') and cfg('memoryGB'): updateDunit('mem', 'GB') if thread_kpis[0] in kpiStylesNN[h]: update_hardcoded(kpiStylesNN[h], thread_kpis, 33) if 'active_thread_count' in kpiStylesNN[h]: update(kpiStylesNN[h]['active_thread_count']['group'], 'thr')
def menuFont(self): id = QInputDialog sf = cfg('fontScale', 1) sf, ok = id.getDouble(self, 'Input the scaling factor', 'Scaling Factor', sf, 0, 5, 2) if ok: self.chartArea.widget.calculateMargins(sf) self.chartArea.adjustScale(sf)
def generateRaduga(n): #random.seed(cfg('radugaSeed', 1)) colors = utils.cfg('raduga') for c in colors: color = QColor(c) pen = QPen(color) radugaColors.append(color) radugaPens.append(pen)
def handler(self, exctype, value, tb): global ryba cwd = getcwd() log('[!] fatal exception\n') #details = '%s: %s\n' % (str(exctype), str(value)) details = '%s.%s: %s\n\n' % (exctype.__module__, exctype.__qualname__, str(value)) #??? #self.errorSignal.emit() #sys._excepthook(exctype, value, traceback) for s in traceback.format_tb(tb): details += '>>' + s.replace('\\n', '\n').replace(cwd, '..') log(details, nots=True) if ryba.tabs: for i in range(ryba.tabs.count() - 1, 0, -1): w = ryba.tabs.widget(i) if isinstance(w, sqlConsole.sqlConsole): w.delayBackup() try: if utils.cfg('saveLayout', True): ryba.dumpLayout() except Exception as e: log('[!] Exception during exception handler: %s' % str(e)) details += '\n[!] Exception during exception handler:\n' details += str(e) msgBox = QMessageBox() msgBox.setWindowTitle('Fatal error') msgBox.setText( 'Unhandled exception occured. Check the log file for details.') msgBox.setIcon(QMessageBox.Critical) msgBox.setDetailedText(details) iconPath = resourcePath('ico\\favicon.ico') msgBox.setWindowIcon(QIcon(iconPath)) msgBox.exec_() sys.exit(0)
def contextMenuEvent(self, event): cmenu = QMenu(self) if cfg('experimental-disabled'): increaseScale = cmenu.addAction('Increase') decreaseScale = cmenu.addAction('Decrease') resetScale = cmenu.addAction('Reset') action = cmenu.exec_(self.mapToGlobal(event.pos())) kpi = self.kpiNames[self.currentRow()] if action == increaseScale: self.adjustScale.emit('increase', kpi) if action == decreaseScale: self.adjustScale.emit('decrease', kpi)
def menuQuit(self): ''' for i in range(self.tabs.count() -1, 0, -1): w = self.tabs.widget(i) if isinstance(w, sqlConsole.sqlConsole): status = w.close(True) # can abort if status == True: self.tabs.removeTab(i) if status == False: return ''' if cfg('saveLayout', True): self.dumpLayout() self.close()
init_system_policy.load_state_dict(system_policy.state_dict()) system_ppo = PPO(config, system_policy, init_policy=init_system_policy) # reward_true = RewardTruth(config).to(device=device) # this is the ground truth which will not be updated once randomly initialized. reward_true = RewardTruthSampled(config).to(device) reward_true = init_net(reward_true) logging.info("Finish building module: reward agent, user ppo, system ppo") main_agent = InteractAgent(config=config, user_agent=user_ppo, user_reward=reward_agent, system_agent=system_ppo, reward_groundtruth=reward_true ) for e_id in range(config.master_epochs): main_agent.master_train(e_id) # for _ in range(3): # main_agent.system_train() # raise ValueError("stop here") logging.info("@@@@@@@@@@ Finished @@@@@@@@@@@") if __name__ == "__main__": config = cfg() main(config)
def closeEvent(self, event): log('Exiting...') if cfg('saveLayout', True): self.dumpLayout() '''
def initUI(self): if cfg('saveLayout', True): self.layout = Layout(True) if self.layout['running']: answer = utils.yesNoDialog( 'Warning', 'Another RybaFish is already running, all the layout and autosave features will be disabled.\n\nExit now?', ignore=True) #answer = utils.yesNoDialog('Warning', 'RybaFish is already running or crashed last time, all the layout and autosave features will be disabled.\n\nExit now?', ignore = True) if answer == True or answer is None: exit(0) if answer == 'ignore': log('Ignoring the layout') else: self.layout = None else: self.layout['running'] = True self.layout.dump() else: self.layout = Layout() # bottom left frame (hosts) hostsArea = QFrame(self) self.hostTable = hostsTable.hostsTable() # bottom right frame (KPIs) self.kpisTable = kpiTable.kpiTable() kpisTable = self.kpisTable # top (main chart area) self.chartArea = chartArea.chartArea() ind = indicator() self.chartArea.indicator = ind # establish hard links: kpisTable.kpiScales = self.chartArea.widget.nscales self.chartArea.widget.hosts = self.hostTable.hosts kpisTable.hosts = self.chartArea.widget.hosts #why do we have hosts inside widget? because we have all data there... kpisTable.hostKPIs = self.chartArea.hostKPIs kpisTable.srvcKPIs = self.chartArea.srvcKPIs kpisTable.nkpis = self.chartArea.widget.nkpis # bottm part left+right self.kpiSplitter = QSplitter(Qt.Horizontal) self.kpiSplitter.addWidget(self.hostTable) self.kpiSplitter.addWidget(kpisTable) self.kpiSplitter.setSizes([200, 380]) self.tabs = QTabWidget() # self.tabs.currentChanged.connect(self.tabChanged) # main window splitter self.mainSplitter = QSplitter(Qt.Vertical) kpisWidget = QWidget() lo = QVBoxLayout(kpisWidget) lo.addWidget(self.kpiSplitter) self.mainSplitter.addWidget(self.chartArea) self.mainSplitter.addWidget(kpisWidget) if self.layout is not None: if self.layout['mainSplitter']: self.mainSplitter.setSizes(self.layout['mainSplitter']) else: self.mainSplitter.setSizes([300, 90]) if self.layout['kpiSplitter']: self.kpiSplitter.setSizes(self.layout['kpiSplitter']) else: self.kpiSplitter.setSizes([200, 380]) if self.layout['hostTableWidth']: hostTableWidth = self.layout['hostTableWidth'] for i in range(self.hostTable.columnCount()): if i > len(hostTableWidth) - 1: break self.hostTable.setColumnWidth(i, hostTableWidth[i]) if self.layout['KPIsTableWidth']: KPIsTableWidth = self.layout['KPIsTableWidth'] for i in range(self.kpisTable.columnCount()): if i > len(KPIsTableWidth) - 1: break self.kpisTable.setColumnWidth(i, KPIsTableWidth[i]) else: self.mainSplitter.setSizes([300, 90]) self.kpiSplitter.setSizes([200, 380]) self.mainSplitter.setAutoFillBackground(True) # central widget #self.setCentralWidget(mainSplitter) kpisWidget.autoFillBackground = True self.tabs.addTab(self.mainSplitter, 'Chart') self.chartArea.selfRaise.connect(self.raiseTab) ind.iClicked.connect(self.chartArea.indicatorSignal) self.setCentralWidget(self.tabs) # service stuff self.statusbar = self.statusBar() self.statusbar.addPermanentWidget(ind) #menu iconPath = resourcePath('ico\\favicon.ico') exitAct = QAction('&Exit', self) exitAct.setShortcut('Alt+Q') exitAct.setStatusTip('Exit application') exitAct.triggered.connect(self.menuQuit) dummyAct = QAction('&Dummy', self) dummyAct.setShortcut('Alt+D') dummyAct.setStatusTip('Dummy Data provider') dummyAct.triggered.connect(self.menuDummy) configAct = QAction('&Connect', self) configAct.setShortcut('Alt+C') configAct.setStatusTip('Configure connection') configAct.triggered.connect(self.menuConfig) importAct = QAction('&Import nameserver history trace', self) importAct.setShortcut('Ctrl+I') importAct.setStatusTip('Import nameserver.trc') importAct.triggered.connect(self.menuImport) sqlConsAct = QAction('New &SQL Console', self) sqlConsAct.setShortcut('Alt+S') sqlConsAct.setStatusTip('Create SQL Console') sqlConsAct.triggered.connect(self.menuSQLConsole) openAct = QAction('&Open file in new sql console', self) openAct.setShortcut('Ctrl+O') openAct.setStatusTip('Open new console with the file') openAct.triggered.connect(self.menuOpen) saveAct = QAction('&Save sql to a file', self) saveAct.setShortcut('Ctrl+S') saveAct.setStatusTip('Saves sql from current console to a file') saveAct.triggered.connect(self.menuSave) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(configAct) fileMenu.addAction(importAct) fileMenu.addAction(sqlConsAct) fileMenu.addAction(openAct) fileMenu.addAction(saveAct) if cfg('experimental'): fileMenu.addAction(dummyAct) fileMenu.addAction(exitAct) actionsMenu = menubar.addMenu('&Actions') if cfg('experimental'): # fileMenu.addAction(aboutAct) -- print not sure why its here fontAct = QAction('&Adjust Fonts', self) fontAct.setStatusTip( 'Adjust margins after font change (for example after move to secondary screen)' ) fontAct.triggered.connect(self.menuFont) actionsMenu.addAction(fontAct) # issue #255 reloadConfigAct = QAction('Reload &Config', self) reloadConfigAct.setStatusTip( 'Reload configuration file. Note: some values used during the connect or other one-time-actions (restart required).' ) reloadConfigAct.triggered.connect(self.menuReloadConfig) actionsMenu.addAction(reloadConfigAct) reloadCustomKPIsAct = QAction('Reload Custom &KPIs', self) reloadCustomKPIsAct.setStatusTip('Reload definition of custom KPIs') reloadCustomKPIsAct.triggered.connect(self.menuReloadCustomKPIs) actionsMenu.addAction(reloadCustomKPIsAct) # help menu part aboutAct = QAction(QIcon(iconPath), '&About', self) aboutAct.setStatusTip('About this app') aboutAct.triggered.connect(self.menuAbout) confHelpAct = QAction('Configuration', self) confHelpAct.setStatusTip('Configuration options description') confHelpAct.triggered.connect(self.menuConfHelp) confCustomHelpAct = QAction('Custom KPIs', self) confCustomHelpAct.setStatusTip('Short manual on custom KPIs') confCustomHelpAct.triggered.connect(self.menuCustomConfHelp) confTipsAct = QAction('Tips and tricks', self) confTipsAct.setStatusTip('Tips and tricks description') confTipsAct.triggered.connect(self.menuTips) helpMenu = menubar.addMenu('&Help') helpMenu.addAction(confHelpAct) helpMenu.addAction(confCustomHelpAct) helpMenu.addAction(confTipsAct) helpMenu.addAction(aboutAct) # finalization if self.layout is not None and self.layout['pos'] and self.layout[ 'size']: pos = self.layout['pos'] size = self.layout['size'] #print('screen number', QApplication.desktop().screenNumber()) #print('number of screens', QApplication.desktop().screenCount()) #print('available geometry:', QApplication.desktop().availableGeometry()) #print('screen geometry:', QApplication.desktop().screenGeometry()) r = QRect(pos[0], pos[1], size[0], size[1]) if QApplication.desktop().screenCount() == 1: # only when just one screen is available... if not QApplication.desktop().screenGeometry().contains( r) and not cfg('dontAutodetectScreen'): #the window will not be visible so jump to the main screen: (pos[0], pos[1]) = (100, 50) #self.setGeometry(pos[0] + 8, pos[1] + 31, size[0], size[1]) #self.setGeometry(pos[0], pos[1], size[0], size[1]) self.move(pos[0], pos[1]) self.resize(size[0], size[1]) else: self.setGeometry(200, 200, 1400, 800) self.setWindowTitle('RybaFish Charts') self.setWindowIcon(QIcon(iconPath)) scrollPosition = [] if cfg('saveOpenTabs', True) and self.layout is not None and self.layout['tabs']: for t in self.layout['tabs']: if len(t) != 4: continue console = sqlConsole.sqlConsole(self, None, '?') console.nameChanged.connect(self.changeActiveTabName) console.cons.closeSignal.connect(self.closeTab) self.tabs.addTab(console, console.tabname) ind = indicator() console.indicator = ind console.selfRaise.connect(self.raiseTab) ind.iClicked.connect(console.reportRuntime) self.statusbar.addPermanentWidget(ind) self.tabs.setCurrentIndex(self.tabs.count() - 1) if t[0] is not None or t[1] is not None: # such a tab should not ever be saved (this call will just open fileOpen dialog), anyway... # should we even create such a tab? console.openFile(t[0], t[1]) pos = t[2] block = t[3] scrollPosition.append(block) if isinstance(pos, int) and isinstance(block, int): cursor = console.cons.textCursor() cursor.setPosition(pos, cursor.MoveAnchor) console.cons.setTextCursor(cursor) indx = self.layout['currentTab'] if isinstance(indx, int): self.tabs.setCurrentIndex(indx) w = self.tabs.widget(indx) if isinstance(w, sqlConsole.sqlConsole): w.cons.setFocus() else: self.tabs.setCurrentIndex(0) self.show() #scroll everything to stored position for i in range(self.tabs.count() - 1, 0, -1): w = self.tabs.widget(i) if isinstance(w, sqlConsole.sqlConsole): if i - 1 < len(scrollPosition): block = scrollPosition[i - 1] w.cons.edit.verticalScrollBar().setValue(block) else: log('[w] scroll position list out of range, ignoring scrollback...' ) ''' set up some interactions ''' # bind kpi checkbox signal kpisTable.checkboxToggle.connect(self.chartArea.checkboxToggle) # bind change scales signal kpisTable.adjustScale.connect(self.chartArea.adjustScale) kpisTable.setScale.connect(self.chartArea.setScale) # host table row change signal self.hostTable.hostChanged.connect(kpisTable.refill) # to fill hosts self.chartArea.hostsUpdated.connect(self.hostTable.hostsUpdated) # refresh self.chartArea.kpiToggled.connect(kpisTable.refill) # update scales signal self.chartArea.scalesUpdated.connect(kpisTable.updateScales) log('self.scalesUpdated.emit() #0', 5) self.chartArea.scalesUpdated.emit( ) # it really not supposed to have any to update here #bind statusbox updating signals self.chartArea.statusMessage_.connect(self.statusMessage) self.chartArea.widget.statusMessage_.connect(self.statusMessage) self.chartArea.connected.connect(self.setTabName) log('init finish()') # offline console tests if cfg('developmentMode'): #tname = sqlConsole.generateTabName() #idx = self.tabs.count() self.sqlTabCounter += 1 idx = self.sqlTabCounter if idx > 1: tname = 'sql' + str(idx) else: tname = 'sql' console = sqlConsole.sqlConsole(self, None, tname) console.nameChanged.connect(self.changeActiveTabName) from SQLSyntaxHighlighter import SQLSyntaxHighlighter self.tabs.addTab(console, tname) console.selfRaise.connect(self.raiseTab) self.tabs.setCurrentIndex(self.tabs.count() - 1) self.SQLSyntax = SQLSyntaxHighlighter(console.cons.document()) #console.cons.setPlainText('select * from dummy;\n\nselect \n *\n from dummy;\n\nselect * from m_host_information;'); ind = indicator() console.indicator = ind self.statusbar.addPermanentWidget(ind) ind.iClicked.connect(console.reportRuntime) if cfg('developmentMode'): console.cons.setPlainText('''select 0 from dummy; create procedure ... ( (as begin) select * from dummy); end; where timestamp between '2020-02-10 00:00:00' and '2020-02-16 23:59:59' -- test comment where not "NAME1" = '' and "DOKST" in ('D0', 'D2') and (1 = 2) select 1 from dummy; select 2 from dummy; select 3 from dummy;''') console.dummyResultTable() self.statusMessage('', False) if self.chartArea.dp: self.chartArea.initDP()
def initHosts(self, hosts, hostKPIs, srvcKPIs): kpiDummy = { 'hierarchy': '1', 'type': 'service', 'name': 'cpu', 'group': 'cpu', 'label': 'CPU', 'description': 'Service CPU', 'sUnit': '%', 'dUnit': '%', 'color': '#F00', 'style': 'solid' } kpiDummyMem = { 'hierarchy': '2', 'type': 'service', 'name': 'indexserverMemUsed', 'group': 'mem', 'sUnit': 'Byte/sample', 'dUnit': 'MB/sec', 'label': 'Memory used', 'description': 'Service Memory Usage', 'color': '#0D0', 'style': 'solid' } kpiDescriptions.kpiStylesNN['service'][ 'cpu'] = kpiDescriptions.createStyle(kpiDummy) kpiDescriptions.kpiStylesNN['service'][ 'indexserverMemUsed'] = kpiDescriptions.createStyle(kpiDummyMem) kpiDummy['type'] = 'host' kpiDummy['style'] = 'dashed' kpiDummy['description'] = 'Host CPU' kpiDescriptions.kpiStylesNN['host'][ 'cpu'] = kpiDescriptions.createStyle(kpiDummy) hostKPIs.append('cpu') srvcKPIs.append('cpu') srvcKPIs.append('indexserverMemUsed') #srvcKPIs.append('memory_allocation_limit') stime = datetime.datetime.now() - datetime.timedelta(seconds=18 * 3600) stime -= datetime.timedelta(seconds=stime.timestamp() % 3600) #etime = stime + datetime.timedelta(seconds = 5*3600) etime = datetime.datetime.now() hosts.append({ 'host': 'dummy1', 'port': '', 'from': stime, 'to': etime }) hosts.append({ 'host': 'dummy1', 'port': '30040', 'from': stime, 'to': etime }) hosts.append({ 'host': 'dummy1', 'port': '30041', 'from': stime, 'to': etime }) if cfg('experimental'): dpDBCustom.scanKPIsN(hostKPIs, srvcKPIs, kpiDescriptions.kpiStylesNN)
def menuConfig(self): if self.connectionConf is None: connConf = cfg('server') else: connConf = self.connectionConf conf, ok = configDialog.Config.getConfig(connConf, self) if ok: self.connectionConf = conf if ok and conf['ok']: try: # need to disconnect open consoles first... self.statusMessage('Disconnecing open consoles...', False) for i in range(self.tabs.count()): w = self.tabs.widget(i) if isinstance( w, sqlConsole.sqlConsole) and w.conn is not None: log('closing connection...') w.disconnectDB() w.indicator.status = 'disconnected' w.indicator.repaint() log('disconnected...') self.statusMessage('Connecting...', False) self.repaint() self.chartArea.setStatus('sync', True) self.chartArea.dp = dpDB.dataProvider(conf) # db data provider self.chartArea.setStatus('idle') for i in range(self.tabs.count()): w = self.tabs.widget(i) if isinstance(w, sqlConsole.sqlConsole): w.config = conf if cfg('saveKPIs', True): if self.layout and 'kpis' in self.layout.lo: self.chartArea.initDP(self.layout['kpis']) else: self.chartArea.initDP() starttime = datetime.datetime.now() - datetime.timedelta( seconds=12 * 3600) starttime -= datetime.timedelta( seconds=starttime.timestamp() % 3600) self.chartArea.fromEdit.setText( starttime.strftime('%Y-%m-%d %H:%M:%S')) self.chartArea.toEdit.setText('') else: self.chartArea.initDP() if hasattr(self.chartArea.dp, 'dbProperties'): self.chartArea.widget.timeZoneDelta = self.chartArea.dp.dbProperties[ 'timeZoneDelta'] self.chartArea.reloadChart() propStr = conf['user'] + '@' + self.chartArea.dp.dbProperties[ 'sid'] self.tabs.setTabText(0, propStr) self.setWindowTitle('RybaFish Charts [%s]' % propStr) #setup keep alives if cfg('keepalive'): try: keepalive = int(cfg('keepalive')) self.chartArea.dp.enableKeepAlive(self, keepalive) except: log('wrong keepalive setting: %s' % (cfg('keepalive'))) except dbException as e: log('Connect or init error:') if hasattr(e, 'message'): log(e.message) else: log(e) msgBox = QMessageBox() msgBox.setWindowTitle('Connection error') msgBox.setText('Connection failed: %s ' % (str(e))) iconPath = resourcePath('ico\\favicon.ico') msgBox.setWindowIcon(QIcon(iconPath)) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() self.statusMessage('', False) except Exception as e: log('Init exception not related to DB') log(str(e)) msgBox = QMessageBox() msgBox.setWindowTitle('Error') msgBox.setText( 'Init failed: %s \n\nSee more deteails in the log file.' % (str(e))) iconPath = resourcePath('ico\\favicon.ico') msgBox.setWindowIcon(QIcon(iconPath)) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() self.statusMessage('', False) else: # cancel or parsing error if ok and conf[ 'ok'] == False: #it's connection string dict in case of [Cancel] msgBox = QMessageBox() msgBox.setWindowTitle('Connection string') msgBox.setText( 'Could not start the connection. Please check the connection string: host, port, etc.' ) iconPath = resourcePath('ico\\favicon.ico') msgBox.setWindowIcon(QIcon(iconPath)) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() self.statusMessage('', False)
def console_connection(server, dbProperties=None, data_format_version2=False): global largeSql longdate = cfg('longdate', True) t0 = time.time() try: if largeSql: old_ms = pyhdb.protocol.constants.MAX_MESSAGE_SIZE old_ss = pyhdb.protocol.constants.MAX_SEGMENT_SIZE pyhdb.protocol.constants.MAX_MESSAGE_SIZE = 2**19 pyhdb.protocol.constants.MAX_SEGMENT_SIZE = pyhdb.protocol.constants.MAX_MESSAGE_SIZE - 32 if longdate: log('largesql console with longdates') connection = pyhdb.connect(host=server['host'], port=server['port'], user=server['user'], password=server['password'], data_format_version2=longdate) else: log('largesql console without longdates') connection = pyhdb.connect(host=server['host'], port=server['port'], user=server['user'], password=server['password']) connection.large_sql = True largeSql = False old_ms = pyhdb.protocol.constants.MAX_MESSAGE_SIZE old_ss = pyhdb.protocol.constants.MAX_SEGMENT_SIZE else: # normal connection if longdate: log('console connection with longdates') connection = pyhdb.connect(host=server['host'], port=server['port'], user=server['user'], password=server['password'], data_format_version2=longdate) else: log('console connection without longdates') connection = pyhdb.connect(host=server['host'], port=server['port'], user=server['user'], password=server['password']) connection.large_sql = False largeSql = False if cfg('internal', True): setApp = "set 'APPLICATION' = 'RybaFish %s'" % version execute_query_desc(connection, setApp, [], 0) setApp = "set 'APPLICATIONUSER' = '%s'" % getlogin() execute_query_desc(connection, setApp, [], 0) except Exception as e: # except pyhdb.exceptions.DatabaseError as e: log('[!]: connection failed: %s\n' % e) connection = None raise dbException(str(e)) t1 = time.time() log('sql (re)connect: %s' % (str(round(t1 - t0, 3)))) return connection
def clarifyGroups(): ''' gives pre-defined names to most useful groups ''' thread_kpis = [ 'active_thread_count', 'waiting_thread_count', 'total_thread_count', 'active_sql_executor_count', 'waiting_sql_executor_count', 'total_sql_executor_count' ] thread_kpis_ns = [ 'indexserverthreads', 'waitingthreads', 'totalthreads', 'activesqlexecutors', 'waitingsqlexecutors', 'totalsqlexecutors' ] def update_hardcoded(kpis, kpiList, grp): for kpi in kpis: if kpis[kpi]['name'] in kpiList: kpis[kpi]['group'] = grp def update(grpIdx, grpName): if grpIdx == 0: return if grpIdx == grpName: return for h in kpiStylesNN: for kpi in kpiStylesNN[h]: if kpiStylesNN[h][kpi]['group'] == grpIdx: kpiStylesNN[h][kpi]['group'] = grpName def updateDunit(grpIdx, dUnit): for h in kpiStylesNN: for kpi in kpiStylesNN[h]: if kpiStylesNN[h][kpi]['group'] == grpIdx: kpiStylesNN[h][kpi]['dUnit'] = dUnit for h in kpiStylesNN: if 'cpu' in kpiStylesNN[h]: update(kpiStylesNN[h]['cpu']['group'], 'cpu') if 'memory_used' in kpiStylesNN[h]: update(kpiStylesNN[h]['memory_used']['group'], 'mem') # those two for dpTrace as it is based on ns KPI names if 'cpuused' in kpiStylesNN[h]: update(kpiStylesNN[h]['cpuused']['group'], 'cpu') if 'memoryused' in kpiStylesNN[h]: update(kpiStylesNN[h]['memoryused']['group'], 'mem') if cfg('memoryGB'): updateDunit('mem', 'GB') # enforce threads scaling if thread_kpis[0] in kpiStylesNN[h]: update_hardcoded(kpiStylesNN[h], thread_kpis, 33) if 'active_thread_count' in kpiStylesNN[h]: update(kpiStylesNN[h]['active_thread_count']['group'], 'thr') # now the same for ns... if thread_kpis_ns[0] in kpiStylesNN[h]: update_hardcoded(kpiStylesNN[h], thread_kpis_ns, 33) if 'indexserverthreads' in kpiStylesNN[h]: update(kpiStylesNN[h]['indexserverthreads']['group'], 'thr')
def create_connection(server, dbProperties=None): t0 = time.time() try: # normal connection connection = pyhdb.connect(host=server['host'], port=server['port'], user=server['user'], password=server['password']) connection.large_sql = False if cfg('internal', True): setApp = "set 'APPLICATION' = 'RybaFish %s'" % version execute_query_desc(connection, setApp, [], 0) setApp = "set 'APPLICATIONUSER' = '%s'" % getlogin() execute_query_desc(connection, setApp, [], 0) except Exception as e: # except pyhdb.exceptions.DatabaseError as e: log('[!]: connection failed: %s\n' % e) connection = None raise dbException(str(e)) t1 = time.time() if dbProperties is not None: rows = execute_query( connection, 'select distinct key, value from m_host_information where key in (?, ?)', ['timezone_offset', 'sid']) for row in rows: if row[0] == 'timezone_offset': dbUTCDelta = row[1] hostNow = datetime.now().timestamp() hostUTCDelta = ( datetime.fromtimestamp(hostNow) - datetime.utcfromtimestamp(hostNow)).total_seconds() dbProperties['timeZoneDelta'] = int(dbUTCDelta) - int( hostUTCDelta) elif row[0] == 'sid': if cfg('sidmapping'): sm = cfg('sidmapping') dbProperties['sid'] = row[1].replace(sm[0], sm[1]) else: dbProperties['sid'] = row[1] if 'timeZoneDelta' not in dbProperties: dbProperties['timeZoneDelta'] = 0 if 'sid' not in dbProperties: dbProperties['sid'] = '???' t2 = time.time() log('(re)connect/properties: %s/%s' % (str(round(t1 - t0, 3)), str(round(t2 - t1, 3)))) return connection
def menuConfig(self): if self.connectionConf is None: connConf = cfg('server') else: connConf = self.connectionConf conf, ok = configDialog.Config.getConfig(connConf) if ok: self.connectionConf = conf if ok and conf['ok']: try: self.statusMessage('Connecting...', False) self.repaint() self.chartArea.dp = dpDB.dataProvider(conf) # db data provider self.chartArea.initDP() if hasattr(self.chartArea.dp, 'dbProperties'): self.chartArea.widget.timeZoneDelta = self.chartArea.dp.dbProperties['timeZoneDelta'] self.chartArea.reloadChart() self.tabs.setTabText(0, conf['user'] + '@' + self.chartArea.dp.dbProperties['sid']) #setup keep alives if cfg('keepalive'): try: keepalive = int(cfg('keepalive')) self.chartArea.dp.enableKeepAlive(self, keepalive) except: log('wrong keepalive setting: %s' % (cfg('keepalive'))) except dbException as e: log('connect or init error:') if hasattr(e, 'message'): log(e.message) else: log(e) msgBox = QMessageBox() msgBox.setWindowTitle('Connection error') msgBox.setText('Connection failed: %s ' % (str(e))) iconPath = resourcePath('ico\\favicon.ico') msgBox.setWindowIcon(QIcon(iconPath)) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() self.statusMessage('', False) # raise(e) else: # cancel or parsing error if ok and conf['ok'] == False: #it's connection string dict in case of [Cancel] msgBox = QMessageBox() msgBox.setWindowTitle('Connection string') msgBox.setText('Could not start the connection. Please check the connection string: host, port, etc.') iconPath = resourcePath('ico\\favicon.ico') msgBox.setWindowIcon(QIcon(iconPath)) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() self.statusMessage('', False)
def initUI(self): # bottom left frame (hosts) hostsArea = QFrame(self) self.hostTable = hostsTable.hostsTable() # bottom right frame (KPIs) self.kpisTable = kpiTable.kpiTable() kpisTable = self.kpisTable # top (main chart area) self.chartArea = chartArea.chartArea() # establish hard links: kpisTable.kpiScales = self.chartArea.widget.nscales self.chartArea.widget.hosts = self.hostTable.hosts kpisTable.hosts = self.chartArea.widget.hosts #why do we have hosts inside widget? because we have all data there... kpisTable.hostKPIs = self.chartArea.hostKPIs kpisTable.srvcKPIs = self.chartArea.srvcKPIs kpisTable.nkpis = self.chartArea.widget.nkpis # bottm part left+right kpiSplitter = QSplitter(Qt.Horizontal) kpiSplitter.addWidget(self.hostTable) kpiSplitter.addWidget(kpisTable) kpiSplitter.setSizes([200, 380]) self.tabs = QTabWidget() console = sqlConsole.sqlConsole() # main window splitter mainSplitter = QSplitter(Qt.Vertical) kpisWidget = QWidget() lo = QVBoxLayout(kpisWidget) lo.addWidget(kpiSplitter) mainSplitter.addWidget(self.chartArea) mainSplitter.addWidget(kpisWidget) mainSplitter.setSizes([300, 90]) mainSplitter.setAutoFillBackground(True) # central widget #self.setCentralWidget(mainSplitter) kpisWidget.autoFillBackground = True self.tabs.addTab(mainSplitter, 'Chart') if cfg('experimental-notnow'): self.tabs.addTab(console, 'Sql') self.setCentralWidget(self.tabs) # service stuff self.statusbar = self.statusBar() #menu iconPath = resourcePath('ico\\favicon.ico') exitAct = QAction('&Exit', self) exitAct.setShortcut('Alt+Q') exitAct.setStatusTip('Exit application') exitAct.triggered.connect(self.menuQuit) aboutAct = QAction(QIcon(iconPath), '&About', self) aboutAct.setStatusTip('About this app') aboutAct.triggered.connect(self.menuAbout) dummyAct = QAction('&Dummy', self) dummyAct.setShortcut('Alt+D') dummyAct.setStatusTip('Dummy Data provider') dummyAct.triggered.connect(self.menuDummy) configAct = QAction('&Connect', self) configAct.setShortcut('Alt+C') configAct.setStatusTip('Configure connection') configAct.triggered.connect(self.menuConfig) importAct = QAction('&Import', self) importAct.setShortcut('Ctrl+I') importAct.setStatusTip('Import nameserver.trc') importAct.triggered.connect(self.menuImport) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(aboutAct) fileMenu.addAction(configAct) if cfg('experimental'): fileMenu.addAction(importAct) fileMenu.addAction(dummyAct) fileMenu.addAction(exitAct) if cfg('experimental'): actionsMenu = menubar.addMenu('&Actions') fileMenu.addAction(aboutAct) fontAct = QAction('&Adjust Fonts', self) fontAct.setStatusTip('Adjust margins after font change (for example after move to secondary screen)') fontAct.triggered.connect(self.menuFont) reloadConfigAct = QAction('Reload &Config', self) reloadConfigAct.setStatusTip('Reload configuration file. Note: some values used during the connect or other one-time-actions') reloadConfigAct.triggered.connect(self.menuReloadConfig) actionsMenu.addAction(fontAct) actionsMenu.addAction(reloadConfigAct) reloadCustomKPIsAct = QAction('Reload Custom &KPIs', self) reloadCustomKPIsAct.setStatusTip('Reload definition of custom KPIs') reloadCustomKPIsAct.triggered.connect(self.menuReloadCustomKPIs) actionsMenu.addAction(reloadCustomKPIsAct) # finalization self.setGeometry(200, 200, 1400, 800) #self.setWindowTitle('SAP HANA Studio Light') # self.setWindowTitle('HANA Army Knife') self.setWindowTitle('Ryba Fish Charts') self.setWindowIcon(QIcon(iconPath)) self.show() ''' set up some interactions ''' # bind kpi checkbox signal kpisTable.checkboxToggle.connect(self.chartArea.checkboxToggle) # bind change scales signal kpisTable.adjustScale.connect(self.chartArea.adjustScale) kpisTable.setScale.connect(self.chartArea.setScale) # host table row change signal self.hostTable.hostChanged.connect(kpisTable.refill) # to fill hosts self.chartArea.hostsUpdated.connect(self.hostTable.hostsUpdated) # refresh self.chartArea.kpiToggled.connect(kpisTable.refill) # update scales signal self.chartArea.scalesUpdated.connect(kpisTable.updateScales) self.chartArea.scalesUpdated.emit() # it really not supposed to have any to update here #bind statusbox updating signals self.chartArea.statusMessage_.connect(self.statusMessage) self.chartArea.widget.statusMessage_.connect(self.statusMessage) self.chartArea.connected.connect(self.setTabName) log('init finish()') if self.chartArea.dp: self.chartArea.initDP()
def dumpLayout(self): if self.layoutDumped: return if self.layout is None: return self.layoutDumped = True kpis = {} for i in range(len(self.chartArea.widget.hosts)): host = self.chartArea.widget.hosts[i] hst = '%s:%s' % (host['host'], host['port']) if i < len(self.chartArea.widget.nkpis ) and self.chartArea.widget.nkpis[i]: kpis[hst] = self.chartArea.widget.nkpis[i] if kpis: self.layout['kpis'] = kpis else: if 'kpis' in self.layout.lo: del self.layout.lo['kpis'] self.layout['pos'] = [self.pos().x(), self.pos().y()] self.layout['size'] = [self.size().width(), self.size().height()] self.layout['mainSplitter'] = self.mainSplitter.sizes() self.layout['kpiSplitter'] = self.kpiSplitter.sizes() hostTableWidth = [] KPIsTableWidth = [] for i in range(self.hostTable.columnCount()): hostTableWidth.append(self.hostTable.columnWidth(i)) for i in range(self.kpisTable.columnCount()): KPIsTableWidth.append(self.kpisTable.columnWidth(i)) self.layout['hostTableWidth'] = hostTableWidth self.layout['KPIsTableWidth'] = KPIsTableWidth # print(self.pos().x(), self.pos().y()) tabs = [] self.layout['currentTab'] = self.tabs.currentIndex() if cfg('saveOpenTabs', True): for i in range(self.tabs.count() - 1, 0, -1): w = self.tabs.widget(i) if isinstance(w, sqlConsole.sqlConsole): w.delayBackup() if w.fileName is not None or w.backup is not None: pos = w.cons.textCursor().position() block = w.cons.edit.verticalScrollBar().value() #print('scroll position:', block) #block = w.cons.firstVisibleBlock().position() if w.backup: bkp = os.path.abspath(w.backup) else: bkp = None tabs.append([w.fileName, bkp, pos, block]) #tabs.append([w.fileName, bkp, pos]) w.close(None) # can not abort (and dont need to any more!) self.tabs.removeTab(i) tabs.reverse() if len(tabs) > 0: self.layout['tabs'] = tabs else: if 'tabs' in self.layout.lo: self.layout.lo.pop('tabs') if 'running' in self.layout.lo: self.layout.lo.pop('running') self.layout.dump()
def getData(self, h, fromto, kpiIn, data): ''' returns boolean False = some kpis were disabled due to sql errors ''' host = h.copy() if cfg('hostmapping'): hm = cfg('hostmapping') pm = cfg('portmapping') host['host'] = host['host'].replace(hm[1], hm[0]) host['port'] = host['port'].replace(pm[1], pm[0]) sql_pref = 'select time,' tfilter = '' hfilter = '' orderby = 'order by time asc' log('getData host: %s' % (str(host))) log('getData kpis: %s' % (str(kpiIn))) if host['port'] == '': type = 'host' else: type = 'service' ''' if self.lock: log('[w] getData lock set, exiting') return ''' if self.connection is None: raise dbException('No valid db connection') # self.lock = True params = [] kpiList = self.splitKpis(type, kpiIn) if host['port'] == '': t = 'h' hfilter = 'where host = ?' params.append(host['host']) else: t = 's' hfilter = 'where host = ? and port = ?' params.append(host['host']) params.append(host['port']) if fromto: # this to check fromto pair log('fromto: %s' % (str(fromto))) if fromto['from'] != '' and fromto['to'] == '': if fromto['from'][:1] == '-': hours = int(fromto['from'][1:]) params.append(hours) tfilter = " time > add_seconds(now(), -3600 * ?)" gtfilter = ' "STOP" > add_seconds(now(), -3600 * ?)' else: params.append(fromto['from']) tfilter = " time > ?" gtfilter = ' "STOP" > ?' elif fromto['from'] == '' and fromto['to'] != '': params.append(fromto['to']) tfilter = " time < ?" gtfilter = ' "START" < ?' else: params.append(fromto['from']) params.append(fromto['to']) tfilter = " time between ? and ?" gtfilter = ' "STOP" >= ? and "START" <= ?' else: log('[!] code should not ever reach here (tfilter)', 2) tfilter = " time > add_seconds(now(), -3600*12)" gtfilter = ' "STOP" >= add_seconds(now(), -3600*12)' # allOk = True # loop through kpi sources for kpiSrc in kpiList.keys(): nofilter = False kpisSql = [] kpis = kpiList[kpiSrc] if len(kpis) == 0: continue if host['port'] == '': if kpiSrc == '-': fromTable = 'from m_load_history_host' else: fromTable = 'from (%s)' % kpiDescriptions.customSql[kpiSrc] else: if kpiSrc == '-': fromTable = 'from m_load_history_service' else: fromTable = 'from (%s)' % kpiDescriptions.customSql[kpiSrc] for kpi in kpis: if kpiSrc == '-': kpisSql.append(kpi) else: kpisSql.append( kpiDescriptions.kpiStylesNN[type][kpi]['sqlname']) if 'nofilter' in kpiDescriptions.kpiStylesNN[type][ kpi] and kpiDescriptions.kpiStylesNN[type][kpi]['nofilter']: nofilter = True cols = ', '.join(kpisSql) hfilter_now = hfilter # cannot modify hfilter as it is reused for the other KPI sources... gtfilter_now = gtfilter # cannot modify hfilter as it is reused for the other KPI sources... params_now = params.copy() # same for params list if nofilter == False: #normal KPI sql = '%s %s %s %s and%s %s' % (sql_pref, cols, fromTable, hfilter_now, tfilter, orderby) else: #need to remove host:port filter both from the SQL and parameters... hfilter_now = 'where' sql = '%s %s %s %s%s %s' % (sql_pref, cols, fromTable, hfilter_now, tfilter, orderby) if host['port'] == '': params_now = params_now[1:] else: params_now = params_now[2:] ''' print('sql_pref', sql_pref) print('cols', cols) print('fromTable', fromTable) print('hfilter', hfilter) print('tfilter', tfilter) print('orderby', orderby) ''' #if gantt to be checked here gantt = False if len(kpis) == 1: #only one kpi can be in gantt data source kpi = kpis[0] if kpiDescriptions.getSubtype(type, kpi) == 'gantt': # tfilter_mod = tfilter.replace('time', '"START"') # removed 2021-03-23 #sql = 'select entity, "START", "STOP", details %s %s%s order by entity, "START" desc' % (fromTable, hfilter, tfilter_mod) #sql = 'select entity, "START", "STOP", details %s %s%s order by entity, seconds_between("START", "STOP") desc' % (fromTable, hfilter, tfilter_mod) if hfilter_now == 'where': # no host/port filter due to nofilter kpi setting pass else: # there is a filter so we have to add ' AND ' before the time filter... # tfilter_mod = ' and ' + tfilter_mod gtfilter_now = ' and ' + gtfilter_now sql = 'select entity, "START", "STOP", details %s %s%s order by entity desc, "START"' % ( fromTable, hfilter_now, gtfilter_now) gantt = True try: if not gantt: self.getHostKpis(type, kpis, data, sql, params_now, kpiSrc) else: self.getGanttData(type, kpis[0], data, sql, params_now, kpiSrc) except Exception as e: reply = False if customKpi(kpis[0]): if True or str(e)[:22] == '[db]: sql syntax error': log('yesNoDialog ---> disable %s?' % (kpiSrc)) reply = yesNoDialog( 'Error: custom SQL exception', 'SQL for custom KPIs %s terminated with the following error:\n\n%s\n\n Disable this KPI source (%s)?' % (', '.join(kpis), str(e), kpiSrc)) else: log('Custom KPI exception: ' + str(e), 2) # ? pass if reply == True: # need to mark failed kpis as disabled #badSrc = kpiDescriptions.kpiStylesNN[type][kpis[0]]['sql'] badSrc = kpiSrc for kpi in kpiDescriptions.kpiStylesNN[type]: if kpiDescriptions.kpiStylesNN[type][kpi][ 'sql'] == badSrc: kpiDescriptions.kpiStylesNN[type][kpi][ 'disabled'] = True log('disable custom kpi due to exception: %s%s' % (badSrc, kpi)) #also destroy the if already exist (from previous runs) if kpi in data: del (data[kpi]) # allOk = False else: self.connection = None log('[!] getHostKpis (%s) failed: %s' % (str(kpis), str(e))) raise e self.renewKeepAlive() # self.lock = False #print('before clnp', kpiIn) #remove disabled stuff for kpi in kpiIn.copy(): #print('kpi: ', kpi) if 'disabled' in kpiDescriptions.kpiStylesNN[type][kpi]: # this will affect the actual list of enabled kpis, which is good! kpiIn.remove(kpi) #print('after clnp', kpiIn) return
def initHosts(self, hosts, hostKPIs, srvcKPIs): # kpis_sql = 'select view_name, column_name, display_line_color, display_line_style from m_load_history_info order by display_hierarchy' #kpis_sql = 'select view_name, column_name from m_load_history_info order by display_hierarchy' kpis_sql = sql.kpis_info if not self.connection: log('no db connection...') return log('init hosts: %s' % str(hosts)) log('init hosts, hostKPIs: %s' % str(hostKPIs)) log('init hosts, srvcKPIs: %s' % str(srvcKPIs)) sql_string = sql.hosts_info t0 = time.time() rows = db.execute_query(self.connection, sql_string) for i in range(0, len(rows)): hosts.append({ 'host': rows[i][0], 'port': rows[i][1], 'from': rows[i][2], 'to': rows[i][3] }) rows = db.execute_query(self.connection, kpis_sql) for kpi in rows: if kpi[1].lower() == 'm_load_history_host': type = 'host' else: type = 'service' if kpi[1] == '': #hierarchy nodes if len(kpi[0]) == 1: continue # top level hierarchy node (Host/Service) else: # Normal hierarchy node kpiName = '.' + kpi[4] else: kpiName = kpi[2].lower() kpiDummy = { 'hierarchy': kpi[0], 'type': type, 'name': kpiName, 'group': kpi[3], 'label': kpi[4], 'description': kpi[5], 'sUnit': kpi[6], 'dUnit': kpi[7], 'color': kpi[8], 'style': kpiDescriptions.nsStyle(kpi[9]) } kpiStylesNN[type][kpiName] = kpiDescriptions.createStyle( kpiDummy) if kpi[1].lower() == 'm_load_history_host': hostKPIs.append(kpiName) else: srvcKPIs.append(kpiName) t1 = time.time() if cfg('experimental'): dpDBCustom.scanKPIsN(hostKPIs, srvcKPIs, kpiDescriptions.kpiStylesNN) t2 = time.time() kpiDescriptions.clarifyGroups() log('hostsInit time: %s/%s' % (str(round(t1 - t0, 3)), str(round(t2 - t1, 3))))