mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
100 lines
2.8 KiB
Go
100 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/sagernet/sing-box/daemon"
|
|
"github.com/sagernet/sing/common/byteformats"
|
|
F "github.com/sagernet/sing/common/format"
|
|
|
|
"github.com/spf13/cobra"
|
|
"google.golang.org/protobuf/types/known/emptypb"
|
|
)
|
|
|
|
var commandAPIStatus = &cobra.Command{
|
|
Use: "status",
|
|
Short: "Print the service status",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return runAPIStatus()
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
commandAPIRoot.AddCommand(commandAPIStatus)
|
|
}
|
|
|
|
func runAPIStatus() error {
|
|
clientConn, client, err := createAPIClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer clientConn.Close()
|
|
ctx, cancel := context.WithCancel(globalCtx)
|
|
defer cancel()
|
|
statusStream, err := client.SubscribeStatus(ctx, &daemon.SubscribeStatusRequest{Interval: int64(time.Second)})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var (
|
|
waitGroup sync.WaitGroup
|
|
serviceStatus *daemon.ServiceStatus
|
|
startedAt *daemon.StartedAt
|
|
)
|
|
waitGroup.Go(func() {
|
|
serviceStatusStream, statusErr := client.SubscribeServiceStatus(ctx, &emptypb.Empty{})
|
|
if statusErr != nil {
|
|
return
|
|
}
|
|
serviceStatus, _ = serviceStatusStream.Recv()
|
|
})
|
|
waitGroup.Go(func() {
|
|
startedAt, _ = client.GetStartedAt(ctx, &emptypb.Empty{})
|
|
})
|
|
status, err := statusStream.Recv()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rateStatus, err := statusStream.Recv()
|
|
if err == nil {
|
|
status = rateStatus
|
|
}
|
|
waitGroup.Wait()
|
|
|
|
var state string
|
|
if serviceStatus != nil {
|
|
state = strings.ToLower(serviceStatus.GetStatus().String())
|
|
}
|
|
var uptime string
|
|
if startedAt.GetStartedAt() > 0 {
|
|
uptime = time.Since(time.UnixMilli(startedAt.GetStartedAt())).Truncate(time.Second).String()
|
|
}
|
|
var connections string
|
|
if status.GetTrafficAvailable() {
|
|
connections = F.ToString(status.GetConnectionsIn(), " in / ", status.GetConnectionsOut(), " out")
|
|
} else {
|
|
connections = F.ToString("- in / ", status.GetConnectionsOut(), " out")
|
|
}
|
|
var uplink, downlink string
|
|
if status.GetTrafficAvailable() {
|
|
uplink = F.ToString(byteformats.FormatBytes(uint64(status.GetUplink())), "/s (", byteformats.FormatBytes(uint64(status.GetUplinkTotal())), " total)")
|
|
downlink = F.ToString(byteformats.FormatBytes(uint64(status.GetDownlink())), "/s (", byteformats.FormatBytes(uint64(status.GetDownlinkTotal())), " total)")
|
|
}
|
|
var block blockWriter
|
|
block.addLine("State", state)
|
|
block.addLine("Uptime", uptime)
|
|
block.addLine("Memory", byteformats.FormatMemoryBytes(status.GetMemory()))
|
|
block.addLine("Goroutines", F.ToString(status.GetGoroutines()))
|
|
block.addLine("Connections", connections)
|
|
block.addLine("Uplink", uplink)
|
|
block.addLine("Downlink", downlink)
|
|
if serviceStatus.GetStatus() == daemon.ServiceStatus_FATAL {
|
|
block.addLine("Error", serviceStatus.GetErrorMessage())
|
|
}
|
|
block.flush()
|
|
return nil
|
|
}
|