U
    VcOa                     @   sP   d Z ddlZddlmZ dZdZdZdd Zd	d
 Zdd Z	G dd de
ZdS )zCA wrapper around DebugDataReader used for retrieving tfdbg v2 data.    N)errorsZ__default_debugger_run__i     c                    s6   t    fdd}t j|dd}|   |fS )a  Run a target task repeatedly in the background.

    In the context of this module, `target` is the `update()` method of the
    underlying reader for tfdbg2-format data.
    This method is mocked by unit tests for deterministic behaviors during
    testing.

    Args:
      target: The target task to run in the background, a callable with no args.
      interval_sec: Time interval between repeats, in seconds.

    Returns:
      - A `threading.Event` object that can be used to interrupt an ongoing
          waiting interval between successive runs of `target`. To interrupt the
          interval, call the `set()` method of the object.
      - The `threading.Thread` object on which `target` is run repeatedly.
    c                      s           q d S N)waitclear eventinterval_sectargetr   Z/tmp/pip-unpacked-wheel-g8kmtpbc/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py_run_repeatedly<   s    
z5run_repeatedly_in_background.<locals>._run_repeatedlyT)r   daemon)	threadingEventThreadstart)r   r
   r   threadr   r   r   run_repeatedly_in_background(   s
    r   c              
   C   sT   ddl m} t| |jr@d| j| j| j| j| j| j	| j
| jd	S tdt|  d S )Nr   debug_events_monitorsInfNanAlert)	
alert_typeop_typeoutput_slotsizenum_neg_infnum_pos_infnum_nanexecution_indexgraph_execution_trace_indexzUnrecognized alert subtype: %s)tensorflow.python.debug.libr   
isinstancer   r   r   r   r   r   r   r   r    	TypeErrortype)alertr   r   r   r   _alert_to_jsonH   s    r&   c                 C   s0   d}d| kr$|  d\}}t|}n| }||fS )z@Helper function that extracts op name and slot from tensor name.r   :)splitint)Ztensor_namer   op_namer   r   r   parse_tensor_name_   s    
r+   c                   @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
d)ddZdd Zdd Zd*ddZd+ddZdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( ZdS ),DebuggerV2EventMultiplexera  A class used for accessing tfdbg v2 DebugEvent data on local filesystem.

    This class is a short-term hack, mirroring the EventMultiplexer for the main
    TensorBoard plugins (e.g., scalar, histogram and graphs.) As such, it only
    implements the methods relevant to the Debugger V2 pluggin.

    TODO(cais): Integrate it with EventMultiplexer and use the integrated class
    from MultiplexerDataProvider for a single path of accessing debugger and
    non-debugger data.
    c                 C   s(   || _ d| _t | _d| _|   dS )zConstructor for the `DebugEventMultiplexer`.

        Args:
          logdir: Path to the directory to load the tfdbg v2 data from.
        N)_logdir_readerr   Lock_reader_lock_reload_needed_event_tryCreateReader)selfZlogdirr   r   r   __init__v   s
    
z#DebuggerV2EventMultiplexer.__init__c              	   C   s   | j r
dS | j | j szddlm} ddlm} W n  tk
rT   Y W 5 Q R  dS X z|| j| _ W n> tk
r   Y W 5 Q R  dS  t	k
r   Y W 5 Q R  dS X |j
| j tdg| _t| j jt\| _}W 5 Q R X dS )a*  Try creating reader for tfdbg2 data in the logdir.

        If the reader has already been created, a new one will not be created and
        this function is a no-op.

        If a reader has not been created, create it and start periodic calls to
        `update()` on a separate thread.
        Nr   )debug_events_readerr   )limit)r.   r0   r!   r5   r   ImportErrorZDebugDataReaderr-   AttributeError
