locust 2.32.2.dev7__tar.gz → 2.32.2.dev19__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/PKG-INFO +1 -1
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/_version.py +2 -2
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/html.py +3 -1
- locust-2.32.2.dev19/locust/util/date.py +23 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/web.py +13 -5
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/webui/dist/report.html +1 -1
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/poetry.lock +48 -1
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/pyproject.toml +2 -1
- locust-2.32.2.dev7/locust/util/date.py +0 -5
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/LICENSE +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/README.md +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/__init__.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/__main__.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/argument_parser.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/clients.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/contrib/__init__.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/contrib/fasthttp.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/contrib/mongodb.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/contrib/postgres.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/debug.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/dispatch.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/env.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/event.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/exception.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/input_events.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/log.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/main.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/py.typed +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/rpc/__init__.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/rpc/protocol.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/rpc/zmqrpc.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/runners.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/shape.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/stats.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/user/__init__.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/user/inspectuser.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/user/sequential_taskset.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/user/task.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/user/users.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/user/wait_time.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/__init__.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/cache.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/deprecation.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/directory.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/exception_handler.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/load_locustfile.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/rounding.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/timespan.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/util/url.py +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/webui/dist/assets/favicon-dark.png +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/webui/dist/assets/favicon-light.png +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/webui/dist/assets/index-CV_-ndKF.js +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/webui/dist/auth.html +0 -0
- {locust-2.32.2.dev7 → locust-2.32.2.dev19}/locust/webui/dist/index.html +0 -0
@@ -14,7 +14,7 @@ __version_tuple__: VERSION_TUPLE
|
|
14
14
|
version_tuple: VERSION_TUPLE
|
15
15
|
|
16
16
|
|
17
|
-
__version__ = "2.32.2.
|
17
|
+
__version__ = "2.32.2.dev19"
|
18
18
|
version = __version__
|
19
|
-
__version_tuple__ = (2, 32, 2, "
|
19
|
+
__version_tuple__ = (2, 32, 2, "dev19")
|
20
20
|
version_tuple = __version_tuple__
|
@@ -12,7 +12,7 @@ from . import stats as stats_module
|
|
12
12
|
from .runners import STATE_STOPPED, STATE_STOPPING, MasterRunner
|
13
13
|
from .stats import sort_stats, update_stats_history
|
14
14
|
from .user.inspectuser import get_ratio
|
15
|
-
from .util.date import format_utc_timestamp
|
15
|
+
from .util.date import format_duration, format_utc_timestamp
|
16
16
|
|
17
17
|
PERCENTILES_FOR_HTML_REPORT = [0.50, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1.0]
|
18
18
|
DEFAULT_BUILD_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "webui", "dist")
|
@@ -36,6 +36,7 @@ def get_html_report(
|
|
36
36
|
if end_ts := stats.last_request_timestamp:
|
37
37
|
end_time = format_utc_timestamp(end_ts)
|
38
38
|
else:
|
39
|
+
end_ts = stats.start_time
|
39
40
|
end_time = start_time
|
40
41
|
|
41
42
|
host = None
|
@@ -88,6 +89,7 @@ def get_html_report(
|
|
88
89
|
],
|
89
90
|
"start_time": start_time,
|
90
91
|
"end_time": end_time,
|
92
|
+
"duration": format_duration(stats.start_time, end_ts),
|
91
93
|
"host": escape(str(host)),
|
92
94
|
"history": history,
|
93
95
|
"show_download_link": show_download_link,
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from datetime import datetime, timezone
|
2
|
+
|
3
|
+
|
4
|
+
def format_utc_timestamp(unix_timestamp):
|
5
|
+
return datetime.fromtimestamp(int(unix_timestamp), timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
6
|
+
|
7
|
+
|
8
|
+
def format_safe_timestamp(unix_timestamp):
|
9
|
+
return datetime.fromtimestamp(int(unix_timestamp)).strftime("%Y-%m-%d-%Hh%M")
|
10
|
+
|
11
|
+
|
12
|
+
def format_duration(start_time, end_time):
|
13
|
+
seconds = int(end_time) - int(start_time)
|
14
|
+
days = seconds // 86400
|
15
|
+
hours = (seconds % 86400) // 3600
|
16
|
+
minutes = (seconds % 3600) // 60
|
17
|
+
seconds = seconds % 60
|
18
|
+
|
19
|
+
time_parts = [(days, "day"), (hours, "hour"), (minutes, "minute"), (seconds, "second")]
|
20
|
+
|
21
|
+
parts = [f"{value} {label}{'s' if value != 1 else ''}" for value, label in time_parts if value > 0]
|
22
|
+
|
23
|
+
return " and ".join(filter(None, [", ".join(parts[:-1])] + parts[-1:])) if parts else "0 seconds"
|
@@ -40,7 +40,7 @@ from .runners import STATE_MISSING, STATE_RUNNING, MasterRunner
|
|
40
40
|
from .stats import StatsCSV, StatsCSVFileWriter, StatsErrorDict, sort_stats
|
41
41
|
from .user.inspectuser import get_ratio
|
42
42
|
from .util.cache import memoize
|
43
|
-
from .util.date import
|
43
|
+
from .util.date import format_safe_timestamp
|
44
44
|
from .util.timespan import parse_timespan
|
45
45
|
|
46
46
|
if TYPE_CHECKING:
|
@@ -347,17 +347,25 @@ class WebUI:
|
|
347
347
|
)
|
348
348
|
if request.args.get("download"):
|
349
349
|
res = app.make_response(res)
|
350
|
-
|
350
|
+
host = f"_{self.environment.host}" if self.environment.host else ""
|
351
|
+
res.headers["Content-Disposition"] = (
|
352
|
+
f"attachment;filename=Locust_{format_safe_timestamp(self.environment.stats.start_time)}_"
|
353
|
+
+ f"{self.environment.locustfile}{host}.html"
|
354
|
+
)
|
351
355
|
return res
|
352
356
|
|
353
357
|
def _download_csv_suggest_file_name(suggest_filename_prefix: str) -> str:
|
354
358
|
"""Generate csv file download attachment filename suggestion.
|
355
359
|
|
356
360
|
Arguments:
|
357
|
-
suggest_filename_prefix: Prefix of the filename to suggest for saving the download.
|
361
|
+
suggest_filename_prefix: Prefix of the filename to suggest for saving the download.
|
362
|
+
Will be appended with timestamp.
|
358
363
|
"""
|
359
|
-
|
360
|
-
return
|
364
|
+
host = f"_{self.environment.host}" if self.environment.host else ""
|
365
|
+
return (
|
366
|
+
f"Locust_{format_safe_timestamp(self.environment.stats.start_time)}_"
|
367
|
+
+ f"{self.environment.locustfile}{host}_{suggest_filename_prefix}.csv"
|
368
|
+
)
|
361
369
|
|
362
370
|
def _download_csv_response(csv_data: str, filename_prefix: str) -> Response:
|
363
371
|
"""Generate csv file download response with 'csv_data'.
|
@@ -220,7 +220,7 @@ PERFORMANCE OF THIS SOFTWARE.
|
|
220
220
|
<span style="color:${f};">
|
221
221
|
${h}: ${Rbe({chartValueFormatter:i,value:d})}
|
222
222
|
</span>
|
223
|
-
`,""):"No data",borderWidth:0},xAxis:{type:"time",min:(e.time||[new Date().toISOString()])[0],startValue:(e.time||[])[0],axisLabel:{formatter:Lbe}},grid:{left:60,right:40},yAxis:Ebe({splitAxis:a,yAxisLabels:o}),series:NW({charts:e,lines:r,scatterplot:s}),color:n,toolbox:{right:10,feature:{dataZoom:{title:{zoom:"Zoom Select",back:"Zoom Reset"},yAxisIndex:!1},saveAsImage:{name:t.replace(/\s+/g,"_").toLowerCase()+"_"+new Date().getTime()/1e3,title:"Download as PNG",emphasis:{iconStyle:{textPosition:"left"}}}}}}),Nbe=e=>({symbol:"none",label:{formatter:t=>`Run #${t.dataIndex+1}`,padding:[0,0,8,0]},data:(e.markers||[]).map(t=>({xAxis:t}))}),zbe=e=>t=>{const{batch:r}=t;if(!r)return;const[{start:n,startValue:i,end:a}]=r,o=n>0&&a<=100||i>0;e.setOption({dataZoom:[{type:"slider",show:o}]})},Bbe=aQ;function Fbe({charts:e,title:t,lines:r,colors:n,chartValueFormatter:i,splitAxis:a,yAxisLabels:o,scatterplot:s,shouldReplaceMergeLines:l=!1}){const[u,c]=V.useState(null),f=Bbe(({theme:{isDarkMode:d}})=>d),h=V.useRef(null);return V.useEffect(()=>{if(!h.current)return;const d=bce(h.current);d.setOption(Obe({charts:e,title:t,lines:r,colors:n,chartValueFormatter:i,splitAxis:a,yAxisLabels:o,scatterplot:s})),d.on("datazoom",zbe(d));const p=()=>d.resize();return window.addEventListener("resize",p),d.group="swarmCharts",Cce("swarmCharts"),c(d),()=>{Tce(d),window.removeEventListener("resize",p)}},[h]),V.useEffect(()=>{const d=r.every(({key:p})=>!!e[p]);u&&d&&u.setOption({series:r.map(({key:p,yAxisIndex:v,...g},y)=>({...g,data:e[p],...a?{yAxisIndex:v||y}:{},...y===0?{markLine:Nbe(e)}:{}}))})},[e,u,r]),V.useEffect(()=>{if(u){const{textColor:d,axisColor:p,backgroundColor:v,splitLine:g}=f?Lz.DARK:Lz.LIGHT;u.setOption({backgroundColor:v,textStyle:{color:d},title:{textStyle:{color:d}},legend:{icon:"circle",inactiveColor:d,textStyle:{color:d}},tooltip:{backgroundColor:v,textStyle:{color:d}},xAxis:{axisLine:{lineStyle:{color:p}}},yAxis:{axisLine:{lineStyle:{color:p}},splitLine:{lineStyle:{color:g}}}})}},[u,f]),V.useEffect(()=>{u&&u.setOption({series:NW({charts:e,lines:r,scatterplot:s})},l?{replaceMerge:["series"]}:void 0)},[r]),H.jsx("div",{ref:h,style:{width:"100%",height:"300px"}})}const Vbe=dl.percentilesToChart?dl.percentilesToChart.map(e=>({name:`${e*100}th percentile`,key:`responseTimePercentile${e}`})):[],Gbe=["#ff9f00","#9966CC","#8A2BE2","#8E4585","#E0B0FF","#C8A2C8","#E6E6FA"],$be=[{title:"Total Requests per Second",lines:[{name:"RPS",key:"currentRps"},{name:"Failures/s",key:"currentFailPerSec"}],colors:["#00ca5a","#ff6d6d"]},{title:"Response Times (ms)",lines:Vbe,colors:Gbe},{title:"Number of Users",lines:[{name:"Number of Users",key:"userCount"}],colors:["#0099ff"]}];function zW({charts:e}){return H.jsx("div",{children:$be.map((t,r)=>H.jsx(Fbe,{...t,charts:e},`swarm-chart-${r}`))})}const Hbe=({ui:{charts:e}})=>({charts:e});Kd(Hbe)(zW);function Wbe(e){return(e*100).toFixed(1)+"%"}function EC({classRatio:e}){return H.jsx("ul",{children:Object.entries(e).map(([t,{ratio:r,tasks:n}])=>H.jsxs("li",{children:[`${Wbe(r)} ${t}`,n&&H.jsx(EC,{classRatio:n})]},`nested-ratio-${t}`))})}function BW({ratios:{perClass:e,total:t}}){return!e&&!t?null:H.jsxs("div",{children:[e&&H.jsxs(H.Fragment,{children:[H.jsx("h3",{children:"Ratio Per Class"}),H.jsx(EC,{classRatio:e})]}),t&&H.jsxs(H.Fragment,{children:[H.jsx("h3",{children:"Total Ratio"}),H.jsx(EC,{classRatio:t})]})]})}const Ube=({ui:{ratios:e}})=>({ratios:e});Kd(Ube)(BW);const xS={DARK:"dark",LIGHT:"light"},FW=localStorage.theme===xS.DARK||!("theme"in localStorage)&&window.matchMedia("(prefers-color-scheme: dark)").matches?xS.DARK:xS.LIGHT,jbe={isDarkMode:!1},Ybe=Oq({name:"theme",initialState:jbe,reducers:{setIsDarkMode:(e,{payload:t})=>{e.isDarkMode=t}}}),Xbe=Ybe.reducer,Zbe=e=>ZT({palette:{mode:e,primary:{main:"#15803d"},success:{main:"#00C853"}},components:{MuiCssBaseline:{styleOverrides:{":root":{"--footer-height":"40px"}}}}}),Kbe=Zbe(window.theme||FW),qbe=(window.theme||FW)==="dark",Qbe=[{key:"method",title:"Type"},{key:"name",title:"Name"},{key:"numRequests",title:"# Requests"},{key:"numFailures",title:"# Fails"},{key:"avgResponseTime",title:"Average (ms)",round:2},{key:"minResponseTime",title:"Min (ms)"},{key:"maxResponseTime",title:"Max (ms)"},{key:"avgContentLength",title:"Average size (bytes)",round:2},{key:"totalRps",title:"RPS",round:2},{key:"totalFailPerSec",title:"Failures/s",round:2}],Jbe=Aq({reducer:W3({theme:Xbe}),preloadedState:{theme:{isDarkMode:qbe}}});function eCe({locustfile:e,showDownloadLink:t,startTime:r,endTime:n,
|
223
|
+
`,""):"No data",borderWidth:0},xAxis:{type:"time",min:(e.time||[new Date().toISOString()])[0],startValue:(e.time||[])[0],axisLabel:{formatter:Lbe}},grid:{left:60,right:40},yAxis:Ebe({splitAxis:a,yAxisLabels:o}),series:NW({charts:e,lines:r,scatterplot:s}),color:n,toolbox:{right:10,feature:{dataZoom:{title:{zoom:"Zoom Select",back:"Zoom Reset"},yAxisIndex:!1},saveAsImage:{name:t.replace(/\s+/g,"_").toLowerCase()+"_"+new Date().getTime()/1e3,title:"Download as PNG",emphasis:{iconStyle:{textPosition:"left"}}}}}}),Nbe=e=>({symbol:"none",label:{formatter:t=>`Run #${t.dataIndex+1}`,padding:[0,0,8,0]},data:(e.markers||[]).map(t=>({xAxis:t}))}),zbe=e=>t=>{const{batch:r}=t;if(!r)return;const[{start:n,startValue:i,end:a}]=r,o=n>0&&a<=100||i>0;e.setOption({dataZoom:[{type:"slider",show:o}]})},Bbe=aQ;function Fbe({charts:e,title:t,lines:r,colors:n,chartValueFormatter:i,splitAxis:a,yAxisLabels:o,scatterplot:s,shouldReplaceMergeLines:l=!1}){const[u,c]=V.useState(null),f=Bbe(({theme:{isDarkMode:d}})=>d),h=V.useRef(null);return V.useEffect(()=>{if(!h.current)return;const d=bce(h.current);d.setOption(Obe({charts:e,title:t,lines:r,colors:n,chartValueFormatter:i,splitAxis:a,yAxisLabels:o,scatterplot:s})),d.on("datazoom",zbe(d));const p=()=>d.resize();return window.addEventListener("resize",p),d.group="swarmCharts",Cce("swarmCharts"),c(d),()=>{Tce(d),window.removeEventListener("resize",p)}},[h]),V.useEffect(()=>{const d=r.every(({key:p})=>!!e[p]);u&&d&&u.setOption({series:r.map(({key:p,yAxisIndex:v,...g},y)=>({...g,data:e[p],...a?{yAxisIndex:v||y}:{},...y===0?{markLine:Nbe(e)}:{}}))})},[e,u,r]),V.useEffect(()=>{if(u){const{textColor:d,axisColor:p,backgroundColor:v,splitLine:g}=f?Lz.DARK:Lz.LIGHT;u.setOption({backgroundColor:v,textStyle:{color:d},title:{textStyle:{color:d}},legend:{icon:"circle",inactiveColor:d,textStyle:{color:d}},tooltip:{backgroundColor:v,textStyle:{color:d}},xAxis:{axisLine:{lineStyle:{color:p}}},yAxis:{axisLine:{lineStyle:{color:p}},splitLine:{lineStyle:{color:g}}}})}},[u,f]),V.useEffect(()=>{u&&u.setOption({series:NW({charts:e,lines:r,scatterplot:s})},l?{replaceMerge:["series"]}:void 0)},[r]),H.jsx("div",{ref:h,style:{width:"100%",height:"300px"}})}const Vbe=dl.percentilesToChart?dl.percentilesToChart.map(e=>({name:`${e*100}th percentile`,key:`responseTimePercentile${e}`})):[],Gbe=["#ff9f00","#9966CC","#8A2BE2","#8E4585","#E0B0FF","#C8A2C8","#E6E6FA"],$be=[{title:"Total Requests per Second",lines:[{name:"RPS",key:"currentRps"},{name:"Failures/s",key:"currentFailPerSec"}],colors:["#00ca5a","#ff6d6d"]},{title:"Response Times (ms)",lines:Vbe,colors:Gbe},{title:"Number of Users",lines:[{name:"Number of Users",key:"userCount"}],colors:["#0099ff"]}];function zW({charts:e}){return H.jsx("div",{children:$be.map((t,r)=>H.jsx(Fbe,{...t,charts:e},`swarm-chart-${r}`))})}const Hbe=({ui:{charts:e}})=>({charts:e});Kd(Hbe)(zW);function Wbe(e){return(e*100).toFixed(1)+"%"}function EC({classRatio:e}){return H.jsx("ul",{children:Object.entries(e).map(([t,{ratio:r,tasks:n}])=>H.jsxs("li",{children:[`${Wbe(r)} ${t}`,n&&H.jsx(EC,{classRatio:n})]},`nested-ratio-${t}`))})}function BW({ratios:{perClass:e,total:t}}){return!e&&!t?null:H.jsxs("div",{children:[e&&H.jsxs(H.Fragment,{children:[H.jsx("h3",{children:"Ratio Per Class"}),H.jsx(EC,{classRatio:e})]}),t&&H.jsxs(H.Fragment,{children:[H.jsx("h3",{children:"Total Ratio"}),H.jsx(EC,{classRatio:t})]})]})}const Ube=({ui:{ratios:e}})=>({ratios:e});Kd(Ube)(BW);const xS={DARK:"dark",LIGHT:"light"},FW=localStorage.theme===xS.DARK||!("theme"in localStorage)&&window.matchMedia("(prefers-color-scheme: dark)").matches?xS.DARK:xS.LIGHT,jbe={isDarkMode:!1},Ybe=Oq({name:"theme",initialState:jbe,reducers:{setIsDarkMode:(e,{payload:t})=>{e.isDarkMode=t}}}),Xbe=Ybe.reducer,Zbe=e=>ZT({palette:{mode:e,primary:{main:"#15803d"},success:{main:"#00C853"}},components:{MuiCssBaseline:{styleOverrides:{":root":{"--footer-height":"40px"}}}}}),Kbe=Zbe(window.theme||FW),qbe=(window.theme||FW)==="dark",Qbe=[{key:"method",title:"Type"},{key:"name",title:"Name"},{key:"numRequests",title:"# Requests"},{key:"numFailures",title:"# Fails"},{key:"avgResponseTime",title:"Average (ms)",round:2},{key:"minResponseTime",title:"Min (ms)"},{key:"maxResponseTime",title:"Max (ms)"},{key:"avgContentLength",title:"Average size (bytes)",round:2},{key:"totalRps",title:"RPS",round:2},{key:"totalFailPerSec",title:"Failures/s",round:2}],Jbe=Aq({reducer:W3({theme:Xbe}),preloadedState:{theme:{isDarkMode:qbe}}});function eCe({locustfile:e,showDownloadLink:t,startTime:r,endTime:n,duration:i,charts:a,host:o,exceptionsStatistics:s,requestsStatistics:l,failuresStatistics:u,responseTimeStatistics:c,tasks:f}){return H.jsx(ZQ,{store:Jbe,children:H.jsxs($Y,{theme:Kbe,children:[H.jsx(TZ,{}),H.jsxs(SZ,{maxWidth:"lg",sx:{my:4},children:[H.jsxs(Nn,{sx:{display:"flex",justifyContent:"space-between",alignItems:"flex-end"},children:[H.jsx(Tr,{component:"h1",noWrap:!0,sx:{fontWeight:700},variant:"h3",children:"Locust Test Report"}),t&&H.jsx(G3,{href:`?download=1&theme=${window.theme}`,children:"Download the Report"})]}),H.jsxs(Nn,{sx:{my:2},children:[H.jsxs(Nn,{sx:{display:"flex",columnGap:.5},children:[H.jsx(Tr,{fontWeight:600,children:"During:"}),H.jsxs(Tr,{children:[IC(r)," - ",IC(n)," (",i,")"]})]}),H.jsxs(Nn,{sx:{display:"flex",columnGap:.5},children:[H.jsx(Tr,{fontWeight:600,children:"Target Host:"}),H.jsx(Tr,{children:o||"None"})]}),H.jsxs(Nn,{sx:{display:"flex",columnGap:.5},children:[H.jsx(Tr,{fontWeight:600,children:"Script:"}),H.jsx(Tr,{children:e})]})]}),H.jsxs(Nn,{sx:{display:"flex",flexDirection:"column",rowGap:4},children:[H.jsxs(Nn,{children:[H.jsx(Tr,{component:"h2",mb:1,noWrap:!0,variant:"h4",children:"Request Statistics"}),H.jsx(t4,{stats:l,tableStructure:Qbe})]}),!!c.length&&H.jsxs(Nn,{children:[H.jsx(Tr,{component:"h2",mb:1,noWrap:!0,variant:"h4",children:"Response Time Statistics"}),H.jsx(bne,{responseTimes:c})]}),H.jsxs(Nn,{children:[H.jsx(Tr,{component:"h2",mb:1,noWrap:!0,variant:"h4",children:"Failures Statistics"}),H.jsx(QF,{errors:u})]}),!!s.length&&H.jsxs(Nn,{children:[H.jsx(Tr,{component:"h2",mb:1,noWrap:!0,variant:"h4",children:"Exceptions Statistics"}),H.jsx(qF,{exceptions:s})]}),H.jsxs(Nn,{children:[H.jsx(Tr,{component:"h2",mb:1,noWrap:!0,variant:"h4",children:"Charts"}),H.jsx(zW,{charts:a})]}),H.jsxs(Nn,{children:[H.jsx(Tr,{component:"h2",mb:1,noWrap:!0,variant:"h4",children:"Final ratio"}),H.jsx(BW,{ratios:f})]})]})]})]})})}const tCe=SS.createRoot(document.getElementById("root"));tCe.render(H.jsx(p9,{fallbackRender:g9,children:H.jsx(eCe,{...x9})}));
|
224
224
|
</script>
|
225
225
|
</head>
|
226
226
|
{% endraw %}
|
@@ -513,6 +513,20 @@ files = [
|
|
513
513
|
{file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"},
|
514
514
|
]
|
515
515
|
|
516
|
+
[[package]]
|
517
|
+
name = "exceptiongroup"
|
518
|
+
version = "1.2.2"
|
519
|
+
description = "Backport of PEP 654 (exception groups)"
|
520
|
+
optional = false
|
521
|
+
python-versions = ">=3.7"
|
522
|
+
files = [
|
523
|
+
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
524
|
+
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
|
525
|
+
]
|
526
|
+
|
527
|
+
[package.extras]
|
528
|
+
test = ["pytest (>=6)"]
|
529
|
+
|
516
530
|
[[package]]
|
517
531
|
name = "filelock"
|
518
532
|
version = "3.16.1"
|
@@ -872,6 +886,17 @@ perf = ["ipython"]
|
|
872
886
|
test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
|
873
887
|
type = ["pytest-mypy"]
|
874
888
|
|
889
|
+
[[package]]
|
890
|
+
name = "iniconfig"
|
891
|
+
version = "2.0.0"
|
892
|
+
description = "brain-dead simple config-ini parsing"
|
893
|
+
optional = false
|
894
|
+
python-versions = ">=3.7"
|
895
|
+
files = [
|
896
|
+
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
897
|
+
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
898
|
+
]
|
899
|
+
|
875
900
|
[[package]]
|
876
901
|
name = "itsdangerous"
|
877
902
|
version = "2.2.0"
|
@@ -1632,6 +1657,28 @@ lxml = ">=2.1"
|
|
1632
1657
|
[package.extras]
|
1633
1658
|
test = ["pytest", "pytest-cov", "requests", "webob", "webtest"]
|
1634
1659
|
|
1660
|
+
[[package]]
|
1661
|
+
name = "pytest"
|
1662
|
+
version = "8.3.3"
|
1663
|
+
description = "pytest: simple powerful testing with Python"
|
1664
|
+
optional = false
|
1665
|
+
python-versions = ">=3.8"
|
1666
|
+
files = [
|
1667
|
+
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
|
1668
|
+
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
|
1669
|
+
]
|
1670
|
+
|
1671
|
+
[package.dependencies]
|
1672
|
+
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
1673
|
+
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
1674
|
+
iniconfig = "*"
|
1675
|
+
packaging = "*"
|
1676
|
+
pluggy = ">=1.5,<2"
|
1677
|
+
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
|
1678
|
+
|
1679
|
+
[package.extras]
|
1680
|
+
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
1681
|
+
|
1635
1682
|
[[package]]
|
1636
1683
|
name = "pywin32"
|
1637
1684
|
version = "308"
|
@@ -2474,4 +2521,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"]
|
|
2474
2521
|
[metadata]
|
2475
2522
|
lock-version = "2.0"
|
2476
2523
|
python-versions = ">=3.9"
|
2477
|
-
content-hash = "
|
2524
|
+
content-hash = "87823fddd6f62da6dd45b8f33d7e7cf6b707ea6c8bb6e06d1f7753d6ec6c6e83"
|
@@ -5,7 +5,7 @@ build-backend = "poetry_dynamic_versioning.backend"
|
|
5
5
|
[tool.poetry]
|
6
6
|
name = "locust"
|
7
7
|
description = "Developer-friendly load testing framework"
|
8
|
-
version = "2.32.2.
|
8
|
+
version = "2.32.2.dev19"
|
9
9
|
license = "MIT"
|
10
10
|
readme = "README.md"
|
11
11
|
authors = ["Jonatan Heyman", "Lars Holmberg"]
|
@@ -156,6 +156,7 @@ retry = "^0.9.2"
|
|
156
156
|
ruff = "0.3.7"
|
157
157
|
tox = "^4.16.0"
|
158
158
|
types-requests = "^2.32.0.20240622"
|
159
|
+
pytest = "^8.3.3"
|
159
160
|
|
160
161
|
[tool.poetry.group.docs]
|
161
162
|
optional = true
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|