
:orphan:

.. _ZES_extension_info_logs:

=====================
 Info Logs Extension
=====================

.. rst-class:: ext-version

*Introduced in Level Zero version 1.19*

API
----
* Enumerations

    * :ref:`zes-info-logs-ext-version-t`
    * :ref:`zes-info-log-type-ext-t`
    * :ref:`zes-info-log-format-ext-t`
    * :ref:`zes-info-log-record-type-ext-t`

* Handles

    * zes_info_log_handle_t
    * zes_info_log_instance_handle_t

* Structures

    * :ref:`zes-info-log-ext-properties-t`
    * :ref:`zes-info-log-instance-ext-desc-t`
    * :ref:`zes-info-log-metadata-ext-t`
    * :ref:`zes-info-log-read-status-ext-t`

* Functions

    * :ref:`zesDriverEnumInfoLogsExt`
    * :ref:`zesInfoLogGetPropertiesExt`
    * :ref:`zesInfoLogCreateInstanceExt`
    * :ref:`zesInfoLogInstanceReadWithMetadataExt`
    * :ref:`zesInfoLogInstancePeekWithMetadataExt`
    * :ref:`zesInfoLogInstanceDeleteExt`

* Macros

    * ZES_INFO_LOGS_EXT_NAME

Info Logs Overview
~~~~~~~~~~~~~~~~~~

An info log is a stream of records reported by the driver, where each record describes
an error or another event of interest that occurred on one of the devices managed by
that driver.

Info logs are driver scoped: a single info log may carry records generated by any of the
devices managed by the driver. The device that generated a record is identified by the
PCI address and the UUID reported in the metadata of that record.

The format of the records is reported by :ref:`zesInfoLogGetPropertiesExt`\. Records in
``:ref:`ZES_INFO_LOG_FORMAT_EXT_CPER <zes-info-log-format-ext-t>`\`` format are UEFI Common Platform Error Records; the
extension returns them as opaque binary data and the application is responsible for
decoding them.

Enumerating Info Logs and Querying Properties
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. parsed-literal::

    // Query the number of info logs supported by the driver
    uint32_t logCount = 0;
    :ref:`zesDriverEnumInfoLogsExt`\(hDriver, &logCount, nullptr);

    if (logCount == 0) {
        output("No info logs available\\n");
        return;
    }

    zes_info_log_handle_t* phInfoLogs = (zes_info_log_handle_t*)
        allocate(logCount * sizeof(zes_info_log_handle_t));
    :ref:`zesDriverEnumInfoLogsExt`\(hDriver, &logCount, phInfoLogs);

    // Query the properties of the first info log
    :ref:`zes-info-log-ext-properties-t` logProps = {};
    logProps.stype = :ref:`ZES_STRUCTURE_TYPE_INFO_LOG_EXT_PROPERTIES <zes-structure-type-t>`\;
    logProps.pNext = nullptr;

    :ref:`zesInfoLogGetPropertiesExt`\(phInfoLogs[0], &logProps);

    output("Info log type: %u, format: %u\\n",
           logProps.infoLogType, logProps.infoLogFormat);
    output("Named collection instances supported: %s\\n",
           logProps.isNamedInstanceSupported ? "yes" : "no");
    output("Peek supported: %s\\n",
           logProps.isPeekDataSupported ? "yes" : "no");

