Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion core/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ COPY configuration/motd /etc/motd

# Copy configuration files
COPY start-blueos-core /usr/bin/start-blueos-core
COPY run-service.sh /usr/bin/run-service

# Copy binaries and necessary folders from download-binaries to this stage
COPY --from=download-binaries \
Expand Down
7 changes: 7 additions & 0 deletions core/frontend/src/menus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ const menus = [
text: 'Allows creating UDP/TCP to Serial bridges, used for communication to serial'
+ ' devices from your Control Station Computer.',
},
{
title: 'Service Manager',
icon: 'mdi-cogs',
route: '/tools/service-manager',
advanced: true,
text: 'View and manage BlueOS services. Monitor logs, metrics, and control service lifecycle.',
},
{
title: 'System Information',
icon: 'mdi-chart-pie',
Expand Down
5 changes: 5 additions & 0 deletions core/frontend/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ const routes: Array<RouteConfig> = [
name: 'Zenoh Inspector',
component: defineAsyncComponent(() => import('../views/ZenohInspectorView.vue')),
},
{
path: '/tools/service-manager',
name: 'Service Manager',
component: defineAsyncComponent(() => import('../views/ServiceManagerView.vue')),
},
{
path: '/settings',
name: 'Settings',
Expand Down
75 changes: 75 additions & 0 deletions core/frontend/src/types/service-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
export interface ResourceLimits {
cpu_cores: number | null
memory_mb: number | null
io_read_mbps: number | null
io_write_mbps: number | null
max_pids: number | null
}

export interface ServiceState {
name: string
status: 'running' | 'stopped' | 'starting' | 'stopping'
pid: number | null
exit_code: number | null
started_at: string | null
stopped_at: string | null
restart_count: number
uptime_seconds: number | null
command: string[]
enabled: boolean
restart: boolean
env: Record<string, string>
cwd: string | null
restart_delay_sec: number
stop_timeout_sec: number
limits: ResourceLimits
}

export interface LogLine {
timestamp: string
stream: 'stdout' | 'stderr'
line: string
}

export interface ServiceMetrics {
timestamp: string
cpu_percent: number
memory_mb: number
memory_peak_mb: number
io_read_mb: number
io_write_mb: number
io_read_rate_mbps: number
io_write_rate_mbps: number
pids: number
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServiceMetrics TypeScript interface missing six API fields

High Severity

The ServiceMetrics interface is missing swap_mb, swap_peak_mb, net_rx_mb, net_tx_mb, net_rx_rate_mbps, and net_tx_rate_mbps. The backend's to_dict() in metrics.py returns all these fields, and the Vue component references them extensively in the template (Swap card, Network card, peak labels) and in computed properties (memoryChartSeries, networkChartSeries). With strict: true in the project's tsconfig, accessing these undeclared properties on the typed ServiceMetrics objects will fail TypeScript compilation, breaking the Swap and Network sections of the Metrics tab entirely.

Additional Locations (2)

Fix in Cursor Fix in Web


export interface ServicesResponse {
services: ServiceState[]
count: number
}

export interface ServiceLogsResponse {
service: string
lines: LogLine[]
count: number
}

export interface AllMetricsResponse {
metrics: Record<string, ServiceMetrics>
count: number
}

export interface ServiceMetricsResponse {
service: string
metrics: ServiceMetrics | null
}

export interface MessageResponse {
message: string
}

export interface HealthResponse {
status: string
services_running: number
services_total: number
}
Loading