.. _Log Viewer:

Log Viewer
==========


.. |error-icon|   image:: ../../images/common/log_viewer_icon_error_vsc.png
   :class: inline
.. |warning-icon| image:: ../../images/common/log_viewer_icon_warning_vsc.png
   :class: inline 
.. |fatal-icon|   image:: ../../images/common/log_viewer_icon_fatal_vsc.png
   :class: inline 


Overview
~~~~~~~~


The DVT Log Viewer is a powerful tool for simulation log analysis.
It identifies structured entries such as UVM messages within the log and extracts attributes,
like the timestamp, file, line, UVM component, message ID and text.

.. figure:: ../../images/common/log_viewer_overview.png

You can search and filter by entry attributes using an intuitive :ref:`query-language`.
The log content is presented by default in a compact format, with a dedicated timeline.
You can easily hyperlink to source code by file/line or UVM component,
cross-link with the :ref:`Waveform Viewer` by timestamp and expand entries to drill down into details.

Right click on any file in the :guilabel:`Explorer`, and from the context menu choose 
:guilabel:`Open With … ‣ Log Viewer`,  or browse to any location on disk
from the :guilabel:`File ‣ Open file…` menu.

.. tip::
    You can directly open zipped logs such as :code:`*.log.gz`

When you open a log file, an :ref:`Indexing` process is started in the background.

The :guilabel:`annotation ruler` displays icons for message severity: |warning-icon| warning, |error-icon| error and |fatal-icon| fatal

.. figure:: ../../images/common/log_viewer_severities.png

The :guilabel:`timeline ruler` presents message timestamps, highlighting changes 
so you can easily visualize groups of messages at the same timestamp. 
Double-click on a timestamp to reveal it in the current :ref:`Waveform Viewer`.

.. figure:: ../../images/common/log_viewer_waveform_link.png

The viewer displays messages in a condensed format: filename, line, 
UVM component (report_object_name) and message ID as well as the first line of the actual message text.
The filename link takes you to the source code line where the message was printed, 
for example the :code:`\`uvm_info()` call. The UVM component link takes you to the definition of the UVM report object.

.. figure:: ../../images/common/log_viewer_links.png

.. note::
    For accurate links to UVM components, use a :ref:`runtime elaborated <UVM Runtime Elaboration>` verification hierarchy,
    with the same runtime arguments used for the test that generated the log.

You can expand the entries to inspect their structure, including the full message text.

.. figure:: ../../images/common/log_viewer_expand.png

.. |go-to-top| image:: ../../images/common/lzv_slider_top.png
   :class: inline

.. |up-one-page| image:: ../../images/common/lzv_slider_pgup.png
   :class: inline

.. |up| image:: ../../images/common/lzv_slider_up.png
   :class: inline

.. |down| image:: ../../images/common/lzv_slider_down.png
   :class: inline

.. |down-one-page| image:: ../../images/common/lzv_slider_pgdn.png
   :class: inline

.. |go-to-bottom| image:: ../../images/common/lzv_slider_bottom.png
   :class: inline
   
The :guilabel:`scrollbar` on the right side of the viewer allows to quickly navigate:
  -   |go-to-top| to the top of the log: :kbd:`Ctrl+Home`
  -   |up-one-page| up one page: :kbd:`PageUp`
  -   |up| up one entry: :kbd:`ArrowUp`
  -   |down| down one entry: :kbd:`ArrowDown`
  -   |down-one-page| down one page: :kbd:`PageDown`
  -   |go-to-bottom| to the bottom of the log: :kbd:`Ctrl+End`

.. _filtering-searching:

Filtering and searching
~~~~~~~~~~~~~~~~~~~~~~~

You can type queries into the :guilabel:`filter box` at the top using a dedicated :ref:`query-language`.
Press enter to apply the filter. 

.. figure:: ../../images/common/log_viewer_filter_bar.png

:kbd:`Ctrl+F` brings up the :guilabel:`search box` at the bottom of the viewer.
Type the query and use the arrows to navigate across matches.
Press esc or click the close button to hide it.

.. figure:: ../../images/common/log_viewer_search_bar.png

Both filter and search input boxes provide content assist and input validation. 
Press :kbd:`Ctrl+Space` to see available query keys and operators.
Validation problems are clearly signaled, hover to get more information.


.. _templates:

Message templates
~~~~~~~~~~~~~~~~~

Each template has a name, category and a pattern which is matched against the log content.
Every pattern match creates a structured entry, mapping attribute keys to their matched value.
The Log Viewer has built-in templates for standard UVM messages and popular compiler and simulator messages.
To select which ones are applicable for the current log, from the :guilabel:`☰` menu choose :guilabel:`Configure message templates`:

.. figure:: ../../images/common/log_viewer_template_config.png 

