The logger global provides formatted logging functions for debugging and monitoring your scripts. All logging uses the fmt library for powerful string formatting.
local player = world:get_local_player()if player then logger.info("Player {}: {} at ({}, {})", player.net_id, player.name, player.position.x, player.position.y )end-- Output: Player 12345: MyName at (50, 30)
event.on("server:Connect", function(ctx) logger.info("Connected to game server")end)event.on("server:Disconnect", function(ctx) logger.warn("Disconnected from game server")end)
event.on("server:SendToServer", function(ctx) if ctx:has_packet() then local pkt = ctx:parse() logger.debug("Outgoing packet type: {}", pkt.type) else local data = ctx:get_data() logger.debug("Raw packet: {} bytes", #data) endend)
command.register("spawn", "Spawn item", function(ctx) if #ctx.args < 1 then logger.error("Usage: /spawn <item_id>") return false end local item_id = tonumber(ctx.args[1]) if not item_id then logger.error("Invalid item ID: {}", ctx.args[1]) return false end logger.info("Spawning item {}", item_id) return trueend)
error - Error conditions that prevent normal operation
Format strings are more readable than concatenation
-- Goodlogger.info("Player {} at position ({}, {})", name, x, y)-- Harder to readlogger.info("Player " .. name .. " at position (" .. x .. ", " .. y .. ")")
Avoid logging sensitive informationDon’t log passwords, tokens, or other sensitive data:
-- Bad - logs passwordlogger.info("Login: user={}, pass={}", username, password)-- Good - omit sensitive datalogger.info("Login attempt: user={}", username)