Remote Instance Performance Tab - Improve Feedback
- Dominant language
- JavaScript
- Stars
- 400
- Forks
- 89
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 149
Description
## The Problem
When a user creates a new instance or onboards a remote device, they often navigate to the **Performance tab** to check if their instance is working. Currently, this experience is confusing:
**For Hosted Instances:**
- The Performance tab shows "The Hosted Instance must be running in order to view performance data" with "Error: Instance is not running"
- This appears even when the instance IS actively starting up (states: `loading`, `installing`, `starting`)
- The word "Error" makes users think something is broken, when actually they just need to wait
**For Remote Instances:**
- The tab renders but shows empty charts with no explanation
- Users see blank graphs and don't know if it's broken or just waiting for data
## User Impact
1. **Confusion during onboarding** - New users checking on their instance see "Error" and think something went wrong
2. **No guidance** - Users don't know whether to wait, refresh, or troubleshoot
3. **Inconsistent experience** - Hosted and Remote instances behave differently for the same states
## Context
This was discovered during device agent onboarding testing (see [Slack thread](https://flowforgeworkspace.slack.com/archives/C032Q63FGG1/p1758871794097689?thread_ts=1758028312.143589&cid=C032Q63FGG1)). A user was trying to determine if their device was "doing something" during installation, and the Performance tab provided no useful feedback.
**Important technical note** (from @hardillb): Performance data comes from a plugin inside Node-RED, not from the launcher. During `installing`/`starting` states, there won't be actual data - but we should still allow the tab to render with a helpful message explaining why.
## Expected Behavior
- The Performance tab should be accessible during startup states
- State-specific messages should explain what's happening and when data will appear
- The word "Error" should only appear for actual errors, not expected waiting states
---
## Current Behavior
| Status | Badge Icon | Hosted Tab | Hosted Message | Remote Tab | Remote Message |
|--------|------------|------------|----------------|------------|----------------|
| **Startup Transitions** |
| `loading` | `CloudUploadIcon` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Empty charts, no explanation |
| `installing` | `AnimIconInstalling` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Empty charts, no explanation |
| `starting` | `AnimIconStarting` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Empty charts, no explanation |
| `importing` | `AnimIconInstalling` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Empty charts, no explanation |
| **Running** |
| `running` | `PlayIcon` | ✅ Shows data | - | ✅ Shows data | - |
| **Active Operations** |
| `updating` | `AnimIconInstalling` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Data may be stale |
| `pushing` | `AnimIconPushing` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Shows data |
| `pulling` | `AnimIconPulling` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Shows data |
| `restarting` | `AnimIconRestarting` | ❌ Blocked | "Error: Instance is not running" | ✅ Allowed | Data may be stale |
| **Stopped States** |
| `stopped` | `ExclamationIcon` | ❌ Blocked | "Error: Instance is not running" | ❌ Blocked | Generic empty state |
| `suspended` | `ExclamationIcon` | ❌ Blocked | "Error: Instance is not running" | ❌ Blocked | Generic empty state |
| **Error States** |
| `error` | `ExclamationCircleIcon` | ❌ Blocked | "Error: Instance is not running" | ❌ Blocked | Generic empty state |
| `crashed` | `ExclamationCircleIcon` | ❌ Blocked | "Error: Instance is not running" | ❌ Blocked | Generic empty state |
---
## Solution
### Hosted Instances - Changes Needed
| Status | Current | Change To | Message |
|--------|---------|-----------|---------|
| `loading` | ❌ Blocked | ✅ Allow | "Setting up environment... data available once Node-RED starts" |
| `installing` | ❌ Blocked | ✅ Allow | "Installing packages... data available once Node-RED starts" |
| `starting` | ❌ Blocked | ✅ Allow | "Starting Node-RED... data available shortly" |
| `importing` | ❌ Blocked | ✅ Allow | "Importing flows... data available shortly" |
| `updating` | ❌ Blocked | ✅ Allow | "Updating instance... please wait" |
| `pushing` | ❌ Blocked | ✅ Allow | *(show charts)* |
| `pulling` | ❌ Blocked | ✅ Allow | *(show charts)* |
| `restarting` | ❌ Blocked | ✅ Allow | "Restarting... data will return shortly" |
| `running` | ✅ Allow | No change | *(show charts)* |
| `stopped` | ❌ Blocked | No change | "Instance stopped. Start it to view data." |
| `suspended` | ❌ Blocked | No change | "Instance suspended. Resume to view data." |
| `error` | ❌ Blocked | No change | "Error occurred. Check Node-RED Logs." |
| `crashed` | ❌ Blocked | No change | "Instance crashed. Check Node-RED Logs." |
### Remote Instances - Changes Needed
| Status | Current | Change To | Message |
|--------|---------|-----------|---------|
| `loading` | ✅ Allowed (no message) | No change | Add: "Setting up environment... data available once Node-RED starts" |
| `installing` | ✅ Allowed (no message) | No change | Add: "Installing packages... data available once Node-RED starts" |
| `starting` | ✅ Allowed (no message) | No change | Add: "Starting Node-RED... data available shortly" |
| `importing` | ✅ Allowed (no message) | No change | Add: "Importing flows... data available shortly" |
| `updating` | ✅ Allowed | No change | Add: "Updating instance... please wait" |
| `pushing` | ✅ Allowed | No change | No change |
| `pulling` | ✅ Allowed | No change | No change |
| `restarting` | ✅ Allowed | No change | Add: "Restarting... data will return shortly" |
| `running` | ✅ Allowed | No change | No change |
| `stopped` | ❌ Blocked (generic) | No change | "Instance stopped. Start it to view data." |
| `suspended` | ❌ Blocked (generic) | No change | "Instance suspended. Resume to view data." |
| `error` | ❌ Blocked (generic) | No change | "Error occurred. Check Node-RED Logs." |
| `crashed` | ❌ Blocked (generic) | No change | "Instance crashed. Check Node-RED Logs." |
### Summary of Changes
| Component | File | Access Logic Change | Message Change |
|-----------|------|--------------------|-----------------|
| **Hosted** | `frontend/src/pages/instance/Performance/index.vue` | Yes - change from `=== 'running'` to blocklist | Yes - state-specific messages |
| **Remote** | `frontend/src/pages/device/components/DevicePerformance.vue` | No - already permissive | Yes - state-specific messages |
---
Technical Details
### Current Logic
**Hosted Instance** (`Performance/index.vue:161-162`):
```javascript
isInstanceRunning () {
return this.instance.meta.state === 'running' // Very strict
}
```
**Remote Instance** (`DevicePerformance.vue:119-121`):
```javascript
deviceOnline () {
const offline = ['stopped', 'offline', 'error']
return !offline.includes(this.device.status) // Permissive
}
```
### Proposed Logic (Hosted)
```javascript
isInstanceAvailable () {
const unavailable = ['stopped', 'suspended', 'error', 'crashed']
return !unavailable.includes(this.instance.meta.state)
}
```
Contributor guide
Assessment
This issue has not been assessed yet.