Description
Add lightweight runtime metrics collection to the lume_pva.Runner and expose the collected metrics through a Python method on the Runner class.
This is not an HTTP API and the Runner does not need to expose Prometheus, OpenTelemetry, or any other monitoring protocol directly.
The higher-level application embedding the Runner should be able to call something such as:
metrics = runner.get_metrics()
and combine those metrics with its own application-level metrics before exposing them externally.
The intent is to instrument the work that the Runner itself owns:
Input Updates
|
v
Runner Queue
|
+-- update coalescing
|
v
model.set(...)
|
v
model.get(...)
|
v
Output Publication
|
+-- PVA
+-- CA
|
v
Higher-Level Application
|
+-- runner.get_metrics()
+-- application metrics
|
v
External Monitoring
Why this belongs in Runner
The current Runner is the component that:
- receives local CA/PVA writes;
- receives remote PV monitor updates;
- handles snapshot requests;
- queues incoming updates;
- coalesces updates for
update_rate;
- transitions the model between
Idle and Simulating;
- calls
model.reset() when requested;
- calls
model.set(...);
- calls
model.get(...);
- publishes model outputs through PVA and/or CA;
- reports put completion;
- restores cached model state after simulation failures.
These are the best locations for collecting operational metrics because the higher-level application cannot reliably reconstruct them from outside the Runner.
Proposed Python Interface
Add a method on Runner, for example:
metrics = runner.get_metrics()
The exact name and return type can be decided during implementation.
A typed, immutable snapshot is preferred, for example:
@dataclass(frozen=True)
class RunnerMetrics:
...
get_metrics() should return the current snapshot and must not reset counters.
A separate reset method can be added later if needed.
Metrics to Collect
1. Runner State / Health
These metrics describe whether the Runner is alive and able to process model updates.
Suggested fields:
state
simulation_active
simulation_cycles_total
simulation_cycles_failed_total
last_simulation_started_at
last_simulation_completed_at
last_simulation_error
time_since_last_successful_simulation_seconds
- 'simulation_latency_[max/min,mean]_time'
The Runner already tracks Idle / Simulating, so the metrics snapshot should reuse that state rather than create a second independent state model.
The last error should be treated as diagnostic state rather than a counter. It may be omitted if exposing error text through metrics is considered undesirable.
2. Input Update Metrics
Inputs can currently arrive through several paths:
- PVA PUT
- CA write
- remote PV monitor callback
- snapshot
- reset/control request
- initial update created when the Runner starts
Track the source where practical.
Suggested counters:
input_updates_received_total
input_variables_received_total
pva_puts_total
ca_puts_total
remote_monitor_updates_total
snapshot_requests_total
reset_requests_total
invalid_input_updates_total
It is useful to distinguish:
from:
individual variable values contained in those updates
because one queued update may contain several variables.
For example, a snapshot can update many input variables at once.
3. Queue / Backpressure Metrics
The Runner uses an internal queue and intentionally coalesces updates during the configured update_rate window before starting a simulation.
This makes queue metrics particularly important.
Suggested metrics:
queue_depth
queue_depth_max
queue_items_enqueued_total
queue_items_dequeued_total
queue_items_coalesced_total
variables_coalesced_total
update_batches_total
average_updates_per_batch
average_variables_per_batch
queue_wait_time_ms
A key metric should show how much incoming activity is being collapsed into a single model execution.
For example:
8 queued updates
|
| update_rate window
v
1 model execution
This is important when determining whether the Runner is keeping up with incoming control-system updates.
4. End-to-End Update Latency
The Runner already associates timestamps with incoming values and propagates the newest input timestamp to the output PV updates.
Use this to measure end-to-end Runner latency.
Suggested metric:
input_to_output_latency_ms
Conceptually:
input update timestamp
|
v
queue/coalescing
|
v
model execution
|
v
output publication
This is one of the most useful operational metrics because it represents the delay seen by a user of the virtual accelerator.
5. Model Execution Metrics
The Runner has clearly separated execution stages around:
model.reset()
model.set(...)
model.get(...)
Collect latency independently for each stage.
Suggested metrics:
model.set()
model_set_total
model_set_failures_total
model_set_latency_ms
model.get()
model_get_total
model_get_failures_total
model_get_latency_ms
Full simulation cycle
simulation_cycle_latency_ms
The full cycle should measure from the point at which the Runner starts processing a coalesced update batch until output publication is complete.
This is more useful than a generic "inference latency" metric because not every supported LUME backend is an ML inference model. The same Runner may use Bmad/Tao, surrogate models, staged models, or other LUME implementations.
6. Reset and Recovery Metrics
The Runner supports explicit model reset and also restores cached model state after a failed simulation.
Suggested metrics:
model_resets_total
model_reset_failures_total
model_reset_latency_ms
cached_state_restore_total
cached_state_restore_failures_total
This makes it possible to differentiate between:
and:
failure followed by successful/failed state recovery
7. Output Publication Metrics
After model.get(...), the Runner iterates over returned values and publishes them through PVA and/or CA.
Suggested counters:
output_variables_returned_total
output_variables_published_total
output_variables_skipped_total
output_none_values_total
output_publish_failures_total
pva_posts_total
pva_post_failures_total
ca_updates_total
ca_update_failures_total
Also collect:
output_publication_latency_ms
The Runner currently skips outputs whose value is None. This should have its own counter because frequent None outputs can indicate a model or configuration problem even when the simulation itself does not throw an exception.
8. Put Completion Metrics
The Runner supports two put modes:
When complete mode is used, completion callbacks are invoked after the model execution finishes.
Useful metrics include:
put_completion_callbacks_total
put_completion_callback_failures_total
put_completion_latency_ms
This is useful for diagnosing control clients that experience long PUT completion times or timeouts.
9. Snapshot Metrics
Snapshot mode performs synchronous reads of configured remote PVs before enqueuing the model update.
Suggested metrics:
snapshot_requests_total
snapshot_remote_pvs_read_total
snapshot_failures_total
snapshot_collection_latency_ms
If individual remote get() failures can be handled independently in the future, also track:
snapshot_remote_pv_read_failures_total
10. Remote Input Monitor Metrics
For continuous remote input mode, updates arrive through monitor callbacks.
Suggested metrics:
remote_monitor_updates_total
remote_monitor_variables_total
Optionally, if subscription state is available:
remote_monitors_configured
remote_monitors_connected
remote_monitor_disconnects_total
Connection-level metrics should only be added if the underlying PV client exposes them reliably.
Configuration / Identity Information
The metrics snapshot should also expose enough static information for the higher-level application to identify the Runner.
Suggested fields:
- model class/name
- Runner/lume-pva version
- configured protocols (
ca, pva)
- configured
put_mode
- configured
remote_model_mode
- configured
update_rate
- number of supported variables
- number of local input/output PVs
- number of remote variables
Do not duplicate the complete model_info PV payload unless needed.
Metrics That Should NOT Be Owned by Runner
Avoid putting general infrastructure metrics into this interface unless there is a strong reason.
For example:
- process CPU
- host memory
- container memory
- GPU utilization
- network throughput
- Kubernetes state
These are better collected by the higher-level deployment/infrastructure layer.
The Runner should focus on metrics that only it can accurately provide:
input -> queue -> model execution -> output
Suggested Initial Scope
The first implementation does not need every metric above.
The highest-value initial set is:
Runner health
state
uptime
successful/failed cycles
Input
updates received
variables received
invalid updates
Queue
current/max depth
updates coalesced
Execution
cycle latency
model.set latency
model.get latency
Output
values returned
values published
None values
publication failures
Recovery
resets
simulation failures
cached-state restores
End-to-end
input-to-output latency
These metrics cover the major failure and performance boundaries without creating excessive instrumentation.
Example API
The following is only an example of the intended API shape:
metrics = runner.get_metrics()
print(metrics.state)
print(metrics.queue.depth)
print(metrics.execution.cycles_total)
print(metrics.execution.cycle_latency_ms.p95)
Possible structure:
RunnerMetrics(
uptime_seconds=...,
state=ModelState.Idle,
input=InputMetrics(
updates_received_total=...,
variables_received_total=...,
invalid_updates_total=...,
),
queue=QueueMetrics(
depth=...,
max_depth=...,
items_enqueued_total=...,
items_coalesced_total=...,
),
execution=ExecutionMetrics(
cycles_total=...,
cycles_failed_total=...,
set_latency_ms=...,
get_latency_ms=...,
cycle_latency_ms=...,
),
output=OutputMetrics(
variables_returned_total=...,
variables_published_total=...,
none_values_total=...,
publish_failures_total=...,
),
)
The implementation does not need to use this exact schema.
Implementation Requirements
Metrics collection should add negligible overhead to the simulation path.
Prefer:
- monotonic/performance clocks for durations;
- cumulative integer counters;
- gauges for current state;
- bounded histograms or streaming statistics for latency;
- no unbounded list of individual timing samples;
- thread-safe updates;
- immutable/copy-on-read metric snapshots.
get_metrics() must be safe to call while the Runner is processing updates.
Retrieving metrics must not block model execution for a significant amount of time.
The Runner should not depend on Prometheus or any external metrics library unless there is a compelling implementation reason.
Description
Add lightweight runtime metrics collection to the
lume_pva.Runnerand expose the collected metrics through a Python method on theRunnerclass.This is not an HTTP API and the Runner does not need to expose Prometheus, OpenTelemetry, or any other monitoring protocol directly.
The higher-level application embedding the Runner should be able to call something such as:
and combine those metrics with its own application-level metrics before exposing them externally.
The intent is to instrument the work that the Runner itself owns:
Why this belongs in
RunnerThe current
Runneris the component that:update_rate;IdleandSimulating;model.reset()when requested;model.set(...);model.get(...);These are the best locations for collecting operational metrics because the higher-level application cannot reliably reconstruct them from outside the Runner.
Proposed Python Interface
Add a method on
Runner, for example:The exact name and return type can be decided during implementation.
A typed, immutable snapshot is preferred, for example:
get_metrics()should return the current snapshot and must not reset counters.A separate reset method can be added later if needed.
Metrics to Collect
1. Runner State / Health
These metrics describe whether the Runner is alive and able to process model updates.
Suggested fields:
stateidlesimulatingsimulation_activesimulation_cycles_totalsimulation_cycles_failed_totallast_simulation_started_atlast_simulation_completed_atlast_simulation_errortime_since_last_successful_simulation_secondsThe Runner already tracks
Idle/Simulating, so the metrics snapshot should reuse that state rather than create a second independent state model.The last error should be treated as diagnostic state rather than a counter. It may be omitted if exposing error text through metrics is considered undesirable.
2. Input Update Metrics
Inputs can currently arrive through several paths:
Track the source where practical.
Suggested counters:
input_updates_received_totalinput_variables_received_totalpva_puts_totalca_puts_totalremote_monitor_updates_totalsnapshot_requests_totalreset_requests_totalinvalid_input_updates_totalIt is useful to distinguish:
from:
because one queued update may contain several variables.
For example, a snapshot can update many input variables at once.
3. Queue / Backpressure Metrics
The Runner uses an internal queue and intentionally coalesces updates during the configured
update_ratewindow before starting a simulation.This makes queue metrics particularly important.
Suggested metrics:
queue_depthqueue_depth_maxqueue_items_enqueued_totalqueue_items_dequeued_totalqueue_items_coalesced_totalvariables_coalesced_totalupdate_batches_totalaverage_updates_per_batchaverage_variables_per_batchqueue_wait_time_msA key metric should show how much incoming activity is being collapsed into a single model execution.
For example:
This is important when determining whether the Runner is keeping up with incoming control-system updates.
4. End-to-End Update Latency
The Runner already associates timestamps with incoming values and propagates the newest input timestamp to the output PV updates.
Use this to measure end-to-end Runner latency.
Suggested metric:
input_to_output_latency_msConceptually:
This is one of the most useful operational metrics because it represents the delay seen by a user of the virtual accelerator.
5. Model Execution Metrics
The Runner has clearly separated execution stages around:
Collect latency independently for each stage.
Suggested metrics:
model.set()model_set_totalmodel_set_failures_totalmodel_set_latency_msmodel.get()model_get_totalmodel_get_failures_totalmodel_get_latency_msFull simulation cycle
simulation_cycle_latency_msThe full cycle should measure from the point at which the Runner starts processing a coalesced update batch until output publication is complete.
This is more useful than a generic "inference latency" metric because not every supported LUME backend is an ML inference model. The same Runner may use Bmad/Tao, surrogate models, staged models, or other LUME implementations.
6. Reset and Recovery Metrics
The Runner supports explicit model reset and also restores cached model state after a failed simulation.
Suggested metrics:
model_resets_totalmodel_reset_failures_totalmodel_reset_latency_mscached_state_restore_totalcached_state_restore_failures_totalThis makes it possible to differentiate between:
and:
7. Output Publication Metrics
After
model.get(...), the Runner iterates over returned values and publishes them through PVA and/or CA.Suggested counters:
output_variables_returned_totaloutput_variables_published_totaloutput_variables_skipped_totaloutput_none_values_totaloutput_publish_failures_totalpva_posts_totalpva_post_failures_totalca_updates_totalca_update_failures_totalAlso collect:
output_publication_latency_msThe Runner currently skips outputs whose value is
None. This should have its own counter because frequentNoneoutputs can indicate a model or configuration problem even when the simulation itself does not throw an exception.8. Put Completion Metrics
The Runner supports two put modes:
immediatecompleteWhen
completemode is used, completion callbacks are invoked after the model execution finishes.Useful metrics include:
put_completion_callbacks_totalput_completion_callback_failures_totalput_completion_latency_msThis is useful for diagnosing control clients that experience long PUT completion times or timeouts.
9. Snapshot Metrics
Snapshot mode performs synchronous reads of configured remote PVs before enqueuing the model update.
Suggested metrics:
snapshot_requests_totalsnapshot_remote_pvs_read_totalsnapshot_failures_totalsnapshot_collection_latency_msIf individual remote
get()failures can be handled independently in the future, also track:snapshot_remote_pv_read_failures_total10. Remote Input Monitor Metrics
For continuous remote input mode, updates arrive through monitor callbacks.
Suggested metrics:
remote_monitor_updates_totalremote_monitor_variables_totalOptionally, if subscription state is available:
remote_monitors_configuredremote_monitors_connectedremote_monitor_disconnects_totalConnection-level metrics should only be added if the underlying PV client exposes them reliably.
Configuration / Identity Information
The metrics snapshot should also expose enough static information for the higher-level application to identify the Runner.
Suggested fields:
ca,pva)put_moderemote_model_modeupdate_rateDo not duplicate the complete
model_infoPV payload unless needed.Metrics That Should NOT Be Owned by Runner
Avoid putting general infrastructure metrics into this interface unless there is a strong reason.
For example:
These are better collected by the higher-level deployment/infrastructure layer.
The Runner should focus on metrics that only it can accurately provide:
Suggested Initial Scope
The first implementation does not need every metric above.
The highest-value initial set is:
These metrics cover the major failure and performance boundaries without creating excessive instrumentation.
Example API
The following is only an example of the intended API shape:
Possible structure:
The implementation does not need to use this exact schema.
Implementation Requirements
Metrics collection should add negligible overhead to the simulation path.
Prefer:
get_metrics()must be safe to call while the Runner is processing updates.Retrieving metrics must not block model execution for a significant amount of time.
The Runner should not depend on Prometheus or any external metrics library unless there is a compelling implementation reason.