@shipfox/api-runners 12.4.0 → 12.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +14 -0
- package/dist/core/errors.d.ts +5 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +9 -2
- package/dist/core/errors.js.map +1 -1
- package/dist/core/runner-control-sessions.d.ts.map +1 -1
- package/dist/core/runner-control-sessions.js +62 -12
- package/dist/core/runner-control-sessions.js.map +1 -1
- package/dist/db/job-executions.d.ts.map +1 -1
- package/dist/db/job-executions.js +35 -4
- package/dist/db/job-executions.js.map +1 -1
- package/dist/db/runner-assignments.d.ts +8 -1
- package/dist/db/runner-assignments.d.ts.map +1 -1
- package/dist/db/runner-assignments.js +57 -10
- package/dist/db/runner-assignments.js.map +1 -1
- package/dist/db/runner-instances.d.ts +9 -0
- package/dist/db/runner-instances.d.ts.map +1 -1
- package/dist/db/runner-instances.js +43 -0
- package/dist/db/runner-instances.js.map +1 -1
- package/dist/db/runner-sessions.d.ts.map +1 -1
- package/dist/db/runner-sessions.js +14 -1
- package/dist/db/runner-sessions.js.map +1 -1
- package/dist/metrics/index.d.ts +2 -2
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +1 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/instance.d.ts +48 -0
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +138 -1
- package/dist/metrics/instance.js.map +1 -1
- package/dist/metrics/service.d.ts.map +1 -1
- package/dist/metrics/service.js +25 -4
- package/dist/metrics/service.js.map +1 -1
- package/dist/presentation/routes/assign-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/assign-runner-instances.js +7 -1
- package/dist/presentation/routes/assign-runner-instances.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/core/errors.ts +30 -1
- package/src/core/runner-control-sessions.test.ts +71 -0
- package/src/core/runner-control-sessions.ts +79 -10
- package/src/db/job-executions.test.ts +98 -12
- package/src/db/job-executions.ts +52 -4
- package/src/db/runner-assignments.ts +67 -16
- package/src/db/runner-instances.test.ts +92 -0
- package/src/db/runner-instances.ts +74 -0
- package/src/db/runner-sessions.ts +19 -1
- package/src/metrics/index.ts +14 -0
- package/src/metrics/instance.test.ts +118 -0
- package/src/metrics/instance.ts +188 -1
- package/src/metrics/service.test.ts +38 -0
- package/src/metrics/service.ts +55 -8
- package/src/presentation/routes/assign-runner-instances.ts +8 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/metrics/instance.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/metrics/instance.ts"],"names":[],"mappings":"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"}
|
package/dist/metrics/instance.js
CHANGED
|
@@ -1,5 +1,96 @@
|
|
|
1
|
-
import { instanceMetrics } from '@shipfox/node-opentelemetry';
|
|
1
|
+
import { instanceMetrics, logger } from '@shipfox/node-opentelemetry';
|
|
2
2
|
const meter = instanceMetrics.getMeter('runners');
|
|
3
|
+
export const UNKNOWN_PROVIDER_KIND = 'unknown';
|
|
4
|
+
const lifecycleDurationBuckets = {
|
|
5
|
+
long: [
|
|
6
|
+
100,
|
|
7
|
+
500,
|
|
8
|
+
1_000,
|
|
9
|
+
5_000,
|
|
10
|
+
10_000,
|
|
11
|
+
15_000,
|
|
12
|
+
20_000,
|
|
13
|
+
30_000,
|
|
14
|
+
45_000,
|
|
15
|
+
60_000,
|
|
16
|
+
90_000,
|
|
17
|
+
120_000,
|
|
18
|
+
300_000,
|
|
19
|
+
600_000
|
|
20
|
+
],
|
|
21
|
+
short: [
|
|
22
|
+
10,
|
|
23
|
+
25,
|
|
24
|
+
50,
|
|
25
|
+
100,
|
|
26
|
+
250,
|
|
27
|
+
500,
|
|
28
|
+
1_000,
|
|
29
|
+
5_000,
|
|
30
|
+
10_000
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
const queueTimeBucketsMilliseconds = [
|
|
34
|
+
100,
|
|
35
|
+
500,
|
|
36
|
+
1_000,
|
|
37
|
+
5_000,
|
|
38
|
+
10_000,
|
|
39
|
+
15_000,
|
|
40
|
+
20_000,
|
|
41
|
+
30_000,
|
|
42
|
+
45_000,
|
|
43
|
+
60_000,
|
|
44
|
+
90_000,
|
|
45
|
+
120_000,
|
|
46
|
+
300_000,
|
|
47
|
+
600_000,
|
|
48
|
+
900_000,
|
|
49
|
+
1_800_000,
|
|
50
|
+
3_600_000,
|
|
51
|
+
7_200_000,
|
|
52
|
+
14_400_000
|
|
53
|
+
];
|
|
54
|
+
// Keep the ordered lifecycle phases as separate histograms so long boot times do not flatten
|
|
55
|
+
// short handoffs. Assignment is the only phase with a surface dimension.
|
|
56
|
+
export const providerRunnerCreatedToControlSessionDuration = meter.createHistogram('runners_provider_runner_created_to_control_session', {
|
|
57
|
+
description: 'Provider runner row creation to control-session creation duration',
|
|
58
|
+
unit: 'ms',
|
|
59
|
+
advice: {
|
|
60
|
+
explicitBucketBoundaries: lifecycleDurationBuckets.long
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
export const providerRunnerControlSessionToAssignmentDuration = meter.createHistogram('runners_provider_runner_control_session_to_assignment', {
|
|
64
|
+
description: 'Provider runner control-session creation to reservation assignment duration',
|
|
65
|
+
unit: 'ms',
|
|
66
|
+
advice: {
|
|
67
|
+
explicitBucketBoundaries: lifecycleDurationBuckets.long
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
export const providerRunnerAssignmentToActivationDuration = meter.createHistogram('runners_provider_runner_assignment_to_activation', {
|
|
71
|
+
description: 'Provider runner reservation assignment to workspace runner-session creation duration',
|
|
72
|
+
unit: 'ms',
|
|
73
|
+
advice: {
|
|
74
|
+
explicitBucketBoundaries: lifecycleDurationBuckets.short
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
export const providerRunnerActivationToFirstClaimDuration = meter.createHistogram('runners_provider_runner_activation_to_first_claim', {
|
|
78
|
+
description: 'Provider runner workspace runner-session creation to first job claim duration',
|
|
79
|
+
unit: 'ms',
|
|
80
|
+
advice: {
|
|
81
|
+
explicitBucketBoundaries: lifecycleDurationBuckets.short
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
export const jobExecutionQueueTimeDuration = meter.createHistogram('runners_job_execution_queue_time', {
|
|
85
|
+
description: 'Job execution pending queue duration from enqueue to runner claim',
|
|
86
|
+
unit: 'ms',
|
|
87
|
+
advice: {
|
|
88
|
+
explicitBucketBoundaries: queueTimeBucketsMilliseconds
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
export const providerRunnerAssignmentRejectedCount = meter.createCounter('runners_provider_runner_assignment_rejected', {
|
|
92
|
+
description: 'Provider runner assignment operations rejected by bounded reason and surface'
|
|
93
|
+
});
|
|
3
94
|
export const jobExecutionEnqueuedCount = meter.createCounter('runners_job_execution_enqueued', {
|
|
4
95
|
description: 'Job executions added to the pending queue'
|
|
5
96
|
});
|
|
@@ -64,6 +155,52 @@ function recordMetric(record) {
|
|
|
64
155
|
// Metrics must not affect runner or provisioner request outcomes.
|
|
65
156
|
}
|
|
66
157
|
}
|
|
158
|
+
function resolveProviderRunnerMetricProvider(params) {
|
|
159
|
+
if (params.provider) return params.provider;
|
|
160
|
+
logger().debug({
|
|
161
|
+
runnerInstanceId: params.runnerInstanceId
|
|
162
|
+
}, 'Provider runner metric missing provider kind');
|
|
163
|
+
return UNKNOWN_PROVIDER_KIND;
|
|
164
|
+
}
|
|
165
|
+
export function recordProviderRunnerCreatedToControlSession(params) {
|
|
166
|
+
if (params.durationMilliseconds < 0) return;
|
|
167
|
+
recordMetric(()=>providerRunnerCreatedToControlSessionDuration.record(params.durationMilliseconds, {
|
|
168
|
+
provider: resolveProviderRunnerMetricProvider(params),
|
|
169
|
+
launch_kind: params.launchKind
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
export function recordProviderRunnerControlSessionToAssignment(params) {
|
|
173
|
+
if (params.durationMilliseconds < 0) return;
|
|
174
|
+
recordMetric(()=>providerRunnerControlSessionToAssignmentDuration.record(params.durationMilliseconds, {
|
|
175
|
+
provider: resolveProviderRunnerMetricProvider(params),
|
|
176
|
+
launch_kind: params.launchKind,
|
|
177
|
+
surface: params.surface
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
export function recordProviderRunnerAssignmentToActivation(params) {
|
|
181
|
+
if (params.durationMilliseconds < 0) return;
|
|
182
|
+
recordMetric(()=>providerRunnerAssignmentToActivationDuration.record(params.durationMilliseconds, {
|
|
183
|
+
provider: resolveProviderRunnerMetricProvider(params),
|
|
184
|
+
launch_kind: params.launchKind
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
export function recordProviderRunnerActivationToFirstClaim(params) {
|
|
188
|
+
if (params.durationMilliseconds < 0) return;
|
|
189
|
+
recordMetric(()=>providerRunnerActivationToFirstClaimDuration.record(params.durationMilliseconds, {
|
|
190
|
+
provider: resolveProviderRunnerMetricProvider(params),
|
|
191
|
+
launch_kind: params.launchKind
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
export function recordJobExecutionQueueTime(params) {
|
|
195
|
+
if (params.durationMilliseconds < 0) return;
|
|
196
|
+
recordMetric(()=>jobExecutionQueueTimeDuration.record(params.durationMilliseconds, {
|
|
197
|
+
provider: params.provider ?? UNKNOWN_PROVIDER_KIND,
|
|
198
|
+
launch_kind: params.launchKind
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
export function recordProviderRunnerAssignmentRejected(params) {
|
|
202
|
+
recordMetric(()=>providerRunnerAssignmentRejectedCount.add(1, params));
|
|
203
|
+
}
|
|
67
204
|
export function recordRunnerReservationPromotionFailure(reason) {
|
|
68
205
|
recordMetric(()=>runnerReservationPromotionFailureCount.add(1, {
|
|
69
206
|
reason
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import {instanceMetrics} from '@shipfox/node-opentelemetry';\n\nconst meter = instanceMetrics.getMeter('runners');\n\nexport const jobExecutionEnqueuedCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_enqueued',\n {\n description: 'Job executions added to the pending queue',\n },\n);\n\nexport const jobExecutionClaimedCount = meter.createCounter<{outcome: 'claimed' | 'empty'}>(\n 'runners_job_execution_claimed',\n {description: 'Job execution claim attempts by outcome'},\n);\n\nexport const jobExecutionLeaseExpiredCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_lease_expired',\n {description: 'Job execution leases reaped after passing the heartbeat threshold'},\n);\n\nexport const providerRunnerReportCount = meter.createCounter<{\n state: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'terminated';\n}>('runners_provider_runner_reported', {\n description: 'Provisioned runner lifecycle reports accepted by state',\n});\n\nexport const runnerBootstrapExchangeCount = meter.createCounter<{\n outcome: 'accepted' | 'rejected';\n}>('runners_runner_bootstrap_exchange', {\n description: 'Runner bootstrap-token exchanges by outcome',\n});\n\nexport type RunnerActivationTokenNotIssuedReason =\n | 'runner-not-found'\n | 'missing-workspace'\n | 'existing-session'\n | 'not-running';\n\nexport type RunnerActivationTokenNotIssuedSurface = 'enrollment' | 'poll';\n\nexport const runnerActivationTokenNotIssuedCount = meter.createCounter<{\n reason: RunnerActivationTokenNotIssuedReason;\n surface: RunnerActivationTokenNotIssuedSurface;\n}>('runners_runner_activation_token_not_issued', {\n description: 'Runner activation token issuance skips by reason and surface',\n});\n\nexport const runnerControlHeartbeatCount = meter.createCounter<Record<string, never>>(\n 'runners_runner_control_heartbeat',\n {description: 'Pre-workspace runner-control heartbeats accepted'},\n);\n\nexport const providerRunnerReapedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reaped',\n {\n description: 'Stale provisioned runners marked failed by backend maintenance',\n },\n);\n\nexport const providerRunnerCountDivergenceCount = meter.createCounter<{\n template_key?: string;\n state: 'starting' | 'running';\n direction: 'backend-higher' | 'advertised-higher';\n}>('runners_provider_runner_count_divergence', {\n description:\n 'Absolute difference between provisioner-advertised and backend-observed provisioned runner counts',\n});\n\nexport const providerRunnerReconcileCallCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reconcile_called',\n {description: 'Provisioned runner reconcile calls completed successfully'},\n);\n\nexport const providerRunnerAbsentTerminatedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_absent_terminated',\n {\n description:\n 'Owned provisioned runners marked terminated because they were absent from reconcile',\n },\n);\n\nexport const providerRunnerTerminateIntentIssuedCount = meter.createCounter<{\n surface: 'poll-demand' | 'reconcile';\n reason: 'activation-timeout' | 'job-cancelled' | 'terminal-state';\n}>('runners_provider_runner_terminate_intent_issued', {\n description: 'Provisioned runner terminate intents returned to provisioners',\n});\n\nexport const providerRunnerTerminateIntentHonoredCount = meter.createCounter<{\n reason: 'activation-timeout' | 'job-cancelled';\n}>('runners_provider_runner_terminate_intent_honored', {\n description: 'Provisioned runner terminate intents honored by first transition to terminated',\n});\n\nexport const providerRunnerActivationOutcomeCount = meter.createCounter<{\n outcome: 'reaped' | 'rebound';\n}>('runners_provider_runner_activation_outcome', {\n description: 'Demand-backed runner activation outcomes by recovery action',\n});\n\nexport const reservationReleasedCount = meter.createCounter<Record<string, never>>(\n 'runners_reservation_released',\n {description: 'Reservation units released from terminal provisioned runner reports'},\n);\n\nexport type RunnerReservationPromotionFailureReason =\n | 'reservation-expired'\n | 'reservation-not-found'\n | 'already-assigned'\n | 'not-assignable';\n\nexport const runnerReservationPromotionFailureCount = meter.createCounter<{\n reason: RunnerReservationPromotionFailureReason;\n}>('runners_reservation_promotion_failures', {\n description: 'Runner reservation promotion failures during enrollment by reason',\n});\n\nexport type RunnerReservationCapacityFailureReason =\n | 'reservation-not-found'\n | 'reservation-kind-mismatch'\n | 'reservation-expired'\n | 'capacity-exhausted';\n\nexport const runnerReservationCapacityFailureCount = meter.createCounter<{\n reason: RunnerReservationCapacityFailureReason;\n}>('runners_reservation_capacity_failures', {\n description: 'Runner reservation admission shortfalls by reason',\n});\n\nexport type RunnersRateLimitAction = 'provisioner-mint' | 'ephemeral-register';\nexport type RunnersRateLimitScope = 'provisioner' | 'ephemeral-token';\nexport type RunnersRateLimitOutcome = 'allowed' | 'blocked' | 'unavailable';\n\nconst rateLimitCheckCount = meter.createCounter<{\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}>('runners_rate_limit_checks', {\n description: 'Runners rate limit checks by action, scope, and outcome',\n});\n\nconst rateLimitPruneFailureCount = meter.createCounter('runners_rate_limit_prune_failures', {\n description: 'Runners rate limit prune failures',\n});\n\nfunction recordMetric(record: () => void): void {\n try {\n record();\n } catch {\n // Metrics must not affect runner or provisioner request outcomes.\n }\n}\n\nexport function recordRunnerReservationPromotionFailure(\n reason: RunnerReservationPromotionFailureReason,\n): void {\n recordMetric(() => runnerReservationPromotionFailureCount.add(1, {reason}));\n}\n\nexport function recordRunnerActivationTokenNotIssued(params: {\n reason: RunnerActivationTokenNotIssuedReason;\n surface: RunnerActivationTokenNotIssuedSurface;\n}): void {\n recordMetric(() => runnerActivationTokenNotIssuedCount.add(1, params));\n}\n\nexport function recordRunnerReservationCapacityFailure(\n reason: RunnerReservationCapacityFailureReason,\n count: number,\n): void {\n if (count <= 0) return;\n recordMetric(() => runnerReservationCapacityFailureCount.add(count, {reason}));\n}\n\nexport function recordRunnersRateLimitCheck(params: {\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}): void {\n recordMetric(() =>\n rateLimitCheckCount.add(1, {\n action: params.action,\n scope: params.scope,\n outcome: params.outcome,\n }),\n );\n}\n\nexport function recordRunnersRateLimitPruneFailure(): void {\n recordMetric(() => rateLimitPruneFailureCount.add(1));\n}\n\nexport function recordProviderRunnerActivationOutcome(params: {\n outcome: 'reaped' | 'rebound';\n count?: number;\n}): void {\n recordMetric(() =>\n providerRunnerActivationOutcomeCount.add(params.count ?? 1, {outcome: params.outcome}),\n );\n}\n"],"names":["instanceMetrics","meter","getMeter","jobExecutionEnqueuedCount","createCounter","description","jobExecutionClaimedCount","jobExecutionLeaseExpiredCount","providerRunnerReportCount","runnerBootstrapExchangeCount","runnerActivationTokenNotIssuedCount","runnerControlHeartbeatCount","providerRunnerReapedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerAbsentTerminatedCount","providerRunnerTerminateIntentIssuedCount","providerRunnerTerminateIntentHonoredCount","providerRunnerActivationOutcomeCount","reservationReleasedCount","runnerReservationPromotionFailureCount","runnerReservationCapacityFailureCount","rateLimitCheckCount","rateLimitPruneFailureCount","recordMetric","record","recordRunnerReservationPromotionFailure","reason","add","recordRunnerActivationTokenNotIssued","params","recordRunnerReservationCapacityFailure","count","recordRunnersRateLimitCheck","action","scope","outcome","recordRunnersRateLimitPruneFailure","recordProviderRunnerActivationOutcome"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import {instanceMetrics, logger} from '@shipfox/node-opentelemetry';\nimport type {RunnerAssignmentRejectionReason} from '#core/errors.js';\n\nconst meter = instanceMetrics.getMeter('runners');\n\nexport type RunnerLaunchKind = 'demand' | 'warm' | 'manual';\nexport type RunnerAssignmentSurface = 'provisioner' | 'enrollment';\n\ntype ProviderRunnerLifecycleLabels = {\n provider: string;\n launch_kind: RunnerLaunchKind;\n};\n\ntype ProviderRunnerAssignmentLifecycleLabels = ProviderRunnerLifecycleLabels & {\n surface: RunnerAssignmentSurface;\n};\n\ntype JobExecutionQueueTimeLabels = {\n provider: string;\n launch_kind: RunnerLaunchKind | 'unknown';\n};\n\nexport interface JobExecutionQueueTimeObservation {\n durationMilliseconds: number;\n provider: string | null;\n launchKind: RunnerLaunchKind | 'unknown';\n}\n\nexport interface ProviderRunnerLifecycleObservation {\n durationMilliseconds: number;\n provider: string | null;\n launchKind: RunnerLaunchKind;\n runnerInstanceId?: string;\n}\n\nexport interface ProviderRunnerAssignmentObservation extends ProviderRunnerLifecycleObservation {\n surface: RunnerAssignmentSurface;\n}\n\nexport const UNKNOWN_PROVIDER_KIND = 'unknown';\n\nconst lifecycleDurationBuckets = {\n long: [\n 100, 500, 1_000, 5_000, 10_000, 15_000, 20_000, 30_000, 45_000, 60_000, 90_000, 120_000,\n 300_000, 600_000,\n ],\n short: [10, 25, 50, 100, 250, 500, 1_000, 5_000, 10_000],\n};\n\nconst queueTimeBucketsMilliseconds = [\n 100, 500, 1_000, 5_000, 10_000, 15_000, 20_000, 30_000, 45_000, 60_000, 90_000, 120_000, 300_000,\n 600_000, 900_000, 1_800_000, 3_600_000, 7_200_000, 14_400_000,\n];\n\n// Keep the ordered lifecycle phases as separate histograms so long boot times do not flatten\n// short handoffs. Assignment is the only phase with a surface dimension.\nexport const providerRunnerCreatedToControlSessionDuration =\n meter.createHistogram<ProviderRunnerLifecycleLabels>(\n 'runners_provider_runner_created_to_control_session',\n {\n description: 'Provider runner row creation to control-session creation duration',\n unit: 'ms',\n advice: {explicitBucketBoundaries: lifecycleDurationBuckets.long},\n },\n );\n\nexport const providerRunnerControlSessionToAssignmentDuration =\n meter.createHistogram<ProviderRunnerAssignmentLifecycleLabels>(\n 'runners_provider_runner_control_session_to_assignment',\n {\n description: 'Provider runner control-session creation to reservation assignment duration',\n unit: 'ms',\n advice: {explicitBucketBoundaries: lifecycleDurationBuckets.long},\n },\n );\n\nexport const providerRunnerAssignmentToActivationDuration =\n meter.createHistogram<ProviderRunnerLifecycleLabels>(\n 'runners_provider_runner_assignment_to_activation',\n {\n description:\n 'Provider runner reservation assignment to workspace runner-session creation duration',\n unit: 'ms',\n advice: {explicitBucketBoundaries: lifecycleDurationBuckets.short},\n },\n );\n\nexport const providerRunnerActivationToFirstClaimDuration =\n meter.createHistogram<ProviderRunnerLifecycleLabels>(\n 'runners_provider_runner_activation_to_first_claim',\n {\n description: 'Provider runner workspace runner-session creation to first job claim duration',\n unit: 'ms',\n advice: {explicitBucketBoundaries: lifecycleDurationBuckets.short},\n },\n );\n\nexport const jobExecutionQueueTimeDuration = meter.createHistogram<JobExecutionQueueTimeLabels>(\n 'runners_job_execution_queue_time',\n {\n description: 'Job execution pending queue duration from enqueue to runner claim',\n unit: 'ms',\n advice: {explicitBucketBoundaries: queueTimeBucketsMilliseconds},\n },\n);\n\nexport const providerRunnerAssignmentRejectedCount = meter.createCounter<{\n reason: RunnerAssignmentRejectionReason;\n surface: RunnerAssignmentSurface;\n}>('runners_provider_runner_assignment_rejected', {\n description: 'Provider runner assignment operations rejected by bounded reason and surface',\n});\n\nexport const jobExecutionEnqueuedCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_enqueued',\n {\n description: 'Job executions added to the pending queue',\n },\n);\n\nexport const jobExecutionClaimedCount = meter.createCounter<{outcome: 'claimed' | 'empty'}>(\n 'runners_job_execution_claimed',\n {description: 'Job execution claim attempts by outcome'},\n);\n\nexport const jobExecutionLeaseExpiredCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_lease_expired',\n {description: 'Job execution leases reaped after passing the heartbeat threshold'},\n);\n\nexport const providerRunnerReportCount = meter.createCounter<{\n state: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'terminated';\n}>('runners_provider_runner_reported', {\n description: 'Provisioned runner lifecycle reports accepted by state',\n});\n\nexport const runnerBootstrapExchangeCount = meter.createCounter<{\n outcome: 'accepted' | 'rejected';\n}>('runners_runner_bootstrap_exchange', {\n description: 'Runner bootstrap-token exchanges by outcome',\n});\n\nexport type RunnerActivationTokenNotIssuedReason =\n | 'runner-not-found'\n | 'missing-workspace'\n | 'existing-session'\n | 'not-running';\n\nexport type RunnerActivationTokenNotIssuedSurface = 'enrollment' | 'poll';\n\nexport const runnerActivationTokenNotIssuedCount = meter.createCounter<{\n reason: RunnerActivationTokenNotIssuedReason;\n surface: RunnerActivationTokenNotIssuedSurface;\n}>('runners_runner_activation_token_not_issued', {\n description: 'Runner activation token issuance skips by reason and surface',\n});\n\nexport const runnerControlHeartbeatCount = meter.createCounter<Record<string, never>>(\n 'runners_runner_control_heartbeat',\n {description: 'Pre-workspace runner-control heartbeats accepted'},\n);\n\nexport const providerRunnerReapedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reaped',\n {\n description: 'Stale provisioned runners marked failed by backend maintenance',\n },\n);\n\nexport const providerRunnerCountDivergenceCount = meter.createCounter<{\n template_key?: string;\n state: 'starting' | 'running';\n direction: 'backend-higher' | 'advertised-higher';\n}>('runners_provider_runner_count_divergence', {\n description:\n 'Absolute difference between provisioner-advertised and backend-observed provisioned runner counts',\n});\n\nexport const providerRunnerReconcileCallCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reconcile_called',\n {description: 'Provisioned runner reconcile calls completed successfully'},\n);\n\nexport const providerRunnerAbsentTerminatedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_absent_terminated',\n {\n description:\n 'Owned provisioned runners marked terminated because they were absent from reconcile',\n },\n);\n\nexport const providerRunnerTerminateIntentIssuedCount = meter.createCounter<{\n surface: 'poll-demand' | 'reconcile';\n reason: 'activation-timeout' | 'job-cancelled' | 'terminal-state';\n}>('runners_provider_runner_terminate_intent_issued', {\n description: 'Provisioned runner terminate intents returned to provisioners',\n});\n\nexport const providerRunnerTerminateIntentHonoredCount = meter.createCounter<{\n reason: 'activation-timeout' | 'job-cancelled';\n}>('runners_provider_runner_terminate_intent_honored', {\n description: 'Provisioned runner terminate intents honored by first transition to terminated',\n});\n\nexport const providerRunnerActivationOutcomeCount = meter.createCounter<{\n outcome: 'reaped' | 'rebound';\n}>('runners_provider_runner_activation_outcome', {\n description: 'Demand-backed runner activation outcomes by recovery action',\n});\n\nexport const reservationReleasedCount = meter.createCounter<Record<string, never>>(\n 'runners_reservation_released',\n {description: 'Reservation units released from terminal provisioned runner reports'},\n);\n\nexport type RunnerReservationPromotionFailureReason =\n | 'reservation-expired'\n | 'reservation-not-found'\n | 'already-assigned'\n | 'not-assignable';\n\nexport const runnerReservationPromotionFailureCount = meter.createCounter<{\n reason: RunnerReservationPromotionFailureReason;\n}>('runners_reservation_promotion_failures', {\n description: 'Runner reservation promotion failures during enrollment by reason',\n});\n\nexport type RunnerReservationCapacityFailureReason =\n | 'reservation-not-found'\n | 'reservation-kind-mismatch'\n | 'reservation-expired'\n | 'capacity-exhausted';\n\nexport const runnerReservationCapacityFailureCount = meter.createCounter<{\n reason: RunnerReservationCapacityFailureReason;\n}>('runners_reservation_capacity_failures', {\n description: 'Runner reservation admission shortfalls by reason',\n});\n\nexport type RunnersRateLimitAction = 'provisioner-mint' | 'ephemeral-register';\nexport type RunnersRateLimitScope = 'provisioner' | 'ephemeral-token';\nexport type RunnersRateLimitOutcome = 'allowed' | 'blocked' | 'unavailable';\n\nconst rateLimitCheckCount = meter.createCounter<{\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}>('runners_rate_limit_checks', {\n description: 'Runners rate limit checks by action, scope, and outcome',\n});\n\nconst rateLimitPruneFailureCount = meter.createCounter('runners_rate_limit_prune_failures', {\n description: 'Runners rate limit prune failures',\n});\n\nfunction recordMetric(record: () => void): void {\n try {\n record();\n } catch {\n // Metrics must not affect runner or provisioner request outcomes.\n }\n}\n\nfunction resolveProviderRunnerMetricProvider(params: {\n provider: string | null;\n runnerInstanceId?: string;\n}): string {\n if (params.provider) return params.provider;\n logger().debug(\n {runnerInstanceId: params.runnerInstanceId},\n 'Provider runner metric missing provider kind',\n );\n return UNKNOWN_PROVIDER_KIND;\n}\n\nexport function recordProviderRunnerCreatedToControlSession(\n params: ProviderRunnerLifecycleObservation,\n): void {\n if (params.durationMilliseconds < 0) return;\n recordMetric(() =>\n providerRunnerCreatedToControlSessionDuration.record(params.durationMilliseconds, {\n provider: resolveProviderRunnerMetricProvider(params),\n launch_kind: params.launchKind,\n }),\n );\n}\n\nexport function recordProviderRunnerControlSessionToAssignment(\n params: ProviderRunnerAssignmentObservation,\n): void {\n if (params.durationMilliseconds < 0) return;\n recordMetric(() =>\n providerRunnerControlSessionToAssignmentDuration.record(params.durationMilliseconds, {\n provider: resolveProviderRunnerMetricProvider(params),\n launch_kind: params.launchKind,\n surface: params.surface,\n }),\n );\n}\n\nexport function recordProviderRunnerAssignmentToActivation(\n params: ProviderRunnerLifecycleObservation,\n): void {\n if (params.durationMilliseconds < 0) return;\n recordMetric(() =>\n providerRunnerAssignmentToActivationDuration.record(params.durationMilliseconds, {\n provider: resolveProviderRunnerMetricProvider(params),\n launch_kind: params.launchKind,\n }),\n );\n}\n\nexport function recordProviderRunnerActivationToFirstClaim(\n params: ProviderRunnerLifecycleObservation,\n): void {\n if (params.durationMilliseconds < 0) return;\n recordMetric(() =>\n providerRunnerActivationToFirstClaimDuration.record(params.durationMilliseconds, {\n provider: resolveProviderRunnerMetricProvider(params),\n launch_kind: params.launchKind,\n }),\n );\n}\n\nexport function recordJobExecutionQueueTime(params: JobExecutionQueueTimeObservation): void {\n if (params.durationMilliseconds < 0) return;\n recordMetric(() =>\n jobExecutionQueueTimeDuration.record(params.durationMilliseconds, {\n provider: params.provider ?? UNKNOWN_PROVIDER_KIND,\n launch_kind: params.launchKind,\n }),\n );\n}\n\nexport function recordProviderRunnerAssignmentRejected(params: {\n reason: RunnerAssignmentRejectionReason;\n surface: RunnerAssignmentSurface;\n}): void {\n recordMetric(() => providerRunnerAssignmentRejectedCount.add(1, params));\n}\n\nexport function recordRunnerReservationPromotionFailure(\n reason: RunnerReservationPromotionFailureReason,\n): void {\n recordMetric(() => runnerReservationPromotionFailureCount.add(1, {reason}));\n}\n\nexport function recordRunnerActivationTokenNotIssued(params: {\n reason: RunnerActivationTokenNotIssuedReason;\n surface: RunnerActivationTokenNotIssuedSurface;\n}): void {\n recordMetric(() => runnerActivationTokenNotIssuedCount.add(1, params));\n}\n\nexport function recordRunnerReservationCapacityFailure(\n reason: RunnerReservationCapacityFailureReason,\n count: number,\n): void {\n if (count <= 0) return;\n recordMetric(() => runnerReservationCapacityFailureCount.add(count, {reason}));\n}\n\nexport function recordRunnersRateLimitCheck(params: {\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}): void {\n recordMetric(() =>\n rateLimitCheckCount.add(1, {\n action: params.action,\n scope: params.scope,\n outcome: params.outcome,\n }),\n );\n}\n\nexport function recordRunnersRateLimitPruneFailure(): void {\n recordMetric(() => rateLimitPruneFailureCount.add(1));\n}\n\nexport function recordProviderRunnerActivationOutcome(params: {\n outcome: 'reaped' | 'rebound';\n count?: number;\n}): void {\n recordMetric(() =>\n providerRunnerActivationOutcomeCount.add(params.count ?? 1, {outcome: params.outcome}),\n );\n}\n"],"names":["instanceMetrics","logger","meter","getMeter","UNKNOWN_PROVIDER_KIND","lifecycleDurationBuckets","long","short","queueTimeBucketsMilliseconds","providerRunnerCreatedToControlSessionDuration","createHistogram","description","unit","advice","explicitBucketBoundaries","providerRunnerControlSessionToAssignmentDuration","providerRunnerAssignmentToActivationDuration","providerRunnerActivationToFirstClaimDuration","jobExecutionQueueTimeDuration","providerRunnerAssignmentRejectedCount","createCounter","jobExecutionEnqueuedCount","jobExecutionClaimedCount","jobExecutionLeaseExpiredCount","providerRunnerReportCount","runnerBootstrapExchangeCount","runnerActivationTokenNotIssuedCount","runnerControlHeartbeatCount","providerRunnerReapedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerAbsentTerminatedCount","providerRunnerTerminateIntentIssuedCount","providerRunnerTerminateIntentHonoredCount","providerRunnerActivationOutcomeCount","reservationReleasedCount","runnerReservationPromotionFailureCount","runnerReservationCapacityFailureCount","rateLimitCheckCount","rateLimitPruneFailureCount","recordMetric","record","resolveProviderRunnerMetricProvider","params","provider","debug","runnerInstanceId","recordProviderRunnerCreatedToControlSession","durationMilliseconds","launch_kind","launchKind","recordProviderRunnerControlSessionToAssignment","surface","recordProviderRunnerAssignmentToActivation","recordProviderRunnerActivationToFirstClaim","recordJobExecutionQueueTime","recordProviderRunnerAssignmentRejected","add","recordRunnerReservationPromotionFailure","reason","recordRunnerActivationTokenNotIssued","recordRunnerReservationCapacityFailure","count","recordRunnersRateLimitCheck","action","scope","outcome","recordRunnersRateLimitPruneFailure","recordProviderRunnerActivationOutcome"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/metrics/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/metrics/service.ts"],"names":[],"mappings":"AAeA,wBAAgB,6BAA6B,IAAI,IAAI,CAyEpD"}
|
package/dist/metrics/service.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getServiceMetricsProvider } from '@shipfox/node-opentelemetry';
|
|
2
2
|
import { config } from '#config.js';
|
|
3
3
|
import { getJobExecutionQueueDepth } from '#db/job-executions.js';
|
|
4
|
-
import { countStaleEnrolledRunnerInstances } from '#db/runner-instances.js';
|
|
4
|
+
import { countStaleEnrolledRunnerInstances, listProviderRunnerByPhaseMetrics } from '#db/runner-instances.js';
|
|
5
5
|
export function registerRunnersServiceMetrics() {
|
|
6
6
|
const meter = getServiceMetricsProvider().getMeter('runners');
|
|
7
7
|
const pendingJobExecutions = meter.createObservableGauge('runners_pending_job_executions', {
|
|
@@ -13,12 +13,20 @@ export function registerRunnersServiceMetrics() {
|
|
|
13
13
|
const enrolledRunnersWithoutRecentReport = meter.createObservableGauge('runners_enrolled_without_recent_report', {
|
|
14
14
|
description: 'Running enrolled runners with a live control session, no workspace or runner session, and no recent provisioner report after the stale-runner grace window'
|
|
15
15
|
});
|
|
16
|
+
const providerRunnersByPhase = meter.createObservableGauge('runners_provider_runner_by_phase', {
|
|
17
|
+
description: 'Provider runners by lifecycle phase, including idle runners without an active assignment'
|
|
18
|
+
});
|
|
19
|
+
const providerRunnersByPhaseOldestAge = meter.createObservableGauge('runners_provider_runner_by_phase_oldest_age', {
|
|
20
|
+
description: 'Oldest provider runner age by lifecycle phase',
|
|
21
|
+
unit: 'ms'
|
|
22
|
+
});
|
|
16
23
|
meter.addBatchObservableCallback(async (observer)=>{
|
|
17
|
-
const [depthResult, staleEnrolledRunnerCountResult] = await Promise.allSettled([
|
|
24
|
+
const [depthResult, staleEnrolledRunnerCountResult, providerRunnersByPhaseResult] = await Promise.allSettled([
|
|
18
25
|
getJobExecutionQueueDepth(),
|
|
19
26
|
countStaleEnrolledRunnerInstances({
|
|
20
27
|
graceSeconds: config.RUNNER_STALE_PROVISIONED_RUNNER_THRESHOLD_SECONDS
|
|
21
|
-
})
|
|
28
|
+
}),
|
|
29
|
+
listProviderRunnerByPhaseMetrics()
|
|
22
30
|
]);
|
|
23
31
|
if (depthResult.status === 'fulfilled') {
|
|
24
32
|
observer.observe(pendingJobExecutions, depthResult.value.pendingJobExecutions);
|
|
@@ -27,10 +35,23 @@ export function registerRunnersServiceMetrics() {
|
|
|
27
35
|
if (staleEnrolledRunnerCountResult.status === 'fulfilled') {
|
|
28
36
|
observer.observe(enrolledRunnersWithoutRecentReport, staleEnrolledRunnerCountResult.value);
|
|
29
37
|
}
|
|
38
|
+
if (providerRunnersByPhaseResult.status === 'fulfilled') {
|
|
39
|
+
for (const metric of providerRunnersByPhaseResult.value){
|
|
40
|
+
const attributes = {
|
|
41
|
+
phase: metric.phase,
|
|
42
|
+
provider: metric.provider,
|
|
43
|
+
launch_kind: metric.launchKind
|
|
44
|
+
};
|
|
45
|
+
observer.observe(providerRunnersByPhase, metric.count, attributes);
|
|
46
|
+
observer.observe(providerRunnersByPhaseOldestAge, metric.oldestAgeMilliseconds, attributes);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
30
49
|
}, [
|
|
31
50
|
pendingJobExecutions,
|
|
32
51
|
runningJobExecutions,
|
|
33
|
-
enrolledRunnersWithoutRecentReport
|
|
52
|
+
enrolledRunnersWithoutRecentReport,
|
|
53
|
+
providerRunnersByPhase,
|
|
54
|
+
providerRunnersByPhaseOldestAge
|
|
34
55
|
]);
|
|
35
56
|
}
|
|
36
57
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/service.ts"],"sourcesContent":["import {getServiceMetricsProvider} from '@shipfox/node-opentelemetry';\nimport {config} from '#config.js';\nimport {getJobExecutionQueueDepth} from '#db/job-executions.js';\nimport {countStaleEnrolledRunnerInstances} from '#db/runner-instances.js';\n\nexport function registerRunnersServiceMetrics(): void {\n const meter = getServiceMetricsProvider().getMeter('runners');\n\n const pendingJobExecutions = meter.createObservableGauge('runners_pending_job_executions', {\n description: 'Job executions currently waiting in the queue to be claimed',\n });\n const runningJobExecutions = meter.createObservableGauge('runners_running_job_executions', {\n description: 'Job executions currently claimed by a runner and in progress',\n });\n const enrolledRunnersWithoutRecentReport = meter.createObservableGauge(\n 'runners_enrolled_without_recent_report',\n {\n description:\n 'Running enrolled runners with a live control session, no workspace or runner session, and no recent provisioner report after the stale-runner grace window',\n },\n );\n\n meter.addBatchObservableCallback(\n async (observer) => {\n const [depthResult, staleEnrolledRunnerCountResult]
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/service.ts"],"sourcesContent":["import {getServiceMetricsProvider} from '@shipfox/node-opentelemetry';\nimport {config} from '#config.js';\nimport {getJobExecutionQueueDepth} from '#db/job-executions.js';\nimport {\n countStaleEnrolledRunnerInstances,\n listProviderRunnerByPhaseMetrics,\n type ProviderRunnerPhaseMetric,\n} from '#db/runner-instances.js';\n\ntype ProviderRunnerPhaseLabels = {\n phase: ProviderRunnerPhaseMetric['phase'];\n provider: string;\n launch_kind: ProviderRunnerPhaseMetric['launchKind'];\n};\n\nexport function registerRunnersServiceMetrics(): void {\n const meter = getServiceMetricsProvider().getMeter('runners');\n\n const pendingJobExecutions = meter.createObservableGauge('runners_pending_job_executions', {\n description: 'Job executions currently waiting in the queue to be claimed',\n });\n const runningJobExecutions = meter.createObservableGauge('runners_running_job_executions', {\n description: 'Job executions currently claimed by a runner and in progress',\n });\n const enrolledRunnersWithoutRecentReport = meter.createObservableGauge(\n 'runners_enrolled_without_recent_report',\n {\n description:\n 'Running enrolled runners with a live control session, no workspace or runner session, and no recent provisioner report after the stale-runner grace window',\n },\n );\n const providerRunnersByPhase = meter.createObservableGauge<ProviderRunnerPhaseLabels>(\n 'runners_provider_runner_by_phase',\n {\n description:\n 'Provider runners by lifecycle phase, including idle runners without an active assignment',\n },\n );\n const providerRunnersByPhaseOldestAge = meter.createObservableGauge<ProviderRunnerPhaseLabels>(\n 'runners_provider_runner_by_phase_oldest_age',\n {\n description: 'Oldest provider runner age by lifecycle phase',\n unit: 'ms',\n },\n );\n\n meter.addBatchObservableCallback(\n async (observer) => {\n const [depthResult, staleEnrolledRunnerCountResult, providerRunnersByPhaseResult] =\n await Promise.allSettled([\n getJobExecutionQueueDepth(),\n countStaleEnrolledRunnerInstances({\n graceSeconds: config.RUNNER_STALE_PROVISIONED_RUNNER_THRESHOLD_SECONDS,\n }),\n listProviderRunnerByPhaseMetrics(),\n ]);\n\n if (depthResult.status === 'fulfilled') {\n observer.observe(pendingJobExecutions, depthResult.value.pendingJobExecutions);\n observer.observe(runningJobExecutions, depthResult.value.runningJobExecutions);\n }\n if (staleEnrolledRunnerCountResult.status === 'fulfilled') {\n observer.observe(enrolledRunnersWithoutRecentReport, staleEnrolledRunnerCountResult.value);\n }\n if (providerRunnersByPhaseResult.status === 'fulfilled') {\n for (const metric of providerRunnersByPhaseResult.value) {\n const attributes: ProviderRunnerPhaseLabels = {\n phase: metric.phase,\n provider: metric.provider,\n launch_kind: metric.launchKind,\n };\n observer.observe(providerRunnersByPhase, metric.count, attributes);\n observer.observe(\n providerRunnersByPhaseOldestAge,\n metric.oldestAgeMilliseconds,\n attributes,\n );\n }\n }\n },\n [\n pendingJobExecutions,\n runningJobExecutions,\n enrolledRunnersWithoutRecentReport,\n providerRunnersByPhase,\n providerRunnersByPhaseOldestAge,\n ],\n );\n}\n"],"names":["getServiceMetricsProvider","config","getJobExecutionQueueDepth","countStaleEnrolledRunnerInstances","listProviderRunnerByPhaseMetrics","registerRunnersServiceMetrics","meter","getMeter","pendingJobExecutions","createObservableGauge","description","runningJobExecutions","enrolledRunnersWithoutRecentReport","providerRunnersByPhase","providerRunnersByPhaseOldestAge","unit","addBatchObservableCallback","observer","depthResult","staleEnrolledRunnerCountResult","providerRunnersByPhaseResult","Promise","allSettled","graceSeconds","RUNNER_STALE_PROVISIONED_RUNNER_THRESHOLD_SECONDS","status","observe","value","metric","attributes","phase","provider","launch_kind","launchKind","count","oldestAgeMilliseconds"],"mappings":"AAAA,SAAQA,yBAAyB,QAAO,8BAA8B;AACtE,SAAQC,MAAM,QAAO,aAAa;AAClC,SAAQC,yBAAyB,QAAO,wBAAwB;AAChE,SACEC,iCAAiC,EACjCC,gCAAgC,QAE3B,0BAA0B;AAQjC,OAAO,SAASC;IACd,MAAMC,QAAQN,4BAA4BO,QAAQ,CAAC;IAEnD,MAAMC,uBAAuBF,MAAMG,qBAAqB,CAAC,kCAAkC;QACzFC,aAAa;IACf;IACA,MAAMC,uBAAuBL,MAAMG,qBAAqB,CAAC,kCAAkC;QACzFC,aAAa;IACf;IACA,MAAME,qCAAqCN,MAAMG,qBAAqB,CACpE,0CACA;QACEC,aACE;IACJ;IAEF,MAAMG,yBAAyBP,MAAMG,qBAAqB,CACxD,oCACA;QACEC,aACE;IACJ;IAEF,MAAMI,kCAAkCR,MAAMG,qBAAqB,CACjE,+CACA;QACEC,aAAa;QACbK,MAAM;IACR;IAGFT,MAAMU,0BAA0B,CAC9B,OAAOC;QACL,MAAM,CAACC,aAAaC,gCAAgCC,6BAA6B,GAC/E,MAAMC,QAAQC,UAAU,CAAC;YACvBpB;YACAC,kCAAkC;gBAChCoB,cAActB,OAAOuB,iDAAiD;YACxE;YACApB;SACD;QAEH,IAAIc,YAAYO,MAAM,KAAK,aAAa;YACtCR,SAASS,OAAO,CAAClB,sBAAsBU,YAAYS,KAAK,CAACnB,oBAAoB;YAC7ES,SAASS,OAAO,CAACf,sBAAsBO,YAAYS,KAAK,CAAChB,oBAAoB;QAC/E;QACA,IAAIQ,+BAA+BM,MAAM,KAAK,aAAa;YACzDR,SAASS,OAAO,CAACd,oCAAoCO,+BAA+BQ,KAAK;QAC3F;QACA,IAAIP,6BAA6BK,MAAM,KAAK,aAAa;YACvD,KAAK,MAAMG,UAAUR,6BAA6BO,KAAK,CAAE;gBACvD,MAAME,aAAwC;oBAC5CC,OAAOF,OAAOE,KAAK;oBACnBC,UAAUH,OAAOG,QAAQ;oBACzBC,aAAaJ,OAAOK,UAAU;gBAChC;gBACAhB,SAASS,OAAO,CAACb,wBAAwBe,OAAOM,KAAK,EAAEL;gBACvDZ,SAASS,OAAO,CACdZ,iCACAc,OAAOO,qBAAqB,EAC5BN;YAEJ;QACF;IACF,GACA;QACErB;QACAG;QACAC;QACAC;QACAC;KACD;AAEL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assign-runner-instances.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/assign-runner-instances.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assign-runner-instances.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/assign-runner-instances.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,0BAA0B,iDA0CrC,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { requireProvisionerContext } from '@shipfox/api-auth-context';
|
|
2
2
|
import { assignRunnerInstancesBodySchema, assignRunnerInstancesResponseSchema, RESERVATION_EXPIRED_ERROR_CODE, RUNNER_INSTANCE_NOT_ASSIGNABLE_ERROR_CODE } from '@shipfox/api-runners-dto';
|
|
3
3
|
import { ClientError, defineRoute } from '@shipfox/node-fastify';
|
|
4
|
-
import { ReservationExpiredError, ReservationNotFoundError, RunnerInstanceAlreadyAssignedError, RunnerInstanceNotAssignableError } from '#core/errors.js';
|
|
4
|
+
import { getRunnerAssignmentRejectionReason, ReservationExpiredError, ReservationNotFoundError, RunnerInstanceAlreadyAssignedError, RunnerInstanceNotAssignableError } from '#core/errors.js';
|
|
5
5
|
import { assignRunnerInstances } from '#core/runner-assignments.js';
|
|
6
|
+
import { recordProviderRunnerAssignmentRejected } from '#metrics/instance.js';
|
|
6
7
|
export const assignRunnerInstancesRoute = defineRoute({
|
|
7
8
|
method: 'POST',
|
|
8
9
|
path: '/runner-instances/assignments',
|
|
@@ -14,6 +15,11 @@ export const assignRunnerInstancesRoute = defineRoute({
|
|
|
14
15
|
}
|
|
15
16
|
},
|
|
16
17
|
errorHandler: (error)=>{
|
|
18
|
+
const rejectionReason = getRunnerAssignmentRejectionReason(error);
|
|
19
|
+
if (rejectionReason) recordProviderRunnerAssignmentRejected({
|
|
20
|
+
reason: rejectionReason,
|
|
21
|
+
surface: 'provisioner'
|
|
22
|
+
});
|
|
17
23
|
if (error instanceof ReservationNotFoundError) throw new ClientError('Reservation not found', 'reservation-not-found', {
|
|
18
24
|
status: 404
|
|
19
25
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/routes/assign-runner-instances.ts"],"sourcesContent":["import {requireProvisionerContext} from '@shipfox/api-auth-context';\nimport {\n assignRunnerInstancesBodySchema,\n assignRunnerInstancesResponseSchema,\n RESERVATION_EXPIRED_ERROR_CODE,\n RUNNER_INSTANCE_NOT_ASSIGNABLE_ERROR_CODE,\n} from '@shipfox/api-runners-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {\n ReservationExpiredError,\n ReservationNotFoundError,\n RunnerInstanceAlreadyAssignedError,\n RunnerInstanceNotAssignableError,\n} from '#core/errors.js';\nimport {assignRunnerInstances} from '#core/runner-assignments.js';\n\nexport const assignRunnerInstancesRoute = defineRoute({\n method: 'POST',\n path: '/runner-instances/assignments',\n description: 'Assign enrolled runner instances to an owned demand reservation',\n schema: {\n body: assignRunnerInstancesBodySchema,\n response: {200: assignRunnerInstancesResponseSchema},\n },\n errorHandler: (error) => {\n if (error instanceof ReservationNotFoundError)\n throw new ClientError('Reservation not found', 'reservation-not-found', {status: 404});\n if (error instanceof ReservationExpiredError)\n throw new ClientError('Reservation has expired', RESERVATION_EXPIRED_ERROR_CODE, {\n status: 409,\n });\n if (\n error instanceof RunnerInstanceAlreadyAssignedError ||\n error instanceof RunnerInstanceNotAssignableError\n )\n throw new ClientError(\n 'Runner instance cannot be assigned',\n RUNNER_INSTANCE_NOT_ASSIGNABLE_ERROR_CODE,\n {status: 409},\n );\n throw error;\n },\n handler: async (request) => {\n const {provisionerTokenId} = requireProvisionerContext(request);\n return {\n runner_instance_ids: await assignRunnerInstances({\n provisionerId: provisionerTokenId,\n reservationId: request.body.reservation_id,\n runnerInstanceIds: request.body.runner_instance_ids,\n }),\n };\n },\n});\n"],"names":["requireProvisionerContext","assignRunnerInstancesBodySchema","assignRunnerInstancesResponseSchema","RESERVATION_EXPIRED_ERROR_CODE","RUNNER_INSTANCE_NOT_ASSIGNABLE_ERROR_CODE","ClientError","defineRoute","ReservationExpiredError","ReservationNotFoundError","RunnerInstanceAlreadyAssignedError","RunnerInstanceNotAssignableError","assignRunnerInstances","assignRunnerInstancesRoute","method","path","description","schema","body","response","errorHandler","error","status","handler","request","provisionerTokenId","runner_instance_ids","provisionerId","reservationId","reservation_id","runnerInstanceIds"],"mappings":"AAAA,SAAQA,yBAAyB,QAAO,4BAA4B;AACpE,SACEC,+BAA+B,EAC/BC,mCAAmC,EACnCC,8BAA8B,EAC9BC,yCAAyC,QACpC,2BAA2B;AAClC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SACEC,uBAAuB,EACvBC,wBAAwB,EACxBC,kCAAkC,EAClCC,gCAAgC,QAC3B,kBAAkB;AACzB,SAAQC,qBAAqB,QAAO,8BAA8B;
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/assign-runner-instances.ts"],"sourcesContent":["import {requireProvisionerContext} from '@shipfox/api-auth-context';\nimport {\n assignRunnerInstancesBodySchema,\n assignRunnerInstancesResponseSchema,\n RESERVATION_EXPIRED_ERROR_CODE,\n RUNNER_INSTANCE_NOT_ASSIGNABLE_ERROR_CODE,\n} from '@shipfox/api-runners-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {\n getRunnerAssignmentRejectionReason,\n ReservationExpiredError,\n ReservationNotFoundError,\n RunnerInstanceAlreadyAssignedError,\n RunnerInstanceNotAssignableError,\n} from '#core/errors.js';\nimport {assignRunnerInstances} from '#core/runner-assignments.js';\nimport {recordProviderRunnerAssignmentRejected} from '#metrics/instance.js';\n\nexport const assignRunnerInstancesRoute = defineRoute({\n method: 'POST',\n path: '/runner-instances/assignments',\n description: 'Assign enrolled runner instances to an owned demand reservation',\n schema: {\n body: assignRunnerInstancesBodySchema,\n response: {200: assignRunnerInstancesResponseSchema},\n },\n errorHandler: (error) => {\n const rejectionReason = getRunnerAssignmentRejectionReason(error);\n if (rejectionReason)\n recordProviderRunnerAssignmentRejected({\n reason: rejectionReason,\n surface: 'provisioner',\n });\n if (error instanceof ReservationNotFoundError)\n throw new ClientError('Reservation not found', 'reservation-not-found', {status: 404});\n if (error instanceof ReservationExpiredError)\n throw new ClientError('Reservation has expired', RESERVATION_EXPIRED_ERROR_CODE, {\n status: 409,\n });\n if (\n error instanceof RunnerInstanceAlreadyAssignedError ||\n error instanceof RunnerInstanceNotAssignableError\n )\n throw new ClientError(\n 'Runner instance cannot be assigned',\n RUNNER_INSTANCE_NOT_ASSIGNABLE_ERROR_CODE,\n {status: 409},\n );\n throw error;\n },\n handler: async (request) => {\n const {provisionerTokenId} = requireProvisionerContext(request);\n return {\n runner_instance_ids: await assignRunnerInstances({\n provisionerId: provisionerTokenId,\n reservationId: request.body.reservation_id,\n runnerInstanceIds: request.body.runner_instance_ids,\n }),\n };\n },\n});\n"],"names":["requireProvisionerContext","assignRunnerInstancesBodySchema","assignRunnerInstancesResponseSchema","RESERVATION_EXPIRED_ERROR_CODE","RUNNER_INSTANCE_NOT_ASSIGNABLE_ERROR_CODE","ClientError","defineRoute","getRunnerAssignmentRejectionReason","ReservationExpiredError","ReservationNotFoundError","RunnerInstanceAlreadyAssignedError","RunnerInstanceNotAssignableError","assignRunnerInstances","recordProviderRunnerAssignmentRejected","assignRunnerInstancesRoute","method","path","description","schema","body","response","errorHandler","error","rejectionReason","reason","surface","status","handler","request","provisionerTokenId","runner_instance_ids","provisionerId","reservationId","reservation_id","runnerInstanceIds"],"mappings":"AAAA,SAAQA,yBAAyB,QAAO,4BAA4B;AACpE,SACEC,+BAA+B,EAC/BC,mCAAmC,EACnCC,8BAA8B,EAC9BC,yCAAyC,QACpC,2BAA2B;AAClC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SACEC,kCAAkC,EAClCC,uBAAuB,EACvBC,wBAAwB,EACxBC,kCAAkC,EAClCC,gCAAgC,QAC3B,kBAAkB;AACzB,SAAQC,qBAAqB,QAAO,8BAA8B;AAClE,SAAQC,sCAAsC,QAAO,uBAAuB;AAE5E,OAAO,MAAMC,6BAA6BR,YAAY;IACpDS,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,MAAMlB;QACNmB,UAAU;YAAC,KAAKlB;QAAmC;IACrD;IACAmB,cAAc,CAACC;QACb,MAAMC,kBAAkBhB,mCAAmCe;QAC3D,IAAIC,iBACFV,uCAAuC;YACrCW,QAAQD;YACRE,SAAS;QACX;QACF,IAAIH,iBAAiBb,0BACnB,MAAM,IAAIJ,YAAY,yBAAyB,yBAAyB;YAACqB,QAAQ;QAAG;QACtF,IAAIJ,iBAAiBd,yBACnB,MAAM,IAAIH,YAAY,2BAA2BF,gCAAgC;YAC/EuB,QAAQ;QACV;QACF,IACEJ,iBAAiBZ,sCACjBY,iBAAiBX,kCAEjB,MAAM,IAAIN,YACR,sCACAD,2CACA;YAACsB,QAAQ;QAAG;QAEhB,MAAMJ;IACR;IACAK,SAAS,OAAOC;QACd,MAAM,EAACC,kBAAkB,EAAC,GAAG7B,0BAA0B4B;QACvD,OAAO;YACLE,qBAAqB,MAAMlB,sBAAsB;gBAC/CmB,eAAeF;gBACfG,eAAeJ,QAAQT,IAAI,CAACc,cAAc;gBAC1CC,mBAAmBN,QAAQT,IAAI,CAACW,mBAAmB;YACrD;QACF;IACF;AACF,GAAG"}
|