Beispiel #1
0
    def _afterAppInit(self):
        """
            Fired after WinterApp initialisation
        """

        self.setWindowTitle(u'Нагрузочное тестирование БД')

        table=Table(self)
        # table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table=table

        forms=QWidget()
        forms.setLayout(QGridLayout())
        userform=QWidget()
        userform.setLayout(QFormLayout())
        userform.setLayout(QVBoxLayout())
        userform.layout().addWidget(QLabel(u'Список пользователей настраивается в файле main.cfg. <br>Пользователи циклично распределяются по потокам.'))

        dbform=QWidget()
        dbform.setLayout(QFormLayout())
        self.user=QLineEdit()
        self.user.setText(self.config.options.app.db_user)
        self.password=QLineEdit()
        self.password.setText(self.config.options.app.db_password)
        self.host=QLineEdit()
        self.host.setText(self.config.options.app.db_host)
        self.base=QLineEdit()
        self.base.setText(self.config.options.app.db_base)
        self.domain=QLineEdit()
        self.domain.setText(self.config.options.app.domain)
        dbform.layout().addRow(u'Пользователь',self.user)
        dbform.layout().addRow(u'Пароль',self.password)
        dbform.layout().addRow(u'Сервер',self.host)
        dbform.layout().addRow(u'Имя базы',self.base)
        dbform.layout().addRow(u'Имя домена',self.domain)


        threadform=QWidget()
        threadform.setLayout(QGridLayout())
        self.num=QSpinBox()
        self.num.setMaximum(999)
        self.num.setMinimum(1)
        self.num.setValue(self.config.options.app.threads_num)
        self.num.setToolTip(u'Значительно влияет на время выполнения и загрузку компьютера')

        threadform.layout().addWidget(QLabel(u'Количество потоков'),1,0)
        threadform.layout().addWidget(self.num,1,1)
        self.sepconnects=Switch(u'Создавать отдельные подключения на каждый запрос')
        threadform.layout().addWidget(self.sepconnects,3,0)
        self.skiperrors=Switch(u'Пропускать ошибки')
        threadform.layout().addWidget(self.skiperrors,4,0)

        self.fullc=Switch(u'Полный цикл')
        self.fullc.setChecked(True)
        self.fullc.stateChanged.connect(self.togglefull)
        threadform.layout().addWidget(self.fullc,5,0)
        self.minthreads=QSpinBox()
        self.minthreads.setValue(1)
        self.minthreads.setMaximum(999)
        self.minthreads.setMinimum(1)

        threadform.layout().addWidget(QLabel(u'Начально потоков'),6,0)
        threadform.layout().addWidget(self.minthreads,6,1)

        self.step=QSpinBox()
        self.step.setValue(1)
        self.step.setMaximum(999)
        self.step.setMinimum(1)
        threadform.layout().addWidget(QLabel(u'Шаг'),7,0)
        threadform.layout().addWidget(self.step,7,1)

        self.mc=QSpinBox()
        self.mc.setValue(0)
        self.mc.setMaximum(99999)
        self.mc.setMinimum(0)
        threadform.layout().addWidget(QLabel(u'Максимум запросов (0 = весь файл)'),2,0)
        threadform.layout().addWidget(self.mc,2,1)

        # options=QTabWidget()
        # options.addTab(dbform,u'Настройки БД')

        graphoptions=QWidget()
        graphoptions.setLayout(QFormLayout())
        # options.addTab(graphoptions,u'Настройки графика')
        self.notshowmavg=Switch(u'Не показывать среднюю по максимуму')
        graphoptions.layout().addRow('',self.notshowmavg)

        self.showlevel01=Switch(u'Всегда показывать линию уровня 0.1sec')
        graphoptions.layout().addRow('',self.showlevel01)
        self.showlevel1=Switch(u'Всегда показывать линию уровня 1sec')
        graphoptions.layout().addRow('',self.showlevel1)

        self.notshowerr=Switch(u'Не показывать ошибки')
        graphoptions.layout().addRow('',self.notshowerr)

        self.detail=Switch(u'Детальный отчет')
        threadform.layout().addWidget(self.detail,8,0)

        # graphoptions.layout().addRow('',self.detail)

        # forms.layout().addWidget(options,1,1)
        # forms.layout().addWidget(threadform,1,0)

        self.sideBar = WinterSideBar(self)
        threadform.layout().setAlignment(Qt.AlignTop)
        self.createSBAction('configure','MainOptions',threadform,toolbar=True)
        self.createSBAction('db','db settings',dbform,toolbar=True)
        self.createSBAction('graph','graph settings',graphoptions,toolbar=True)


        self.resize(1200,600)
        widget=QWidget()
        widget.setLayout(QVBoxLayout())
        widget.layout().addWidget(forms)
        widget.layout().addWidget(QLabel(u''))
        widget.layout().addWidget(table)


        buttons=QWidget()
        buttons.setLayout(QHBoxLayout())

        hb=QPushButton(u'Справка')
        hb.clicked.connect(self.help)

        self.progress=QProgressBar()
        buttons.layout().addWidget(hb)
        buttons.layout().addWidget(self.progress)

        spacerItem=QWidget()
        spacerItem.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum))
        buttons.layout().addWidget(spacerItem)
        sb=QPushButton(u'Поехали!')
        sb.clicked.connect(self.launch)
        buttons.layout().addWidget(sb)
        bb=QPushButton(u'Стоп')
        bb.clicked.connect(self.stop)
        buttons.layout().addWidget(bb)
        qb=QPushButton(u'Выход')
        qb.clicked.connect(self.quit)
        buttons.layout().addWidget(qb)

        self.help=QMainWindow()
        self.help.resize(800,600)
        self.help.setWindowTitle(u'Справка')
        hwidget=QWidget()
        hwidget.setLayout(QVBoxLayout())
        self.help.browser=QWebView()
        hwidget.layout().addWidget(self.help.browser)
        self.help.setCentralWidget(hwidget)


        self.viewer=QWebView()
        self.viewer.setFixedWidth(950)
        self.viewer.hide()

        wrapper=QWidget()
        wrapper.setLayout(QHBoxLayout())
        wrapper.layout().addWidget(widget)
        wrapper.layout().addWidget(self.viewer)

        widget.layout().addWidget(buttons)

        self.total=0
        self.callsnum=0
        self.errnum=0

        self.data=[]
        self.edata=[]
        self.mdata=[]
        self.tt=0
        self.tts=[]
        self.force_stop=False
        self.callsavg={}
        self.pdata={}
        self.cc={}

        self.args={}

        self.setMainWidget(wrapper)
        # self.sideBar = WinterSideBar(self)

        self.core.start()
