Packages
Tensor library for Gleam/BEAM with a pure Gleam API, zero-copy views, and optional native acceleration
Retired package: Release invalid
Current section
Files
Jump to
Current section
Files
src/viva_tensor@telemetry.erl
-module(viva_tensor@telemetry).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/viva_tensor/telemetry.gleam").
-export([default_config/0, init/0, init_with_json/1, init_with_config/1, op_counter/1, matmul_histogram/0, op_histogram/0, backward_histogram/0, backend_counter/1, memory_gauge/0, quant_counter/1, log_backend/2, log_backward/2, log_error/2, record_op/2, record_dot/3, record_backward/2, report_memory/0, prometheus/0, benchmark/2, benchmark_with_config/4, benchmark_all/1, benchmark_compare/2, benchmark_print/1, benchmark_print_comparison/1, benchmark_to_markdown/1, benchmark_table/1, log_op/2, log_matmul/5, log_quantize/2, record_matmul/5, record_quantize/2]).
-export_type([config/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Observability for viva_tensor.\n"
"\n"
" Structured logging, metrics collection, and statistical benchmarking\n"
" powered by viva_telemetry. Gives you full visibility into tensor\n"
" operations, backend selection, memory usage, and gradient computation.\n"
"\n"
" ## Quick Start\n"
"\n"
" ```gleam\n"
" import viva_tensor/telemetry\n"
"\n"
" // Console logging at Info level + all metrics\n"
" telemetry.init()\n"
"\n"
" // With JSON file output for production\n"
" telemetry.init_with_json(\"logs/viva_tensor.json\")\n"
"\n"
" // Full custom config\n"
" telemetry.init_with_config(telemetry.Config(\n"
" log_level: level.Debug,\n"
" json_path: option.Some(\"logs/tensor.json\"),\n"
" ))\n"
" ```\n"
"\n"
" ## Prometheus Metrics\n"
"\n"
" ```gleam\n"
" let metrics_text = telemetry.prometheus()\n"
" // Returns all metrics in Prometheus exposition format\n"
" ```\n"
"\n"
" ## Benchmarking\n"
"\n"
" ```gleam\n"
" let result = telemetry.benchmark(\"matmul_100x100\", fn() {\n"
" ops.matmul_auto(a, b)\n"
" })\n"
" telemetry.benchmark_print(result)\n"
" ```\n"
).
-type config() :: {config,
viva_telemetry@log@level:level(),
gleam@option:option(binary())}.
-file("src/viva_tensor/telemetry.gleam", 62).
?DOC(" Default configuration: Info level, console only.\n").
-spec default_config() -> config().
default_config() ->
{config, info, none}.
-file("src/viva_tensor/telemetry.gleam", 70).
?DOC(
" Initialize telemetry with sensible defaults.\n"
" Console logging at Info level, all metrics enabled.\n"
).
-spec init() -> nil.
init() ->
viva_telemetry@log:configure_console(info),
nil.
-file("src/viva_tensor/telemetry.gleam", 77).
?DOC(
" Initialize with console + JSON file logging.\n"
" JSON file gets all levels for post-mortem analysis.\n"
).
-spec init_with_json(binary()) -> nil.
init_with_json(Path) ->
viva_telemetry@log:configure_full(info, Path, debug),
nil.
-file("src/viva_tensor/telemetry.gleam", 83).
?DOC(" Initialize with full custom configuration.\n").
-spec init_with_config(config()) -> nil.
init_with_config(Config) ->
case erlang:element(3, Config) of
{some, Path} ->
viva_telemetry@log:configure_full(
erlang:element(2, Config),
Path,
erlang:element(2, Config)
);
none ->
viva_telemetry@log:configure_console(erlang:element(2, Config))
end,
nil.
-file("src/viva_tensor/telemetry.gleam", 96).
?DOC(" Counter for tensor operations by name.\n").
-spec op_counter(binary()) -> viva_telemetry@metrics:counter().
op_counter(Op) ->
viva_telemetry@metrics:counter_with_labels(
<<"vt_ops_total"/utf8>>,
[{<<"op"/utf8>>, Op}]
).
-file("src/viva_tensor/telemetry.gleam", 101).
?DOC(" Histogram for matmul latency in microseconds.\n").
-spec matmul_histogram() -> viva_telemetry@metrics:histogram().
matmul_histogram() ->
viva_telemetry@metrics:histogram(
<<"vt_matmul_duration_us"/utf8>>,
[10.0, 50.0, 100.0, 500.0, 1000.0, 5000.0, 10000.0, 50000.0, 100000.0]
).
-file("src/viva_tensor/telemetry.gleam", 108).
?DOC(" Histogram for general operation latency in microseconds.\n").
-spec op_histogram() -> viva_telemetry@metrics:histogram().
op_histogram() ->
viva_telemetry@metrics:histogram(
<<"vt_op_duration_us"/utf8>>,
[1.0, 5.0, 10.0, 50.0, 100.0, 500.0, 1000.0, 5000.0, 10000.0]
).
-file("src/viva_tensor/telemetry.gleam", 115).
?DOC(" Histogram for backward pass latency in microseconds.\n").
-spec backward_histogram() -> viva_telemetry@metrics:histogram().
backward_histogram() ->
viva_telemetry@metrics:histogram(
<<"vt_backward_duration_us"/utf8>>,
[100.0, 500.0, 1000.0, 5000.0, 10000.0, 50000.0, 100000.0]
).
-file("src/viva_tensor/telemetry.gleam", 122).
?DOC(" Counter for backend selections (accelerate, zig, erlang).\n").
-spec backend_counter(binary()) -> viva_telemetry@metrics:counter().
backend_counter(Backend) ->
viva_telemetry@metrics:counter_with_labels(
<<"vt_backend_total"/utf8>>,
[{<<"backend"/utf8>>, Backend}]
).
-file("src/viva_tensor/telemetry.gleam", 127).
?DOC(" Gauge for BEAM process memory in bytes.\n").
-spec memory_gauge() -> viva_telemetry@metrics:gauge().
memory_gauge() ->
viva_telemetry@metrics:gauge(<<"vt_memory_bytes"/utf8>>).
-file("src/viva_tensor/telemetry.gleam", 132).
?DOC(" Counter for quantization operations by format.\n").
-spec quant_counter(binary()) -> viva_telemetry@metrics:counter().
quant_counter(Format) ->
viva_telemetry@metrics:counter_with_labels(
<<"vt_quant_ops_total"/utf8>>,
[{<<"format"/utf8>>, Format}]
).
-file("src/viva_tensor/telemetry.gleam", 175).
?DOC(" Log backend selection at debug level.\n").
-spec log_backend(binary(), binary()) -> nil.
log_backend(Backend, Op) ->
viva_telemetry@log:debug(
<<"backend selected"/utf8>>,
[{<<"backend"/utf8>>, Backend}, {<<"op"/utf8>>, Op}]
).
-file("src/viva_tensor/telemetry.gleam", 180).
?DOC(" Log backward pass completion.\n").
-spec log_backward(integer(), integer()) -> nil.
log_backward(Num_nodes, Duration_us) ->
viva_telemetry@log:info(
<<"backward"/utf8>>,
[{<<"nodes"/utf8>>, erlang:integer_to_binary(Num_nodes)},
{<<"duration_us"/utf8>>, erlang:integer_to_binary(Duration_us)}]
).
-file("src/viva_tensor/telemetry.gleam", 196).
?DOC(" Log a tensor error.\n").
-spec log_error(binary(), binary()) -> nil.
log_error(Op, Reason) ->
viva_telemetry@log:error(
<<"tensor error"/utf8>>,
[{<<"op"/utf8>>, Op}, {<<"reason"/utf8>>, Reason}]
).
-file("src/viva_tensor/telemetry.gleam", 203).
?DOC(" Record a generic tensor operation with timing.\n").
-spec record_op(binary(), integer()) -> nil.
record_op(Op, Duration_us) ->
viva_telemetry@metrics:inc(op_counter(Op)),
viva_telemetry@metrics:observe(op_histogram(), erlang:float(Duration_us)).
-file("src/viva_tensor/telemetry.gleam", 223).
?DOC(" Record a dot product operation.\n").
-spec record_dot(integer(), integer(), binary()) -> nil.
record_dot(Size, Duration_us, Backend) ->
viva_telemetry@metrics:inc(op_counter(<<"dot"/utf8>>)),
viva_telemetry@metrics:observe(op_histogram(), erlang:float(Duration_us)),
viva_telemetry@metrics:inc(backend_counter(Backend)),
viva_telemetry@log:debug(
<<"dot"/utf8>>,
[{<<"size"/utf8>>, erlang:integer_to_binary(Size)},
{<<"backend"/utf8>>, Backend},
{<<"duration_us"/utf8>>, erlang:integer_to_binary(Duration_us)}]
).
-file("src/viva_tensor/telemetry.gleam", 235).
?DOC(" Record a backward pass.\n").
-spec record_backward(integer(), integer()) -> nil.
record_backward(Num_nodes, Duration_us) ->
viva_telemetry@metrics:observe(
backward_histogram(),
erlang:float(Duration_us)
),
log_backward(Num_nodes, Duration_us).
-file("src/viva_tensor/telemetry.gleam", 249).
?DOC(" Report BEAM memory usage. Logs and records gauge.\n").
-spec report_memory() -> viva_telemetry@metrics:beam_memory().
report_memory() ->
Mem = viva_telemetry@metrics:beam_memory(),
viva_telemetry@metrics:set(
memory_gauge(),
erlang:float(erlang:element(2, Mem))
),
viva_telemetry@log:info(
<<"beam memory"/utf8>>,
[{<<"total_mb"/utf8>>,
erlang:integer_to_binary(erlang:element(2, Mem) div 1048576)},
{<<"processes_mb"/utf8>>,
erlang:integer_to_binary(erlang:element(3, Mem) div 1048576)},
{<<"binary_mb"/utf8>>,
erlang:integer_to_binary(erlang:element(8, Mem) div 1048576)},
{<<"ets_mb"/utf8>>,
erlang:integer_to_binary(erlang:element(10, Mem) div 1048576)}]
),
Mem.
-file("src/viva_tensor/telemetry.gleam", 264).
?DOC(" Export all collected metrics in Prometheus text format.\n").
-spec prometheus() -> binary().
prometheus() ->
viva_telemetry@metrics:to_prometheus().
-file("src/viva_tensor/telemetry.gleam", 272).
?DOC(" Run a benchmark with default config (100 warmup, 1000 iterations).\n").
-spec benchmark(binary(), fun(() -> any())) -> viva_telemetry@bench:bench_result().
benchmark(Name, F) ->
viva_telemetry@bench:run(Name, F).
-file("src/viva_tensor/telemetry.gleam", 277).
?DOC(" Run a benchmark with custom iterations.\n").
-spec benchmark_with_config(binary(), fun(() -> any()), integer(), integer()) -> viva_telemetry@bench:bench_result().
benchmark_with_config(Name, F, Warmup, Iterations) ->
viva_telemetry@bench:run_with_config(
Name,
F,
viva_telemetry@bench:config(Warmup, Iterations)
).
-file("src/viva_tensor/telemetry.gleam", 287).
?DOC(" Run multiple benchmarks and return all results.\n").
-spec benchmark_all(list({binary(), fun(() -> any())})) -> list(viva_telemetry@bench:bench_result()).
benchmark_all(Benchmarks) ->
viva_telemetry@bench:run_all(
Benchmarks,
viva_telemetry@bench:default_config()
).
-file("src/viva_tensor/telemetry.gleam", 294).
?DOC(" Compare two benchmark results. Returns speedup and significance.\n").
-spec benchmark_compare(
viva_telemetry@bench:bench_result(),
viva_telemetry@bench:bench_result()
) -> viva_telemetry@bench:comparison().
benchmark_compare(Baseline, Target) ->
viva_telemetry@bench:compare(Baseline, Target).
-file("src/viva_tensor/telemetry.gleam", 302).
?DOC(" Print benchmark result to stdout.\n").
-spec benchmark_print(viva_telemetry@bench:bench_result()) -> nil.
benchmark_print(Result) ->
viva_telemetry@bench:print(Result).
-file("src/viva_tensor/telemetry.gleam", 307).
?DOC(" Print comparison to stdout.\n").
-spec benchmark_print_comparison(viva_telemetry@bench:comparison()) -> nil.
benchmark_print_comparison(Comparison) ->
viva_telemetry@bench:print_comparison(Comparison).
-file("src/viva_tensor/telemetry.gleam", 312).
?DOC(" Convert benchmark result to markdown.\n").
-spec benchmark_to_markdown(viva_telemetry@bench:bench_result()) -> binary().
benchmark_to_markdown(Result) ->
viva_telemetry@bench:to_markdown(Result).
-file("src/viva_tensor/telemetry.gleam", 317).
?DOC(" Convert multiple results to a markdown comparison table.\n").
-spec benchmark_table(list(viva_telemetry@bench:bench_result())) -> binary().
benchmark_table(Results) ->
viva_telemetry@bench:to_markdown_table(Results).
-file("src/viva_tensor/telemetry.gleam", 323).
-spec format_shape(list(integer())) -> binary().
format_shape(Shape) ->
<<<<"["/utf8,
(gleam@string:join(
gleam@list:map(Shape, fun erlang:integer_to_binary/1),
<<", "/utf8>>
))/binary>>/binary,
"]"/utf8>>.
-file("src/viva_tensor/telemetry.gleam", 139).
?DOC(" Log a tensor operation at debug level.\n").
-spec log_op(binary(), list(integer())) -> nil.
log_op(Op, Shape) ->
viva_telemetry@log:debug(
<<"tensor op"/utf8>>,
[{<<"op"/utf8>>, Op}, {<<"shape"/utf8>>, format_shape(Shape)}]
).
-file("src/viva_tensor/telemetry.gleam", 327).
-spec format_float(float()) -> binary().
format_float(F) ->
Rounded = erlang:round(F * 100.0),
gleam_stdlib:float_to_string(erlang:float(Rounded) / 100.0).
-file("src/viva_tensor/telemetry.gleam", 144).
?DOC(" Log matmul execution with performance details.\n").
-spec log_matmul(integer(), integer(), integer(), binary(), integer()) -> nil.
log_matmul(M, K, N, Backend, Duration_us) ->
Flops = ((2 * M) * K) * N,
Gflops = case Duration_us > 0 of
true ->
format_float((case erlang:float(Duration_us) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> erlang:float(Flops) / Gleam@denominator
end) / 1000.0);
false ->
<<"inf"/utf8>>
end,
viva_telemetry@log:info(
<<"matmul"/utf8>>,
[{<<"dims"/utf8>>,
<<<<<<<<<<<<(erlang:integer_to_binary(M))/binary, "x"/utf8>>/binary,
(erlang:integer_to_binary(K))/binary>>/binary,
" @ "/utf8>>/binary,
(erlang:integer_to_binary(K))/binary>>/binary,
"x"/utf8>>/binary,
(erlang:integer_to_binary(N))/binary>>},
{<<"backend"/utf8>>, Backend},
{<<"duration_us"/utf8>>, erlang:integer_to_binary(Duration_us)},
{<<"gflops"/utf8>>, Gflops}]
).
-file("src/viva_tensor/telemetry.gleam", 188).
?DOC(" Log quantization operation.\n").
-spec log_quantize(binary(), float()) -> nil.
log_quantize(Format, Ratio) ->
viva_telemetry@log:info(
<<"quantize"/utf8>>,
[{<<"format"/utf8>>, Format},
{<<"ratio"/utf8>>, <<(format_float(Ratio))/binary, "x"/utf8>>}]
).
-file("src/viva_tensor/telemetry.gleam", 209).
?DOC(" Record a matmul operation with full details.\n").
-spec record_matmul(integer(), integer(), integer(), integer(), binary()) -> nil.
record_matmul(M, N, K, Duration_us, Backend) ->
viva_telemetry@metrics:inc(op_counter(<<"matmul"/utf8>>)),
viva_telemetry@metrics:observe(
matmul_histogram(),
erlang:float(Duration_us)
),
viva_telemetry@metrics:inc(backend_counter(Backend)),
log_matmul(M, K, N, Backend, Duration_us).
-file("src/viva_tensor/telemetry.gleam", 241).
?DOC(" Record a quantization operation.\n").
-spec record_quantize(binary(), float()) -> nil.
record_quantize(Format, Ratio) ->
viva_telemetry@metrics:inc(quant_counter(Format)),
log_quantize(Format, Ratio).