Shift+F3 debug menu (#18065)

* F3 debug menu

* Some tweaks

* So that escalated

* Update code/controllers/subsystem.dm

* Update code/controllers/subsystem/debugview.dm

* Charlie tweaks
This commit is contained in:
AffectedArc07
2022-06-26 20:10:09 +01:00
committed by GitHub
parent d43eb77b25
commit d538100ceb
34 changed files with 172 additions and 66 deletions
+8 -3
View File
@@ -159,6 +159,9 @@
if(SS_SLEEPING)
state = SS_PAUSING
// Gets extra details for the subsystem stat panes
/datum/controller/subsystem/proc/get_stat_details()
return
//used to initialize the subsystem AFTER the map has loaded
/datum/controller/subsystem/Initialize(start_timeofday)
@@ -172,16 +175,18 @@
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
var/ss_info = get_stat_details()
if(can_fire && !(SS_NO_FIRE & flags))
msg = "[round(cost, 1)]ms | [round(tick_usage, 1)]%([round(tick_overrun, 1)]%) | [round(ticks, 0.1)]\t[msg]"
msg = "[round(cost, 1)]ms | [round(tick_usage, 1)]%([round(tick_overrun, 1)]%) | [round(ticks, 0.1)]\t[ss_info]"
else
msg = "OFFLINE\t[msg]"
msg = "OFFLINE\t[ss_info]"
var/title = name
if(can_fire)
title = "[state_colour()]\[[state_letter()]][title]</font>"
else
title = "\[O][title]"
stat(title, statclick.update(msg))
+2 -2
View File
@@ -8,8 +8,8 @@ SUBSYSTEM_DEF(acid)
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/acid/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/acid/get_stat_details()
return "P:[length(processing)]"
/datum/controller/subsystem/acid/get_metrics()
. = ..()
+3 -2
View File
@@ -46,7 +46,8 @@ SUBSYSTEM_DEF(air)
var/list/currentrun = list()
var/currentpart = SSAIR_DEFERREDPIPENETS
/datum/controller/subsystem/air/stat_entry(msg)
/datum/controller/subsystem/air/get_stat_details()
var/list/msg = list()
msg += "C:{"
msg += "AT:[round(cost_turfs,1)]|"
msg += "EG:[round(cost_groups,1)]|"
@@ -64,7 +65,7 @@ SUBSYSTEM_DEF(air)
msg += "HP:[high_pressure_delta.len]|"
msg += "AS:[active_super_conductivity.len]|"
msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]"
..(msg)
return msg.Join("")
/datum/controller/subsystem/air/get_metrics()
. = ..()
+2 -2
View File
@@ -12,5 +12,5 @@ SUBSYSTEM_DEF(chat_pings)
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/chat_pings/stat_entry()
..("P: [length(chat_datums)]")
/datum/controller/subsystem/chat_pings/get_stat_details()
return "P: [length(chat_datums)]"
+2 -2
View File
@@ -24,8 +24,8 @@ SUBSYSTEM_DEF(dbcore)
offline_implications = "The server will no longer check for undeleted SQL Queries. No immediate action is needed."
/datum/controller/subsystem/dbcore/stat_entry()
..("A: [length(active_queries)]")
/datum/controller/subsystem/dbcore/get_stat_details()
return "A: [length(active_queries)]"
// This is in Initialize() so that its actually seen in chat
/datum/controller/subsystem/dbcore/Initialize()
+81
View File
@@ -0,0 +1,81 @@
SUBSYSTEM_DEF(debugview)
name = "Debug View"
wait = 1 // SS_TICKER subsystem, so wait is in ticks
flags = SS_TICKER|SS_NO_INIT
offline_implications = "Shift+F3 will no longer show a debug view. No immediate action is needed."
/// List of clients currently processing
var/list/client/processing = list()
/datum/controller/subsystem/debugview/fire(resumed)
// Generate debug text
var/list/entries = list()
entries += "CPU: [round(world.cpu, 1)] | MCPU: [round(world.map_cpu, 1)] | FPS/TPS: [world.fps] | Clients: [length(GLOB.clients)] | BYOND: [world.byond_version].[world.byond_build]"
entries += "\[Air] Cost: [round(SSair.cost, 1)]ms | AT: [length(SSair.active_turfs)]"
entries += "\[Debug] Cost: [round(SSdebugview.cost, 1)]ms | P: [length(SSdebugview.processing)]" // meta af (tbf we need to know how much were using)
entries += "\[FP] Cost: [round(SSfastprocess.cost, 1)]ms | P: [length(SSfastprocess.processing)]"
// Snowflakery for SSgarbage
var/list/counts = list()
for(var/list/L in SSgarbage.queues)
counts += length(L)
entries += "\[GC] Cost: [round(SSgarbage.cost, 1)]ms | Q: [counts.Join(",")] H: [SSgarbage.delslasttick] | S: [SSgarbage.gcedlasttick]"
entries += "\[Input] Cost: [round(SSinput.cost, 1)]ms"
entries += "\[Lighting] Cost: [round(SSlighting.cost, 1)]ms | SQ: [length(SSlighting.sources_queue)] | CQ: [length(SSlighting.corners_queue)] | OQ: [length(SSlighting.objects_queue)]"
entries += "\[Machines] Cost: [round(SSmachines.cost, 1)]ms | M: [length(SSmachines.processing)] | P: [length(SSmachines.powernets)]"
entries += "\[Mobs] Cost: [round(SSmobs.cost, 1)]ms | P: [length(GLOB.mob_living_list)]"
entries += "\[Objects] Cost: [round(SSobj.cost, 1)]ms | P: [length(SSobj.processing)]"
entries += "\[Processing] Cost: [round(SSprocessing.cost, 1)]ms | P: [length(SSprocessing.processing)]"
entries += "\[Projectiles] Cost: [round(SSprojectiles.cost, 1)]ms | P: [length(SSprojectiles.processing)]"
entries += "\[Runechat] Cost: [round(SSrunechat.cost, 1)]ms | AM: [SSrunechat.bucket_count] | SQ: [length(SSrunechat.second_queue)]"
entries += "\[TGUI] Cost: [round(SStgui.cost, 1)]ms | P: [length(SStgui.processing_uis)]"
entries += "\[Timer] Cost: [round(SStimer.cost, 1)]ms | B: [SStimer.bucket_count] | P: [length(SStimer.second_queue)] | RST: [SStimer.bucket_reset_count]"
// Do some parsing to format it properly
var/out_text = entries.Join("\n")
var/mty = 480 - 9 * length(entries)
// And update the clients
for(var/client/C as anything in processing)
C.debug_text_overlay.maptext_y = mty
C.debug_text_overlay.maptext = "<span class='maptext' style='background-color: #272727;'>[out_text]</span>"
/datum/controller/subsystem/debugview/proc/start_processing(client/C)
C.debug_text_overlay = new /obj/screen/debugtextholder
C.screen |= C.debug_text_overlay
processing |= C
/datum/controller/subsystem/debugview/proc/stop_processing(client/C)
processing -= C
C.screen -= C.debug_text_overlay
qdel(C.debug_text_overlay)
/obj/screen/debugtextholder
icon = 'icons/mob/screen_full.dmi'
icon_state = "default"
screen_loc = "CENTER-7,CENTER-7"
plane = HUD_PLANE_DEBUGVIEW
maptext_height = 480 // If we ever change view size, increase this
maptext_width = 480
// Make a verb for dumping full SS stats
/client/proc/ss_breakdown()
set name = "SS Info Breakdown"
set category = "Debug"
if(!check_rights(R_DEBUG|R_VIEWRUNTIMES))
return
var/datum/browser/popup = new(usr, "ss_breakdown", "Subsystem Breakdown", 1100, 850)
var/list/html = list()
html += "CPU: [round(world.cpu, 1)] | MCPU: [round(world.map_cpu, 1)] | FPS/TPS: [world.fps] | Clients: [length(GLOB.clients)] | BYOND: [world.byond_version].[world.byond_build]"
html += "--- SS BREAKDOWN ---"
for(var/datum/controller/subsystem/SS as anything in Master.subsystems)
// We dont care about subsystems that arent firing (or are unable to)
if((SS.flags & SS_NO_FIRE) || !SS.can_fire)
continue
html += "[SS.state_colour()]\[[SS.state_letter()]][SS.ss_id]</font>\t[round(SS.cost, 1)]ms | [round(SS.tick_usage, 1)]% | [SS.get_stat_details()]"
popup.set_content(html.Join("<br>"))
popup.open(FALSE)
+2 -2
View File
@@ -8,8 +8,8 @@ SUBSYSTEM_DEF(fires)
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/fires/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/fires/get_stat_details()
return "P:[length(processing)]"
/datum/controller/subsystem/fires/get_metrics()
+9 -8
View File
@@ -41,25 +41,26 @@ SUBSYSTEM_DEF(garbage)
pass_counts[i] = 0
fail_counts[i] = 0
/datum/controller/subsystem/garbage/stat_entry(msg)
/datum/controller/subsystem/garbage/get_stat_details()
var/list/msg = list()
var/list/counts = list()
for(var/list/L in queues)
counts += length(L)
msg += "Queue:[counts.Join(",")] | Del's:[delslasttick] | Soft:[gcedlasttick] |"
msg += "GR:"
msg += "Q:[counts.Join(", ")] | D:[delslasttick] | S:[gcedlasttick] |"
msg += "GCR:"
if(!(delslasttick + gcedlasttick))
msg += "n/a|"
else
msg += "[round((gcedlasttick / (delslasttick + gcedlasttick)) * 100, 0.01)]% |"
msg += "Total Dels:[totaldels] | Soft:[totalgcs] |"
msg += "TD:[totaldels] | TS:[totalgcs] |"
if(!(totaldels + totalgcs))
msg += "n/a|"
else
msg += "TGR:[round((totalgcs / (totaldels + totalgcs)) * 100, 0.01)]% |"
msg += " Pass:[pass_counts.Join(",")]"
msg += " | Fail:[fail_counts.Join(",")]"
..(msg)
msg += "TGCR:[round((totalgcs / (totaldels + totalgcs)) * 100, 0.01)]% |"
msg += " P:[pass_counts.Join(",")]"
msg += " | F:[fail_counts.Join(",")]"
return msg.Join("")
/datum/controller/subsystem/garbage/get_metrics()
. = ..()
+3 -2
View File
@@ -201,11 +201,12 @@ SUBSYSTEM_DEF(ghost_spawns)
if(!next_poll_to_finish || P2.time_left() < next_poll_to_finish.time_left())
next_poll_to_finish = P2
/datum/controller/subsystem/ghost_spawns/stat_entry(msg)
/datum/controller/subsystem/ghost_spawns/get_stat_details()
var/list/msg = list()
msg += "Active: [length(currently_polling)] | Total: [total_polls]"
if(next_poll_to_finish)
msg += " | Next: [DisplayTimeText(next_poll_to_finish.time_left())] ([length(next_poll_to_finish.signed_up)] candidates)"
..(msg)
return msg.Join("")
// The datum that describes one instance of candidate polling
/datum/candidate_poll
+2 -2
View File
@@ -20,8 +20,8 @@ SUBSYSTEM_DEF(http)
active_async_requests = list()
return ..()
/datum/controller/subsystem/http/stat_entry()
..("P: [length(active_async_requests)] | T: [total_requests]")
/datum/controller/subsystem/http/get_stat_details()
return "P: [length(active_async_requests)] | T: [total_requests]"
/datum/controller/subsystem/http/fire(resumed)
for(var/r in active_async_requests)
+2 -4
View File
@@ -9,10 +9,8 @@ SUBSYSTEM_DEF(idlenpcpool)
var/list/currentrun = list()
var/static/list/idle_mobs_by_zlevel[][]
/datum/controller/subsystem/idlenpcpool/stat_entry()
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
var/list/zlist = GLOB.simple_animals[AI_Z_OFF]
..("IdleNPCS:[idlelist.len]|Z:[zlist.len]")
/datum/controller/subsystem/idlenpcpool/get_stat_details()
return "IdleNPCS:[length(GLOB.simple_animals[AI_IDLE])]|Z:[length(GLOB.simple_animals[AI_Z_OFF])]"
/datum/controller/subsystem/idlenpcpool/Initialize(start_timeofday)
idle_mobs_by_zlevel = new /list(world.maxz,0)
+2 -2
View File
@@ -8,8 +8,8 @@ SUBSYSTEM_DEF(lighting)
var/static/list/corners_queue = list() // List of lighting corners queued for update.
var/static/list/objects_queue = list() // List of lighting objects queued for update.
/datum/controller/subsystem/lighting/stat_entry()
..("L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]")
/datum/controller/subsystem/lighting/get_stat_details()
return "L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]"
/datum/controller/subsystem/lighting/get_metrics()
. = ..()
+2 -2
View File
@@ -37,8 +37,8 @@ SUBSYSTEM_DEF(machines)
NewPN.add_cable(PC)
propagate_network(PC,PC.powernet)
/datum/controller/subsystem/machines/stat_entry()
..("Machines: [processing.len]\nPowernets: [powernets.len]\tDeferred: [deferred_powernet_rebuilds.len]")
/datum/controller/subsystem/machines/get_stat_details()
return "Machines: [processing.len] | Powernets: [powernets.len] | Deferred: [deferred_powernet_rebuilds.len]"
/datum/controller/subsystem/machines/proc/process_defered_powernets(resumed = 0)
if(!resumed)
+2 -2
View File
@@ -18,8 +18,8 @@ SUBSYSTEM_DEF(mobs)
cust["processing"] = length(GLOB.mob_living_list)
.["custom"] = cust
/datum/controller/subsystem/mobs/stat_entry()
..("P:[GLOB.mob_living_list.len]")
/datum/controller/subsystem/mobs/get_stat_details()
return "P:[length(GLOB.mob_living_list.len)]"
/datum/controller/subsystem/mobs/Initialize(start_timeofday)
clients_by_zlevel = new /list(world.maxz,0)
+2 -3
View File
@@ -7,9 +7,8 @@ SUBSYSTEM_DEF(npcpool)
var/list/currentrun = list()
/datum/controller/subsystem/npcpool/stat_entry()
var/list/activelist = GLOB.simple_animals[AI_ON]
..("SimpleAnimals:[activelist.len]")
/datum/controller/subsystem/npcpool/get_stat_details()
return "SimpleAnimals: [length(GLOB.simple_animals[AI_ON])]"
/datum/controller/subsystem/npcpool/fire(resumed = FALSE)
+2 -2
View File
@@ -23,8 +23,8 @@ SUBSYSTEM_DEF(overlays)
return ..()
/datum/controller/subsystem/overlays/stat_entry()
..("Ov:[length(queue)]")
/datum/controller/subsystem/overlays/get_stat_details()
return "Ov:[length(queue)]"
/datum/controller/subsystem/overlays/Recover()
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
@@ -11,8 +11,8 @@ SUBSYSTEM_DEF(processing)
var/list/currentrun = list()
offline_implications = "Objects using the default processor will no longer process. Shuttle call recommended."
/datum/controller/subsystem/processing/stat_entry()
..("[stat_tag]:[processing.len]")
/datum/controller/subsystem/processing/get_stat_details()
return "[stat_tag]:[length(processing)]"
/datum/controller/subsystem/processing/get_metrics()
. = ..()
+2 -2
View File
@@ -13,8 +13,8 @@ SUBSYSTEM_DEF(profiler)
/// Time it took to send the stuff down FFI for redis (ms)
var/send_ffi_cost = 0
/datum/controller/subsystem/profiler/stat_entry()
..("F:[round(fetch_cost, 1)]ms | W:[round(write_cost, 1)]ms | SE:[round(send_encode_cost, 1)]ms | SF:[round(send_ffi_cost, 1)]ms")
/datum/controller/subsystem/profiler/get_stat_details()
return "F:[round(fetch_cost, 1)]ms | W:[round(write_cost, 1)]ms | SE:[round(send_encode_cost, 1)]ms | SF:[round(send_ffi_cost, 1)]ms"
/datum/controller/subsystem/profiler/Initialize()
if(!GLOB.configuration.general.enable_auto_profiler)
+2 -2
View File
@@ -13,8 +13,8 @@ SUBSYSTEM_DEF(redis)
offline_implications = "The server will no longer be able to send or receive redis messages. Shuttle call recommended (Potential server crash inbound)."
// SS meta procs
/datum/controller/subsystem/redis/stat_entry()
..("S:[length(subbed_channels)] | Q:[length(queue)] | C:[connected ? "Y" : "N"]")
/datum/controller/subsystem/redis/get_stat_details()
return "S:[length(subbed_channels)] | Q:[length(queue)] | C:[connected ? "Y" : "N"]"
/datum/controller/subsystem/redis/Initialize()
// Connect to cappuccino
+2 -2
View File
@@ -46,8 +46,8 @@ SUBSYSTEM_DEF(runechat)
head_offset = world.time
bucket_resolution = world.tick_lag
/datum/controller/subsystem/runechat/stat_entry(msg)
..("ActMsgs:[bucket_count] SecQueue:[length(second_queue)]")
/datum/controller/subsystem/runechat/get_stat_details()
return "ActMsgs:[bucket_count] SecQueue:[length(second_queue)]"
/datum/controller/subsystem/runechat/fire(resumed = FALSE)
// Store local references to datum vars as it is faster to access them this way
+2 -2
View File
@@ -65,8 +65,8 @@ SUBSYSTEM_DEF(shuttle)
return ..()
/datum/controller/subsystem/shuttle/stat_entry(msg)
..("M:[mobile.len] S:[stationary.len] T:[transit.len]")
/datum/controller/subsystem/shuttle/get_stat_details()
return "M:[length(mobile)] S:[length(stationary)] T:[length(transit)]"
/datum/controller/subsystem/shuttle/proc/initial_load()
for(var/obj/docking_port/D in world)
+2 -2
View File
@@ -9,8 +9,8 @@ SUBSYSTEM_DEF(spacedrift)
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/spacedrift/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/spacedrift/get_stat_details()
return "P:[length(processing)]"
/datum/controller/subsystem/spacedrift/get_metrics()
. = ..()
+2 -2
View File
@@ -25,8 +25,8 @@ SUBSYSTEM_DEF(sun)
return ..()
/datum/controller/subsystem/sun/stat_entry(msg)
..("P:[solars.len]")
/datum/controller/subsystem/sun/get_stat_details()
return "P:[length(solars)]"
/datum/controller/subsystem/sun/fire()
angle = (360 + angle + rate * 6) % 360 // increase/decrease the angle to the sun, adjusted by the rate
+2 -2
View File
@@ -24,8 +24,8 @@ SUBSYSTEM_DEF(tgui)
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
/datum/controller/subsystem/tgui/stat_entry()
..("P:[processing_uis.len]")
/datum/controller/subsystem/tgui/get_stat_details()
return "P:[length(processing_uis)]"
/datum/controller/subsystem/tgui/get_metrics()
. = ..()
+2 -2
View File
@@ -12,8 +12,8 @@ SUBSYSTEM_DEF(throwing)
var/list/currentrun
var/list/processing = list()
/datum/controller/subsystem/throwing/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/throwing/get_stat_details()
return "P:[length(processing)]"
/datum/controller/subsystem/throwing/get_metrics()
. = ..()
@@ -62,8 +62,8 @@ SUBSYSTEM_DEF(tickets)
report += "[num], "
message_staff("<span class='[span_class]'>Tickets [report] have been open for over [TICKET_TIMEOUT / 600] minutes. Changing status to stale.</span>")
/datum/controller/subsystem/tickets/stat_entry()
..("Tickets: [LAZYLEN(allTickets)]")
/datum/controller/subsystem/tickets/get_stat_details()
return "Tickets: [LAZYLEN(allTickets)]"
/datum/controller/subsystem/tickets/proc/checkStaleness()
var/stales = list()
+2 -2
View File
@@ -58,8 +58,8 @@ SUBSYSTEM_DEF(timer)
head_offset = world.time
bucket_resolution = world.tick_lag
/datum/controller/subsystem/timer/stat_entry(msg)
..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]")
/datum/controller/subsystem/timer/get_stat_details()
return "B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]"
/datum/controller/subsystem/timer/proc/dump_timer_buckets(full = TRUE)
var/list/to_log = list("Timer bucket reset. world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")