Skip to main content
The Logger component provides a centralized logging system with multiple output targets: console, files, database, and Discord webhooks. It supports different log levels for filtering and categorizing log messages.

Log Levels

The Logger supports 6 log levels with increasing severity:
LevelMethodUse CaseConsole Color
0LogLegacy/generalDefault
1TraceDetailed debuggingDefault
2InfoGeneral informationBlue
3WarnWarningsYellow
4ErrorErrorsRed
5CriticalCritical failuresBright Red

Method Signature

Important: All logger methods use this signature (not the commonly assumed signature):
COMPONENTS.Logger:MethodName(component, log, flags, data)
Parameters:
NameTypeRequiredDescription
componentstringYesComponent/resource name
logstringYesLog message
flagstableNoOutput flags {console, file, discord, database}
dataanyNoAdditional data to store (database only)

Logging Methods

Info

Log informational message. Example:
-- Server side
COMPONENTS.Logger:Info('MyResource', 'Player joined server')

-- With flags
COMPONENTS.Logger:Info('MyResource', 'Important event occurred', {
    console = true,
    file = true,
    discord = true
})

-- With data
COMPONENTS.Logger:Info('MyResource', 'Transaction completed', {
    console = true,
    database = true
}, {
    amount = 5000,
    from = 'player1',
    to = 'player2'
})

Warn

Log warning message. Example:
-- Server side
COMPONENTS.Logger:Warn('AntiCheat', 'Suspicious activity detected', {
    console = true,
    discord = true
})

Error

Log error message. Example:
-- Server side
COMPONENTS.Logger:Error('Database', 'Failed to save player data', {
    console = true,
    file = true,
    discord = true
}, {
    playerId = 123,
    error = errorMessage
})

Critical

Log critical failure. Example:
-- Server side
COMPONENTS.Logger:Critical('Core', 'System failure detected', {
    console = true,
    file = true,
    discord = {
        embed = true,
        type = 'error',
        content = '@everyone Critical system failure!'
    }
}, {
    system = 'database',
    uptime = os.time()
})

Trace

Log detailed debugging information. Example:
-- Server side
COMPONENTS.Logger:Trace('Inventory', 'Item added to inventory', {
    console = true
}, {
    item = 'water',
    count = 5,
    slot = 3
})

Log (Legacy)

General logging (retained for backward compatibility). Example:
-- Server side
COMPONENTS.Logger:Log('MyResource', 'Generic log message')
Log() method is legacy. Use Info(), Warn(), Error(), etc. instead for proper log level categorization.

Output Flags

The flags parameter controls where logs are output:

Console Output

flags = {
    console = true  -- Print to server console
}
Console Format:
[INFO]  [MyResource] Player joined server
[WARN]  [AntiCheat] Suspicious activity
[ERROR] [Database] Connection failed
Log Level Filter:
  • Controlled by COMPONENTS.Convar.LOGGING.value
  • Only logs >= this level will print to console
  • Configured in server.cfg

File Output

flags = {
    file = true  -- Write to log file
}
File Structure:
logs/
├── MyResource/
│   ├── 2025-01-15.log
│   └── 2025-01-16.log
├── Database/
│   └── 2025-01-15.log
└── AntiCheat/
    └── 2025-01-15.log
File Format:
[INFO]     [02:30:45 PM]    Player joined server
[WARN]     [02:31:12 PM]    Suspicious activity detected
[ERROR]    [02:32:00 PM]    Connection failed
Files are organized by component name and date. New file created daily.

Discord Output

-- Simple Discord webhook
flags = {
    discord = true
}

-- Advanced Discord embed
flags = {
    discord = {
        embed = true,
        type = 'info',  -- or 'success', 'warning', 'error'
        title = 'System Alert',
        description = 'Optional description',
        content = 'Message content',
        webhook = 'https://discord.com/api/webhooks/...'  -- Optional custom webhook
    }
}
Discord Webhook Configuration: Set in server.cfg:
set discord_log_webhook "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"
Embed Colors:
  • trace - Gray
  • info - Blue
  • success - Green
  • warning - Yellow
  • error - Red
  • critical - Bright Red
Example:
COMPONENTS.Logger:Info('AntiCheat', 'Player banned', {
    console = true,
    discord = {
        embed = true,
        type = 'warning',
        title = 'Player Banned',
        description = 'Automatic ban for cheating',
        content = '@here Cheater detected'
    }
}, {
    player = 'PlayerName',
    reason = 'Aimbot detected',
    evidence = 'Screenshot URL'
})

