Repository: pion/sctp
Pull request #57 (2019-08-22 16:26:43)

Add basic transport stats
bytes sent and received

codecov-io: # [Codecov](https://codecov.io/gh/pion/sctp/pull/57?src=pr&el=h1) Report
> Merging [#57](https://codecov.io/gh/pion/sctp/pull/57?src=pr&el=desc) into [master](https://codecov.io/gh/pion/sctp/commit/bce3726b9d24cc2a47957cfd1382e829c08fdcdc?src=pr&el=desc) will **decrease** coverage by `0.17%`.
> The diff coverage is `33.33%`.

[![Impacted file tree graph](https://codecov.io/gh/pion/sctp/pull/57/graphs/tree.svg?width=650&token=AB8S3U6xR9&height=150&src=pr)](https://codecov.io/gh/pion/sctp/pull/57?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #57      +/-   ##
==========================================
- Coverage   75.79%   75.62%   -0.18%     
==========================================
  Files          43       43              
  Lines        2611     2617       +6     
==========================================
  Hits         1979     1979              
- Misses        509      514       +5     
- Partials      123      124       +1
```


| [Impacted Files](https://codecov.io/gh/pion/sctp/pull/57?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [association.go](https://codecov.io/gh/pion/sctp/pull/57/diff?src=pr&el=tree#diff-YXNzb2NpYXRpb24uZ28=) | `81.08% <33.33%> (-0.48%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pion/sctp/pull/57?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pion/sctp/pull/57?src=pr&el=footer). Last update [bce3726...38bf6d8](https://codecov.io/gh/pion/sctp/pull/57?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/association.go b/association.go
index 9bbd20f..c093b6b 100644
--- a/association.go
+++ b/association.go
@@ -176,6 +176,9 @@ type Association struct {
 
 	name string
 	log  logging.LeveledLogger
+
+	bytesReceived uint64
+	bytesSent     uint64
 }
 
 // Config collects the arguments to createAssociation construction into
@@ -403,6 +406,7 @@ func (a *Association) readLoop() {
 			break
 		}
 
+		atomic.AddUint64(&a.bytesReceived, uint64(n))
 		if err = a.handleInbound(buffer[:n]); err != nil {
 			a.log.Warnf("[%s] %s]", a.name, errors.Wrap(err, "failed to push SCTP packet").Error())
 		}
@@ -427,6 +431,7 @@ loop:
 				a.log.Debugf("[%s] writeLoop ended", a.name)
 				break loop
 			}
+			atomic.AddUint64(&a.bytesSent, uint64(len(raw)))
 		}
 
 		select {
@@ -717,6 +722,16 @@ func (a *Association) getState() uint32 {
 	return atomic.LoadUint32(&a.state)
 }
 
+// BytesSent returns the number of bytes sent
+func (a *Association) BytesSent() uint64 {
+	return atomic.LoadUint64(&a.bytesSent)
+}
+
+// BytesReceived returns the number of bytes received
+func (a *Association) BytesReceived() uint64 {
+	return atomic.LoadUint64(&a.bytesReceived)
+}
+
 func setSupportedExtensions(init *chunkInitCommon) {
 	// TODO RFC5061 https://tools.ietf.org/html/rfc6525#section-5.2
 	// An implementation supporting this (Supported Extensions Parameter)


Test patch:
diff --git a/association_test.go b/association_test.go
index 4802829..0136248 100644
--- a/association_test.go
+++ b/association_test.go
@@ -2091,6 +2091,9 @@ type fakeEchoConn struct {
 	once     sync.Once
 	errClose error
 	mu       sync.Mutex
+
+	bytesSent     uint64
+	bytesReceived uint64
 }
 
 func newFakeEchoConn(errClose error) *fakeEchoConn {
@@ -2106,6 +2109,11 @@ func (c *fakeEchoConn) Read(b []byte) (int, error) {
 	if ok {
 		copy(b, r)
 		c.once.Do(func() { close(c.done) })
+
+		c.mu.Lock()
+		c.bytesReceived += uint64(len(r))
+		c.mu.Unlock()
+
 		return len(r), nil
 	}
 	return 0, io.EOF
@@ -2119,6 +2127,7 @@ func (c *fakeEchoConn) Write(b []byte) (int, error) {
 	default:
 	}
 	c.echo <- b
+	c.bytesSent += uint64(len(b))
 	return len(b), nil
 }
 func (c *fakeEchoConn) Close() error {
@@ -2188,3 +2197,18 @@ func TestRoutineLeak(t *testing.T) {
 		assert.Equal(t, n0, runtime.NumGoroutine(), "goroutine is leaked")
 	})
 }
+
+func TestStats(t *testing.T) {
+	loggerFactory := logging.NewDefaultLoggerFactory()
+
+	conn := newFakeEchoConn(nil)
+	a, err := Client(Config{NetConn: conn, LoggerFactory: loggerFactory})
+	assert.Equal(t, nil, err, "errored to initialize Client")
+
+	<-conn.done
+
+	assert.NoError(t, conn.Close())
+
+	assert.Equal(t, conn.bytesReceived, a.BytesReceived())
+	assert.Equal(t, conn.bytesSent, a.BytesSent())
+}