o
    bi.                     @   sV  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZ d dlmZ d dlZd dlm  mZ d dlm  mZ d dlm  mZ d dlmZ d dlmZ d dlmZmZ d dlmZ d d	l m!Z! d d
l"m#Z#m$Z$ d dl%m&Z& d dl'm(Z( e)e*Z+ej,Z-dZ.ej/0e.dkZ1e1re+2d dd Z3G dd dZ4dS )    N)floor)List)Version)ray_constants)get_or_create_event_loop)TagKeyrecord_extra_usage_tag)DashboardPrometheusMetrics)DashboardHeadModule)aiohttphdrs)SubprocessModuleHandle)SubprocessRouteTable#RAY_DASHBOARD_BUILD_FOLLOW_SYMLINKS1zEnabling RAY_DASHBOARD_BUILD_FOLLOW_SYMLINKS is not recommended as it allows symlinks to directories outside the dashboard build folder. You may accidentally expose files on your system outside of the build directory.c                  C   sz   t jt jt jtdd} t jt jt}t j| s,t	t
jd| d| t j| d}tjd|td | S )NclientbuildzDashboard build directory not found. If installing from source, please follow the additional steps required to build the dashboard(cd python/ray/z#/client && npm ci && npm run build)static/static)follow_symlinks)ospathjoindirnameabspath__file__basenameisdirdashboard_utilsFrontendNotFoundErrorerrnoENOENTroutesr   FOLLOW_SYMLINKS_ENABLED)	build_dirmodule_name
static_dir r'   R/home/ubuntu/.local/lib/python3.10/site-packages/ray/dashboard/http_server_head.pysetup_static_dir6   s   r)   c                   @   s   e Zd Zdededededededefdd	Zed
de	j
jfddZedde	j
jfddZedde	j
jfddZdd Ze	j
jdd Ze	j
jdd Ze	j
jdd Ze	j
jdd Zdee dee fd d!Zd"d# Zd$S )%HttpServerDashboardHeadip	http_host	http_porthttp_port_retriesgcs_addresssession_namemetricsc           
   
   C   s   || _ || _|| _|| _|dd | _|| _|| _d | _zt	 }t