Beispiel #2
0
class UI(WinterQtApp):
    """
        Main class
    """
    def __init__(self,app):
        """
            Create your own mymainwidget inherits QWidget and set it through self.setMainWidget. For future access use self.mainWidget property
        """
        WinterQtApp.__init__(self,app)



    def _afterMWInit(self):
        """
            Fired after MainWindow initialisation
        """

        pass

    def _afterAppInit(self):
        """
            Fired after WinterApp initialisation
        """

        self.setWindowTitle(u'Нагрузочное тестирование БД')

        table=Table(self)
        # table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table=table

        forms=QWidget()
        forms.setLayout(QGridLayout())
        userform=QWidget()
        userform.setLayout(QFormLayout())
        userform.setLayout(QVBoxLayout())
        userform.layout().addWidget(QLabel(u'Список пользователей настраивается в файле main.cfg. <br>Пользователи циклично распределяются по потокам.'))

        dbform=QWidget()
        dbform.setLayout(QFormLayout())
        self.user=QLineEdit()
        self.user.setText(self.config.options.app.db_user)
        self.password=QLineEdit()
        self.password.setText(self.config.options.app.db_password)
        self.host=QLineEdit()
        self.host.setText(self.config.options.app.db_host)
        self.base=QLineEdit()
        self.base.setText(self.config.options.app.db_base)
        self.domain=QLineEdit()
        self.domain.setText(self.config.options.app.domain)
        dbform.layout().addRow(u'Пользователь',self.user)
        dbform.layout().addRow(u'Пароль',self.password)
        dbform.layout().addRow(u'Сервер',self.host)
        dbform.layout().addRow(u'Имя базы',self.base)
        dbform.layout().addRow(u'Имя домена',self.domain)


        threadform=QWidget()
        threadform.setLayout(QGridLayout())
        self.num=QSpinBox()
        self.num.setMaximum(999)
        self.num.setMinimum(1)
        self.num.setValue(self.config.options.app.threads_num)
        self.num.setToolTip(u'Значительно влияет на время выполнения и загрузку компьютера')

        threadform.layout().addWidget(QLabel(u'Количество потоков'),1,0)
        threadform.layout().addWidget(self.num,1,1)
        self.sepconnects=Switch(u'Создавать отдельные подключения на каждый запрос')
        threadform.layout().addWidget(self.sepconnects,3,0)
        self.skiperrors=Switch(u'Пропускать ошибки')
        threadform.layout().addWidget(self.skiperrors,4,0)

        self.fullc=Switch(u'Полный цикл')
        self.fullc.setChecked(True)
        self.fullc.stateChanged.connect(self.togglefull)
        threadform.layout().addWidget(self.fullc,5,0)
        self.minthreads=QSpinBox()
        self.minthreads.setValue(1)
        self.minthreads.setMaximum(999)
        self.minthreads.setMinimum(1)

        threadform.layout().addWidget(QLabel(u'Начально потоков'),6,0)
        threadform.layout().addWidget(self.minthreads,6,1)

        self.step=QSpinBox()
        self.step.setValue(1)
        self.step.setMaximum(999)
        self.step.setMinimum(1)
        threadform.layout().addWidget(QLabel(u'Шаг'),7,0)
        threadform.layout().addWidget(self.step,7,1)

        self.mc=QSpinBox()
        self.mc.setValue(0)
        self.mc.setMaximum(99999)
        self.mc.setMinimum(0)
        threadform.layout().addWidget(QLabel(u'Максимум запросов (0 = весь файл)'),2,0)
        threadform.layout().addWidget(self.mc,2,1)

        # options=QTabWidget()
        # options.addTab(dbform,u'Настройки БД')

        graphoptions=QWidget()
        graphoptions.setLayout(QFormLayout())
        # options.addTab(graphoptions,u'Настройки графика')
        self.notshowmavg=Switch(u'Не показывать среднюю по максимуму')
        graphoptions.layout().addRow('',self.notshowmavg)

        self.showlevel01=Switch(u'Всегда показывать линию уровня 0.1sec')
        graphoptions.layout().addRow('',self.showlevel01)
        self.showlevel1=Switch(u'Всегда показывать линию уровня 1sec')
        graphoptions.layout().addRow('',self.showlevel1)

        self.notshowerr=Switch(u'Не показывать ошибки')
        graphoptions.layout().addRow('',self.notshowerr)

        self.detail=Switch(u'Детальный отчет')
        threadform.layout().addWidget(self.detail,8,0)

        # graphoptions.layout().addRow('',self.detail)

        # forms.layout().addWidget(options,1,1)
        # forms.layout().addWidget(threadform,1,0)

        self.sideBar = WinterSideBar(self)
        threadform.layout().setAlignment(Qt.AlignTop)
        self.createSBAction('configure','MainOptions',threadform,toolbar=True)
        self.createSBAction('db','db settings',dbform,toolbar=True)
        self.createSBAction('graph','graph settings',graphoptions,toolbar=True)


        self.resize(1200,600)
        widget=QWidget()
        widget.setLayout(QVBoxLayout())
        widget.layout().addWidget(forms)
        widget.layout().addWidget(QLabel(u''))
        widget.layout().addWidget(table)


        buttons=QWidget()
        buttons.setLayout(QHBoxLayout())

        hb=QPushButton(u'Справка')
        hb.clicked.connect(self.help)

        self.progress=QProgressBar()
        buttons.layout().addWidget(hb)
        buttons.layout().addWidget(self.progress)

        spacerItem=QWidget()
        spacerItem.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum))
        buttons.layout().addWidget(spacerItem)
        sb=QPushButton(u'Поехали!')
        sb.clicked.connect(self.launch)
        buttons.layout().addWidget(sb)
        bb=QPushButton(u'Стоп')
        bb.clicked.connect(self.stop)
        buttons.layout().addWidget(bb)
        qb=QPushButton(u'Выход')
        qb.clicked.connect(self.quit)
        buttons.layout().addWidget(qb)

        self.help=QMainWindow()
        self.help.resize(800,600)
        self.help.setWindowTitle(u'Справка')
        hwidget=QWidget()
        hwidget.setLayout(QVBoxLayout())
        self.help.browser=QWebView()
        hwidget.layout().addWidget(self.help.browser)
        self.help.setCentralWidget(hwidget)


        self.viewer=QWebView()
        self.viewer.setFixedWidth(950)
        self.viewer.hide()

        wrapper=QWidget()
        wrapper.setLayout(QHBoxLayout())
        wrapper.layout().addWidget(widget)
        wrapper.layout().addWidget(self.viewer)

        widget.layout().addWidget(buttons)

        self.total=0
        self.callsnum=0
        self.errnum=0

        self.data=[]
        self.edata=[]
        self.mdata=[]
        self.tt=0
        self.tts=[]
        self.force_stop=False
        self.callsavg={}
        self.pdata={}
        self.cc={}

        self.args={}

        self.setMainWidget(wrapper)
        # self.sideBar = WinterSideBar(self)

        self.core.start()

    def togglefull(self):
        if self.fullc.isChecked():
            self.minthreads.setEnabled(True)
            self.step.setEnabled(True)
            self.detail.setEnabled(True)
        else:
            self.minthreads.setEnabled(False)
            self.step.setEnabled(False)
            self.detail.setEnabled(False)


    def full(self):
        if int(self.num.value())-int(self.minthreads.value())>=1:
            self.total=int(self.num.value())
            self.num.setValue(self.minthreads.value())
            self.start()
        else:
            QMessageBox.information(self, 'Warning', u'Для полного цикла требуется минимум два потока')


    def help(self):
        self.help.browser.load(QUrl('help.html'))
        self.help.show()

    def quit(self):
        self.stop()
        sys.exit()

    def stop(self):
        self.force_stop=True
        for t in self.threads:
            t.stop=True
        self.progress.reset()
        self.api.info('Threads was stopped')
        QMessageBox.information(self, 'Threads was stopped', u'Ага, остановили')
        self.total=0
        self.callsnum=0
        self.errnum=0

        self.data=[]
        self.edata=[]
        self.mdata=[]
        self.tt=0
        self.tts=[]
        self.force_stop=False
        self.callsavg={}
        self.pdata={}
        self.cc={}

        self.args={}

        plt.close()
        plt.clf()

    def deadlock(self):
        # for t in self.threads:
            # t.stop=True
        # self.progress.reset()
        self.api.error('Deadlock!')
        # QMessageBox.information(self, 'Deadlock', u'Попробуйте еще раз.')

    def onPress(self,item):
        if hasattr(item,'args'):
            QMessageBox.information(self, 'Call arguments', item.args)

    def launch(self):
        if self.fullc.isChecked():
            self.full()
        else:
            self.start()

    def start(self):
        self.table.clear()
        self.table.setRowCount(0)
        self.table.setHorizontalHeaderLabels(self.table.headers)
        opts=[
        self.user.text(),
        self.password.text(),
        self.host.text(),
        self.base.text(),
        ]
        self.threads=[]
        for n,opt in enumerate(opts):
            opts[n]=str(opt)
        opts.insert(0,CWD+'qt.sh')
        

        f = file(CWD+'proc.list', 'r')
        count=0
        for line in f:
            count+=1
        if count>int(self.mc.value()) and int(self.mc.value()):
            count=int(self.mc.value())
        else:
            self.mc.setValue(count)
        f.close()

        self.progress.reset()
        self.progress.setMaximum(count*int(self.num.value()))

        for i in xrange(int(self.num.value())):
            topts=opts[:]
            for o in users[i%len(users)]:
                topts.append(users[i%len(users)][o])
            
            topts.append(str(i))
            topts.append(int(self.mc.value()))
            topts.append(self.domain.text())
            if int(self.num.value())!=1:
                w=Worker(self,topts,i,self)
            else:
                w=Worker(self,topts,i,self,False)

            self.threads.append(w)
            self.connect(w,SIGNAL('pylog'),self.table.pylog)
            self.connect(w,SIGNAL('errlog'),self.table.errlog)
            self.connect(w,SIGNAL('proc_end'),self.proc_end)
            self.connect(w,SIGNAL('deadlock'),self.deadlock)
            self.connect(w,SIGNAL('log'),self.api.debug)
            self.connect(w,SIGNAL('err'),self.api.error)

        self.calls={}
        
        self.ended=0


    def proc_end(self,num):
        self.ended+=1
        if not self.threads[num].killed:
            self.tt+=1
            self.api.info('Thread #%s ended [sid: %s] (Total finished: %s)' % (num,self.threads[num].sid,self.ended))
        else:
            self.api.info('Thread #%s KILLED (Total finished: %s)' % (num,self.ended))
        if self.ended==len(self.threads) and not self.force_stop:
            if self.total and self.total>int(self.num.value()):
                self.num.setValue(int(self.num.value())+int(self.step.value()))
                self.progress.setValue(self.progress.minimum())
                self.api.info('One cycle finished. Total calls: %s, Errors: %s' % (self.callsnum,self.errnum))

                self.average()
                self.start()
            elif self.total:
                self.progress.setValue(self.progress.maximum())
                self.api.info('Full cycle finished. Total calls: %s, Errors: %s' % (self.callsnum,self.errnum))
                QMessageBox.information(self, u'Полный цикл', u'Прогон закончен. Всего вызовов: %s, Ошибок: %s' % (self.callsnum,self.errnum))
                self.average()
                self.stop()
                
            else:
                self.progress.setValue(self.progress.maximum())
                # print u'Всего вызовов: %s, Ошибок: %s' % (self.callsnum,self.errnum)
                self.data=[]
                self.mdata=[]
                self.edata=[]
                self.api.info('Finished. Total calls: %s, Errors: %s' % (self.callsnum,self.errnum))
                QMessageBox.information(self, u'Завершено', u'Всего вызовов: %s, Ошибок: %s' % (self.callsnum,self.errnum))
                self.stop()
            self.tt=0

    def average(self):
        totalavg=timedelta(seconds=0)
        m=[]
        for proc in self.calls:
            item=self.calls[proc]
            avg=item['time'][0]
            for t in item['time'][1:]:
                avg+=t
            avg=avg/len(item['time'])
            totalavg+=avg
            m.append(sorted(item['time'])[-1])

        totalavg/=len(self.calls)
        td=totalavg
        td=(td.microseconds + (td.seconds + td.days * 86400) * 1000000)

        self.data.append(td)
        self.edata.append(self.errnum*100)
        tm=timedelta(seconds=0)
        for t in m:
            tm+=t
        tm/=len(m)
        tm=(tm.microseconds + (tm.seconds + tm.days * 86400) * 1000000)
        self.mdata.append(tm)
        self.graph()

    def graph(self):
        self.tts.append(self.tt)
        if sorted(self.mdata)[-1]>100000 or self.showlevel01.isChecked():
            line=[]
            for i in self.data:
                line.append(100000)
            l=plt.plot(self.tts,line)
            plt.setp(l, color='blue', linewidth=1.0,label='0.1 second')

        if sorted(self.mdata)[-1]>1000000 or self.showlevel1.isChecked():
            lline=[]
            for i in self.data:
                lline.append(1000000)
            ll=plt.plot(self.tts,lline)
            plt.setp(ll, color='red', linewidth=2.0,label='1 second')
        
        avg=plt.plot(self.tts,self.data)
        plt.setp(avg, color='g', linewidth=2.0,marker='o',label='Average time')
        if not self.notshowmavg.isChecked():
            m=plt.plot(self.tts,self.mdata)
            plt.setp(m, color='orange', linewidth=2.0,marker='o',label='Average max time')
        if not self.notshowerr.isChecked():
            err=plt.plot(self.tts,self.edata)
            plt.setp(err, color='red', linewidth=1.0,marker='.',label='Error count*100')

        plots=[avg]
        labels=['Average time']
        if sorted(self.mdata)[-1]>100000 or self.showlevel01.isChecked():
            plots.append(l)
            labels.append('0.1 second')
        if sorted(self.mdata)[-1]>1000000 or self.showlevel1.isChecked():
            plots.append(ll)
            labels.append('1 second')
        if not self.notshowmavg.isChecked():
            plots.append(m)
            labels.append('Average max time')
        if not self.notshowerr.isChecked():
            plots.append(err)
            labels.append('Error count*100')
        leg = plt.legend(plots,labels, fancybox=True)
        leg.get_frame().set_alpha(0.5)


        plt.ylabel('Microseconds (1 second = 1000000 ms)')
        plt.xlabel('Threads count')

        plt.title('Average time of procedure calls')
        # plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
        # plt.axis([1, len(self.data), 0, sorted(self.mdata)[-1]])
        plt.grid(True)
        # plt.minorticks_on()
        ax=avg[0].get_axes()
        # ax.minorticks_on()
        ticks=self.data[:]
        ticks.insert(0,0)
        ticks.extend(self.mdata)
        ticks=sorted(ticks)

        for n in xrange(len(ticks)-2):
            if not ticks[n+1]-ticks[n]>0.1*ticks[-1]:
                ticks[n]=0
                ticks=sorted(ticks)
        ticks=list(set(ticks))

        ax.set_yticks(ticks, minor=False)
        # self.tts.insert(0,0)
        # ax.set_xticks(self.tts, minor=False)
        try:
            ax.minorticks_on()
        except:
            pass
        # ylabels=[str(x) for x in self.data]
        # ylabels.insert(0,'0')
        # ax.set_yticklabels(ylabels, minor=True)

        plt.savefig('chart.png')
        plt.close()
        plt.clf()

        if self.detail.isChecked():
            try:
                os.mkdir(CWD+'charts')
            except OSError:
                pass
            for proc in self.callsavg:
                data=self.callsavg[proc]
                x=data.keys()
                y1=[]
                y2=[]
                for threads in data:
                    tm=data[threads][1]
                    tm=(tm.microseconds + (tm.seconds + tm.days * 86400) * 1000000)
                    y1.append(tm)
                    ta=data[threads][0]
                    ta=(ta.microseconds + (ta.seconds + ta.days * 86400) * 1000000)
                    y2.append(ta)
                    if proc not in self.pdata:
                        self.pdata[proc]={}
                    self.pdata[proc][threads]={'tavg':ta, 'tmax':tm}
                    self.cc[proc]=data[threads][2]
                m=plt.plot(x,y1)
                plt.setp(m, color='orange', linewidth=2.0,marker='o')
                a=plt.plot(x,y2)
                plt.setp(a, color='green', linewidth=2.0,marker='o')

                plots=[m,a]
                labels=['Average max time','Average time']

                if sorted(self.mdata)[-1]>100000 or self.showlevel01.isChecked():
                    line=[]
                    for i in self.data:
                        line.append(100000)
                    l=plt.plot(self.tts,line)
                    plt.setp(l, color='blue', linewidth=1.0,label='0.1 second')

                if sorted(self.mdata)[-1]>1000000 or self.showlevel1.isChecked():
                    lline=[]
                    for i in self.data:
                        lline.append(1000000)
                    ll=plt.plot(self.tts,lline)
                    plt.setp(ll, color='red', linewidth=2.0,label='1 second')

                if not self.notshowmavg.isChecked():
                    plots.append(m)
                    labels.append('Average max time')
                if not self.notshowerr.isChecked():
                    plots.append(err)
                    labels.append('Error count*100')

                leg = plt.legend(plots,labels, fancybox=True)
                leg.get_frame().set_alpha(0.5)


                plt.ylabel('Microseconds (1 second = 1000000 ms)')
                plt.xlabel('Threads count')
                plt.title('Average time of %s call' % proc)
                plt.grid(True, which='both')

                plt.savefig('charts/%s.png'%proc)
                plt.close()
                plt.clf()

        self.report()
        self.errnum=0
        self.calls={}
            

    def report(self):
        try:
            os.mkdir(CWD+'reports')
        except OSError:
            pass
        tpl=file(CWD+'templates/total_report.html','r').read()
        template=Template(tpl.decode('utf-8'))
        data=[]
        for i,dot in enumerate(self.tts):
            data.append({'threads':dot,'tavg':self.data[i],'tmax':self.mdata[i]})
        args={'host':self.host.text(),'base':self.base.text(),'data':data,'cpt':str(self.mc.value()),
        'tts':str(self.tts),'cycles':len(data),'procs':self.callsavg,'detail':self.detail.isChecked(),
        'cc':self.callsnum,'errc':self.errnum}
        report=template.render(**args).encode('utf-8')
        file(CWD+'index.html','w').write(report)

        self.viewer.show()
        self.viewer.load(QUrl(CWD+'index.html'))
        self.viewer.reload()

        
        if self.detail.isChecked():
            tpl=file(CWD+'templates/proc_report.html','r').read()
            template=Template(tpl.decode('utf-8'))
            for proc in self.callsavg:
                args={'proc':proc,'host':self.host.text(),'base':self.base.text(),'data':self.pdata[proc],
                'cycles':self.cc[proc],'tts':len(self.callsavg[proc]),'args':self.args[proc]}
                report=template.render(**args).encode('utf-8')
                file(CWD+'reports/%s.html'%proc,'w').write(report)



    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            QMainWindow.close(self)

    def getLog(self):
        return self.log