Auto merge of #4597 - str4d:rust-tracing, r=str4d

Use the Rust tracing crate for C++ logging

This PR swaps in the `tracing` crate (via FFI) for logging to either standard
output or `debug.log`. It transparently maps all existing `LogPrintf` and
`LogPrint` invocations to info-level `tracing` events, and passes through
correct file and line information. `error` invocations are mapped to error-level
`tracing` events, currently without line information (due to the way that
`error` is used in the codebase; swapping individual callsites to the new
`LogError` macro will provide that information).

The end-goal for this change is that we don't need to make any disruptive
changes to the codebase, but we can start to leverage `tracing`-specific
functionality where we want to, such as providing extra fields on certain log
lines (that can be filtered for), adding spans to record the flow of execution
through `zcashd`, and logging within C++ and Rust simultaneously. Support
for extra fields on spans and events will be added in a subsequent PR.

The `-debug` config options are converted at launch into their corresponding
directives for tracing's `EnvFilter`. The new `setlogfilter` RPC method allows
this filter to be reloaded dynamically. The syntax is documented in the
`setlogfilter` help text, as well as here:

https://docs.rs/tracing-subscriber/0.2.7/tracing_subscriber/filter/struct.EnvFilter.html#directives

When `-printtoconsole` is specified, the output now includes timestamps and
ANSI encoding :)
This commit is contained in:
Homu 2020-08-07 21:54:46 +00:00
commit d36718542c
47 changed files with 1601 additions and 170 deletions

214
Cargo.lock generated
View File

