Integrate nim-metrics and add some metrics from the ETH2 spec (#394)

This commit is contained in:
zah 2019-09-07 13:48:05 -04:00 committed by Jacek Sieka
parent 0c174036a5
commit 93cdb43f1e
7 changed files with 77 additions and 13 deletions

View File

@ -17,19 +17,20 @@ bin = @[
### Dependencies ### Dependencies
requires "nim >= 0.19.0", requires "nim >= 0.19.0",
"eth",
"nimcrypto",
"blscurve", "blscurve",
"stew",
"chronicles", "chronicles",
"confutils",
"serialization",
"json_serialization",
"json_rpc",
"chronos", "chronos",
"yaml", "confutils",
"eth",
"json_rpc",
"json_serialization",
"libp2p", "libp2p",
"web3" "metrics",
"nimcrypto",
"serialization",
"stew",
"web3",
"yaml"
### Helper functions ### Helper functions
proc buildBinary(name: string, srcDir = "./", params = "", cmdParams = "", lang = "c") = proc buildBinary(name: string, srcDir = "./", params = "", cmdParams = "", lang = "c") =

View File

@ -1,7 +1,7 @@
import import
net, sequtils, options, tables, osproc, random, strutils, times, strformat, net, sequtils, options, tables, osproc, random, strutils, times, strformat,
stew/shims/os, stew/[objects, bitseqs], stew/shims/os, stew/[objects, bitseqs],
chronos, chronicles, confutils, chronos, chronicles, confutils, metrics,
json_serialization/std/sets, serialization/errors, json_serialization/std/sets, serialization/errors,
eth/trie/db, eth/trie/backends/rocksdb_backend, eth/async_utils, eth/trie/db, eth/trie/backends/rocksdb_backend, eth/async_utils,
spec/[datatypes, digest, crypto, beaconstate, helpers, validator, spec/[datatypes, digest, crypto, beaconstate, helpers, validator,
@ -23,6 +23,28 @@ const
genesisFile = "genesis.json" genesisFile = "genesis.json"
testnetsBaseUrl = "https://serenity-testnets.status.im" testnetsBaseUrl = "https://serenity-testnets.status.im"
declareGauge beacon_slot, "Latest slot of the beacon chain state"
declareGauge beacon_head_slot, "Slot of the head block of the beacon chain"
declareGauge beacon_head_root, "Root of the head block of the beacon chain"
# TODO Implement these additional metrics (some of the them should be moved to different modules):
declareGauge beacon_finalized_epoch, "Current finalized epoch" # On epoch transition
declareGauge beacon_finalized_root, "Current finalized root" # On epoch transition
declareGauge beacon_current_justified_epoch, "Current justified epoch" # On epoch transition
declareGauge beacon_current_justified_root, "Current justified root" # On epoch transition
declareGauge beacon_previous_justified_epoch, "Current previously justified epoch" # On epoch transition
declareGauge beacon_previous_justified_root, "Current previously justified root" # On epoch transition
declareGauge beacon_current_validators, """Number of status="pending|active|exited|withdrawable" validators in current epoch""" # On epoch transition
declareGauge beacon_previous_validators, """Number of status="pending|active|exited|withdrawable" validators in previous epoch""" # On epoch transition
declareGauge beacon_current_live_validators, "Number of active validators that successfully included attestation on chain for current epoch" # On block
declareGauge beacon_previous_live_validators, "Number of active validators that successfully included attestation on chain for previous epoch" # On block
declareGauge beacon_pending_deposits, "Number of pending deposits (state.eth1_data.deposit_count - state.eth1_deposit_index)" # On block
declareGauge beacon_processed_deposits_total, "Number of total deposits included on chain" # On block
declareGauge beacon_pending_exits, "Number of pending voluntary exits in local operation pool" # On slot
declareGauge beacon_previous_epoch_orphaned_blocks, "Number of blocks orphaned in the previous epoch" # On epoch transition
declareCounter beacon_reorgs_total, "Total occurrences of reorganizations of the chain" # On fork choice
proc onBeaconBlock*(node: BeaconNode, blck: BeaconBlock) {.gcsafe.} proc onBeaconBlock*(node: BeaconNode, blck: BeaconBlock) {.gcsafe.}
func localValidatorsDir(conf: BeaconNodeConf): string = func localValidatorsDir(conf: BeaconNodeConf): string =
@ -212,6 +234,12 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
result.network.saveConnectionAddressFile(addressFile) result.network.saveConnectionAddressFile(addressFile)
result.beaconClock = BeaconClock.init(result.stateCache.data.data) result.beaconClock = BeaconClock.init(result.stateCache.data.data)
when useInsecureFeatures:
if conf.metricsServer:
let metricsAddress = conf.metricsServerAddress
info "Starting metrics HTTP server", address = metricsAddress, port = conf.metricsServerPort
metrics.startHttpServer(metricsAddress, Port(conf.metricsServerPort))
template withState( template withState(
pool: BlockPool, cache: var StateData, blockSlot: BlockSlot, body: untyped): untyped = pool: BlockPool, cache: var StateData, blockSlot: BlockSlot, body: untyped): untyped =
## Helper template that updates state to a particular BlockSlot - usage of ## Helper template that updates state to a particular BlockSlot - usage of
@ -296,6 +324,9 @@ proc updateHead(node: BeaconNode, slot: Slot): BlockRef =
newHeadBlockRoot = shortLog(newHead.root) newHeadBlockRoot = shortLog(newHead.root)
node.blockPool.updateHead(node.stateCache, newHead) node.blockPool.updateHead(node.stateCache, newHead)
beacon_head_slot.set slot.int64
beacon_head_root.set newHead.root.toGaugeValue
newHead newHead
proc sendAttestation(node: BeaconNode, proc sendAttestation(node: BeaconNode,
@ -589,6 +620,8 @@ proc onSlotStart(node: BeaconNode, lastSlot, scheduledSlot: Slot) {.gcsafe, asyn
slot = wallSlot.slot # afterGenesis == true! slot = wallSlot.slot # afterGenesis == true!
nextSlot = slot + 1 nextSlot = slot + 1
beacon_slot.set slot.int64
if slot > lastSlot + SLOTS_PER_EPOCH: if slot > lastSlot + SLOTS_PER_EPOCH:
# We've fallen behind more than an epoch - there's nothing clever we can # We've fallen behind more than an epoch - there's nothing clever we can
# do here really, except skip all the work and try again later. # do here really, except skip all the work and try again later.

View File

@ -1,6 +1,6 @@
import import
sets, deques, tables, sets, deques, tables,
eth/keys, stew/bitseqs, eth/keys, stew/[bitseqs, endians2],
spec/[datatypes, crypto, digest], spec/[datatypes, crypto, digest],
beacon_chain_db, conf, mainchain_monitor, eth2_network, time beacon_chain_db, conf, mainchain_monitor, eth2_network, time
@ -270,3 +270,10 @@ proc userValidatorsRange*(d: NetworkMetadata): HSlice[int, int] =
0 .. d.lastUserValidator.int 0 .. d.lastUserValidator.int
proc shortLog*(v: AttachedValidator): string = shortLog(v.pubKey) proc shortLog*(v: AttachedValidator): string = shortLog(v.pubKey)
proc toGaugeValue*(hash: Eth2Digest): int64 =
# Only the last 8 bytes are taken into consideration in accordance
# to the ETH2 metrics spec:
# https://github.com/ethereum/eth2.0-metrics/blob/6a79914cb31f7d54858c7dd57eee75b6162ec737/metrics.md#interop-metrics
cast[int64](uint64.fromBytes(hash.data[24..31], littleEndian))

View File

@ -86,6 +86,18 @@ type
"If you set this to 'auto', a persistent automatically generated ID will be seleceted for each --dataDir folder" "If you set this to 'auto', a persistent automatically generated ID will be seleceted for each --dataDir folder"
defaultValue: ""}: string defaultValue: ""}: string
metricsServer* {.
desc: "Enable the metrics server"
defaultValue: false.}: bool
metricsServerAddress* {.
desc: "Listening address of the metrics server"
defaultValue: "0.0.0.0".}: string # TODO: use a validated type here
metricsServerPort* {.
desc: "Listening HTTP port of the metrics server"
defaultValue: 8008 .}: uint16
of createTestnet: of createTestnet:
networkId* {. networkId* {.
desc: "An unique numeric identifier for the network".}: uint8 desc: "An unique numeric identifier for the network".}: uint8

View File

@ -1,6 +1,6 @@
import import
options, tables, sequtils, algorithm, sets, macros, options, tables, sequtils, algorithm, sets, macros,
chronicles, chronos, stew/ranges/bitranges, chronicles, chronos, metrics, stew/ranges/bitranges,
spec/[datatypes, crypto, digest, helpers], eth/rlp, spec/[datatypes, crypto, digest, helpers], eth/rlp,
beacon_node_types, eth2_network, beacon_chain_db, block_pool, time, ssz beacon_node_types, eth2_network, beacon_chain_db, block_pool, time, ssz
@ -8,6 +8,8 @@ when networkBackend == rlpxBackend:
import eth/rlp/options as rlpOptions import eth/rlp/options as rlpOptions
template libp2pProtocol*(name: string, version: int) {.pragma.} template libp2pProtocol*(name: string, version: int) {.pragma.}
declareGauge libp2p_peers, "Number of libp2p peers"
type type
ValidatorSetDeltaFlags {.pure.} = enum ValidatorSetDeltaFlags {.pure.} = enum
Activation = 0 Activation = 0
@ -108,6 +110,7 @@ p2pProtocol BeaconSync(version = 1,
# where it needs to sync and it should execute the sync algorithm with a certain # where it needs to sync and it should execute the sync algorithm with a certain
# number of randomly selected peers. The algorithm itself must be extracted in a proc. # number of randomly selected peers. The algorithm itself must be extracted in a proc.
try: try:
libp2p_peers.set peer.network.peers.len.int64
debug "Peer connected. Initiating sync", peer, bestSlot, remoteBestSlot = m.bestSlot debug "Peer connected. Initiating sync", peer, bestSlot, remoteBestSlot = m.bestSlot
let bestDiff = cmp((latestFinalizedEpoch, bestSlot), (m.latestFinalizedEpoch, m.bestSlot)) let bestDiff = cmp((latestFinalizedEpoch, bestSlot), (m.latestFinalizedEpoch, m.bestSlot))
@ -140,6 +143,9 @@ p2pProtocol BeaconSync(version = 1,
except CatchableError: except CatchableError:
warn "Failed to sync with peer", peer, err = getCurrentExceptionMsg() warn "Failed to sync with peer", peer, err = getCurrentExceptionMsg()
onPeerDisconnected do (peer: Peer):
libp2p_peers.set peer.network.peers.len.int64
handshake: handshake:
proc hello( proc hello(
peer: Peer, peer: Peer,

View File

@ -20,6 +20,11 @@ const
# Clients having different semantic versions won't be able # Clients having different semantic versions won't be able
# to join the same testnets. # to join the same testnets.
useInsecureFeatures* = true # defined(insecure)
# TODO This is temporarily set to true, so it's easier for other teams to
# launch the beacon_node with metrics enabled during the interop lock-in.
# We'll disable it once the lock-in is over.
template versionAsStr*: string = template versionAsStr*: string =
$versionMajor & "." & $versionMinor & "." & $versionBuild $versionMajor & "." & $versionMinor & "." & $versionBuild

2
vendor/nim-eth vendored

@ -1 +1 @@
Subproject commit bef28a18e58f52f24bcc50f0cadefac0224d4630 Subproject commit 44adb2a70a7a6d5720652029f722960eeec400de