- Cyberpunk-themed Unraid dashboard - Disk usage monitoring with ring charts - System metrics (CPU, Memory, Parity) - Docker container status display - Optimized for Raspberry Pi 3 - GraphQL API integration 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
474 lines
10 KiB
Markdown
474 lines
10 KiB
Markdown
# Unraid GraphQL Schema Findings
|
|
|
|
## Investigation Date
|
|
2025-11-22
|
|
|
|
## Server Information
|
|
- **Server URL**: http://192.168.2.61:81/graphql
|
|
- **Authentication**: API Key via `x-api-key` header
|
|
|
|
## Schema Exploration Process
|
|
|
|
This document contains our findings from systematically exploring the Unraid GraphQL API schema to identify the correct fields and types for retrieving system information.
|
|
|
|
---
|
|
|
|
## Type: Info
|
|
|
|
The root `Info` type contains various system information categories.
|
|
|
|
### Available Fields
|
|
|
|
```graphql
|
|
{
|
|
"__type": {
|
|
"name": "Info",
|
|
"fields": [
|
|
{ "name": "id", "type": { "name": null } },
|
|
{ "name": "time", "type": { "name": null } },
|
|
{ "name": "baseboard", "type": { "name": null } },
|
|
{ "name": "cpu", "type": { "name": null } },
|
|
{ "name": "devices", "type": { "name": null } },
|
|
{ "name": "display", "type": { "name": null } },
|
|
{ "name": "machineId", "type": { "name": "ID" } },
|
|
{ "name": "memory", "type": { "name": null } },
|
|
{ "name": "os", "type": { "name": null } },
|
|
{ "name": "system", "type": { "name": null } },
|
|
{ "name": "versions", "type": { "name": null } }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Field Descriptions
|
|
|
|
- `id` - Identifier
|
|
- `time` - Time information (unknown structure)
|
|
- `baseboard` - Motherboard information
|
|
- `cpu` - CPU hardware information
|
|
- `devices` - Connected devices
|
|
- `display` - Display/graphics information
|
|
- `machineId` - Machine identifier (returns ID scalar)
|
|
- `memory` - Memory hardware information (NOT usage statistics)
|
|
- `os` - Operating system information
|
|
- `system` - System information (potentially contains usage stats - **needs investigation**)
|
|
- `versions` - Version information
|
|
|
|
---
|
|
|
|
## Type: InfoMemory
|
|
|
|
The `InfoMemory` type describes physical RAM hardware, NOT runtime memory usage.
|
|
|
|
### Available Fields
|
|
|
|
```graphql
|
|
{
|
|
"__type": {
|
|
"name": "InfoMemory",
|
|
"fields": [
|
|
{ "name": "id", "type": { "name": null, "kind": "NON_NULL" } },
|
|
{ "name": "layout", "type": { "name": null, "kind": "NON_NULL" } }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Field Details
|
|
|
|
- `id` - Memory identifier (required)
|
|
- `layout` - Array of `MemoryLayout` objects (required)
|
|
- Type: `[MemoryLayout!]!`
|
|
|
|
### Important Note
|
|
|
|
**This type does NOT contain the fields we initially attempted to query:**
|
|
- ❌ `total` - Does not exist
|
|
- ❌ `free` - Does not exist
|
|
- ❌ `used` - Does not exist
|
|
|
|
These field names were incorrectly assumed based on documentation examples.
|
|
|
|
---
|
|
|
|
## Type: MemoryLayout
|
|
|
|
Physical RAM module information (hardware specs, not usage).
|
|
|
|
### Available Fields
|
|
|
|
```graphql
|
|
{
|
|
"__type": {
|
|
"name": "MemoryLayout",
|
|
"fields": [
|
|
{ "name": "id", "type": { "name": null, "kind": "NON_NULL" } },
|
|
{ "name": "size", "type": { "name": null, "kind": "NON_NULL" } },
|
|
{ "name": "bank", "type": { "name": "String", "kind": "SCALAR" } },
|
|
{ "name": "type", "type": { "name": "String", "kind": "SCALAR" } },
|
|
{ "name": "clockSpeed", "type": { "name": "Int", "kind": "SCALAR" } },
|
|
{ "name": "partNum", "type": { "name": "String", "kind": "SCALAR" } },
|
|
{ "name": "serialNum", "type": { "name": "String", "kind": "SCALAR" } },
|
|
{ "name": "manufacturer", "type": { "name": "String", "kind": "SCALAR" } },
|
|
{ "name": "formFactor", "type": { "name": "String", "kind": "SCALAR" } },
|
|
{ "name": "voltageConfigured", "type": { "name": "Int", "kind": "SCALAR" } },
|
|
{ "name": "voltageMin", "type": { "name": "Int", "kind": "SCALAR" } },
|
|
{ "name": "voltageMax", "type": { "name": "Int", "kind": "SCALAR" } }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Field Descriptions
|
|
|
|
- `id` - Module identifier (required)
|
|
- `size` - RAM module size in bytes (required)
|
|
- `bank` - Memory bank location (e.g., "BANK 0")
|
|
- `type` - RAM type (e.g., "DDR4", "DDR5")
|
|
- `clockSpeed` - Operating frequency in MHz
|
|
- `partNum` - Part number
|
|
- `serialNum` - Serial number
|
|
- `manufacturer` - Manufacturer name
|
|
- `formFactor` - Physical form factor (e.g., "DIMM")
|
|
- `voltageConfigured` - Configured voltage
|
|
- `voltageMin` - Minimum voltage
|
|
- `voltageMax` - Maximum voltage
|
|
|
|
### Usage Example
|
|
|
|
```graphql
|
|
query {
|
|
info {
|
|
memory {
|
|
id
|
|
layout {
|
|
size
|
|
bank
|
|
type
|
|
manufacturer
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Purpose
|
|
|
|
This type provides hardware inventory information about installed RAM modules. It can be used to:
|
|
- Calculate total installed RAM (sum of all `size` fields)
|
|
- Display RAM configuration
|
|
- Show hardware specifications
|
|
|
|
**However, it does NOT provide:**
|
|
- Current memory usage
|
|
- Available memory
|
|
- Memory utilization percentage
|
|
|
|
---
|
|
|
|
## ✅ RESOLVED: Runtime Statistics Location
|
|
|
|
### Memory and CPU Usage Data
|
|
|
|
**Location Found:** `metrics` query root
|
|
|
|
#### Type: Metrics
|
|
|
|
The `Metrics` type provides real-time system utilization data.
|
|
|
|
**Query Structure:**
|
|
```graphql
|
|
query {
|
|
metrics {
|
|
cpu {
|
|
percentTotal
|
|
cpus {
|
|
percentTotal
|
|
percentUser
|
|
percentSystem
|
|
percentIdle
|
|
}
|
|
}
|
|
memory {
|
|
total
|
|
used
|
|
free
|
|
available
|
|
percentTotal
|
|
swapTotal
|
|
swapUsed
|
|
swapFree
|
|
percentSwapTotal
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### CpuUtilization Fields
|
|
|
|
- `percentTotal` - Overall CPU usage percentage (what we need for dashboard)
|
|
- `cpus` - Array of per-core CPU loads
|
|
|
|
#### MemoryUtilization Fields
|
|
|
|
- `total` - Total system memory in bytes
|
|
- `used` - Used memory in bytes
|
|
- `free` - Free memory in bytes
|
|
- `available` - Available memory in bytes
|
|
- `percentTotal` - Memory usage percentage (what we need for dashboard)
|
|
- `swapTotal` - Total swap memory
|
|
- `swapUsed` - Used swap memory
|
|
- `swapFree` - Free swap memory
|
|
- `percentSwapTotal` - Swap usage percentage
|
|
|
|
### Required Introspection Queries
|
|
|
|
To continue investigation, run these queries:
|
|
|
|
**1. List all available types:**
|
|
```graphql
|
|
query {
|
|
__schema {
|
|
types {
|
|
name
|
|
kind
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**2. Investigate InfoSystem type:**
|
|
```graphql
|
|
query {
|
|
__type(name: "InfoSystem") {
|
|
name
|
|
fields {
|
|
name
|
|
type {
|
|
name
|
|
kind
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**3. Search for stats-related types:**
|
|
Look through the full type list for names containing:
|
|
- Stats
|
|
- Metrics
|
|
- Usage
|
|
- Monitor
|
|
- Performance
|
|
- Resource
|
|
|
|
---
|
|
|
|
## Array Type Information
|
|
|
|
### Status
|
|
|
|
The `array` query successfully returns basic state information.
|
|
|
|
**Working Query:**
|
|
```graphql
|
|
query {
|
|
array {
|
|
state
|
|
}
|
|
}
|
|
```
|
|
|
|
### Fields to Investigate
|
|
|
|
Based on earlier attempts, we know:
|
|
- `array.state` - Works (returns array state)
|
|
- `array.capacity.disks` - Contains `free`, `used`, `total` fields
|
|
- `array.disks` - Contains `name`, `size`, `status`, `temp` fields
|
|
|
|
**Need to verify:**
|
|
- Exact structure of `capacity` field
|
|
- Whether disk arrays are parallel (same index = same disk)
|
|
- Parity information location
|
|
|
|
---
|
|
|
|
## Docker Container Information
|
|
|
|
### Status
|
|
|
|
Docker container queries appear to work.
|
|
|
|
**Working Query:**
|
|
```graphql
|
|
query {
|
|
dockerContainers {
|
|
names
|
|
state
|
|
}
|
|
}
|
|
```
|
|
|
|
### Available Fields (from earlier attempts)
|
|
|
|
- `id` - Container ID
|
|
- `names` - Container names (array)
|
|
- `state` - Container state (running/stopped/etc.)
|
|
- `status` - Status string
|
|
- `autoStart` - Auto-start configuration
|
|
|
|
**Note:** This query succeeded in earlier tests. Docker integration appears functional.
|
|
|
|
---
|
|
|
|
## Error Patterns Observed
|
|
|
|
### Pattern 1: Field Does Not Exist
|
|
|
|
```json
|
|
{
|
|
"message": "Cannot query field \"fieldName\" on type \"TypeName\"."
|
|
}
|
|
```
|
|
|
|
**Cause:** Field name is incorrect or does not exist in schema.
|
|
|
|
**Solution:** Use introspection to discover actual field names.
|
|
|
|
### Pattern 2: Missing Subfield Selection
|
|
|
|
```json
|
|
{
|
|
"message": "Field \"fieldName\" of type \"[Type!]!\" must have a selection of subfields."
|
|
}
|
|
```
|
|
|
|
**Cause:** Field returns a complex object/array but no subfields were specified.
|
|
|
|
**Solution:** Query reveals the return type - use introspection to find available subfields.
|
|
|
|
### Pattern 3: Syntax Error
|
|
|
|
```json
|
|
{
|
|
"message": "Syntax Error: Expected Name, found ."
|
|
}
|
|
```
|
|
|
|
**Cause:** Query has syntax error (extra characters, malformed structure).
|
|
|
|
**Solution:** Verify query syntax, check for copy-paste issues.
|
|
|
|
---
|
|
|
|
## Introspection Capabilities
|
|
|
|
### Confirmed Working
|
|
|
|
- `__type(name: "TypeName")` - Retrieve specific type information
|
|
- `__typename` - Get runtime type name
|
|
- Field type introspection with nested `ofType`
|
|
|
|
### Not Yet Tested
|
|
|
|
- `__schema { types }` - Full schema type list
|
|
- `queryType` / `mutationType` - Root operation types
|
|
- Subscription support
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
1. ✅ Run `__schema { types }` query to see all available types
|
|
2. ⏳ Locate memory usage statistics type
|
|
3. ⏳ Locate CPU usage statistics type
|
|
4. ⏳ Verify array and disk query structure
|
|
5. ⏳ Find parity status information
|
|
6. ⏳ Document complete working queries for all dashboard data
|
|
7. ⏳ Update dashboard JavaScript with correct queries
|
|
|
|
---
|
|
|
|
## Tools Used
|
|
|
|
- **schema-test.html** - Custom introspection and query testing tool
|
|
- Located at: `/Users/michaelsimard/dev/web/unraid-dash/schema-test.html`
|
|
- Features: Introspection queries, custom query execution, preset tests, copy-to-clipboard
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- [Unraid API Documentation](https://docs.unraid.net/API/how-to-use-the-api/)
|
|
- [GraphQL Introspection Specification](https://graphql.org/learn/introspection/)
|
|
- Project Summary: `PROJECT_SUMMARY.md`
|
|
|
|
---
|
|
|
|
## Final Working Queries for Dashboard
|
|
|
|
### Complete System Metrics Query
|
|
```graphql
|
|
query {
|
|
metrics {
|
|
cpu {
|
|
percentTotal
|
|
}
|
|
memory {
|
|
total
|
|
used
|
|
free
|
|
percentTotal
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Complete Array and Disk Query
|
|
```graphql
|
|
query {
|
|
array {
|
|
state
|
|
capacity {
|
|
disks {
|
|
free
|
|
used
|
|
total
|
|
}
|
|
}
|
|
disks {
|
|
name
|
|
size
|
|
status
|
|
temp
|
|
}
|
|
parityCheckStatus {
|
|
status
|
|
errors
|
|
date
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Complete Docker Containers Query
|
|
```graphql
|
|
query {
|
|
docker {
|
|
containers {
|
|
id
|
|
names
|
|
state
|
|
status
|
|
autoStart
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-11-22
|
|
**Status**: ✅ COMPLETE - All required queries identified and working
|
|
**Next Action**: Test dashboard with real Unraid server data
|