@ -32,6 +32,24 @@ dependencies = [
"opaque-debug",
]
[[package]]
name = "aho-corasick"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "arrayref"
version = "0.3.5"
@ -53,6 +71,12 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "bellman"
version = "0.6.0"
@ -164,9 +188,20 @@ dependencies = [
[[package]]
name = "cfg-if"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "chrono"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6"
dependencies = [
"num-integer",
"num-traits",
"time",
]
[[package]]
name = "constant_time_eq"
@ -181,11 +216,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c"
dependencies = [
"cfg-if",
"crossbeam-channel",
"crossbeam-channel 0.3.9",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
"crossbeam-utils 0.6.6",
]
[[package]]
@ -194,7 +229,17 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
dependencies = [
"crossbeam-utils",
"crossbeam-utils 0.6.6",
]
[[package]]
name = "crossbeam-channel"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6"
dependencies = [
"cfg-if",
"crossbeam-utils 0.7.2",
]
[[package]]
@ -204,7 +249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
"crossbeam-utils 0.6.6",
]
[[package]]
@ -215,7 +260,7 @@ checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
dependencies = [
"arrayvec",
"cfg-if",
"crossbeam-utils",
"crossbeam-utils 0.6.6",
"lazy_static",
"memoffset",
"scopeguard",
@ -227,7 +272,7 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
dependencies = [
"crossbeam-utils",
"crossbeam-utils 0.6.6",
]
[[package]]
@ -240,6 +285,17 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [
"autocfg 1.0.0",
"cfg-if",
"lazy_static",
]
[[package]]
name = "crunchy"
version = "0.1.6"
@ -418,9 +474,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.62"
version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
checksum = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701"
[[package]]
name = "librustzcash"
@ -435,6 +491,10 @@ dependencies = [
"libc",
"pairing",
"rand_core",
"tracing",
"tracing-appender",
"tracing-core",
"tracing-subscriber",
"zcash_history",
"zcash_primitives",
"zcash_proofs",
@ -449,6 +509,21 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "matchers"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
dependencies = [
"regex-automata",
]
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "memoffset"
version = "0.5.1"
@ -470,7 +545,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a"
dependencies = [
"autocfg",
"autocfg 0.1.6",
"num-integer",
"num-traits",
]
@ -481,7 +556,7 @@ version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
dependencies = [
"autocfg",
"autocfg 0.1.6",
"num-traits",
]
@ -491,7 +566,7 @@ version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
dependencies = [
"autocfg",
"autocfg 0.1.6",
]
[[package]]
@ -595,6 +670,34 @@ dependencies = [
"rand_core",
]
[[package]]
name = "regex"
version = "1.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-automata"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
dependencies = [
"byteorder",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -657,6 +760,15 @@ dependencies = [
"opaque-debug",
]
[[package]]
name = "sharded-slab"
version = "0.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e"
dependencies = [
"lazy_static",
]
[[package]]
name = "subtle"
version = "2.2.3"
@ -694,6 +806,82 @@ dependencies = [
"syn",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "tracing"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178"
dependencies = [
"cfg-if",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-appender"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7aa52d56cc0d79ab604e8a022a1cebc4de33cf09dc9933c94353bea2e00d6e88"
dependencies = [
"chrono",
"crossbeam-channel 0.4.3",
"tracing-subscriber",
]
[[package]]
name = "tracing-attributes"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9"
dependencies = [
"lazy_static",
]
[[package]]
name = "tracing-subscriber"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7b33f8b2ef2ab0c3778c12646d9c42a24f7772bee4cdafc72199644a9f58fdc"
dependencies = [
"ansi_term",
"chrono",
"lazy_static",
"matchers",
"regex",
"sharded-slab",
"tracing-core",
]
[[package]]
name = "typenum"
version = "1.11.2"

View File

@ -28,11 +28,19 @@ libc = "0.2"
pairing = "0.16"
lazy_static = "1"
rand_core = "0.5.1"
tracing = "0.1"
tracing-core = "0.1"
tracing-appender = "0.1"
zcash_history = "0.2"
zcash_primitives = "0.2"
zcash_proofs = "0.2"
ed25519-zebra = "2.0.0"
[dependencies.tracing-subscriber]
version = "0.2"
default-features = false
features = ["ansi", "chrono", "env-filter"]
[profile.release]
lto = true
panic = 'abort'

View File

@ -0,0 +1,15 @@
package=crate_aho_corasick
$(package)_crate_name=aho-corasick
$(package)_version=0.7.13
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_ansi_term
$(package)_crate_name=ansi_term
$(package)_version=0.12.1
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -1,9 +1,9 @@
package=crate_autocfg
$(package)_crate_name=autocfg
$(package)_version=0.1.6
$(package)_version=1.0.0
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875
$(package)_sha256_hash=f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds

View File

@ -0,0 +1,15 @@
package=crate_autocfg
$(package)_crate_name=autocfg
$(package)_version=0.1.6
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875
$(package)_crate_versioned_name=$($(package)_crate_name)-$($(package)_version)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -1,9 +1,9 @@
package=crate_cfg_if
$(package)_crate_name=cfg-if
$(package)_version=0.1.9
$(package)_version=0.1.10
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33
$(package)_sha256_hash=4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds

View File

@ -0,0 +1,15 @@
package=crate_chrono
$(package)_crate_name=chrono
$(package)_version=0.4.13
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -1,9 +1,9 @@
package=crate_crossbeam_channel
$(package)_crate_name=crossbeam-channel
$(package)_version=0.3.9
$(package)_version=0.4.3
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa
$(package)_sha256_hash=09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds

View File

@ -0,0 +1,15 @@
package=crate_crossbeam_channel
$(package)_crate_name=crossbeam-channel
$(package)_version=0.3.9
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa
$(package)_crate_versioned_name=$($(package)_crate_name)-$($(package)_version)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -1,9 +1,9 @@
package=crate_crossbeam_utils
$(package)_crate_name=crossbeam-utils
$(package)_version=0.6.6
$(package)_version=0.7.2
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6
$(package)_sha256_hash=c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds

View File

@ -0,0 +1,15 @@
package=crate_crossbeam_utils
$(package)_crate_name=crossbeam-utils
$(package)_version=0.6.6
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6
$(package)_crate_versioned_name=$($(package)_crate_name)-$($(package)_version)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -1,9 +1,9 @@
package=crate_libc
$(package)_crate_name=libc
$(package)_version=0.2.62
$(package)_version=0.2.72
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba
$(package)_sha256_hash=a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds

View File

@ -0,0 +1,15 @@
package=crate_matchers
$(package)_crate_name=matchers
$(package)_version=0.0.1
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_memchr
$(package)_crate_name=memchr
$(package)_version=2.3.3
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_regex
$(package)_crate_name=regex
$(package)_version=1.3.9
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_regex_automata
$(package)_crate_name=regex-automata
$(package)_version=0.1.9
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_regex_syntax
$(package)_crate_name=regex-syntax
$(package)_version=0.6.18
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_sharded_slab
$(package)_crate_name=sharded-slab
$(package)_version=0.0.9
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_thread_local
$(package)_crate_name=thread_local
$(package)_version=1.0.1
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_time
$(package)_crate_name=time
$(package)_version=0.1.43
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_tracing
$(package)_crate_name=tracing
$(package)_version=0.1.18
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_tracing_appender
$(package)_crate_name=tracing-appender
$(package)_version=0.1.1
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=7aa52d56cc0d79ab604e8a022a1cebc4de33cf09dc9933c94353bea2e00d6e88
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_tracing_attributes
$(package)_crate_name=tracing-attributes
$(package)_version=0.1.9
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_tracing_core
$(package)_crate_name=tracing-core
$(package)_version=0.1.13
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -0,0 +1,15 @@
package=crate_tracing_subscriber
$(package)_crate_name=tracing-subscriber
$(package)_version=0.2.10
$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name)
$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate
$(package)_sha256_hash=f7b33f8b2ef2ab0c3778c12646d9c42a24f7772bee4cdafc72199644a9f58fdc
$(package)_crate_versioned_name=$($(package)_crate_name)
define $(package)_preprocess_cmds
$(call generate_crate_checksum,$(package))
endef
define $(package)_stage_cmds
$(call vendor_crate_source,$(package))
endef

View File

@ -2,8 +2,11 @@ rust_crates := \
crate_aes \
crate_aesni \
crate_aes_soft \
crate_aho_corasick \
crate_ansi_term \
crate_arrayref \
crate_arrayvec \
crate_autocfg_0.1 \
crate_autocfg \
crate_bellman \
crate_bigint \
@ -17,11 +20,14 @@ rust_crates := \
crate_byteorder \
crate_c2_chacha \
crate_cfg_if \
crate_chrono \
crate_constant_time_eq \
crate_crossbeam_channel_0.3 \
crate_crossbeam_channel \
crate_crossbeam_deque \
crate_crossbeam_epoch \
crate_crossbeam_queue \
crate_crossbeam_utils_0.6 \
crate_crossbeam_utils \
crate_crossbeam \
crate_crunchy \
@ -45,6 +51,8 @@ rust_crates := \
crate_lazy_static \
crate_libc \
crate_log \
crate_matchers \
crate_memchr \
crate_memoffset \
crate_nodrop \
crate_num_bigint \
@ -61,6 +69,9 @@ rust_crates := \
crate_rand_hc \
crate_rand_xorshift \
crate_rand \
crate_regex_automata \
crate_regex_syntax \
crate_regex \
crate_rustc_version \
crate_scopeguard \
crate_semver_parser \
@ -68,10 +79,18 @@ rust_crates := \
crate_serde \
crate_serde_derive \
crate_sha2 \
crate_sharded_slab \
crate_subtle \
crate_syn \
crate_time \
crate_thiserror \
crate_thiserror_impl \
crate_thread_local \
crate_tracing_appender \
crate_tracing_attributes \
crate_tracing_core \
crate_tracing_subscriber \
crate_tracing \
crate_typenum \
crate_unicode_xid \
crate_wasi \

View File

@ -4,3 +4,27 @@ release-notes at release time)
Notable changes
===============
New logging system
------------------
The `zcashd` logging system is now powered by the Rust `tracing` crate. This
has two main benefits:
- `tracing` supports the concept of "spans", which represent periods of time
with a beginning and end. These enable logging additional information about
temporality and causality of events. (Regular log lines, which represent
moments in time, are called `events` in `tracing`.)
- Spans and events are structured, and can record typed data in addition to text
messages. This structure can then be filtered dynamically.
The existing `-debug=target` config flags are mapped to `tracing` log filters,
and will continue to correctly enable additional logging when starting `zcashd`.
A new `setlogfilter` RPC method has been introduced that enables reconfiguring
the log filter at runtime. See `zcash-cli help setlogfilter` for its syntax.
As a minor note, `zcashd` no longer reopens the `debug.log` file on `SIGHUP`.
This behaviour was originally introduced in upstream Bitcoin Core to support log
rotation using external tools. `tracing` supports log rotation internally (which
is currently disabled), as well as a variety of interesting backends (such as
`journald` and OpenTelemetry integration); we are investigating how these might
be exposed in future releases.

View File

@ -57,8 +57,8 @@ crate_arrayvec 0.4.12 2020-10-01
crate_arrayvec 0.5.0 2020-10-01
crate_arrayvec 0.5.1 2020-10-01
crate_arrayref 0.3.6 2020-10-01
crate_autocfg 0.1.7 2020-10-01
crate_autocfg 1.0.0 2020-10-01
crate_autocfg_0.1 0.1.7 2020-10-01
crate_autocfg_0.1 1.0.0 2020-10-01
crate_bigint 4.4.2 2020-10-01
crate_bigint 4.4.3 2020-10-01
crate_blake2b_simd 0.5.9 2020-10-01
@ -85,17 +85,17 @@ crate_crunchy 0.2.2 2020-10-01
crate_constant_time_eq 0.1.5 2020-10-01
crate_crossbeam 0.7.3 2020-10-01
crate_digest 0.9.0 2020-10-01
crate_crossbeam_channel 0.4.0 2020-10-01
crate_crossbeam_channel 0.4.1 2020-10-01
crate_crossbeam_channel 0.4.2 2020-10-01
crate_crossbeam_channel_0.3 0.4.0 2020-10-01
crate_crossbeam_channel_0.3 0.4.1 2020-10-01
crate_crossbeam_channel_0.3 0.4.2 2020-10-01
crate_crossbeam_deque 0.7.2 2020-10-01
crate_crossbeam_deque 0.7.3 2020-10-01
crate_crossbeam_epoch 0.8.0 2020-10-01
crate_crossbeam_epoch 0.8.1 2020-10-01
crate_crossbeam_epoch 0.8.2 2020-10-01
crate_crossbeam_utils 0.7.0 2020-10-01
crate_crossbeam_utils 0.7.1 2020-10-01
crate_crossbeam_utils 0.7.2 2020-10-01
crate_crossbeam_utils_0.6 0.7.0 2020-10-01
crate_crossbeam_utils_0.6 0.7.1 2020-10-01
crate_crossbeam_utils_0.6 0.7.2 2020-10-01
crate_crossbeam_queue 0.2.0 2020-10-01
crate_crossbeam_queue 0.2.1 2020-10-01
crate_crossbeam_queue 0.2.2 2020-10-01
@ -246,3 +246,23 @@ crate_winapi 0.3.9 2020-10-01
rust 1.45.0 2020-10-01
rust 1.45.1 2020-10-01
rust 1.45.2 2020-10-01
# The chrono crate depends on "time ^0.1.43", and is highly unlikely to
# upgrade to v0.2: https://github.com/chronotope/chrono/issues/400
crate_time 0.2.0 2021-02-01
crate_time 0.2.1 2021-02-01
crate_time 0.2.2 2021-02-01
crate_time 0.2.3 2021-02-01
crate_time 0.2.4 2021-02-01
crate_time 0.2.5 2021-02-01
crate_time 0.2.6 2021-02-01
crate_time 0.2.7 2021-02-01
crate_time 0.2.8 2021-02-01
crate_time 0.2.9 2021-02-01
crate_time 0.2.10 2021-02-01
crate_time 0.2.11 2021-02-01
crate_time 0.2.12 2021-02-01
crate_time 0.2.13 2021-02-01
crate_time 0.2.14 2021-02-01
crate_time 0.2.15 2021-02-01
crate_time 0.2.16 2021-02-01

View File

@ -97,23 +97,28 @@ def get_dependency_list():
# Rust crates (filename portion: depends/packages/crate_<NAME>.mk).
crates = [
"aes", "aesni", "aes_soft", "arrayvec", "bellman", "arrayref",
"autocfg", "bigint", "blake2b_simd", "blake2s_simd", "bit_vec",
"aes", "aesni", "aes_soft", "aho_corasick", "ansi_term",
"arrayvec", "arrayref", "autocfg", "autocfg_0.1",
"bellman", "bigint", "blake2b_simd", "blake2s_simd", "bit_vec",
"block_cipher_trait", "byteorder", "byte_tools", "block_buffer",
"block_padding", "c2_chacha", "cfg_if", "crunchy",
"block_padding", "c2_chacha", "cfg_if", "chrono", "crunchy",
"curve25519_dalek", "constant_time_eq", "crossbeam", "digest", "fpe",
"crossbeam_channel_0.3", "crossbeam_utils_0.6",
"crossbeam_channel", "crossbeam_deque", "crossbeam_epoch",
"crossbeam_utils", "crossbeam_queue", "crypto_api",
"crypto_api_chachapoly", "directories", "ed25519_zebra", "fake_simd",
"ff", "ff_derive", "getrandom", "hex", "hex2", "log",
"futures_cpupool", "futures", "generic_array", "group",
"lazy_static", "libc", "nodrop", "num_bigint", "memoffset",
"lazy_static", "libc", "matchers", "memchr", "memoffset", "nodrop", "num_bigint",
"ppv_lite86", "proc_macro2", "quote", "num_cpus", "num_integer",
"num_traits", "opaque_debug", "pairing", "rand", "typenum",
"rand_chacha", "rand_core", "rand_hc", "rand_xorshift",
"regex", "regex_automata", "regex_syntax",
"rustc_version", "scopeguard", "semver", "semver_parser", "serde",
"serde_derive", "sha2", "subtle", "syn", "thiserror",
"thiserror_impl", "unicode_xid", "wasi",
"serde_derive", "sha2", "sharded_slab", "subtle", "syn", "thiserror",
"thiserror_impl", "thread_local", "time", "tracing", "tracing_appender",
"tracing_attributes", "tracing_core", "tracing_subscriber",
"unicode_xid", "wasi",
"winapi_i686_pc_windows_gnu", "winapi",
"winapi_x86_64_pc_windows_gnu", "zcash_history", "zcash_primitives",
"zcash_proofs", "zeroize"
@ -122,6 +127,9 @@ def get_dependency_list():
# Sometimes we need multiple versions of a crate, in which case there can't
# be a direct mapping between the filename portion and the crate name.
crate_name_exceptions = {
"autocfg_0.1": "autocfg",
"crossbeam_channel_0.3": "crossbeam_channel",
"crossbeam_utils_0.6": "crossbeam_utils",
"hex2": "hex"
}
@ -284,7 +292,7 @@ class DependsVersionGetter:
self.name = name
def current_version(self):
mk_file_path = os.path.join(SOURCE_ROOT, "depends", "packages", safe(self.name) + ".mk")
mk_file_path = os.path.join(SOURCE_ROOT, "depends", "packages", safe_depends(self.name) + ".mk")
mk_file = open(mk_file_path, 'r').read()
regexp_whitelist = [
@ -361,6 +369,12 @@ def safe(string):
else:
raise RuntimeError("Potentially-dangerous string encountered.")
def safe_depends(string):
if re.match('^[a-zA-Z0-9._-]*$', string):
return string
else:
raise RuntimeError("Potentially-dangerous string encountered.")
def print_row(name, status, current_version, known_versions):
COL_FMT_LARGE = "{:<35}"
COL_FMT_SMALL = "{:<18}"

View File

@ -29,6 +29,7 @@ endif
BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
BITCOIN_CONFIG_INCLUDES += -I$(srcdir)/rust/include
BITCOIN_INCLUDES += -I$(srcdir)/rust/include
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
BITCOIN_INCLUDES += -I$(srcdir)/univalue/include

View File

@ -71,6 +71,8 @@ using namespace std;
extern void ThreadSendAlert();
TracingHandle* pTracingHandle = nullptr;
bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
@ -259,6 +261,9 @@ void Shutdown()
globalVerifyHandle.reset();
ECC_Stop();
LogPrintf("%s: done\n", __func__);
if (pTracingHandle) {
tracing_free(pTracingHandle);
}
}
/**
@ -800,6 +805,23 @@ void InitLogging()
fLogTimestamps = GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS);
// Set up the initial filtering directive from the -debug flags.
std::string initialFilter = LogConfigFilter();
if (fPrintToConsole) {
pTracingHandle = tracing_init(nullptr, 0, initialFilter.c_str(), fLogTimestamps);
} else {
boost::filesystem::path pathDebug = GetDebugLogPath();
const boost::filesystem::path::string_type& pathDebugStr = pathDebug.native();
static_assert(sizeof(boost::filesystem::path::value_type) == sizeof(codeunit),
"native path has unexpected code unit size");
pTracingHandle = tracing_init(
reinterpret_cast<const codeunit*>(pathDebugStr.c_str()),
pathDebugStr.length(),
initialFilter.c_str(),
fLogTimestamps);
}
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
LogPrintf("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
}
@ -1144,12 +1166,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// if (GetBoolArg("-shrinkdebugfile", !fDebug))
// ShrinkDebugFile();
if (fPrintToDebugLog) {
if (!OpenDebugLog()) {
return InitError(strprintf("Could not open debug log file %s", GetDebugLogPath().string()));
}
}
LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
#ifdef ENABLE_WALLET
LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));

View File

@ -8,6 +8,8 @@
#include <string>
#include <tracing.h>
class CScheduler;
class CWallet;
@ -16,6 +18,8 @@ namespace boost
class thread_group;
} // namespace boost
extern TracingHandle* pTracingHandle;
void StartShutdown();
bool ShutdownRequested();
/** Interrupt threads */

View File

@ -4321,6 +4321,9 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp)
{
auto span = TracingSpan("info", "main", "ProcessNewBlock");
auto spanGuard = span.Enter();
// Preliminary checks
auto verifier = ProofVerifier::Disabled();
bool checked = CheckBlock(*pblock, state, chainparams, verifier);

View File

@ -994,6 +994,8 @@ void ThreadSocketHandler()
if (pnode->fDisconnect ||
(pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty()))
{
auto spanGuard = pnode->span.Enter();
// remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
@ -1152,6 +1154,8 @@ void ThreadSocketHandler()
{
boost::this_thread::interruption_point();
auto spanGuard = pnode->span.Enter();
//
// Receive
//
@ -1557,6 +1561,8 @@ void ThreadMessageHandler()
if (pnode->fDisconnect)
continue;
auto spanGuard = pnode->span.Enter();
// Receive messages
{
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
@ -1890,6 +1896,7 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
if(!pnode->fRelayTxes)
continue;
LOCK(pnode->cs_filter);
auto spanGuard = pnode->span.Enter();
if (pnode->pfilter)
{
if (pnode->pfilter->IsRelevantAndUpdate(tx))
@ -2101,6 +2108,8 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
nPingUsecTime = 0;
fPingQueued = false;
nMinPingUsecTime = std::numeric_limits<int64_t>::max();
span = TracingSpan("info", "net", "CNode");
auto spanGuard = span.Enter();
{
LOCK(cs_nLastNodeId);

View File

@ -30,6 +30,8 @@
#include <boost/foreach.hpp>
#include <boost/signals2/signal.hpp>
#include <tracing.h>
class CAddrMan;
class CBlockIndex;
class CScheduler;
@ -297,6 +299,8 @@ public:
CBloomFilter* pfilter;
int nRefCount;
NodeId id;
tracing::Span span;
protected:
// Denial-of-service detection/prevention

View File

@ -28,6 +28,8 @@
#include <boost/thread.hpp>
#include <boost/algorithm/string/case_conv.hpp> // for to_upper()
#include <tracing.h>
using namespace RPCServer;
using namespace std;
@ -239,6 +241,42 @@ UniValue help(const UniValue& params, bool fHelp)
}
UniValue setlogfilter(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1) {
throw runtime_error(
"setlogfilter \"directives\"\n"
"\nSets the filter to be used for selecting events to log.\n"
"\nA filter is a comma-separated list of directives.\n"
"The syntax for each directive is:\n"
"\n target[span{field=value}]=level\n"
"\nThe default filter, derived from the -debug=target flags, is:\n"
+ strprintf("\n %s", LogConfigFilter()) + "\n"
"\nPassing a valid filter here will replace the existing filter.\n"
"Passing an empty string will reset the filter to the default.\n"
"\nArguments:\n"
"1. newFilterDirectives (string, required) The new log filter.\n"
"\nExamples:\n"
+ HelpExampleCli("setlogfilter", "\"main=info,rpc=info\"")
+ HelpExampleRpc("setlogfilter", "\"main=info,rpc=info\"")
);
}
auto newFilter = params[0].getValStr();
if (newFilter.empty()) {
newFilter = LogConfigFilter();
}
if (pTracingHandle) {
if (!tracing_reload(pTracingHandle, newFilter.c_str())) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Filter reload failed; check logs");
}
}
return NullUniValue;
}
UniValue stop(const UniValue& params, bool fHelp)
{
// Accept the deprecated and ignored 'detach' boolean argument
@ -260,6 +298,7 @@ static const CRPCCommand vRPCCommands[] =
// --------------------- ------------------------ ----------------------- ----------
/* Overall control/query calls */
{ "control", "help", &help, true },
{ "control", "setlogfilter", &setlogfilter, true },
{ "control", "stop", &stop, true },
};

View File

@ -1,6 +1,9 @@
#ifndef LIBRUSTZCASH_INCLUDE_H_
#define LIBRUSTZCASH_INCLUDE_H_
#include "rust/types.h"
#include <stddef.h>
#include <stdint.h>
#ifndef __cplusplus
@ -29,11 +32,6 @@ static_assert(alignof(HistoryEntry) == 1, "HistoryEntry struct alignment is not
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WIN32
typedef uint16_t codeunit;
#else
typedef uint8_t codeunit;
#endif
void librustzcash_to_scalar(const unsigned char *input, unsigned char *result);

View File

@ -0,0 +1,16 @@
// 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 RUST_TYPES_H_
#define RUST_TYPES_H_
#include <stdint.h>
#ifdef WIN32
typedef uint16_t codeunit;
#else
typedef uint8_t codeunit;
#endif
#endif // RUST_TYPES_H_

301
src/rust/include/tracing.h Normal file
View File

@ -0,0 +1,301 @@
// 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 TRACING_INCLUDE_H_
#define TRACING_INCLUDE_H_
#include "rust/types.h"
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
#include <memory>
extern "C" {
#endif
struct TracingHandle;
typedef struct TracingHandle TracingHandle;
/// Initializes the tracing crate, returning a handle for the logging
/// component. The handle must be freed to close the logging component.
///
/// If log_path is NULL, logging is sent to standard output.
TracingHandle* tracing_init(
const codeunit* log_path,
size_t log_path_len,
const char* initial_filter,
bool log_timestamps);
/// Frees a tracing handle returned from `tracing_init`;
void tracing_free(TracingHandle* handle);
/// Reloads the tracing filter.
///
/// Returns `true` if the reload succeeded.
bool tracing_reload(TracingHandle* handle, const char* new_filter);
struct TracingCallsite;
typedef struct TracingCallsite TracingCallsite;
/// Creates a tracing callsite.
///
/// You should usually call the `TracingLog` macro (or one of the helper
/// macros such as `TracingInfo`) instead of calling this directly.
///
/// This MUST ONLY be called to assign a `static TracingCallsite*`, and all
/// string arguments MUST be static `const char*` constants, and MUST be valid
/// UTF-8.
TracingCallsite* tracing_callsite(
const char* name,
const char* target,
const char* level,
const char* file,
uint32_t line,
const char* const* fields,
size_t fields_len,
bool is_span);
struct TracingSpanHandle;
typedef struct TracingSpanHandle TracingSpanHandle;
struct TracingSpanGuard;
typedef struct TracingSpanGuard TracingSpanGuard;
/// Creates a span for a callsite.
///
/// The span must be freed when it goes out of scope.
TracingSpanHandle* tracing_span_create(const TracingCallsite* callsite);
/// Clones the given span.
///
/// Both spans need to be separately freed when they go out of scope.
TracingSpanHandle* tracing_span_clone(const TracingSpanHandle* span);
/// Frees a span.
void tracing_span_free(TracingSpanHandle* span);
/// Enters the given span, returning a guard.
///
/// `tracing_span_exit` must be called to drop this guard before the span
/// goes out of scope.
TracingSpanGuard* tracing_span_enter(const TracingSpanHandle* span);
/// Exits a span by dropping the given guard.
void tracing_span_exit(TracingSpanGuard* guard);
/// Logs a message for a callsite.
///
/// You should usually call the `TracingLog` macro (or one of the helper
/// macros such as `TracingInfo`) instead of calling this directly.
void tracing_log(
const TracingCallsite* callsite,
const char* const* field_values,
size_t fields_len);
#ifdef __cplusplus
}
#endif
//
// Helper macros
//
#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
// Constructs a tracing callsite.
//
// The 'static constexpr' hack ensures that name, target, level, and fields are
// compile-time constants with static storage duration. The output of this macro
// MUST be stored as a static TracingCallsite*.
#define T_CALLSITE(name, target, level, fields, is_span) ([&] { \
static constexpr const char* _t_name = name; \
static constexpr const char* _t_target = target; \
static constexpr const char* _t_level = level; \
static constexpr const char* const* _t_fields = fields; \
return tracing_callsite( \
_t_name, \
_t_target, \
_t_level, \
__FILE__, \
__LINE__, \
_t_fields, \
T_ARRLEN(fields), \
is_span); \
}())
#else
// Constructs a tracing callsite.
//
// name, target, level, and fields MUST be static constants, and the output of
// this macro MUST be stored as a static TracingCallsite*.
#define T_CALLSITE(name, target, level, fields, is_span) \
tracing_callsite( \
name, \
target, \
level, \
__FILE__, \
__LINE__, \
fields, \
T_ARRLEN(fields), \
is_span)
#endif
//
// Spans
//
#ifdef __cplusplus
namespace tracing
{
class Span;
/// A guard representing a span which has been entered and is currently
/// executing.
///
/// When the guard is dropped, the span will be exited.
///
/// This is returned by the `Span::Enter` function.
class Entered
{
private:
friend class Span;
std::unique_ptr<TracingSpanGuard, decltype(&tracing_span_exit)> inner;
Entered(const TracingSpanHandle* span) : inner(tracing_span_enter(span), tracing_span_exit) {}
};
/// A handle representing a span, with the capability to enter the span if it
/// exists.
///
/// If the span was rejected by the current `Subscriber`'s filter, entering the
/// span will silently do nothing. Thus, the handle can be used in the same
/// manner regardless of whether or not the trace is currently being collected.
class Span
{
private:
std::unique_ptr<TracingSpanHandle, decltype(&tracing_span_free)> inner;
public:
/// Constructs a span that does nothing.
///
/// This constructor is present to enable spans to be stored in classes,
/// while also containing fields that are initialized within the class
/// constructor:
///
/// class Foo {
/// std::string name;
/// tracing::Span span;
///
/// Foo(std::string tag)
/// {
/// name = "Foo-" + tag;
/// span = TracingSpan("info", "main", "Foo", "name", name);
/// }
/// }
Span() : inner(nullptr, tracing_span_free) {}
/// Use the `TracingSpan` macro instead of calling this constructor directly.
Span(const TracingCallsite* callsite) : inner(tracing_span_create(callsite), tracing_span_free) {}
Span(Span& span) : inner(std::move(span.inner)) {}
Span(const Span& span) : inner(tracing_span_clone(span.inner.get()), tracing_span_free) {}
Span& operator=(Span& span)
{
if (this != &span) {
inner = std::move(span.inner);
}
return *this;
}
Span& operator=(const Span& span)
{
if (this != &span) {
inner.reset(tracing_span_clone(span.inner.get()));
}
return *this;
}
/// Enters this span, returning a guard that will exit the span when dropped.
///
/// If this span is enabled by the current subscriber, then this function
/// will call `Subscriber::enter` with the span's `Id`, and dropping the
/// guard will call `Subscriber::exit`. If the span is disabled, this does
/// nothing.
Entered Enter()
{
return Entered(inner.get());
}
};
} // 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[] = {}; \
static TracingCallsite* CALLSITE = \
T_CALLSITE(name, target, level, FIELDS, true); \
return tracing::Span(CALLSITE); \
}())
#endif
//
// Events
//
/// Constructs a new event.
///
/// level and target MUST be static constants, and MUST be valid UTF-8 strings.
#define TracingLog(level, target, message) \
do { \
static constexpr const char* const FIELDS[] = \
{"message"}; \
const char* T_VALUES[] = {message}; \
static TracingCallsite* CALLSITE = T_CALLSITE( \
"event " __FILE__ ":" T_ESCAPEQUOTE(__LINE__), \
target, level, FIELDS, false); \
tracing_log(CALLSITE, T_VALUES, T_ARRLEN(T_VALUES)); \
} while (0)
/// Constructs an event at the error level.
///
/// Arguments: (target, message)
///
/// target MUST be a static constant, and MUST be valid UTF-8 string.
#define TracingError(...) TracingLog("error", __VA_ARGS__)
/// Constructs an event at the warn level.
///
/// Arguments: (target, message)
///
/// target MUST be a static constant, and MUST be valid UTF-8 string.
#define TracingWarn(...) TracingLog("warn", __VA_ARGS__)
/// Constructs an event at the info level.
///
/// Arguments: (target, message)
///
/// target MUST be a static constant, and MUST be valid UTF-8 string.
#define TracingInfo(...) TracingLog("info", __VA_ARGS__)
/// Constructs an event at the debug level.
///
/// Arguments: (target, message)
///
/// target MUST be a static constant, and MUST be valid UTF-8 string.
#define TracingDebug(...) TracingLog("debug", __VA_ARGS__)
/// Constructs an event at the trace level.
///
/// Arguments: (target, message)
///
/// target MUST be a static constant, and MUST be valid UTF-8 string.
#define TracingTrace(...) TracingLog("trace", __VA_ARGS__)
#endif // TRACING_INCLUDE_H_

View File

@ -67,6 +67,8 @@ use zcash_proofs::{
use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree};
mod tracing_ffi;
#[cfg(test)]
mod tests;

552
src/rust/src/tracing_ffi.rs Normal file
View File

@ -0,0 +1,552 @@
use libc::c_char;
use std::ffi::CStr;
use std::path::Path;
use std::slice;
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use tracing::{
callsite::{Callsite, Identifier},
field::{FieldSet, Value},
level_enabled,
metadata::Kind,
span::Entered,
subscriber::{Interest, Subscriber},
Event, Metadata, Span,
};
use tracing_appender::non_blocking::WorkerGuard;
use tracing_core::Once;
use tracing_subscriber::{
filter::EnvFilter,
layer::Layer,
reload::{self, Handle},
};
#[cfg(not(target_os = "windows"))]
use std::ffi::OsStr;
#[cfg(not(target_os = "windows"))]
use std::os::unix::ffi::OsStrExt;
#[cfg(target_os = "windows")]
use std::ffi::OsString;
#[cfg(target_os = "windows")]
use std::os::windows::ffi::OsStringExt;
trait ReloadHandle {
fn reload(&self, new_filter: EnvFilter) -> Result<(), reload::Error>;
}
impl<L, S> ReloadHandle for Handle<L, S>
where
L: From<EnvFilter> + Layer<S> + 'static,
S: Subscriber,
{
fn reload(&self, new_filter: EnvFilter) -> Result<(), reload::Error> {
self.reload(new_filter)
}
}
pub struct TracingHandle {
_file_guard: Option<WorkerGuard>,
reload_handle: Box<dyn ReloadHandle>,
}
#[no_mangle]
pub extern "C" fn tracing_init(
#[cfg(not(target_os = "windows"))] log_path: *const u8,
#[cfg(target_os = "windows")] log_path: *const u16,
log_path_len: usize,
initial_filter: *const c_char,
log_timestamps: bool,
) -> *mut TracingHandle {
let initial_filter = unsafe { CStr::from_ptr(initial_filter) }
.to_str()
.expect("initial filter should be a valid string");
if log_path.is_null() {
tracing_init_stdout(initial_filter, log_timestamps)
} else {
let log_path = unsafe { slice::from_raw_parts(log_path, log_path_len) };
#[cfg(not(target_os = "windows"))]
let log_path = Path::new(OsStr::from_bytes(log_path));
#[cfg(target_os = "windows")]
let log_path = Path::new(OsString::from_wide(log_path));
tracing_init_file(log_path, initial_filter, log_timestamps)
}
}
fn tracing_init_stdout(initial_filter: &str, log_timestamps: bool) -> *mut TracingHandle {
let builder = tracing_subscriber::fmt()
.with_ansi(true)
.with_env_filter(initial_filter);
let reload_handle = if log_timestamps {
let builder = builder.with_filter_reloading();
let reload_handle = builder.reload_handle();
builder.init();
Box::new(reload_handle) as Box<dyn ReloadHandle>
} else {
let builder = builder.without_time().with_filter_reloading();
let reload_handle = builder.reload_handle();
builder.init();
Box::new(reload_handle) as Box<dyn ReloadHandle>
};
Box::into_raw(Box::new(TracingHandle {
_file_guard: None,
reload_handle,
}))
}
fn tracing_init_file(
log_path: &Path,
initial_filter: &str,
log_timestamps: bool,
) -> *mut TracingHandle {
let file_appender =
tracing_appender::rolling::never(log_path.parent().unwrap(), log_path.file_name().unwrap());
let (non_blocking, file_guard) = tracing_appender::non_blocking(file_appender);
let builder = tracing_subscriber::fmt()
.with_ansi(false)
.with_env_filter(initial_filter)
.with_writer(non_blocking);
let reload_handle = if log_timestamps {
let builder = builder.with_filter_reloading();
let reload_handle = builder.reload_handle();
builder.init();
Box::new(reload_handle) as Box<dyn ReloadHandle>
} else {
let builder = builder.without_time().with_filter_reloading();
let reload_handle = builder.reload_handle();
builder.init();
Box::new(reload_handle) as Box<dyn ReloadHandle>
};
Box::into_raw(Box::new(TracingHandle {
_file_guard: Some(file_guard),
reload_handle,
}))
}
#[no_mangle]
pub extern "C" fn tracing_free(handle: *mut TracingHandle) {
drop(unsafe { Box::from_raw(handle) });
}
#[no_mangle]
pub extern "C" fn tracing_reload(handle: *mut TracingHandle, new_filter: *const c_char) -> bool {
let handle = unsafe { &mut *handle };
match unsafe { CStr::from_ptr(new_filter) }
.to_str()
.map(EnvFilter::new)
{
Err(e) => {
tracing::error!("New filter is not valid UTF-8: {}", e);
false
}
Ok(new_filter) => {
if let Err(e) = handle.reload_handle.reload(new_filter) {
tracing::error!("Filter reload failed: {}", e);
false
} else {
true
}
}
}
}
pub struct FfiCallsite {
interest: AtomicUsize,
meta: Option<Metadata<'static>>,
registration: Once,
fields: Vec<&'static str>,
}
impl FfiCallsite {
fn new(fields: Vec<&'static str>) -> Self {
FfiCallsite {
interest: AtomicUsize::new(0),
meta: None,
registration: Once::new(),
fields,
}
}
#[inline(always)]
fn is_enabled(&self) -> bool {
let interest = self.interest();
if interest.is_always() {
return true;
}
if interest.is_never() {
return false;
}
tracing::dispatcher::get_default(|current| current.enabled(self.metadata()))
}
#[inline(always)]
pub fn register(&'static self) {
self.registration
.call_once(|| tracing::callsite::register(self));
}
#[inline(always)]
fn interest(&self) -> Interest {
match self.interest.load(Ordering::Relaxed) {
0 => Interest::never(),
2 => Interest::always(),
_ => Interest::sometimes(),
}
}
}
impl Callsite for FfiCallsite {
fn set_interest(&self, interest: Interest) {
let interest = match () {
_ if interest.is_never() => 0,
_ if interest.is_always() => 2,
_ => 1,
};
self.interest.store(interest, Ordering::SeqCst);
}
#[inline(always)]
fn metadata(&self) -> &Metadata<'static> {
self.meta.as_ref().unwrap()
}
}
#[no_mangle]
pub extern "C" fn tracing_callsite(
name: *const c_char,
target: *const c_char,
level: *const c_char,
file: *const c_char,
line: u32,
fields: *const *const c_char,
fields_len: usize,
is_span: bool,
) -> *mut FfiCallsite {
let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap();
let target = unsafe { CStr::from_ptr(target) }.to_str().unwrap();
let level = unsafe { CStr::from_ptr(level) }.to_str().unwrap();
let file = unsafe { CStr::from_ptr(file) }.to_str().unwrap();
let fields = unsafe { slice::from_raw_parts(fields, fields_len) };
let fields = fields
.iter()
.map(|&p| unsafe { CStr::from_ptr(p) })
.map(|cs| cs.to_str())
.collect::<Result<Vec<_>, _>>()
.unwrap();
let level = level.parse().unwrap();
// We immediately convert the new callsite into a pointer to erase lifetime
// information. The caller MUST ensure that the callsite is stored statically.
let site = Box::into_raw(Box::new(FfiCallsite::new(fields)));
let site_ref = unsafe { &*site };
let meta: Metadata<'static> = Metadata::new(
name,
target,
level,
Some(file),
Some(line),
None,
FieldSet::new(&site_ref.fields, Identifier(site_ref)),
if is_span { Kind::SPAN } else { Kind::EVENT },
);
unsafe { &mut *site }.meta = Some(meta);
site_ref.register();
site
}
macro_rules! repeat {
(1, $val:expr) => {
[$val]
};
(2, $val:expr) => {
[$val, $val]
};
(3, $val:expr) => {
[$val, $val, $val]
};
(4, $val:expr) => {
[$val, $val, $val, $val]
};
(5, $val:expr) => {
[$val, $val, $val, $val, $val]
};
(6, $val:expr) => {
[$val, $val, $val, $val, $val, $val]
};
(7, $val:expr) => {
[$val, $val, $val, $val, $val, $val, $val]
};
(8, $val:expr) => {
[$val, $val, $val, $val, $val, $val, $val, $val]
};
(9, $val:expr) => {
[$val, $val, $val, $val, $val, $val, $val, $val, $val]
};
(10, $val:expr) => {
[$val, $val, $val, $val, $val, $val, $val, $val, $val, $val]
};
(11, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(12, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(13, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(14, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(15, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val,
]
};
(16, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val,
]
};
(17, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val,
]
};
(18, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val,
]
};
(19, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val,
]
};
(20, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val,
]
};
(21, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val,
]
};
(22, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val,
]
};
(23, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(24, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(25, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(26, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(27, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(28, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
]
};
(29, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val,
]
};
(30, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val,
]
};
(31, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val,
]
};
(32, $val:expr) => {
[
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val, $val,
$val, $val, $val, $val,
]
};
}
#[no_mangle]
pub extern "C" fn tracing_span_create(callsite: *const FfiCallsite) -> *mut Span {
let callsite = unsafe { &*callsite };
let meta = callsite.metadata();
assert!(meta.is_span());
let span = if level_enabled!(*meta.level()) && callsite.is_enabled() {
Span::new(meta, &meta.fields().value_set(&[]))
} else {
Span::none()
};
Box::into_raw(Box::new(span))
}
#[no_mangle]
pub extern "C" fn tracing_span_clone(span: *const Span) -> *mut Span {
unsafe { span.as_ref() }
.map(|span| Box::into_raw(Box::new(span.clone())))
.unwrap_or(std::ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn tracing_span_free(span: *mut Span) {
if !span.is_null() {
drop(unsafe { Box::from_raw(span) });
}
}
#[no_mangle]
pub extern "C" fn tracing_span_enter(span: *const Span) -> *mut Entered<'static> {
unsafe { span.as_ref() }
.map(|span| Box::into_raw(Box::new(span.enter())))
.unwrap_or(std::ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn tracing_span_exit(guard: *mut Entered) {
if !guard.is_null() {
drop(unsafe { Box::from_raw(guard) });
}
}
#[no_mangle]
pub extern "C" fn tracing_log(
callsite: *const FfiCallsite,
field_values: *const *const c_char,
fields_len: usize,
) {
let callsite = unsafe { &*callsite };
let field_values = unsafe { slice::from_raw_parts(field_values, fields_len) };
let meta = callsite.metadata();
assert!(meta.is_event());
if level_enabled!(*meta.level()) && callsite.is_enabled() {
let mut fi = meta.fields().iter();
let mut vi = field_values
.iter()
.map(|&p| unsafe { CStr::from_ptr(p) })
.map(|cs| cs.to_string_lossy());
macro_rules! dispatch {
($n:tt) => {
Event::dispatch(
meta,
&meta.fields().value_set(&repeat!(
$n,
(
&fi.next().unwrap(),
Some(&vi.next().unwrap().as_ref() as &dyn Value)
)
)),
)
};
}
// https://github.com/tokio-rs/tracing/issues/782 might help improve things here.
match field_values.len() {
1 => dispatch!(1),
2 => dispatch!(2),
3 => dispatch!(3),
4 => dispatch!(4),
5 => dispatch!(5),
6 => dispatch!(6),
7 => dispatch!(7),
8 => dispatch!(8),
9 => dispatch!(9),
10 => dispatch!(10),
11 => dispatch!(11),
12 => dispatch!(12),
13 => dispatch!(13),
14 => dispatch!(14),
15 => dispatch!(15),
16 => dispatch!(16),
17 => dispatch!(17),
18 => dispatch!(18),
19 => dispatch!(19),
20 => dispatch!(20),
21 => dispatch!(21),
22 => dispatch!(22),
23 => dispatch!(23),
24 => dispatch!(24),
25 => dispatch!(25),
26 => dispatch!(26),
27 => dispatch!(27),
28 => dispatch!(28),
29 => dispatch!(29),
30 => dispatch!(30),
31 => dispatch!(31),
32 => dispatch!(32),
_ => unimplemented!(),
}
}
}

View File

@ -32,6 +32,8 @@
#include "librustzcash.h"
CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
TracingHandle* pTracingHandle = nullptr;
FastRandomContext insecure_rand_ctx(true);
extern bool fPrintToConsole;

View File

@ -221,30 +221,23 @@ boost::filesystem::path GetDebugLogPath()
}
}
bool OpenDebugLog()
std::string LogConfigFilter()
{
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
// With no -debug flags, show errors and LogPrintf lines.
std::string filter = "error,main=info";
assert(fileout == NULL);
assert(vMsgsBeforeOpenLog);
boost::filesystem::path pathDebug = GetDebugLogPath();
fileout = fopen(pathDebug.string().c_str(), "a");
if (!fileout) {
return false;
auto& categories = mapMultiArgs["-debug"];
std::set<std::string> setCategories(categories.begin(), categories.end());
if (setCategories.count(string("")) != 0 || setCategories.count(string("1")) != 0) {
// Turn on the firehose!
filter = "info";
} else {
for (auto category : setCategories) {
filter += "," + category + "=info";
}
}
setbuf(fileout, nullptr); // unbuffered
// dump buffered messages from before we opened the log
while (!vMsgsBeforeOpenLog->empty()) {
FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
vMsgsBeforeOpenLog->pop_front();
}
delete vMsgsBeforeOpenLog;
vMsgsBeforeOpenLog = NULL;
return true;
return filter;
}
bool LogAcceptCategory(const char* category)
@ -276,70 +269,6 @@ bool LogAcceptCategory(const char* category)
return true;
}
/**
* fStartedNewLine is a state variable held by the calling context that will
* suppress printing of the timestamp when multiple calls are made that don't
* end in a newline. Initialize it to true, and hold it, in the calling context.
*/
static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
{
string strStamped;
if (!fLogTimestamps)
return str;
if (*fStartedNewLine)
strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
else
strStamped = str;
if (!str.empty() && str[str.size()-1] == '\n')
*fStartedNewLine = true;
else
*fStartedNewLine = false;
return strStamped;
}
int LogPrintStr(const std::string &str)
{
int ret = 0; // Returns total number of characters written
static bool fStartedNewLine = true;
if (fPrintToConsole)
{
// print to console
ret = fwrite(str.data(), 1, str.size(), stdout);
fflush(stdout);
}
else if (fPrintToDebugLog)
{
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
// buffer if we haven't opened the log yet
if (fileout == NULL) {
assert(vMsgsBeforeOpenLog);
ret = strTimestamped.length();
vMsgsBeforeOpenLog->push_back(strTimestamped);
}
else
{
// reopen the log file, if requested
if (fReopenDebugLog) {
fReopenDebugLog = false;
boost::filesystem::path pathDebug = GetDebugLogPath();
if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
setbuf(fileout, NULL); // unbuffered
}
ret = FileWriteStr(strTimestamped, fileout);
}
}
return ret;
}
/** Interpret string as boolean, for argument parsing */
static bool InterpretBool(const std::string& strValue)
{

View File

@ -29,6 +29,8 @@
#include <boost/signals2/signal.hpp>
#include <boost/thread/exceptions.hpp>
#include <tracing.h>
static const bool DEFAULT_LOGTIMEMICROS = false;
static const bool DEFAULT_LOGIPS = false;
static const bool DEFAULT_LOGTIMESTAMPS = true;
@ -72,48 +74,34 @@ inline std::string _(const char* psz)
void SetupEnvironment();
bool SetupNetworking();
/** Returns the filtering directive set by the -debug flags. */
std::string LogConfigFilter();
/** Return true if log accepts specified category */
bool LogAcceptCategory(const char* category);
/** Send a string to the log output */
int LogPrintStr(const std::string &str);
#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__)
/**
* When we switch to C++11, this can be switched to variadic templates instead
* of this macro-based construction (see tinyformat.h).
*/
#define MAKE_ERROR_AND_LOG_FUNC(n) \
/** Print to debug.log if -debug=category switch is given OR category is NULL. */ \
template<TINYFORMAT_ARGTYPES(n)> \
static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \
{ \
if(!LogAcceptCategory(category)) return 0; \
return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \
} \
/** Log error and return false */ \
template<TINYFORMAT_ARGTYPES(n)> \
static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \
{ \
LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \
return false; \
}
/** Print to debug.log if -debug=category switch is given OR category is NULL. */
#define LogPrint(category, ...) do { \
std::string T_MSG = tfm::format(__VA_ARGS__); \
if (!T_MSG.empty() && T_MSG[T_MSG.size()-1] == '\n') { \
T_MSG.erase(T_MSG.size()-1); \
} \
TracingInfo( \
category == NULL ? "main" : category, \
T_MSG.c_str()); \
} while(0)
TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC)
#define LogError(category, ...) ([&]() { \
std::string T_MSG = tfm::format(__VA_ARGS__); \
TracingError(category, T_MSG.c_str()); \
return false; \
}())
/**
* Zero-arg versions of logging and error, these are not covered by
* TINYFORMAT_FOREACH_ARGNUM
*/
static inline int LogPrint(const char* category, const char* format)
template<typename... Args>
static inline bool error(const char* format, const Args&... args)
{
if(!LogAcceptCategory(category)) return 0;
return LogPrintStr(format);
}
static inline bool error(const char* format)
{
LogPrintStr(std::string("ERROR: ") + format + "\n");
return false;
return LogError("main", format, args...);
}
const boost::filesystem::path &ZC_GetParamsDir();
@ -144,7 +132,6 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
boost::filesystem::path GetTempPath();
boost::filesystem::path GetDebugLogPath();
bool OpenDebugLog();
void ShrinkDebugFile();
void runCommand(const std::string& strCommand);
const boost::filesystem::path GetExportDir();

