debug.gno
2.90 Kb · 93 lines
1// Package debug provides utilities for logging and displaying debug information
2// 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 debug
11
12import (
13 "chain/runtime"
14 "chain/runtime/unsafe"
15 "time"
16
17 "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)
22
23// Debug encapsulates debug information, including logs and metadata.
24type Debug struct {
25 Logs []string
26 HideMetadata bool
27}
28
29// 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}
33
34// 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 }
40
41 var content string
42
43 if d.Logs != nil {
44 content += md.H3("Logs")
45 content += md.BulletList(d.Logs)
46 }
47
48 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 }
61
62 if content == "" {
63 return ""
64 }
65
66 return md.CollapsibleSection("debug", content)
67}
68
69// 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}
74
75// 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}
81
82// 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}