-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat (dot/telemetry): implement telemetry system.interval message #1528
Changes from 3 commits
d68f7f2
cfa4302
67448d7
ac28587
1c68d46
b35bb3a
cc07fdf
922ac7c
3ab3bc7
4b1ee15
a9ddf04
1cbed8d
6eab866
1292bfa
25d35e4
3caeb27
517a46c
9f60995
54b3233
8735fed
66e85c7
121c7fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -26,11 +26,11 @@ import ( | |||||||||||||||||||||||||||||||||
"time" | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
gssmrmetrics "github.com/ChainSafe/gossamer/dot/metrics" | ||||||||||||||||||||||||||||||||||
"github.com/ChainSafe/gossamer/dot/telemetry" | ||||||||||||||||||||||||||||||||||
"github.com/ChainSafe/gossamer/lib/common" | ||||||||||||||||||||||||||||||||||
"github.com/ChainSafe/gossamer/lib/services" | ||||||||||||||||||||||||||||||||||
"github.com/ethereum/go-ethereum/metrics" | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
log "github.com/ChainSafe/log15" | ||||||||||||||||||||||||||||||||||
"github.com/ethereum/go-ethereum/metrics" | ||||||||||||||||||||||||||||||||||
libp2pnetwork "github.com/libp2p/go-libp2p-core/network" | ||||||||||||||||||||||||||||||||||
"github.com/libp2p/go-libp2p-core/peer" | ||||||||||||||||||||||||||||||||||
"github.com/libp2p/go-libp2p-core/protocol" | ||||||||||||||||||||||||||||||||||
|
@@ -246,6 +246,8 @@ func (s *Service) Start() error { | |||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
go s.logPeerCount() | ||||||||||||||||||||||||||||||||||
go s.publishNetworkTelemetry() | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
@@ -279,6 +281,18 @@ func (s *Service) logPeerCount() { | |||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
func (s *Service) publishNetworkTelemetry() { | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I modified publishNetworkTelemetry as noted above, however when I added |
||||||||||||||||||||||||||||||||||
for { | ||||||||||||||||||||||||||||||||||
o := s.host.bwc.GetBandwidthTotals() | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
telemetry.GetInstance().SendNetworkData(&telemetry.NetworkData{ | ||||||||||||||||||||||||||||||||||
Peers: s.host.peerCount(), | ||||||||||||||||||||||||||||||||||
RateIn: o.RateIn, | ||||||||||||||||||||||||||||||||||
RateOut: o.RateOut, | ||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||
time.Sleep(time.Second * 5) | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we make the duration configurable on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added |
||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
func (s *Service) handleConn(conn libp2pnetwork.Conn) { | ||||||||||||||||||||||||||||||||||
// give new peers a slight weight | ||||||||||||||||||||||||||||||||||
// TODO: do this once handshake is received | ||||||||||||||||||||||||||||||||||
|
@@ -521,6 +535,9 @@ func (s *Service) readStream(stream libp2pnetwork.Stream, peer peer.ID, decoder | |||||||||||||||||||||||||||||||||
_ = stream.Close() | ||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// todo (ed) determine if there are other places to capture data received | ||||||||||||||||||||||||||||||||||
s.host.bwc.LogRecvMessage(int64(tot)) | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all messages received by the network go through this function, and no where else, so having this just here is fine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Excellent, thanks. |
||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ import ( | |
"sync" | ||
"time" | ||
|
||
"github.com/ChainSafe/gossamer/dot/telemetry" | ||
"github.com/ChainSafe/gossamer/dot/types" | ||
"github.com/ChainSafe/gossamer/lib/common" | ||
"github.com/ChainSafe/gossamer/lib/common/optional" | ||
|
@@ -170,6 +171,7 @@ func (q *syncQueue) start() { | |
|
||
go q.benchmark() | ||
go q.prunePeers() | ||
go q.sentBlockIntervalTelemetry() | ||
} | ||
|
||
func (q *syncQueue) syncAtHead() { | ||
|
@@ -356,6 +358,28 @@ func (q *syncQueue) benchmark() { | |
} | ||
} | ||
|
||
func (q *syncQueue) sentBlockIntervalTelemetry() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this function could be just part of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea, I've moved this. |
||
for { | ||
best, err := q.s.blockState.BestBlockHeader() | ||
if err != nil { | ||
continue | ||
} | ||
finalized, err := q.s.blockState.GetFinalizedHeader(0, 0) //nolint | ||
if err != nil { | ||
continue | ||
} | ||
|
||
telemetry.GetInstance().SendBlockIntervalData(&telemetry.BlockIntervalData{ | ||
BestHash: best.Hash(), | ||
BestHeight: best.Number, | ||
FinalizedHash: finalized.Hash(), | ||
FinalizedHeight: finalized.Number, | ||
TXCount: 0, // todo (ed) determine where to get tx count | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this the count of txs in a block, or in the queue? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what they want reported. |
||
UsedStateCacheSize: 0, // todo (ed) determine where to get used_state_cache_size | ||
}) | ||
time.Sleep(time.Second * 5) | ||
} | ||
} | ||
func (q *syncQueue) stringifyResponseQueue() string { | ||
if len(q.responses) == 0 { | ||
return "[empty]" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ import ( | |
"sync" | ||
"time" | ||
|
||
"github.com/ChainSafe/gossamer/lib/common" | ||
"github.com/ChainSafe/gossamer/lib/genesis" | ||
"github.com/gorilla/websocket" | ||
log "github.com/sirupsen/logrus" | ||
|
@@ -33,6 +34,7 @@ type Handler struct { | |
buf bytes.Buffer | ||
wsConn []*websocket.Conn | ||
telemetryLogger *log.Entry | ||
sync.RWMutex | ||
} | ||
|
||
// MyJSONFormatter struct for defining JSON Formatter | ||
|
@@ -100,18 +102,55 @@ func (h *Handler) SendConnection(data *ConnectionData) { | |
"version": data.SystemVersion} | ||
h.telemetryLogger = log.WithFields(log.Fields{"id": 1, "payload": payload, "ts": time.Now()}) | ||
h.telemetryLogger.Print() | ||
h.sendTelemtry() | ||
h.sendTelemetry() | ||
} | ||
|
||
// SendBlockImport sends block imported message to telemetry connection | ||
func (h *Handler) SendBlockImport(bestHash string, height *big.Int) { | ||
payload := log.Fields{"best": bestHash, "height": height.Int64(), "msg": "block.import", "origin": "NetworkInitialSync"} | ||
h.telemetryLogger = log.WithFields(log.Fields{"id": 1, "payload": payload, "ts": time.Now()}) | ||
h.telemetryLogger.Print() | ||
h.sendTelemtry() | ||
h.sendTelemetry() | ||
} | ||
|
||
func (h *Handler) sendTelemtry() { | ||
// NetworkData struct to hold network data telemetry information | ||
type NetworkData struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Struct and all its fields are exported. Is it required? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I've updated this. |
||
Peers int | ||
RateIn float64 | ||
RateOut float64 | ||
} | ||
|
||
// SendNetworkData send network data system.interval message to telemetry connection | ||
func (h *Handler) SendNetworkData(data *NetworkData) { | ||
payload := log.Fields{"bandwidth_download": data.RateIn, "bandwidth_upload": data.RateOut, "msg": "system.interval", "peers": data.Peers} | ||
h.telemetryLogger = log.WithFields(log.Fields{"id": 1, "payload": payload, "ts": time.Now()}) | ||
h.telemetryLogger.Print() | ||
h.sendTelemetry() | ||
} | ||
|
||
// BlockIntervalData struct to hold data for block system.interval message | ||
type BlockIntervalData struct { | ||
BestHash common.Hash | ||
BestHeight *big.Int | ||
FinalizedHash common.Hash | ||
FinalizedHeight *big.Int | ||
TXCount int | ||
UsedStateCacheSize int | ||
} | ||
|
||
// SendBlockIntervalData send block data system interval information to telemetry connection | ||
func (h *Handler) SendBlockIntervalData(data *BlockIntervalData) { | ||
payload := log.Fields{"best": data.BestHash.String(), "finalized_hash": data.FinalizedHash.String(), | ||
"finalized_height": data.FinalizedHeight, "height": data.BestHeight, "msg": "system.interval", "txcount": data.TXCount, | ||
"used_state_cache_size": data.UsedStateCacheSize} | ||
h.telemetryLogger = log.WithFields(log.Fields{"id": 1, "payload": payload, "ts": time.Now()}) | ||
h.telemetryLogger.Print() | ||
h.sendTelemetry() | ||
} | ||
|
||
func (h *Handler) sendTelemetry() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add lock in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the lock should be acquired in the functions calling
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've updated this to add locks and created sender which reads from buffer and sends messages. |
||
h.Lock() | ||
defer h.Unlock() | ||
for _, c := range h.wsConn { | ||
err := c.WriteMessage(websocket.TextMessage, h.buf.Bytes()) | ||
if err != nil { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ import ( | |
"testing" | ||
"time" | ||
|
||
"github.com/ChainSafe/gossamer/lib/common" | ||
"github.com/ChainSafe/gossamer/lib/genesis" | ||
"github.com/gorilla/websocket" | ||
"github.com/stretchr/testify/require" | ||
|
@@ -61,6 +62,32 @@ func TestHandler_SendBlockImport(t *testing.T) { | |
require.Equal(t, expected, lastMessage[:101]) | ||
} | ||
|
||
func TestHandler_SendNetworkData(t *testing.T) { | ||
expected := []byte(`{"id":1,"payload":{"bandwidth_download":2,"bandwidth_upload":3,"msg":"system.interval","peers":1},"ts":`) | ||
GetInstance().SendNetworkData(&NetworkData{ | ||
Peers: 1, | ||
RateIn: 2, | ||
RateOut: 3, | ||
}) | ||
time.Sleep(time.Millisecond) | ||
// note, we only check the first 103 bytes because the remaining bytes are the timestamp, which we can't estimate | ||
require.Equal(t, expected, lastMessage[:103]) | ||
} | ||
|
||
func TestHandler_SendBlockIntervalData(t *testing.T) { | ||
expected := []byte(`{"id":1,"payload":{"best":"0x07b749b6e20fd5f1159153a2e790235018621dd06072a62bcd25e8576f6ff5e6","finalized_hash":"0x687197c11b4cf95374159843e7f46fbcd63558db981aaef01a8bac2a44a1d6b2","finalized_height":32256,"height":32375,"msg":"system.interval","txcount":2,"used_state_cache_size":1886357},"ts":`) | ||
GetInstance().SendBlockIntervalData(&BlockIntervalData{ | ||
BestHash: common.MustHexToHash("0x07b749b6e20fd5f1159153a2e790235018621dd06072a62bcd25e8576f6ff5e6"), | ||
BestHeight: big.NewInt(32375), | ||
FinalizedHash: common.MustHexToHash("0x687197c11b4cf95374159843e7f46fbcd63558db981aaef01a8bac2a44a1d6b2"), | ||
FinalizedHeight: big.NewInt(32256), | ||
TXCount: 2, | ||
UsedStateCacheSize: 1886357, | ||
}) | ||
time.Sleep(time.Millisecond) | ||
require.Equal(t, expected, lastMessage[:295]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
} | ||
|
||
func listen(w http.ResponseWriter, r *http.Request) { | ||
c, err := upgrader.Upgrade(w, r, nil) | ||
if err != nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change to
if err != nil { return err }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, this is the only function where outgoing messages are sent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. Ok, thanks.