mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 08:11:04 +00:00
Tracing for wasm with bridging to native (#6916)
* implement events handling, implement parent_id for spans & events * add events to sp_io::storage * update test * add tests * adjust limit * let tracing crate handle parent_ids * re-enable current-id tracking * add test for threads with CurrentSpan * fix log level * remove redundant check for non wasm traces * remove duplicate definition in test * Adding conditional events API * prefer explicit parent_id over current, enhance test * limit changes to client::tracing event implementation * remove From impl due to fallback required on parent_id * make tracing codecable * replace with global tracing * new tracing interface * impl TracingSubscriber in client * implement access to global TracingSubscriber from primitives * span for wasm * increment towards Wasm Tracing Subscriber implementation * increment, remove sp-tracing from runtime-interface * increment, it compiles * attained original functionality with new mechanism * implement remaining TracingSubscriber functions * remove spans from decl_module * add handling for encoded values * Revert "replace with global tracing" This reverts commit 8824a60deea54d9b437407a21c8ceaf6a1902ee5. * Wasm Side Tracing * tracing on wasm * enable tracing wasm on node-runtime * export all the macros in std * tracing subscriber on wasm-side only * pass spans and events over and record them * reactivate previous code and cleanup * further cleaning up * extend the span macros, activate through executive * tracking the actual extrinsic, too * style * fixing tests * spaces -> tabs * attempting to reactivate params * activate our tests in CI * some passing * tests passing * with core lazy * global tracer for wasm side with pass over * fixing metadata referencing * remove const_fn feature requirement * reenable dispatch traces * reset client tracing * further cleaning up * fixing runtime-test * move tracing-build setup into runtime-test * Merge DebugWriter from tracing and frame-support, move to sp-std * remove dangling fixme * Docs for tracing primitives * cleaning up a bit more * Wasm interface docs * optimise docs.rs setup * adding tracing flags to uncomment * remove brace * fixing imports * fixing broken syntax * add required modules * nicer formatting * better target management * adding low level storage tracing events into frame * add custom Debug impl for WasmMetadata * cloning profiler * adding info about cloning profiler * using in-scope for within calls * proper time tracing, cleaning up println * allow to disable tracing on runtime_interface-macro * disable tracing for wasm-tracing-interface * simplify wasm-tracing-api * update client to new interface * fixing docs and tests for sp-tracing * update integration tests * re-activating enter_span * dropping FIXME, it's documented * fix formatting * fix formatting * fix imports * more debug info * inform wasm about it being disabled by returning 1 * only one tracer, but enabled multi-all support * make trait pub again for tests * Apply suggestions from code review Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> * fixing wasm doc tests for proper usage * remove unnecessary import * fixing formatting * minor style fixes * downgrading wabt * update error message for UI * Fix interface test * next attempt to fix macros * geee * revert tracing on hashed for future PR * remove local macros, use originals * we are able to convert to static items * implement more WasmValue types * adding support to convert str, debug and encoded values * more minor fixes * revert unsafe 'static making * fix indentation * remove commented lines * bump all them tracing versions * cleaning up docs and info * document new flag * the new layered system handles span cloning better * Apply suggestions from code review Co-authored-by: David <dvdplm@gmail.com> Co-authored-by: Matt Rutherford <mattrutherford@users.noreply.github.com> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: David <dvdplm@gmail.com>
This commit is contained in:
committed by
GitHub
parent
649bee1a1e
commit
a9c73113a8
@@ -17,7 +17,7 @@
|
||||
|
||||
//! Substrate tracing primitives and macros.
|
||||
//!
|
||||
//! To trace functions or invidual code in Substrate, this crate provides [`tracing_span`]
|
||||
//! To trace functions or invidual code in Substrate, this crate provides [`within_span`]
|
||||
//! and [`enter_span`]. See the individual docs for how to use these macros.
|
||||
//!
|
||||
//! Note that to allow traces from wasm execution environment there are
|
||||
@@ -28,21 +28,80 @@
|
||||
//! Additionally, we have a const: `WASM_TRACE_IDENTIFIER`, which holds a span name used
|
||||
//! to signal that the 'actual' span name and target should be retrieved instead from
|
||||
//! the associated Fields mentioned above.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate rental;
|
||||
/// Tracing facilities and helpers.
|
||||
///
|
||||
/// This is modeled after the `tracing`/`tracing-core` interface and uses that more or
|
||||
/// less directly for the native side. Because of certain optimisations the these crates
|
||||
/// have done, the wasm implementation diverges slightly and is optimised for thtat use
|
||||
/// case (like being able to cross the wasm/native boundary via scale codecs).
|
||||
///
|
||||
/// One of said optimisations is that all macros will yield to a `noop` in non-std unless
|
||||
/// the `with-tracing` feature is explicitly activated. This allows you to just use the
|
||||
/// tracing wherever you deem fit and without any performance impact by default. Only if
|
||||
/// the specific `with-tracing`-feature is activated on this crate will it actually include
|
||||
/// the tracing code in the non-std environment.
|
||||
///
|
||||
/// Because of that optimisation, you should not use the `span!` and `span_*!` macros
|
||||
/// directly as they yield nothing without the feature present. Instead you should use
|
||||
/// `enter_span!` and `within_span!` – which would strip away even any parameter conversion
|
||||
/// you do within the span-definition (and thus optimise your performance). For your
|
||||
/// convineience you directly specify the `Level` and name of the span or use the full
|
||||
/// feature set of `span!`/`span_*!` on it:
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// sp_tracing::enter_span!(sp_tracing::Level::TRACE, "fn wide span");
|
||||
/// {
|
||||
/// sp_tracing::enter_span!(sp_tracing::trace_span!("outer-span"));
|
||||
/// {
|
||||
/// sp_tracing::enter_span!(sp_tracing::Level::TRACE, "inner-span");
|
||||
/// // ..
|
||||
/// } // inner span exists here
|
||||
/// } // outer span exists here
|
||||
///
|
||||
/// sp_tracing::within_span! {
|
||||
/// sp_tracing::debug_span!("debug-span", you_can_pass="any params");
|
||||
/// 1 + 1;
|
||||
/// // some other complex code
|
||||
/// } // debug span ends here
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// # Setup
|
||||
///
|
||||
/// This project only provides the macros and facilities to manage tracing
|
||||
/// it doesn't implement the tracing subscriber or backend directly – that is
|
||||
/// up to the developer integrating it into a specific environment. In native
|
||||
/// this can and must be done through the regular `tracing`-facitilies, please
|
||||
/// see their documentation for details.
|
||||
///
|
||||
/// On the wasm-side we've adopted a similar approach of having a global
|
||||
/// `TracingSubscriber` that the macros call and that does the actual work
|
||||
/// of tracking. To provide your tracking, you must implement `TracingSubscriber`
|
||||
/// and call `set_tracing_subscriber` at the very beginning of your execution –
|
||||
/// the default subscriber is doing nothing, so any spans or events happening before
|
||||
/// will not be recorded!
|
||||
///
|
||||
|
||||
mod types;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[doc(hidden)]
|
||||
pub use tracing;
|
||||
use tracing;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod proxy;
|
||||
pub use tracing::{
|
||||
debug, debug_span, error, error_span, info, info_span, trace, trace_span, warn, warn_span,
|
||||
span, event, Level, Span,
|
||||
};
|
||||
|
||||
pub use crate::types::{
|
||||
WasmMetadata, WasmEntryAttributes, WasmValuesSet, WasmValue, WasmFields, WasmLevel, WasmFieldName
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// Try to init a simple tracing subscriber with log compatibility layer.
|
||||
/// Ignores any error. Useful for testing.
|
||||
@@ -51,74 +110,127 @@ pub fn try_init_simple() {
|
||||
let _ = tracing_subscriber::fmt().with_writer(std::io::stderr).try_init();
|
||||
}
|
||||
|
||||
/// Flag to signal whether to run wasm tracing
|
||||
#[cfg(feature = "std")]
|
||||
static WASM_TRACING_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
pub use crate::types::{
|
||||
WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER
|
||||
};
|
||||
|
||||
|
||||
/// Runs given code within a tracing span, measuring it's execution time.
|
||||
///
|
||||
/// If tracing is not enabled, the code is still executed.
|
||||
/// If tracing is not enabled, the code is still executed. Pass in level and name or
|
||||
/// use any valid `sp_tracing::Span`followe by `;` and the code to execute,
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// sp_tracing::tracing_span! {
|
||||
/// sp_tracing::within_span! {
|
||||
/// sp_tracing::Level::TRACE,
|
||||
/// "test-span";
|
||||
/// 1 + 1;
|
||||
/// // some other complex code
|
||||
/// }
|
||||
///
|
||||
/// sp_tracing::within_span! {
|
||||
/// sp_tracing::span!(sp_tracing::Level::WARN, "warn-span", you_can_pass="any params");
|
||||
/// 1 + 1;
|
||||
/// // some other complex code
|
||||
/// }
|
||||
///
|
||||
/// sp_tracing::within_span! {
|
||||
/// sp_tracing::debug_span!("debug-span", you_can_pass="any params");
|
||||
/// 1 + 1;
|
||||
/// // some other complex code
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(any(feature = "std", feature = "with-tracing"))]
|
||||
#[macro_export]
|
||||
macro_rules! tracing_span {
|
||||
macro_rules! within_span {
|
||||
(
|
||||
$span:expr;
|
||||
$( $code:tt )*
|
||||
) => {
|
||||
$span.in_scope(||
|
||||
{
|
||||
$( $code )*
|
||||
}
|
||||
)
|
||||
};
|
||||
(
|
||||
$lvl:expr,
|
||||
$name:expr;
|
||||
$( $code:tt )*
|
||||
) => {
|
||||
{
|
||||
$crate::enter_span!($name);
|
||||
$( $code )*
|
||||
$crate::within_span!($crate::span!($crate::Level::TRACE, $name); $( $code )*)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "std"), not(feature = "with-tracing")))]
|
||||
#[macro_export]
|
||||
macro_rules! within_span {
|
||||
(
|
||||
$span:stmt;
|
||||
$( $code:tt )*
|
||||
) => {
|
||||
$( $code )*
|
||||
};
|
||||
(
|
||||
$lvl:expr,
|
||||
$name:expr;
|
||||
$( $code:tt )*
|
||||
) => {
|
||||
$( $code )*
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// Enter a span - noop for `no_std` without `with-tracing`
|
||||
#[cfg(all(not(feature = "std"), not(feature = "with-tracing")))]
|
||||
#[macro_export]
|
||||
macro_rules! enter_span {
|
||||
( $lvl:expr, $name:expr ) => ( );
|
||||
( $name:expr ) => ( ) // no-op
|
||||
}
|
||||
|
||||
/// Enter a span.
|
||||
///
|
||||
/// The span will be valid, until the scope is left.
|
||||
/// The span will be valid, until the scope is left. Use either level and name
|
||||
/// or pass in any valid `sp_tracing::Span` for extended usage. The span will
|
||||
/// be exited on drop – which is at the end of the block or to the next
|
||||
/// `enter_span!` calls, as this overwrites the local variable. For nested
|
||||
/// usage or to ensure the span closes at certain time either put it into a block
|
||||
/// or use `within_span!`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// sp_tracing::enter_span!("test-span");
|
||||
/// sp_tracing::enter_span!(sp_tracing::Level::TRACE, "test-span");
|
||||
/// // previous will be dropped here
|
||||
/// sp_tracing::enter_span!(
|
||||
/// sp_tracing::span!(sp_tracing::Level::DEBUG, "debug-span", params="value"));
|
||||
/// sp_tracing::enter_span!(sp_tracing::info_span!("info-span", params="value"));
|
||||
///
|
||||
/// {
|
||||
/// sp_tracing::enter_span!(sp_tracing::Level::TRACE, "outer-span");
|
||||
/// {
|
||||
/// sp_tracing::enter_span!(sp_tracing::Level::TRACE, "inner-span");
|
||||
/// // ..
|
||||
/// } // inner span exists here
|
||||
/// } // outer span exists here
|
||||
///
|
||||
/// ```
|
||||
#[cfg(any(feature = "std", feature = "with-tracing"))]
|
||||
#[macro_export]
|
||||
macro_rules! enter_span {
|
||||
( $name:expr ) => {
|
||||
let __tracing_span__ = $crate::if_tracing!(
|
||||
$crate::tracing::span!($crate::tracing::Level::TRACE, $name)
|
||||
);
|
||||
let __tracing_guard__ = $crate::if_tracing!(__tracing_span__.enter());
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the given code if the tracing dependency is enabled.
|
||||
#[macro_export]
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! if_tracing {
|
||||
( $if:expr ) => {{ $if }}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[cfg(not(feature = "std"))]
|
||||
macro_rules! if_tracing {
|
||||
( $if:expr ) => {{}}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn wasm_tracing_enabled() -> bool {
|
||||
WASM_TRACING_ENABLED.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn set_wasm_tracing(b: bool) {
|
||||
WASM_TRACING_ENABLED.store(b, Ordering::Relaxed)
|
||||
( $span:expr ) => {
|
||||
// Calling this twice in a row will overwrite (and drop) the earlier
|
||||
// that is a _documented feature_!
|
||||
let __within_span__ = $span;
|
||||
let __tracing_guard__ = __within_span__.enter();
|
||||
};
|
||||
( $lvl:expr, $name:expr ) => {
|
||||
$crate::enter_span!($crate::span!($crate::Level::TRACE, $name))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Proxy to allow entering tracing spans from wasm.
|
||||
//!
|
||||
//! Use `enter_span` and `exit_span` to surround the code that you wish to trace
|
||||
use rental;
|
||||
use tracing::info_span;
|
||||
|
||||
/// Used to identify a proxied WASM trace
|
||||
pub const WASM_TRACE_IDENTIFIER: &'static str = "WASM_TRACE";
|
||||
/// Used to extract the real `target` from the associated values of the span
|
||||
pub const WASM_TARGET_KEY: &'static str = "proxied_wasm_target";
|
||||
/// Used to extract the real `name` from the associated values of the span
|
||||
pub const WASM_NAME_KEY: &'static str = "proxied_wasm_name";
|
||||
|
||||
const MAX_SPANS_LEN: usize = 1000;
|
||||
|
||||
rental! {
|
||||
pub mod rent_span {
|
||||
#[rental]
|
||||
pub struct SpanAndGuard {
|
||||
span: Box<tracing::Span>,
|
||||
guard: tracing::span::Entered<'span>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires a tracing::Subscriber to process span traces,
|
||||
/// this is available when running with client (and relevant cli params).
|
||||
pub struct TracingProxy {
|
||||
next_id: u64,
|
||||
spans: Vec<(u64, rent_span::SpanAndGuard)>,
|
||||
}
|
||||
|
||||
impl Drop for TracingProxy {
|
||||
fn drop(&mut self) {
|
||||
if !self.spans.is_empty() {
|
||||
log::debug!(
|
||||
target: "tracing",
|
||||
"Dropping TracingProxy with {} un-exited spans, marking as not valid", self.spans.len()
|
||||
);
|
||||
while let Some((_, mut sg)) = self.spans.pop() {
|
||||
sg.rent_all_mut(|s| { s.span.record("is_valid_trace", &false); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TracingProxy {
|
||||
pub fn new() -> TracingProxy {
|
||||
TracingProxy {
|
||||
next_id: 0,
|
||||
spans: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TracingProxy {
|
||||
/// Create and enter a `tracing` Span, returning the span id,
|
||||
/// which should be passed to `exit_span(id)` to signal that the span should exit.
|
||||
pub fn enter_span(&mut self, proxied_wasm_target: &str, proxied_wasm_name: &str) -> u64 {
|
||||
// The identifiers `proxied_wasm_target` and `proxied_wasm_name` must match their associated const,
|
||||
// WASM_TARGET_KEY and WASM_NAME_KEY.
|
||||
let span = info_span!(WASM_TRACE_IDENTIFIER, is_valid_trace = true, proxied_wasm_target, proxied_wasm_name);
|
||||
self.next_id += 1;
|
||||
let sg = rent_span::SpanAndGuard::new(
|
||||
Box::new(span),
|
||||
|span| span.enter(),
|
||||
);
|
||||
self.spans.push((self.next_id, sg));
|
||||
if self.spans.len() > MAX_SPANS_LEN {
|
||||
// This is to prevent unbounded growth of Vec and could mean one of the following:
|
||||
// 1. Too many nested spans, or MAX_SPANS_LEN is too low.
|
||||
// 2. Not correctly exiting spans due to misconfiguration / misuse
|
||||
log::warn!(
|
||||
target: "tracing",
|
||||
"TracingProxy MAX_SPANS_LEN exceeded, removing oldest span."
|
||||
);
|
||||
let mut sg = self.spans.remove(0).1;
|
||||
sg.rent_all_mut(|s| { s.span.record("is_valid_trace", &false); });
|
||||
}
|
||||
self.next_id
|
||||
}
|
||||
|
||||
/// Exit a span by dropping it along with it's associated guard.
|
||||
pub fn exit_span(&mut self, id: u64) {
|
||||
if self.spans.last().map(|l| id > l.0).unwrap_or(true) {
|
||||
log::warn!(target: "tracing", "Span id not found in TracingProxy: {}", id);
|
||||
return;
|
||||
}
|
||||
let mut last_span = self.spans.pop().expect("Just checked that there is an element to pop; qed");
|
||||
while id < last_span.0 {
|
||||
log::warn!(
|
||||
target: "tracing",
|
||||
"TracingProxy Span ids not equal! id parameter given: {}, last span: {}",
|
||||
id,
|
||||
last_span.0,
|
||||
);
|
||||
last_span.1.rent_all_mut(|s| { s.span.record("is_valid_trace", &false); });
|
||||
if let Some(s) = self.spans.pop() {
|
||||
last_span = s;
|
||||
} else {
|
||||
log::warn!(target: "tracing", "Span id not found in TracingProxy {}", id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn create_spans(proxy: &mut TracingProxy, qty: usize) -> Vec<u64> {
|
||||
let mut spans = Vec::new();
|
||||
for n in 0..qty {
|
||||
spans.push(proxy.enter_span("target", &format!("{}", n)));
|
||||
}
|
||||
spans
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_spans_len_respected() {
|
||||
let mut proxy = TracingProxy::new();
|
||||
let _spans = create_spans(&mut proxy, MAX_SPANS_LEN + 10);
|
||||
assert_eq!(proxy.spans.len(), MAX_SPANS_LEN);
|
||||
// ensure oldest spans removed
|
||||
assert_eq!(proxy.spans[0].0, 11);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handles_span_exit_scenarios() {
|
||||
let mut proxy = TracingProxy::new();
|
||||
let _spans = create_spans(&mut proxy, 10);
|
||||
assert_eq!(proxy.spans.len(), 10);
|
||||
// exit span normally
|
||||
proxy.exit_span(10);
|
||||
assert_eq!(proxy.spans.len(), 9);
|
||||
// skip and exit outer span without exiting inner, id: 8 instead of 9
|
||||
proxy.exit_span(8);
|
||||
// should have also removed the inner span that was lost
|
||||
assert_eq!(proxy.spans.len(), 7);
|
||||
// try to exit span not held
|
||||
proxy.exit_span(9);
|
||||
assert_eq!(proxy.spans.len(), 7);
|
||||
// exit all spans
|
||||
proxy.exit_span(1);
|
||||
assert_eq!(proxy.spans.len(), 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,623 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2020 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Types for wasm based tracing. Loosly inspired by `tracing-core` but
|
||||
/// optimised for the specific use case.
|
||||
|
||||
use core::{format_args, fmt::Debug};
|
||||
use sp_std::{
|
||||
vec, vec::Vec,
|
||||
};
|
||||
use sp_std::Writer;
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// The Tracing Level – the user can filter by this
|
||||
#[derive(Clone, Encode, Decode, Debug)]
|
||||
pub enum WasmLevel {
|
||||
/// This is a fatal errors
|
||||
ERROR,
|
||||
/// This is a warning you should be aware of
|
||||
WARN,
|
||||
/// Nice to now info
|
||||
INFO,
|
||||
/// Further information for debugging purposes
|
||||
DEBUG,
|
||||
/// The lowest level, keeping track of minute detail
|
||||
TRACE
|
||||
}
|
||||
|
||||
|
||||
impl From<&tracing_core::Level> for WasmLevel {
|
||||
fn from(l: &tracing_core::Level) -> WasmLevel {
|
||||
match l {
|
||||
&tracing_core::Level::ERROR => WasmLevel::ERROR,
|
||||
&tracing_core::Level::WARN => WasmLevel::WARN,
|
||||
&tracing_core::Level::INFO => WasmLevel::INFO,
|
||||
&tracing_core::Level::DEBUG => WasmLevel::DEBUG,
|
||||
&tracing_core::Level::TRACE => WasmLevel::TRACE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl core::default::Default for WasmLevel {
|
||||
fn default() -> Self {
|
||||
WasmLevel::TRACE
|
||||
}
|
||||
}
|
||||
|
||||
/// A paramter value provided to the span/event
|
||||
#[derive(Encode, Decode, Clone)]
|
||||
pub enum WasmValue {
|
||||
U8(u8),
|
||||
I8(i8),
|
||||
U32(u32),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
U64(u64),
|
||||
Bool(bool),
|
||||
Str(Vec<u8>),
|
||||
/// Debug or Display call, this is most-likely a print-able UTF8 String
|
||||
Formatted(Vec<u8>),
|
||||
/// SCALE CODEC encoded object – the name should allow the received to know
|
||||
/// how to decode this.
|
||||
Encoded(Vec<u8>),
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for WasmValue {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
match self {
|
||||
WasmValue::U8(ref i) => {
|
||||
f.write_fmt(format_args!("{}_u8", i))
|
||||
}
|
||||
WasmValue::I8(ref i) => {
|
||||
f.write_fmt(format_args!("{}_i8", i))
|
||||
}
|
||||
WasmValue::U32(ref i) => {
|
||||
f.write_fmt(format_args!("{}_u32", i))
|
||||
}
|
||||
WasmValue::I32(ref i) => {
|
||||
f.write_fmt(format_args!("{}_i32", i))
|
||||
}
|
||||
WasmValue::I64(ref i) => {
|
||||
f.write_fmt(format_args!("{}_i64", i))
|
||||
}
|
||||
WasmValue::U64(ref i) => {
|
||||
f.write_fmt(format_args!("{}_u64", i))
|
||||
}
|
||||
WasmValue::Bool(ref i) => {
|
||||
f.write_fmt(format_args!("{}_bool", i))
|
||||
}
|
||||
WasmValue::Formatted(ref i) | WasmValue::Str(ref i) => {
|
||||
if let Ok(v) = core::str::from_utf8(i) {
|
||||
f.write_fmt(format_args!("{}", v))
|
||||
} else {
|
||||
f.write_fmt(format_args!("{:?}", i))
|
||||
}
|
||||
}
|
||||
WasmValue::Encoded(ref v) => {
|
||||
f.write_str("Scale(")?;
|
||||
for byte in v {
|
||||
f.write_fmt(format_args!("{:02x}", byte))?;
|
||||
}
|
||||
f.write_str(")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for WasmValue {
|
||||
fn from(u: u8) -> WasmValue {
|
||||
WasmValue::U8(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&i8> for WasmValue {
|
||||
fn from(inp: &i8) -> WasmValue {
|
||||
WasmValue::I8(inp.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for WasmValue {
|
||||
fn from(inp: &str) -> WasmValue {
|
||||
WasmValue::Str(inp.as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&&str> for WasmValue {
|
||||
fn from(inp: &&str) -> WasmValue {
|
||||
WasmValue::Str((*inp).as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for WasmValue {
|
||||
fn from(inp: bool) -> WasmValue {
|
||||
WasmValue::Bool(inp)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<core::fmt::Arguments<'_>> for WasmValue {
|
||||
fn from(inp: core::fmt::Arguments<'_>) -> WasmValue {
|
||||
let mut buf = Writer::default();
|
||||
core::fmt::write(&mut buf, inp).expect("Writing of arguments doesn't fail");
|
||||
WasmValue::Formatted(buf.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i8> for WasmValue {
|
||||
fn from(u: i8) -> WasmValue {
|
||||
WasmValue::I8(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for WasmValue {
|
||||
fn from(u: i32) -> WasmValue {
|
||||
WasmValue::I32(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&i32> for WasmValue {
|
||||
fn from(u: &i32) -> WasmValue {
|
||||
WasmValue::I32(*u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for WasmValue {
|
||||
fn from(u: u32) -> WasmValue {
|
||||
WasmValue::U32(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&u32> for WasmValue {
|
||||
fn from(u: &u32) -> WasmValue {
|
||||
WasmValue::U32(*u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for WasmValue {
|
||||
fn from(u: u64) -> WasmValue {
|
||||
WasmValue::U64(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for WasmValue {
|
||||
fn from(u: i64) -> WasmValue {
|
||||
WasmValue::I64(u)
|
||||
}
|
||||
}
|
||||
|
||||
/// The name of a field provided as the argument name when contstructing an
|
||||
/// `event!` or `span!`.
|
||||
/// Generally generated automaticaly via `stringify` from an `'static &str`.
|
||||
/// Likely print-able.
|
||||
#[derive(Encode, Decode, Clone)]
|
||||
pub struct WasmFieldName(Vec<u8>);
|
||||
|
||||
impl core::fmt::Debug for WasmFieldName {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
if let Ok(v) = core::str::from_utf8(&self.0) {
|
||||
f.write_fmt(format_args!("{}", v))
|
||||
} else {
|
||||
for byte in self.0.iter() {
|
||||
f.write_fmt(format_args!("{:02x}", byte))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for WasmFieldName {
|
||||
fn from(v: Vec<u8>) -> Self {
|
||||
WasmFieldName(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for WasmFieldName {
|
||||
fn from(v: &str) -> Self {
|
||||
WasmFieldName(v.as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of `WasmFieldName`s in the order provided
|
||||
#[derive(Encode, Decode, Clone, Debug)]
|
||||
pub struct WasmFields(Vec<WasmFieldName>);
|
||||
|
||||
impl WasmFields {
|
||||
/// Iterate over the fields
|
||||
pub fn iter(&self) -> core::slice::Iter<'_, WasmFieldName> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<WasmFieldName>> for WasmFields {
|
||||
fn from(v: Vec<WasmFieldName>) -> WasmFields {
|
||||
WasmFields(v.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<&str>> for WasmFields {
|
||||
fn from(v: Vec<&str>) -> WasmFields {
|
||||
WasmFields(v.into_iter().map(|v| v.into()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl WasmFields {
|
||||
/// Create an empty entry
|
||||
pub fn empty() -> Self {
|
||||
WasmFields(Vec::with_capacity(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&tracing_core::field::FieldSet> for WasmFields {
|
||||
fn from(wm: &tracing_core::field::FieldSet) -> WasmFields {
|
||||
WasmFields(wm.iter().map(|s| s.name().into()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of `WasmFieldName`s with the given `WasmValue` (if provided)
|
||||
/// in the order specified.
|
||||
#[derive(Encode, Decode, Clone)]
|
||||
pub struct WasmValuesSet(Vec<(WasmFieldName, Option<WasmValue>)>);
|
||||
|
||||
impl core::fmt::Debug for WasmValuesSet {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
let mut wrt = f.debug_struct("");
|
||||
let mut non_str = false;
|
||||
for (f, v) in self.0.iter() {
|
||||
if let Ok(s) = core::str::from_utf8(&f.0) {
|
||||
match v {
|
||||
Some(ref i) => wrt.field(s, i),
|
||||
None => wrt.field(s, &(None as Option<WasmValue>)),
|
||||
};
|
||||
} else {
|
||||
non_str = true;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: replace with using `finish_non_exhaustive()` once stable
|
||||
// https://github.com/rust-lang/rust/issues/67364
|
||||
if non_str {
|
||||
wrt.field("..", &"..");
|
||||
}
|
||||
|
||||
wrt.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<Vec<(WasmFieldName, Option<WasmValue>)>> for WasmValuesSet {
|
||||
fn from(v: Vec<(WasmFieldName, Option<WasmValue>)>) -> Self {
|
||||
WasmValuesSet(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<(&&WasmFieldName, Option<WasmValue>)>> for WasmValuesSet {
|
||||
fn from(v: Vec<(&&WasmFieldName, Option<WasmValue>)>) -> Self {
|
||||
WasmValuesSet(v.into_iter().map(|(k, v)| ((**k).clone(), v)).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<(&&str, Option<WasmValue>)>> for WasmValuesSet {
|
||||
fn from(v: Vec<(&&str, Option<WasmValue>)>) -> Self {
|
||||
WasmValuesSet(v.into_iter().map(|(k, v)| ((*k).into(), v)).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl WasmValuesSet {
|
||||
/// Create an empty entry
|
||||
pub fn empty() -> Self {
|
||||
WasmValuesSet(Vec::with_capacity(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl tracing_core::field::Visit for WasmValuesSet {
|
||||
fn record_debug(&mut self, field: &tracing_core::field::Field, value: &dyn Debug) {
|
||||
self.0.push( (
|
||||
field.name().into(),
|
||||
Some(WasmValue::from(format_args!("{:?}", value)))
|
||||
))
|
||||
}
|
||||
fn record_i64(&mut self, field: &tracing_core::field::Field, value: i64) {
|
||||
self.0.push( (
|
||||
field.name().into(),
|
||||
Some(WasmValue::from(value))
|
||||
))
|
||||
}
|
||||
fn record_u64(&mut self, field: &tracing_core::field::Field, value: u64) {
|
||||
self.0.push( (
|
||||
field.name().into(),
|
||||
Some(WasmValue::from(value))
|
||||
))
|
||||
}
|
||||
fn record_bool(&mut self, field: &tracing_core::field::Field, value: bool) {
|
||||
self.0.push( (
|
||||
field.name().into(),
|
||||
Some(WasmValue::from(value))
|
||||
))
|
||||
}
|
||||
fn record_str(&mut self, field: &tracing_core::field::Field, value: &str) {
|
||||
self.0.push( (
|
||||
field.name().into(),
|
||||
Some(WasmValue::from(value))
|
||||
))
|
||||
}
|
||||
}
|
||||
/// Metadata provides generic information about the specifc location of the
|
||||
/// `span!` or `event!` call on the wasm-side.
|
||||
#[derive(Encode, Decode, Clone)]
|
||||
pub struct WasmMetadata {
|
||||
/// The name given to `event!`/`span!`, `&'static str` converted to bytes
|
||||
pub name: Vec<u8>,
|
||||
/// The given target to `event!`/`span!` – or module-name, `&'static str` converted to bytes
|
||||
pub target: Vec<u8>,
|
||||
/// The level of this entry
|
||||
pub level: WasmLevel,
|
||||
/// The file this was emitted from – useful for debugging; `&'static str` converted to bytes
|
||||
pub file: Vec<u8>,
|
||||
/// The specific line number in the file – useful for debugging
|
||||
pub line: u32,
|
||||
/// The module path; `&'static str` converted to bytes
|
||||
pub module_path: Vec<u8>,
|
||||
/// Whether this is a call to `span!` or `event!`
|
||||
pub is_span: bool,
|
||||
/// The list of fields specified in the call
|
||||
pub fields: WasmFields,
|
||||
}
|
||||
|
||||
impl From<&tracing_core::Metadata<'_>> for WasmMetadata {
|
||||
fn from(wm: &tracing_core::Metadata<'_>) -> WasmMetadata {
|
||||
WasmMetadata {
|
||||
name: wm.name().as_bytes().to_vec(),
|
||||
target: wm.target().as_bytes().to_vec(),
|
||||
level: wm.level().into(),
|
||||
file: wm.file().map(|f| f.as_bytes().to_vec()).unwrap_or_default(),
|
||||
line: wm.line().unwrap_or_default(),
|
||||
module_path: wm.module_path().map(|m| m.as_bytes().to_vec()).unwrap_or_default(),
|
||||
is_span: wm.is_span(),
|
||||
fields: wm.fields().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for WasmMetadata {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("WasmMetadata")
|
||||
.field("name", &decode_field(&self.name))
|
||||
.field("target", &decode_field(&self.target))
|
||||
.field("level", &self.level)
|
||||
.field("file", &decode_field(&self.file))
|
||||
.field("line", &self.line)
|
||||
.field("module_path", &decode_field(&self.module_path))
|
||||
.field("is_span", &self.is_span)
|
||||
.field("fields", &self.fields)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::default::Default for WasmMetadata {
|
||||
fn default() -> Self {
|
||||
let target = "default".as_bytes().to_vec();
|
||||
WasmMetadata {
|
||||
target,
|
||||
name: Default::default(),
|
||||
level: Default::default(),
|
||||
file: Default::default(),
|
||||
line: Default::default(),
|
||||
module_path: Default::default(),
|
||||
is_span: true,
|
||||
fields: WasmFields::empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn decode_field(field: &[u8]) -> &str {
|
||||
core::str::from_utf8(field).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Span or Event Attributes
|
||||
#[derive(Encode, Decode, Clone, Debug)]
|
||||
pub struct WasmEntryAttributes {
|
||||
/// the parent, if directly specified – otherwise assume most inner span
|
||||
pub parent_id: Option<u64>,
|
||||
/// the metadata of the location
|
||||
pub metadata: WasmMetadata,
|
||||
/// the Values provided
|
||||
pub fields: WasmValuesSet,
|
||||
}
|
||||
|
||||
impl From<&tracing_core::Event<'_>> for WasmEntryAttributes {
|
||||
fn from(evt: &tracing_core::Event<'_>) -> WasmEntryAttributes {
|
||||
let mut fields = WasmValuesSet(Vec::new());
|
||||
evt.record(&mut fields);
|
||||
WasmEntryAttributes {
|
||||
parent_id: evt.parent().map(|id| id.into_u64()),
|
||||
metadata: evt.metadata().into(),
|
||||
fields: fields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&tracing_core::span::Attributes<'_>> for WasmEntryAttributes {
|
||||
fn from(attrs: &tracing_core::span::Attributes<'_>) -> WasmEntryAttributes {
|
||||
let mut fields = WasmValuesSet(Vec::new());
|
||||
attrs.record(&mut fields);
|
||||
WasmEntryAttributes {
|
||||
parent_id: attrs.parent().map(|id| id.into_u64()),
|
||||
metadata: attrs.metadata().into(),
|
||||
fields: fields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::default::Default for WasmEntryAttributes {
|
||||
fn default() -> Self {
|
||||
WasmEntryAttributes {
|
||||
parent_id: None,
|
||||
metadata: Default::default(),
|
||||
fields: WasmValuesSet(vec![]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod std_features {
|
||||
|
||||
use tracing_core::callsite;
|
||||
use tracing;
|
||||
|
||||
/// Static entry use for wasm-originated metadata.
|
||||
pub struct WasmCallsite;
|
||||
impl callsite::Callsite for WasmCallsite {
|
||||
fn set_interest(&self, _: tracing_core::Interest) { unimplemented!() }
|
||||
fn metadata(&self) -> &tracing_core::Metadata { unimplemented!() }
|
||||
}
|
||||
static CALLSITE: WasmCallsite = WasmCallsite;
|
||||
/// The identifier we are using to inject the wasm events in the generic `tracing` system
|
||||
pub static WASM_TRACE_IDENTIFIER: &'static str = "wasm_tracing";
|
||||
/// The fieldname for the wasm-originated name
|
||||
pub static WASM_NAME_KEY: &'static str = "name";
|
||||
/// The fieldname for the wasm-originated target
|
||||
pub static WASM_TARGET_KEY: &'static str = "target";
|
||||
/// The the list of all static field names we construct from the given metadata
|
||||
pub static GENERIC_FIELDS: &'static [&'static str] = &[WASM_TARGET_KEY, WASM_NAME_KEY,
|
||||
"file", "line", "module_path", "params"];
|
||||
|
||||
// Implementation Note:
|
||||
// the original `tracing` crate generates these static metadata entries at every `span!` and
|
||||
// `event!` location to allow for highly optimised filtering. For us to allow level-based emitting
|
||||
// of wasm events we need these static metadata entries to inject into that system. We then provide
|
||||
// generic `From`-implementations picking the right metadata to refer to.
|
||||
|
||||
static SPAN_ERROR_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::ERROR, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::SPAN
|
||||
);
|
||||
|
||||
static SPAN_WARN_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::WARN, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::SPAN
|
||||
);
|
||||
static SPAN_INFO_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::INFO, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::SPAN
|
||||
);
|
||||
|
||||
static SPAN_DEBUG_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::DEBUG, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::SPAN
|
||||
);
|
||||
|
||||
static SPAN_TRACE_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::TRACE, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::SPAN
|
||||
);
|
||||
|
||||
static EVENT_ERROR_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::ERROR, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::EVENT
|
||||
);
|
||||
|
||||
static EVENT_WARN_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::WARN, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::EVENT
|
||||
);
|
||||
|
||||
static EVENT_INFO_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::INFO, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::EVENT
|
||||
);
|
||||
|
||||
static EVENT_DEBUG_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::DEBUG, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::EVENT
|
||||
);
|
||||
|
||||
static EVENT_TRACE_METADATA : tracing_core::Metadata<'static> = tracing::Metadata::new(
|
||||
WASM_TRACE_IDENTIFIER, WASM_TRACE_IDENTIFIER, tracing::Level::TRACE, None, None, None,
|
||||
tracing_core::field::FieldSet::new(GENERIC_FIELDS, tracing_core::identify_callsite!(&CALLSITE)),
|
||||
tracing_core::metadata::Kind::EVENT
|
||||
);
|
||||
|
||||
// FIXME: this could be done a lot in 0.2 if they opt for using `Cow<str,'static>` instead
|
||||
// https://github.com/paritytech/substrate/issues/7134
|
||||
impl From<&crate::WasmMetadata> for &'static tracing_core::Metadata<'static> {
|
||||
fn from(wm: &crate::WasmMetadata) -> &'static tracing_core::Metadata<'static> {
|
||||
match (&wm.level, wm.is_span) {
|
||||
(&crate::WasmLevel::ERROR, true) => &SPAN_ERROR_METADATA,
|
||||
(&crate::WasmLevel::WARN, true) => &SPAN_WARN_METADATA,
|
||||
(&crate::WasmLevel::INFO, true) => &SPAN_INFO_METADATA,
|
||||
(&crate::WasmLevel::DEBUG, true) => &SPAN_DEBUG_METADATA,
|
||||
(&crate::WasmLevel::TRACE, true) => &SPAN_TRACE_METADATA,
|
||||
(&crate::WasmLevel::ERROR, false) => &EVENT_ERROR_METADATA,
|
||||
(&crate::WasmLevel::WARN, false) => &EVENT_WARN_METADATA,
|
||||
(&crate::WasmLevel::INFO, false) => &EVENT_INFO_METADATA,
|
||||
(&crate::WasmLevel::DEBUG, false) => &EVENT_DEBUG_METADATA,
|
||||
(&crate::WasmLevel::TRACE, false) => &EVENT_TRACE_METADATA,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::WasmEntryAttributes> for tracing::Span {
|
||||
fn from(a: crate::WasmEntryAttributes) -> tracing::Span {
|
||||
let name = std::str::from_utf8(&a.metadata.name).unwrap_or_default();
|
||||
let target = std::str::from_utf8(&a.metadata.target).unwrap_or_default();
|
||||
let file = std::str::from_utf8(&a.metadata.file).unwrap_or_default();
|
||||
let line = a.metadata.line;
|
||||
let module_path = std::str::from_utf8(&a.metadata.module_path).unwrap_or_default();
|
||||
let params = a.fields;
|
||||
let metadata : &tracing_core::metadata::Metadata<'static> = (&a.metadata).into();
|
||||
|
||||
tracing::span::Span::child_of(
|
||||
a.parent_id.map(|i|tracing_core::span::Id::from_u64(i)),
|
||||
&metadata,
|
||||
&tracing::valueset!{ metadata.fields(), target, name, file, line, module_path, ?params }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::WasmEntryAttributes {
|
||||
/// convert the given Attributes to an event and emit it using `tracing_core`.
|
||||
pub fn emit(self: crate::WasmEntryAttributes) {
|
||||
let name = std::str::from_utf8(&self.metadata.name).unwrap_or_default();
|
||||
let target = std::str::from_utf8(&self.metadata.target).unwrap_or_default();
|
||||
let file = std::str::from_utf8(&self.metadata.file).unwrap_or_default();
|
||||
let line = self.metadata.line;
|
||||
let module_path = std::str::from_utf8(&self.metadata.module_path).unwrap_or_default();
|
||||
let params = self.fields;
|
||||
let metadata : &tracing_core::metadata::Metadata<'static> = (&self.metadata).into();
|
||||
|
||||
tracing_core::Event::child_of(
|
||||
self.parent_id.map(|i|tracing_core::span::Id::from_u64(i)),
|
||||
&metadata,
|
||||
&tracing::valueset!{ metadata.fields(), target, name, file, line, module_path, ?params }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std_features::*;
|
||||
Reference in New Issue
Block a user