FlowFuse / FlowFuse/flowfuse

Remote Instance Performance Tab - Improve Feedback

Open
#6,063 6 comments 0 reactions 1 assignee Claimed by @dimitrieh View on GitHub
design size:XS task
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.