Database Output

flags = {
    database = true
}
Database Storage:
  • Collection: logs
  • Only in production environment
  • Must pass data parameter for context
Document Structure:
{
    date = 1705334400,      -- Unix timestamp
    level = 2,               -- Log level (1-5)
    component = 'MyResource',
    log = 'Transaction completed',
    data = {                 -- Your custom data
        amount = 5000,
        from = 'player1',
        to = 'player2'
    }
}
Database logging only works when GlobalState.IsProduction is true and requires flags.database = true.

Complete Examples

Basic Logging

-- Simple info log to console
COMPONENTS.Logger:Info('MyResource', 'Server started')

-- Warning with file logging
COMPONENTS.Logger:Warn('Security', 'Failed login attempt', {
    console = true,
    file = true
})

-- Error with all outputs
COMPONENTS.Logger:Error('Database', 'Connection lost', {
    console = true,
    file = true,
    discord = true,
    database = true
}, {
    host = 'localhost',
    port = 27017,
    error = errorMessage
})

Player Action Logging

-- Log player purchase
AddEventHandler('shop:server:Purchase', function(itemName, price)
    local src = source
    local player = Fetch:Source(src)
    local char = player:GetData('Character')

    COMPONENTS.Logger:Info('Shop', string.format(
        '%s %s purchased %s for $%d',
        char:GetData('First'),
        char:GetData('Last'),
        itemName,
        price
    ), {
        console = true,
        file = true,
        database = true
    }, {
        characterSID = char:GetData('SID'),
        accountID = player:GetData('AccountID'),
        item = itemName,
        price = price,
        timestamp = os.time()
    })
end)

Anti-Cheat Detection

-- Detect and log cheating
AddEventHandler('anticheat:detection', function(source, cheatType, details)
    local player = Fetch:Source(source)
    local char = player:GetData('Character')

    COMPONENTS.Logger:Critical('AntiCheat', string.format(
        'CHEAT DETECTED: %s by %s %s (SID: %d)',
        cheatType,
        char:GetData('First'),
        char:GetData('Last'),
        char:GetData('SID')
    ), {
        console = true,
        file = true,
        discord = {
            embed = true,
            type = 'critical',
            title = '🚨 Cheat Detection',
            content = '@here Immediate action required',
            description = string.format('**Type:** %s\n**Player:** %s %s\n**Details:** %s',
                cheatType,
                char:GetData('First'),
                char:GetData('Last'),
                details
            )
        },
        database = true
    }, {
        characterSID = char:GetData('SID'),
        accountID = player:GetData('AccountID'),
        cheatType = cheatType,
        details = details,
        playerCoords = GetEntityCoords(GetPlayerPed(source))
    })

    -- Ban player
    DropPlayer(source, 'Banned for cheating: ' .. cheatType)
end)

Best Practices

Use the right level for the right situation:
-- ✅ Good
COMPONENTS.Logger:Info('Shop', 'Purchase completed')
COMPONENTS.Logger:Warn('Security', 'Multiple failed login attempts')
COMPONENTS.Logger:Error('Database', 'Connection failed')
COMPONENTS.Logger:Critical('Core', 'System shutdown imminent')

-- ❌ Bad
COMPONENTS.Logger:Error('Shop', 'Purchase completed')  -- Not an error
COMPONENTS.Logger:Info('Core', 'Database exploded')    -- Too severe for Info
Always pass data parameter for important logs:
-- ✅ Good - includes context
COMPONENTS.Logger:Error('Inventory', 'Failed to add item', {
    console = true,
    database = true
}, {
    characterSID = char:GetData('SID'),
    item = itemName,
    count = count,
    error = errorMessage
})

-- ❌ Bad - no context
COMPONENTS.Logger:Error('Inventory', 'Failed to add item')
Use file logging for high-frequency logs:
-- ✅ Good - file only for frequent logs
COMPONENTS.Logger:Trace('Movement', 'Player moved', {
    console = false,
    file = true
})

-- ❌ Bad - console spam
COMPONENTS.Logger:Info('Movement', 'Player moved', {
    console = true
})

Next Steps

Pro Tip: Create helper functions for common logging patterns:
function LogPlayerAction(component, action, char, data)
    COMPONENTS.Logger:Info(component, string.format(
        '%s %s: %s',
        char:GetData('First'),
        char:GetData('Last'),
        action
    ), {
        console = true,
        file = true,
        database = true
    }, data)
end