feat(supervisor): workload create duration histogram with backend and outcome labels (#3928)
Adds a `workload_create_duration_seconds` Prometheus histogram to the supervisor, observed around the workload manager `create()` call: - `backend` label: `kubernetes` | `compute` | `docker` — set once from the configured workload manager - `outcome` label: `success` | `error` — the per-outcome counts double as a create error rate Registered on the supervisor's existing metrics registry, so it's exposed on the existing `/metrics` endpoint with no config changes. Notes: - Covers cold creates only; warm starts and restores return before reaching `create()`. - A create may include backend-internal retries, so one observation can span multiple attempts. - Fixed low cardinality: 2 active label sets per deployment × 10 buckets.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
area: supervisor
|
||||
type: improvement
|
||||
---
|
||||
|
||||
Add a `workload_create_duration_seconds` Prometheus histogram recording the duration and outcome (success/error) of workload manager create calls, labeled by backend (kubernetes/compute/docker). Previously failed creates were only visible as error logs.
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
isKubernetesEnvironment,
|
||||
} from "@trigger.dev/core/v3/serverOnly";
|
||||
import { createK8sApi } from "./clients/kubernetes.js";
|
||||
import { collectDefaultMetrics } from "prom-client";
|
||||
import { collectDefaultMetrics, Histogram } from "prom-client";
|
||||
import { register } from "./metrics.js";
|
||||
import { PodCleaner } from "./services/podCleaner.js";
|
||||
import { FailedPodHandler } from "./services/failedPodHandler.js";
|
||||
@@ -45,11 +45,20 @@ if (env.METRICS_COLLECT_DEFAULTS) {
|
||||
collectDefaultMetrics({ register });
|
||||
}
|
||||
|
||||
const workloadCreateDuration = new Histogram({
|
||||
name: "workload_create_duration_seconds",
|
||||
help: "Duration of workload manager create calls. A create may include backend-internal retries, so one observation can span multiple attempts.",
|
||||
labelNames: ["backend", "outcome"],
|
||||
buckets: [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60],
|
||||
registers: [register],
|
||||
});
|
||||
|
||||
class ManagedSupervisor {
|
||||
private readonly workerSession: SupervisorSession;
|
||||
private readonly metricsServer?: HttpServer;
|
||||
private readonly workloadServer: WorkloadServer;
|
||||
private readonly workloadManager: WorkloadManager;
|
||||
private readonly workloadManagerBackend: "compute" | "kubernetes" | "docker";
|
||||
private readonly computeManager?: ComputeWorkloadManager;
|
||||
private readonly logger = new SimpleStructuredLogger("managed-supervisor");
|
||||
private readonly resourceMonitor: ResourceMonitor;
|
||||
@@ -151,10 +160,13 @@ class ManagedSupervisor {
|
||||
});
|
||||
this.computeManager = computeManager;
|
||||
this.workloadManager = computeManager;
|
||||
this.workloadManagerBackend = "compute";
|
||||
} else if (this.isKubernetes) {
|
||||
this.workloadManager = new KubernetesWorkloadManager(workloadManagerOptions);
|
||||
this.workloadManagerBackend = "kubernetes";
|
||||
} else {
|
||||
this.workloadManager = this.isKubernetes
|
||||
? new KubernetesWorkloadManager(workloadManagerOptions)
|
||||
: new DockerWorkloadManager(workloadManagerOptions);
|
||||
this.workloadManager = new DockerWorkloadManager(workloadManagerOptions);
|
||||
this.workloadManagerBackend = "docker";
|
||||
}
|
||||
|
||||
if (this.isKubernetes) {
|
||||
@@ -493,6 +505,10 @@ class ManagedSupervisor {
|
||||
hasPrivateLink: message.organization.hasPrivateLink,
|
||||
});
|
||||
recordPhaseSince("workload_create", createStart, undefined);
|
||||
workloadCreateDuration.observe(
|
||||
{ backend: this.workloadManagerBackend, outcome: "success" },
|
||||
(performance.now() - createStart) / 1000
|
||||
);
|
||||
|
||||
// Disabled for now
|
||||
// this.resourceMonitor.blockResources({
|
||||
@@ -505,6 +521,10 @@ class ManagedSupervisor {
|
||||
createStart,
|
||||
error instanceof Error ? error : new Error(String(error))
|
||||
);
|
||||
workloadCreateDuration.observe(
|
||||
{ backend: this.workloadManagerBackend, outcome: "error" },
|
||||
(performance.now() - createStart) / 1000
|
||||
);
|
||||
this.logger.error("Failed to create workload", { error });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user