better proxyReader metrics
Vladimir Bauer
7 years ago
| 3 | 3 |
"bytes"
|
| 4 | 4 |
"fmt"
|
| 5 | 5 |
"io"
|
|
6 |
"io/ioutil"
|
| 6 | 7 |
"strings"
|
| 7 | 8 |
"sync"
|
| 8 | 9 |
"time"
|
|
| 142 | 143 |
}
|
| 143 | 144 |
}
|
| 144 | 145 |
|
| 145 | |
// ProxyReader allows progress tracking against provided io.Reader.
|
|
146 |
// ProxyReader wraps r with metrics required for progress tracking.
|
| 146 | 147 |
func (b *Bar) ProxyReader(r io.Reader) io.Reader {
|
| 147 | |
return &proxyReader{r, b}
|
|
148 |
if r == nil {
|
|
149 |
panic("expect io.Reader, got nil")
|
|
150 |
}
|
|
151 |
rc, ok := r.(io.ReadCloser)
|
|
152 |
if !ok {
|
|
153 |
rc = ioutil.NopCloser(r)
|
|
154 |
}
|
|
155 |
return &proxyReader{rc, b, time.Now()}
|
| 148 | 156 |
}
|
| 149 | 157 |
|
| 150 | 158 |
// ID returs id of the bar.
|
| 6 | 6 |
|
| 7 | 7 |
// proxyReader is io.Reader wrapper, for proxy read bytes
|
| 8 | 8 |
type proxyReader struct {
|
| 9 | |
r io.Reader
|
| 10 | |
b *Bar
|
|
9 |
io.ReadCloser
|
|
10 |
bar *Bar
|
|
11 |
iT time.Time
|
| 11 | 12 |
}
|
| 12 | 13 |
|
| 13 | |
func (s *proxyReader) Read(p []byte) (n int, err error) {
|
| 14 | |
start := time.Now()
|
| 15 | |
n, err = s.r.Read(p)
|
|
14 |
func (pr *proxyReader) Read(p []byte) (n int, err error) {
|
|
15 |
n, err = pr.ReadCloser.Read(p)
|
| 16 | 16 |
if n > 0 {
|
| 17 | |
s.b.IncrBy(n, time.Since(start))
|
|
17 |
pr.bar.IncrBy(n, time.Since(pr.iT))
|
|
18 |
pr.iT = time.Now()
|
| 18 | 19 |
}
|
| 19 | 20 |
return
|
| 20 | 21 |
}
|
| 21 | |
|
| 22 | |
func (s *proxyReader) Close() error {
|
| 23 | |
if closer, ok := s.r.(io.Closer); ok {
|
| 24 | |
return closer.Close()
|
| 25 | |
}
|
| 26 | |
return nil
|
| 27 | |
}
|