This commit is contained in:
ponzischeme89
2026-08-19 14:25:44 +12:00
parent 2b43b9ef12
commit 590e069366
83 changed files with 8948 additions and 1266 deletions
+213 -2
View File
@@ -385,9 +385,21 @@ export interface DeviceDetailResponse {
/* ---------- scheduled tasks ---------- */
/** What a run counted. Every task carries the shape; most count nothing, and a run whose
* `processed` is zero counted nothing at all — the console prints no figures rather than
* four zeroes. */
export interface RunCounts {
processed: number;
changed: number;
skipped: number;
failed: number;
}
export interface TaskRun {
id: number;
taskId: string;
/** The external service this run belongs to, absent for the gateway's own work. */
integrationId?: string;
trigger: string;
status: 'running' | 'success' | 'failed' | 'skipped';
startedAt: string;
@@ -395,6 +407,7 @@ export interface TaskRun {
durationMs: number;
detail?: string;
error?: string;
counts: RunCounts;
}
export interface ScheduledTask {
@@ -402,6 +415,8 @@ export interface ScheduledTask {
name: string;
description: string;
group: string;
/** The external service this job belongs to, absent for the gateway's own work. */
integration?: string;
intervalSeconds: number;
/** The cadence declared in code. Differs from intervalSeconds only when overridden. */
defaultIntervalSeconds: number;
@@ -419,6 +434,68 @@ export interface TasksResponse {
/* ---------- integrations ---------- */
/* The external services Memby depends on, which is a different question from the webhook
destinations below: those are places administrative events are posted to, these are
things without which parts of Memby stop working. */
export type IntegrationStatus =
| 'healthy'
| 'error'
| 'running'
| 'disabled'
| 'unconfigured'
| 'idle';
export interface IntegrationProbe {
reachable: boolean;
checkedAt: string;
error?: string;
latencyMs: number;
}
export interface IntegrationFact {
label: string;
value: string;
tone?: string;
}
export interface IntegrationService {
id: string;
name: string;
summary: string;
address?: string;
configured: boolean;
enabled: boolean;
status: IntegrationStatus;
statusLabel: string;
detail?: string;
running: boolean;
/** What stops working when this service is switched off. */
powers: string[];
lastRun?: TaskRun;
lastSuccessAt?: string;
lastFailureAt?: string;
lastError?: string;
nextRun?: string;
runs: number;
failures: number;
health?: IntegrationProbe;
/** Whether this service can be probed at all — see the MDBList note on the server. */
probed: boolean;
tasks: ScheduledTask[];
facts?: IntegrationFact[];
}
export interface IntegrationServicesResponse {
services: IntegrationService[];
runs: TaskRun[];
}
export interface IntegrationServiceResponse {
service: IntegrationService;
runs: TaskRun[];
}
export interface IntegrationHealth {
integrationId: string;
lastSuccess?: string;
@@ -514,9 +591,53 @@ export interface LogResponse {
/* ---------- runtime ---------- */
export interface RuntimeStatus {
/* The process figures, and the interpretation of them.
*
* The gateway sends the verdict rather than the console deriving one, for the reason every
* label the gateway prints is its own: the threshold and the sentence explaining it belong
* together, and a console built before a threshold existed must not be the thing deciding
* what "watch" means. See server/internal/runtimestats. */
export type RuntimeLevel = 'ok' | 'watch' | 'bad';
export type TrendDirection = 'unknown' | 'steady' | 'rising' | 'falling';
export interface RuntimeTrend {
direction: TrendDirection;
/** perHour is the observed rate of change in the value's own units — goroutines an hour,
* bytes an hour — which is what makes "rising" something to act on rather than notice. */
perHour: number;
first: number;
latest: number;
min: number;
max: number;
spanSeconds: number;
points: number;
}
export interface RuntimeSample {
at: string;
goroutines: number;
gomaxprocs: number;
heapInuse: number;
sys: number;
numGc: number;
}
export interface RuntimeNote {
level: RuntimeLevel;
/** area names the part of Memby to look at. It is the note's most useful field: a number
* that has moved is only actionable once it points somewhere. */
area: string;
message: string;
}
export interface RuntimeHealth {
level: RuntimeLevel;
summary: string;
notes?: RuntimeNote[];
areas?: string[];
}
export interface RuntimeMemory {
heapAlloc: number;
heapInuse: number;
heapIdle: number;
@@ -525,8 +646,98 @@ export interface RuntimeStatus {
sys: number;
nextGc: number;
numGc: number;
pauseTotalMs: number;
pauseRecentMs: number;
memoryLimit: number;
configuredLimit?: string;
/** heapShare is heap in use as a fraction of the limit, or 0 when there is no limit. */
heapShare: number;
gcPerHour: number;
}
export interface RuntimeWorker {
name: string;
component: string;
state: 'running' | 'finished';
started: string;
stopped?: string;
starts: number;
}
export interface RuntimeProcess {
pid: number;
cpuSeconds?: number;
cpuPercent?: number;
/** cpuKnown and filesKnown separate "nothing open" from "could not look": these come
* from /proc, which the container has and a developer machine does not. */
cpuKnown: boolean;
openFiles?: number;
openSockets?: number;
fileLimit?: number;
filesKnown: boolean;
}
export interface RuntimeStatus {
at: string;
uptimeSeconds: number;
goroutines: number;
gomaxprocs: number;
threads: number;
goVersion: string;
memory: RuntimeMemory;
workers?: RuntimeWorker[];
process: RuntimeProcess;
samples?: RuntimeSample[];
goroutineTrend: RuntimeTrend;
heapTrend: RuntimeTrend;
reservedTrend: RuntimeTrend;
sampleEverySeconds: number;
health: RuntimeHealth;
}
/* The on-demand half. Walking every goroutine's stack stops the world, so this is asked
for and never polled — which is also why it says when it was collected and what it cost. */
export interface RuntimeStateCount {
state: string;
count: number;
}
export interface RuntimeCategory {
category: string;
label: string;
description: string;
count: number;
states?: RuntimeStateCount[];
}
export interface RuntimeComponentCount {
component: string;
count: number;
longestWaitMinutes: number;
}
export interface RuntimeStackGroup {
count: number;
component: string;
category: string;
state: string;
function: string;
file: string;
createdBy?: string;
longestWaitMinutes: number;
}
export interface GoroutineReport {
at: string;
total: number;
collectedInMs: number;
dumpBytes: number;
categories?: RuntimeCategory[];
components?: RuntimeComponentCount[];
groups?: RuntimeStackGroup[];
groupsTotal: number;
workers?: RuntimeWorker[];
}
/* ---------- gateway settings ---------- */