ValueErrorInfNanMonitorDEFAULT_PER_TYPE_ALERT_LIMIT	_monitorsr   updateDEFAULT_RELOAD_INTERVAL_SECr1   )r3   r5   r   _r   r   r   r2      s4    	
  z+DebuggerV2EventMultiplexer._tryCreateReaderc                 C   s   | j r| j   dS )a(  If a reader exists and has started period updating, unblock the update.

        The updates are performed periodically with a sleep interval between
        successive calls to the reader's update() method. Calling this method
        interrupts the sleep immediately if one is ongoing.
        N)r1   setr3   r   r   r   _reloadReader   s    z(DebuggerV2EventMultiplexer._reloadReaderc                 C   s4   | j dkrtd|tkr*tdt|f | j  S )aW  Return the timestamp of the first DebugEvent of the given run.

        This may perform I/O if no events have been loaded yet for the run.

        Args:
          run: A string name of the run for which the timestamp is retrieved.
            This currently must be hardcoded as `DEFAULT_DEBUGGER_RUN_NAME`,
            as each logdir contains at most one DebugEvent file set (i.e., a
            run of a tfdbg2-instrumented TensorFlow program.)

        Returns:
            The wall_time of the first event of the run, which will be in seconds
            since the epoch as a `float`.
        NzNo tfdbg2 runs exists.z&Expected run name to be %s, but got %s)r.   r9   DEFAULT_DEBUGGER_RUN_NAMEZstarting_wall_time)r3   runr   r   r   FirstEventTimestamp   s    
z.DebuggerV2EventMultiplexer.FirstEventTimestampc                 C   s   t dd S )NzLDebugDataMultiplexer.PluginRunToTagToContent() has not been implemented yet.)NotImplementedError)r3   Zplugin_namer   r   r   PluginRunToTagToContent   s    z2DebuggerV2EventMultiplexer.PluginRunToTagToContentc                 C   s*   |    | jr"|   tdg iiS i S dS )a  Return all the tfdbg2 run names in the logdir watched by this instance.

        The `Run()` method of this class is specialized for the tfdbg2-format
        DebugEvent files.

        As a side effect, this method unblocks the underlying reader's period
        reloading if a reader exists. This lets the reader update at a higher
        frequency than the default one with 30-second sleeping period between
        reloading when data is being queried actively from this instance.
        Note that this `Runs()` method is used by all other public data-access
        methods of this class (e.g., `ExecutionData()`, `GraphExecutionData()`).
        Hence calls to those methods will lead to accelerated data reloading of
        the reader.

        Returns:
          If tfdbg2-format data exists in the `logdir` of this object, returns:
              ```
              {runName: { "debugger-v2": [tag1, tag2, tag3] } }
              ```
              where `runName` is the hard-coded string `DEFAULT_DEBUGGER_RUN_NAME`
              string. This is related to the fact that tfdbg2 currently contains
              at most one DebugEvent file set per directory.
          If no tfdbg2-format data exists in the `logdir`, an empty `dict`.
        zdebugger-v2N)r2   r.   rB   rC   rA   r   r   r   Runs   s     zDebuggerV2EventMultiplexer.Runsc                 C   sb   |dk rt d| ||kr0t d||f |dkrR||k rRt d||f |dk r^|}|S )Nr   zInvalid begin index (%d)z!end index (%d) out of bounds (%d)z9end index (%d) is unexpectedly less than begin index (%d))r   InvalidArgumentError)r3   beginendZtotal_countr   r   r   _checkBeginEndIndices
  s"    
z0DebuggerV2EventMultiplexer._checkBeginEndIndicesNc              
   C   s   ddl m} |  }||kr dS g }t }t }	| jD ]F}
|
 }|sHq6|| t|
|jrdd}nd}t	|||< ||	|< q6t	|}|dk	r||krt
d| |	| }| ||t	|}|||||tdd ||| D d	S )
a  Get alerts from the debugged TensorFlow program.

        Args:
          run: The tfdbg2 run to get Alerts from.
          begin: Beginning alert index.
          end: Ending alert index.
          alert_type_filter: Optional filter string for alert type, used to
            restrict retrieved alerts data to a single type. If used,
            `begin` and `end` refer to the beginning and ending indices within
            the filtered alert type.
        r   r   Nr   Z__MiscellaneousAlert__z8Filtering of alerts failed: alert type %s does not existc                 S   s   g | ]}t |qS r   )r&   ).0r%   r   r   r   
<listcomp>N  s     z5DebuggerV2EventMultiplexer.Alerts.<locals>.<listcomp>)rJ   rK   r   
num_alertsalerts_breakdownZper_type_alert_limitalerts)r!   r   rH   dictr<   rQ   extendr"   r:   lenr   rI   rL   r;   )r3   rD   rJ   rK   Zalert_type_filterr   runsrQ   rP   Zalerts_by_typeZmonitorZmonitor_alertsr   rO   r   r   r   Alerts  sF    


