From 651da65a0e843105eaf21db3f8e8cb01350a7da9 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 1 Jun 2020 21:04:16 +0200 Subject: [PATCH 01/32] wip --- Cargo.lock | 80 +++++++++++++++++++------------- Cargo.toml | 2 +- cli-signer/rpc-client/Cargo.toml | 4 +- miner/stratum/Cargo.toml | 4 +- rpc/Cargo.toml | 12 ++--- rpc/src/lib.rs | 1 + rpc/src/v1/impls/light/parity.rs | 4 ++ rpc/src/v1/impls/parity.rs | 19 ++++++++ rpc/src/v1/traits/parity.rs | 4 ++ 9 files changed, 86 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 022e1c0b328..0abe6cbfdac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1533,7 +1533,7 @@ version = "1.12.0" dependencies = [ "env_logger 0.5.13", "ethereum-types", - "jsonrpc-core", + "jsonrpc-core 14.1.0", "jsonrpc-tcp-server", "keccak-hash", "log", @@ -2384,11 +2384,20 @@ dependencies = [ "serde_json", ] +[[package]] +name = "jsonrpc-core" +version = "14.1.0" +dependencies = [ + "futures", + "log", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "jsonrpc-derive" -version = "14.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8609af8f63b626e8e211f52441fcdb6ec54f1a446606b10d5c89ae9bf8a20058" +version = "14.1.0" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.9", @@ -2398,13 +2407,11 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" -version = "14.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816d63997ea45d3634608edbef83ddb35e661f7c0b27b5b72f237e321f0e9807" +version = "14.1.0" dependencies = [ "hyper", - "jsonrpc-core", - "jsonrpc-server-utils", + "jsonrpc-core 14.1.0", + "jsonrpc-server-utils 14.1.0", "log", "net2", "parking_lot 0.10.0", @@ -2413,12 +2420,10 @@ dependencies = [ [[package]] name = "jsonrpc-ipc-server" -version = "14.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3cc22b91e6e92e7925110c080bfa0dfdc731b156ccb2a3ce0561e902a33a9cf" +version = "14.1.0" dependencies = [ - "jsonrpc-core", - "jsonrpc-server-utils", + "jsonrpc-core 14.1.0", + "jsonrpc-server-utils 14.1.0", "log", "parity-tokio-ipc", "parking_lot 0.10.0", @@ -2427,13 +2432,12 @@ dependencies = [ [[package]] name = "jsonrpc-pubsub" -version = "14.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b31c9b90731276fdd24d896f31bb10aecf2e5151733364ae81123186643d939" +version = "14.1.0" dependencies = [ - "jsonrpc-core", + "jsonrpc-core 14.1.0", "log", "parking_lot 0.10.0", + "rand 0.7.3", "serde", ] @@ -2445,7 +2449,21 @@ checksum = "95b7635e618a0edbbe0d2a2bbbc69874277c49383fcf6c3c0414491cfb517d22" dependencies = [ "bytes", "globset", - "jsonrpc-core", + "jsonrpc-core 14.0.5", + "lazy_static", + "log", + "tokio", + "tokio-codec", + "unicase", +] + +[[package]] +name = "jsonrpc-server-utils" +version = "14.1.0" +dependencies = [ + "bytes", + "globset", + "jsonrpc-core 14.1.0", "lazy_static", "log", "tokio", @@ -2455,12 +2473,10 @@ dependencies = [ [[package]] name = "jsonrpc-tcp-server" -version = "14.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a03d03b8eccd463b8f1c675d5e5febff5055291b82235c8ec0af973e6d7b84fc" +version = "14.1.0" dependencies = [ - "jsonrpc-core", - "jsonrpc-server-utils", + "jsonrpc-core 14.1.0", + "jsonrpc-server-utils 14.1.0", "log", "parking_lot 0.10.0", "tokio-service", @@ -2468,12 +2484,10 @@ dependencies = [ [[package]] name = "jsonrpc-ws-server" -version = "14.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94e5773b2ae66e0e02c80775ce6bbba6f15d5bb47c14ec36a36fcf94f8df851" +version = "14.1.0" dependencies = [ - "jsonrpc-core", - "jsonrpc-server-utils", + "jsonrpc-core 14.1.0", + "jsonrpc-server-utils 14.1.0", "log", "parking_lot 0.10.0", "slab", @@ -3139,7 +3153,7 @@ dependencies = [ "futures", "ipnetwork", "journaldb", - "jsonrpc-core", + "jsonrpc-core 14.1.0", "keccak-hash", "kvdb", "kvdb-rocksdb", @@ -3341,7 +3355,7 @@ dependencies = [ "fetch", "futures", "itertools", - "jsonrpc-core", + "jsonrpc-core 14.1.0", "jsonrpc-derive", "jsonrpc-http-server", "jsonrpc-ipc-server", @@ -3386,7 +3400,7 @@ version = "1.4.0" dependencies = [ "ethereum-types", "futures", - "jsonrpc-core", + "jsonrpc-core 14.1.0", "jsonrpc-ws-server", "keccak-hash", "log", @@ -3432,7 +3446,7 @@ dependencies = [ "ethereum-types", "futures", "hyper", - "jsonrpc-server-utils", + "jsonrpc-server-utils 14.0.5", "keccak-hash", "kvdb", "kvdb-rocksdb", diff --git a/Cargo.toml b/Cargo.toml index fe140117de1..9303da6f162 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ ethstore = { path = "accounts/ethstore" } fdlimit = "0.1" futures = "0.1" journaldb = { path = "util/journaldb" } -jsonrpc-core = "14.0.3" +jsonrpc-core = { path = "../jsonrpc/core"} keccak-hash = "0.5.0" kvdb = "0.5.0" kvdb-rocksdb = "0.7.0" diff --git a/cli-signer/rpc-client/Cargo.toml b/cli-signer/rpc-client/Cargo.toml index f1931921f57..3beb61697f2 100644 --- a/cli-signer/rpc-client/Cargo.toml +++ b/cli-signer/rpc-client/Cargo.toml @@ -15,7 +15,7 @@ serde_json = "1.0" url = "2.1.1" matches = "0.1" parking_lot = "0.10.0" -jsonrpc-core = "14.0.3" -jsonrpc-ws-server = "14.0.3" +jsonrpc-core = { path = "../../../jsonrpc/core" } +jsonrpc-ws-server = { path = "../../../jsonrpc/ws" } parity-rpc = { path = "../../rpc" } keccak-hash = "0.5.0" diff --git a/miner/stratum/Cargo.toml b/miner/stratum/Cargo.toml index c681e52db24..06d6f1e4bd8 100644 --- a/miner/stratum/Cargo.toml +++ b/miner/stratum/Cargo.toml @@ -8,8 +8,8 @@ authors = ["Parity Technologies "] [dependencies] ethereum-types = "0.9.0" keccak-hash = "0.5.0" -jsonrpc-core = "14.0.3" -jsonrpc-tcp-server = "14.0.3" +jsonrpc-core = { path = "../../../jsonrpc/core" } +jsonrpc-tcp-server = { path = "../../../jsonrpc/tcp" } log = "0.4" parking_lot = "0.10.0" diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 19208fa8328..5b1779806bc 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -26,12 +26,12 @@ tokio-timer = "0.2.13" transient-hashmap = "0.4" itertools = "0.8.2" -jsonrpc-core = "14.0.5" -jsonrpc-derive = "14.0.5" -jsonrpc-http-server = "14.0.5" -jsonrpc-ws-server = "14.0.5" -jsonrpc-ipc-server = "14.0.6" -jsonrpc-pubsub = "14.0.5" +jsonrpc-core = { path = "../../jsonrpc/core" } +jsonrpc-derive = { path = "../../jsonrpc/derive" } +jsonrpc-http-server = { path = "../../jsonrpc/http" } +jsonrpc-ws-server = { path = "../../jsonrpc/ws" } +jsonrpc-ipc-server = { path = "../../jsonrpc/ipc" } +jsonrpc-pubsub = { path = "../../jsonrpc/pubsub" } client-traits = { path = "../ethcore/client-traits" } common-types = { path = "../ethcore/types" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 3a3673b7b5d..8ef813cad37 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -188,6 +188,7 @@ pub fn start_http( .cors(cors_domains) .allowed_hosts(allowed_hosts) .health_api(("/api/health", "parity_nodeStatus")) + .raw_api(("/metrics", "parity_nodeMetrics")) .cors_allow_headers(AccessControlAllowHeaders::Any) .max_request_body_size(max_payload * 1024 * 1024) .start_http(addr)?) diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 4168abd9717..8ed10c58207 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -391,6 +391,10 @@ where } } + fn metrics(&self) -> Result { + Ok(String::from("none")) + } + fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture> { let filter = match filter.try_into() { Ok(value) => value, diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index cbb89a8ca95..c97f4a7c2c9 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -453,6 +453,25 @@ impl Parity for ParityClient where } } + fn metrics(&self) -> Result { + let mut r = String::new(); + + let scalar = |b| if b {1} else {0}; + + let sync_status = self.sync.status(); + r.push_str(&format!("oe_sync_peers {}\n",sync_status.num_peers)); + r.push_str(&format!("oe_sync_active_peers {}\n",sync_status.num_active_peers)); + r.push_str(&format!("oe_sync_blocks_recieved {}\n",sync_status.blocks_received)); + r.push_str(&format!("oe_sync_blocks_total {}\n",sync_status.blocks_total)); + r.push_str(&format!("oe_sync_blocks_highest {}\n",sync_status.highest_block_number.unwrap_or(0))); + r.push_str(&format!("oe_sync_is_majorsync {}\n",scalar(self.sync.is_major_syncing()))); + r.push_str(&format!("oe_sync_snapshot_is_sync {}\n",scalar(sync_status.is_snapshot_syncing()))); + r.push_str(&format!("oe_sync_snapshot_chunks {}\n",sync_status.num_snapshot_chunks)); + r.push_str(&format!("oe_sync_snapshot_chunks_done {}\n",sync_status.snapshot_chunks_done)); + r.push_str(&format!("oe_sync_mem_used {}\n",sync_status.mem_used)); + Ok(String::from(r)) + } + fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture> { use v1::impls::eth::base_logs; // only specific impl for lightclient diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index 1eeb2fd5b79..2983b0165a6 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -226,6 +226,10 @@ pub trait Parity { #[rpc(name = "parity_nodeStatus")] fn status(&self) -> Result<()>; + /// [adria0] document + #[rpc(name = "parity_nodeMetrics")] + fn metrics(&self) -> Result; + /// Extracts Address and public key from signature using the r, s and v params. Equivalent to Solidity erecover /// as well as checks the signature for chain replay protection #[rpc(name = "parity_verifySignature")] From f85bd4036624598b4e22bb5579b0a053a6714428 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 4 Jun 2020 22:19:33 +0200 Subject: [PATCH 02/32] working version --- Cargo.lock | 51 +++++++++++++++++++++++++ Cargo.toml | 3 +- cli-signer/rpc-client/Cargo.toml | 4 +- ethcore/Cargo.toml | 2 +- ethcore/src/client/client.rs | 64 ++++++++++++++++++++++++++++++++ ethcore/src/lib.rs | 1 + ethcore/sync/Cargo.toml | 1 + ethcore/sync/src/api.rs | 22 ++++++++++- miner/stratum/Cargo.toml | 4 +- parity/lib.rs | 1 + rpc/Cargo.toml | 12 +++--- rpc/src/v1/impls/parity.rs | 30 +++++++-------- util/stats/Cargo.toml | 1 + util/stats/src/lib.rs | 19 +++++++++- 14 files changed, 184 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0abe6cbfdac..bc4a31e9246 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1577,6 +1577,7 @@ dependencies = [ "rustc-hex 2.1.0", "snapshot", "spec", + "stats", "trace-time", "triehash-ethereum", ] @@ -2387,6 +2388,7 @@ dependencies = [ [[package]] name = "jsonrpc-core" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "futures", "log", @@ -2398,6 +2400,7 @@ dependencies = [ [[package]] name = "jsonrpc-derive" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "proc-macro-crate", "proc-macro2 1.0.9", @@ -2408,6 +2411,7 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "hyper", "jsonrpc-core 14.1.0", @@ -2421,6 +2425,7 @@ dependencies = [ [[package]] name = "jsonrpc-ipc-server" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "jsonrpc-core 14.1.0", "jsonrpc-server-utils 14.1.0", @@ -2433,6 +2438,7 @@ dependencies = [ [[package]] name = "jsonrpc-pubsub" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "jsonrpc-core 14.1.0", "log", @@ -2460,6 +2466,7 @@ dependencies = [ [[package]] name = "jsonrpc-server-utils" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "bytes", "globset", @@ -2474,6 +2481,7 @@ dependencies = [ [[package]] name = "jsonrpc-tcp-server" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "jsonrpc-core 14.1.0", "jsonrpc-server-utils 14.1.0", @@ -2485,6 +2493,7 @@ dependencies = [ [[package]] name = "jsonrpc-ws-server" version = "14.1.0" +source = "git+https://github.com/adria0/jsonrpc?branch=adria0/rawapi#2707b08fb757cdc83697ef6bc5b8127b53d317c4" dependencies = [ "jsonrpc-core 14.1.0", "jsonrpc-server-utils 14.1.0", @@ -3177,6 +3186,7 @@ dependencies = [ "parity-version", "parking_lot 0.10.0", "pretty_assertions", + "prometheus", "regex", "registrar", "rlp", @@ -3876,6 +3886,26 @@ dependencies = [ "unicode-xid 0.2.0", ] +[[package]] +name = "prometheus" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0ced56dee39a6e960c15c74dc48849d614586db2eaada6497477af7c7811cd" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "protobuf", + "spin", + "thiserror", +] + +[[package]] +name = "protobuf" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e86d370532557ae7573551a1ec8235a0f8d6cb276c7c9e6aa490b511c447485" + [[package]] name = "pwasm-run-test" version = "0.1.0" @@ -4747,6 +4777,7 @@ name = "stats" version = "0.1.0" dependencies = [ "log", + "prometheus", ] [[package]] @@ -4874,6 +4905,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479" +dependencies = [ + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn 1.0.17", +] + [[package]] name = "thread-id" version = "3.3.0" diff --git a/Cargo.toml b/Cargo.toml index 9303da6f162..845a729c273 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ ethstore = { path = "accounts/ethstore" } fdlimit = "0.1" futures = "0.1" journaldb = { path = "util/journaldb" } -jsonrpc-core = { path = "../jsonrpc/core"} +jsonrpc-core = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} keccak-hash = "0.5.0" kvdb = "0.5.0" kvdb-rocksdb = "0.7.0" @@ -79,6 +79,7 @@ term_size = "0.3" textwrap = "0.11.0" toml = "0.5.6" verification = { path = "ethcore/verification" } +prometheus = "0.9.0" [build-dependencies] rustc_version = "0.2" diff --git a/cli-signer/rpc-client/Cargo.toml b/cli-signer/rpc-client/Cargo.toml index 3beb61697f2..bf2f9905a63 100644 --- a/cli-signer/rpc-client/Cargo.toml +++ b/cli-signer/rpc-client/Cargo.toml @@ -15,7 +15,7 @@ serde_json = "1.0" url = "2.1.1" matches = "0.1" parking_lot = "0.10.0" -jsonrpc-core = { path = "../../../jsonrpc/core" } -jsonrpc-ws-server = { path = "../../../jsonrpc/ws" } +jsonrpc-core = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} +jsonrpc-ws-server = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} parity-rpc = { path = "../../rpc" } keccak-hash = "0.5.0" diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index a7133316af6..8e07b7fa59a 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -56,6 +56,7 @@ serde_derive = "1.0" snapshot = { path = "snapshot" } spec = { path = "spec" } state-db = { path = "state-db" } +stats = { path = "../util/stats" } tempfile = { version = "3.1", optional = true } trace = { path = "trace" } trace-time = "0.1" @@ -83,7 +84,6 @@ lazy_static = "1.3" machine = { path = "./machine", features = ["test-helpers"] } parity-runtime = "0.1.1" serde_json = "1.0" -stats = { path = "../util/stats" } pod = { path = "pod" } tempfile = "3.1" trie-standardmap = "0.15.0" diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 17419c5eca2..8c40353282c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -136,6 +136,7 @@ use types::data_format::DataFormat; use verification::{self, BlockQueue}; use verification::queue::kind::BlockLike; use vm::{CreateContractAddress, EnvInfo, LastHashes}; +use stats::{prometheus_counter,prometheus_gauge,prometheus,PrometheusMetrics}; const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096; // Max number of blocks imported at once. @@ -2857,6 +2858,69 @@ impl IoChannelQueue { } } +impl PrometheusMetrics for Client { + fn prometheus_metrics(&self, r: &mut prometheus::Registry) { + + // gas, tx & blocks + let report = self.report(); + + prometheus_counter(r,"import_gas","Gas processed",report.gas_processed.as_u64() as i64); + prometheus_counter(r,"import_blocks","Blocks imported",report.blocks_imported as i64); + prometheus_counter(r,"import_txs","Transactions applied",report.transactions_applied as i64); + + let state_db = self.state_db.read(); + prometheus_gauge(r,"statedb_mem_used","State DB memory used",state_db.mem_used() as i64); + prometheus_gauge(r,"statedb_cache_size","State DB cache size",state_db.cache_size() as i64); + + // blockchain caché + let blockchain_cache_info = self.blockchain_cache_info(); + prometheus_gauge(r,"blockchaincache_block_details","BlockDetails cache size",blockchain_cache_info.block_details as i64); + prometheus_gauge(r,"blockchaincache_block_recipts","Block receipts size",blockchain_cache_info.block_receipts as i64); + prometheus_gauge(r,"blockchaincache_blocks","Blocks cache size",blockchain_cache_info.blocks as i64); + prometheus_gauge(r,"blockchaincache_txaddrs","Transaction addresses cache size",blockchain_cache_info.transaction_addresses as i64); + prometheus_gauge(r,"blockchaincache_size","Total blockchain cache size",blockchain_cache_info.total() as i64); + + // io + let io_stats = self.db.read().key_value().io_stats(kvdb::IoStatsKind::Overall); + prometheus_counter(r,"io_transactions","Number of transactions", io_stats.transactions as i64); + prometheus_counter(r,"io_reads","Number of read operations", io_stats.reads as i64); + prometheus_counter(r,"io_writes","Number of write operations", io_stats.writes as i64); + prometheus_counter(r,"io_cache_reads","Number of reads resulted in a read from cache", io_stats.cache_reads as i64); + prometheus_counter(r,"io_bytes_read","Number of bytes read", io_stats.bytes_read as i64); + prometheus_counter(r,"io_cache_read_bytes",".", io_stats.cache_read_bytes as i64); + prometheus_counter(r,"io_bytes_written","Number of bytes written", io_stats.bytes_written as i64); + + // chain info + let chain = self.chain_info(); + + let gap = chain.ancient_block_number.map(|x| U256::from(x + 1)) + .and_then(|first| chain.first_block_number.map(|last| (first, U256::from(last)))); + if let Some((first,last)) = gap { + prometheus_gauge(r,"chain_warpsync_gap_first","Warp sync gap, first block",first.as_u64() as i64); + prometheus_gauge(r,"chain_warpsync_gap_last","Warp sync gap, last block",last.as_u64() as i64); + } + + prometheus_gauge(r,"chain_difficulty_total","Blockchain difficulty",chain.total_difficulty.as_u64() as i64); + prometheus_gauge(r,"chain_difficulty_total_pending","Block queue difficulty",chain.pending_total_difficulty.as_u64() as i64); + prometheus_gauge(r,"chain_block","Best block number",chain.best_block_number as i64); + + + // prunning info + let prunning = self.pruning_info(); + prometheus_gauge(r,"prunning_earliest_chain","The first block which everything can be served after",prunning.earliest_chain as i64); + prometheus_gauge(r,"prunning_earliest_state","The first block where state requests may be served",prunning.earliest_state as i64); + + // queue info + let queue = self.queue_info(); + prometheus_gauge(r,"queue_mem_used","Queue heap memory used in bytes",queue.mem_used as i64); + prometheus_gauge(r,"queue_size_total","The total size of the queues",queue.total_queue_size() as i64); + prometheus_gauge(r,"queue_size_unverified","Number of queued items pending verification",queue.unverified_queue_size as i64); + prometheus_gauge(r,"queue_size_verified","Number of verified queued items pending import",queue.verified_queue_size as i64); + prometheus_gauge(r,"queue_size_verifying","Number of items being verified",queue.verifying_queue_size as i64); + + } +} + #[cfg(test)] mod tests { use std::sync::Arc; diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index b21cd959b5f..8b81c1e6ecf 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -49,6 +49,7 @@ extern crate rlp; extern crate rustc_hex; extern crate serde; extern crate snapshot; +extern crate stats; extern crate spec; extern crate state_db; extern crate trace; diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index 89c98a741dd..c4a54a22a96 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -32,6 +32,7 @@ rand = "0.7.3" parking_lot = "0.10.0" rlp = "0.4.5" snapshot = { path = "../snapshot" } +stats = { path = "../../util/stats" } trace-time = "0.1" triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" } diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index cd96c9eea58..46c7c84bb58 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -66,7 +66,7 @@ use common_types::{ pruning_info::PruningInfo, transaction::UnverifiedTransaction, }; - +use stats::{PrometheusMetrics, prometheus_counter, prometheus_gauge, prometheus}; /// Parity sync protocol pub const WARP_SYNC_PROTOCOL_ID: ProtocolId = *b"par"; @@ -150,7 +150,7 @@ impl Default for SyncConfig { pub type Notification = futures_mpsc::UnboundedReceiver; /// Current sync status -pub trait SyncProvider: Send + Sync { +pub trait SyncProvider: Send + Sync + PrometheusMetrics { /// Get sync status fn status(&self) -> EthSyncStatus; @@ -412,6 +412,24 @@ impl EthSync { } } +impl PrometheusMetrics for EthSync { + fn prometheus_metrics(&self, r: &mut prometheus::Registry) { + let scalar = |b| if b {1i64} else {0i64}; + let sync_status = self.status(); + + prometheus_gauge(r,"sync_peers","Total number of connected peers",sync_status.num_peers as i64); + prometheus_gauge(r,"sync_active_peers","Total number of active peers",sync_status.num_active_peers as i64); + prometheus_counter(r,"sync_blocks_recieved","Number of blocks downloaded so far",sync_status.blocks_received as i64); + prometheus_counter(r,"sync_blocks_total","Total number of blocks for the sync process",sync_status.blocks_total as i64); + prometheus_gauge(r,"sync_blocks_highest","Highest block number in the download queue",sync_status.highest_block_number.unwrap_or(0) as i64); + prometheus_gauge(r,"sync_is_majorsync","Are we in the middle of a major sync?",scalar(self.is_major_syncing())); + prometheus_gauge(r,"sync_mem_used","Heap memory used in bytes",sync_status.mem_used as i64); + prometheus_gauge(r,"sync_snapshot_is_sync",".",scalar(sync_status.is_snapshot_syncing())); + prometheus_gauge(r,"sync_snapshot_chunks","Snapshot chunks",sync_status.num_snapshot_chunks as i64); + prometheus_gauge(r,"sync_snapshot_chunks_done","Snapshot chunks downloaded",sync_status.snapshot_chunks_done as i64); + } +} + impl SyncProvider for EthSync { /// Get sync status fn status(&self) -> EthSyncStatus { diff --git a/miner/stratum/Cargo.toml b/miner/stratum/Cargo.toml index 06d6f1e4bd8..b96134a80b8 100644 --- a/miner/stratum/Cargo.toml +++ b/miner/stratum/Cargo.toml @@ -8,8 +8,8 @@ authors = ["Parity Technologies "] [dependencies] ethereum-types = "0.9.0" keccak-hash = "0.5.0" -jsonrpc-core = { path = "../../../jsonrpc/core" } -jsonrpc-tcp-server = { path = "../../../jsonrpc/tcp" } +jsonrpc-core = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} +jsonrpc-tcp-server = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} log = "0.4" parking_lot = "0.10.0" diff --git a/parity/lib.rs b/parity/lib.rs index f8be172fa0e..5fe34004a8b 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -75,6 +75,7 @@ extern crate registrar; extern crate snapshot; extern crate spec; extern crate verification; +extern crate prometheus; #[macro_use] extern crate log as rlog; diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 5b1779806bc..90dacf2f4a2 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -26,12 +26,12 @@ tokio-timer = "0.2.13" transient-hashmap = "0.4" itertools = "0.8.2" -jsonrpc-core = { path = "../../jsonrpc/core" } -jsonrpc-derive = { path = "../../jsonrpc/derive" } -jsonrpc-http-server = { path = "../../jsonrpc/http" } -jsonrpc-ws-server = { path = "../../jsonrpc/ws" } -jsonrpc-ipc-server = { path = "../../jsonrpc/ipc" } -jsonrpc-pubsub = { path = "../../jsonrpc/pubsub" } +jsonrpc-core ={ git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} +jsonrpc-derive = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} +jsonrpc-http-server = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} +jsonrpc-ws-server = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} +jsonrpc-ipc-server = { git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} +jsonrpc-pubsub ={ git = "https://github.com/adria0/jsonrpc", branch="adria0/rawapi"} client-traits = { path = "../ethcore/client-traits" } common-types = { path = "../ethcore/types" } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index c97f4a7c2c9..f9774ed1f1c 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -39,6 +39,10 @@ use types::{ }; use updater::{Service as UpdateService}; use version::version_data; +use stats::{ + PrometheusMetrics, + prometheus::{self, Encoder} +}; use v1::helpers::{self, errors, fake_sign, NetworkSettings, verify_signature}; use v1::helpers::external_signer::{SigningQueue, SignerService}; @@ -70,7 +74,7 @@ pub struct ParityClient { } impl ParityClient where - C: BlockChainClient, + C: BlockChainClient + PrometheusMetrics, { /// Creates new `ParityClient`. pub fn new( @@ -102,7 +106,7 @@ impl ParityClient where impl Parity for ParityClient where S: StateInfo + 'static, - C: miner::BlockChainClient + BlockChainClient + StateClient + Call + 'static, + C: miner::BlockChainClient + BlockChainClient + PrometheusMetrics + StateClient + Call + 'static, M: MinerService + 'static, U: UpdateService + 'static, { @@ -454,22 +458,16 @@ impl Parity for ParityClient where } fn metrics(&self) -> Result { - let mut r = String::new(); - let scalar = |b| if b {1} else {0}; + let mut reg = prometheus::Registry::new(); + self.client.prometheus_metrics(&mut reg); + self.sync.prometheus_metrics(&mut reg); - let sync_status = self.sync.status(); - r.push_str(&format!("oe_sync_peers {}\n",sync_status.num_peers)); - r.push_str(&format!("oe_sync_active_peers {}\n",sync_status.num_active_peers)); - r.push_str(&format!("oe_sync_blocks_recieved {}\n",sync_status.blocks_received)); - r.push_str(&format!("oe_sync_blocks_total {}\n",sync_status.blocks_total)); - r.push_str(&format!("oe_sync_blocks_highest {}\n",sync_status.highest_block_number.unwrap_or(0))); - r.push_str(&format!("oe_sync_is_majorsync {}\n",scalar(self.sync.is_major_syncing()))); - r.push_str(&format!("oe_sync_snapshot_is_sync {}\n",scalar(sync_status.is_snapshot_syncing()))); - r.push_str(&format!("oe_sync_snapshot_chunks {}\n",sync_status.num_snapshot_chunks)); - r.push_str(&format!("oe_sync_snapshot_chunks_done {}\n",sync_status.snapshot_chunks_done)); - r.push_str(&format!("oe_sync_mem_used {}\n",sync_status.mem_used)); - Ok(String::from(r)) + let mut buffer = vec![]; + let encoder = prometheus::TextEncoder::new(); + let metric_families = reg.gather(); + encoder.encode(&metric_families, &mut buffer).unwrap(); + Ok(String::from_utf8(buffer).unwrap()) } fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture> { diff --git a/util/stats/Cargo.toml b/util/stats/Cargo.toml index 9997c7846d2..52c7cae728a 100644 --- a/util/stats/Cargo.toml +++ b/util/stats/Cargo.toml @@ -5,3 +5,4 @@ authors = ["Parity Technologies "] [dependencies] log = "0.4" +prometheus = "0.9.0" \ No newline at end of file diff --git a/util/stats/src/lib.rs b/util/stats/src/lib.rs index fa56bf273ae..631d0553df7 100644 --- a/util/stats/src/lib.rs +++ b/util/stats/src/lib.rs @@ -21,8 +21,25 @@ use std::ops::{Add, Sub, Deref, Div}; #[macro_use] extern crate log; +pub extern crate prometheus; -/// Sorted corpus of data. +pub trait PrometheusMetrics { + fn prometheus_metrics(&self, registry: &mut prometheus::Registry); +} + +pub fn prometheus_counter(reg: &mut prometheus::Registry, name: &str, help: &str, value: i64) { + let c = prometheus::IntCounter::new(name,help).expect("does not fail. qed."); + c.inc_by(value); + reg.register(Box::new(c)).expect("qed"); +} + +pub fn prometheus_gauge(reg: &mut prometheus::Registry, name: &str, help: &str, value: i64) { + let g = prometheus::IntGauge::new(name,help).expect("does not fail. qed."); + g.set(value); + reg.register(Box::new(g)).expect("qed"); +} + +/// Sorted corpus of data.1 #[derive(Debug, Clone, PartialEq)] pub struct Corpus(Vec); From 6e967d6212bad0912da7e6fedf537b28cd42b071 Mon Sep 17 00:00:00 2001 From: adria0 Date: Fri, 5 Jun 2020 08:19:03 +0200 Subject: [PATCH 03/32] fix perf compilation --- ethcore/src/test_helpers/test_client.rs | 6 ++++++ rpc/src/v1/tests/helpers/sync_provider.rs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/ethcore/src/test_helpers/test_client.rs b/ethcore/src/test_helpers/test_client.rs index 0f4cde783b8..bc800723394 100644 --- a/ethcore/src/test_helpers/test_client.rs +++ b/ethcore/src/test_helpers/test_client.rs @@ -81,6 +81,7 @@ use spec::{Spec, self}; use account_state::state::StateInfo; use state_db::StateDB; use trace::LocalizedTrace; +use stats::{PrometheusMetrics,prometheus}; /// Test client. pub struct TestBlockChainClient { @@ -995,3 +996,8 @@ impl client_traits::EngineClient for TestBlockChainClient { BlockChainClient::block_header(self, id) } } + +impl PrometheusMetrics for TestBlockChainClient { + fn prometheus_metrics(&self, r: &mut prometheus::Registry) { + } +} \ No newline at end of file diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index 27fd16ba7c0..97863669ee5 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -22,6 +22,7 @@ use parking_lot::RwLock; use network::client_version::ClientVersion; use futures::sync::mpsc; use sync::{SyncProvider, EthProtocolInfo, SyncStatus, PeerInfo, TransactionStats, SyncState}; +use stats::{PrometheusMetrics,prometheus}; /// TestSyncProvider config. pub struct Config { @@ -72,6 +73,11 @@ impl TestSyncProvider { } } +impl PrometheusMetrics for TestSyncProvider { + fn prometheus_metrics(&self, r: &mut prometheus::Registry) { + } +} + impl SyncProvider for TestSyncProvider { fn status(&self) -> SyncStatus { self.status.read().clone() From 6665e8dda4d9791e5fbbbfda93377b2736c10d8f Mon Sep 17 00:00:00 2001 From: adria0 Date: Fri, 5 Jun 2020 13:54:04 +0200 Subject: [PATCH 04/32] docker-compose --- scripts/prometheus/config/grafana/grafana.ini | 705 +++++++++++ scripts/prometheus/config/grafana/loki.yaml | 10 + .../prometheus/config/grafana/prometheus.yaml | 50 + .../config/prometheus/prometheus.yml | 44 + .../prometheus/config/promtail/config.yaml | 18 + scripts/prometheus/docker-compose.yaml | 107 ++ scripts/prometheus/model.json | 1092 +++++++++++++++++ scripts/prometheus/start.sh | 1 + 8 files changed, 2027 insertions(+) create mode 100644 scripts/prometheus/config/grafana/grafana.ini create mode 100644 scripts/prometheus/config/grafana/loki.yaml create mode 100644 scripts/prometheus/config/grafana/prometheus.yaml create mode 100644 scripts/prometheus/config/prometheus/prometheus.yml create mode 100644 scripts/prometheus/config/promtail/config.yaml create mode 100644 scripts/prometheus/docker-compose.yaml create mode 100644 scripts/prometheus/model.json create mode 100755 scripts/prometheus/start.sh diff --git a/scripts/prometheus/config/grafana/grafana.ini b/scripts/prometheus/config/grafana/grafana.ini new file mode 100644 index 00000000000..49e05c3b519 --- /dev/null +++ b/scripts/prometheus/config/grafana/grafana.ini @@ -0,0 +1,705 @@ +##################### Grafana Configuration Defaults ##################### +# +# Do not modify this file in grafana installs +# + +# possible values : production, development +app_mode = production + +# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty +instance_name = ${HOSTNAME} + +#################################### Paths ############################### +[paths] +# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) +data = data + +# Temporary files in `data` directory older than given duration will be removed +temp_data_lifetime = 24h + +# Directory where grafana can store logs +logs = data/log + +# Directory where grafana will automatically scan and look for plugins +plugins = data/plugins + +# folder that contains provisioning config files that grafana will apply on startup and while running. +provisioning = conf/provisioning + +#################################### Server ############################## +[server] +# Protocol (http, https, h2, socket) +protocol = http + +# The ip address to bind to, empty will bind to all interfaces +http_addr = + +# The http port to use +http_port = 3000 + +# The public facing domain name used to access grafana from a browser +domain = localhost + +# Redirect to correct domain if host header does not match domain +# Prevents DNS rebinding attacks +enforce_domain = false + +# The full public facing url +root_url = %(protocol)s://%(domain)s:%(http_port)s/ + +# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons. +serve_from_sub_path = false + +# Log web requests +router_logging = false + +# the path relative working path +static_root_path = public + +# enable gzip +enable_gzip = false + +# https certs & key file +cert_file = +cert_key = + +# Unix socket path +socket = /tmp/grafana.sock + +#################################### Database ############################ +[database] +# You can configure the database connection by specifying type, host, name, user and password +# as separate properties or as on string using the url property. + +# Either "mysql", "postgres" or "sqlite3", it's your choice +type = sqlite3 +host = 127.0.0.1:3306 +name = grafana +user = root +# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" +password = +# Use either URL or the previous fields to configure the database +# Example: mysql://user:secret@host:port/database +url = + +# Max idle conn setting default is 2 +max_idle_conn = 2 + +# Max conn setting default is 0 (mean not set) +max_open_conn = + +# Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) +conn_max_lifetime = 14400 + +# Set to true to log the sql calls and execution times. +log_queries = + +# For "postgres", use either "disable", "require" or "verify-full" +# For "mysql", use either "true", "false", or "skip-verify". +ssl_mode = disable + +ca_cert_path = +client_key_path = +client_cert_path = +server_cert_name = + +# For "sqlite3" only, path relative to data_path setting +path = grafana.db + +# For "sqlite3" only. cache mode setting used for connecting to the database +cache_mode = private + +#################################### Cache server ############################# +[remote_cache] +# Either "redis", "memcached" or "database" default is "database" +type = database + +# cache connectionstring options +# database: will use Grafana primary database. +# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'. +# memcache: 127.0.0.1:11211 +connstr = + +#################################### Data proxy ########################### +[dataproxy] + +# This enables data proxy logging, default is false +logging = false + +# How long the data proxy should wait before timing out default is 30 (seconds) +timeout = 30 + +# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request, default is false. +send_user_header = false + +#################################### Analytics ########################### +[analytics] +# Server reporting, sends usage counters to stats.grafana.org every 24 hours. +# No ip addresses are being tracked, only simple counters to track +# running instances, dashboard and error counts. It is very helpful to us. +# Change this option to false to disable reporting. +reporting_enabled = true + +# Set to false to disable all checks to https://grafana.com +# for new versions (grafana itself and plugins), check is used +# in some UI views to notify that grafana or plugin update exists +# This option does not cause any auto updates, nor send any information +# only a GET request to https://grafana.com to get latest versions +check_for_updates = true + +# Google Analytics universal tracking code, only enabled if you specify an id here +google_analytics_ua_id = + +# Google Tag Manager ID, only enabled if you specify an id here +google_tag_manager_id = + +#################################### Security ############################ +[security] +# disable creation of admin user on first start of grafana +disable_initial_admin_creation = false + +# default admin user, created on startup +admin_user = admin + +# default admin password, can be changed before first start of grafana, or in profile settings +admin_password = admin + +# used for signing +secret_key = SW2YcwTIb9zpOOhoPsMm + +# disable gravatar profile images +disable_gravatar = false + +# data source proxy whitelist (ip_or_domain:port separated by spaces) +data_source_proxy_whitelist = + +# disable protection against brute force login attempts +disable_brute_force_login_protection = false + +# set to true if you host Grafana behind HTTPS. default is false. +cookie_secure = false + +# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict" and "none" +cookie_samesite = lax + +# set to true if you want to allow browsers to render Grafana in a ,