Auto merge of #4657 - str4d:tracing-fields, r=str4d
Add support for logging fields in spans and events Field values must be pointers to C strings, which in practice means that they cannot be formatted inline (as the pointer must remain valid across the FFI). This might be improved by future iterations of the macros. `LogPrint()` is also moved to the DEBUG level, leaving `LogPrintf()` at INFO.
This commit is contained in:
commit
940fe0b3be
|
@ -126,6 +126,15 @@ Files: src/crypto/ctaes/*
|
||||||
Copyright: Copyright (c) 2016 Pieter Wuille
|
Copyright: Copyright (c) 2016 Pieter Wuille
|
||||||
License: Expat
|
License: Expat
|
||||||
|
|
||||||
|
Files: src/rust/include/tracing.h
|
||||||
|
src/rust/src/tracing_ffi.rs
|
||||||
|
Copyright: Copyright (c) 2020 Jack Grigg
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files: src/rust/include/tracing/map.h
|
||||||
|
Copyright: Copyright (c) 2012 William Swanson
|
||||||
|
License: Expat-with-advertising-clause
|
||||||
|
|
||||||
Files: src/secp256k1/*
|
Files: src/secp256k1/*
|
||||||
Copyright: Copyright (c) 2013 Pieter Wuille
|
Copyright: Copyright (c) 2013 Pieter Wuille
|
||||||
License: Expat
|
License: Expat
|
||||||
|
@ -1237,3 +1246,28 @@ License: GPLv3-or-later-with-Autoconf-exception
|
||||||
Comment:
|
Comment:
|
||||||
The "special exception" is extended to the versions of files covered by
|
The "special exception" is extended to the versions of files covered by
|
||||||
this license that are distributed with this software.
|
this license that are distributed with this software.
|
||||||
|
|
||||||
|
License: Expat-with-advertising-clause
|
||||||
|
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.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the names of the authors or
|
||||||
|
their institutions shall not be used in advertising or otherwise to
|
||||||
|
promote the sale, use or other dealings in this Software without
|
||||||
|
prior written authorization from the authors.
|
||||||
|
|
23
src/main.cpp
23
src/main.cpp
|
@ -3235,11 +3235,24 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
|
||||||
nTimeBestReceived = GetTime();
|
nTimeBestReceived = GetTime();
|
||||||
mempool.AddTransactionsUpdated(1);
|
mempool.AddTransactionsUpdated(1);
|
||||||
|
|
||||||
LogPrintf("%s: new best=%s height=%d bits=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__,
|
auto hash = tfm::format("%s", chainActive.Tip()->GetBlockHash().ToString());
|
||||||
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nBits,
|
auto height = tfm::format("%d", chainActive.Height());
|
||||||
log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
|
auto bits = tfm::format("%d", chainActive.Tip()->nBits);
|
||||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
|
auto log2_work = tfm::format("%.8g", log(chainActive.Tip()->nChainWork.getdouble())/log(2.0));
|
||||||
Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
|
auto tx = tfm::format("%lu", (unsigned long)chainActive.Tip()->nChainTx);
|
||||||
|
auto date = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime());
|
||||||
|
auto progress = tfm::format("%f", Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()));
|
||||||
|
auto cache = tfm::format("%.1fMiB(%utx)", pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
|
||||||
|
|
||||||
|
TracingInfo("main", "UpdateTip: new best",
|
||||||
|
"hash", hash.c_str(),
|
||||||
|
"height", height.c_str(),
|
||||||
|
"bits", bits.c_str(),
|
||||||
|
"log2_work", log2_work.c_str(),
|
||||||
|
"tx", tx.c_str(),
|
||||||
|
"date", date.c_str(),
|
||||||
|
"progress", progress.c_str(),
|
||||||
|
"cache", cache.c_str());
|
||||||
|
|
||||||
cvBlockChange.notify_all();
|
cvBlockChange.notify_all();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2108,7 +2108,12 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
|
||||||
nPingUsecTime = 0;
|
nPingUsecTime = 0;
|
||||||
fPingQueued = false;
|
fPingQueued = false;
|
||||||
nMinPingUsecTime = std::numeric_limits<int64_t>::max();
|
nMinPingUsecTime = std::numeric_limits<int64_t>::max();
|
||||||
|
|
||||||
|
if (fLogIPs) {
|
||||||
|
span = TracingSpanFields("info", "net", "CNode", "addr", addrName.c_str());
|
||||||
|
} else {
|
||||||
span = TracingSpan("info", "net", "CNode");
|
span = TracingSpan("info", "net", "CNode");
|
||||||
|
}
|
||||||
auto spanGuard = span.Enter();
|
auto spanGuard = span.Enter();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define TRACING_INCLUDE_H_
|
#define TRACING_INCLUDE_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>
|
||||||
|
@ -67,7 +68,10 @@ typedef struct TracingSpanGuard TracingSpanGuard;
|
||||||
/// Creates a span for a callsite.
|
/// Creates a span for a callsite.
|
||||||
///
|
///
|
||||||
/// The span must be freed when it goes out of scope.
|
/// The span must be freed when it goes out of scope.
|
||||||
TracingSpanHandle* tracing_span_create(const TracingCallsite* callsite);
|
TracingSpanHandle* tracing_span_create(
|
||||||
|
const TracingCallsite* callsite,
|
||||||
|
const char* const* field_values,
|
||||||
|
size_t fields_len);
|
||||||
|
|
||||||
/// Clones the given span.
|
/// Clones the given span.
|
||||||
///
|
///
|
||||||
|
@ -103,6 +107,19 @@ 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_DOUBLEESCAPE(a) #a
|
||||||
#define T_ESCAPEQUOTE(a) T_DOUBLEESCAPE(a)
|
#define T_ESCAPEQUOTE(a) T_DOUBLEESCAPE(a)
|
||||||
|
|
||||||
|
@ -202,7 +219,7 @@ public:
|
||||||
Span() : inner(nullptr, tracing_span_free) {}
|
Span() : inner(nullptr, tracing_span_free) {}
|
||||||
|
|
||||||
/// Use the `TracingSpan` macro instead of calling this constructor directly.
|
/// Use the `TracingSpan` macro instead of calling this constructor directly.
|
||||||
Span(const TracingCallsite* callsite) : inner(tracing_span_create(callsite), tracing_span_free) {}
|
Span(const TracingCallsite* callsite, const char* const* field_values, size_t fields_len) : inner(tracing_span_create(callsite, field_values, fields_len), tracing_span_free) {}
|
||||||
|
|
||||||
Span(Span& span) : inner(std::move(span.inner)) {}
|
Span(Span& span) : inner(std::move(span.inner)) {}
|
||||||
Span(const Span& span) : inner(tracing_span_clone(span.inner.get()), tracing_span_free) {}
|
Span(const Span& span) : inner(tracing_span_clone(span.inner.get()), tracing_span_free) {}
|
||||||
|
@ -243,9 +260,31 @@ public:
|
||||||
/// strings.
|
/// strings.
|
||||||
#define TracingSpan(level, target, name) ([&] { \
|
#define TracingSpan(level, target, name) ([&] { \
|
||||||
static constexpr const char* const FIELDS[] = {}; \
|
static constexpr const char* const FIELDS[] = {}; \
|
||||||
|
const char* T_VALUES[] = {}; \
|
||||||
static TracingCallsite* CALLSITE = \
|
static TracingCallsite* CALLSITE = \
|
||||||
T_CALLSITE(name, target, level, FIELDS, true); \
|
T_CALLSITE(name, target, level, FIELDS, true); \
|
||||||
return tracing::Span(CALLSITE); \
|
return tracing::Span( \
|
||||||
|
CALLSITE, T_VALUES, T_ARRLEN(T_VALUES)); \
|
||||||
|
}())
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// Arguments: (level, target, name, key, value[, key2, value2, ...])
|
||||||
|
///
|
||||||
|
/// level, target, name, and all keys MUST be static constants, and MUST be
|
||||||
|
/// valid UTF-8 strings.
|
||||||
|
#define TracingSpanFields(level, target, name, ...) ([&] { \
|
||||||
|
static constexpr const char* const FIELDS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
const char* T_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
static TracingCallsite* CALLSITE = \
|
||||||
|
T_CALLSITE(name, target, level, FIELDS, true); \
|
||||||
|
return tracing::Span( \
|
||||||
|
CALLSITE, T_VALUES, T_ARRLEN(T_VALUES)); \
|
||||||
}())
|
}())
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -256,11 +295,12 @@ public:
|
||||||
/// Constructs a new event.
|
/// Constructs a new event.
|
||||||
///
|
///
|
||||||
/// level and target MUST be static constants, and MUST be valid UTF-8 strings.
|
/// level and target MUST be static constants, and MUST be valid UTF-8 strings.
|
||||||
#define TracingLog(level, target, message) \
|
#define TracingLog(level, target, ...) \
|
||||||
do { \
|
do { \
|
||||||
static constexpr const char* const FIELDS[] = \
|
static constexpr const char* const FIELDS[] = \
|
||||||
{"message"}; \
|
{T_FIELD_NAMES("message", __VA_ARGS__)}; \
|
||||||
const char* T_VALUES[] = {message}; \
|
const char* T_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES("message", __VA_ARGS__)}; \
|
||||||
static TracingCallsite* CALLSITE = T_CALLSITE( \
|
static TracingCallsite* CALLSITE = T_CALLSITE( \
|
||||||
"event " __FILE__ ":" T_ESCAPEQUOTE(__LINE__), \
|
"event " __FILE__ ":" T_ESCAPEQUOTE(__LINE__), \
|
||||||
target, level, FIELDS, false); \
|
target, level, FIELDS, false); \
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 William Swanson
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Except as contained in this notice, the names of the authors or
|
||||||
|
* their institutions shall not be used in advertising or otherwise to
|
||||||
|
* promote the sale, use or other dealings in this Software without
|
||||||
|
* prior written authorization from the authors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAP_H_INCLUDED
|
||||||
|
#define MAP_H_INCLUDED
|
||||||
|
|
||||||
|
#define EVAL0(...) __VA_ARGS__
|
||||||
|
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
|
||||||
|
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
|
||||||
|
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
|
||||||
|
#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
|
||||||
|
#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
|
||||||
|
|
||||||
|
#define MAP_END(...)
|
||||||
|
#define MAP_OUT
|
||||||
|
#define MAP_COMMA ,
|
||||||
|
|
||||||
|
#define MAP_GET_END2() 0, MAP_END
|
||||||
|
#define MAP_GET_END1(...) MAP_GET_END2
|
||||||
|
#define MAP_GET_END(...) MAP_GET_END1
|
||||||
|
#define MAP_NEXT0(test, next, ...) next MAP_OUT
|
||||||
|
#define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0)
|
||||||
|
#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
|
||||||
|
|
||||||
|
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__)
|
||||||
|
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0)
|
||||||
|
#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
|
||||||
|
|
||||||
|
#define MAP_LIST0(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, peek, __VA_ARGS__)
|
||||||
|
#define MAP_LIST1(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, peek, __VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the function macro `f` to each of the remaining parameters.
|
||||||
|
*/
|
||||||
|
#define MAP(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the function macro `f` to each of the remaining parameters and
|
||||||
|
* inserts commas between the results.
|
||||||
|
*/
|
||||||
|
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||||
|
|
||||||
|
#endif
|
|
@ -295,6 +295,9 @@ pub extern "C" fn tracing_callsite(
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! repeat {
|
macro_rules! repeat {
|
||||||
|
(0, $val:expr) => {
|
||||||
|
[]
|
||||||
|
};
|
||||||
(1, $val:expr) => {
|
(1, $val:expr) => {
|
||||||
[$val]
|
[$val]
|
||||||
};
|
};
|
||||||
|
@ -460,14 +463,77 @@ macro_rules! repeat {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn tracing_span_create(callsite: *const FfiCallsite) -> *mut Span {
|
pub extern "C" fn tracing_span_create(
|
||||||
|
callsite: *const FfiCallsite,
|
||||||
|
field_values: *const *const c_char,
|
||||||
|
fields_len: usize,
|
||||||
|
) -> *mut Span {
|
||||||
let callsite = unsafe { &*callsite };
|
let callsite = unsafe { &*callsite };
|
||||||
|
let field_values = unsafe { slice::from_raw_parts(field_values, fields_len) };
|
||||||
|
|
||||||
let meta = callsite.metadata();
|
let meta = callsite.metadata();
|
||||||
assert!(meta.is_span());
|
assert!(meta.is_span());
|
||||||
|
|
||||||
let span = if level_enabled!(*meta.level()) && callsite.is_enabled() {
|
let span = if level_enabled!(*meta.level()) && callsite.is_enabled() {
|
||||||
Span::new(meta, &meta.fields().value_set(&[]))
|
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());
|
||||||
|
|
||||||
|
use tracing::field::display;
|
||||||
|
macro_rules! new_span {
|
||||||
|
($n:tt) => {
|
||||||
|
Span::new(
|
||||||
|
meta,
|
||||||
|
&meta.fields().value_set(&repeat!(
|
||||||
|
$n,
|
||||||
|
(
|
||||||
|
&fi.next().unwrap(),
|
||||||
|
Some(&display(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() {
|
||||||
|
0 => new_span!(0),
|
||||||
|
1 => new_span!(1),
|
||||||
|
2 => new_span!(2),
|
||||||
|
3 => new_span!(3),
|
||||||
|
4 => new_span!(4),
|
||||||
|
5 => new_span!(5),
|
||||||
|
6 => new_span!(6),
|
||||||
|
7 => new_span!(7),
|
||||||
|
8 => new_span!(8),
|
||||||
|
9 => new_span!(9),
|
||||||
|
10 => new_span!(10),
|
||||||
|
11 => new_span!(11),
|
||||||
|
12 => new_span!(12),
|
||||||
|
13 => new_span!(13),
|
||||||
|
14 => new_span!(14),
|
||||||
|
15 => new_span!(15),
|
||||||
|
16 => new_span!(16),
|
||||||
|
17 => new_span!(17),
|
||||||
|
18 => new_span!(18),
|
||||||
|
19 => new_span!(19),
|
||||||
|
20 => new_span!(20),
|
||||||
|
21 => new_span!(21),
|
||||||
|
22 => new_span!(22),
|
||||||
|
23 => new_span!(23),
|
||||||
|
24 => new_span!(24),
|
||||||
|
25 => new_span!(25),
|
||||||
|
26 => new_span!(26),
|
||||||
|
27 => new_span!(27),
|
||||||
|
28 => new_span!(28),
|
||||||
|
29 => new_span!(29),
|
||||||
|
30 => new_span!(30),
|
||||||
|
31 => new_span!(31),
|
||||||
|
32 => new_span!(32),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Span::none()
|
Span::none()
|
||||||
};
|
};
|
||||||
|
@ -522,6 +588,7 @@ pub extern "C" fn tracing_log(
|
||||||
.map(|&p| unsafe { CStr::from_ptr(p) })
|
.map(|&p| unsafe { CStr::from_ptr(p) })
|
||||||
.map(|cs| cs.to_string_lossy());
|
.map(|cs| cs.to_string_lossy());
|
||||||
|
|
||||||
|
use tracing::field::display;
|
||||||
macro_rules! dispatch {
|
macro_rules! dispatch {
|
||||||
($n:tt) => {
|
($n:tt) => {
|
||||||
Event::dispatch(
|
Event::dispatch(
|
||||||
|
@ -530,7 +597,7 @@ pub extern "C" fn tracing_log(
|
||||||
$n,
|
$n,
|
||||||
(
|
(
|
||||||
&fi.next().unwrap(),
|
&fi.next().unwrap(),
|
||||||
Some(&vi.next().unwrap().as_ref() as &dyn Value)
|
Some(&display(vi.next().unwrap().as_ref()) as &dyn Value)
|
||||||
)
|
)
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
|
|
@ -230,10 +230,10 @@ std::string LogConfigFilter()
|
||||||
std::set<std::string> setCategories(categories.begin(), categories.end());
|
std::set<std::string> setCategories(categories.begin(), categories.end());
|
||||||
if (setCategories.count(string("")) != 0 || setCategories.count(string("1")) != 0) {
|
if (setCategories.count(string("")) != 0 || setCategories.count(string("1")) != 0) {
|
||||||
// Turn on the firehose!
|
// Turn on the firehose!
|
||||||
filter = "info";
|
filter = "debug";
|
||||||
} else {
|
} else {
|
||||||
for (auto category : setCategories) {
|
for (auto category : setCategories) {
|
||||||
filter += "," + category + "=info";
|
filter += "," + category + "=debug";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/util.h
13
src/util.h
|
@ -79,17 +79,18 @@ std::string LogConfigFilter();
|
||||||
/** Return true if log accepts specified category */
|
/** Return true if log accepts specified category */
|
||||||
bool LogAcceptCategory(const char* category);
|
bool LogAcceptCategory(const char* category);
|
||||||
|
|
||||||
#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__)
|
/** Print to debug.log with level INFO and category "main". */
|
||||||
|
#define LogPrintf(...) LogPrintInner("info", "main", __VA_ARGS__)
|
||||||
|
|
||||||
/** Print to debug.log if -debug=category switch is given OR category is NULL. */
|
/** Print to debug.log with level DEBUG. */
|
||||||
#define LogPrint(category, ...) do { \
|
#define LogPrint(category, ...) LogPrintInner("debug", category, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define LogPrintInner(level, category, ...) do { \
|
||||||
std::string T_MSG = tfm::format(__VA_ARGS__); \
|
std::string T_MSG = tfm::format(__VA_ARGS__); \
|
||||||
if (!T_MSG.empty() && T_MSG[T_MSG.size()-1] == '\n') { \
|
if (!T_MSG.empty() && T_MSG[T_MSG.size()-1] == '\n') { \
|
||||||
T_MSG.erase(T_MSG.size()-1); \
|
T_MSG.erase(T_MSG.size()-1); \
|
||||||
} \
|
} \
|
||||||
TracingInfo( \
|
TracingLog(level, category, T_MSG.c_str()); \
|
||||||
category == NULL ? "main" : category, \
|
|
||||||
T_MSG.c_str()); \
|
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define LogError(category, ...) ([&]() { \
|
#define LogError(category, ...) ([&]() { \
|
||||||
|
|
Loading…
Reference in New Issue