trace¶
In [ ]:
//// test
open testing
trace¶
trace_level¶
In [ ]:
union trace_level =
| Verbose
| Debug
| Info
| Warning
| Critical
read_state¶
In [ ]:
inl read_state () =
run_target function
| Rust (Wasm) => fun () =>
{
trace_level = None
repl_start = None
}
| Rust (Contract) => fun () =>
{
trace_level = None
repl_start =
open rust.rust_operators
inl automation = env.get_environment_variable_comptime "AUTOMATION"
if automation <>. "True"
then None
else
inl timestamp : u64 = !\($'$"near_sdk::env::block_timestamp()"')
timestamp |> i64 |> Some
}
| _ => fun () =>
join
{
trace_level =
"TRACE_LEVEL"
|> env.get_environment_variable
|> reflection.union_try_pick
repl_start =
inl automation = env.get_environment_variable "AUTOMATION"
if automation <>. "True"
then None
else
date_time.now ()
|> date_time.ticks
|> fun (date_time.timestamp x) => x |> convert
|> Some
}
trace_state¶
In [ ]:
type trace_state =
{
count : mut i64
trace_file : mut (string -> ())
enabled : mut bool
acc : mut string
level : mut trace_level
repl_start : optionm'.option' i64
}
new_trace_state¶
In [ ]:
let new_trace_state trace_level' =
inl { repl_start trace_level } = read_state ()
{
count = mut 1i64
trace_file = mut ignore
enabled = mut true
acc = mut ""
level = trace_level |> optionm'.default_value trace_level' |> mut
repl_start = repl_start |> optionm'.box
} : trace_state
init_trace_state¶
In [ ]:
inl init_trace_state trace_level : () =
inl trace_level = trace_level |> optionm'.default_value Verbose
backend_switch {
Fsharp = fun () =>
backend_switch {
Fsharp = fun () =>
global "module TraceState = let mutable trace_state = None"
}
fun () =>
if $'TraceState.trace_state.IsNone' then
inl trace_state = new_trace_state trace_level |> optionm'.some'
$'TraceState.trace_state <- !trace_state ' : ()
|> exec_unit
Python = fun () =>
global "class TraceState: trace_state = None"
$'if TraceState.trace_state is None: TraceState.trace_state = !new_trace_state(!trace_level)' : ()
}
get_trace_state_or_init¶
In [ ]:
inl get_trace_state_or_init trace_level : trace_state =
init_trace_state trace_level
backend_switch {
Fsharp = fun () =>
$'TraceState.trace_state.Value' : trace_state
Python = fun () =>
$'TraceState.trace_state' : trace_state
}
test_trace_level¶
In [ ]:
let test_trace_level level : bool =
inl state = get_trace_state_or_init None
inl level' = *state.level
if *state.enabled |> not
then false
else
inl level : i32 = real real_core.union_tag level
inl level' : i32 = real real_core.union_tag level'
level >= level'
In [ ]:
//// test
///! fsharp
///! cuda
///! rust
///! typescript
///! python
test_trace_level Critical |> _assert_eq true
test_trace_level Verbose |> _assert_eq true
inl level = get_trace_state_or_init None .level
level <- Debug
test_trace_level Verbose |> _assert_eq false
level <- Verbose
test_trace_level Verbose |> _assert_eq true
.py output (Cuda): __assert_eq / actual: True / expected: True __assert_eq / actual: True / expected: True __assert_eq / actual: False / expected: False __assert_eq / actual: True / expected: True .rs output: __assert_eq / actual: true / expected: true __assert_eq / actual: true / expected: true __assert_eq / actual: false / expected: false __assert_eq / actual: true / expected: true .ts output: __assert_eq / actual: true / expected: true __assert_eq / actual: true / expected: true __assert_eq / actual: false / expected: false __assert_eq / actual: true / expected: true .py output: __assert_eq / actual: true / expected: true __assert_eq / actual: true / expected: true __assert_eq / actual: false / expected: false __assert_eq / actual: true / expected: true
.fsx output: __assert_eq / actual: true / expected: true __assert_eq / actual: true / expected: true __assert_eq / actual: false / expected: false __assert_eq / actual: true / expected: true
trace_raw¶
In [ ]:
inl trace_raw level fn =
fun () =>
if level |> test_trace_level then
inl text = fn ()
join
inl ({ count acc } & trace_state) = get_trace_state_or_init None
fun () =>
count <- *count + 1
|> exec_unit
open rust
open rust.rust_operators
run_target_args (fun () => text, console.write_line) function
| Rust (Contract) => fun text, _ =>
inl new_acc =
if *acc = ""
then text
elif text = ""
then *acc
else *acc +. "\n" +. text
inl chunks =
new_acc
|> sm'.as_str
|> sm'.chars
|> rust.from_mut
|> iter_collect
|> am'.vec_chunks 15000
|> am'.vec_map sm'.from_iter
inl chunks_len = chunks |> am'.vec_len |> i32
if text <>. "" && chunks_len <= 1
then acc <- new_acc
else
acc <- ""
chunks
|> am'.vec_for_each''' near.log
| Rust _ => fun text, _ =>
!\\(text, $'\@"println\!(""{}"", $0)"')
| _ => fun text, write_line =>
text |> write_line
text |> *trace_state.trace_file
|> exec_unit
trace¶
In [ ]:
inl trace (level : trace_level) (text_fn : () -> string) (locals : () -> _) =
fun () =>
inl trace_state = get_trace_state_or_init None
inl time =
join
run_target fun target =>
match target with
| Rust (Contract) => fun () =>
open rust.rust_operators
open rust
inl timestamp = near.block_timestamp ()
inl timestamp =
match trace_state.repl_start |> optionm'.unbox with
| Some repl_start => timestamp - u64 repl_start
| None => timestamp
inl timestamp_s = timestamp / 1_000_000_000
inl s = timestamp_s % 60
inl m = (timestamp_s / 60) % 60
inl h = (timestamp_s / 3600) % 24
inl str : sm'.std_string =
!\\((h, m, s), $'$"format\!(\\\"{{:02}}:{{:02}}:{{:02}}\\\", $0, $1, $2)"')
str |> sm'.from_std_string
| _ => fun () =>
match trace_state.repl_start |> optionm'.unbox with
| Some repl_start =>
inl t =
date_time.now ()
|> date_time.ticks
|> fun (date_time.timestamp x) => x |> convert
|> flip (-) repl_start
|> date_time.time_span
date_time.date_time_milliseconds
1i32 1i32 1i32
(t |> date_time.hours)
(t |> date_time.minutes)
(t |> date_time.seconds)
(t |> date_time.milliseconds)
| None => date_time.now ()
|> date_time.format (
backend_switch {
Fsharp = fun () =>
match target with
| Rust _ => join "hh:mm:ss"
| _ => join "HH:mm:ss"
Python = fun () => "%H:%M:%S"
}
)
inl level_str =
join
inl level_str =
level
|> reflection.union_to_string
|> sm'.to_lower
|> sm'.index 0i32
|> sm'.format
run_target function
| Rust _ => fun () =>
open rust
open rust.rust_operators
inl color : rust.ref sm'.str =
match level with
| Verbose => !\($'"inline_colorization::color_bright_black"')
| Debug => !\($'"inline_colorization::color_bright_blue"')
| Info => !\($'"inline_colorization::color_bright_green"')
| Warning => !\($'"inline_colorization::color_yellow"')
| Critical => !\($'"inline_colorization::color_bright_red"')
inl level_str = level_str |> sm'.as_str
inl color_reset : rust.ref sm'.str = !\($'"inline_colorization::color_reset"')
!\\((color, level_str, color_reset), $'$"format\!(\\\"{{}}{{}}{{}}\\\", $0, $1, $2)"')
|> sm'.from_std_string
| _ => fun () =>
inl color =
match level with
| Verbose => $'"\\u001b[90m"'
| Debug => $'"\\u001b[94m"'
| Info => $'"\\u001b[92m"'
| Warning => $'"\\u001b[93m"'
| Critical => $'"\\u001b[91m"'
inl color_reset = join $'"\\u001b[0m"'
color +. level_str +. color_reset
inl text = text_fn ()
if text = ""
then ""
else
inl locals = locals ()
join
inl locals = locals |> sm'.format
inl count = *trace_state.count
backend_switch {
Fsharp = fun () => $'$"{!time} {!level_str} #{!count} %s{!text} / {!locals}"' : string
Python = fun () => $'f"{!time} {!level_str} #{!count} {!text} / {!locals}"' : string
}
|> fun x =>
join
x
|> sm'.trim_start []
|> sm'.trim_end [ ' '; '/' ]
|> trace_raw level
In [ ]:
//// test
///! fsharp
///! cuda
///! rust
///! typescript
///! python
trace Debug (fun () => "test1") id
trace Debug (fun () => "test2") id
get_trace_state_or_init None .count
|> fun x => *x
|> _assert_eq 3
.py output (Cuda): 00:00:00 d #1 test1 00:00:00 d #2 test2 __assert_eq / actual: 3 / expected: 3 .rs output: 00:00:00 d #1 test1 00:00:00 d #2 test2 __assert_eq / actual: 3 / expected: 3 .ts output: 00:00:00 d #1 test1 00:00:00 d #2 test2 __assert_eq / actual: 3 / expected: 3 .py output: 00:00:00 d #1 test1 00:00:00 d #2 test2 __assert_eq / actual: 3 / expected: 3
.fsx output: 00:00:00 d #1 test1 00:00:00 d #2 test2 __assert_eq / actual: 3L / expected: 3L
main¶
In [ ]:
inl main () =
init_trace_state None
inl trace level text_fn (locals : () -> string) = trace level text_fn locals
$'let trace x = !trace x' : ()