d| W n  tjyH }	 ztjdv r<t
|	 n|	W Y d }	~	nd }	~	ww tj|  ttjtdk rbtjt d| _d S t | _d S )N:r   z"Setup static dir for dashboard: %s)win32cygwinz4.0.0)loop)r+   r,   r-   r.   splithead_node_ipr1   _session_namerunnerr)   loggerinfor   r   sysplatformwarningdashboard_optional_utilsDashboardHeadRouteTablebindr   r   __version__ClientSessionr   http_session)
selfr+   r,   r-   r.   r/   r0   r1   r$   exr'   r'   r(   __init__M   s,   

z HttpServerDashboardHead.__init__/returnc              
      s|   zt tjd W n ty# } ztd|  W Y d }~nd }~ww tjt	j
t	j
t	j
td}d|jd< |S )NTruez`Failed to record the dashboard usage. This error message is harmless and can be ignored. Error: zclient/build/index.htmlzno-cacheCache-Control)r   r   DASHBOARD_USED	Exceptionr:   r>   r   webFileResponser   r   r   r   r   r   headers)rE   reqerespr'   r'   r(   	get_indexw   s$   
z!HttpServerDashboardHead.get_indexz/favicon.icoc              	      s(   t jtjtjtjtdS )Nzclient/build/favicon.ico)	r   rN   rO   r   r   r   r   r   r   )rE   rQ   r'   r'   r(   get_favicon   s   z#HttpServerDashboardHead.get_faviconz	/timezonec              
      sf   zt  }tj|W S  ty2 } ztd|  tjjddt	| dW  Y d }~S d }~ww )NzError getting timezone: i  zInternal Server Error:statustext)
timezone_utilsget_current_timezone_infor   rN   json_responserM   r:   errorResponsestr)rE   rQ   current_timezonerR   r'   r'   r(   get_timezone   s   z$HttpServerDashboardHead.get_timezonec                 C   s   | j r| jsJ | j | jfS N)r,   r-   rE   r'   r'   r(   get_address   s   z#HttpServerDashboardHead.get_addressc                    s   |j ds|j dr=t|j drdnd}ttj|j }||kr=||jvr=td|d| t	j
 ||I d H S )Nr   z/logszRejecting request_path=z& because it is not relative to parent=)r   
startswithpathlibPurePosixPath	posixpathrealpathparentsr:   r;   r   rN   HTTPForbidden)rE   requesthandlerparentrequest_pathr'   r'   r(   path_clean_middleware   s   
z-HttpServerDashboardHead.path_clean_middlewarec                    s<   t |r|jtjtjfv rtjjdddS ||I d H S )Ni  z'Method Not Allowed for browser traffic.rV   )	r?   is_browser_requestmethodr   	METH_POSTMETH_PUTr   rN   r]   )rE   rk   rl   r'   r'   r(   browsers_no_post_put_middleware   s   z7HttpServerDashboardHead.browsers_no_post_put_middlewarec                    sp  t  }zjz\||I d H }t|jd  d}|W W t  | }z'| jjj|j|tj	| j
dd| | jjj|j|j|tj	| j
dd  W S  tyb } ztd|  W Y d }~S d }~ww  ttjfyo   d} w t  | }z'| jjj|j|tj	| j
dd| | jjj|j|j|tj	| j
dd  W w  ty } ztd|  W Y d }~w d }~ww )Nd   xx	dashboard)endpointhttp_statusr   SessionName	Component)rq   rx   ry   r   rz   r{   zError emitting api metrics: 5xx)time	monotonicr   rW   r1   metrics_request_durationlabels__name__rayrB   r8   observemetrics_request_countrq   incrM   r:   	exceptionasyncioCancelledError)rE   rk   rl   
start_timeresponse
status_tag	resp_timerR   r'   r'   r(   metrics_middleware   sp   

z*HttpServerDashboardHead.metrics_middlewarec                    s8   |j dr||I d H }d|jd< |S ||I d H S )Nr   zmax-age=31536000rK   )r   rd   rP   )rE   rk   rl   r   r'   r'   r(   cache_control_static_middleware   s   
z7HttpServerDashboardHead.cache_control_static_middlewaredashboard_head_modulessubprocess_module_handlesc                    s  |D ]}t j| q|D ]}t| qtjjtj| j	| j
| j| jgd}|jt d |jt d tjj|dd| _| j I d H  d }td| j D ]:}ztj| j| j| j}| I d H  W  n. ty }	 z|	}|  jd7  _td| j|	 W Y d }	~	qQd }	~	ww td| j d| |jjd	  ^| _| _}
t !| jj"r| j#n| j| _t$d
| j| j dd |j% D }|D ]}t$| qt$dt&| d S )N)client_max_sizemiddlewares)r"   z;%a %t '%r' %s %b bytes %D us '%{Referer}i' '%{User-Agent}i')access_log_format   zTry to use port %s: %sz0Failed to find a valid port for dashboard after z
 retries: r   z"Dashboard head http address: %s:%sc                 S   s   g | ]
}|j tjkr|qS r'   )rq   r   	METH_HEAD).0rr'   r'   r(   
<listcomp>'  s    z/HttpServerDashboardHead.run.<locals>.<listcomp>zRegistered %s routes.)'r?   r@   rA   r   r   rN   Applicationr   DASHBOARD_CLIENT_MAX_SIZEr   ro   rt   r   
add_routesr"   bound_routes	AppRunnerr9   setupranger.   TCPSiter,   r-   startOSErrorr:   r>   rM   _serversocketsgetsockname	ipaddress
ip_addressis_unspecifiedr+   r;   routerlen)rE   r   r   mhapplast_exisiterR   _dump_routesr   r'   r'   r(   run   sf   	
zHttpServerDashboardHead.runc                    s   | j  I d H  d S ra   )r9   cleanuprb   r'   r'   r(   r   ,  s   zHttpServerDashboardHead.cleanupN)r   
__module____qualname__r^   intr	   rG   r"   getr   rN   rO   rT   rU   r]   r`   rc   
middlewarero   rt   r   r   r   r
   r   r   r   r'   r'   r'   r(   r*   L   sJ    
*




?r*   )5r   r    r   loggingr   re   r<   r}   mathr   typingr   packaging.versionr   r   ray.dashboard.optional_utilsrw   optional_utilsr?   ray.dashboard.timezone_utilsrY   ray.dashboard.utilsutilsr   r   ray._common.utilsr   ray._private.usage.usage_libr   r   ray.dashboard.dashboard_metricsr	   ray.dashboard.headr
   ray.dashboard.optional_depsr   r   !ray.dashboard.subprocesses.handler   !ray.dashboard.subprocesses.routesr   	getLoggerr   r:   r@   r"   ENV_VAR_FOLLOW_SYMLINKSenvironr   r#   r>   r)   r*   r'   r'   r'   r(   <module>   sB    