.. note::
    Templates are applied in the specified order - the first one matching a chunk of log file content consumes it.
    You can move them up and down in the list using the arrow buttons.
    In case of templates with overlapping patterns, keep the more specific templates ahead of generic ones.

From this dialog you can also define new templates, for example if using a custom :code:`uvm_report_server`.
Click the add button :guilabel:`+`, fill in the name and pattern, then click :guilabel:`✓` and :guilabel:`OK`.

Patterns are made up of plain text, which must match literally, and attributes.
You can make an attribute optional by prefixing its name with a question mark, for example :code:`<?optional:text>`.
Attributes have the form :code:`<attribute_key:attribute_type>` and match log content based on their type:

.. list-table::

   * - **Attribute type**
     - **Example usage**
     - **Matches**
     - **Example match**
   * - file
     - <filename:file>
     - relative or absolute path 
     - /path/to/uvm/src/uvm_pkg.sv
   * - file_and_line
     - <fileline:file_and_line>
     - relative or absolute path followed by line number between brackets
     - ../env/usb/usb_monitor.sv (1234)
   * - line
     - <line_no:line>
     - positive number
     - 3754
   * - long
     - <timestamp:long>
     - integer numbers representable as standard 'long' format
     - 12345678
   * - report_object
     - <comp:report_object>
     - hierarchical path of a UVM component
     - uvm_test_top.env.usb_agents[0].usb_monitor
   * - severity
     - <severity:severity>
     - an enumerated set of values mapped to warnings, errors and UVM severities
     - UVM_FATAL
   * - text
     - <message:text>
     - **any text** including newlines numbers and symbols up to the next matching attribute
     - APB_READ: addr = 'h810000, data = 'h55
   * - word
     - <timeunit:word>
     - single word, any combination of upper- and lower-case letters, digits and underscores
     - ps

You can use any identifier for attribute keys, however the following have a special meaning:

.. list-table::

   * - **timestamp**
     - matched values are shown on the timeline ruler
   * - **file, line, file_line_str, report_object**
     - matched values are rendered as hyperlinks
   * - **severity**
     - matched values are rendered as icons on the vertical ruler

.. _query-language:

Query language
~~~~~~~~~~~~~~

Queries are used for filtering and searching the log entries.
In the query you can reference any attribute key from the applicable patterns.
A query can be as simple as a single match clause, for example:

message = "reset done"
    matches entries where attribute key "message" has a value containing "reset done" text (case sensitive)

timestamp = 1234567
    matches entries where attribute key "timestamp" has a value of exactly 1234567

You can combine multiple match clauses using boolean operators, for example:

message = "reset done" && timestamp > 1000
    "reset done" messages after time 1000

You can combine clauses into complex queries using parentheses, for example:

message = "reset done" && (timestamp < 1000 || timestamp > 123456)
    "reset done" messages outside a interval

message = "reset done" && (timestamp < 1000 || timestamp > 123456)
    "reset done" messages outside a interval

report_object_name = "uart0.master_agent.driver" && (message_id = "RX_ITEM" || message_id = "TX_ITEM")
    all log entries from UART0 master driver with specific UVM message IDs

.. note:: The **entry_structure** built-in attribute is set to the name of the pattern, and can be used to hide all unmatched sections of the log using **entry_structure != N/A**

.. note:: Queries which don't start with an attribute key will be applied on all the attributes.

When used for filtering, the query can also include display modifiers:

.. list-table::

   * - **Modifier**
     - **Example**
     - **Effect**
   * - **hide**
     - report_object_name = "uart0.master_agent.driver" && **hide report_object_name**
     - hide report_object_name in the collapsed entry as all entries will show the same matched value
   * - **sort_by**
     - entry_structure = "Retry pattern" && sort_by:-nof_retries
     - show only user defined entry structures called "Retry pattern" and sort descending by custom attribute nof_retries in 


.. _indexing:

Indexing
~~~~~~~~

When you open a log file, it is processed in the background.
Log entries are identified and a search/filter index is built.
The index is saved in a folder called :code:`.dvt.<log_name>`, side by side with the log file.
If you reopen the log at a later time, the index is reused unless the log file changed.

.. note::
    When the log is located in a read-only directory, the index is saved in a temporary location.

To save resources, indexing is lazy. For example, if you open a log to see 
just the first few configuration messages printed at the start of the test, 
only a few small chunks of the file are quickly indexed and **content is immediately available**. 
However, performing a narrow search might require the full index to be built. 
**Once the index is built all subsequent operations are fast, regardless of the log size.**

.. Tip::
    From the main menu you can choose to continue indexing in the background 
    and return to a fully indexed log later.

.. TODO: Cum stii cand e gata?
.. TODO: Ce se intampla daca se modifica logul in timp ce e deschis?

.. Tip::
    Press the top right :guilabel:`refresh` button to bring in new content,
    for example when the current log is being actively generated.




