# Diagnostics

## IPC CLI Diagnostics

The following functions are documented as being a part of the DiagnosticsManager class and are available via:

    ipc.diagnostic.<function>

A common use of the diagnostic commands could be:

    ipc.diagnostic.markExperiment()
       *do something interesting*
    ipc.diagnostic.collect()
    >>>...Collecting Log Results
    ...Logging Preset Restored to *previous preset*
    ...Compiling Payload
    ...Diagnostic Payload can be found at: *PATH to payload*

class DiagnosticsManager(cli)

  Provides diagnostic operations evaluating the health of the Transport and JTAG scan chains.

  collect(tag='payload', uid=None)

    Resets log levels and compiles payload

    Complies an archive with logging and diagnostic info and prints path. Can be used independent of markExperiment.

    Parameters

      - uid (str) – upload ID (defaults to None)

      - tag (str) – tag string to append to archive name (defaults to ‘payload’)

    Returns

      None. Prints archive location.

  info(categories=['Host', 'JTAG', 'Transport'])

    Gathers the settings

    Collects the settings that affect JTAG and returns them as a report.

    Parameters

      categories (list) – a list of the categories to include in the report. (default is [“Host”, “JTAG”, “Transport”]).

    Returns

      DiagnosticResults

  mark_experiment(tag='anonymous', logging_preset='All')

    Loads preset, flushes logs, and writes start message

    Parameters

      - tag (str) – tag/title for the experiment that appears int he logs (defaults to ‘anonymous’)

      - logging_preset (str) – the name of the logging preset to load (defaults to ‘All’)

    Returns

      None.

  run(categories=['JTAG'])

    Runs the available jtag diagnostic tests.

    Run a number of jtag diagnostic test and returns a structure containing the results of the tests.

    Parameters

      categories (list) – a list of the categories to include in the report. (default is [“JTAG”]).

    Returns

      DiagnosticResults

  stress(categories=['JTAG'], seconds=60, stop_on_error=True)

    Runs the available stress tests.

    Run stress tests for the specified amount of time. The aggregate of the results will be returned. If stop_on_error is True and an error occurs then details about the error will be returned instead.

    Parameters

      - categories (list) – a list of the categories to include in the report. (default is [“JTAG”]).

      - seconds (int) – the number of seconds to run for. This is divided evenly among the selected categories. (default is 60)

      - stop_on_error (bool) – if true the stress execution will end once an error is detected even if the specified time hasn’t elapsed yet. (default is True)

    Returns

      DiagnosticResults

# Logging

## IPC CLI Debug Logging

The following functions are documented as being a part of the LoggerManager class. However, all of these functions are available via:

    ipc.logger.<function>

The most frequently used debug configuration commands will be:

    ipc.logger.level("ipc","debugall") # to turn on ALL debug information for the IPC CLI
    ipc.logger.echo(True) # to echo the output to the screen
    ipc.logger.setFile("path_to_log.log") # to send out put to the file
    ipc.logger.openipc_echo(True) # to echo the output to the Open IPC log files
    ... do something interesting
    ipc.logger.reset() # put all logging back to defaults

For the CLI logging with debugall you will typically see at least three log messages. CALLER, ENTER, and EXIT.

> - The CALLER should show the first call outside of the ipccli that called the function in the ipccli.

> - The ENTER will show the value of the parameters passed in to the ipccli function.

> - The EXIT will show the code leaving the ipccli function and the value of any data that was created.

For Example:

    >>> ipc.threads[0].irdrscan(2,32)
    CALLER: File "<stdin>", line 1, in <module>
    ENTER: irdrscan(device=0x10003e8L,instruction=0x02, bitCount=32, data=None, writeData=None)
    EXIT : irdrscan result = [32b] 0x0A3CA013
    [32b] 0x0A3CA013

Here is the complete list of functions available via ipc.logger.<function_name>:

