# Debug

## Summary

This page contains the source code for the `debug`  helper class, along with examples on how to use it.&#x20;

If you just want to log something, check [Logs & Debug](/cyber-engine-tweaks/first-steps/logs-debug.md).

## What does this class do?

* Prints one or multiple objects into [CET Console](/cyber-engine-tweaks/console/console.md)
* Prints one or multiple objects into [Individual Mod Logs](/cyber-engine-tweaks/first-steps/logs-debug.md#individual-mod-logs) file
* Pretty-print `table` (with indent)
* Handle `boolean`, `nil`, `string` and other classic types
* Parse `userdata` via `GameDump()` or `Dump()` if possible
* Parse `CName` via `NameToString()` if possible

## Source code

```lua
debug = {

    -- log
    log = function(...)

        spdlog.info(debug.parse(...))

    end,

    -- print
    print = function(...)

        print(debug.parse(...))

    end,

    -- parse arguments
    parse = function(...)

        local args = {}
        for _, v in pairs{debug.null(...)} do
            table.insert(args, debug.parseDeep(v))
        end

        local output = ""
        for i, value in pairs(args) do
            output = output .. tostring(value)
            if i ~= #args then
                output = output .. " "
            end
        end

        return output

    end,

    -- parse deep table
    parseDeep = function(t, max, depth)

        -- convert nil to 'nil'
        t = debug.null(t)

        if type(t) ~= 'table' then

            if type(t) == 'userdata' then
                t = debug.parseUserData(t)
            end

            return t
        end

        max = max or 63
        depth = depth or 4

        local dumpStr = '{\n'
        local indent = string.rep(' ', depth)

        for k, v in pairs(t) do

            -- vars
            local ktype = type(k)
            local vtype = type(v)
            local vstr = ''

            -- key
            local kstr = ''
            if ktype == 'string' then
                kstr = string.format('[%q] = ', k)
            end

            -- string
            if vtype == 'string' then
                vstr = string.format('%q', v)

            -- table
            elseif vtype == 'table' then

                if depth < max then
                    vstr = debug.parseDeep(v, max, depth + 4)
                end

            -- userdata
            elseif vtype == 'userdata' then
                vstr = debug.parseUserData(v)

            -- thread (do nothing)
            elseif vtype == 'thread' then

            -- else
            else
                vstr = tostring(v)
            end

            -- format dump
            if vstr ~= '' then
                dumpStr = string.format('%s%s%s%s,\n', dumpStr, indent, kstr, vstr)
            end
        end

        -- unindent
        local unIndent = indent:sub(1, -5)

        -- return
        return string.format('%s%s}', dumpStr, unIndent)

    end,

    -- parse userdata
    parseUserData = function(t)

        local tstr = tostring(t)

        if tstr:find('^ToCName{') then
            tstr = NameToString(t)
        elseif tstr:find('^userdata:') or tstr:find('^sol%.') then

            local gdump = false
            local ddump = false
            pcall(function() gdump = GameDump(t) end)
            pcall(function() ddump = Dump(t, true) end)

            if gdump then
                tstr = GameDump(t)
            elseif ddump then
                tstr = ddump
            end
        end

        return tstr

    end,

    -- convert nil into 'nil'
    null = function(...)

        local t, n = {...}, select('#', ...)

        for k = 1, n do
            local v = t[k]
            if     v == debug.null then t[k] = 'nil'
            elseif v == nil  then t[k] = debug.null
            end
        end

        return (table.unpack or unpack)(t, 1, n)
    end,

}
```

## Definitions

Prints to [CET Console](/cyber-engine-tweaks/console/console.md), similar to [print()](/cyber-engine-tweaks/cet-functions/misc/debug-functions.md#print) function.

```swift
debug.print(obj: object [, obj2, ...]) -> nil
```

Write in [Individual Mod Logs](/cyber-engine-tweaks/first-steps/logs-debug.md#individual-mod-logs) file. eg, `<`[`cet_path`](#user-content-fn-1)[^1]`>/mods/my_mod/my_mod.log`. Similar to [spdlog](/cyber-engine-tweaks/cet-functions/misc/debug-functions.md).

```swift
debug.log(obj: object [, obj2, ...]) -> nil
```

## Usage example

{% code title="init.lua" %}

```lua
local myTable = {
    var = true,
    enabled = false,
    subTable = {
        player = Game.GetPlayer(),
        stats = Game.GetStatsSystem()
    }
}

debug.log('myTable:', myTable)
```

{% endcode %}

{% code title="my\_mod.log" %}

```
[13:49:03] myTable: {
    ["var"] = true,
    ["enabled"] = false,
    ["subTable"] = {
        ["player"] = PlayerPuppet[ customCameraTarget:ECCTV_OnlyOnscreen, ...]
        ["stats"] = gameStatsSystem[ ],
    },
}
```

{% endcode %}

[^1]: The directory where Cyber Engine Tweaks is installed.

    Usually: C:/Program Files (x86)/Steam/steamapps/common/Cyberpunk 2077/bin/x64/plugins/cyber\_engine\_tweaks


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.redmodding.org/cyber-engine-tweaks/snippets-examples/utilities/debug.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
