mirror of
https://github.com/Quad4-Software/Reticulum-Go
synced 2026-08-29 23:48:44 -04:00
122 lines
3.5 KiB
Go
122 lines
3.5 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright (c) 2024-2026 Quad4.io
|
|
|
|
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"runtime"
|
|
"time"
|
|
|
|
"quad4/reticulum-go/pkg/debug"
|
|
"quad4/reticulum-go/pkg/rnsutil"
|
|
)
|
|
|
|
// RunDebug prints effective runtime diagnostics via shared-instance RPC.
|
|
func RunDebug(args []string, opt ...Options) int {
|
|
stdout, stderr := cliIO(opt)
|
|
fs := flag.NewFlagSet("debug", flag.ContinueOnError)
|
|
fs.SetOutput(stderr)
|
|
configDir := fs.String("config", "", "path to config directory")
|
|
jsonOut := fs.Bool("json", false, "emit JSON")
|
|
rates := fs.Bool("rates", false, "include rate table")
|
|
timeout := fs.Duration("timeout", 10*time.Second, "RPC timeout")
|
|
if err := fs.Parse(args); err != nil {
|
|
return 2
|
|
}
|
|
|
|
cfg, err := rnsutil.LoadConfigDir(*configDir)
|
|
if err != nil {
|
|
fmt.Fprintf(stderr, "config: %v\n", err)
|
|
return 1
|
|
}
|
|
|
|
type dump struct {
|
|
ConfigPath string `json:"config_path"`
|
|
LogLevel int `json:"log_level"`
|
|
DebugLevel int `json:"debug_level"`
|
|
GOOS string `json:"goos"`
|
|
GOARCH string `json:"goarch"`
|
|
RPCAddr string `json:"rpc_addr,omitempty"`
|
|
TransportID string `json:"transport_id,omitempty"`
|
|
UptimeSec float64 `json:"uptime_sec,omitempty"`
|
|
InterfaceN int `json:"interfaces,omitempty"`
|
|
RateTableLen int `json:"rate_table_len,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
out := dump{
|
|
ConfigPath: cfg.ConfigPath,
|
|
LogLevel: cfg.LogLevel,
|
|
DebugLevel: debug.GetDebugLevel(),
|
|
GOOS: runtime.GOOS,
|
|
GOARCH: runtime.GOARCH,
|
|
}
|
|
|
|
client, err := rnsutil.DialRPC(cfg, nil)
|
|
if err != nil {
|
|
out.Error = err.Error()
|
|
if *jsonOut {
|
|
enc := json.NewEncoder(stdout)
|
|
enc.SetIndent("", " ")
|
|
_ = enc.Encode(out)
|
|
return 1
|
|
}
|
|
fmt.Fprintf(stderr, "rpc: %v\n", err)
|
|
fmt.Fprintf(stdout, "config_path=%s log_level=%d goos=%s goarch=%s\n",
|
|
out.ConfigPath, out.LogLevel, out.GOOS, out.GOARCH)
|
|
return 1
|
|
}
|
|
client.SetTimeout(*timeout)
|
|
out.RPCAddr = client.Addr()
|
|
|
|
stats, err := client.GetInterfaceStats()
|
|
if err != nil {
|
|
out.Error = err.Error()
|
|
} else {
|
|
out.InterfaceN = len(stats.Interfaces)
|
|
out.UptimeSec = stats.TransportUptime
|
|
out.TransportID = rnsutil.PrettyHex(stats.TransportID)
|
|
}
|
|
|
|
if *rates {
|
|
var raw any
|
|
if err := client.Call(map[string]any{"get": "rate_table"}, &raw); err == nil {
|
|
switch v := raw.(type) {
|
|
case []any:
|
|
out.RateTableLen = len(v)
|
|
case []map[string]any:
|
|
out.RateTableLen = len(v)
|
|
}
|
|
}
|
|
}
|
|
|
|
if *jsonOut {
|
|
enc := json.NewEncoder(stdout)
|
|
enc.SetIndent("", " ")
|
|
if err := enc.Encode(out); err != nil {
|
|
fmt.Fprintf(stderr, "json: %v\n", err)
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
fmt.Fprintf(stdout, "%s : %s\n", infoMsg(stdout, "config_path "), out.ConfigPath)
|
|
fmt.Fprintf(stdout, "%s : %d\n", infoMsg(stdout, "log_level "), out.LogLevel)
|
|
fmt.Fprintf(stdout, "%s : %d\n", infoMsg(stdout, "debug_level "), out.DebugLevel)
|
|
fmt.Fprintf(stdout, "%s : %s/%s\n", infoMsg(stdout, "platform "), out.GOOS, out.GOARCH)
|
|
fmt.Fprintf(stdout, "%s : %s\n", infoMsg(stdout, "rpc_addr "), out.RPCAddr)
|
|
if out.Error != "" {
|
|
fmt.Fprintf(stdout, "%s : %s\n", errMsg(stdout, "rpc_error "), out.Error)
|
|
return 1
|
|
}
|
|
fmt.Fprintf(stdout, "%s : %s\n", infoMsg(stdout, "transport_id"), out.TransportID)
|
|
fmt.Fprintf(stdout, "%s : %.1f\n", infoMsg(stdout, "uptime_sec "), out.UptimeSec)
|
|
fmt.Fprintf(stdout, "%s : %d\n", infoMsg(stdout, "interfaces "), out.InterfaceN)
|
|
if *rates {
|
|
fmt.Fprintf(stdout, "%s : %d entries\n", infoMsg(stdout, "rate_table "), out.RateTableLen)
|
|
}
|
|
return 0
|
|
}
|