[UPDATED] Improving Output Log functionality

[Updated System (Post #6) overrides default: print() & warn() so you can use them]

One of the Major bugbears i’ve come to live with working on large projects are the painful to read outputs you often get that make it hard to find what you’re looking for - especially when you’re in a team and not all using the same formatting etc. To address this nagging issue i’ve built a simple, open source module that:

  • Converts all print and warn statements to use the same formatting.
  • Adds the system name (script name)/custom name + environment (client/server) to output.
  • Customizable output template.
  • Supports warn() & print().

In action this module looks like:

How to Use:

The code is really simple, just require the module from ReplicatedStorage (or wherever you choose to put it), then:
Setup New OutputLog:

.new(CustomName,CustomTemplate) 
--// Both Optional, template must include: "%s"

Print Statement to Output Window:

:Warn("Invalid Request") 
:Print("Hello World")
Example Code:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LogModule = require(ReplicatedStorage:WaitForChild("OutputLog"))

local OutputLog = LogModule.new("CustomLocationTag") --// If no input, defaults to environment above the current function’s (script name)
OutputLog:Print("TeStIng sTaTmEnT") --// prints: "[ScriptName Server/Client] Testing statement"
Module Script:
local OutputLog = {}
OutputLog.__index = OutputLog

local RunService = game:GetService("RunService")
local DEFAULT_TEMPLATE = "[%s] "

--// Private Functions \\--

local function EnvironmentCheck()
    if RunService:IsClient() then
        return "Client"
    end
    return "Server"
 end

local function SetupNewOuput(self,text)
    if not text or not self then return error("Print Failed",2) end
    return string.upper(string.sub(text,1,1))..string.lower(string.sub(text,2))
end

--// Public Functions \\--

function OutputLog.new(CustomName,template)
    local self = {}
    
    local locationTag = CustomName or getfenv(2).script.Name
    self.prefix = string.format(template or DEFAULT_TEMPLATE,locationTag.." "..EnvironmentCheck())

    setmetatable(self,OutputLog)
    return self
end

function OutputLog:Print(text)
    print(self.prefix,SetupNewOuput(self,text))
end

function OutputLog:Warn(text)
    warn(self.prefix,SetupNewOuput(self,text))
end

return OutputLog

Feel free to drop any questions in the comments and i’ll do my best to address them (You can set up more than one Custom Name & Output Template within a singular script).

5 Likes

Would be nice to have the ability to overload warn and print globals. I.e local print, warn = require(path.to.OutputLog). Nice module.

1 Like

Great Idea! I don’t intend to put this in the module by default but if you’d like this behaviour you can always do:

local print = function(value)
    OutputLog:Print(value)
end

print("Hello World")

Could just use roblox’s expressive output as it has all the features this has and more and it has pretty much 0 issue and it gives you a clickable text that opens up the script and you can change what you see and stuffs

Robloxs expressive console, while awesome, doesn’t offer any of the above features;
It also has a number of issues:

(Changed my mind :relaxed:) Code for your suggestion can be found below:

Updated System with print, warn override
local OutputLog = {}
OutputLog.__index = OutputLog

local RunService = game:GetService("RunService")
local DEFAULT_TEMPLATE = "[%s] "

--// Private Functions \\--

local function EnvironmentCheck()
	if RunService:IsClient() then
		return "Client"
	end
	return "Server"
end

local function SetupNewOuput(self,text)
	if not text or not self then return error("Print Failed",3) end
	return string.upper(string.sub(text,1,1))..string.lower(string.sub(text,2))
end

--// Public Functions \\--

function OutputLog.new(CustomName,template)
	local self = {}
	
	local locationTag = CustomName or getfenv(2).script.Name
	self.prefix = string.format(template or DEFAULT_TEMPLATE,locationTag.." "..EnvironmentCheck())
	
	setmetatable(self,OutputLog)
	return self:Print(),self:Warn()
end

function OutputLog:Print()
	return function(text)
		print(self.prefix,SetupNewOuput(self,text))
	end
end

function OutputLog:Warn()
	return function(text)
		warn(self.prefix,SetupNewOuput(self,text))
	end
end

return OutputLog

Example with updated module:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LogModule = require(ReplicatedStorage:WaitForChild("OutputLog"))

local print,warn = LogModule.new("InputHandler")

print("Hello World")
warn("Issue Detected")

System now overrides the default roblox globals: print & warn with OutputLog functions.

2 Likes