View File

@ -254,8 +254,13 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
tx_ = CTransaction(rawTx);
}
LogPrint(isPureTaddrOnlyTx ? "zrpc" : "zrpcunsafe", "%s: spending %s to send %s with fee %s\n",
if (isPureTaddrOnlyTx) {
LogPrint("zrpc", "%s: spending %s to send %s with fee %s\n",
getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee));
} else {
LogPrint("zrpcunsafe", "%s: spending %s to send %s with fee %s\n",
getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee));
}
LogPrint("zrpc", "%s: transparent input: %s\n", getId(), FormatMoney(t_inputs_total));
LogPrint("zrpcunsafe", "%s: private input: %s\n", getId(), FormatMoney(z_inputs_total));
if (isToTaddr_) {

View File

@ -338,8 +338,13 @@ bool AsyncRPCOperation_sendmany::main_impl() {
}
}
LogPrint((isfromtaddr_) ? "zrpc" : "zrpcunsafe", "%s: spending %s to send %s with fee %s\n",
if (isfromtaddr_) {
LogPrint("zrpc", "%s: spending %s to send %s with fee %s\n",
getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee));
} else {
LogPrint("zrpcunsafe", "%s: spending %s to send %s with fee %s\n",
getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee));
}
LogPrint("zrpc", "%s: transparent input: %s (to choose from)\n", getId(), FormatMoney(t_inputs_total));
LogPrint("zrpcunsafe", "%s: private input: %s (to choose from)\n", getId(), FormatMoney(z_inputs_total));
LogPrint("zrpc", "%s: transparent output: %s\n", getId(), FormatMoney(t_outputs_total));