Auto merge of #4947 - str4d:rust-metrics, r=str4d
Add metrics collection and a Prometheus exporter This adds an FFI wrapper around the `metrics` crate, and exposes CPP macros for collecting metrics in the C++ codebase. With this, we can collect metrics from both C++ and Rust. The following metrics are included in this PR: - Chain metrics: - (counter) `zcash.chain.verified.block.total` - (gauge) `zcash.chain.verified.block.height` - (histogram) `zcash.chain.verified.block.seconds` - Value pool metrics: - (gauge) `zcash.pool.notes.created[name]` - (gauge) `zcash.pool.notes.spent[name]` (currently not measured) - (gauge) `zcash.pool.notes.unspent[name]` (currently not measured) - (gauge) `zcash.pool.value.zatoshis[name]` - P2P network metrics: - (gauge) `zcash.net.peers` - (counter) `zcash.net.in.bytes.total` - (counter) `zcash.net.in.bytes[command]` - (counter) `zcash.net.in.messages[command]` - (counter) `zcash.net.out.bytes.total` - (counter) `zcash.net.out.bytes[command]` - (counter) `zcash.net.out.messages[command]` - Node metrics: - (gauge) `zcash.mempool.size.transactions` - (gauge) `zcash.mempool.size.bytes` - (gauge) `zcash.mempool.usage.bytes` - (informational) `zcashd.build.info` Collection of metrics is conditional on enabling an exporter. This PR adds a Prometheus exporter that can be enabled with `-prometheusport=<port>`. Metrics names have `.` replaced by `_` for compatibility with Prometheus. By default, metrics are only exposed to localhost. This can be expanded with `-metricsallowip=<ip>`.
This commit is contained in:
commit
49d76cf3f6
|
@ -31,6 +31,15 @@ dependencies = [
|
||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -52,6 +61,15 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-shim"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d20fdac7156779a1a30d970e838195558b4810dd06aa69e7c7461bdc518edf9b"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -94,6 +112,12 @@ dependencies = [
|
||||||
"crunchy",
|
"crunchy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitvec"
|
name = "bitvec"
|
||||||
version = "0.18.5"
|
version = "0.18.5"
|
||||||
|
@ -172,6 +196,12 @@ version = "1.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
|
@ -227,7 +257,7 @@ dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"crossbeam-channel 0.4.4",
|
"crossbeam-channel 0.4.4",
|
||||||
"crossbeam-deque",
|
"crossbeam-deque",
|
||||||
"crossbeam-epoch",
|
"crossbeam-epoch 0.8.2",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"crossbeam-utils 0.7.2",
|
"crossbeam-utils 0.7.2",
|
||||||
]
|
]
|
||||||
|
@ -258,7 +288,7 @@ version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
|
checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-epoch",
|
"crossbeam-epoch 0.8.2",
|
||||||
"crossbeam-utils 0.7.2",
|
"crossbeam-utils 0.7.2",
|
||||||
"maybe-uninit",
|
"maybe-uninit",
|
||||||
]
|
]
|
||||||
|
@ -274,7 +304,20 @@ dependencies = [
|
||||||
"crossbeam-utils 0.7.2",
|
"crossbeam-utils 0.7.2",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"maybe-uninit",
|
"maybe-uninit",
|
||||||
"memoffset",
|
"memoffset 0.5.6",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"crossbeam-utils 0.8.3",
|
||||||
|
"lazy_static",
|
||||||
|
"memoffset 0.6.3",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -332,6 +375,16 @@ dependencies = [
|
||||||
"crypto_api",
|
"crypto_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctor"
|
||||||
|
version = "0.1.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "3.0.2"
|
version = "3.0.2"
|
||||||
|
@ -345,6 +398,16 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dashmap"
|
||||||
|
version = "4.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -409,6 +472,12 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fpe"
|
name = "fpe"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -434,6 +503,21 @@ version = "0.1.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
|
checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-cpupool"
|
name = "futures-cpupool"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
|
@ -444,6 +528,24 @@ dependencies = [
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.4"
|
version = "0.14.4"
|
||||||
|
@ -477,6 +579,12 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.18"
|
version = "0.1.18"
|
||||||
|
@ -492,6 +600,94 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"itoa",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-body"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5dfb77c123b4e2f72a2069aeae0b4b4949cc7e966df277813fc16347e7549737"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httparse"
|
||||||
|
version = "1.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httpdate"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12219dc884514cb4a6a03737f4413c0e01c23a1b059b0156004b23f1e19dccbe"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"httparse",
|
||||||
|
"httpdate",
|
||||||
|
"itoa",
|
||||||
|
"pin-project",
|
||||||
|
"socket2",
|
||||||
|
"tokio",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
"want",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipnet"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jubjub"
|
name = "jubjub"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -529,10 +725,16 @@ dependencies = [
|
||||||
"ed25519-zebra",
|
"ed25519-zebra",
|
||||||
"funty",
|
"funty",
|
||||||
"group",
|
"group",
|
||||||
|
"hyper",
|
||||||
|
"ipnet",
|
||||||
"jubjub",
|
"jubjub",
|
||||||
"libc",
|
"libc",
|
||||||
|
"metrics",
|
||||||
|
"metrics-exporter-prometheus",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"subtle",
|
"subtle",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
|
@ -542,6 +744,15 @@ dependencies = [
|
||||||
"zcash_proofs",
|
"zcash_proofs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
@ -551,6 +762,15 @@ dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mach"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchers"
|
name = "matchers"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -566,6 +786,12 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memoffset"
|
name = "memoffset"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
|
@ -575,6 +801,104 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "metrics"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58e285601dcfb9f3a8f37a7093b9956a0df730b50848c8ac0117406aff06c851"
|
||||||
|
dependencies = [
|
||||||
|
"metrics-macros",
|
||||||
|
"proc-macro-hack",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "metrics-exporter-prometheus"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d23bb354bd7dd5d244f2e9a389a0c3249bb6b994aca71bd6c2f7cd6fa2657fc"
|
||||||
|
dependencies = [
|
||||||
|
"hyper",
|
||||||
|
"metrics",
|
||||||
|
"metrics-util",
|
||||||
|
"parking_lot",
|
||||||
|
"quanta",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "metrics-macros"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11ac60cd4d3a869fd39d57baf0ed7f79fb677580d8d6655c4330d4f1126bc27b"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"proc-macro-hack",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "metrics-util"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ace44e2c64f785c3c37605ecf7504e5fc4efbb2936a49cc56c1084d79657a4d"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"atomic-shim",
|
||||||
|
"crossbeam-epoch 0.9.3",
|
||||||
|
"crossbeam-utils 0.8.3",
|
||||||
|
"dashmap",
|
||||||
|
"indexmap",
|
||||||
|
"metrics",
|
||||||
|
"ordered-float",
|
||||||
|
"parking_lot",
|
||||||
|
"quanta",
|
||||||
|
"sketches-ddsketch",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.7.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"miow",
|
||||||
|
"ntapi",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miow"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -627,6 +951,15 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "766f840da25490628d8e63e529cd21c014f6600c6b8517add12a6fa6167a6218"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pairing"
|
name = "pairing"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
|
@ -637,18 +970,75 @@ dependencies = [
|
||||||
"group",
|
"group",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"instant",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.2.5",
|
||||||
|
"smallvec",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc174859768806e91ae575187ada95c91a29e96a98dc5d2cd9a1fed039501ba6"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-internal",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-internal"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
|
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-hack"
|
||||||
|
version = "0.5.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
@ -658,6 +1048,21 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quanta"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e76a3afdefd0ce2c0363bf3146271e947782240ea617885dd64e56c4de9fb3c9"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-shim",
|
||||||
|
"ctor",
|
||||||
|
"libc",
|
||||||
|
"mach",
|
||||||
|
"once_cell",
|
||||||
|
"raw-cpuid",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
|
@ -714,12 +1119,30 @@ dependencies = [
|
||||||
"rand_core",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "raw-cpuid"
|
||||||
|
version = "9.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c27cb5785b85bd05d4eb171556c9a1a514552e26123aeae6bb7d811353148026"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.1.57"
|
version = "0.1.57"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
@ -727,7 +1150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"redox_syscall",
|
"redox_syscall 0.1.57",
|
||||||
"rust-argon2",
|
"rust-argon2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -737,6 +1160,8 @@ version = "1.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -816,6 +1241,29 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sketches-ddsketch"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76a77a8fd93886010f05e7ea0720e569d6d16c65329dbe3ec033bbbccccb017b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.4.0"
|
version = "2.4.0"
|
||||||
|
@ -873,6 +1321,36 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-service"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.25"
|
version = "0.1.25"
|
||||||
|
@ -933,6 +1411,12 @@ dependencies = [
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "try-lock"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
|
@ -951,6 +1435,16 @@ version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "want"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"try-lock",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.9.0+wasi-snapshot-preview1"
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
|
|
@ -37,6 +37,14 @@ zcash_primitives = "0.5"
|
||||||
zcash_proofs = "0.5"
|
zcash_proofs = "0.5"
|
||||||
ed25519-zebra = "2.0.0"
|
ed25519-zebra = "2.0.0"
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
hyper = { version = "=0.14.2", default-features = false, features = ["server", "tcp", "http1"] }
|
||||||
|
ipnet = "2"
|
||||||
|
metrics = "0.14.2"
|
||||||
|
metrics-exporter-prometheus = "0.3"
|
||||||
|
thiserror = "1"
|
||||||
|
tokio = { version = "1.0", features = ["rt", "net", "time", "macros"] }
|
||||||
|
|
||||||
# Temporary workaround for https://github.com/myrrlyn/funty/issues/3
|
# Temporary workaround for https://github.com/myrrlyn/funty/issues/3
|
||||||
funty = "=1.1.0"
|
funty = "=1.1.0"
|
||||||
|
|
||||||
|
|
|
@ -124,14 +124,24 @@ Files: src/crypto/ctaes/*
|
||||||
Copyright: Copyright (c) 2016 Pieter Wuille
|
Copyright: Copyright (c) 2016 Pieter Wuille
|
||||||
License: Expat
|
License: Expat
|
||||||
|
|
||||||
|
Files: src/rust/include/rust/map.h
|
||||||
|
Copyright: Copyright (c) 2012 William Swanson
|
||||||
|
License: Expat-with-advertising-clause
|
||||||
|
|
||||||
|
Files: src/rust/include/rust/VA_OPT.hpp
|
||||||
|
Copyright: Copyright (c) 2019 Will Wray
|
||||||
|
License: Boost-Software-License-1.0
|
||||||
|
|
||||||
Files: src/rust/include/tracing.h
|
Files: src/rust/include/tracing.h
|
||||||
src/rust/src/tracing_ffi.rs
|
src/rust/src/tracing_ffi.rs
|
||||||
Copyright: Copyright (c) 2020 Jack Grigg
|
Copyright: Copyright (c) 2020 Jack Grigg
|
||||||
License: Expat
|
License: Expat
|
||||||
|
|
||||||
Files: src/rust/include/tracing/map.h
|
Files: src/rust/src/metrics_ffi/prometheus.rs
|
||||||
Copyright: Copyright (c) 2012 William Swanson
|
Copyright:
|
||||||
License: Expat-with-advertising-clause
|
2020-2021 The contributors to the metrics project
|
||||||
|
2021 Jack Grigg
|
||||||
|
License: Expat
|
||||||
|
|
||||||
Files: src/secp256k1/*
|
Files: src/secp256k1/*
|
||||||
Copyright: Copyright (c) 2013 Pieter Wuille
|
Copyright: Copyright (c) 2013 Pieter Wuille
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'zcashd'
|
||||||
|
scrape_interval: 500ms
|
||||||
|
metrics_path: '/'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['127.0.0.1:9969']
|
|
@ -1,6 +1,8 @@
|
||||||
# The zcashd Book
|
# The zcashd Book
|
||||||
|
|
||||||
[zcashd](README.md)
|
[zcashd](README.md)
|
||||||
|
- [User Documentation](user.md)
|
||||||
|
- [Metrics](user/metrics.md)
|
||||||
- [Design](design.md)
|
- [Design](design.md)
|
||||||
- [Chain state](design/chain-state.md)
|
- [Chain state](design/chain-state.md)
|
||||||
- ["Coins" view](design/coins-view.md)
|
- ["Coins" view](design/coins-view.md)
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# User Documentation
|
||||||
|
|
||||||
|
This section contains user documentation specific to `zcashd`.
|
||||||
|
|
||||||
|
See [here](https://zcash.readthedocs.io/) for more general Zcash documentation, as well as
|
||||||
|
installation instructions for `zcashd`.
|
|
@ -0,0 +1,84 @@
|
||||||
|
# zcashd metrics
|
||||||
|
|
||||||
|
## Metrics UI
|
||||||
|
|
||||||
|
This is the user interface that `zcashd` displays by default when run. It
|
||||||
|
displays a small selection of interesting metrics, but is not intended for
|
||||||
|
programmatic consumption.
|
||||||
|
|
||||||
|
## RPC methods
|
||||||
|
|
||||||
|
`zcashd` provides the following JSON-RPC methods that expose node metrics:
|
||||||
|
|
||||||
|
- Chain:
|
||||||
|
- `getblockchaininfo`: Various state info regarding block chain processing.
|
||||||
|
- `gettxoutsetinfo`: Statistics about the unspent transparent transaction output set.
|
||||||
|
- `getmempoolinfo`: Details on the active state of the TX memory pool.
|
||||||
|
- P2P network:
|
||||||
|
- `getnetworkinfo`: Various state info regarding P2P networking.
|
||||||
|
- `getpeerinfo`: Data about each connected network node.
|
||||||
|
- `getdeprecationinfo`: The current node version and deprecation block height.
|
||||||
|
- Miscellaneous
|
||||||
|
- `getmemoryinfo`: Information about memory usage.
|
||||||
|
- `getmininginfo`: Mining-related information.
|
||||||
|
- `getinfo` (deprecated): A small subset of the above metrics.
|
||||||
|
|
||||||
|
You can see what each method provides with `zcash-cli help METHOD_NAME`.
|
||||||
|
|
||||||
|
## Prometheus support
|
||||||
|
|
||||||
|
`zcashd` can optionally expose an HTTP server that acts as a Prometheus scrape
|
||||||
|
endpoint. The server will respond to `GET` requests on any request path.
|
||||||
|
|
||||||
|
To enable the endpoint, add `-prometheusport=<port>` to your `zcashd`
|
||||||
|
configuration (either in `zcash.conf` or on the command line). After
|
||||||
|
restarting `zcashd` you can then test the endpoint by querying it:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ curl http://127.0.0.1:<port>
|
||||||
|
# TYPE zcash_net_out_messages counter
|
||||||
|
zcash_net_out_messages 181
|
||||||
|
|
||||||
|
# TYPE zcash_net_in_bytes_total counter
|
||||||
|
zcash_net_in_bytes_total 3701998
|
||||||
|
|
||||||
|
# TYPE zcash_net_in_messages counter
|
||||||
|
zcash_net_in_messages 184
|
||||||
|
|
||||||
|
# TYPE zcashd_build_info counter
|
||||||
|
zcashd_build_info{version="v4.2.0"} 1
|
||||||
|
|
||||||
|
# TYPE zcash_chain_verified_block_total counter
|
||||||
|
zcash_chain_verified_block_total 162
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, access is restricted to localhost. This can be expanded with
|
||||||
|
`-metricsallowip=<ip>`, which can specify IPs or subnets. Note that HTTPS is not
|
||||||
|
supported, and therefore connections to the endpoint are not encrypted or
|
||||||
|
authenticated. Access to the endpoint should be assumed to compromise the
|
||||||
|
privacy of node operations, by the provided metrics and/or by timing side
|
||||||
|
channels. Non-localhost access is **strongly discouraged** if the node has a
|
||||||
|
wallet holding live funds.
|
||||||
|
|
||||||
|
### Example metrics collection with Docker
|
||||||
|
|
||||||
|
The example instructions below were tested on Windows 10 using Docker Desktop
|
||||||
|
with the WSL 2 backend:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Create a storage volume for Grafana (once)
|
||||||
|
docker volume create grafana-storage
|
||||||
|
|
||||||
|
# Create a storage volume for Prometheus (once)
|
||||||
|
docker volume create prometheus-storage
|
||||||
|
|
||||||
|
# Run Prometheus
|
||||||
|
# You will need to modify ~/contrib/metrics/prometheus.yaml to match the
|
||||||
|
# endpoint configured with -prometheusmetrics (and possibly also for your Docker
|
||||||
|
# network setup).
|
||||||
|
docker run --detach -p 9090:9090 --volume prometheus-storage:/prometheus --volume ~/contrib/metrics/prometheus.yaml:/etc/prometheus/prometheus.yml prom/prometheus
|
||||||
|
|
||||||
|
# Run Grafana
|
||||||
|
docker run --detach -p 3030:3030 --env GF_SERVER_HTTP_PORT=3030 --volume grafana-storage:/var/lib/grafana grafana/grafana
|
||||||
|
```
|
|
@ -4,3 +4,25 @@ release-notes at release time)
|
||||||
Notable changes
|
Notable changes
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
Prometheus metrics
|
||||||
|
------------------
|
||||||
|
|
||||||
|
`zcashd` can now be configured to optionally expose an HTTP server that acts as
|
||||||
|
a Prometheus scrape endpoint. The server will respond to `GET` requests on any
|
||||||
|
request path.
|
||||||
|
|
||||||
|
To enable the endpoint, add `-prometheusport=<port>` to your `zcashd`
|
||||||
|
configuration (either in `zcash.conf` or on the command line). After
|
||||||
|
restarting `zcashd` you can then test the endpoint by querying it with e.g.
|
||||||
|
`curl http://127.0.0.1:<port>`.
|
||||||
|
|
||||||
|
By default, access is restricted to localhost. This can be expanded with
|
||||||
|
`-metricsallowip=<ip>`, which can specify IPs or subnets. Note that HTTPS is not
|
||||||
|
supported, and therefore connections to the endpoint are not encrypted or
|
||||||
|
authenticated. Access to the endpoint should be assumed to compromise the
|
||||||
|
privacy of node operations, by the provided metrics and/or by timing side
|
||||||
|
channels. Non-localhost access is **strongly discouraged** if the node has a
|
||||||
|
wallet holding live funds.
|
||||||
|
|
||||||
|
The specific metrics names may change in subsequent releases, in particular to
|
||||||
|
improve interoperability with `zebrad`.
|
||||||
|
|
39
src/init.cpp
39
src/init.cpp
|
@ -64,6 +64,8 @@
|
||||||
#include "zmq/zmqnotificationinterface.h"
|
#include "zmq/zmqnotificationinterface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <rust/metrics.h>
|
||||||
|
|
||||||
#include "librustzcash.h"
|
#include "librustzcash.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -410,6 +412,15 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
strUsage += HelpMessageOpt("-zmqpubrawtx=<address>", _("Enable publish raw transaction in <address>"));
|
strUsage += HelpMessageOpt("-zmqpubrawtx=<address>", _("Enable publish raw transaction in <address>"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
strUsage += HelpMessageGroup(_("Monitoring options:"));
|
||||||
|
strUsage += HelpMessageOpt("-metricsallowip=<ip>", _("Allow metrics connections from specified source. "
|
||||||
|
"Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). "
|
||||||
|
"This option can be specified multiple times. (default: only localhost)"));
|
||||||
|
strUsage += HelpMessageOpt("-metricsbind=<addr>", _("Bind to given address to listen for metrics connections. (default: bind to all interfaces)"));
|
||||||
|
strUsage += HelpMessageOpt("-prometheusport=<port>", _("Expose node metrics in the Prometheus exposition format. "
|
||||||
|
"An HTTP listener will be started on <port>, which responds to GET requests on any request path. "
|
||||||
|
"Use -metricsallowip and -metricsbind to control access."));
|
||||||
|
|
||||||
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
|
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
|
||||||
if (showDebug)
|
if (showDebug)
|
||||||
{
|
{
|
||||||
|
@ -1221,6 +1232,34 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
// Count uptime
|
// Count uptime
|
||||||
MarkStartTime();
|
MarkStartTime();
|
||||||
|
|
||||||
|
int prometheusPort = GetArg("-prometheusport", -1);
|
||||||
|
if (prometheusPort > 0) {
|
||||||
|
const std::vector<std::string>& vAllow = mapMultiArgs["-metricsallowip"];
|
||||||
|
std::vector<const char*> vAllowCstr;
|
||||||
|
for (const std::string& strAllow : vAllow) {
|
||||||
|
vAllowCstr.push_back(strAllow.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string metricsBind = GetArg("-metricsbind", "");
|
||||||
|
const char* metricsBindCstr = nullptr;
|
||||||
|
if (!metricsBind.empty()) {
|
||||||
|
metricsBindCstr = metricsBind.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start up the metrics runtime. This spins off a Rust thread that runs
|
||||||
|
// the Prometheus exporter. We just let this thread die at process end.
|
||||||
|
LogPrintf("metrics thread start");
|
||||||
|
if (!metrics_run(metricsBindCstr, vAllowCstr.data(), vAllowCstr.size(), prometheusPort)) {
|
||||||
|
return InitError(strprintf(_("Failed to start Prometheus metrics exporter")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose binary metadata to metrics, using a single time series with value 1.
|
||||||
|
// https://www.robustperception.io/exposing-the-software-version-to-prometheus
|
||||||
|
MetricsIncrementCounter(
|
||||||
|
"zcashd.build.info",
|
||||||
|
"version", CLIENT_BUILD.c_str());
|
||||||
|
|
||||||
if ((chainparams.NetworkIDString() != "regtest") &&
|
if ((chainparams.NetworkIDString() != "regtest") &&
|
||||||
GetBoolArg("-showmetrics", isatty(STDOUT_FILENO)) &&
|
GetBoolArg("-showmetrics", isatty(STDOUT_FILENO)) &&
|
||||||
!fPrintToConsole && !GetBoolArg("-daemon", false)) {
|
!fPrintToConsole && !GetBoolArg("-daemon", false)) {
|
||||||
|
|
95
src/main.cpp
95
src/main.cpp
|
@ -46,6 +46,7 @@
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#include <rust/ed25519.h>
|
#include <rust/ed25519.h>
|
||||||
|
#include <rust/metrics.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -1692,6 +1693,10 @@ bool AcceptToMemoryPool(
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.EnsureSizeLimit();
|
pool.EnsureSizeLimit();
|
||||||
|
|
||||||
|
MetricsGauge("zcash.mempool.size.transactions", mempool.size());
|
||||||
|
MetricsGauge("zcash.mempool.size.bytes", mempool.GetTotalTxSize());
|
||||||
|
MetricsGauge("zcash.mempool.usage.bytes", mempool.DynamicMemoryUsage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3211,6 +3216,85 @@ void PruneAndFlush() {
|
||||||
FlushStateToDisk(Params(), state, FLUSH_STATE_NONE);
|
FlushStateToDisk(Params(), state, FLUSH_STATE_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PoolMetrics {
|
||||||
|
std::optional<size_t> created;
|
||||||
|
std::optional<size_t> spent;
|
||||||
|
std::optional<size_t> unspent;
|
||||||
|
std::optional<CAmount> value;
|
||||||
|
|
||||||
|
static PoolMetrics Sprout(CBlockIndex *pindex, CCoinsViewCache *view) {
|
||||||
|
PoolMetrics stats;
|
||||||
|
stats.value = pindex->nChainSproutValue;
|
||||||
|
|
||||||
|
// RewindBlockIndex calls DisconnectTip in a way that can potentially cause a
|
||||||
|
// Sprout tree to not exist (the rewind_index RPC test reliably triggers this).
|
||||||
|
// We only need to access the tree during disconnection for metrics purposes, and
|
||||||
|
// we will never encounter this rewind situation on either mainnet or testnet, so
|
||||||
|
// if we can't access the Sprout tree we default to zero.
|
||||||
|
SproutMerkleTree sproutTree;
|
||||||
|
if (view->GetSproutAnchorAt(pindex->hashFinalSproutRoot, sproutTree)) {
|
||||||
|
stats.created = sproutTree.size();
|
||||||
|
} else {
|
||||||
|
stats.created = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PoolMetrics Sapling(CBlockIndex *pindex, CCoinsViewCache *view) {
|
||||||
|
PoolMetrics stats;
|
||||||
|
stats.value = pindex->nChainSaplingValue;
|
||||||
|
|
||||||
|
// Before Sapling activation, the Sapling commitment set is empty.
|
||||||
|
SaplingMerkleTree saplingTree;
|
||||||
|
if (view->GetSaplingAnchorAt(pindex->hashFinalSaplingRoot, saplingTree)) {
|
||||||
|
stats.created = saplingTree.size();
|
||||||
|
} else {
|
||||||
|
stats.created = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PoolMetrics Transparent(CBlockIndex *pindex, CCoinsViewCache *view) {
|
||||||
|
PoolMetrics stats;
|
||||||
|
// TODO: Collect transparent pool value.
|
||||||
|
|
||||||
|
// TODO: Figure out a way to efficiently collect UTXO set metrics
|
||||||
|
// (view->GetStats() is too slow to call during block verification).
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RenderPoolMetrics(poolName, poolMetrics) \
|
||||||
|
do { \
|
||||||
|
if (poolMetrics.created) { \
|
||||||
|
MetricsStaticGauge( \
|
||||||
|
"zcash.pool.notes.created", \
|
||||||
|
poolMetrics.created.value(), \
|
||||||
|
"name", poolName); \
|
||||||
|
} \
|
||||||
|
if (poolMetrics.spent) { \
|
||||||
|
MetricsStaticGauge( \
|
||||||
|
"zcash.pool.notes.spent", \
|
||||||
|
poolMetrics.spent.value(), \
|
||||||
|
"name", poolName); \
|
||||||
|
} \
|
||||||
|
if (poolMetrics.unspent) { \
|
||||||
|
MetricsStaticGauge( \
|
||||||
|
"zcash.pool.notes.unspent", \
|
||||||
|
poolMetrics.unspent.value(), \
|
||||||
|
"name", poolName); \
|
||||||
|
} \
|
||||||
|
if (poolMetrics.value) { \
|
||||||
|
MetricsStaticGauge( \
|
||||||
|
"zcash.pool.value.zatoshis", \
|
||||||
|
poolMetrics.value.value(), \
|
||||||
|
"name", poolName); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/** Update chainActive and related internal data structures. */
|
/** Update chainActive and related internal data structures. */
|
||||||
void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
|
void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
|
||||||
chainActive.SetTip(pindexNew);
|
chainActive.SetTip(pindexNew);
|
||||||
|
@ -3238,6 +3322,15 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
|
||||||
"progress", progress.c_str(),
|
"progress", progress.c_str(),
|
||||||
"cache", cache.c_str());
|
"cache", cache.c_str());
|
||||||
|
|
||||||
|
auto sproutPool = PoolMetrics::Sprout(pindexNew, pcoinsTip);
|
||||||
|
auto saplingPool = PoolMetrics::Sapling(pindexNew, pcoinsTip);
|
||||||
|
auto transparentPool = PoolMetrics::Transparent(pindexNew, pcoinsTip);
|
||||||
|
|
||||||
|
MetricsGauge("zcash.chain.verified.block.height", pindexNew->nHeight);
|
||||||
|
RenderPoolMetrics("sprout", sproutPool);
|
||||||
|
RenderPoolMetrics("sapling", saplingPool);
|
||||||
|
RenderPoolMetrics("transparent", transparentPool);
|
||||||
|
|
||||||
cvBlockChange.notify_all();
|
cvBlockChange.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3369,6 +3462,8 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
|
||||||
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
|
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
|
||||||
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
|
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
|
||||||
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
|
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
|
||||||
|
MetricsIncrementCounter("zcash.chain.verified.block.total");
|
||||||
|
MetricsHistogram("zcash.chain.verified.block.seconds", (nTime6 - nTime1) * 0.000001);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
src/net.cpp
24
src/net.cpp
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <rust/metrics.h>
|
||||||
|
|
||||||
// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
|
// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
|
||||||
#define DUMP_ADDRESSES_INTERVAL 900
|
#define DUMP_ADDRESSES_INTERVAL 900
|
||||||
|
|
||||||
|
@ -702,6 +704,11 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
|
||||||
|
|
||||||
if (msg.complete()) {
|
if (msg.complete()) {
|
||||||
msg.nTime = GetTimeMicros();
|
msg.nTime = GetTimeMicros();
|
||||||
|
std::string strCommand = SanitizeString(msg.hdr.GetCommand());
|
||||||
|
MetricsIncrementCounter("zcash.net.in.messages", "command", strCommand.c_str());
|
||||||
|
MetricsCounter(
|
||||||
|
"zcash.net.in.bytes", msg.hdr.nMessageSize,
|
||||||
|
"command", strCommand.c_str());
|
||||||
messageHandlerCondition.notify_one();
|
messageHandlerCondition.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1104,6 +1111,7 @@ void ThreadSocketHandler()
|
||||||
}
|
}
|
||||||
if (vNodesSize != nPrevNodeCount) {
|
if (vNodesSize != nPrevNodeCount) {
|
||||||
nPrevNodeCount = vNodesSize;
|
nPrevNodeCount = vNodesSize;
|
||||||
|
MetricsGauge("zcash.net.peers", nPrevNodeCount);
|
||||||
uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
|
uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2001,12 +2009,14 @@ void CNode::RecordBytesRecv(uint64_t bytes)
|
||||||
{
|
{
|
||||||
LOCK(cs_totalBytesRecv);
|
LOCK(cs_totalBytesRecv);
|
||||||
nTotalBytesRecv += bytes;
|
nTotalBytesRecv += bytes;
|
||||||
|
MetricsCounter("zcash.net.in.bytes.total", bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNode::RecordBytesSent(uint64_t bytes)
|
void CNode::RecordBytesSent(uint64_t bytes)
|
||||||
{
|
{
|
||||||
LOCK(cs_totalBytesSent);
|
LOCK(cs_totalBytesSent);
|
||||||
nTotalBytesSent += bytes;
|
nTotalBytesSent += bytes;
|
||||||
|
MetricsCounter("zcash.net.out.bytes.total", bytes);
|
||||||
|
|
||||||
uint64_t now = GetTime();
|
uint64_t now = GetTime();
|
||||||
if (nMaxOutboundCycleStartTime + nMaxOutboundTimeframe < now)
|
if (nMaxOutboundCycleStartTime + nMaxOutboundTimeframe < now)
|
||||||
|
@ -2218,11 +2228,11 @@ CNode::~CNode()
|
||||||
void CNode::ReloadTracingSpan()
|
void CNode::ReloadTracingSpan()
|
||||||
{
|
{
|
||||||
if (fLogIPs) {
|
if (fLogIPs) {
|
||||||
span = TracingSpanFields("info", "net", "Peer",
|
span = TracingSpan("info", "net", "Peer",
|
||||||
"id", idStr.c_str(),
|
"id", idStr.c_str(),
|
||||||
"addr", addrName.c_str());
|
"addr", addrName.c_str());
|
||||||
} else {
|
} else {
|
||||||
span = TracingSpanFields("info", "net", "Peer",
|
span = TracingSpan("info", "net", "Peer",
|
||||||
"id", idStr.c_str());
|
"id", idStr.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2265,13 +2275,16 @@ void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSen
|
||||||
{
|
{
|
||||||
ENTER_CRITICAL_SECTION(cs_vSend);
|
ENTER_CRITICAL_SECTION(cs_vSend);
|
||||||
assert(ssSend.size() == 0);
|
assert(ssSend.size() == 0);
|
||||||
|
assert(strSendCommand.empty());
|
||||||
ssSend << CMessageHeader(Params().MessageStart(), pszCommand, 0);
|
ssSend << CMessageHeader(Params().MessageStart(), pszCommand, 0);
|
||||||
LogPrint("net", "sending: %s ", SanitizeString(pszCommand));
|
strSendCommand = SanitizeString(pszCommand);
|
||||||
|
LogPrint("net", "sending: %s ", strSendCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
|
void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
|
||||||
{
|
{
|
||||||
ssSend.clear();
|
ssSend.clear();
|
||||||
|
strSendCommand.clear();
|
||||||
|
|
||||||
LEAVE_CRITICAL_SECTION(cs_vSend);
|
LEAVE_CRITICAL_SECTION(cs_vSend);
|
||||||
|
|
||||||
|
@ -2280,6 +2293,7 @@ void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
|
||||||
|
|
||||||
void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
|
void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
|
||||||
{
|
{
|
||||||
|
MetricsIncrementCounter("zcash.net.out.messages", "command", strSendCommand.c_str());
|
||||||
// The -*messagestest options are intentionally not documented in the help message,
|
// The -*messagestest options are intentionally not documented in the help message,
|
||||||
// since they are only used during development to debug the networking code and are
|
// since they are only used during development to debug the networking code and are
|
||||||
// not intended for end-users.
|
// not intended for end-users.
|
||||||
|
@ -2313,6 +2327,10 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
|
||||||
std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
|
std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
|
||||||
ssSend.GetAndClear(*it);
|
ssSend.GetAndClear(*it);
|
||||||
nSendSize += (*it).size();
|
nSendSize += (*it).size();
|
||||||
|
MetricsCounter(
|
||||||
|
"zcash.net.out.bytes", (*it).size(),
|
||||||
|
"command", strSendCommand.c_str());
|
||||||
|
strSendCommand.clear();
|
||||||
|
|
||||||
// If write queue empty, attempt "optimistic write"
|
// If write queue empty, attempt "optimistic write"
|
||||||
if (it == vSendMsg.begin())
|
if (it == vSendMsg.begin())
|
||||||
|
|
|
@ -256,6 +256,7 @@ public:
|
||||||
uint64_t nServices;
|
uint64_t nServices;
|
||||||
SOCKET hSocket;
|
SOCKET hSocket;
|
||||||
CDataStream ssSend;
|
CDataStream ssSend;
|
||||||
|
std::string strSendCommand; // Current command being assembled in ssSend
|
||||||
size_t nSendSize; // total size of all vSendMsg entries
|
size_t nSendSize; // total size of all vSendMsg entries
|
||||||
size_t nSendOffset; // offset inside the first vSendMsg already sent
|
size_t nSendOffset; // offset inside the first vSendMsg already sent
|
||||||
uint64_t nSendBytes;
|
uint64_t nSendBytes;
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
// Copyright (c) 2019 Will Wray https://keybase.io/willwray
|
||||||
|
// Copyright (c) 2020 The Zcash developers
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt
|
||||||
|
//
|
||||||
|
// Repo: https://github.com/willwray/VA_OPT
|
||||||
|
|
||||||
|
#ifndef ZCASH_RUST_INCLUDE_RUST_VA_OPT_H
|
||||||
|
#define ZCASH_RUST_INCLUDE_RUST_VA_OPT_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
VA_OPT.hpp
|
||||||
|
==========
|
||||||
|
|
||||||
|
Preprocessor utilities for testing emptiness of macro arguments
|
||||||
|
and for conditional expansion based on the emptiness of ARGS.
|
||||||
|
|
||||||
|
VA_OPT_SUPPORT(?)
|
||||||
|
1 if __VA_OPT__ support is detected else 0 (see platform note).
|
||||||
|
|
||||||
|
C++20's __VA_OPT__ finally provides a reliable test for empty ARGS.
|
||||||
|
The following macros use __VA_OPT__, if detected, otherwise they
|
||||||
|
provide 'polyfill' fallbacks (though with some failing edge cases).
|
||||||
|
|
||||||
|
IS_EMPTY(...)
|
||||||
|
1 if the ... ARGS is empty else 0.
|
||||||
|
|
||||||
|
IFN(...)
|
||||||
|
If ... ARGS are not empty then a trailing 'paren expression' (X)
|
||||||
|
is deparenthesized to X else the trailing (X) term is consumed.
|
||||||
|
E.g. IFN()(N) vanishes, while IFN(NotEmpty)(N) -> N
|
||||||
|
|
||||||
|
In other words, IFN(ARGS) is like __VA_OPT__, but with explicit
|
||||||
|
(ARGS) in place of an implicit __VA_ARGS__ check.
|
||||||
|
|
||||||
|
IFE(...)
|
||||||
|
If ... ARGS is empty expand trailing 'paren expression' (X) to X
|
||||||
|
else if ARGS are not empty consume the trailing paren expression.
|
||||||
|
E.g. IFE(NotEmpty)(E) vanishes, while IFE()(E) -> E
|
||||||
|
|
||||||
|
IFNE(...)(N,E...)
|
||||||
|
If ... ARGS are not empty expands to N else expands to E...
|
||||||
|
E.g. IFNE(ARG)(X,()) is equivalent to IFN(ARG)(X)IFE(ARG)(())
|
||||||
|
both put back a terminating () removed by the outer macro call.
|
||||||
|
|
||||||
|
Without VA_OPT_SUPPORT these 'emptiness' macros are not perfect;
|
||||||
|
IS_EMPTY, IFN, IFE, IFNE may cause a compile error ('too few args')
|
||||||
|
if the argument is a function-like macro name that expects ARG(s).
|
||||||
|
|
||||||
|
IBP(...)
|
||||||
|
IS_BEGIN_PARENS macro to test if an argument is parenthesised:
|
||||||
|
1 if ... ARGS begins with a 'paren expression' else 0.
|
||||||
|
|
||||||
|
Platform note: Current Sept 2019 __VA_OPT__ support:
|
||||||
|
-------------
|
||||||
|
Clang -std=c++2a enables it. GCC has it enabled without -std=c++2a
|
||||||
|
but warns "__VA_OPT__ is not available until C++2a" if another -std
|
||||||
|
flag is supplied along with -pedantic (dont know how to supress it).
|
||||||
|
MSVC TBD
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
Props to pre-pro pioneers, particularly Paul Mensonides.
|
||||||
|
The 'emptiness' methods are adapted from BOOST_VMD_IS_EMPTY which,
|
||||||
|
. in turn, depends on BOOST Preprocessor's BOOST_PP_IS_BEGIN_PARENS
|
||||||
|
(adapted and exposed here as IBP 'Is Begin Parens'):
|
||||||
|
www.boost.org/doc/libs/1_71_0/libs/vmd
|
||||||
|
www.boost.org/doc/libs/1_71_0/libs/preprocessor
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VA_ARG1(A0,A1,...) A1
|
||||||
|
// VA_EMPTY works only if __VA_OPT__ is supported, else always -> 1
|
||||||
|
#define VA_EMPTY(...) VA_ARG1(__VA_OPT__(,)0,1,)
|
||||||
|
|
||||||
|
// VA_OPT_SUPPORT helper macro for __VA_OPT__ feature detection.
|
||||||
|
// Adapted from https://stackoverflow.com/a/48045656/7443483
|
||||||
|
// Use as #if VA_OPT_SUPPORT(?)
|
||||||
|
#define VA_OPT_SUPPORT ! VA_EMPTY
|
||||||
|
|
||||||
|
#if VA_OPT_SUPPORT(?)
|
||||||
|
|
||||||
|
# define IS_EMPTY(...) VA_EMPTY(__VA_ARGS__)
|
||||||
|
# define IFN(...) VA_EAT __VA_OPT__(()VA_IDENT)
|
||||||
|
# define IFE(...) VA_IDENT __VA_OPT__(()VA_EAT)
|
||||||
|
# define IFNE(...) VA_ARGTAIL __VA_OPT__((,)VA_ARG0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define IS_EMPTY(...) IFP(IBP(__VA_ARGS__))(IE_GEN_0,IE_IBP)(__VA_ARGS__)
|
||||||
|
# define IFN(...) IFP(IBP(__VA_ARGS__))(GEN_IDENT,EAT_OR_IDENT)(__VA_ARGS__)
|
||||||
|
# define IFE(...) IFP(IBP(__VA_ARGS__))(GEN_EAT,IDENT_OR_EAT)(__VA_ARGS__)
|
||||||
|
# define IFNE(...) IFP(IBP(__VA_ARGS__))(GEN_ARGTAIL,ARG0_OR_TAIL)(__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define VA_EAT(...)
|
||||||
|
#define VA_IDENT(...) __VA_ARGS__
|
||||||
|
#define VA_ARG0_(A0,...) A0
|
||||||
|
#define VA_ARG0(...) VA_ARG0_(__VA_ARGS__)
|
||||||
|
#define VA_ARGTAIL_(A0,...) __VA_ARGS__
|
||||||
|
#define VA_ARGTAIL(...) VA_ARGTAIL_(__VA_ARGS__)
|
||||||
|
|
||||||
|
// IFP helper macros to test IBP for IFN and IS_EMPTY
|
||||||
|
#define IFP_0(T,...) __VA_ARGS__
|
||||||
|
#define IFP_1(T,...) T
|
||||||
|
|
||||||
|
#define IFP_CAT(A,...) A##__VA_ARGS__
|
||||||
|
#define IFP(BP) IFP_CAT(IFP_,BP)
|
||||||
|
|
||||||
|
// IS_BEGIN_PAREN helper macros adapted from BOOST VMD
|
||||||
|
#define IBP_CAT_(A,...) A##__VA_ARGS__
|
||||||
|
#define IBP_CAT(A,...) IBP_CAT_(A,__VA_ARGS__)
|
||||||
|
|
||||||
|
#define IBP_ARG0_(A,...) A
|
||||||
|
#define IBP_ARG0(...) IBP_ARG0_(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define IBP_IS_ARGS(...) 1
|
||||||
|
|
||||||
|
#define IBP_1 1,
|
||||||
|
#define IBP_IBP_IS_ARGS 0,
|
||||||
|
|
||||||
|
// IBP IS_BEGIN_PAREN returns 1 or 0 if ... ARGS is parenthesised
|
||||||
|
#define IBP(...) IBP_ARG0(IBP_CAT(IBP_, IBP_IS_ARGS __VA_ARGS__))
|
||||||
|
|
||||||
|
// IFN, IFE, IFNE and IF_EMPTY helpers without __VA_OPT__ support
|
||||||
|
#if ! VA_OPT_SUPPORT(?)
|
||||||
|
|
||||||
|
# define IBP_(T,...) IBP_ARG0(IBP_CAT(IF##T##_, IBP_IS_ARGS __VA_ARGS__))
|
||||||
|
|
||||||
|
// IS_EMPTY helper macros, depend on IBP
|
||||||
|
# define IE_REDUCE_IBP(...) ()
|
||||||
|
# define IE_GEN_0(...) 0
|
||||||
|
# define IE_IBP(...) IBP(IE_REDUCE_IBP __VA_ARGS__ ())
|
||||||
|
|
||||||
|
# define GEN_IDENT(...) VA_IDENT
|
||||||
|
# define GEN_EAT(...) VA_EAT
|
||||||
|
# define GEN_ARGTAIL(...) VA_ARGTAIL
|
||||||
|
# define GEN_ARG0(...) VA_ARG0
|
||||||
|
|
||||||
|
// IFN, IFE, IFNE helper macros
|
||||||
|
# define EAT_OR_IDENT(...) IBP_(N,IE_REDUCE_IBP __VA_ARGS__ ())
|
||||||
|
# define IFN_1 VA_EAT,
|
||||||
|
# define IFN_IBP_IS_ARGS VA_IDENT,
|
||||||
|
|
||||||
|
# define IDENT_OR_EAT(...) IBP_(E,IE_REDUCE_IBP __VA_ARGS__ ())
|
||||||
|
# define IFE_1 VA_IDENT,
|
||||||
|
# define IFE_IBP_IS_ARGS VA_EAT,
|
||||||
|
|
||||||
|
# define ARG0_OR_TAIL(...) IBP_(NE,IE_REDUCE_IBP __VA_ARGS__ ())
|
||||||
|
# define IFNE_1 VA_ARGTAIL,
|
||||||
|
# define IFNE_IBP_IS_ARGS VA_ARG0,
|
||||||
|
|
||||||
|
#endif // IFN and IF_EMPTY defs
|
||||||
|
|
||||||
|
#endif // ZCASH_RUST_INCLUDE_RUST_VA_OPT_H
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) 2020 Jack Grigg
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||||
|
|
||||||
|
#ifndef ZCASH_RUST_INCLUDE_RUST_HELPERS_H
|
||||||
|
#define ZCASH_RUST_INCLUDE_RUST_HELPERS_H
|
||||||
|
|
||||||
|
#include "rust/map.h"
|
||||||
|
#include "rust/VA_OPT.hpp"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper macros
|
||||||
|
//
|
||||||
|
|
||||||
|
#define MAP_PAIR_LIST0(f, x, y, peek, ...) f(x, y) MAP_LIST_NEXT(peek, MAP_PAIR_LIST1)(f, peek, __VA_ARGS__)
|
||||||
|
#define MAP_PAIR_LIST1(f, x, y, peek, ...) f(x, y) MAP_LIST_NEXT(peek, MAP_PAIR_LIST0)(f, peek, __VA_ARGS__)
|
||||||
|
|
||||||
|
/// Applies the function macro `f` to each pair of the remaining parameters and
|
||||||
|
/// inserts commas between the results.
|
||||||
|
#define MAP_PAIR_LIST(f, ...) EVAL(MAP_PAIR_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||||
|
|
||||||
|
#define T_FIELD_NAME(x, y) x
|
||||||
|
#define T_FIELD_VALUE(x, y) y
|
||||||
|
|
||||||
|
#define T_FIELD_NAMES(...) IFN(__VA_ARGS__)(MAP_PAIR_LIST(T_FIELD_NAME, __VA_ARGS__))
|
||||||
|
#define T_FIELD_VALUES(...) IFN(__VA_ARGS__)(MAP_PAIR_LIST(T_FIELD_VALUE, __VA_ARGS__))
|
||||||
|
|
||||||
|
#define T_DOUBLEESCAPE(a) #a
|
||||||
|
#define T_ESCAPEQUOTE(a) T_DOUBLEESCAPE(a)
|
||||||
|
|
||||||
|
// Computes the length of the given array. This is COUNT_OF from Chromium.
|
||||||
|
#define T_ARRLEN(x) ((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x])))))
|
||||||
|
|
||||||
|
#endif // ZCASH_RUST_INCLUDE_RUST_HELPERS_H
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 William Swanson
|
* Copyright (C) 2012 William Swanson
|
||||||
|
* Copyright (C) 2020 The Zcash developers
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
|
@ -26,8 +27,8 @@
|
||||||
* prior written authorization from the authors.
|
* prior written authorization from the authors.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZCASH_RUST_INCLUDE_TRACING_MAP_H
|
#ifndef ZCASH_RUST_INCLUDE_RUST_MAP_H
|
||||||
#define ZCASH_RUST_INCLUDE_TRACING_MAP_H
|
#define ZCASH_RUST_INCLUDE_RUST_MAP_H
|
||||||
|
|
||||||
#define EVAL0(...) __VA_ARGS__
|
#define EVAL0(...) __VA_ARGS__
|
||||||
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
|
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
|
||||||
|
@ -67,4 +68,4 @@
|
||||||
*/
|
*/
|
||||||
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||||
|
|
||||||
#endif // ZCASH_RUST_INCLUDE_TRACING_MAP_H
|
#endif // ZCASH_RUST_INCLUDE_RUST_MAP_H
|
|
@ -0,0 +1,314 @@
|
||||||
|
// Copyright (c) 2020 The Zcash developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||||
|
|
||||||
|
#ifndef ZCASH_RUST_INCLUDE_RUST_METRICS_H
|
||||||
|
#define ZCASH_RUST_INCLUDE_RUST_METRICS_H
|
||||||
|
|
||||||
|
#include "rust/helpers.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Initializes the metrics runtime and runs the Prometheus exporter in a new
|
||||||
|
/// thread.
|
||||||
|
///
|
||||||
|
/// bind_address is an IP address to bind to, or empty to use the default.
|
||||||
|
///
|
||||||
|
/// Returns false on any error.
|
||||||
|
bool metrics_run(
|
||||||
|
const char* bind_address,
|
||||||
|
const char* const* allow_ips,
|
||||||
|
size_t allow_ips_len,
|
||||||
|
uint16_t prometheus_port);
|
||||||
|
|
||||||
|
struct MetricsCallsite;
|
||||||
|
typedef struct MetricsCallsite MetricsCallsite;
|
||||||
|
|
||||||
|
struct MetricsKey;
|
||||||
|
typedef struct MetricsKey MetricsKey;
|
||||||
|
|
||||||
|
/// Creates a metrics callsite.
|
||||||
|
///
|
||||||
|
/// This API supports labels that MUST have static values. For non-static label
|
||||||
|
/// values, use `metrics_key`.
|
||||||
|
///
|
||||||
|
/// You should usually call one of the helper macros such as `MetricsCounter`
|
||||||
|
/// instead of calling this directly.
|
||||||
|
///
|
||||||
|
/// This MUST ONLY be called to assign a `static MetricsCallsite*`, and all
|
||||||
|
/// string arguments MUST be static `const char*` constants, and MUST be valid
|
||||||
|
/// UTF-8.
|
||||||
|
MetricsCallsite* metrics_callsite(
|
||||||
|
const char* name,
|
||||||
|
const char* const* label_names,
|
||||||
|
const char* const* label_values,
|
||||||
|
size_t labels_len);
|
||||||
|
|
||||||
|
/// Creates a metrics key.
|
||||||
|
///
|
||||||
|
/// This API supports labels that may not have static values, and is intended
|
||||||
|
/// to be called for each metrics callsite invocation. As such, it returns null
|
||||||
|
/// if a metrics recorder is not installed, to save on construction costs.
|
||||||
|
///
|
||||||
|
/// You should usually call one of the helper macros such as `MetricsCounter`
|
||||||
|
/// instead of calling this directly.
|
||||||
|
///
|
||||||
|
/// API requirements:
|
||||||
|
/// - label_names and label_values, if not null, MUST be the same length.
|
||||||
|
/// - All string arguments MUST be valid UTF-8.
|
||||||
|
MetricsKey* metrics_key(
|
||||||
|
const char* name,
|
||||||
|
const char* const* label_names,
|
||||||
|
const char* const* label_values,
|
||||||
|
size_t labels_len);
|
||||||
|
|
||||||
|
/// Increments a counter.
|
||||||
|
///
|
||||||
|
/// Counters represent a single monotonic value, which means the value can only
|
||||||
|
/// be incremented, not decremented, and always starts out with an initial value
|
||||||
|
/// of zero.
|
||||||
|
void metrics_static_increment_counter(const MetricsCallsite* callsite, uint64_t value);
|
||||||
|
|
||||||
|
/// Increments a counter.
|
||||||
|
///
|
||||||
|
/// Counters represent a single monotonic value, which means the value can only
|
||||||
|
/// be incremented, not decremented, and always starts out with an initial value
|
||||||
|
/// of zero.
|
||||||
|
void metrics_increment_counter(MetricsKey* key, uint64_t value);
|
||||||
|
|
||||||
|
/// Updates a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
void metrics_static_update_gauge(const MetricsCallsite* callsite, double value);
|
||||||
|
|
||||||
|
/// Updates a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
void metrics_update_gauge(MetricsKey* callsite, double value);
|
||||||
|
|
||||||
|
/// Increments a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
void metrics_static_increment_gauge(const MetricsCallsite* callsite, double value);
|
||||||
|
|
||||||
|
/// Increments a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
void metrics_increment_gauge(MetricsKey* callsite, double value);
|
||||||
|
|
||||||
|
/// Decrements a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
void metrics_static_decrement_gauge(const MetricsCallsite* callsite, double value);
|
||||||
|
|
||||||
|
/// Decrements a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
void metrics_decrement_gauge(MetricsKey* callsite, double value);
|
||||||
|
|
||||||
|
/// Records a histogram.
|
||||||
|
///
|
||||||
|
/// Histograms measure the distribution of values for a given set of
|
||||||
|
/// measurements, and start with no initial values.
|
||||||
|
void metrics_static_record_histogram(const MetricsCallsite* callsite, double value);
|
||||||
|
|
||||||
|
/// Records a histogram.
|
||||||
|
///
|
||||||
|
/// Histograms measure the distribution of values for a given set of
|
||||||
|
/// measurements, and start with no initial values.
|
||||||
|
void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper macros
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
// Constructs a metrics callsite.
|
||||||
|
//
|
||||||
|
// The 'static constexpr' hack ensures that all arguments are compile-time
|
||||||
|
// constants with static storage duration. The output of this macro MUST be
|
||||||
|
// stored as a static MetricsCallsite*.
|
||||||
|
#define M_CALLSITE(name, label_names, label_values) ([&] { \
|
||||||
|
static constexpr const char* _m_name = name; \
|
||||||
|
static constexpr const char* const* _m_label_names = \
|
||||||
|
label_names; \
|
||||||
|
static constexpr const char* const* _m_label_values = \
|
||||||
|
label_values; \
|
||||||
|
return metrics_callsite( \
|
||||||
|
_m_name, _m_label_names, _m_label_values, \
|
||||||
|
T_ARRLEN(label_names)); \
|
||||||
|
}())
|
||||||
|
#else
|
||||||
|
// Constructs a metrics callsite.
|
||||||
|
//
|
||||||
|
// All arguments MUST be static constants, and the output of this macro MUST be
|
||||||
|
// stored as a static MetricsCallsite*.
|
||||||
|
#define M_CALLSITE(name, label_names, label_values) \
|
||||||
|
metrics_callsite(name, label_names, label_values, T_ARRLEN(label_names))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Constructs a metrics key.
|
||||||
|
#define M_KEY(name, labels, values) \
|
||||||
|
metrics_key( \
|
||||||
|
name, \
|
||||||
|
labels, \
|
||||||
|
values, \
|
||||||
|
T_ARRLEN(labels))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Metrics
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Increments a counter.
|
||||||
|
///
|
||||||
|
/// Counters represent a single monotonic value, which means the value can only
|
||||||
|
/// be incremented, not decremented, and always starts out with an initial value
|
||||||
|
/// of zero.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsCounter(name, value, ...) \
|
||||||
|
do { \
|
||||||
|
IFE(__VA_ARGS__) \
|
||||||
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
|
metrics_static_increment_counter(CALLSITE, value);) \
|
||||||
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
const char* M_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
MetricsKey* KEY = \
|
||||||
|
M_KEY(name, M_LABELS, M_VALUES); \
|
||||||
|
metrics_increment_counter(KEY, value);) \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/// Increments a counter by one.
|
||||||
|
///
|
||||||
|
/// Counters represent a single monotonic value, which means the value can only
|
||||||
|
/// be incremented, not decremented, and always starts out with an initial value
|
||||||
|
/// of zero.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsIncrementCounter(name, ...) MetricsCounter(name, 1, __VA_ARGS__)
|
||||||
|
|
||||||
|
/// Updates a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsGauge(name, value, ...) \
|
||||||
|
do { \
|
||||||
|
IFE(__VA_ARGS__) \
|
||||||
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
|
metrics_static_update_gauge(CALLSITE, value);) \
|
||||||
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
const char* M_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
MetricsKey* KEY = \
|
||||||
|
M_KEY(name, M_LABELS, M_VALUES); \
|
||||||
|
metrics_update_gauge(KEY, value);) \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/// Updates a gauge with optional static labels.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsStaticGauge(name, value, ...) \
|
||||||
|
do { \
|
||||||
|
static constexpr const char* M_LABELS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
static constexpr const char* M_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, M_LABELS, M_VALUES); \
|
||||||
|
metrics_static_update_gauge(CALLSITE, value); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/// Increments a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsIncrementGauge(name, value, ...) \
|
||||||
|
do { \
|
||||||
|
IFE(__VA_ARGS__) \
|
||||||
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
|
metrics_static_increment_gauge(CALLSITE, value);) \
|
||||||
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
const char* M_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
MetricsKey* KEY = \
|
||||||
|
M_KEY(name, M_LABELS, M_VALUES); \
|
||||||
|
metrics_increment_gauge(KEY, value);) \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/// Decrements a gauge.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsDecrementGauge(name, value, ...) \
|
||||||
|
do { \
|
||||||
|
IFE(__VA_ARGS__) \
|
||||||
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
|
metrics_static_decrement_gauge(CALLSITE, value);) \
|
||||||
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
const char* M_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
MetricsKey* KEY = \
|
||||||
|
M_KEY(name, M_LABELS, M_VALUES); \
|
||||||
|
metrics_decrement_gauge(KEY, value);) \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/// Records a histogram.
|
||||||
|
///
|
||||||
|
/// Histograms measure the distribution of values for a given set of
|
||||||
|
/// measurements, and start with no initial values.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsHistogram(name, value, ...) \
|
||||||
|
do { \
|
||||||
|
IFE(__VA_ARGS__) \
|
||||||
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
|
metrics_static_record_histogram(CALLSITE, value);) \
|
||||||
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
const char* M_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
MetricsKey* KEY = \
|
||||||
|
M_KEY(name, M_LABELS, M_VALUES); \
|
||||||
|
metrics_record_histogram(KEY, value);) \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif // ZCASH_RUST_INCLUDE_RUST_METRICS_H
|
|
@ -5,8 +5,8 @@
|
||||||
#ifndef ZCASH_RUST_INCLUDE_TRACING_H
|
#ifndef ZCASH_RUST_INCLUDE_TRACING_H
|
||||||
#define ZCASH_RUST_INCLUDE_TRACING_H
|
#define ZCASH_RUST_INCLUDE_TRACING_H
|
||||||
|
|
||||||
|
#include "rust/helpers.h"
|
||||||
#include "rust/types.h"
|
#include "rust/types.h"
|
||||||
#include "tracing/map.h"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -107,25 +107,6 @@ void tracing_log(
|
||||||
// Helper macros
|
// Helper macros
|
||||||
//
|
//
|
||||||
|
|
||||||
#define MAP_PAIR_LIST0(f, x, y, peek, ...) f(x, y) MAP_LIST_NEXT(peek, MAP_PAIR_LIST1)(f, peek, __VA_ARGS__)
|
|
||||||
#define MAP_PAIR_LIST1(f, x, y, peek, ...) f(x, y) MAP_LIST_NEXT(peek, MAP_PAIR_LIST0)(f, peek, __VA_ARGS__)
|
|
||||||
|
|
||||||
/// Applies the function macro `f` to each pair of the remaining parameters and
|
|
||||||
/// inserts commas between the results.
|
|
||||||
#define MAP_PAIR_LIST(f, ...) EVAL(MAP_PAIR_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
|
||||||
|
|
||||||
#define T_FIELD_NAME(x, y) x
|
|
||||||
#define T_FIELD_VALUE(x, y) y
|
|
||||||
|
|
||||||
#define T_FIELD_NAMES(...) MAP_PAIR_LIST(T_FIELD_NAME, __VA_ARGS__)
|
|
||||||
#define T_FIELD_VALUES(...) MAP_PAIR_LIST(T_FIELD_VALUE, __VA_ARGS__)
|
|
||||||
|
|
||||||
#define T_DOUBLEESCAPE(a) #a
|
|
||||||
#define T_ESCAPEQUOTE(a) T_DOUBLEESCAPE(a)
|
|
||||||
|
|
||||||
// Computes the length of the given array. This is COUNT_OF from Chromium.
|
|
||||||
#define T_ARRLEN(x) ((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x])))))
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
// Constructs a tracing callsite.
|
// Constructs a tracing callsite.
|
||||||
//
|
//
|
||||||
|
@ -251,22 +232,6 @@ public:
|
||||||
};
|
};
|
||||||
} // namespace tracing
|
} // namespace tracing
|
||||||
|
|
||||||
/// Expands to a `tracing::Span` object which is used to record a span.
|
|
||||||
/// The `Span::Enter` method on that object records that the span has been
|
|
||||||
/// entered, and returns a RAII guard object, which will exit the span when
|
|
||||||
/// dropped.
|
|
||||||
///
|
|
||||||
/// level, target, and name MUST be static constants, and MUST be valid UTF-8
|
|
||||||
/// strings.
|
|
||||||
#define TracingSpan(level, target, name) ([&] { \
|
|
||||||
static constexpr const char* const FIELDS[] = {}; \
|
|
||||||
const char* T_VALUES[] = {}; \
|
|
||||||
static TracingCallsite* CALLSITE = \
|
|
||||||
T_CALLSITE(name, target, level, FIELDS, true); \
|
|
||||||
return tracing::Span( \
|
|
||||||
CALLSITE, T_VALUES, T_ARRLEN(T_VALUES)); \
|
|
||||||
}())
|
|
||||||
|
|
||||||
/// Expands to a `tracing::Span` object which is used to record a span.
|
/// Expands to a `tracing::Span` object which is used to record a span.
|
||||||
/// The `Span::Enter` method on that object records that the span has been
|
/// The `Span::Enter` method on that object records that the span has been
|
||||||
/// entered, and returns a RAII guard object, which will exit the span when
|
/// entered, and returns a RAII guard object, which will exit the span when
|
||||||
|
@ -276,7 +241,7 @@ public:
|
||||||
///
|
///
|
||||||
/// level, target, name, and all keys MUST be static constants, and MUST be
|
/// level, target, name, and all keys MUST be static constants, and MUST be
|
||||||
/// valid UTF-8 strings.
|
/// valid UTF-8 strings.
|
||||||
#define TracingSpanFields(level, target, name, ...) ([&] { \
|
#define TracingSpan(level, target, name, ...) ([&] { \
|
||||||
static constexpr const char* const FIELDS[] = \
|
static constexpr const char* const FIELDS[] = \
|
||||||
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
const char* T_VALUES[] = \
|
const char* T_VALUES[] = \
|
||||||
|
|
|
@ -0,0 +1,244 @@
|
||||||
|
use libc::{c_char, c_double};
|
||||||
|
use metrics::{try_recorder, GaugeValue, Key, KeyData, Label};
|
||||||
|
use metrics_exporter_prometheus::PrometheusBuilder;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
use std::ptr;
|
||||||
|
use std::slice;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
mod prometheus;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_run(
|
||||||
|
bind_address: *const c_char,
|
||||||
|
allow_ips: *const *const c_char,
|
||||||
|
allow_ips_len: usize,
|
||||||
|
prometheus_port: u16,
|
||||||
|
) -> bool {
|
||||||
|
// Parse any allowed IPs.
|
||||||
|
let allow_ips = unsafe { slice::from_raw_parts(allow_ips, allow_ips_len) };
|
||||||
|
let mut allow_ips: Vec<ipnet::IpNet> = match allow_ips
|
||||||
|
.iter()
|
||||||
|
.map(|&p| unsafe { CStr::from_ptr(p) })
|
||||||
|
.map(|s| {
|
||||||
|
s.to_str().ok().and_then(|s| {
|
||||||
|
s.parse()
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Invalid -metricsallowip argument '{}': {}", s, e);
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
{
|
||||||
|
Some(ips) => ips,
|
||||||
|
None => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// We always allow localhost.
|
||||||
|
allow_ips.extend(&["127.0.0.0/8".parse().unwrap(), "::1/128".parse().unwrap()]);
|
||||||
|
|
||||||
|
// Parse the address to bind to.
|
||||||
|
let bind_address = SocketAddr::new(
|
||||||
|
if allow_ips.is_empty() {
|
||||||
|
// Default to loopback if not allowing external IPs.
|
||||||
|
"127.0.0.1".parse::<IpAddr>().unwrap()
|
||||||
|
} else if bind_address.is_null() {
|
||||||
|
// No specific bind address specified, bind to any.
|
||||||
|
"0.0.0.0".parse::<IpAddr>().unwrap()
|
||||||
|
} else {
|
||||||
|
match unsafe { CStr::from_ptr(bind_address) }
|
||||||
|
.to_str()
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| s.parse::<IpAddr>().ok())
|
||||||
|
{
|
||||||
|
Some(addr) => addr,
|
||||||
|
None => {
|
||||||
|
error!("Invalid -metricsbind argument");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prometheus_port,
|
||||||
|
);
|
||||||
|
|
||||||
|
prometheus::install(bind_address, PrometheusBuilder::new(), allow_ips).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FfiCallsite {
|
||||||
|
key_data: KeyData,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_callsite(
|
||||||
|
name: *const c_char,
|
||||||
|
label_names: *const *const c_char,
|
||||||
|
label_values: *const *const c_char,
|
||||||
|
labels_len: usize,
|
||||||
|
) -> *mut FfiCallsite {
|
||||||
|
let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap();
|
||||||
|
let labels = unsafe { slice::from_raw_parts(label_names, labels_len) };
|
||||||
|
let values = unsafe { slice::from_raw_parts(label_values, labels_len) };
|
||||||
|
|
||||||
|
let stringify = |s: &[_]| {
|
||||||
|
s.iter()
|
||||||
|
.map(|&p| unsafe { CStr::from_ptr(p) })
|
||||||
|
.map(|cs| cs.to_string_lossy().into_owned())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
let labels = stringify(labels);
|
||||||
|
let values = stringify(values);
|
||||||
|
|
||||||
|
let labels: Vec<_> = labels
|
||||||
|
.into_iter()
|
||||||
|
.zip(values.into_iter())
|
||||||
|
.map(|(name, value)| Label::new(name, value))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Box::into_raw(Box::new(FfiCallsite {
|
||||||
|
key_data: KeyData::from_parts(name, labels),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FfiKey {
|
||||||
|
inner: Key,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_key(
|
||||||
|
name: *const c_char,
|
||||||
|
label_names: *const *const c_char,
|
||||||
|
label_values: *const *const c_char,
|
||||||
|
labels_len: usize,
|
||||||
|
) -> *mut FfiKey {
|
||||||
|
if try_recorder().is_none() {
|
||||||
|
// No recorder is currently installed, so don't genenerate a key. We check for
|
||||||
|
// null inside each API that consumes an FfiKey, just in case a recorder was
|
||||||
|
// installed in a racy way.
|
||||||
|
ptr::null_mut()
|
||||||
|
} else {
|
||||||
|
let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap();
|
||||||
|
let labels = unsafe { slice::from_raw_parts(label_names, labels_len) };
|
||||||
|
let values = unsafe { slice::from_raw_parts(label_values, labels_len) };
|
||||||
|
|
||||||
|
let stringify = |s: &[_]| {
|
||||||
|
s.iter()
|
||||||
|
.map(|&p| unsafe { CStr::from_ptr(p) })
|
||||||
|
.map(|cs| cs.to_string_lossy().into_owned())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
let labels = stringify(labels);
|
||||||
|
let values = stringify(values);
|
||||||
|
|
||||||
|
let labels: Vec<_> = labels
|
||||||
|
.into_iter()
|
||||||
|
.zip(values.into_iter())
|
||||||
|
.map(|(name, value)| Label::new(name, value))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Box::into_raw(Box::new(FfiKey {
|
||||||
|
inner: Key::Owned(KeyData::from_parts(name, labels)),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_static_increment_counter(callsite: *const FfiCallsite, value: u64) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
let callsite = unsafe { callsite.as_ref().unwrap() };
|
||||||
|
recorder.increment_counter(Key::Borrowed(&callsite.key_data), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_increment_counter(key: *mut FfiKey, value: u64) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
if !key.is_null() {
|
||||||
|
let key = unsafe { Box::from_raw(key) };
|
||||||
|
recorder.increment_counter(key.inner, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_static_update_gauge(callsite: *const FfiCallsite, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
let callsite = unsafe { callsite.as_ref().unwrap() };
|
||||||
|
recorder.update_gauge(
|
||||||
|
Key::Borrowed(&callsite.key_data),
|
||||||
|
GaugeValue::Absolute(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_update_gauge(key: *mut FfiKey, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
if !key.is_null() {
|
||||||
|
let key = unsafe { Box::from_raw(key) };
|
||||||
|
recorder.update_gauge(key.inner, GaugeValue::Absolute(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_static_increment_gauge(callsite: *const FfiCallsite, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
let callsite = unsafe { callsite.as_ref().unwrap() };
|
||||||
|
recorder.update_gauge(
|
||||||
|
Key::Borrowed(&callsite.key_data),
|
||||||
|
GaugeValue::Increment(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_increment_gauge(key: *mut FfiKey, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
if !key.is_null() {
|
||||||
|
let key = unsafe { Box::from_raw(key) };
|
||||||
|
recorder.update_gauge(key.inner, GaugeValue::Increment(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_static_decrement_gauge(callsite: *const FfiCallsite, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
let callsite = unsafe { callsite.as_ref().unwrap() };
|
||||||
|
recorder.update_gauge(
|
||||||
|
Key::Borrowed(&callsite.key_data),
|
||||||
|
GaugeValue::Decrement(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_decrement_gauge(key: *mut FfiKey, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
if !key.is_null() {
|
||||||
|
let key = unsafe { Box::from_raw(key) };
|
||||||
|
recorder.update_gauge(key.inner, GaugeValue::Decrement(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_static_record_histogram(callsite: *const FfiCallsite, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
let callsite = unsafe { callsite.as_ref().unwrap() };
|
||||||
|
recorder.record_histogram(Key::Borrowed(&callsite.key_data), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn metrics_record_histogram(key: *mut FfiKey, value: c_double) {
|
||||||
|
if let Some(recorder) = try_recorder() {
|
||||||
|
if !key.is_null() {
|
||||||
|
let key = unsafe { Box::from_raw(key) };
|
||||||
|
recorder.record_histogram(key.inner, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
// This is mostly code copied from metrics_exporter_prometheus. The copied portions are
|
||||||
|
// licensed under the same terms as the zcash codebase (reproduced below from
|
||||||
|
// https://github.com/metrics-rs/metrics/blob/main/metrics-exporter-prometheus/LICENSE):
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
use hyper::{
|
||||||
|
server::{conn::AddrStream, Server},
|
||||||
|
service::{make_service_fn, service_fn},
|
||||||
|
{Body, Error as HyperError, Response, StatusCode},
|
||||||
|
};
|
||||||
|
use metrics::SetRecorderError;
|
||||||
|
use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusRecorder};
|
||||||
|
use std::future::Future;
|
||||||
|
use std::io;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::thread;
|
||||||
|
use thiserror::Error as ThisError;
|
||||||
|
use tokio::{pin, runtime, select};
|
||||||
|
|
||||||
|
/// Errors that could occur while installing a Prometheus recorder/exporter.
|
||||||
|
#[derive(Debug, ThisError)]
|
||||||
|
pub enum InstallError {
|
||||||
|
/// Creating the networking event loop did not succeed.
|
||||||
|
#[error("failed to spawn Tokio runtime for endpoint: {0}")]
|
||||||
|
Io(#[from] io::Error),
|
||||||
|
|
||||||
|
/// Binding/listening to the given address did not succeed.
|
||||||
|
#[error("failed to bind to given listen address: {0}")]
|
||||||
|
Hyper(#[from] HyperError),
|
||||||
|
|
||||||
|
/// Installing the recorder did not succeed.
|
||||||
|
#[error("failed to install exporter as global recorder: {0}")]
|
||||||
|
Recorder(#[from] SetRecorderError),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A copy of `PrometheusBuilder::build_with_exporter` that adds support for an IP address
|
||||||
|
/// or subnet allowlist.
|
||||||
|
pub(super) fn build(
|
||||||
|
bind_address: SocketAddr,
|
||||||
|
builder: PrometheusBuilder,
|
||||||
|
allow_ips: Vec<ipnet::IpNet>,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
PrometheusRecorder,
|
||||||
|
impl Future<Output = Result<(), HyperError>> + Send + 'static,
|
||||||
|
),
|
||||||
|
InstallError,
|
||||||
|
> {
|
||||||
|
let recorder = builder.build();
|
||||||
|
let handle = recorder.handle();
|
||||||
|
|
||||||
|
let server = Server::try_bind(&bind_address)?;
|
||||||
|
|
||||||
|
let exporter = async move {
|
||||||
|
let make_svc = make_service_fn(move |socket: &AddrStream| {
|
||||||
|
let remote_addr = socket.remote_addr().ip();
|
||||||
|
let allowed = allow_ips.iter().any(|subnet| subnet.contains(&remote_addr));
|
||||||
|
let handle = handle.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
Ok::<_, HyperError>(service_fn(move |_| {
|
||||||
|
let handle = handle.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
if allowed {
|
||||||
|
let output = handle.render();
|
||||||
|
Ok(Response::new(Body::from(output)))
|
||||||
|
} else {
|
||||||
|
Response::builder()
|
||||||
|
.status(StatusCode::FORBIDDEN)
|
||||||
|
.body(Body::empty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.serve(make_svc).await
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((recorder, exporter))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A copy of `PrometheusBuilder::install` that adds support for an IP address or subnet
|
||||||
|
/// allowlist.
|
||||||
|
pub(super) fn install(
|
||||||
|
bind_address: SocketAddr,
|
||||||
|
builder: PrometheusBuilder,
|
||||||
|
allow_ips: Vec<ipnet::IpNet>,
|
||||||
|
) -> Result<(), InstallError> {
|
||||||
|
let runtime = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let (recorder, exporter) = {
|
||||||
|
let _guard = runtime.enter();
|
||||||
|
build(bind_address, builder, allow_ips)?
|
||||||
|
};
|
||||||
|
metrics::set_boxed_recorder(Box::new(recorder))?;
|
||||||
|
|
||||||
|
thread::Builder::new()
|
||||||
|
.name("zcash-prometheus".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
runtime.block_on(async move {
|
||||||
|
pin!(exporter);
|
||||||
|
loop {
|
||||||
|
select! {
|
||||||
|
_ = &mut exporter => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -63,6 +63,7 @@ use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree}
|
||||||
|
|
||||||
mod blake2b;
|
mod blake2b;
|
||||||
mod ed25519;
|
mod ed25519;
|
||||||
|
mod metrics_ffi;
|
||||||
mod tracing_ffi;
|
mod tracing_ffi;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -389,6 +389,7 @@ void ReadConfigFile(const std::string& confPath,
|
||||||
"externalip",
|
"externalip",
|
||||||
"fundingstream",
|
"fundingstream",
|
||||||
"loadblock",
|
"loadblock",
|
||||||
|
"metricsallowip",
|
||||||
"nuparams",
|
"nuparams",
|
||||||
"onlynet",
|
"onlynet",
|
||||||
"rpcallowip",
|
"rpcallowip",
|
||||||
|
|
Loading…
Reference in New Issue