z!DebuggerV2EventMultiplexer.Alertsc                 C   sX   |   }||krdS | jjdd}| ||t|}||t|dd ||| D dS )a>  Get ExecutionDigests.

        Args:
          run: The tfdbg2 run to get `ExecutionDigest`s from.
          begin: Beginning execution index.
          end: Ending execution index.

        Returns:
          A JSON-serializable object containing the `ExecutionDigest`s and
          related meta-information
        NTdigestc                 S   s   g | ]}|  qS r   to_jsonrM   rX   r   r   r   rN   h  s    z?DebuggerV2EventMultiplexer.ExecutionDigests.<locals>.<listcomp>)rJ   rK   num_digestsexecution_digestsrH   r.   
executionsrL   rT   )r3   rD   rJ   rK   rU   r]   r   r   r   ExecutionDigestsQ  s    
z+DebuggerV2EventMultiplexer.ExecutionDigestsc                 C   sh   |   }||krdS | jjdd}| ||t|}||| }| jjd||d}||dd |D dS )	a`  Get Execution data objects (Detailed, non-digest form).

        Args:
          run: The tfdbg2 run to get `ExecutionDigest`s from.
          begin: Beginning execution index.
          end: Ending execution index.

        Returns:
          A JSON-serializable object containing the `ExecutionDigest`s and
          related meta-information
        NTrW   FrX   rJ   rK   c                 S   s   g | ]}|  qS r   rY   )rM   Z	executionr   r   r   rN     s     z<DebuggerV2EventMultiplexer.ExecutionData.<locals>.<listcomp>)rJ   rK   r_   r^   )r3   rD   rJ   rK   rU   r]   r_   r   r   r   ExecutionDatam  s    z(DebuggerV2EventMultiplexer.ExecutionDatac                 C   sh   |   }||krdS |dk	r$td| jjdd}| ||t|}||t|dd ||| D dS )a`  Get `GraphExecutionTraceDigest`s.

        Args:
          run: The tfdbg2 run to get `GraphExecutionTraceDigest`s from.
          begin: Beginning graph-execution index.
          end: Ending graph-execution index.

        Returns:
          A JSON-serializable object containing the `ExecutionDigest`s and
          related meta-information
        NzFtrace_id support for GraphExecutionTraceDigest is not implemented yet.TrW   c                 S   s   g | ]}|  qS r   rY   r[   r   r   r   rN     s    zDDebuggerV2EventMultiplexer.GraphExecutionDigests.<locals>.<listcomp>)rJ   rK   r\   Zgraph_execution_digestsrH   rF   r.   Zgraph_execution_tracesrL   rT   )r3   rD   rJ   rK   trace_idrU   Zgraph_exec_digestsr   r   r   GraphExecutionDigests  s     
z0DebuggerV2EventMultiplexer.GraphExecutionDigestsc                 C   sl   |   }||krdS |dk	r$td| jjdd}| ||t|}| jjd||d}||dd |D d	S )
aT  Get `GraphExecutionTrace`s.

        Args:
          run: The tfdbg2 run to get `GraphExecutionTrace`s from.
          begin: Beginning graph-execution index.
          end: Ending graph-execution index.

        Returns:
          A JSON-serializable object containing the `ExecutionDigest`s and
          related meta-information
        NzDtrace_id support for GraphExecutionTraceData is not implemented yet.TrW   Fra   c                 S   s   g | ]}|  qS r   rY   )rM   Z
graph_execr   r   r   rN     s    zADebuggerV2EventMultiplexer.GraphExecutionData.<locals>.<listcomp>)rJ   rK   graph_executionsrc   )r3   rD   rJ   rK   rd   rU   digestsrf   r   r   r   GraphExecutionData  s(      z-DebuggerV2EventMultiplexer.GraphExecutionDatac                 C   sP   |   }||krdS z| j|}W n" tk
rF   td| Y nX | S )a  Get the information regarding a TensorFlow graph.

        Args:
          run: Name of the run.
          graph_id: Debugger-generated ID of the graph in question.
            This information is available in the return values
            of `GraphOpInfo`, `GraphExecution`, etc.

        Returns:
          A JSON-serializable object containing the information regarding
            the TensorFlow graph.

        Raises:
          NotFoundError if the graph_id is not known to the debugger.
        NThere is no graph with ID "%s")rH   r.   graph_by_idKeyErrorr   NotFoundErrorrZ   )r3   rD   graph_idrU   graphr   r   r   	GraphInfo  s    
