def buildTrivialStatsTable(self, deltaSeriesCollection, klass=TRIVIAL_STATS_TABLE, style=''): """ Builds a html table with statistics for a collection of transactions :param deltaSeriesCollection: A series of elapsed time or pmc values for a pair of probes :param klass: Css selector for this table (Default value = TRIVIAL_STATS_TABLE) :param style: Css inline style attributes for this table (Default value = '') """ tableWrapper = HTML().div() klass = '{} {}'.format(TABLE_SUMMARY, klass) table = tableWrapper.table(border='1', klass=klass, style=style) self.buildStatsTableHeader(table) tbody = table.tbody for i, deltaSeries in enumerate(deltaSeriesCollection, 1): row = tbody.tr row.td('{0:,}'.format(i), klass=TD_KEY) row.td(deltaSeries.beginProbeName, klass=TD_KEY) row.td(deltaSeries.endProbeName, klass=TD_KEY) row.td(DURATION_FORMAT.format(deltaSeries.getMin())) row.td(DURATION_FORMAT.format(deltaSeries.getMax())) row.td(DURATION_FORMAT.format(deltaSeries.getMedian())) row.td(DURATION_FORMAT.format(deltaSeries.getMean())) row.td( DURATION_FORMAT.format( deltaSeries.getPercentile(self.percentile1))) row.td( DURATION_FORMAT.format( deltaSeries.getPercentile(self.percentile2))) row.td(DURATION_FORMAT.format(deltaSeries.getStandardDeviation())) return tableWrapper
def buildTimelineTable(self, timelineStats, probes, resultOrder, threshold, uid, logAbsoluteValues=False, logTimeline=False, logData=False): """ Builds a html table for timelines with common category and route :param timelineStats: A collection of timelines to be reported :param probes: List of probes in route taken by, the transaction collection :param resultOrder: Sort order for a collection of timelines :param threshold: Threshold for number of transactions rendered in html reports. :param logAbsoluteValues: Flag to enable reporting of absolute tsc values :param logTimeline: Flag to enable reporting of timeline details :param logData: Flag to enable logging of data associated with transaction """ begin = time.time() tableContainer = HTML().div(klass=TABLE_REPORT_CONTAINER) table = tableContainer.table(border='1', klass=TABLE_REPORT) self.buildBreakupTableHeader(table, probes, logAbsoluteValues, logTimeline, logData) tbody = table.tbody timelineCollection = self.reorderTimelineRecords(timelineStats.timelineCollection, resultOrder) #write table rows for i, timeline in enumerate(timelineCollection, 1): row = tbody.tr row.td('{0:,}'.format(i), klass=TD_KEY) row.td('{:,}'.format(timeline.txnId), klass=TD_KEY) if logData: row.td('{}'.format(timeline.data), klass=TD_KEY) row.td('{:,}'.format(timeline.inception), klass=TD_KEY) j = None for j, timepoint in enumerate(timeline): if logTimeline: row.td(DURATION_FORMAT.format(timepoint.point)) if j < len(timeline) -1: # skip the duration for the last time point, since it's always 0 self.buildTimepointCell(row, uid, i, j, timepoint) elif j < len(timeline) -1: # skip the duration for the last time point, since it's always 0 self.buildTimepointCell(row, uid, i, j, timepoint) self.buildTimepointCell(row, uid, i, j, timeline.endpoint, klass=TD_END) if logAbsoluteValues: for j, probe in enumerate(probes): counter = timeline.txn[j] if probe != counter.probe: from xpedite.types import InvariantViloation raise InvariantViloation( 'transaction {} does not match route {}'.format(timeline.txn, probes) ) tsc = counter.tsc if counter else '---' row.td('{}'.format(tsc), klass=TD_DEBUG) if i >= threshold: break elapsed = time.time() - begin if elapsed >= 5: LOGGER.completed('\tprocessed %d out of %d transactions | %0.2f%% complete', i, threshold, float(100 * float(i)/float(threshold)) ) begin = time.time() return tableContainer
def buildFlotTitle(category, title, timelineStats, uid): """ Builds markup to render title for txn visualizations :param category: Category of transactions visualized by this flot :param title: Text title for this visualization :param timelineStats: Timeline stats with delta series to be plotted :param uid: Unique identifier to generate css selector id """ constituentNames = [ '{} -> {}'.format(deltaSeries.beginProbeName, deltaSeries.endProbeName) for deltaSeries in timelineStats.getTscDeltaSeriesCollection() ] title = '{} {} charts {}'.format( category, title, ' for constituent - ' if constituentNames else '') element = HTML().div(klass=TIME_POINT_STATS_TITLE) element.h3(title, style='display: inline') if constituentNames: elementId = '{}ConstituentSelector'.format(uid) constituentSelector = element.select(id=elementId, klass=SELECTOR) for i, constituentName in enumerate(constituentNames): if i == len(constituentNames) - 1: constituentSelector.option(constituentName, selected='selected') else: constituentSelector.option(constituentName) return element
def buildDifferentialStatsTable(self, deltaSeriesCollection, refDsc, klass, style): """ Builds a table with statistics for current profile session side by side with benchmarks :param deltaSeriesCollection: A series of elapsed time or pmc values for a pair of probes :param refDsc: Reference delta series collection for the current profile session :param klass: Css selector for this table (Default value = TRIVIAL_STATS_TABLE) :param style: Css inline style attributes for this table (Default value = '') """ from xpedite.report.markup import getDeltaMarkup, getDeltaType klass = '{} {}'.format(TABLE_SUMMARY, klass) table = HTML().table(border='1', klass=klass, style=style) self.buildStatsTableHeader(table) tbody = table.tbody fmt = DURATION_FORMAT + ' ({1}' + DURATION_FORMAT_2 + ')' for i, deltaSeries in enumerate(deltaSeriesCollection, 1): row = tbody.tr row.td('{0:,}'.format(i), klass=TD_KEY) row.td(deltaSeries.beginProbeName, klass=TD_KEY) row.td(deltaSeries.endProbeName, klass=TD_KEY) delta = deltaSeries.getMin() - refDsc[i - 1].getMin() row.td(fmt.format(deltaSeries.getMin(), getDeltaMarkup(delta), delta), klass=getDeltaType(delta)) delta = deltaSeries.getMax() - refDsc[i - 1].getMax() row.td(fmt.format(deltaSeries.getMax(), getDeltaMarkup(delta), delta), klass=getDeltaType(delta)) delta = deltaSeries.getMedian() - refDsc[i - 1].getMedian() row.td(fmt.format(deltaSeries.getMedian(), getDeltaMarkup(delta), delta), klass=getDeltaType(delta)) delta = deltaSeries.getMean() - refDsc[i - 1].getMean() row.td(fmt.format(deltaSeries.getMean(), getDeltaMarkup(delta), delta), klass=getDeltaType(delta)) percentile1 = deltaSeries.getPercentile(self.percentile1) delta = percentile1 - refDsc[i - 1].getPercentile(self.percentile1) row.td(fmt.format(percentile1, getDeltaMarkup(delta), delta), klass=getDeltaType(delta)) percentile2 = deltaSeries.getPercentile(self.percentile2) delta = percentile2 - refDsc[i - 1].getPercentile(self.percentile2) row.td(fmt.format(percentile2, getDeltaMarkup(delta), delta), klass=getDeltaType(delta)) delta = deltaSeries.getStandardDeviation() - refDsc[ i - 1].getStandardDeviation() row.td(fmt.format(deltaSeries.getStandardDeviation(), getDeltaMarkup(delta), delta), klass=getDeltaType(delta)) return table
def buildTimepointCell(self, tr, uid, xAxis, yAxis, timepoint, klass=None): """ Builds html table cell for a timepoint in a timeline :param tr: Handle to html table row object :param xAxis: Identifier used to generate unique css selector :param yAxis: Identifier used to generate unique css selector :param klass: css selector for this cell (Default value = None) :param timepoint: Timepoint to be reported """ if timepoint.pmcNames: title = HTML().table(border='0', klass=TABLE_PMU) heading = title.thead.tr heading.th('pmc') heading.th('value') body = title.tbody if timepoint.topdownValues: self.buildBottleneckRow(body, timepoint.topdownValues) self.buildPmcRow(body, timepoint.pmcNames, timepoint.deltaPmcs) cellId = 'tp-{}-{}-{}'.format(uid, xAxis, yAxis) if klass: tr.td().a(DURATION_FORMAT.format(timepoint.duration), title=str(title), id=cellId, klass=klass) else: tr.td().a(DURATION_FORMAT.format(timepoint.duration), title=str(title), id=cellId) else: if klass: tr.td(DURATION_FORMAT.format(timepoint.duration), klass=klass) else: tr.td(DURATION_FORMAT.format(timepoint.duration))
def buildEnvironmentTable(app): """ Builds a table with environment details :param app: an instance of xpedite app, to interact with target application """ table = HTML().table(border='1', klass=TABLE_ENV) heading = table.thead.tr heading.th('No') heading.th('Parameter') heading.th('Value') details = [('application', app.name), ('report time', strftime('%Y-%m-%d %H:%M:%S', gmtime())), ('host', app.ip), ('pid', app.pid), ('user', getpass.getuser()), ('os', app.getOsUname()), ('os boot param', app.getBootParam())] tbody = table.tbody for i, (k, val) in enumerate(details): row = tbody.tr row.td('{:,}'.format(i + 1), klass=TD_KEY) row.td('{} '.format(k), klass=TD_KEY) row.td('{} '.format(val)) return table
def buildEnvironmentReportFile(self, app, repo, resultOrder, classifier, txnFilter, benchmarkPaths): """ Creates a file to store the markup for environment details :param app: an instance of xpedite app, to interact with target application :param repo: repository of transactions for current profiling sessions and benchmarks :param resultOrder: Sort order of transactions in latency constituent reports :param classifier: Predicate to classify transactions into different categories :param txnFilter: Lambda to filter transactions prior to report generation :param benchmarkPaths: List of stored reports from previous runs, for benchmarking """ from xpedite.report.profileInfo import ProfileInfoReportBuilder from xpedite.report.tabs import (TAB_HEADER_FMT, TAB_BODY_FMT, TAB_BODY_PREFIX, TAB_BODY_SUFFIX, TAB_JS, TAB_CONTAINER_FMT, tabState, tabContentState) envTable = self.buildEnvironmentTable(app) cpuInfoTable = self.buildCpuInfoTable(app) hostReport = '' if envTable: title = HTML().h3('Test Environment parameters') hostReport += str(title) + str(envTable) if cpuInfoTable: title = HTML().h3('Test Environment cpu info') hostReport += str(title) + str(cpuInfoTable) profileReport = ProfileInfoReportBuilder().buildProfileInfoReportFile( app, repo, resultOrder, classifier, txnFilter, benchmarkPaths) tabHeader = TAB_HEADER_FMT.format('hostInfo', tabState(True), 'Host Info') tabHeader += TAB_HEADER_FMT.format('profileInfo', tabState(False), 'Profile Info') envBodyClass = 'envInfoBody ' tabBody = TAB_BODY_FMT.format('hostInfo', envBodyClass + tabContentState(True), hostReport) tabBody += TAB_BODY_FMT.format('profileInfo', envBodyClass + tabContentState(False), profileReport) tabBody = TAB_BODY_PREFIX + tabBody + TAB_BODY_SUFFIX report = (HTML_BEGIN + TAB_CONTAINER_FMT.format(tabHeader, tabBody) + TAB_JS + HTML_END) return report
def buildStatsTitle(category, benchmarkNames, transactionCount): """ Builds title markup for the stats table :param category: Category of transactions in this profile :param transactionCount: Number of transactions :param benchmarkNames: Names of given benchmarks """ title = '{} latency statistics ({} transactions) {}'.format( category, transactionCount, ' vs benchmark - ' if benchmarkNames else '') element = HTML().div(klass=TIME_POINT_STATS_TITLE) element.h3(title, style='display: inline') if benchmarkNames: bechmarkSelector = element.select( onchange='onSelectBenchmark(this)', klass=SELECTOR) for benchmarkName in benchmarkNames: bechmarkSelector.option(benchmarkName) return element
def buildProbeTable(probes): """Builds a html table for the given list of probes""" probeTable = HTML().table(border='1', klass=TABLE_ENV) heading = probeTable.thead.tr heading.th('Probe #') heading.th('Probe') heading.th('SysName') tbody = probeTable.tbody for i, probe in enumerate(probes): row = tbody.tr row.td('{:,}'.format(i + 1), klass=TD_KEY) row.td('{} '.format(probe.name), klass=TD_KEY) row.td('{} '.format(probe.sysName)) return probeTable
def buildReport(self, timelineStats, benchmarkTlsMap, probes, category, resultOrder, threshold, logAbsoluteValues=False, logTimeline=False, logData=False): """ Builds latency constituent report with statistics, visualizations and timeline table :param timelineStats: Time line and duration series statistics :type timelineStats: xpedite.analytics.timeline.TimelineStats :param benchmarkTlsMap: Time line and duration series statistics for benchmarks :param probes: List of probes in route, taken by the transaction collection :param category: Category of the transactions in this profile :param resultOrder: Sort order for a collection of timelines :param threshold: Threshold for number of transactions rendered in html reports :param logAbsoluteValues: Flag to enable reporting of absolute tsc values :param logTimeline: Flag to enable reporting of timeline details :param logData: Flag to enable logging of data associated with transaction """ uid = makeUniqueId() tableContainer = self.buildTimelineTable(timelineStats, probes, resultOrder, threshold, uid, logAbsoluteValues, logTimeline, logData) timelineCollection = self.reorderTimelineRecords( timelineStats.timelineCollection, resultOrder) pmuScript = self.buildPmuScript(timelineCollection, uid) flotBuilder = FlotBuilder() flotMarkup = flotBuilder.buildBenchmarkFlot(category, timelineStats, benchmarkTlsMap) statsReport = StatsBuilder().buildStatsTable(category, timelineStats, benchmarkTlsMap) reportTitle = HTML().h3('{} Transaction Time lines'.format(category)) return (HTML_BEGIN + statsReport + flotMarkup + str(reportTitle) + pmuScript + str(tableContainer) + HTML_END)
def buildPmcTable(pmcs): """Builds a html table for the given list of pmu events""" pmcTable = HTML().table(border='1', klass=TABLE_ENV) heading = pmcTable.thead.tr heading.th('PMC #') heading.th('Name') heading.th('Uarch Name') heading.th('User') heading.th('Kernel') tbody = pmcTable.tbody for i, pmc in enumerate(pmcs): row = tbody.tr row.td('{:,}'.format(i + 1), klass=TD_KEY) row.td('{} '.format(pmc.name), klass=TD_KEY) row.td('{} '.format(pmc.uarchName)) row.td('{} '.format(pmc.user)) row.td('{} '.format(pmc.kernel)) return pmcTable
def buildPmcTable(pmcNames, pmcValues, topdownValues): """ Builds html table rows for topdown metrics and pmc values for a transaction :param pmcNames: List of pmu event names :param pmcValues: List of pmu event values :param topdownValues: Values of computed topdown metrics """ table = HTML().table(border='0', klass=TABLE_PMU) heading = table.thead.tr heading.th('pmc') heading.th('value') body = table.tbody if topdownValues: ReportBuilder.buildTopdownRows(body, topdownValues) if pmcValues: ReportBuilder.buildPmcRows(body, pmcNames, pmcValues) return table
def buildCpuInfoTable(app): """ Builds a table with cpu info details :param app: an instance of xpedite app, to interact with target application """ info = app.getFullCpuInfo() if info: table = HTML().table(border='1', klass=TABLE_ENV) heading = table.thead.tr heading.th('No') heading.th('Info') heading.th('Value') tbody = table.tbody for i, (k, val) in enumerate(info.items()): row = tbody.tr row.td('{:,}'.format(i + 1), klass=TD_KEY) row.td('{} '.format(k), klass=TD_KEY) row.td('{} '.format(val)) return table return None
def buildReport(self, app, resultOrder, classifier, events, probes, txnFilter, benchmarkPaths): """Builds a html report from contents of a profile info module""" from xpedite.report.codeFormatter import CodeFormatter highlightWrapBegin = '<div class="wy-nav-content">' highlightWrapEnd = '</div>' description = """ <div>This report provides an overview of profile info parameters used in recording this profile.</div> <div>The report below comprises, the list of probes, performance counters, classifiers, and other attributes that control transaction generation.</div> """ report = HTML() report += description appInfoList = [ 'App Name = {}'.format(app.name), 'App Host = {}'.format(app.ip), 'App Info = {}'.format(app.appInfoPath), 'xpedite Run = {}'.format(app.runId), ] if resultOrder: appInfoList.append('Result Order = {}'.format(resultOrder)) report += formatList(appInfoList) report.h3('Probes') report += self.buildProbeTable(probes) if benchmarkPaths: report.h3('Benchmarks') report += formatList(benchmarkPaths) if events: report.h3('Performance Counters') report += self.buildPmcTable(events) if txnFilter: report.h3('Transaction Filter') report += CodeFormatter().format(txnFilter, 'highlight', highlightWrapBegin, highlightWrapEnd) if classifier: report.h3('Transaction Classifier') report += CodeFormatter().format(classifier, 'highlight', highlightWrapBegin, highlightWrapEnd) return report