github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/core/commands/stat.go (about) 1 package commands 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "io" 8 "time" 9 10 humanize "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-humanize" 11 12 cmds "github.com/ipfs/go-ipfs/commands" 13 metrics "github.com/ipfs/go-ipfs/metrics" 14 peer "github.com/ipfs/go-ipfs/p2p/peer" 15 protocol "github.com/ipfs/go-ipfs/p2p/protocol" 16 u "github.com/ipfs/go-ipfs/util" 17 ) 18 19 var StatsCmd = &cmds.Command{ 20 Helptext: cmds.HelpText{ 21 Tagline: "Query IPFS statistics", 22 ShortDescription: ``, 23 }, 24 25 Subcommands: map[string]*cmds.Command{ 26 "bw": statBwCmd, 27 }, 28 } 29 30 var statBwCmd = &cmds.Command{ 31 Helptext: cmds.HelpText{ 32 Tagline: "Print ipfs bandwidth information", 33 ShortDescription: ``, 34 }, 35 Options: []cmds.Option{ 36 cmds.StringOption("peer", "p", "specify a peer to print bandwidth for"), 37 cmds.StringOption("proto", "t", "specify a protocol to print bandwidth for"), 38 cmds.BoolOption("poll", "print bandwidth at an interval"), 39 cmds.StringOption("interval", "i", "time interval to wait between updating output"), 40 }, 41 42 Run: func(req cmds.Request, res cmds.Response) { 43 nd, err := req.InvocContext().GetNode() 44 if err != nil { 45 res.SetError(err, cmds.ErrNormal) 46 return 47 } 48 49 // Must be online! 50 if !nd.OnlineMode() { 51 res.SetError(errNotOnline, cmds.ErrClient) 52 return 53 } 54 55 pstr, pfound, err := req.Option("peer").String() 56 if err != nil { 57 res.SetError(err, cmds.ErrNormal) 58 return 59 } 60 61 tstr, tfound, err := req.Option("proto").String() 62 if err != nil { 63 res.SetError(err, cmds.ErrNormal) 64 return 65 } 66 if pfound && tfound { 67 res.SetError(errors.New("please only specify peer OR protocol"), cmds.ErrClient) 68 return 69 } 70 71 var pid peer.ID 72 if pfound { 73 checkpid, err := peer.IDB58Decode(pstr) 74 if err != nil { 75 res.SetError(err, cmds.ErrNormal) 76 return 77 } 78 pid = checkpid 79 } 80 81 interval := time.Second 82 timeS, found, err := req.Option("interval").String() 83 if err != nil { 84 res.SetError(err, cmds.ErrNormal) 85 return 86 } 87 if found { 88 v, err := time.ParseDuration(timeS) 89 if err != nil { 90 res.SetError(err, cmds.ErrNormal) 91 return 92 } 93 interval = v 94 } 95 96 doPoll, _, err := req.Option("poll").Bool() 97 if err != nil { 98 res.SetError(err, cmds.ErrNormal) 99 return 100 } 101 102 out := make(chan interface{}) 103 res.SetOutput((<-chan interface{})(out)) 104 105 go func() { 106 defer close(out) 107 for { 108 if pfound { 109 stats := nd.Reporter.GetBandwidthForPeer(pid) 110 out <- &stats 111 } else if tfound { 112 protoId := protocol.ID(tstr) 113 stats := nd.Reporter.GetBandwidthForProtocol(protoId) 114 out <- &stats 115 } else { 116 totals := nd.Reporter.GetBandwidthTotals() 117 out <- &totals 118 } 119 if !doPoll { 120 return 121 } 122 select { 123 case <-time.After(interval): 124 case <-req.Context().Done(): 125 return 126 } 127 } 128 }() 129 }, 130 Type: metrics.Stats{}, 131 Marshalers: cmds.MarshalerMap{ 132 cmds.Text: func(res cmds.Response) (io.Reader, error) { 133 outCh, ok := res.Output().(<-chan interface{}) 134 if !ok { 135 return nil, u.ErrCast() 136 } 137 138 polling, _, err := res.Request().Option("poll").Bool() 139 if err != nil { 140 return nil, err 141 } 142 143 first := true 144 marshal := func(v interface{}) (io.Reader, error) { 145 bs, ok := v.(*metrics.Stats) 146 if !ok { 147 return nil, u.ErrCast() 148 } 149 out := new(bytes.Buffer) 150 if !polling { 151 printStats(out, bs) 152 } else { 153 if first { 154 fmt.Fprintln(out, "Total Up\t Total Down\t Rate Up\t Rate Down") 155 first = false 156 } 157 fmt.Fprint(out, "\r") 158 fmt.Fprintf(out, "%s \t\t", humanize.Bytes(uint64(bs.TotalOut))) 159 fmt.Fprintf(out, " %s \t\t", humanize.Bytes(uint64(bs.TotalIn))) 160 fmt.Fprintf(out, " %s/s \t", humanize.Bytes(uint64(bs.RateOut))) 161 fmt.Fprintf(out, " %s/s ", humanize.Bytes(uint64(bs.RateIn))) 162 } 163 return out, nil 164 165 } 166 167 return &cmds.ChannelMarshaler{ 168 Channel: outCh, 169 Marshaler: marshal, 170 Res: res, 171 }, nil 172 }, 173 }, 174 } 175 176 func printStats(out io.Writer, bs *metrics.Stats) { 177 fmt.Fprintln(out, "Bandwidth") 178 fmt.Fprintf(out, "TotalIn: %s\n", humanize.Bytes(uint64(bs.TotalIn))) 179 fmt.Fprintf(out, "TotalOut: %s\n", humanize.Bytes(uint64(bs.TotalOut))) 180 fmt.Fprintf(out, "RateIn: %s/s\n", humanize.Bytes(uint64(bs.RateIn))) 181 fmt.Fprintf(out, "RateOut: %s/s\n", humanize.Bytes(uint64(bs.RateOut))) 182 }