Skip to content

Commit 1592f18

Browse files
committed
Errors Module
1 parent fd2ed87 commit 1592f18

File tree

5 files changed

+175
-14
lines changed

5 files changed

+175
-14
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ For now, the all modules are currently locked away behind only a usergroup == su
3434
| SQLite Schema | :white_check_mark: | :white_check_mark: |
3535
| SQLite Data | :white_check_mark: | :white_check_mark: |
3636
| SQLite Execute | :white_check_mark: | :white_check_mark: |
37+
| Errors | :white_check_mark: | :white_check_mark: |
3738
| Remote SQL Schema | :x: | :x: |
3839
| Remote SQL Data | :x: | :x: |
3940
| Remote SQL Execute | :x: | :x: |

lua/blobsprofiler/client/cl_blobsprofiler.lua

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ blobsProfiler.viewPropertiesPopup = function(title, data, width, height)
108108
return propertiesFrame
109109
end
110110

111-
blobsProfiler.generateAceEditorPanel = function(parentPanel, content, editorMode, readOnly, startLine)
111+
blobsProfiler.generateAceEditorPanel = function(parentPanel, content, editorMode, readOnly, startLine, highlightLine)
112112
local dhtmlPanel = vgui.Create("DHTML", parentPanel)
113113
content = content or [[print("Hello world!")]]
114114
editorMode = editorMode or "Lua"
@@ -120,6 +120,28 @@ blobsProfiler.generateAceEditorPanel = function(parentPanel, content, editorMode
120120
useModeFile = "mode-sql"
121121
end
122122

123+
local highlightJS = ""
124+
if highlightLine and highlightLine ~= 0 then
125+
highlightJS = [[
126+
var lineNumber = ]].. highlightLine - 1 ..[[;
127+
128+
var Range = ace.require("ace/range").Range;
129+
editor.session.addMarker(new Range(lineNumber, 0, lineNumber, 1), "errorHighlight", "fullLine");
130+
131+
editor.session.setAnnotations([{
132+
row: lineNumber,
133+
column: 0,
134+
//text: "Error: ", // TODO: Pass through error message?
135+
type: "error"
136+
}]);
137+
138+
setTimeout(function() {
139+
editor.scrollToLine(lineNumber, true, true, function() {});
140+
editor.gotoLine(lineNumber);
141+
}, 100); // murder me in my sleep
142+
]]
143+
end
144+
123145
dhtmlPanel:SetHTML([[
124146
<!DOCTYPE html>
125147
<html lang="en">
@@ -128,8 +150,13 @@ blobsProfiler.generateAceEditorPanel = function(parentPanel, content, editorMode
128150
<title>blobsProfiler: Lua Execution</title>
129151
<style type="text/css" media="screen">
130152
#editor {
131-
height: 400px;
132-
width: 100%;
153+
height: 400px;
154+
width: 100%;
155+
}
156+
.errorHighlight {
157+
position: absolute;
158+
background-color: rgba(255, 0, 0, 0.3);
159+
z-index: 20;
133160
}
134161
</style>
135162
</head>
@@ -159,6 +186,8 @@ blobsProfiler.generateAceEditorPanel = function(parentPanel, content, editorMode
159186
},
160187
readOnly: true // Disable this command in read-only mode
161188
});
189+
190+
]].. highlightJS ..[[
162191
</script>
163192
</body>
164193
</html>
@@ -169,7 +198,8 @@ end
169198

170199
blobsProfiler.sourceFrames = {}
171200

172-
local function popupSourceView(sourceContent, frameTitle)
201+
local function popupSourceView(sourceContent, frameTitle, highlightLine)
202+
print("highlightLine", highlightLine)
173203
local sourceFrame = vgui.Create("DFrame")
174204
sourceFrame:SetSize(500,500)
175205
sourceFrame:SetTitle(frameTitle or "View source")
@@ -180,7 +210,7 @@ local function popupSourceView(sourceContent, frameTitle)
180210
startLine = tonumber(startLine)
181211
endLine = tonumber(endLine)
182212

183-
local sourcePanel = blobsProfiler.generateAceEditorPanel(sourceFrame, sourceContent, "Lua", true, startLine)
213+
local sourcePanel = blobsProfiler.generateAceEditorPanel(sourceFrame, sourceContent, "Lua", true, startLine, highlightLine)
184214
sourcePanel:Dock(FILL)
185215

186216
sourcePanel.OnRemove = function()
@@ -207,6 +237,7 @@ net.Receive("blobsProfiler:sendSourceChunk", function()
207237
local requestId = net.ReadString()
208238
local startPos = net.ReadUInt(32)
209239
local chunk = net.ReadString()
240+
local highlightLine = net.ReadUInt(16)
210241

211242
if not receivedSource[requestId] then
212243
receivedSource[requestId] = {
@@ -234,7 +265,7 @@ net.Receive("blobsProfiler:sendSourceChunk", function()
234265

235266
if allChunksReceived then
236267
--local splitRequest = string.Explode(":", requestId)
237-
popupSourceView(combinedSource, requestId)
268+
popupSourceView(combinedSource, requestId, highlightLine)
238269

239270
receivedSource[requestId] = nil -- Clean up the request data
240271
end
@@ -396,6 +427,24 @@ blobsProfiler.Menu.RCFunctions_DEFAULT = {
396427
end,
397428
icon = "icon16/magnifier.png"
398429
}
430+
},
431+
["file"] = {
432+
{
433+
name = "View source",
434+
func = function(ref, node, luaState)
435+
if not string.EndsWith(ref.value.Source, ".lua") then
436+
Derma_Message("Invalid file source: ".. ref.value.Source .."\nOnly Lua files can be read!", "Function view source", "OK")
437+
return
438+
end
439+
440+
net.Start("blobsProfiler:requestSource")
441+
net.WriteString(ref.value.Source)
442+
net.WriteUInt(ref.value.Line, 16)
443+
net.WriteUInt(0, 16)
444+
net.SendToServer()
445+
end,
446+
icon = "icon16/magnifier.png"
447+
}
399448
}
400449
}
401450

@@ -1215,6 +1264,10 @@ concommand.Add("blobsprofiler", function(ply, cmd, args, argStr)
12151264
if getSheet.OnActiveTabChanged then
12161265
getSheet:OnActiveTabChanged(nil, getSheet:GetActiveTab())
12171266
end
1267+
1268+
if moduleTable.OnOpen then
1269+
moduleTable.OnOpen("Client", moduleTable.ClientTab)
1270+
end
12181271
end
12191272

12201273
tabServer.OnActiveTabChanged = function(s, pnlOld, pnlNew)

lua/blobsprofiler/server/sv_blobsprofiler.lua

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ util.AddNetworkString("blobsProfiler:sendSourceChunk")
55

66
util.AddNetworkString("blobsProfiler:requestData")
77

8-
local function SendChunkedString(ply, requestID, largeString)
8+
local function SendChunkedString(ply, requestID, largeString, highlightLine)
99
local chunkSize = 30000 -- If changed, don't forget to change on the client!
1010
local totalLength = #largeString
1111

@@ -15,6 +15,7 @@ local function SendChunkedString(ply, requestID, largeString)
1515
net.WriteString(requestID)
1616
net.WriteUInt(i, 32)
1717
net.WriteString(chunk)
18+
net.WriteUInt(highlightLine or 0, 16) -- ugh
1819
net.Send(ply)
1920
end
2021
end
@@ -26,6 +27,13 @@ net.Receive("blobsProfiler:requestSource", function(l, ply)
2627
local startLine = net.ReadUInt(16)
2728
local endLine = net.ReadUInt(16)
2829

30+
local highlightLine
31+
if startLine ~= 0 and endLine == 0 then
32+
highlightLine = startLine
33+
startLine = 0
34+
endLine = 0
35+
end
36+
2937
if startLine < 0 or endLine < 0 or startLine > endLine then return end
3038

3139
local findFile = file.Open(filePath, "r", "GAME")
@@ -60,7 +68,7 @@ net.Receive("blobsProfiler:requestSource", function(l, ply)
6068

6169
local combinedSource = table.concat(fileContent)
6270
local requestID = string.format("View source: %s (Lines: %i-%i)", filePath, startLine, (endLine == 0 and currentLine) or endLine) -- Generate request ID
63-
SendChunkedString(ply, requestID, combinedSource)
71+
SendChunkedString(ply, requestID, combinedSource, highlightLine)
6472
end)
6573

6674
local transmissionStates = {}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
blobsProfiler.RegisterModule("Errors", {
2+
Icon = "icon16/bug.png",
3+
OrderPriority = 9,
4+
UpdateRealmData = function(luaState)
5+
if luaState == "Client" then
6+
-- we dont need to set, it's automatically set by the OnLuaError hook
7+
else
8+
net.Start("blobsProfiler:requestData")
9+
net.WriteString("Errors")
10+
net.SendToServer()
11+
end
12+
end,
13+
PrepServerData = function()
14+
return blobsProfiler.Server and blobsProfiler.Server.Errors or {}
15+
end,
16+
PreloadClient = true,
17+
PreloadServer = false,
18+
BuildPanel = function(luaState, parentPanel)
19+
blobsProfiler.buildDTree(luaState, parentPanel, "Errors")
20+
end,
21+
OnOpen = function(luaState, parentPanel)
22+
if luaState == "Client" then
23+
blobsProfiler.buildDTree(luaState, parentPanel, "Errors")
24+
end
25+
end,
26+
RefreshButton = "Reload",
27+
FormatNodeName = function(luaState, nodeKey, nodeValue)
28+
if nodeKey == "Last Errored" or nodeKey == "First Errored" then
29+
return nodeKey .. ": ".. os.date("%c", nodeValue)
30+
elseif not istable(nodeValue) then
31+
return nodeKey .. ": ".. tostring(nodeValue)
32+
elseif istable(nodeValue) and nodeValue.Error then
33+
return nodeValue.Error
34+
elseif istable(nodeValue) and nodeValue.fakeVarType == "file" then
35+
return "[" .. nodeValue.Level .. "] " .. nodeValue.Source .. ":" ..nodeValue.Line
36+
end
37+
38+
return nodeKey
39+
end,
40+
FormatNodeIcon = function(luaState, nodeKey, nodeValue)
41+
if nodeKey == "Last Errored" or nodeKey == "First Errored" then
42+
return "icon16/clock.png"
43+
elseif nodeKey == "Count" then
44+
return "icon16/chart_bar.png"
45+
elseif nodeKey == "Stacktrace" then
46+
return "icon16/script_error.png"
47+
elseif nodeKey == "Addon ID" then
48+
return "icon16/plugin_link.png"
49+
elseif istable(nodeValue) and nodeValue.Stacktrace and nodeValue.Count then
50+
return "icon16/bug_error.png"
51+
elseif istable(nodeValue) and nodeValue.fakeVarType == "file" then
52+
return "icon16/page_white_code.png"
53+
end
54+
end
55+
})
56+
57+
local function capitalizeFirstLetter(str)
58+
return (str and str:sub(1, 1):upper() .. str:sub(2):lower()) or str -- are you shitting me
59+
end
60+
61+
hook.Add("OnLuaError", "test", function( err, realm, stack, name, addon_id )
62+
local luaState = capitalizeFirstLetter(realm)
63+
64+
name = name or "Unknown Origin"
65+
err = err or "Unknown Error" -- should this ever happen?
66+
67+
local errorKey = util.CRC(err .. "\n" .. (stack and util.TableToJSON(stack) or "No Stack Trace"))
68+
69+
blobsProfiler[luaState] = blobsProfiler[luaState] or {}
70+
blobsProfiler[luaState].Errors = blobsProfiler[luaState].Errors or {}
71+
blobsProfiler[luaState].Errors[name] = blobsProfiler[luaState].Errors[name] or {}
72+
73+
if not blobsProfiler[luaState].Errors[name][errorKey] then
74+
local genStack
75+
for k, stackDetails in ipairs(stack) do
76+
genStack = genStack or {}
77+
78+
local stackData = {}
79+
stackData.fakeVarType = "file"
80+
stackData.Level = k
81+
stackData.Func = tostring(stackDetails.Function)
82+
stackData.Source = stackDetails.File
83+
stackData.Line = stackDetails.Line
84+
85+
table.insert(genStack, stackData)
86+
end
87+
88+
blobsProfiler[luaState].Errors[name][errorKey] = {
89+
Error = err,
90+
Count = 1,
91+
Stacktrace = genStack,
92+
["Addon ID"] = (tonumber(addon_id) ~= 0) and addon_id or nil,
93+
["First Errored"] = os.time()
94+
}
95+
else
96+
blobsProfiler[luaState].Errors[name][errorKey].Count = blobsProfiler[luaState].Errors[name][errorKey].Count + 1
97+
blobsProfiler[luaState].Errors[name][errorKey]["Last Errored"] = os.time()
98+
end
99+
end)

lua/blobsprofiler/shared/modules/bp_lua.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ blobsProfiler.RegisterSubModule("Lua", "Execute", {
162162
end
163163

164164
if luaState == "Client" then
165-
RunString(value)
165+
RunString(value, "blobsprofiler:lua.execute")
166166
elseif luaState == "Server" then
167167
net.Start("blobsProfiler:sendLua")
168168
net.WriteString(value) -- TODO: allow bigger strings? no biggy for now, needs to be done securely!
@@ -331,7 +331,7 @@ local sum = addNumbers(5, 5)]])
331331
local lcStart = SysTime()
332332
for i=1, numIterations do
333333
local ciStart = SysTime()
334-
RunString(leftCodeContent)
334+
RunString(leftCodeContent, "blobsprofiler:lua.versus_LEFT")
335335
local ciTotal = SysTime() - ciStart
336336

337337
if not lcMax or (ciTotal > lcMax) then lcMax = ciTotal end
@@ -342,7 +342,7 @@ local sum = addNumbers(5, 5)]])
342342
local rcStart = SysTime()
343343
for i=1, numIterations do
344344
local ciStart = SysTime()
345-
RunString(rightCodeContent)
345+
RunString(rightCodeContent, "blobsprofiler:lua.versus_RIGHT")
346346
local ciTotal = SysTime() - ciStart
347347

348348
if not rcMax or (ciTotal > rcMax) then rcMax = ciTotal end
@@ -381,7 +381,7 @@ net.Receive("blobsProfiler:sendLua", function(l, ply)
381381
blobsProfiler.Log(blobsProfiler.L_LOG, ply:Name() .. " (".. ply:SteamID64() ..") sent Lua to the server:")
382382
blobsProfiler.Log(blobsProfiler.L_LOG, luaRun)
383383

384-
RunString(luaRun)
384+
RunString(luaRun, "blobsprofiler:lua.execute")
385385
end)
386386

387387

@@ -400,7 +400,7 @@ net.Receive("blobsProfiler:sendLua_versus", function(l, ply)
400400
local lcStart = SysTime()
401401
for i=1, numIterations do
402402
local ciStart = SysTime()
403-
RunString(luaRunL)
403+
RunString(luaRunL, "blobsprofiler:lua.versus_LEFT")
404404
local ciTotal = SysTime() - ciStart
405405

406406
if not lcMax or (ciTotal > lcMax) then lcMax = ciTotal end
@@ -411,7 +411,7 @@ net.Receive("blobsProfiler:sendLua_versus", function(l, ply)
411411
local rcStart = SysTime()
412412
for i=1, numIterations do
413413
local ciStart = SysTime()
414-
RunString(luaRunR)
414+
RunString(luaRunR, "blobsprofiler:lua.versus_RIGHT")
415415
local ciTotal = SysTime() - ciStart
416416

417417
if not rcMax or (ciTotal > rcMax) then rcMax = ciTotal end

0 commit comments

Comments
 (0)