1// Package debug provides utilities for logging and displaying debug information2// within Gno realms. It supports conditional rendering of logs and metadata,3// toggleable via query parameters.4//5// Key Features:6// - Log collection and display using Markdown formatting.7// - Metadata display for realm path, address, and height.8// - Collapsible debug section for cleaner presentation.9// - Query-based debug toggle using `?debug=1`.10package debug1112import (13 "chain/runtime"14 "chain/runtime/unsafe"15 "time"1617 "gno.land/p/moul/md/v0"18 "gno.land/p/moul/mdtable/v0"19 "gno.land/p/moul/realmpath/v0"20 "gno.land/p/nt/ufmt/v0"21)2223// Debug encapsulates debug information, including logs and metadata.24type Debug struct {25 Logs []string26 HideMetadata bool27}2829// Log appends a new line of debug information to the Logs slice.30func (d *Debug) Log(line string) {31 d.Logs = append(d.Logs, line)32}3334// Render generates the debug content as a collapsible Markdown section.35// It conditionally renders logs and metadata if enabled via the `?debug=1` query parameter.36func (d Debug) Render(path string) string {37 if realmpath.Parse(path).Query.Get("debug") != "1" {38 return ""39 }4041 var content string4243 if d.Logs != nil {44 content += md.H3("Logs")45 content += md.BulletList(d.Logs)46 }4748 if !d.HideMetadata {49 content += md.H3("Metadata")50 table := mdtable.Table{51 Headers: []string{"Key", "Value"},52 }53 table.Append([]string{"`std.CurrentRealm().PkgPath()`", string(unsafe.CurrentRealm().PkgPath())})54 table.Append([]string{"`std.CurrentRealm().Address()`", string(unsafe.CurrentRealm().Address())})55 table.Append([]string{"`std.PreviousRealm().PkgPath()`", string(unsafe.PreviousRealm().PkgPath())})56 table.Append([]string{"`std.PreviousRealm().Address()`", string(unsafe.PreviousRealm().Address())})57 table.Append([]string{"`std.ChainHeight()`", ufmt.Sprintf("%d", runtime.ChainHeight())})58 table.Append([]string{"`time.Now().Format(time.RFC3339)`", time.Now().Format(time.RFC3339)})59 content += table.String()60 }6162 if content == "" {63 return ""64 }6566 return md.CollapsibleSection("debug", content)67}6869// Render displays metadata about the current realm but does not display logs.70// This function uses a default Debug struct with metadata enabled and no logs.71func Render(path string) string {72 return Debug{}.Render(path)73}7475// IsEnabled checks if the `?debug=1` query parameter is set in the given path.76// Returns true if debugging is enabled, otherwise false.77func IsEnabled(path string) bool {78 req := realmpath.Parse(path)79 return req.Query.Get("debug") == "1"80}8182// ToggleURL modifies the given path's query string to toggle the `?debug=1` parameter.83// If debugging is currently enabled, it removes the parameter.84// If debugging is disabled, it adds the parameter.85func ToggleURL(path string) string {86 req := realmpath.Parse(path)87 if IsEnabled(path) {88 req.Query.Del("debug")89 } else {90 req.Query.Add("debug", "1")91 }92 return req.String()93}94Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.