11import argparse
22import asyncio
33from functools import partial
4+ import secrets
5+ import time
46import aiometer
57from datetime import datetime
68from typing import List , override
911import json
1012from yarl import URL
1113from dataclasses import dataclass
14+ from playwright .async_api import async_playwright , Browser
1215
1316
1417@dataclass
@@ -19,6 +22,7 @@ class ServerStartResult:
1922 completion_time : datetime
2023 started_successfully : bool
2124 events : List [dict ]
25+ server_url : URL
2226
2327 @property
2428 def startup_duration (self ):
@@ -28,6 +32,29 @@ def startup_duration(self):
2832 def __str__ (self ) -> str :
2933 return f"user:{ self .username } server:{ self .servername } started:{ self .started_successfully } startup_duration:{ self .startup_duration } "
3034
35+
36+ async def load_nbgitpuller_url (browser : Browser , server_url : URL , token : str , nbgitpuller_url : URL , screenshot_name : str ):
37+ print (f"visiting { server_url } " )
38+ nbgitpuller_url = nbgitpuller_url .extend_query ({
39+ 'targetpath' : secrets .token_urlsafe (8 )
40+ })
41+ target_url = (server_url / nbgitpuller_url .path ).with_query (nbgitpuller_url .query )
42+ await_url = server_url / target_url .query .get ("urlpath" , "/lab" ).rstrip ("/" )
43+ start_time = datetime .now ()
44+
45+ context = await browser .new_context (extra_http_headers = {
46+ "Authorization" : f"token { token } "
47+ })
48+ page = await context .new_page ()
49+ await page .goto (str (target_url ))
50+ await page .wait_for_url (str (await_url ), timeout = 120 * 10 * 1000 )
51+ await page .wait_for_load_state ("networkidle" )
52+ await page .screenshot (path = screenshot_name )
53+ duration = datetime .now () - start_time
54+ print (f"{ server_url } completed test in { duration } " )
55+
56+
57+
3158async def start_named_server (session : aiohttp .ClientSession , hub_url : URL , username : str , server_name : str ) -> ServerStartResult :
3259 """
3360 Try to start a named server as defined
@@ -48,17 +75,22 @@ async def start_named_server(session: aiohttp.ClientSession, hub_url: URL, usern
4875 progress_event = json .loads (line .decode ().strip ()[len ("data: " ):])
4976 events .append (progress_event )
5077 if progress_event .get ("ready" ) == True :
78+ print (progress_event )
5179 return ServerStartResult (
5280 username = username ,
5381 servername = server_name ,
5482 start_time = start_time ,
5583 completion_time = datetime .now (),
5684 started_successfully = True ,
57- events = events
85+ events = events ,
86+ server_url = URL (hub_url / progress_event ['url' ][1 :]) # Trim leading slashG
5887 )
5988 elif resp .status == 201 :
6089 # Means the server is immediately ready, and i don't want to deal with that yet
6190 raise NotImplementedError ()
91+ else :
92+ # Some kinda error
93+ resp .raise_for_status ()
6294
6395
6496async def main ():
@@ -67,19 +99,31 @@ async def main():
6799 argparser .add_argument ("username" , help = "Name of the user" )
68100 argparser .add_argument ("servers_count" , type = int , help = "Number of servers to start" )
69101 argparser .add_argument ("--max-concurrency" , type = int , default = 30 , help = "Max Numbers of Servers to start at the same time" )
102+ # nbgitpuller_url = URL("git-pull?repo=https%3A%2F%2Fkernel.googlesource.com%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux.git&urlpath=lab&branch=master")
103+ nbgitpuller_url = URL ("git-pull?repo=https%3A%2F%2Fgithub.com%2Fspara%2Fcloud-101-geolab&urlpath=lab%2Ftree%2Fcloud-101-geolab%2F&branch=main" )
70104
71105 args = argparser .parse_args ()
72106
73107 token = os .environ ["JUPYTERHUB_TOKEN" ]
74108
75109 hub_url = URL (args .hub_url )
76- async with aiohttp .ClientSession (headers = {
77- "Authorization" : f"token { token } "
78- }) as session :
79- servernames = [f"perf-test-{ i } " for i in range (args .servers_count )]
80- async with aiometer .amap (partial (start_named_server , session , hub_url , args .username ), servernames , max_at_once = args .max_concurrency ) as servers :
81- async for server in servers :
82- print (server )
110+ async with async_playwright () as p :
111+ browser = await p .firefox .launch (headless = False )
112+ async with aiohttp .ClientSession (headers = {
113+ "Authorization" : f"token { token } "
114+ }) as session :
115+ servernames = [f"perf-test-{ i } " for i in range (args .servers_count )]
116+ all_servers = []
117+ async with aiometer .amap (partial (start_named_server , session , hub_url , args .username ), servernames , max_at_once = args .max_concurrency ) as servers :
118+ async for server in servers :
119+ all_servers .append (server )
120+
121+ await aiometer .run_all (
122+ [partial (load_nbgitpuller_url , browser , server .server_url , token , nbgitpuller_url , server .servername + ".png" ) for server in all_servers ],
123+ max_at_once = args .max_concurrency
124+ )
125+
126+ await browser .close ()
83127
84128if __name__ == "__main__" :
85129 asyncio .run (main ())
0 commit comments