class LoggerManager

  Contains all the functions for managing log files within the cli.

  closeFile()

    Stop logging from going to file.

  echo(echoOn=None)

    Enable logging debug information to the screen (you must use level() to set which loggers are enabled for debug).

    Parameters

      echoOn (bool) – a boolean indicating whether logging is to be echoed to the screen (default is None).

    Returns

      The current value of echoOn, if None is passed to the method.

  getLogger(loggername)

    Used by modules to get a new/existing logger instance that will be tied to the IPC.

    Loggers that go through this call will be enabled/disabled via the other output functions in this IPC CLI.

    Parameters

      loggername (str) – the name of the logger to get

    Returns

      the specified logger instance

  getLoggerNames(relative=False)

    Return a list of the known loggers for the cli.

    Parameters

      relative (bool) – used to return whether to only return logger names relative to the base logger name

    Returns

      a list of logger names

  level(loggername=None, loglevel=None)

    Used to choose whether additional logging information will be enabled. You still have to use “echo()” or setFile()” to determine whether the logging goes to the screen or to a file.

    Parameters

      - loggername (str) – name of logger to enable.

      - loglevel (str) – level of information to output.

    - if no parameters are specified, then the current loggers are displayed.

    - if only loglevel is specified, then ALL loggers will be set to that level.

    - if only loggername is specified, then the current log level is returned.

    Valid loglevels are:

      - CRITICAL - logs only CRITICAL messages

      - ERROR - logs ERROR and CRITICAL messages

      - NOTSET - logs WARNING, ERROR, and CRITICAL messages

      - WARN, WARNING - logs WARNING, ERROR, and CRITICAL messages

      - INFO - logs RESULT, INFO, WARNING, ERROR, and CRITICAL messages

      - DEBUG - logs RESULT, DEBUG, INFO, WARNING, ERROR, and CRITICAL messages

      - DEBUGALL - logs all messages

      - RESULT <- Default, recommended value. Logs RESULT, WARNING, ERROR, AND CRITICAL messages

      - OFF - reverts the loglevel to the default RESULT level

    Warning

    If you specify WARNING or CRITICAL it will prevent logging and display of most output.

    Raises

      ValueError – if an invalid logger name is passed in

  reset()

    Reset all logging to defaults.

  setFile(filename, filemode='w', maxBytes=0, backupCount=10, logformat='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    Used to log CLI related information to a file.

    Parameters

      - filename (str) – Path to where to write file, default output is the current working directory.

      - filemode (str) – ‘w’ or ‘a’ - to write (default) or append to current file.

      - maxBytes (int) – maximum number of bytes to write before rolling in to a new file.

      - backupCount (int) – if backupCount is zero, rollover never occurs; if backupCount is non-zero, the system will save old log files by appending the extensions ‘.1’, ‘.2’ etc., to the filename. For example, with a backupCount of 5 and a base file name of app.log, you would get app.log, app.log.1, up to app.log.5.

      - logformat (str) – format of information written to log file.

    Returns

      None.

    This function makes use of the logger module’s RotateFileHandler class which is documented here in the standard Python documentation:

    https://docs.python.org/2/library/logging.html

    The logformat choices are documented under the LogRecord options in the standard Python documentation:

    https://docs.python.org/2/library/logging.html#logrecord-attributes

    Some examples of what happens with filemode/maxBytes:

      - filemode -‘a’, maxBytes=0 - append to existing file

      - filemode -‘w’, maxBytes=0 - roll over any existing file, start new one

      - filemode -‘a’, maxBytes=>0 - append to existing one, then rollover at maxBytes

      - filemode -‘w’, maxBytes=>0 - roll over any existing file, start new one, rollover again at maxBytes

  show()

    Display all the loggers that are available and the levels they are at.

    Example:

        >>> ipc.logger.show()
        Logname                        = Loglevel
        -------                        = --------
        ipc                            = RESULT
        state_uarch                    = RESULT
        node                           = RESULT
        bitdata                        = RESULT
        device                         = RESULT
        itpii_import_hook              = RESULT
        breakpoint                     = RESULT
        Debug logging to file is currently: OFF
        Debug logging to screen is currently: OFF

## OpenIPC Debug Logging

The following ipccli commands are intended to allow a user or script access to the logging capabilities implemented within the OpenIPC application. Intended for diagnostic and debug activities. These command are only available when the ipccli is running on top of OpenIPC. Which almost always the case.

In order to gain more insight into internal operations, the OpenIPC implements a logging infrastructure to enable recording of events and operations that occur. These logs may not be useful to end-users, but an OpenIPC developer(s) may ask you to turn on these logs if you encounter a problem.

OpenIPC has the concept of Presets which allows for a group of loggers to be enabled using a Preset Name. Presets include “GeneralDebug”, “All”, “Off”, and “Custom”. The names are fairly self explanatory as to what sort of logging output will be provided from each Preset type.

The “GeneralDebug” preset should cover most logging needs and should be selected by default.

The “All” preset is appropriate to set when low level driver, probe hardware or debug transport issues are suspected.

Use the “Off” preset to turn logging off.

If at first you are not sure which Preset to use, select the “GeneralDebug” Preset.

The Preset setting will be persistent across restart and reconnect. OpenIPC application performance will be impacted by logging. Be sure to turn logging “Off” when no longer needed.

The logging output file(s) will be in a .OpenIPC directory within your user directory. During runtime, while the log file(s) are being actively written to disk, they are found in .OpenIPC directory. When the current active file(s) are closed, such as when OpenIPC is shut down or the rollback limit is reached, then the files are moved to the .OpenIPC/Log directory. If OpenIPC crashes then the move will not occur and the most recent written log file will be found in .OpenIPC directory. Again, logs are either found in the .OpenIPC directory or the .OpenIPC/Log directory.

By default, the logging output file(s) will be stored in an .OpenIPC directory within your OS specific home directory:

> Windows:

>   C:Users<user>.OpenIPC

> Linux:

>   ~/.OpenIPC

> macOS:

>   ~/.OpenIPC

Here is the complete list of functions available via ipc.logger.<function_name> for OpenIPC:

> openipc_echo(echoOn=None)

>   Enable logging to Open IPC log files when echoOn is `True` (you must use level() to set which loggers are enabled for debug). Disables logging to Open IPC log files when echoOn is `False` and returns the current state if echoOn is `None`.

>   Open IPC uses a logging.xml file to configure its own logging. The Open IPC’s IpcInterface logger must be set to a log level of “Info” or above for log messages from ipccli to be recorded. See Open IPC documentation for further details on configuring Open IPC logging.

>   Args: echoOn (boolean) - see above.

>   Returns: None

> openipc_loadpreset(preset)

>   Load a known logging preset setting that controls the level of detail that OpenIPC will log (logging verbosity).

>   Call the openipc_presetnames() command to get a list of available logging presets.

>   - The “GeneralDebug” preset should cover most logging needs and should be selected by default.

>   - The “All” preset is appropriate to set when low level driver, probe hw or debug transport issues are suspected.

>   - Use the “Off” preset to turn logging off

>   Args: preset (str) - name of an acceptable logging preset

>   Returns: None

> openipc_flush()

>   Write any pending log messages to disk. Then create a new rollback log file for further messages. This typically happens after the session closes, but this can be used to force a flush and new file.

>   Args: None

>   Returns: None

> openipc_clear()

>   Delete the log files in the standard logging directory (free up disk space).

>   Args: None

>   Returns: None

> openipc_archive()

>   Creates an archive zip file containing every log file in the standard logging directory and then removes them from the directory. Intended to easily package log files to hand off to another person.

>   Args: None

>   Returns: None

> openipc_presetnames()

>   Returns a list of acceptable logging preset names that can be loaded when calling openipc_loadpreset()

>   Args: None

>   Returns: list of strings

> openipc_writemessage(message)

>   Writes the specified user message to the OpenIPC log file. Makes it easy to place a marker in the log file to pass specific debug information or to tag the beginning and end of a section of commands of interest.

>   Args: message (str) - message to write to the log

>   Returns: None

> openipc_getloadedpreset()

>   Returns the name of the current loaded logging preset. Some preset will always be loaded.

>   Args: None

>   Returns: a preset name (str)

## IPC CLI STDIO Logging

The following can be used to log all of the output that is being sent to stdout/stderr:

baseaccess.log(filename, accesstype='w')

  Begin logging stdout to a file.

  Parameters

    - filename (str) – name of file to log to.

    - accesstype (str) – ‘w’ - write , or ‘a’ - append.

  This will log the command and its output. In order for this to grab ALL loggers created from the builtin python logging module, the ipccli will need to be imported before the logging module.

  Note

  If run under IPython it will grab stdout writes, but it cannot grab the “out” that is displayed to the terminal.

baseaccess.nolog()

  Turn off logging and close log file which was initiated with the log command.

## IPC CLI Logging - for Developers

The IPC-CLI logging is built on top of the standard Python logging module and is compatible with (and similar to) the PythonSv logging framework. The primary difference is that IPC-CLI logging is built so that all logging using its logging goes through a parent logger. The parent logger then controls the screen or file output. To get a logger that ties in to the CLI logging, a new logger is requested via:

    >>> from ipc import ipc_logging
    >>> log = ipc_logging.getLogger("my script")

This will give the caller a logger that is controlled via the ipc.logger functions, such as echo, setFile, and level. The logger will show up in the ipc.logger.show() function as well.

If a script wants its own logging with its own file, then it is recommended to use the python logging module directly or to use the PythonSv logging.

How does the cli_logging work? It makes all of the logging objects child loggers such that the ipc logger is really named ipccli.ipc. The bitdata logger is really ipccli.bitdata. When we set ipccli.ipc to debugall, then that allows the messages to get to the ipccli logger. Then ipccli will log to the screen or file depending on any echo() or setFile() calls that have been made.