Collecting and Reading Records
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. parsed-literal::

    // Request a 256 KB collection buffer
    uint32_t bufferSizeInKb = 256;

    :ref:`zes-info-log-instance-ext-desc-t` desc = {};
    desc.stype = :ref:`ZES_STRUCTURE_TYPE_INFO_LOG_INSTANCE_EXT_DESC <zes-structure-type-t>`\;
    desc.pNext = nullptr;
    desc.pBufferSizeInKb = &bufferSizeInKb;

    // Named instances require isNamedInstanceSupported == true
    const char* pInstanceName =
        logProps.isNamedInstanceSupported ? "my_collection" : nullptr;

    zes_info_log_instance_handle_t hInstance = nullptr;
    if (:ref:`zesInfoLogCreateInstanceExt`\(phInfoLogs[0], pInstanceName, &desc, &hInstance)
            != :ref:`ZE_RESULT_SUCCESS <ze-result-t>`\) {
        output("Could not start info log collection\\n");
        return;
    }

    // The driver may round the requested values; re-read what was applied
    output("Collecting into %u KB\\n", bufferSizeInKb);
    
    const uint64_t timeoutInMs = 500;

    // Size a working buffer once
    const uint32_t bufferSize = 64 * 1024;
    const uint32_t maxRecords = 64;

    uint8_t* pBuffer = (uint8_t*) allocate(bufferSize);
    :ref:`zes-info-log-metadata-ext-t`\* pDescriptors = (:ref:`zes-info-log-metadata-ext-t`\*)
        allocate(maxRecords * sizeof(:ref:`zes-info-log-metadata-ext-t`\));

    ze_bool_t hasDataToRead = true;
    while (hasDataToRead) {
        uint32_t size = bufferSize;
        uint32_t recordCount = maxRecords;

        for (uint32_t i = 0; i < maxRecords; i++) {
            pDescriptors[i].stype = :ref:`ZES_STRUCTURE_TYPE_INFO_LOG_METADATA_EXT <zes-structure-type-t>`\;
            pDescriptors[i].pNext = nullptr;
        }

        :ref:`zes-info-log-read-status-ext-t` readStatus = {};
        readStatus.stype = :ref:`ZES_STRUCTURE_TYPE_INFO_LOG_READ_STATUS_EXT <zes-structure-type-t>`\;
        readStatus.pNext = nullptr;
        
        :ref:`ze-result-t` result = :ref:`zesInfoLogInstanceReadWithMetadataExt`\(
            hInstance, timeoutInMs, &size, pBuffer,
            &recordCount, pDescriptors, &readStatus);

        if (result != :ref:`ZE_RESULT_SUCCESS <ze-result-t>` &&
            result != :ref:`ZE_RESULT_WARNING_DROPPED_DATA <ze-result-t>`\) {
            output("Could not read info log records\\n");
            break;
        }

        if (result == :ref:`ZE_RESULT_WARNING_DROPPED_DATA <ze-result-t>`\) {
            // The collection buffer overflowed. Consider a larger pBufferSizeInKb
            // or reading more often.
            if (readStatus.droppedRecordCount == UINT32_MAX) {
                output("Warning: records were dropped, count unknown\\n");
            } else {
                output("Warning: %u records dropped\\n",
                       readStatus.droppedRecordCount);
            }
        }

        for (uint32_t i = 0; i < recordCount; i++) {
            output("Record %u: device %04x:%02x:%02x.%x, timestamp %llu ns, %u bytes\\n",
                   i, pDescriptors[i].address.domain, pDescriptors[i].address.bus,
                   pDescriptors[i].address.device, pDescriptors[i].address.function,
                   pDescriptors[i].timestamp, pDescriptors[i].lengthOfData);

            switch (pDescriptors[i].recordType) {
            case :ref:`ZES_INFO_LOG_RECORD_TYPE_EXT_ERROR_RECOVERABLE <zes-info-log-record-type-ext-t>`\:
                escalate(&pDescriptors[i]);
                break;
            case :ref:`ZES_INFO_LOG_RECORD_TYPE_EXT_ERROR_CORRECTED <zes-info-log-record-type-ext-t>`\:
            case :ref:`ZES_INFO_LOG_RECORD_TYPE_EXT_INFORMATIONAL <zes-info-log-record-type-ext-t>`\:
                break;
            default:
                // Includes values added by a later version of this extension
                break;
            }

            const uint8_t* pRecord = pBuffer + pDescriptors[i].offset;
            process(pRecord, pDescriptors[i].lengthOfData);
        }

        hasDataToRead = readStatus.hasDataToRead;
    }

    free(pDescriptors);
    free(pBuffer);

    // Cleanup    
    :ref:`zesInfoLogInstanceDeleteExt`\(hInstance);
    free(phInfoLogs);
