Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a report plugin.Anyone interested? #723

Closed
yivanus opened this issue Jan 22, 2018 · 4 comments
Closed

a report plugin.Anyone interested? #723

yivanus opened this issue Jan 22, 2018 · 4 comments

Comments

@yivanus
Copy link

yivanus commented Jan 22, 2018

`"""
pdf report for Locust Test,
提供给webui调用,flask 里面的 路径 /pdfreport 会调用生成pdf,
此文件的 getpdfreport 函数生成一个pdf文件
传回pdf的文件名
"""

def getpdfreport(allreport, curpath):
"""
:param allreport: json数据
:param curpath: 当前路径,用于 logo 获取和字体获取
:return:生成的pdf文件路径
"""
import pathlib
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import time
from reportlab.platypus import Paragraph
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate
from reportlab.platypus import PageBreak
pdfmetrics.registerFont(TTFont('Songti', pathlib.PurePath(curpath) / 'static' / 'Songti.ttc', subfontIndex=1))
page_height = A4[1]
page_width = A4[0]
# 测试的开始与结束时间
st = allreport['reports'][0]['time']
et = allreport['reports'][-1]['time']
filename = pathlib.PurePath(curpath) / 'pdfreports' / ('locustreport_' + str(time.time()) + '.pdf')
# 报告数据,一个数组,存放的是 被打印对象
reports = [PageBreak()]

# 获取文字样式
def getss(s):
    sss = getSampleStyleSheet()
    s = sss.get(s)
    s.fontName = 'Songti'
    return s

# 平均时间图形
def avg(ar):
    return everystats('avg_response_time', ar)

# rpx图形
def rps(ar):
    return everystats('current_rps', ar)

# 公共图形生成(详细数据)
def everystats(tag, ar):
    stats = ar['reports']
    d = []
    for r in stats:
        tmp = []
        for s in r['stats']:
            if s['method']:
                tmp.append(s[tag])
        if len(tmp):
            d.append(tmp)
    from reportlab.graphics.shapes import Drawing
    drawing = Drawing(400, 200)
    drawing.vAlign = 'BOTTOM'
    drawing.hAlign = 'CENTER'
    from reportlab.graphics.charts.linecharts import HorizontalLineChart
    lc = HorizontalLineChart()
    lc.valueAxis.valueMin = 0
    lc.valueAxis.visibleGrid = True
    cc = []
    for i in range(len(d[-1])):
        cc.append([])
    for x in d:
        for s in range(len(x)):
            cc[s].append(x[s])
    maxx = []
    for c in cc:
        maxx.append(max(c))
    lc.valueAxis.valueMax = max(maxx)
    lc.data.clear()
    for c in cc:
        lc.data.append(tuple(c))
    lc.x = 0
    lc.y = 0
    lc.height = 180
    lc.width = 400
    cnames = [time.strftime('%H:%M:%S', time.localtime(st))]
    for i in range(len(lc.data[0]) - 2):
        cnames.append("")
    cnames.append(time.strftime('%H:%M:%S', time.localtime(et)))
    lc.categoryAxis.categoryNames = tuple(cnames)
    lc.categoryAxis.visibleTicks = False
    drawing.add(lc)
    return drawing

# 请求数据表格
def reqreporttable(rs, ar):
    ts = []
    req = ar['request']
    ds = req.splitlines()
    ts.append(ds[0].split(',')[1:])
    for d in ds[1:-1]:
        d = d.split(',')
        urlrow = ['"Url"']
        urlrow.append(d[1])
        ts.append(urlrow)
        datarow = [""]
        datarow.extend(d[2:])
        ts.append(datarow)
    ts.append(ds[-1].split(',')[1:])
    ts[0][2] = '"fails"'
    ts[0][3] = '"median"'
    ts[0][4] = '"average"'
    ts[0][5] = '"min"'
    ts[0][6] = '"max"'
    ts[0][7] = '"content size"'
    ts[0][8] = '"request/s"'

    from reportlab.platypus import Table
    from reportlab.platypus import tables
    from reportlab.platypus import TableStyle
    from reportlab.lib import colors
    tabstyle = TableStyle(
        [('FONT', (0, 0), (-1, -1), 'Songti'),
         ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black),
         ('BOX', (0, 0), (-1, -1), 2, colors.black),
         ('LINEBELOW', (0, 0), (-1, 0), 2, colors.black),
         ('LINEAFTER', (0, 0), (0, -1), 2, colors.black),
         ('ALIGN', (1, 1), (-1, -1), 'LEFT'),
         ('LINEABOVE', (0, -1), (-1, -1), 2, colors.black)]
    )

    x = 1
    for d in ds[1:-1]:
        tabstyle.add('SPAN', (1, x), (-1, x))
        x += 2
    tabreport = Table(ts, style=tabstyle)
    tabtile = Paragraph('统计数据', getss('h2'))
    rs.append(tabtile)
    from reportlab.platypus import Spacer
    rs.append(Spacer(page_width, 10))
    rs.append(tabreport)

# 响应数据表格
def resreporttable(rs, ar):
    ts = []
    res = ar['response']
    ds = res.splitlines()
    ts.append(ds[0].split(','))
    for d in ds[1:-1]:
        d = d.split(',')
        urlrow = ['"Url"']
        urlrow.append(d[0])
        ts.append(urlrow)
        datarow = [""]
        datarow.extend(d[1:])
        ts.append(datarow)
    ts.append(ds[-1].split(','))

    from reportlab.platypus import Table
    from reportlab.platypus import TableStyle
    from reportlab.lib import colors
    tabstyle = TableStyle(
        [('FONT', (0, 0), (-1, -1), 'Songti'),
         ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black),
         ('BOX', (0, 0), (-1, -1), 2, colors.black),
         ('LINEBELOW', (0, 0), (-1, 0), 2, colors.black),
         ('LINEAFTER', (0, 0), (0, -1), 2, colors.black),
         ('ALIGN', (1, 1), (-1, -1), 'LEFT'),
         ('LINEABOVE', (0, -1), (-1, -1), 2, colors.black)]
    )
    tabstyle.add('FONT', (0, 0), (-1, -1), 'Songti')
    tabstyle.add('ALIGN', (1, 1), (-1, -1), 'LEFT')
    x = 1
    for d in ds[1:-1]:
        tabstyle.add('SPAN', (1, x), (-1, x))
        x += 2
    tabreport = Table(ts, style=tabstyle)
    tabtile = Paragraph('详细数据', getss('h2'))
    rs.append(tabtile)
    from reportlab.platypus import Spacer
    rs.append(Spacer(page_width, 10))
    rs.append(tabreport)

# 运行概况数据
def locustrunmsg(rs, ar):

    from reportlab.platypus import Spacer
    rs.append(Spacer(page_width, 20))
    runmsg = Paragraph("测试概况", getss('h2'))

    s = getss('h3')
    rs.append(runmsg)
    from reportlab.platypus.flowables import HRFlowable
    from reportlab.lib import colors
    rs.append(HRFlowable(width="100%", color=colors.black))
    rs.append(Spacer(page_width, 10))
    rs.append(Paragraph("开始时间:" + time.strftime('%m/%d %H:%M:%S', time.localtime(st)), s))
    rs.append(Paragraph("结束时间:" + time.strftime('%m/%d %H:%M:%S', time.localtime(et)), s))
    rs.append(Paragraph("用户数:" + str(ar['reports'][-1]['user_count']), s))
    rs.append(Paragraph("任务数:" + str(len(allreport['reports'][-1]['stats']) - 1), s))
    req = ar['request']
    ds = req.splitlines()
    lt = ds[-1].split(',')
    pastc = int(lt[3]) / int(lt[2]) * 100
    rs.append(Paragraph("失败率:" + str(pastc) + "%", s))
    rs.append(Spacer(page_width, 10))
    rs.append(HRFlowable(width="100%", color=colors.black))
    rs.append(Spacer(page_width, 30))

# 标题与logo图
def firstlogo(cs, doc):
    cs.saveState()
    from reportlab.lib import colors
    cs.setStrokeColor(colors.black)
    cs.setLineWidth(1)
    from reportlab.lib.units import inch
    cs.drawString(inch, A4[1] - inch + 5, time.strftime("%Y/%m/%d", time.localtime(time.time())))
    from reportlab.lib.units import pica
    cs.drawString(page_width - 10 * pica, page_height - inch + 5, "mobTest")
    cs.line(inch, inch, page_width - inch, inch)
    cs.line(inch, page_height - inch, page_width - inch, page_height - inch)
    cs.drawImage(pathlib.PurePath(curpath) / 'static' / 'img' / 'report-logo.png', 2.5 * inch, 7 * inch, 247, 105,
                 mask='auto')
    cs.drawImage(pathlib.PurePath(curpath) / 'static' / 'img' / 'logo.png', 3 * inch, 4 * inch, 400/3,32,mask='auto')
    cs.saveState()
    cs.setFont('Songti', 28)
    cs.drawCentredString(page_width / 2, 6 * inch, "LOCUST 测试报告")
    cs.restoreState()
    cs.drawString(inch, 0.75 * inch, "Print by locust")
    cs.drawString(4 * inch, 0.75 * inch, "Page %d" % doc.page)
    cs.restoreState()

# 脚注,与页码
def footer(cs, doc):
    cs.saveState()
    from reportlab.lib import colors
    cs.setStrokeColor(colors.black)
    cs.setLineWidth(1)
    from reportlab.lib.units import inch
    cs.line(inch, inch, page_width - inch, inch)
    cs.line(inch, page_height - inch, page_width - inch, page_height - inch)
    cs.drawString(inch, page_height - inch + 5, time.strftime("%Y/%m/%d", time.localtime(time.time())))
    cs.drawString(4 * inch, 0.75 * inch, "Page %d" % doc.page)
    from reportlab.lib.units import pica
    cs.drawString(page_width - 10 * pica, page_height - inch + 5, "mobTest")
    cs.restoreState()

def reportcharts(rs, ar):
    """
    全部图形生成
    :param rs:报告数组
    :param ar:json数据
    :return:
    """
    from reportlab.lib.enums import TA_CENTER
    rs.append(PageBreak())
    # 获取几个关键数据,对应webui上的图形数据
    userdata = []
    rpsdata = []
    cp95 = []
    cp50 = []
    fail_ratio = []
    for report in ar['reports']:
        userdata.append(report['user_count'])
        rpsdata.append(report['total_rps'])
        cp95.append(
            report['current_response_time_percentile_95'] if report['current_response_time_percentile_95'] else 0)
        cp50.append(
            report['current_response_time_percentile_50'] if report['current_response_time_percentile_50'] else 0)
        fail_ratio.append(report['fail_ratio'])

    # 公共图形生成方法,传入单组数据
    def getdata(data):
        "A line plot with non-equidistant points in x-axis."
        from reportlab.graphics.shapes import Drawing
        drawing = Drawing(400, 200)
        drawing.vAlign = 'BOTTOM'
        drawing.hAlign = 'CENTER'
        from reportlab.graphics.charts.linecharts import HorizontalLineChart
        lc = HorizontalLineChart()
        lc.valueAxis.valueMin = 0
        cnames = [time.strftime('%H:%M:%S', time.localtime(st))]
        for i in range(len(data[0]) - 2):
            cnames.append("")
        cnames.append(time.strftime('%H:%M:%S', time.localtime(et)))
        lc.categoryAxis.categoryNames = tuple(cnames)
        lc.categoryAxis.visibleTicks = False
        lc.valueAxis.visibleGrid = True
        lc.data = data
        lc.x = 0
        lc.y = 0
        lc.height = 180
        lc.width = 400
        drawing.add(lc)
        return drawing

    # 生成用户图形
    def getchartsuser():
        return getdata([tuple(userdata)])

    # 生成rps图形
    def getchartrps():
        return getdata([tuple(rpsdata)])

    # 生成失败率图形
    def getcharfail():
        return getdata([tuple(fail_ratio)])

    # 生成响应时间图形
    def getcharresponsetime():
        return getdata([tuple(cp95), tuple(cp50)])

    # 下面将对应的图形添加到报告中,
    # 总体用户数,
    # 总体响应数,
    # 总体错误率
    # 总体响应时间分布 95%红线,50%绿线,
    # 独立平均响应时间
    # 独立响应数
    chartitle = getss('h4')
    chartitle.alignment = TA_CENTER
    rs.append(Paragraph('总体用户数', chartitle))
    rs.append(getchartsuser())
    rs.append(Paragraph('总体响应数', chartitle))
    rs.append(getchartrps())
    rs.append(Paragraph('总体错误率', chartitle))
    rs.append(getcharfail())
    rs.append(Paragraph('总体响应时间分布 95%红线,50%绿线 ms', chartitle))
    rs.append(getcharresponsetime())
    rs.append(Paragraph('独立平均响应时间 ms', chartitle))
    rs.append(avg(ar))
    rs.append(Paragraph('独立响应数', chartitle))
    rs.append(rps(ar))

# pdf文件生成步骤
# 概况信息
locustrunmsg(reports, allreport)
# 表格数据
reqreporttable(reports, allreport)
resreporttable(reports, allreport)
# 图形数据
reportcharts(reports, allreport)
# 开始数据生成
SimpleDocTemplate(str(filename), showBoundary=False).build(reports, onLaterPages=footer, onFirstPage=firstlogo)
# 返回生成的pdf文件名给web服务器
return str(filename)

if name == 'main':
import json

data = b'{"reports": [{"stats": [{"method": null, "name": "Total", "num_requests": 0, "num_failures": 0, "avg_response_time": 0, "min": 0, "max": 0, "current_rps": 0.0, "median": 0, "avg_content_length": 0}], "errors": [], "total_rps": 0.0, "fail_ratio": 0.0, "current_response_time_percentile_95": null, "current_response_time_percentile_50": null, "state": "ready", "user_count": 0, "time": 1513062679.330583}, {"stats": [{"method": null, "name": "Total", "num_requests": 0, "num_failures": 0, "avg_response_time": 0, "min": 0, "max": 0, "current_rps": 0.0, "median": 0, "avg_content_length": 0}], "errors": [], "total_rps": 0.0, "fail_ratio": 0.0, "current_response_time_percentile_95": null, "current_response_time_percentile_50": null, "state": "ready", "user_count": 0, "time": 1513062681.439312}, {"stats": [{"method": null, "name": "Total", "num_requests": 0, "num_failures": 0, "avg_response_time": 0, "min": 0, "max": 0, "current_rps": 0.0, "median": 0, "avg_content_length": 0}], "errors": [], "total_rps": 0.0, "fail_ratio": 0.0, "current_response_time_percentile_95": null, "current_response_time_percentile_50": null, "state": "ready", "user_count": 0, "time": 1513062683.4707808}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 109, "num_failures": 0, "avg_response_time": 5.7889908256880735, "min": 3, "max": 15, "current_rps": 0.0, "median": 5, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 109, "num_failures": 0, "avg_response_time": 5.7889908256880735, "min": 3, "max": 15, "current_rps": 0.0, "median": 5, "avg_content_length": 2.0}], "errors": [], "total_rps": 0.0, "fail_ratio": 0.0, "current_response_time_percentile_95": null, "current_response_time_percentile_50": null, "state": "hatching", "user_count": 5, "time": 1513062685.501021}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 718, "num_failures": 0, "avg_response_time": 15.335654596100278, "min": 3, "max": 54, "current_rps": 26.0, "median": 15, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 718, "num_failures": 0, "avg_response_time": 15.335654596100278, "min": 3, "max": 54, "current_rps": 26.0, "median": 15, "avg_content_length": 2.0}], "errors": [], "total_rps": 26.0, "fail_ratio": 0.0, "current_response_time_percentile_95": 26, "current_response_time_percentile_50": 16, "state": "hatching", "user_count": 15, "time": 1513062687.558843}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 1394, "num_failures": 0, "avg_response_time": 26.74461979913917, "min": 3, "max": 172, "current_rps": 170.66666666666666, "median": 25, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 1394, "num_failures": 0, "avg_response_time": 26.74461979913917, "min": 3, "max": 172, "current_rps": 170.66666666666666, "median": 25, "avg_content_length": 2.0}], "errors": [], "total_rps": 170.66666666666666, "fail_ratio": 0.0, "current_response_time_percentile_95": 48, "current_response_time_percentile_50": 25, "state": "hatching", "user_count": 25, "time": 1513062689.631905}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 2099, "num_failures": 0, "avg_response_time": 39.54263935207241, "min": 3, "max": 217, "current_rps": 241.4, "median": 37, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 2099, "num_failures": 0, "avg_response_time": 39.54263935207241, "min": 3, "max": 217, "current_rps": 241.4, "median": 37, "avg_content_length": 2.0}], "errors": [], "total_rps": 241.4, "fail_ratio": 0.0, "current_response_time_percentile_95": 79, "current_response_time_percentile_50": 37, "state": "hatching", "user_count": 35, "time": 1513062691.7160268}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 2653, "num_failures": 0, "avg_response_time": 55.61062947606483, "min": 3, "max": 217, "current_rps": 267.57142857142856, "median": 45, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 2653, "num_failures": 0, "avg_response_time": 55.61062947606483, "min": 3, "max": 217, "current_rps": 267.57142857142856, "median": 45, "avg_content_length": 2.0}], "errors": [], "total_rps": 267.57142857142856, "fail_ratio": 0.0, "current_response_time_percentile_95": 140, "current_response_time_percentile_50": 45, "state": "hatching", "user_count": 44, "time": 1513062693.776733}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 3407, "num_failures": 0, "avg_response_time": 67.16025829175227, "min": 3, "max": 217, "current_rps": 271.8888888888889, "median": 59, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 3407, "num_failures": 0, "avg_response_time": 67.16025829175227, "min": 3, "max": 217, "current_rps": 271.8888888888889, "median": 59, "avg_content_length": 2.0}], "errors": [], "total_rps": 271.8888888888889, "fail_ratio": 0.0, "current_response_time_percentile_95": 140, "current_response_time_percentile_50": 64, "state": "running", "user_count": 50, "time": 1513062695.85082}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 3936, "num_failures": 0, "avg_response_time": 79.76981707317073, "min": 3, "max": 371, "current_rps": 323.3, "median": 72, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 3936, "num_failures": 0, "avg_response_time": 79.76981707317073, "min": 3, "max": 371, "current_rps": 323.3, "median": 72, "avg_content_length": 2.0}], "errors": [], "total_rps": 323.3, "fail_ratio": 0.0, "current_response_time_percentile_95": 190, "current_response_time_percentile_50": 100, "state": "running", "user_count": 50, "time": 1513062698.05043}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 4265, "num_failures": 0, "avg_response_time": 95.86916764361078, "min": 3, "max": 573, "current_rps": 307.7, "median": 86, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 4265, "num_failures": 0, "avg_response_time": 95.86916764361078, "min": 3, "max": 573, "current_rps": 307.7, "median": 86, "avg_content_length": 2.0}], "errors": [], "total_rps": 307.7, "fail_ratio": 0.0, "current_response_time_percentile_95": 340, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062700.236043}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 4940, "num_failures": 0, "avg_response_time": 103.44716599190284, "min": 3, "max": 573, "current_rps": 273.7, "median": 97, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 4940, "num_failures": 0, "avg_response_time": 103.44716599190284, "min": 3, "max": 573, "current_rps": 273.7, "median": 97, "avg_content_length": 2.0}], "errors": [], "total_rps": 273.7, "fail_ratio": 0.0, "current_response_time_percentile_95": 350, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062702.538628}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 5499, "num_failures": 0, "avg_response_time": 108.16493907983269, "min": 3, "max": 573, "current_rps": 257.5, "median": 100, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 5499, "num_failures": 0, "avg_response_time": 108.16493907983269, "min": 3, "max": 573, "current_rps": 257.5, "median": 100, "avg_content_length": 2.0}], "errors": [], "total_rps": 257.5, "fail_ratio": 0.0, "current_response_time_percentile_95": 350, "current_response_time_percentile_50": 140, "state": "running", "user_count": 50, "time": 1513062704.6258938}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 6115, "num_failures": 0, "avg_response_time": 111.07048242027801, "min": 3, "max": 573, "current_rps": 258.9, "median": 100, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 6115, "num_failures": 0, "avg_response_time": 111.07048242027801, "min": 3, "max": 573, "current_rps": 258.9, "median": 100, "avg_content_length": 2.0}], "errors": [], "total_rps": 258.9, "fail_ratio": 0.0, "current_response_time_percentile_95": 350, "current_response_time_percentile_50": 150, "state": "running", "user_count": 50, "time": 1513062706.6940129}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 6790, "num_failures": 0, "avg_response_time": 112.79852724594993, "min": 3, "max": 573, "current_rps": 242.7, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 6790, "num_failures": 0, "avg_response_time": 112.79852724594993, "min": 3, "max": 573, "current_rps": 242.7, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 242.7, "fail_ratio": 0.0, "current_response_time_percentile_95": 260, "current_response_time_percentile_50": 140, "state": "running", "user_count": 50, "time": 1513062708.8220532}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 7297, "num_failures": 0, "avg_response_time": 116.54364807455119, "min": 3, "max": 573, "current_rps": 255.6, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 7297, "num_failures": 0, "avg_response_time": 116.54364807455119, "min": 3, "max": 573, "current_rps": 255.6, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 255.6, "fail_ratio": 0.0, "current_response_time_percentile_95": 220, "current_response_time_percentile_50": 140, "state": "running", "user_count": 50, "time": 1513062710.8932521}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 8059, "num_failures": 0, "avg_response_time": 115.9513587293709, "min": 3, "max": 573, "current_rps": 284.3, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 8059, "num_failures": 0, "avg_response_time": 115.9513587293709, "min": 3, "max": 573, "current_rps": 284.3, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 284.3, "fail_ratio": 0.0, "current_response_time_percentile_95": 220, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062712.9432251}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 8746, "num_failures": 0, "avg_response_time": 116.42682369083009, "min": 3, "max": 573, "current_rps": 301.7, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 8746, "num_failures": 0, "avg_response_time": 116.42682369083009, "min": 3, "max": 573, "current_rps": 301.7, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 301.7, "fail_ratio": 0.0, "current_response_time_percentile_95": 210, "current_response_time_percentile_50": 110, "state": "running", "user_count": 50, "time": 1513062715.021971}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 9473, "num_failures": 0, "avg_response_time": 116.38921144304867, "min": 3, "max": 573, "current_rps": 315.0, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 9473, "num_failures": 0, "avg_response_time": 116.38921144304867, "min": 3, "max": 573, "current_rps": 315.0, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 315.0, "fail_ratio": 0.0, "current_response_time_percentile_95": 190, "current_response_time_percentile_50": 110, "state": "running", "user_count": 50, "time": 1513062717.12848}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 10054, "num_failures": 0, "avg_response_time": 118.05400835488363, "min": 3, "max": 573, "current_rps": 326.5, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 10054, "num_failures": 0, "avg_response_time": 118.05400835488363, "min": 3, "max": 573, "current_rps": 326.5, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 326.5, "fail_ratio": 0.0, "current_response_time_percentile_95": 200, "current_response_time_percentile_50": 110, "state": "running", "user_count": 50, "time": 1513062719.293961}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 10719, "num_failures": 0, "avg_response_time": 118.91034611437634, "min": 3, "max": 573, "current_rps": 318.5, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 10719, "num_failures": 0, "avg_response_time": 118.91034611437634, "min": 3, "max": 573, "current_rps": 318.6, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 318.6, "fail_ratio": 0.0, "current_response_time_percentile_95": 210, "current_response_time_percentile_50": 110, "state": "running", "user_count": 50, "time": 1513062721.383023}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 11231, "num_failures": 0, "avg_response_time": 120.96625411806606, "min": 3, "max": 573, "current_rps": 325.2, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 11231, "num_failures": 0, "avg_response_time": 120.96625411806606, "min": 3, "max": 573, "current_rps": 325.2, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 325.2, "fail_ratio": 0.0, "current_response_time_percentile_95": 240, "current_response_time_percentile_50": 110, "state": "running", "user_count": 50, "time": 1513062723.465596}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 11856, "num_failures": 0, "avg_response_time": 121.57565789473684, "min": 3, "max": 573, "current_rps": 303.5, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 11856, "num_failures": 0, "avg_response_time": 121.57565789473684, "min": 3, "max": 573, "current_rps": 303.5, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 303.5, "fail_ratio": 0.0, "current_response_time_percentile_95": 240, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062725.5316858}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 12360, "num_failures": 0, "avg_response_time": 123.45995145631068, "min": 3, "max": 573, "current_rps": 293.1, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 12360, "num_failures": 0, "avg_response_time": 123.45995145631068, "min": 3, "max": 573, "current_rps": 293.1, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 293.1, "fail_ratio": 0.0, "current_response_time_percentile_95": 260, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062727.657822}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 12991, "num_failures": 0, "avg_response_time": 124.15787853129089, "min": 3, "max": 573, "current_rps": 272.8, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 12991, "num_failures": 0, "avg_response_time": 124.15787853129089, "min": 3, "max": 573, "current_rps": 272.8, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 272.8, "fail_ratio": 0.0, "current_response_time_percentile_95": 260, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062729.807611}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 13580, "num_failures": 0, "avg_response_time": 125.07091310751105, "min": 3, "max": 573, "current_rps": 271.6, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 13580, "num_failures": 0, "avg_response_time": 125.07091310751105, "min": 3, "max": 573, "current_rps": 271.5, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 271.5, "fail_ratio": 0.0, "current_response_time_percentile_95": 260, "current_response_time_percentile_50": 130, "state": "running", "user_count": 50, "time": 1513062731.888284}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 14144, "num_failures": 0, "avg_response_time": 126.17738970588235, "min": 3, "max": 573, "current_rps": 267.9, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 14144, "num_failures": 0, "avg_response_time": 126.17738970588235, "min": 3, "max": 573, "current_rps": 267.9, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 267.9, "fail_ratio": 0.0, "current_response_time_percentile_95": 270, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062733.964267}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 14790, "num_failures": 0, "avg_response_time": 126.27423935091278, "min": 3, "max": 573, "current_rps": 278.7, "median": 110, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 14790, "num_failures": 0, "avg_response_time": 126.27423935091278, "min": 3, "max": 573, "current_rps": 278.7, "median": 110, "avg_content_length": 2.0}], "errors": [], "total_rps": 278.7, "fail_ratio": 0.0, "current_response_time_percentile_95": 260, "current_response_time_percentile_50": 120, "state": "running", "user_count": 50, "time": 1513062736.0495381}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 15225, "num_failures": 0, "avg_response_time": 128.19054187192117, "min": 3, "max": 573, "current_rps": 284.6, "median": 120, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 15225, "num_failures": 0, "avg_response_time": 128.19054187192117, "min": 3, "max": 573, "current_rps": 284.6, "median": 120, "avg_content_length": 2.0}], "errors": [], "total_rps": 284.6, "fail_ratio": 0.0, "current_response_time_percentile_95": 260, "current_response_time_percentile_50": 130, "state": "running", "user_count": 50, "time": 1513062738.151381}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 15721, "num_failures": 0, "avg_response_time": 129.93454614846385, "min": 3, "max": 573, "current_rps": 280.1, "median": 120, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 15721, "num_failures": 0, "avg_response_time": 129.93454614846385, "min": 3, "max": 573, "current_rps": 280.1, "median": 120, "avg_content_length": 2.0}], "errors": [], "total_rps": 280.1, "fail_ratio": 0.0, "current_response_time_percentile_95": 270, "current_response_time_percentile_50": 140, "state": "running", "user_count": 50, "time": 1513062740.254053}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 16277, "num_failures": 0, "avg_response_time": 130.54340480432512, "min": 3, "max": 573, "current_rps": 264.6, "median": 120, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 16277, "num_failures": 0, "avg_response_time": 130.54340480432512, "min": 3, "max": 573, "current_rps": 264.6, "median": 120, "avg_content_length": 2.0}], "errors": [], "total_rps": 264.6, "fail_ratio": 0.0, "current_response_time_percentile_95": 270, "current_response_time_percentile_50": 140, "state": "running", "user_count": 50, "time": 1513062742.329012}, {"stats": [{"method": "GET", "name": "/test", "num_requests": 16732, "num_failures": 0, "avg_response_time": 132.53579966531197, "min": 3, "max": 646, "current_rps": 263.1, "median": 120, "avg_content_length": 2.0}, {"method": null, "name": "Total", "num_requests": 16732, "num_failures": 0, "avg_response_time": 132.53579966531197, "min": 3, "max": 646, "current_rps": 263.1, "median": 120, "avg_content_length": 2.0}], "errors": [], "total_rps": 263.1, "fail_ratio": 0.0, "current_response_time_percentile_95": 310, "current_response_time_percentile_50": 160, "state": "running", "user_count": 50, "time": 1513062744.395705}], "request": "\\"Method\\",\\"Name\\",\\"# requests\\",\\"# failures\\",\\"Median \\",\\"Average \\",\\"Min \\",\\"Max \\",\\"Content Size\\",\\"Requests/s\\"\\n\\"GET\\",\\"/test\\",16815,0,120,132,3,646,2,283.50\\n\\"None\\",\\"Total\\",16815,0,120,132,3,646,2,283.50", "response": "\\"Name\\",\\"# requests\\",\\"50%\\",\\"66%\\",\\"75%\\",\\"80%\\",\\"90%\\",\\"95%\\",\\"98%\\",\\"99%\\",\\"100%\\"\\n\\"GET /test\\",16815,120,140,160,170,210,260,320,390,650\\n\\"Total\\",16815,120,140,160,170,210,260,320,390,650"}'
data = json.loads(data)
getpdfreport(data,".")

`

@yivanus
Copy link
Author

yivanus commented Jan 22, 2018

`
resports = []
@app.route('/pdfreport')
def pdfreport():
requestdata = requests_csv()
responsedata = distribution_csv()
data = {
'reports': resports,
'request': requestdata,
'response': responsedata
}
filename = getpdfreport(data, app.root_path)
return send_file(filename)

`

add route to webserver

add data when request_stats calling

append these code to function request_stats
data = json.dumps(report) if runners.locust_runner.state != 'stopped': report["time"] = time() resports.append(report)

@cgoldberg
Copy link
Member

perhaps make this into a PR?

@yivanus
Copy link
Author

yivanus commented Jan 24, 2018

ok.i will do it.

@aldenpeterson-wf
Copy link
Contributor

Closing in favor of PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants