feat: Rebrand Polkadot/Substrate references to PezkuwiChain

This commit systematically rebrands various references from Parity Technologies'
Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk.

Key changes include:
- Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks.
- Modified internal documentation and code comments to reflect PezkuwiChain naming and structure.
- Replaced direct references to  with  or specific paths within the  for XCM, Pezkuwi, and other modules.
- Cleaned up deprecated  issue and PR references in various  and  files, particularly in  and  modules.
- Adjusted image and logo URLs in documentation to point to PezkuwiChain assets.
- Removed or rephrased comments related to external Polkadot/Substrate PRs and issues.

This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
+44
View File
@@ -0,0 +1,44 @@
[package]
name = "pezsp-tracing"
version = "16.0.0"
license = "Apache-2.0"
authors.workspace = true
edition.workspace = true
homepage.workspace = true
repository.workspace = true
description = "Instrumentation primitives and macros for Bizinikiwi."
readme = "README.md"
[lints]
workspace = true
[package.metadata.docs.rs]
# let's default to wasm32
default-target = "wasm32-unknown-unknown"
# with the tracing enabled
features = ["with-tracing"]
# allowing for linux-gnu here, too, allows for `std` to show up as well
targets = ["wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"]
[dependencies]
codec = { features = ["derive"], workspace = true }
regex = { workspace = true, optional = true }
tracing = { workspace = true }
tracing-core = { workspace = true }
tracing-subscriber = { workspace = true, optional = true, features = [
"env-filter",
"time",
"tracing-log",
] }
[features]
default = ["std"]
with-tracing = ["codec/derive", "codec/full"]
std = [
"codec/std",
"regex",
"tracing-core/std",
"tracing-subscriber",
"tracing/std",
"with-tracing",
]
+15
View File
@@ -0,0 +1,15 @@
Bizinikiwi tracing primitives and macros.
To trace functions or individual code in Bizinikiwi, 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
2 reserved identifiers for tracing `Field` recording, stored in the consts:
`WASM_TARGET_KEY` and `WASM_NAME_KEY` - if you choose to record fields, you
must ensure that your identifiers do not clash with either of these.
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.
License: Apache-2.0
+508
View File
@@ -0,0 +1,508 @@
// This file is part of Bizinikiwi.
// Copyright (C) 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.
//! Bizinikiwi tracing primitives and macros.
//!
//! To trace functions or individual code in Bizinikiwi, 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
//! 2 reserved identifiers for tracing `Field` recording, stored in the consts:
//! `WASM_TARGET_KEY` and `WASM_NAME_KEY` - if you choose to record fields, you
//! must ensure that your identifiers do not clash with either of these.
//!
//! 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.
//!
//! Note: The `tracing` crate requires trace metadata to be static. This does not work
//! for wasm code in bizinikiwi, as it is regularly updated with new code from on-chain
//! events. The workaround for this is for the wasm tracing wrappers to put the
//! `name` and `target` data in the `values` map (normally they would be in the static
//! metadata assembled at compile time).
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[cfg(feature = "std")]
pub use tracing;
pub use tracing::{
debug, debug_span, error, error_span, event, info, info_span, span, trace, trace_span, warn,
warn_span, Level, Span,
};
#[cfg(feature = "std")]
pub use tracing_subscriber;
pub use crate::types::{
WasmEntryAttributes, WasmFieldName, WasmFields, WasmLevel, WasmMetadata, WasmValue,
WasmValuesSet,
};
#[cfg(not(bizinikiwi_runtime))]
pub use crate::types::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER};
/// 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 that 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
/// convenience you directly specify the `Level` and name of the span or use the full
/// feature set of `span!`/`span_*!` on it:
///
/// # Example
///
/// ```rust
/// pezsp_tracing::enter_span!(pezsp_tracing::Level::TRACE, "fn wide span");
/// {
/// pezsp_tracing::enter_span!(pezsp_tracing::trace_span!("outer-span"));
/// {
/// pezsp_tracing::enter_span!(pezsp_tracing::Level::TRACE, "inner-span");
/// // ..
/// } // inner span exists here
/// } // outer span exists here
///
/// pezsp_tracing::within_span! {
/// pezsp_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`-facilities, 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;
/// Try to init a simple tracing subscriber with log compatibility layer.
///
/// Ignores any error. Useful for testing. Uses the default filter for logs.
///
/// Related functions:
/// - [`init_for_tests()`]: Enables `TRACE` level.
/// - [`test_log_capture::init_log_capture()`]: Captures logs for assertions and/or outputs logs.
/// - [`capture_test_logs!()`]: A macro for capturing logs within test blocks.
#[cfg(feature = "std")]
pub fn try_init_simple() {
let _ = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.with_writer(std::io::stderr)
.try_init();
}
/// Init a tracing subscriber for logging in tests.
///
/// Be aware that this enables `TRACE` by default. It also ignores any error
/// while setting up the logger.
///
/// The logs are not shown by default, logs are only shown when the test fails
/// or if [`nocapture`](https://doc.rust-lang.org/cargo/commands/cargo-test.html#display-options)
/// is being used.
///
/// Related functions:
/// - [`try_init_simple()`]: Uses the default filter.
/// - [`test_log_capture::init_log_capture()`]: Captures logs for assertions and/or outputs logs.
/// - [`capture_test_logs!()`]: A macro for capturing logs within test blocks.
#[cfg(feature = "std")]
pub fn init_for_tests() {
let _ = tracing_subscriber::fmt()
.with_max_level(tracing::Level::TRACE)
.with_test_writer()
.try_init();
}
/// Runs given code within a tracing span, measuring it's execution time.
///
/// If tracing is not enabled, the code is still executed. Pass in level and name or
/// use any valid `pezsp_tracing::Span`followed by `;` and the code to execute,
///
/// # Example
///
/// ```
/// pezsp_tracing::within_span! {
/// pezsp_tracing::Level::TRACE,
/// "test-span";
/// 1 + 1;
/// // some other complex code
/// }
///
/// pezsp_tracing::within_span! {
/// pezsp_tracing::span!(pezsp_tracing::Level::WARN, "warn-span", you_can_pass="any params");
/// 1 + 1;
/// // some other complex code
/// }
///
/// pezsp_tracing::within_span! {
/// pezsp_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! within_span {
(
$span:expr;
$( $code:tt )*
) => {
$span.in_scope(||
{
$( $code )*
}
)
};
(
$lvl:expr,
$name:expr;
$( $code:tt )*
) => {
{
$crate::within_span!($crate::span!($lvl, $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. Use either level and name
/// or pass in any valid `pezsp_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
///
/// ```
/// pezsp_tracing::enter_span!(pezsp_tracing::Level::TRACE, "test-span");
/// // previous will be dropped here
/// pezsp_tracing::enter_span!(
/// pezsp_tracing::span!(pezsp_tracing::Level::DEBUG, "debug-span", params="value"));
/// pezsp_tracing::enter_span!(pezsp_tracing::info_span!("info-span", params="value"));
///
/// {
/// pezsp_tracing::enter_span!(pezsp_tracing::Level::TRACE, "outer-span");
/// {
/// pezsp_tracing::enter_span!(pezsp_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 {
( $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!($lvl, $name))
};
}
#[cfg(feature = "std")]
pub mod test_log_capture {
use std::{
io::Write,
sync::{Arc, Mutex},
};
use tracing::level_filters::LevelFilter;
use tracing_subscriber::{fmt, fmt::MakeWriter, layer::SubscriberExt, Layer, Registry};
/// A reusable log capturing struct for unit tests.
/// Captures logs written during test execution for assertions.
///
/// # Examples
/// ```
/// use pezsp_tracing::test_log_capture::LogCapture;
/// use std::io::Write;
///
/// let mut log_capture = LogCapture::new();
/// writeln!(log_capture, "Test log message").unwrap();
/// assert!(log_capture.contains("Test log message"));
/// ```
pub struct LogCapture {
buffer: Arc<Mutex<Vec<u8>>>,
}
impl LogCapture {
/// Creates a new `LogCapture` instance with an internal buffer.
///
/// # Examples
/// ```
/// use pezsp_tracing::test_log_capture::LogCapture;
///
/// let log_capture = LogCapture::new();
/// assert!(log_capture.get_logs().is_empty());
/// ```
pub fn new() -> Self {
LogCapture { buffer: Arc::new(Mutex::new(Vec::new())) }
}
/// Checks if the captured logs contain a specific substring.
///
/// # Examples
/// ```
/// use pezsp_tracing::test_log_capture::LogCapture;
/// use std::io::Write;
///
/// let mut log_capture = LogCapture::new();
/// writeln!(log_capture, "Hello, world!").unwrap();
/// assert!(log_capture.contains("Hello"));
/// assert!(!log_capture.contains("Goodbye"));
/// ```
pub fn contains(&self, expected: &str) -> bool {
let logs = self.get_logs();
logs.contains(expected)
}
/// Retrieves the captured logs as a `String`.
///
/// # Examples
/// ```
/// use pezsp_tracing::test_log_capture::LogCapture;
/// use std::io::Write;
///
/// let mut log_capture = LogCapture::new();
/// writeln!(log_capture, "Log entry").unwrap();
/// assert_eq!(log_capture.get_logs().trim(), "Log entry");
/// ```
pub fn get_logs(&self) -> String {
let raw_logs = String::from_utf8(self.buffer.lock().unwrap().clone()).unwrap();
let ansi_escape = regex::Regex::new(r"\x1B\[[0-9;]*[mK]").unwrap(); // Regex to match ANSI codes
ansi_escape.replace_all(&raw_logs, "").to_string() // Remove ANSI codes
}
/// Returns a clone of the internal buffer for use in `MakeWriter`.
pub fn writer(&self) -> Self {
LogCapture { buffer: Arc::clone(&self.buffer) }
}
}
impl Write for LogCapture {
/// Writes log data into the internal buffer.
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut logs = self.buffer.lock().unwrap();
logs.extend_from_slice(buf);
Ok(buf.len())
}
/// Flushes the internal buffer (no-op in this implementation).
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl<'a> MakeWriter<'a> for LogCapture {
type Writer = Self;
/// Provides a `MakeWriter` implementation for `tracing_subscriber`.
fn make_writer(&'a self) -> Self::Writer {
self.writer()
}
}
/// Initialises a log capture utility for testing, with optional log printing.
///
/// This function sets up a `LogCapture` instance to capture logs during test execution.
/// It also configures a `tracing_subscriber` with the specified maximum log level
/// and a writer that directs logs to `LogCapture`. If `print_logs` is enabled, logs
/// up to `max_level` are also printed to the test output.
///
/// # Arguments
///
/// * `max_level` - The maximum log level to capture and print, which can be converted into
/// `LevelFilter`.
/// * `print_logs` - If `true`, logs up to `max_level` will also be printed to the test output.
///
/// # Returns
///
/// A tuple containing:
/// - `LogCapture`: The log capture instance.
/// - `Subscriber`: A configured `tracing_subscriber` that captures logs.
///
/// # Examples
///
/// ```
/// use pezsp_tracing::{
/// test_log_capture::init_log_capture,
/// tracing::{info, subscriber, Level},
/// };
///
/// let (log_capture, subscriber) = init_log_capture(Level::INFO, false);
/// subscriber::with_default(subscriber, || {
/// info!("This log will be captured");
/// assert!(log_capture.contains("This log will be captured"));
/// });
/// ```
///
/// # Usage Guide
///
/// - If you only need to **capture logs for assertions** without printing them, use
/// `init_log_capture(max_level, false)`.
/// - If you need both **capturing and printing logs**, use `init_log_capture(max_level, true)`.
/// - If you only need to **print logs** but not capture them, use
/// `pezsp_tracing::init_for_tests()`.
pub fn init_log_capture(
max_level: impl Into<LevelFilter>,
print_logs: bool,
) -> (LogCapture, impl tracing::Subscriber + Send + Sync) {
// Create a new log capture instance
let log_capture = LogCapture::new();
// Convert the max log level into LevelFilter
let level_filter = max_level.into();
// Create a layer for capturing logs into LogCapture
let capture_layer = fmt::layer()
.with_writer(log_capture.writer()) // Use LogCapture as the writer
.with_filter(level_filter); // Set the max log level
// Base subscriber with log capturing
let subscriber = Registry::default().with(capture_layer);
// If `print_logs` is enabled, add a layer that prints logs to test output up to `max_level`
let test_layer = if print_logs {
Some(
fmt::layer()
.with_test_writer() // Direct logs to test output
.with_filter(level_filter), // Apply the same max log level filter
)
} else {
None
};
// Combine the log capture subscriber with the test layer (if applicable)
let combined_subscriber = subscriber.with(test_layer);
(log_capture, combined_subscriber)
}
/// Macro for capturing logs during test execution.
///
/// This macro sets up a log subscriber with a specified maximum log level
/// and an option to print logs to the test output while capturing them.
///
/// # Arguments
///
/// - `$max_level`: The maximum log level to capture.
/// - `$print_logs`: Whether to also print logs to the test output.
/// - `$test`: The block of code where logs are captured.
///
/// # Examples
///
/// ```
/// use pezsp_tracing::{
/// capture_test_logs,
/// tracing::{info, warn, Level},
/// };
///
/// // Capture logs at WARN level without printing them
/// let log_capture = capture_test_logs!(Level::WARN, false, {
/// info!("Captured info message");
/// warn!("Captured warning");
/// });
///
/// assert!(!log_capture.contains("Captured info message"));
/// assert!(log_capture.contains("Captured warning"));
///
/// // Capture logs at TRACE level and also print them
/// let log_capture = capture_test_logs!(Level::TRACE, true, {
/// info!("This will be captured and printed");
/// });
///
/// assert!(log_capture.contains("This will be captured and printed"));
/// ```
///
/// # Related functions:
/// - [`init_log_capture()`]: Captures logs for assertions.
/// - `pezsp_tracing::init_for_tests()`: Outputs logs but does not capture them.
#[macro_export]
macro_rules! capture_test_logs {
// Case when max_level and print_logs are provided
($max_level:expr, $print_logs:expr, $test:block) => {{
let (log_capture, subscriber) =
pezsp_tracing::test_log_capture::init_log_capture($max_level, $print_logs);
pezsp_tracing::tracing::subscriber::with_default(subscriber, || $test);
log_capture
}};
// Case when only max_level is provided (defaults to not printing logs)
($max_level:expr, $test:block) => {{
capture_test_logs!($max_level, false, $test)
}};
// Case when max_level is omitted (defaults to DEBUG, no printing)
($test:block) => {{
capture_test_logs!(pezsp_tracing::tracing::Level::DEBUG, false, $test)
}};
}
}
+669
View File
@@ -0,0 +1,669 @@
// This file is part of Bizinikiwi.
// Copyright (C) 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.
use alloc::{vec, vec::Vec};
use codec::{Decode, Encode};
/// Types for wasm based tracing. Loosely inspired by `tracing-core` but
/// optimised for the specific use case.
use core::{fmt::Debug, format_args};
/// 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 parameter 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)
}
}
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 = alloc::string::String::default();
core::fmt::write(&mut buf, inp).expect("Writing of arguments doesn't fail");
WasmValue::Formatted(buf.into_bytes())
}
}
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 constructing an
/// `event!` or `span!`.
/// Generally generated automatically 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)
}
}
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 specific 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,
}
}
}
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,
}
}
}
impl core::default::Default for WasmEntryAttributes {
fn default() -> Self {
WasmEntryAttributes {
parent_id: None,
metadata: Default::default(),
fields: WasmValuesSet(vec![]),
}
}
}
#[cfg(not(bizinikiwi_runtime))]
mod std_features {
use tracing_core::callsite;
/// 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: &str = "wasm_tracing";
/// The fieldname for the wasm-originated name
pub static WASM_NAME_KEY: &str = "name";
/// The fieldname for the wasm-originated target
pub static WASM_TARGET_KEY: &str = "target";
/// The the list of all static field names we construct from the given metadata
pub static GENERIC_FIELDS: &[&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/pezkuwichain/kurdistan-sdk/issues/29
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 = core::str::from_utf8(&a.metadata.name).unwrap_or_default();
let target = core::str::from_utf8(&a.metadata.target).unwrap_or_default();
let file = core::str::from_utf8(&a.metadata.file).unwrap_or_default();
let line = a.metadata.line;
let module_path = core::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(tracing_core::span::Id::from_u64),
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 = core::str::from_utf8(&self.metadata.name).unwrap_or_default();
let target = core::str::from_utf8(&self.metadata.target).unwrap_or_default();
let file = core::str::from_utf8(&self.metadata.file).unwrap_or_default();
let line = self.metadata.line;
let module_path = core::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(tracing_core::span::Id::from_u64),
metadata,
&tracing::valueset! { metadata.fields(), target, name, file, line, module_path, ?params },
)
}
}
}
#[cfg(not(bizinikiwi_runtime))]
pub use std_features::*;