{% extends "base.html" %} {% import "_panel.html" as panel_macros %} {% block content %}

FTMON self-monitoring

Web process version {{ web_version }}.

Budgets

{% if panel %} {% macro history(metric, label) -%} 6h 24h history for {{ label }} {%- endmacro %} {{ panel_macros.budget_row( panel.cpu.row, '%.1f%%'|format(panel.cpu.row.value) if panel.cpu.row.value is not none else '', '%.1f%%'|format(panel.cpu.row.limit) if panel.cpu.row.limit else 'no threshold') }} {{ panel_macros.budget_row( panel.memory.row, panel_macros.bytes_mb(panel.memory.row.value), panel_macros.bytes_mb(panel.memory.row.limit)) }} {{ panel_macros.budget_row( panel.database.row, panel_macros.bytes_mb(panel.database.row.value), panel_macros.bytes_mb(panel.database.row.limit)) }}
Measured against this host's self.toml thresholds. RB-01's cross-platform targets are shown where they differ.
Current {% if panel.cpu.current is none %}—{% else %}{{ '%.1f'|format(panel.cpu.current) }}%{% endif %}, 10-minute average {% if panel.cpu.avg10m is none %}—{% else %}{{ '%.1f'|format(panel.cpu.avg10m) }}%{% endif %}. RB-01 target {{ '%.1f'|format(panel.cpu.row.spec) }}% of one core. {{ history('cpu_10m', 'CPU') }}
{{ history('rss_bytes', 'RSS') }}
Used pages are the DM-05 figure. File allocation {{ panel_macros.bytes_mb(panel.database.allocated) }}, of which {{ panel_macros.bytes_mb(panel.database.freelist) }} is reusable. Headroom to the 200 MB target {% if panel.database.headroom is none %}—{% else %}{{ panel_macros.bytes_mb(panel.database.headroom) }}{% endif %}. {{ history('db_used_bytes', 'used pages') }}

Catalog

Persisted {% if panel.catalog.entities_persisted is none %} not available yet — no daemon has published it {% else %} {{ panel.catalog.entities_persisted }} entities of {{ panel.catalog.max_entities_persisted }} (DM-16 budget), {{ panel.catalog.series_persisted }} series of {{ panel.catalog.max_series_persisted }} (worksheet assumption) {% endif %}
Running {{ panel.catalog.entities_not_gone }} entities, {{ panel.catalog.series_not_gone }} series — present, not persisted; not budget figures
Reap {{ panel_macros.age(panel.catalog.reap_age_s) }}{% if panel.catalog.reap_count is not none %}, {{ panel.catalog.reap_count }} removed{% endif %}
Degradation {{ panel_macros.age(panel.catalog.degradation_age_s) }}

Where the tick goes

{# rejectattr('seconds','none'), not selectattr: a measured 0.0 is a reading. Truthiness here would report real zero timings as uncollected, defeating the absent-vs-zero distinction this panel exists to keep. #} {% if panel.stages | rejectattr('seconds', 'none') | list %} {% for stage in panel.stages if stage.seconds is not none %} {% endfor %}
{{ stage.name }} {{ '%.1f'|format(stage.seconds * 1000) }} ms
{% else %}

Per-stage timings are not collected yet. Until they are, the budgets above say whether the daemon is within its limits but not where its time goes.

{% endif %} {% else %}

No database yet.

{% endif %}

Notification delivery

{% if dispatch %}
Dispatcher {{ dispatch.state }} ({{ dispatch.mode }}){% if dispatch.last_error_category %} — last error {{ dispatch.last_error_category }}{% endif %}
Pending {{ dispatch.pending_total }} ({{ dispatch.due_claimable }} due, {{ dispatch.quiet_held }} held by quiet hours)
Oldest claimable {{ dispatch.oldest_claimable_due_age_s|round|int }}s
Failed {{ dispatch.failed }}{% if dispatch.failed_by_channel %} — {% for channel, count in dispatch.failed_by_channel.items() %}{{ channel }}={{ count }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}
{% else %}

No database yet.

{% endif %}

All self metrics

{% for row in metrics %}{% else %}{% endfor %}
{{ row.metric }}{{ row.value }}
No self metrics yet.

Configuration errors

{% for path,error in config_errors %}
{{ path.name }}: {{ error }}
{% else %}

None.

{% endfor %}

Daemon log tail

{{ log_tail }}
{% endblock %}