mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
214 lines
5.3 KiB
Go
214 lines
5.3 KiB
Go
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
package relayercmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/luxfi/cli/v2/pkg/cobrautils"
|
|
"github.com/luxfi/cli/v2/pkg/contract"
|
|
"github.com/luxfi/cli/v2/pkg/models"
|
|
"github.com/luxfi/cli/v2/pkg/networkoptions"
|
|
"github.com/luxfi/cli/v2/pkg/utils"
|
|
sdkutils "github.com/luxfi/cli/v2/sdk/utils"
|
|
"github.com/luxfi/node/v2/v2/utils/logging"
|
|
|
|
"github.com/jedib0t/go-pretty/v6/table"
|
|
"github.com/mitchellh/go-wordwrap"
|
|
"github.com/spf13/cobra"
|
|
"golang.org/x/exp/maps"
|
|
)
|
|
|
|
var (
|
|
logsNetworkOptions = []networkoptions.NetworkOption{
|
|
networkoptions.Local,
|
|
networkoptions.Testnet,
|
|
}
|
|
raw bool
|
|
last uint
|
|
first uint
|
|
globalNetworkFlags networkoptions.NetworkFlags
|
|
)
|
|
|
|
// lux interchain relayer logs
|
|
func newLogsCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "logs",
|
|
Short: "shows pretty formatted AWM relayer logs",
|
|
Long: "Shows pretty formatted AWM relayer logs",
|
|
RunE: logs,
|
|
Args: cobrautils.ExactArgs(0),
|
|
}
|
|
networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, logsNetworkOptions)
|
|
cmd.Flags().BoolVar(&raw, "raw", false, "raw logs output")
|
|
cmd.Flags().UintVar(&last, "last", 0, "output last N log lines")
|
|
cmd.Flags().UintVar(&first, "first", 0, "output first N log lines")
|
|
return cmd
|
|
}
|
|
|
|
func logs(_ *cobra.Command, _ []string) error {
|
|
network, err := networkoptions.GetNetworkFromCmdLineFlags(
|
|
app,
|
|
"",
|
|
globalNetworkFlags,
|
|
true,
|
|
false,
|
|
logsNetworkOptions,
|
|
"",
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var logLines []string
|
|
logsPath := app.GetLocalRelayerLogPath(network.Kind)
|
|
bs, err := os.ReadFile(logsPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logs := string(bs)
|
|
logLines = strings.Split(logs, "\n")
|
|
if first != 0 {
|
|
if len(logLines) > int(first) {
|
|
logLines = logLines[:first]
|
|
}
|
|
}
|
|
if last != 0 {
|
|
if len(logLines) > int(last) {
|
|
logLines = logLines[len(logLines)-1-int(last):]
|
|
}
|
|
}
|
|
if raw {
|
|
for _, logLine := range logLines {
|
|
logLine = strings.TrimSpace(logLine)
|
|
if len(logLine) != 0 {
|
|
fmt.Println(logLine)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
blockchainIDToBlockchainName, err := getBlockchainIDToBlockchainNameMap(network)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
t := table.NewWriter()
|
|
t.AppendHeader(table.Row{"", "Time", "Chain", "Log"})
|
|
for _, logLine := range logLines {
|
|
logLine = strings.TrimSpace(logLine)
|
|
if len(logLine) != 0 {
|
|
logMap := map[string]interface{}{}
|
|
err := json.Unmarshal([]byte(logLine), &logMap)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
levelEmoji := ""
|
|
levelStr, b := logMap["level"].(string)
|
|
if b {
|
|
levelEmoji, err = utils.LogLevelToEmoji(levelStr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
timeStampStr, b := logMap["timestamp"].(string)
|
|
timeStr := ""
|
|
if b {
|
|
t, err := time.Parse("2006-01-02T15:04:05.000Z0700", timeStampStr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
timeStr = t.Format("15:04:05")
|
|
}
|
|
msg, b := logMap["msg"].(string)
|
|
if !b {
|
|
continue
|
|
}
|
|
logMsg := wordwrap.WrapString(msg, 80)
|
|
logMsgLines := strings.Split(logMsg, "\n")
|
|
logMsgLines = sdkutils.Map(logMsgLines, func(s string) string { return logging.Green.Wrap(s) })
|
|
logMsg = strings.Join(logMsgLines, "\n")
|
|
keys := maps.Keys(logMap)
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
if !sdkutils.Belongs([]string{"logger", "caller", "level", "timestamp", "msg"}, k) {
|
|
logMsg = addAditionalInfo(
|
|
logMsg,
|
|
logMap,
|
|
k,
|
|
k,
|
|
blockchainIDToBlockchainName,
|
|
)
|
|
}
|
|
}
|
|
subnet := getLogSubnet(logMap, blockchainIDToBlockchainName)
|
|
t.AppendRow(table.Row{levelEmoji, timeStr, subnet, logMsg})
|
|
}
|
|
}
|
|
fmt.Println(t.Render())
|
|
|
|
return nil
|
|
}
|
|
|
|
func addAditionalInfo(
|
|
logMsg string,
|
|
logMap map[string]interface{},
|
|
key string,
|
|
outputName string,
|
|
blockchainIDToBlockchainName map[string]string,
|
|
) string {
|
|
value, b := logMap[key].(string)
|
|
if b {
|
|
blockchainName := blockchainIDToBlockchainName[value]
|
|
if blockchainName != "" {
|
|
value = blockchainName
|
|
}
|
|
logMsg = fmt.Sprintf("%s\n %s=%s", logMsg, outputName, value)
|
|
}
|
|
return logMsg
|
|
}
|
|
|
|
func getLogSubnet(
|
|
logMap map[string]interface{},
|
|
blockchainIDToBlockchainName map[string]string,
|
|
) string {
|
|
for _, key := range []string{
|
|
"blockchainID",
|
|
"originBlockchainID",
|
|
"sourceBlockchainID",
|
|
"destinationBlockchainID",
|
|
} {
|
|
value, b := logMap[key].(string)
|
|
if b {
|
|
blockchainName := blockchainIDToBlockchainName[value]
|
|
if blockchainName != "" {
|
|
return blockchainName
|
|
}
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func getBlockchainIDToBlockchainNameMap(network models.Network) (map[string]string, error) {
|
|
blockchainNames, err := app.GetBlockchainNamesOnNetwork(network, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blockchainIDToBlockchainName := map[string]string{}
|
|
for _, blockchainName := range blockchainNames {
|
|
blockchainID, err := contract.GetBlockchainID(app, network, contract.ChainSpec{BlockchainName: blockchainName})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blockchainIDToBlockchainName[blockchainID.String()] = blockchainName
|
|
}
|
|
blockchainID, err := contract.GetBlockchainID(app, network, contract.ChainSpec{CChain: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blockchainIDToBlockchainName[blockchainID.String()] = "c-chain"
|
|
return blockchainIDToBlockchainName, nil
|
|
}
|