o
    bi!1                     @   s   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
 eeZdZdZdZde
eef fd	d
ZdefddZdefddZG dd dZG dd dZdS )    N)datetime)Path)Unionz#sudo chown root: `which {profiler}`z'sudo chown root:root `which {profiler}`aB  
Note that this command requires `{profiler}` to be installed with root permissions. You
can install `{profiler}` and give it root permissions as follows:
  $ pip install {profiler}
  $ {set_chown_command}
  $ sudo chmod u+s `which {profiler}`

Alternatively, you can start Ray with passwordless sudo / root permissions.

stringc                 C   s   t | tr
| dS | S )Nzutf-8)
isinstancebytesdecode)r    r	   b/home/ubuntu/.local/lib/python3.10/site-packages/ray/dashboard/modules/reporter/profile_manager.pyr      s   

r   returnc              	   C   sn   t |}d}d| v r$tjdkrtj|dntj|d}tj||d}d|  d| dt | d	t | d
	S )N 
permissiondarwin)profiler)r   set_chown_commandzFailed to execute `z`.
z
=== stderr ===
z

=== stdout ===

)r   lowersysplatformDARWIN_SET_CHOWN_CMDformatLINUX_SET_CHOWN_CMD"PROFILER_PERMISSIONS_ERROR_MESSAGE)cmdr   stdoutstderr
stderr_strextra_messager   r	   r	   r
   _format_failed_profiler_command"   s"   

r   c                     sV   zt jdddtjtjdI d H } W n
 ty   Y dS w |  I d H \}}| jdkS )Nsudo-ntruer   r   Fr   )asynciocreate_subprocess_exec
subprocessPIPEFileNotFoundErrorcommunicate
returncode)process_r	   r	   r
   _can_passwordless_sudo>   s   
r,   c                
   @   sX   e Zd ZdefddZddededeeffdd	Z	ddedededeeffddZ	dS )CpuProfilingManagerprofile_dir_pathc                 C   s"   t || _| jjdd d| _d S )NTexist_okzpy-spyr   r.   mkdirprofiler_nameselfr.   r	   r	   r
   __init__O   s   

zCpuProfilingManager.__init__Fpidnativer   c                    s   t | j}|du rdS |ddt|g}tjdkr!|r!|d t I dH r-ddg| }tj	|t
jt
jd	I dH }| I dH \}}|jd
krSdt|| j||fS dt|fS )a  
        Capture and dump a trace for a specified process.

        Args:
            pid: The process ID (PID) of the target process for trace capture.
            native (bool, optional): If True, includes native (C/C++) stack frames.
                Default is False.

        Returns:
            Tuple[bool, str]: A tuple containing a boolean indicating the success
                of the trace capture operation and a string with the
                trace data or an error message.
        NFz*Failed to execute: py-spy is not installeddump-plinux--nativer   r    r"   r   FT)shutilwhichr3   strr   r   appendr,   r#   r$   r%   r&   r(   r)   r   r   )r5   r7   r8   pyspyr   r*   r   r   r	   r	   r
   
trace_dumpT   s(   


zCpuProfilingManager.trace_dump
flamegraph   durationc              
      s  t | j}|du rdS |dvrdd| dd fS |dkr"d	}nd
}| j| d| d|  }|dd|dt|dt|d|g
}tjdkrM|rM|d t I dH rYddg| }t	j
|tjtjdI dH }	|	 I dH \}
}|	jdkrdt|| j|
|fS dt|d fS )a  
        Perform CPU profiling on a specified process.

        Args:
            pid: The process ID (PID) of the target process to be profiled.
                format (str, optional): The format of the CPU profile output.
                Default is "flamegraph".
            duration (float, optional): The duration of the profiling
                session in seconds. Default is 5 seconds.
            native (bool, optional): If True, includes native (C/C++) stack frames.
                Default is False.

        Returns:
            Tuple[bool, str]: A tuple containing a boolean indicating the success
                of the profiling operation and a string with the
                profile data or an error message.
        Nr9   )rD   raw
speedscopeFz"Failed to execute: Invalid format z, z%must be [flamegraph, raw, speedscope]rD   svgtxtr+   z_cpu_profiling.record-or;   z-d-fr<   r=   r   r    r"   r   Trb)r>   r?   r3   r.   r@   r   r   rA   r,   r#   r$   r%   r&   r(   r)   r   openread)r5   r7   r   rF   r8   rB   	extensionprofile_file_pathr   r*   r   r   r	   r	   r
   cpu_profiley   sR   