z$DebuggerV2EventMultiplexer.GraphInfoc              
   C   s6  |   }||krdS z| j|}W n" tk
rF   td| Y nX z||}W n& tk
r|   td||f Y nX | ||}|d D ]D}z||d }	W n tk
r   d}	Y nX |	r| |	||d< q|d D ]P}
|
D ]F}z||d }W n tk
r   d}Y nX |r| |||d< qq|S )ab  Get the information regarding a graph op's creation.

        Args:
          run: Name of the run.
          graph_id: Debugger-generated ID of the graph that contains
            the op in question. This ID is available from other methods
            of this class, e.g., the return value of `GraphExecutionDigests()`.
          op_name: Name of the op.

        Returns:
          A JSON-serializable object containing the information regarding
            the op's creation and its immediate inputs and consumers.

        Raises:
          NotFoundError if the graph_id or op_name does not exist.
        Nri   z/There is no op named "%s" in graph with ID "%s"inputsr*   data	consumers)rH   r.   rj   rk   r   rl   Zget_op_creation_digest_opCreationDigestToDataObject)r3   rD   rm   r*   rU   rn   op_creation_digestZdata_objectZ
input_specZinput_op_digestZslot_consumer_specsZconsumer_specrX   r   r   r   GraphOpInfo  s^    

 
 

 z&DebuggerV2EventMultiplexer.GraphOpInfoc                 C   s   |d krd S |  }|d= | |j|d< |j|d< |d= g |d< |jpJg D ]$}t|\}}|d ||d qLg |d< t|d D ]}|d g  q||d D ]"\}}	}
|d | |	|
d	 q|S )
Nrm   	graph_idsnum_outputsinput_namesrp   )r*   r   rr   r*   )r*   Z
input_slot)	rZ   _getGraphStackIdsrm   rw   rx   r+   appendrangeZget_op_consumers)r3   rt   rn   Zjson_objectZinput_tensor_nameZinput_op_namer   r?   Zsrc_slotZconsumer_op_nameZdst_slotr   r   r   rs   $  s2    
z8DebuggerV2EventMultiplexer._opCreationDigestToDataObjectc                 C   s:   |g}| j |}|jr6|d|j | j |j}q|S )aL  Retrieve the IDs of all outer graphs of a graph.

        Args:
          graph_id: Id of the graph being queried with respect to its outer
            graphs context.

        Returns:
          A list of graph_ids, ordered from outermost to innermost, including
            the input `graph_id` argument as the last item.
        r   )r.   rj   Zouter_graph_idinsert)r3   rm   rv   rn   r   r   r   ry   A  s    z,DebuggerV2EventMultiplexer._getGraphStackIdsc                 C   s   |   }||krd S | j S r   )rH   r.   source_file_list)r3   rD   rU   r   r   r   SourceFileListS  s    z)DebuggerV2EventMultiplexer.SourceFileListc                 C   sd   |   }||krd S z| j | \}}W n" tk
rL   td| Y nX ||| j||dS )Nz(There is no source-code file at index %d)	host_name	file_pathlines)rH   r.   r}   
IndexErrorr   rl   Zsource_lines)r3   rD   indexrU   r   r   r   r   r   SourceLinesY  s    
z&DebuggerV2EventMultiplexer.SourceLinesc                 C   sV   |   }||krd S g }|D ]0}|| jjkr:td| || jj|  qd|iS )Nz"Cannot find stack frame with ID %sstack_frames)rH   r.   Z_stack_frame_by_idr   rl   rz   )r3   rD   Zstack_frame_idsrU   r   Zstack_frame_idr   r   r   StackFramesi  s    z&DebuggerV2EventMultiplexer.StackFrames)N)N)N)__name__
__module____qualname____doc__r4   r2   rB   rE   rG   rH   rL   rV   r`   rb   re   rh   ro   ru   rs   ry   r~   r   r   r   r   r   r   r,   j   s(   2
+
5
!
#?r,   )r   r   Ztensorboardr   rC   r;   r>   r   r&   r+   objectr,   r   r   r   r   <module>   s    