unaiverse.stats
What this module does 🔴
Provides the statistics and telemetry subsystem: UIPlot for Plotly panels, DefaultBaseDash for dashboard layout, and Stats for SQLite-backed metric recording and rendering.
stats
¶
█████ █████ ██████ █████ █████ █████ █████ ██████████ ███████████ █████████ ██████████
░░███ ░░███ ░░██████ ░░███ ░░███ ░░███ ░░███ ░░███░░░░░█░░███░░░░░███ ███░░░░░███░░███░░░░░█
░███ ░███ ░███░███ ░███ ██████ ░███ ░███ ░███ ░███ █ ░ ░███ ░███ ░███ ░░░ ░███ █ ░
░███ ░███ ░███░░███░███ ░░░░░███ ░███ ░███ ░███ ░██████ ░██████████ ░░█████████ ░██████
░███ ░███ ░███ ░░██████ ███████ ░███ ░░███ ███ ░███░░█ ░███░░░░░███ ░░░░░░░░███ ░███░░█
░███ ░███ ░███ ░░█████ ███░░███ ░███ ░░░█████░ ░███ ░ █ ░███ ░███ ███ ░███ ░███ ░ █
░░████████ █████ ░░█████░░████████ █████ ░░███ ██████████ █████ █████░░█████████ ██████████
░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░ ░░░░░ ░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░
A Collectionless AI Project (https://collectionless.ai)
Registration/Login: https://unaiverse.io
Code Repositories: https://github.com/collectionlessai/
Main Developers: Stefano Melacci (Project Leader), Christian Di Maio, Tommaso Guidi
THEMES
module-attribute
¶
THEMES = {'dark': {'bg_paper': 'rgba(0,0,0,0)', 'bg_plot': 'rgba(0,0,0,0)', 'text_main': '#C8CDD3', 'text_light': '#677385', 'grid': '#222A36', 'edge': '#495464', 'node_border': '#F5F6F8', 'main': '#1A5CFF', 'main_light': '#4D7FFF', 'table': {'header_bg': '#16171C', 'header_txt': '#F5F6F8', 'cell_bg': '#0E0F14', 'cell_txt': '#C8CDD3', 'line': '#222A36'}, 'peers': ['#1A5CFF', '#FF3B30', '#00D4AA', '#FFB347', '#4D7FFF', '#00B391', '#FF6692', '#33EABD', '#FFD080', '#6B9BFF']}, 'light': {'bg_paper': 'rgba(255,255,255,0)', 'bg_plot': 'rgba(255,255,255,0)', 'text_main': '#0A1628', 'text_light': '#677385', 'grid': '#DBE1EB', 'edge': '#909CB0', 'node_border': '#0A1628', 'main': '#1A5CFF', 'main_light': '#4D7FFF', 'table': {'header_bg': '#F6F8FA', 'header_txt': '#0A1628', 'cell_bg': '#FFFFFF', 'cell_txt': '#0A1628', 'line': '#C0C8D6'}, 'peers': ['#1A5CFF', '#FF3B30', '#00D4AA', '#FFB347', '#4D7FFF', '#00B391', '#FF6692', '#33EABD', '#FFD080', '#6B9BFF']}}
UIPlot
¶
A Python abstraction for a single Plotly chart panel.
Wraps a Plotly data/layout pair behind a fluent builder API so that callers
can construct charts with typed method calls rather than hand-crafting JSON
dictionaries. All traces are accumulated in an internal list; call to_json to
produce the JSON string expected by the frontend.
The default layout follows the dark theme defined by the module-level THEME
constant. Layout properties can be overridden with set_layout_opt or with the
purpose-built helpers (set_y_range, set_legend).
Attributes:
| Name | Type | Description |
|---|---|---|
_data |
list[dict[str, Any]]
|
Ordered list of raw Plotly trace dictionaries. |
_layout |
dict[str, Any]
|
Plotly layout dictionary controlling axes, size, and appearance. |
Initialize a UIPlot with an empty trace list and a dark-themed Plotly layout.
The layout is pre-configured with the module-level dark THEME: transparent
background, dotted grid lines, mirrored axis borders, and matching font colors.
Both axes default to the titles 'Time' (x-axis) and 'Value' (y-axis);
override them after construction with set_layout_opt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
Title text shown at the top of the plot. Defaults to an empty string. |
''
|
height
|
int
|
Height of the plot in pixels. Defaults to 400. |
400
|
Source code in unaiverse/stats.py
add_line
¶
add_line(x: list[Any], y: list[Any], name: str, color: str | None = None, legend_group: str | None = None, show_legend: bool = True)
Add a scatter line trace with markers to the plot.
Creates a Plotly scatter trace in 'lines+markers' mode and appends it to
the internal trace list. Multiple calls accumulate traces on the same axes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
list[Any]
|
Sequence of x-axis values (e.g., millisecond timestamps or category strings). |
required |
y
|
list[Any]
|
Sequence of y-axis values corresponding to each x entry. |
required |
name
|
str
|
Label shown in the legend for this trace. |
required |
color
|
str | None
|
CSS color string (hex, |
None
|
legend_group
|
str | None
|
Plotly legend-group name. Traces sharing the same group are toggled together when the legend entry is clicked. Defaults to None. |
None
|
show_legend
|
bool
|
Whether to display this trace in the legend. Defaults to True. |
True
|
Source code in unaiverse/stats.py
add_area
¶
Add a filled area trace (fill: tozeroy) to the plot.
Creates a Plotly scatter trace filled down to zero on the y-axis, suitable
for visualizing cumulative or bounded quantities.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
list[Any]
|
Sequence of x-axis values. |
required |
y
|
list[Any]
|
Sequence of y-axis values defining the upper boundary of the filled area. |
required |
name
|
str
|
Label shown in the legend for this trace. |
required |
color
|
str | None
|
CSS color string applied to both the line and the fill. Defaults to
the primary theme color |
None
|
Source code in unaiverse/stats.py
add_indicator
¶
Add a big-number indicator trace to the plot.
Creates a Plotly indicator trace in 'number' mode and appends it to the
trace list. The layout height is also reduced to 300 pixels because indicators
require less vertical space than full chart panels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
Numeric (or any JSON-serializable) value to display prominently in the center of the panel. |
required |
title
|
str
|
Subtitle text rendered below the number. |
required |
Source code in unaiverse/stats.py
add_table
¶
Add a Plotly table trace to the plot.
Renders a formatted data table using the dark-theme colors defined in THEME.
When headers is None, a transparent zero-height header row is used so
that no column labels appear, but the table structure is otherwise identical.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
headers
|
list[str] | None
|
Column header labels shown at the top of the table, or |
required |
columns
|
list[list[Any]]
|
Column data as a list of per-column value lists. Each inner list corresponds to one column; all inner lists should have the same length. |
required |
Source code in unaiverse/stats.py
add_bar
¶
Add a bar chart trace with automatic text labels to the plot.
Creates a Plotly bar trace with text annotations positioned automatically on
top of each bar. The y-axis title is reset to 'Value' so that it always
reflects this trace.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xs
|
list[Any]
|
Category labels displayed on the x-axis (one per bar). |
required |
ys
|
list[Any]
|
Numeric values controlling bar heights (one per bar). |
required |
names
|
list[str]
|
Text annotations placed on or near each bar (one per bar). |
required |
colors
|
list[str] | str | None
|
A single CSS color string applied uniformly to all bars, or a list of
per-bar CSS color strings. Defaults to the primary theme color
|
None
|
Source code in unaiverse/stats.py
add_trace
¶
Add an arbitrary raw Plotly trace dictionary to the plot.
Use this method when none of the typed helpers (add_line, add_bar, etc.)
cover the required trace type. The dictionary is appended as-is to the internal
trace list without validation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trace
|
dict[str, Any]
|
A fully-specified Plotly trace dictionary. For example,
|
required |
Source code in unaiverse/stats.py
set_y_range
¶
Force the Y-axis to a fixed numeric range.
Overrides Plotly's auto-scaling by writing a 'range' key into the
'yaxis' layout entry. Useful when the data range changes dramatically over
time and a stable view is preferred.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_val
|
float
|
Lower bound of the Y-axis. |
required |
max_val
|
float
|
Upper bound of the Y-axis. |
required |
Source code in unaiverse/stats.py
set_layout_opt
¶
Set or merge a top-level Plotly layout option.
When both the existing value at key and the incoming value are
dictionaries, the existing entry is updated (shallow-merged) rather than
replaced. For all other types the key is simply overwritten. This makes it safe
to call multiple times on the same key to progressively configure an axis or
other composite layout object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Top-level Plotly layout key, such as |
required |
value
|
Any
|
Value to assign. Dicts are merged into the existing entry; all other types overwrite it. |
required |
Source code in unaiverse/stats.py
set_legend
¶
set_legend(orientation: str = 'v', x: float = 1.0, y: float = 1.0, xanchor: str = 'left', yanchor: str = 'top')
Configure the legend visibility, position, and orientation.
Enables the legend (showlegend: True) and writes a fully-specified
'legend' entry into the layout, styled with theme-consistent background and
border colors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
orientation
|
str
|
Legend box orientation. Use |
'v'
|
x
|
float
|
Horizontal anchor position in Plotly paper coordinates (0.0 = left edge, 1.0 = right edge). Defaults to 1.0. |
1.0
|
y
|
float
|
Vertical anchor position in Plotly paper coordinates (0.0 = bottom, 1.0 = top). Defaults to 1.0. |
1.0
|
xanchor
|
str
|
Horizontal alignment of the legend box relative to |
'left'
|
yanchor
|
str
|
Vertical alignment of the legend box relative to |
'top'
|
Source code in unaiverse/stats.py
to_json
¶
Serialize the panel to a JSON string expected by the frontend.
Returns:
| Type | Description |
|---|---|
str
|
A JSON string containing a top-level object with |
str
|
dicts) and |
str
|
directly to Plotly. |
Source code in unaiverse/stats.py
DefaultBaseDash
¶
A 2x2 grid dashboard that composes four UIPlot panels into a single Plotly figure.
Each of the four fixed cells ('top_left', 'top_right', 'bot_left',
'bot_right') receives one UIPlot via add_panel. The dashboard uses a
shared Plotly layout with independent sub-plot axes so traces from different panels
do not interfere with each other. Call to_json to obtain the assembled figure
ready for the frontend.
The styling follows the dark theme defined by the module-level THEME constant.
Attributes:
| Name | Type | Description |
|---|---|---|
traces |
Accumulated list of raw Plotly trace dicts contributed by each panel. |
|
layout |
Shared Plotly layout dict controlling the 2x2 grid axes, legend, and global appearance. |
Initialize the 2x2 grid dashboard with a dark-themed Plotly layout.
Sets up two rows and two columns of independent sub-plot axes with fixed domain
coordinates, a shared horizontal legend positioned between the rows, and theme-
consistent margins and colors. The four axis pairs are stored in an internal
_map dict for use by add_panel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
Main title text displayed at the top of the dashboard. Defaults to
|
'Network Overview'
|
Source code in unaiverse/stats.py
layout
instance-attribute
¶
layout = {'title': title, 'height': 800, 'template': 'plotly_dark', 'paper_bgcolor': THEME['bg_paper'], 'grid': {'rows': 2, 'columns': 2, 'pattern': 'independent'}, 'xaxis1': {'domain': [0, 0.48]}, 'yaxis1': {'domain': [0.56, 1]}, 'xaxis2': {'domain': [0.52, 1]}, 'yaxis2': {'domain': [0.56, 1]}, 'xaxis3': {'domain': [0, 0.48]}, 'yaxis3': {'domain': [0, 0.44]}, 'xaxis4': {'domain': [0.52, 1]}, 'yaxis4': {'domain': [0, 0.44]}, 'showlegend': True, 'legend': {'orientation': 'h', 'y': 0.55, 'x': 0.55, 'xanchor': 'left', 'yanchor': 'top', 'bgcolor': 'rgba(0,0,0,0)', 'font': {'color': THEME['text_main']}}, 'margin': {'l': 50, 'r': 50, 't': 80, 'b': 50}}
add_panel
¶
add_panel(ui_plot: UIPlot, position: str)
Merge a UIPlot into one of the four fixed grid positions.
Each trace from ui_plot is copied and assigned the axis references that
correspond to the target cell (e.g., 'x1'/'y1' for 'top_left').
Table traces use a 'domain' key instead of axis references. Axis-level layout
settings (grid lines, titles, etc.) from the panel are merged into the shared
layout without overwriting the fixed domain boundaries. If the panel has a title,
it is added as a centered annotation just above the cell.
If position is not one of the four recognized cell names the call is silently
ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ui_plot
|
UIPlot
|
The |
required |
position
|
str
|
Target grid cell. One of |
required |
Source code in unaiverse/stats.py
to_json
¶
Serialize the assembled dashboard to a JSON string expected by the frontend.
Returns:
| Type | Description |
|---|---|
str
|
A JSON string containing a top-level object with |
str
|
trace list from all panels) and |
str
|
to be passed directly to Plotly. |
Source code in unaiverse/stats.py
Stats
¶
Statistics engine for UNaIVERSE agents and worlds.
Stats operates in two distinct modes controlled by is_world:
-
Agent mode (
is_world=False): maintains a lightweight send buffer (_update_batch) and a local world-view snapshot (_world_view). Agents callstore_statto queue measurements for transmission andget_payload_for_worldto retrieve the pending batch before flushing it over the network. -
World mode (
is_world=True): runs the full persistence stack. Incoming measurements are type-validated, written to an in-memory rolling hot-cache (_stats), and also queued in write buffers that are flushed to an SQLite database onsave_to_disk. Historical queries are served from SQLite viaquery_history.
Schema design¶
Statistics are declared by setting class-level schema dictionaries (e.g.,
CORE_WORLD_STATS_DYNAMIC_SCHEMA) before any instance is created. Custom
subclasses may extend the built-in schemas via the CUSTOM_* class variables.
Each schema maps a stat name to a (type, default) pair. At construction time
all schemas are merged and the resulting master key sets (all_static_keys,
all_dynamic_keys, etc.) are used throughout for fast O(1) lookups.
Stat categories¶
- Static stats: single latest value per
group_key(e.g., current HSM state). On the Agent side, duplicate entries for the samegroup_keyare removed from the buffer before the new value is appended (de-duplication). - Dynamic stats: time-series values stored in a
SortedDictkeyed by millisecond timestamps on the World side. The hot cache retains only the rolling window defined bycache_window_hours; older data lives only on disk.
Grouping¶
Stats are either ungrouped (world-level, e.g., membership counts) or grouped
under a group_key (usually a peer ID). Ungrouped world stats live directly in
_stats[stat_name]; grouped stats live in _stats[GROUP_KEY][group_key][stat_name].
Plotting¶
Call plot to obtain a self-contained HTML dashboard that visualizes the world
topology, agent-count history, state distribution, and last-action distribution.
Agents that receive a world-view snapshot via update_view can also call plot
to render their cached view.
Attributes:
| Name | Type | Description |
|---|---|---|
is_world |
bool
|
|
max_seen_timestamp |
int
|
Largest millisecond timestamp encountered so far; used for rolling-window pruning. |
all_static_keys |
set[str]
|
Set of all stat names classified as static across all schemas. |
all_dynamic_keys |
set[str]
|
Set of all stat names classified as dynamic across all schemas. |
all_keys |
set[str]
|
Union of |
stat_types |
Mapping from stat name to its schema-declared Python type. |
|
STORE_DYNAMIC_IF_CHANGED |
Class-level flag; when |
|
GROUP_KEY |
Class-level constant used as the top-level key in |
Initialize the Stats engine in either World or Agent mode.
When is_world is True, the full World-side stack is set up: all CORE and
CUSTOM schemas are merged, master key sets are populated, the SQLite database is
opened (or created) at db_path, the in-memory hot-cache structure is
initialized, and any existing data within the rolling window is loaded from disk.
The parent directory of db_path is created automatically if it does not exist.
When is_world is False, only a lightweight send buffer (_update_batch)
and an empty world-view snapshot (_world_view) are allocated. No database
connection is opened.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
is_world
|
bool
|
|
required |
db_path
|
str | None
|
Filesystem path for the SQLite database file. Required when
|
None
|
cache_window_hours
|
float
|
Duration in hours of the in-memory rolling window kept
by the World hot cache. Dynamic data older than this window is evicted
from RAM but remains on disk and is queryable via |
2.0
|
Source code in unaiverse/stats.py
CORE_WORLD_STATS_STATIC_SCHEMA
class-attribute
instance-attribute
¶
CORE_WORLD_STATS_STATIC_SCHEMA: dict[str, tuple[type, Any]] = {'graph': (dict, {'nodes': {}, 'edges': {}})}
CORE_WORLD_STATS_DYNAMIC_SCHEMA
class-attribute
instance-attribute
¶
CORE_WORLD_STATS_DYNAMIC_SCHEMA: dict[str, tuple[type, Any]] = {'world_masters': (int, 0), 'world_agents': (int, 0), 'human_agents': (int, 0), 'artificial_agents': (int, 0)}
CORE_AGENT_STATS_STATIC_SCHEMA
class-attribute
instance-attribute
¶
CORE_AGENT_STATS_STATIC_SCHEMA: dict[str, tuple[type, Any]] = {'connected_peers': (list, []), 'state': (str, None), 'action': (str, None), 'last_action': (str, None)}
CORE_AGENT_STATS_DYNAMIC_SCHEMA
class-attribute
instance-attribute
¶
CORE_OUTER_STATS_STATIC_SCHEMA
class-attribute
instance-attribute
¶
CORE_OUTER_STATS_DYNAMIC_SCHEMA
class-attribute
instance-attribute
¶
CUSTOM_WORLD_STATS_STATIC_SCHEMA
class-attribute
instance-attribute
¶
CUSTOM_WORLD_STATS_DYNAMIC_SCHEMA
class-attribute
instance-attribute
¶
CUSTOM_AGENT_STATS_STATIC_SCHEMA
class-attribute
instance-attribute
¶
CUSTOM_AGENT_STATS_DYNAMIC_SCHEMA
class-attribute
instance-attribute
¶
CUSTOM_OUTER_STATS_STATIC_SCHEMA
class-attribute
instance-attribute
¶
CUSTOM_OUTER_STATS_DYNAMIC_SCHEMA
class-attribute
instance-attribute
¶
WORLD_STATS_STATIC_SCHEMA
instance-attribute
¶
WORLD_STATS_DYNAMIC_SCHEMA
instance-attribute
¶
AGENT_STATS_STATIC_SCHEMA
instance-attribute
¶
AGENT_STATS_DYNAMIC_SCHEMA
instance-attribute
¶
OUTER_STATS_STATIC_SCHEMA
instance-attribute
¶
OUTER_STATS_DYNAMIC_SCHEMA
instance-attribute
¶
store_stat
¶
Store a single measurement, dispatching to static or dynamic storage.
The stat name is looked up in all_static_keys and all_dynamic_keys to
determine the storage path. Static stats are routed to _store_static; dynamic
stats are routed to _store_dynamic. If stat_name is not recognized, an
error is logged and the call returns without storing anything.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stat_name
|
str
|
Name of the statistic as declared in one of the schema dictionaries. |
required |
value
|
Any
|
Measurement value. Type-validated and cast to the schema-declared type before storage. |
required |
group_key
|
str
|
Grouping identifier for this measurement, typically a peer ID. Used to bucket related records in the world hot-cache and in the database. |
required |
timestamp
|
int
|
Millisecond Unix timestamp associated with the measurement. |
required |
Source code in unaiverse/stats.py
update_view
¶
Merge a world-view snapshot received from the World into the local cache (Agent-side).
This method is a no-op on the World side. On the Agent side it incrementally
updates _world_view with the incoming data. Dynamic stats (whose names appear
in all_dynamic_keys) are stored as [[timestamp, value], ...] lists and are
extended (new pairs appended) rather than replaced on repeated calls. Static
stats are simply overwritten. The running maximum seen timestamp is updated as
dynamic data arrives.
If overwrite is True, the existing _world_view is discarded before
merging, giving a clean snapshot of the new data only.
The expected structure of view_data is the same dictionary produced by the
World's get_view method::
{
"world": { "stat_name": value_or_timeseries },
"peers": { "peer_id": { "stat_name": value_or_timeseries } }
}
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
view_data
|
dict[str, Any] | None
|
The snapshot dictionary received from the world, matching the
structure produced by |
None
|
overwrite
|
bool
|
If |
False
|
Source code in unaiverse/stats.py
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 | |
get_stats
¶
Return the raw internal hot-cache dictionary (World-only).
Provides direct access to the live _stats structure for callers that need
to read or manipulate the cache in ways not covered by the higher-level query
API. The returned object is the actual internal dict, not a copy; mutations
will affect the running state of the Stats engine.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The |
dict[str, Any]
|
stat names (e.g., |
dict[str, Any]
|
( |
dict[str, Any]
|
On the Agent side this attribute does not exist; this method should only be |
dict[str, Any]
|
called from World-mode instances. |
Source code in unaiverse/stats.py
get_payload_for_world
¶
Return the pending stats batch to be transmitted to the world (Agent-only).
Retrieves the current _update_batch and, unless clear_buffer is False,
replaces it with an empty list so that subsequent calls do not re-send already
dispatched updates. On the World side this always returns an empty list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
clear_buffer
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
A list of stat-update dicts ready for transmission. Each dict contains the |
list[dict[str, Any]]
|
keys |
list[dict[str, Any]]
|
Returns an empty list when called on the World side. |
Source code in unaiverse/stats.py
get_view
¶
Return a JSON-serializable snapshot of the current in-memory hot cache (World-side).
Serializes both ungrouped world stats and all peer-grouped stats from the
_stats hot cache. Dynamic stats (SortedDict caches) are sliced to include
only entries with a timestamp strictly greater than since_timestamp, making
this method efficient for incremental polling: pass the last received timestamp
to retrieve only new data points.
Used for initial handshakes (since_timestamp=0) and for lightweight
incremental streaming. For historical data beyond the rolling window, use
query_history instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
since_timestamp
|
int
|
Millisecond Unix timestamp lower bound. Only dynamic data
points recorded after this value are included. Pass |
0
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A dictionary with the structure:: { "world": { "stat_name": value_or_timeseries }, "peers": { "peer_id": { "stat_name": value_or_timeseries } } } |
dict[str, Any]
|
For dynamic stats, |
dict[str, Any]
|
pairs. Empty peer entries (no data points after the cutoff) are omitted. |
dict[str, Any]
|
Returns an empty dict when called on the Agent side. |
Source code in unaiverse/stats.py
get_last_value
¶
Return the most recent value of a stat, regardless of whether it is static or dynamic.
Dispatches to _get_last_static_value or _get_last_dynamic_value based on
stat_name's membership in the master key sets. If the stat name is not
recognised an error is logged and None is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stat_name
|
str
|
Name of the statistic to retrieve. Must be registered in one of the schema dictionaries. |
required |
group_key
|
str | None
|
When |
None
|
Returns:
| Type | Description |
|---|---|
Any | None
|
The most recently recorded value for the stat, or |
Any | None
|
unknown, has no data, or the cache does not hold a value for the requested key. |
Source code in unaiverse/stats.py
save_to_disk
¶
Flush all pending buffers to SQLite and prune stale data (World-only).
Sequentially calls _save_static_to_db, _save_dynamic_to_db,
_prune_cache, and _prune_db, then commits the transaction. If the
instance is not in World mode or the database connection is unavailable, the
call returns immediately without doing anything. Any exception raised during
the save is caught, logged, and the transaction is rolled back so that no
partial writes are committed.
Note
On the Agent side this method is a no-op.
Source code in unaiverse/stats.py
query_history
¶
query_history(stat_names: list[str] | None = None, group_keys: list[str] | None = None, time_range: tuple[int, int] | int | None = None, value_range: tuple[float, float] | None = None, limit: int | None = None) -> dict[str, Any]
Query the SQLite database for historical stats with optional filters (World-only).
Automatically flushes the in-memory static and dynamic buffers to the database
before executing the query, ensuring "read-your-writes" consistency. Both static
and dynamic tables are queried separately and merged into the same structure
produced by get_view, so the result can be fed directly into update_view
on the Agent side.
Static stats are loaded without a time filter (each stat has at most one row per
peer). Dynamic stats are filtered by time_range, value_range, and
limit, then ordered by timestamp ascending.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stat_names
|
list[str] | None
|
Restrict results to these stat names. Pass |
None
|
group_keys
|
list[str] | None
|
Restrict results to these group keys (peer IDs). Pass |
None
|
time_range
|
tuple[int, int] | int | None
|
Time filter applied only to dynamic stats. An |
None
|
value_range
|
tuple[float, float] | None
|
|
None
|
limit
|
int | None
|
Maximum number of dynamic-stat rows to return. Defaults to 5000 when
|
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A dictionary with the same structure as { "world": { "stat_name": value_or_timeseries }, "peers": { "peer_id": { "stat_name": value_or_timeseries } } } |
dict[str, Any]
|
Returns an empty dict when called on the Agent side or when the database |
dict[str, Any]
|
connection is unavailable. Individual query errors are caught and logged; |
dict[str, Any]
|
partial results may be returned. |
Source code in unaiverse/stats.py
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 | |
shutdown
¶
Flush all pending stats to disk and close the SQLite connection gracefully.
Calls save_to_disk to persist any buffered measurements, then closes the
database connection and sets _db_conn to None. Any exception raised by
the final save is caught and logged rather than propagated, so the connection is
always closed even when the flush fails. On the Agent side this method is a no-op.
Note
Call this method explicitly at application shutdown. The destructor
(__del__) also attempts a final save, but relying on the destructor for
critical I/O is not recommended.
Source code in unaiverse/stats.py
plot
¶
Build and return the default 2x2 stats dashboard as a self-contained HTML document.
Composes four panels into a DefaultBaseDash and delegates HTML rendering to
the stats_html_renderer module (imported lazily). Plotly.js is loaded from
CDN inside the generated HTML; the Python plotly package is never imported.
On the World side, get_view(since_timestamp) is called to obtain the data.
On the Agent side, the locally cached _world_view is used directly. If
neither source provides any data, None is returned.
The four panels are: - Top left: Network topology graph (circular layout of connected peers). - Top right: World agent-count history (world masters, agents, humans, artificial). - Bottom left: Network topology graph (duplicate, reserved for future state distribution). - Bottom right: Last-action distribution bar chart across all peers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
since_timestamp
|
int
|
Millisecond Unix timestamp lower bound. Only dynamic data
points recorded after this value are included in the time-series panels.
Pass |
0
|
Returns:
| Type | Description |
|---|---|
str | None
|
A complete |
str | None
|
is available to render. |
Source code in unaiverse/stats.py
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 | |