zCpuProfilingManager.cpu_profileNF)rD   rE   F)
__name__
__module____qualname__r@   r6   intboolrC   floatrS   r	   r	   r	   r
   r-   N   s    &r-   c                   @   s   e Zd ZdefddZ		ddededed	ed
eeff
ddZ			ddedededed
eeff
ddZ	ddeded
eeffddZ	dS )MemoryProfilingManagerr.   c                 C   s&   t |d | _| jjdd d| _d S )NmemrayTr/   r1   r4   r	   r	   r
   r6      s   
zMemoryProfilingManager.__init__rD   Fr7   profiler_filenamer   leaksr   c                    s  t | j}|du rdS | j| }t| s dd| dfS tj|\}}| j| d }	|dkr<|dd|	d	g}
n|d
krH|d
d|	d	g}
ndd| dfS |rW|
	d |
	| t
j|
tjtjdI dH }| I dH \}}|jdkrdt|
| j||fS dt|	d fS )a  
        Convert the Memray profile result to specified format.

        Args:
            pid: The process ID (PID) associated with the profiling operation.
                profiler_filename: The filename of the profiler output to
                be processed.
            format (str, optional): The format of the profile result.
                Default is "flamegraph".
            leaks (bool, optional): If True, include memory leak information in
                the profile result.

        Returns:
            Tuple[bool, str]: A tuple containing a boolean indicating the success
                of the operation and a string with the processed profile result
                or an error message.
        NF*Failed to execute: memray is not installedFzFailed to execute: process z has not been profiledz.htmlrD   rL   rM   tablez'Failed to execute: Report with format: z is not supportedz--leaksr"   r   TrN   )r>   r?   r3   r.   r   is_fileospathsplitextrA   r#   r$   r%   r&   r(   r)   r   rO   rP   )r5   r7   r]   r   r^   r\   rR   r3   r+   profile_visualize_pathvisualize_cmdr*   r   r   r	   r	   r
   get_profile_result   sP   
	




z)MemoryProfilingManager.get_profile_resultr8   trace_python_allocatorsverbosec                    s   t | j}|du rdS t d}| d| d}| j| }|dt|d|g}	|r1|	d |r8|	d	 |r?|	d
 t	 I dH rKddg|	 }	t
j|	tjtjdI dH }
|
 I dH \}}|
jdkrrddt|	| j||fS d|d| fS )a  
        Attach a Memray profiler to a specified process.

        Args:
            pid: The process ID (PID) of the target process which
                the profiler attached to.
            native (bool, optional): If True, includes native (C/C++) stack frames.
                Default is False.
            trace_python_allocators (bool, optional): If True, includes Python
                stack frames. Default is False.
            verbose (bool, optional): If True, enables verbose output.
                Default is False.

        Returns:
            Tuple[bool, str]: A tuple containing a boolean indicating the success
                of the operation and a string of a sucess message or an error message.
        N)FNr`   z%Y%m%d%H%M%S_memory_profiling_z.binattachrL   r=   z--trace-python-allocators	--verboser   r    r"   r   FTz$Success attaching memray to process )r>   r?   r3   r   nowstrftimer.   r@   rA   r,   r#   r$   r%   r&   r(   r)   r   )r5   r7   r8   ri   rj   r\   	timestampr]   rR   r   r*   r   r   r	   r	   r
   attach_profiler  sB   





	z&MemoryProfilingManager.attach_profilerc                    s   t | j}|du rdS |dg}|r|d |t| t I dH r+ddg| }tj|tj	tj	dI dH }|
 I dH \}}|jdkrQd	t|| j||fS d
d| fS )a  
        Detach a profiler from a specified process.

        Args:
            pid: The process ID (PID) of the target process the
                profiler detached from.
            verbose (bool, optional): If True, enables verbose output.
                Default is False.

        Returns:
            Tuple[bool, str]: A tuple containing a boolean indicating the success
                of the operation and a string of a success message or an error message.
        Nr_   detachrm   r   r    r"   r   FTz&Success detaching memray from process )r>   r?   r3   rA   r@   r,   r#   r$   r%   r&   r(   r)   r   )r5   r7   rj   r\   r   r*   r   r   r	   r	   r
   detach_profilerL  s*   


z&MemoryProfilingManager.detach_profilerN)rD   F)FFFrT   )
rU   rV   rW   r@   r6   rX   rY   rh   rq   rs   r	   r	   r	   r
   r[      sJ    	
L
Cr[   )r#   loggingrc   r>   r%   r   r   pathlibr   typingr   	getLoggerrU   loggerr   r   r   r@   r   r   r   rY   r,   r-   r[   r	   r	   r	   r
   <module>   s$    
o