@shipfox/api-runners 12.3.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 +36 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -2
- package/dist/config.js.map +1 -1
- package/dist/core/demand.d.ts +4 -2
- package/dist/core/demand.d.ts.map +1 -1
- package/dist/core/demand.js +22 -6
- package/dist/core/demand.js.map +1 -1
- package/dist/core/entities/reservation.d.ts +1 -0
- package/dist/core/entities/reservation.d.ts.map +1 -1
- package/dist/core/entities/reservation.js.map +1 -1
- package/dist/core/entities/runner-instance.d.ts +3 -0
- package/dist/core/entities/runner-instance.d.ts.map +1 -1
- package/dist/core/entities/runner-instance.js.map +1 -1
- 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-activation.d.ts +4 -1
- package/dist/core/runner-activation.d.ts.map +1 -1
- package/dist/core/runner-activation.js +32 -3
- package/dist/core/runner-activation.js.map +1 -1
- package/dist/core/runner-control-sessions.d.ts +8 -4
- package/dist/core/runner-control-sessions.d.ts.map +1 -1
- package/dist/core/runner-control-sessions.js +116 -20
- package/dist/core/runner-control-sessions.js.map +1 -1
- package/dist/core/runner-instances.d.ts +1 -0
- package/dist/core/runner-instances.d.ts.map +1 -1
- package/dist/core/runner-instances.js +1 -0
- package/dist/core/runner-instances.js.map +1 -1
- package/dist/db/db.d.ts +68 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/ephemeral-registration-tokens.d.ts.map +1 -1
- package/dist/db/ephemeral-registration-tokens.js +1 -1
- package/dist/db/ephemeral-registration-tokens.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/reservation-locks.d.ts +6 -0
- package/dist/db/reservation-locks.d.ts.map +1 -0
- package/dist/db/reservation-locks.js +15 -0
- package/dist/db/reservation-locks.js.map +1 -0
- package/dist/db/reservations.d.ts +17 -3
- package/dist/db/reservations.d.ts.map +1 -1
- package/dist/db/reservations.js +246 -51
- package/dist/db/reservations.js.map +1 -1
- package/dist/db/runner-assignments.d.ts +25 -1
- package/dist/db/runner-assignments.d.ts.map +1 -1
- package/dist/db/runner-assignments.js +160 -18
- package/dist/db/runner-assignments.js.map +1 -1
- package/dist/db/runner-instances.d.ts +11 -2
- package/dist/db/runner-instances.d.ts.map +1 -1
- package/dist/db/runner-instances.js +167 -24
- 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/db/runner-states.d.ts +2 -0
- package/dist/db/runner-states.d.ts.map +1 -0
- package/dist/db/runner-states.js +7 -0
- package/dist/db/runner-states.js.map +1 -0
- package/dist/db/schema/reservations.d.ts +18 -0
- package/dist/db/schema/reservations.d.ts.map +1 -1
- package/dist/db/schema/reservations.js +7 -1
- package/dist/db/schema/reservations.js.map +1 -1
- package/dist/db/schema/runner-instances.d.ts +18 -0
- package/dist/db/schema/runner-instances.d.ts.map +1 -1
- package/dist/db/schema/runner-instances.js +8 -0
- package/dist/db/schema/runner-instances.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 +72 -2
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +161 -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/dto/poll-demand.d.ts.map +1 -1
- package/dist/presentation/dto/poll-demand.js +3 -0
- package/dist/presentation/dto/poll-demand.js.map +1 -1
- package/dist/presentation/dto/runner-instances.d.ts +4 -1
- package/dist/presentation/dto/runner-instances.d.ts.map +1 -1
- package/dist/presentation/dto/runner-instances.js +4 -1
- package/dist/presentation/dto/runner-instances.js.map +1 -1
- package/dist/presentation/routes/assign-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/assign-runner-instances.js +10 -4
- package/dist/presentation/routes/assign-runner-instances.js.map +1 -1
- package/dist/presentation/routes/poll-demand.d.ts.map +1 -1
- package/dist/presentation/routes/poll-demand.js +1 -0
- package/dist/presentation/routes/poll-demand.js.map +1 -1
- package/dist/presentation/routes/reconcile-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/reconcile-runner-instances.js +4 -2
- package/dist/presentation/routes/reconcile-runner-instances.js.map +1 -1
- package/dist/presentation/routes/runner-enrollment.d.ts +4 -1
- package/dist/presentation/routes/runner-enrollment.d.ts.map +1 -1
- package/dist/presentation/routes/runner-enrollment.js +11 -6
- package/dist/presentation/routes/runner-enrollment.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0005_previous_lenny_balinger.sql +5 -0
- package/drizzle/meta/0005_snapshot.json +2220 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +6 -6
- package/src/config.test.ts +22 -0
- package/src/config.ts +15 -2
- package/src/core/demand.test.ts +192 -3
- package/src/core/demand.ts +44 -4
- package/src/core/entities/reservation.ts +1 -0
- package/src/core/entities/runner-instance.ts +4 -0
- package/src/core/errors.ts +30 -1
- package/src/core/runner-activation.ts +48 -2
- package/src/core/runner-control-sessions.test.ts +135 -3
- package/src/core/runner-control-sessions.ts +141 -19
- package/src/core/runner-instances.test.ts +19 -0
- package/src/core/runner-instances.ts +2 -0
- package/src/core/runner-sessions.test.ts +121 -1
- package/src/db/ephemeral-registration-tokens.test.ts +20 -1
- package/src/db/ephemeral-registration-tokens.ts +1 -0
- package/src/db/job-executions.test.ts +98 -12
- package/src/db/job-executions.ts +52 -4
- package/src/db/reservation-locks.ts +22 -0
- package/src/db/reservations.test.ts +733 -22
- package/src/db/reservations.ts +408 -144
- package/src/db/runner-assignments.test.ts +105 -1
- package/src/db/runner-assignments.ts +245 -25
- package/src/db/runner-instances.test.ts +357 -2
- package/src/db/runner-instances.ts +289 -55
- package/src/db/runner-sessions.ts +19 -1
- package/src/db/runner-states.ts +7 -0
- package/src/db/schema/reservations.ts +5 -1
- package/src/db/schema/runner-instances.ts +9 -0
- package/src/metrics/index.ts +24 -1
- package/src/metrics/instance.test.ts +118 -0
- package/src/metrics/instance.ts +247 -3
- package/src/metrics/service.test.ts +46 -1
- package/src/metrics/service.ts +55 -8
- package/src/presentation/dto/poll-demand.ts +3 -0
- package/src/presentation/dto/runner-instances.ts +8 -1
- package/src/presentation/routes/assign-runner-instances.ts +14 -2
- package/src/presentation/routes/late-runner-enrollment.test.ts +219 -2
- package/src/presentation/routes/poll-demand.test.ts +56 -0
- package/src/presentation/routes/poll-demand.ts +1 -0
- package/src/presentation/routes/reconcile-runner-instances.test.ts +34 -2
- package/src/presentation/routes/reconcile-runner-instances.ts +7 -1
- package/src/presentation/routes/runner-enrollment.test.ts +316 -3
- package/src/presentation/routes/runner-enrollment.ts +8 -5
- package/test/factories/reservation.ts +2 -0
- package/test/factories/runner-instance.ts +6 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../../src/db/schema/runner-instances.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAGtE,eAAO,MAAM,uBAAuB,8GAOlC,CAAC;AAEH,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../../src/db/schema/runner-instances.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAGtE,eAAO,MAAM,uBAAuB,8GAOlC,CAAC;AAEH,eAAO,MAAM,4BAA4B,oEAIvC,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyD3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AACnE,MAAM,MAAM,sBAAsB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AAEzE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,cAAc,CA2BtE"}
|
|
@@ -10,6 +10,11 @@ export const providerRunnerStateEnum = pgEnum('runners_provider_runner_state', [
|
|
|
10
10
|
'failed',
|
|
11
11
|
'terminated'
|
|
12
12
|
]);
|
|
13
|
+
export const providerRunnerLaunchKindEnum = pgEnum('runners_provider_runner_launch_kind', [
|
|
14
|
+
'demand',
|
|
15
|
+
'warm',
|
|
16
|
+
'manual'
|
|
17
|
+
]);
|
|
13
18
|
export const providerRunners = pgTable('runner_instances', {
|
|
14
19
|
id: uuidv7PrimaryKey(),
|
|
15
20
|
// Kept during the protocol migration for legacy workspace capacity. New capacity is owned
|
|
@@ -19,6 +24,7 @@ export const providerRunners = pgTable('runner_instances', {
|
|
|
19
24
|
providerRunnerId: text('provider_runner_id'),
|
|
20
25
|
intendedReservationId: uuid('intended_reservation_id'),
|
|
21
26
|
reservationId: uuid('reservation_id'),
|
|
27
|
+
launchKind: providerRunnerLaunchKindEnum('launch_kind').notNull().default('manual'),
|
|
22
28
|
assignedAt: timestamp('assigned_at', {
|
|
23
29
|
withTimezone: true
|
|
24
30
|
}),
|
|
@@ -76,7 +82,9 @@ export function toRunnerInstance(row) {
|
|
|
76
82
|
workspaceId: row.workspaceId,
|
|
77
83
|
provisionerId: row.provisionerId,
|
|
78
84
|
providerRunnerId: row.providerRunnerId,
|
|
85
|
+
intendedReservationId: row.intendedReservationId,
|
|
79
86
|
reservationId: row.reservationId,
|
|
87
|
+
launchKind: row.launchKind,
|
|
80
88
|
assignedAt: row.assignedAt,
|
|
81
89
|
templateKey: row.templateKey,
|
|
82
90
|
labels: row.labels,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db/schema/runner-instances.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {sql} from 'drizzle-orm';\nimport {index, jsonb, pgEnum, text, timestamp, uniqueIndex, uuid} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance} from '#core/entities/runner-instance.js';\nimport {pgTable} from './common.js';\n\nexport const providerRunnerStateEnum = pgEnum('runners_provider_runner_state', [\n 'starting',\n 'running',\n 'stopping',\n 'stopped',\n 'failed',\n 'terminated',\n]);\n\nexport const providerRunners = pgTable(\n 'runner_instances',\n {\n id: uuidv7PrimaryKey(),\n // Kept during the protocol migration for legacy workspace capacity. New capacity is owned\n // only by its provisioner and has no workspace assignment.\n workspaceId: uuid('workspace_id'),\n provisionerId: uuid('provisioner_id').notNull(),\n providerRunnerId: text('provider_runner_id'),\n intendedReservationId: uuid('intended_reservation_id'),\n reservationId: uuid('reservation_id'),\n assignedAt: timestamp('assigned_at', {withTimezone: true}),\n templateKey: text('template_key'),\n labels: text('labels').array().notNull().default([]),\n state: providerRunnerStateEnum('state').notNull(),\n reason: text('reason'),\n runnerSessionId: uuid('runner_session_id'),\n firstClaimedAt: timestamp('first_claimed_at', {withTimezone: true}),\n providerKind: text('provider_kind'),\n protocolVersion: text('protocol_version'),\n capabilities: jsonb('capabilities').$type<RunnerToolCapabilitiesDto | null>(),\n reportedAt: timestamp('reported_at', {withTimezone: true}).notNull(),\n startedAt: timestamp('started_at', {withTimezone: true}),\n stoppingAt: timestamp('stopping_at', {withTimezone: true}),\n stoppedAt: timestamp('stopped_at', {withTimezone: true}),\n failedAt: timestamp('failed_at', {withTimezone: true}),\n terminatedAt: timestamp('terminated_at', {withTimezone: true}),\n reservationReleasedAt: timestamp('reservation_released_at', {withTimezone: true}),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('runners_runner_instances_provisioner_runner_unique')\n .on(table.provisionerId, table.providerRunnerId)\n .where(sql`${table.providerRunnerId} is not null`),\n index('runners_runner_instances_workspace_state_updated_idx').on(table.state, table.updatedAt),\n index('runners_runner_instances_stale_reaper_idx').on(\n table.state,\n table.updatedAt,\n table.reportedAt,\n ),\n index('runners_runner_instances_provisioner_intended_reservation_idx')\n .on(table.provisionerId, table.intendedReservationId)\n .where(\n sql`${table.intendedReservationId} is not null and ${table.reservationReleasedAt} is null`,\n ),\n index('runners_runner_instances_intended_reservation_idx')\n .on(table.intendedReservationId)\n .where(sql`${table.intendedReservationId} is not null`),\n index('runners_runner_instances_provisioner_reservation_idx')\n .on(table.provisionerId, table.reservationId)\n .where(sql`${table.reservationId} is not null`),\n index('runners_runner_instances_active_template_counts_idx')\n .on(table.provisionerId, table.state, table.templateKey)\n .where(sql`\"state\" in ('starting', 'running') and \"template_key\" is not null`),\n ],\n);\n\nexport type RunnerInstanceDb = typeof providerRunners.$inferSelect;\nexport type RunnerInstanceInsertDb = typeof providerRunners.$inferInsert;\n\nexport function toRunnerInstance(row: RunnerInstanceDb): RunnerInstance {\n if (!row.providerRunnerId) throw new Error('Runner instance has no provider runner identity');\n return {\n id: row.id,\n workspaceId: row.workspaceId,\n provisionerId: row.provisionerId,\n providerRunnerId: row.providerRunnerId,\n reservationId: row.reservationId,\n assignedAt: row.assignedAt,\n templateKey: row.templateKey,\n labels: row.labels,\n state: row.state,\n reason: row.reason,\n runnerSessionId: row.runnerSessionId,\n providerKind: row.providerKind,\n reportedAt: row.reportedAt,\n startedAt: row.startedAt,\n stoppingAt: row.stoppingAt,\n stoppedAt: row.stoppedAt,\n failedAt: row.failedAt,\n terminatedAt: row.terminatedAt,\n reservationReleasedAt: row.reservationReleasedAt,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n"],"names":["uuidv7PrimaryKey","sql","index","jsonb","pgEnum","text","timestamp","uniqueIndex","uuid","pgTable","providerRunnerStateEnum","providerRunners","id","workspaceId","provisionerId","notNull","providerRunnerId","intendedReservationId","reservationId","assignedAt","withTimezone","templateKey","labels","array","
|
|
1
|
+
{"version":3,"sources":["../../../src/db/schema/runner-instances.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {sql} from 'drizzle-orm';\nimport {index, jsonb, pgEnum, text, timestamp, uniqueIndex, uuid} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance} from '#core/entities/runner-instance.js';\nimport {pgTable} from './common.js';\n\nexport const providerRunnerStateEnum = pgEnum('runners_provider_runner_state', [\n 'starting',\n 'running',\n 'stopping',\n 'stopped',\n 'failed',\n 'terminated',\n]);\n\nexport const providerRunnerLaunchKindEnum = pgEnum('runners_provider_runner_launch_kind', [\n 'demand',\n 'warm',\n 'manual',\n]);\n\nexport const providerRunners = pgTable(\n 'runner_instances',\n {\n id: uuidv7PrimaryKey(),\n // Kept during the protocol migration for legacy workspace capacity. New capacity is owned\n // only by its provisioner and has no workspace assignment.\n workspaceId: uuid('workspace_id'),\n provisionerId: uuid('provisioner_id').notNull(),\n providerRunnerId: text('provider_runner_id'),\n intendedReservationId: uuid('intended_reservation_id'),\n reservationId: uuid('reservation_id'),\n launchKind: providerRunnerLaunchKindEnum('launch_kind').notNull().default('manual'),\n assignedAt: timestamp('assigned_at', {withTimezone: true}),\n templateKey: text('template_key'),\n labels: text('labels').array().notNull().default([]),\n state: providerRunnerStateEnum('state').notNull(),\n reason: text('reason'),\n runnerSessionId: uuid('runner_session_id'),\n firstClaimedAt: timestamp('first_claimed_at', {withTimezone: true}),\n providerKind: text('provider_kind'),\n protocolVersion: text('protocol_version'),\n capabilities: jsonb('capabilities').$type<RunnerToolCapabilitiesDto | null>(),\n reportedAt: timestamp('reported_at', {withTimezone: true}).notNull(),\n startedAt: timestamp('started_at', {withTimezone: true}),\n stoppingAt: timestamp('stopping_at', {withTimezone: true}),\n stoppedAt: timestamp('stopped_at', {withTimezone: true}),\n failedAt: timestamp('failed_at', {withTimezone: true}),\n terminatedAt: timestamp('terminated_at', {withTimezone: true}),\n reservationReleasedAt: timestamp('reservation_released_at', {withTimezone: true}),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('runners_runner_instances_provisioner_runner_unique')\n .on(table.provisionerId, table.providerRunnerId)\n .where(sql`${table.providerRunnerId} is not null`),\n index('runners_runner_instances_workspace_state_updated_idx').on(table.state, table.updatedAt),\n index('runners_runner_instances_stale_reaper_idx').on(\n table.state,\n table.updatedAt,\n table.reportedAt,\n ),\n index('runners_runner_instances_provisioner_intended_reservation_idx')\n .on(table.provisionerId, table.intendedReservationId)\n .where(\n sql`${table.intendedReservationId} is not null and ${table.reservationReleasedAt} is null`,\n ),\n index('runners_runner_instances_intended_reservation_idx')\n .on(table.intendedReservationId)\n .where(sql`${table.intendedReservationId} is not null`),\n index('runners_runner_instances_provisioner_reservation_idx')\n .on(table.provisionerId, table.reservationId)\n .where(sql`${table.reservationId} is not null`),\n index('runners_runner_instances_active_template_counts_idx')\n .on(table.provisionerId, table.state, table.templateKey)\n .where(sql`\"state\" in ('starting', 'running') and \"template_key\" is not null`),\n ],\n);\n\nexport type RunnerInstanceDb = typeof providerRunners.$inferSelect;\nexport type RunnerInstanceInsertDb = typeof providerRunners.$inferInsert;\n\nexport function toRunnerInstance(row: RunnerInstanceDb): RunnerInstance {\n if (!row.providerRunnerId) throw new Error('Runner instance has no provider runner identity');\n return {\n id: row.id,\n workspaceId: row.workspaceId,\n provisionerId: row.provisionerId,\n providerRunnerId: row.providerRunnerId,\n intendedReservationId: row.intendedReservationId,\n reservationId: row.reservationId,\n launchKind: row.launchKind,\n assignedAt: row.assignedAt,\n templateKey: row.templateKey,\n labels: row.labels,\n state: row.state,\n reason: row.reason,\n runnerSessionId: row.runnerSessionId,\n providerKind: row.providerKind,\n reportedAt: row.reportedAt,\n startedAt: row.startedAt,\n stoppingAt: row.stoppingAt,\n stoppedAt: row.stoppedAt,\n failedAt: row.failedAt,\n terminatedAt: row.terminatedAt,\n reservationReleasedAt: row.reservationReleasedAt,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n"],"names":["uuidv7PrimaryKey","sql","index","jsonb","pgEnum","text","timestamp","uniqueIndex","uuid","pgTable","providerRunnerStateEnum","providerRunnerLaunchKindEnum","providerRunners","id","workspaceId","provisionerId","notNull","providerRunnerId","intendedReservationId","reservationId","launchKind","default","assignedAt","withTimezone","templateKey","labels","array","state","reason","runnerSessionId","firstClaimedAt","providerKind","protocolVersion","capabilities","$type","reportedAt","startedAt","stoppingAt","stoppedAt","failedAt","terminatedAt","reservationReleasedAt","createdAt","defaultNow","updatedAt","table","on","where","toRunnerInstance","row","Error"],"mappings":"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"}
|
package/dist/metrics/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { RunnerReservationPromotionFailureReason } from './instance.js';
|
|
2
|
-
export { jobExecutionClaimedCount, jobExecutionEnqueuedCount, jobExecutionLeaseExpiredCount, providerRunnerAbsentTerminatedCount, providerRunnerCountDivergenceCount, providerRunnerReconcileCallCount, providerRunnerTerminateIntentHonoredCount, providerRunnerTerminateIntentIssuedCount, recordRunnerReservationPromotionFailure, recordRunnersRateLimitCheck, recordRunnersRateLimitPruneFailure, } from './instance.js';
|
|
1
|
+
export type { RunnerActivationTokenNotIssuedReason, RunnerActivationTokenNotIssuedSurface, RunnerAssignmentSurface, RunnerLaunchKind, RunnerReservationCapacityFailureReason, RunnerReservationPromotionFailureReason, } from './instance.js';
|
|
2
|
+
export { jobExecutionClaimedCount, jobExecutionEnqueuedCount, jobExecutionLeaseExpiredCount, jobExecutionQueueTimeDuration, providerRunnerAbsentTerminatedCount, providerRunnerActivationOutcomeCount, providerRunnerActivationToFirstClaimDuration, providerRunnerAssignmentRejectedCount, providerRunnerAssignmentToActivationDuration, providerRunnerControlSessionToAssignmentDuration, providerRunnerCountDivergenceCount, providerRunnerCreatedToControlSessionDuration, providerRunnerReconcileCallCount, providerRunnerTerminateIntentHonoredCount, providerRunnerTerminateIntentIssuedCount, recordJobExecutionQueueTime, recordProviderRunnerActivationOutcome, recordProviderRunnerActivationToFirstClaim, recordProviderRunnerAssignmentRejected, recordProviderRunnerAssignmentToActivation, recordProviderRunnerControlSessionToAssignment, recordProviderRunnerCreatedToControlSession, recordRunnerActivationTokenNotIssued, recordRunnerReservationCapacityFailure, recordRunnerReservationPromotionFailure, recordRunnersRateLimitCheck, recordRunnersRateLimitPruneFailure, } from './instance.js';
|
|
3
3
|
export { registerRunnersServiceMetrics } from './service.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,oCAAoC,EACpC,qCAAqC,EACrC,uBAAuB,EACvB,gBAAgB,EAChB,sCAAsC,EACtC,uCAAuC,GACxC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,EAC7B,6BAA6B,EAC7B,mCAAmC,EACnC,oCAAoC,EACpC,4CAA4C,EAC5C,qCAAqC,EACrC,4CAA4C,EAC5C,gDAAgD,EAChD,kCAAkC,EAClC,6CAA6C,EAC7C,gCAAgC,EAChC,yCAAyC,EACzC,wCAAwC,EACxC,2BAA2B,EAC3B,qCAAqC,EACrC,0CAA0C,EAC1C,sCAAsC,EACtC,0CAA0C,EAC1C,8CAA8C,EAC9C,2CAA2C,EAC3C,oCAAoC,EACpC,sCAAsC,EACtC,uCAAuC,EACvC,2BAA2B,EAC3B,kCAAkC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,6BAA6B,EAAC,MAAM,cAAc,CAAC"}
|
package/dist/metrics/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { jobExecutionClaimedCount, jobExecutionEnqueuedCount, jobExecutionLeaseExpiredCount, providerRunnerAbsentTerminatedCount, providerRunnerCountDivergenceCount, providerRunnerReconcileCallCount, providerRunnerTerminateIntentHonoredCount, providerRunnerTerminateIntentIssuedCount, recordRunnerReservationPromotionFailure, recordRunnersRateLimitCheck, recordRunnersRateLimitPruneFailure } from './instance.js';
|
|
1
|
+
export { jobExecutionClaimedCount, jobExecutionEnqueuedCount, jobExecutionLeaseExpiredCount, jobExecutionQueueTimeDuration, providerRunnerAbsentTerminatedCount, providerRunnerActivationOutcomeCount, providerRunnerActivationToFirstClaimDuration, providerRunnerAssignmentRejectedCount, providerRunnerAssignmentToActivationDuration, providerRunnerControlSessionToAssignmentDuration, providerRunnerCountDivergenceCount, providerRunnerCreatedToControlSessionDuration, providerRunnerReconcileCallCount, providerRunnerTerminateIntentHonoredCount, providerRunnerTerminateIntentIssuedCount, recordJobExecutionQueueTime, recordProviderRunnerActivationOutcome, recordProviderRunnerActivationToFirstClaim, recordProviderRunnerAssignmentRejected, recordProviderRunnerAssignmentToActivation, recordProviderRunnerControlSessionToAssignment, recordProviderRunnerCreatedToControlSession, recordRunnerActivationTokenNotIssued, recordRunnerReservationCapacityFailure, recordRunnerReservationPromotionFailure, recordRunnersRateLimitCheck, recordRunnersRateLimitPruneFailure } from './instance.js';
|
|
2
2
|
export { registerRunnersServiceMetrics } from './service.js';
|
|
3
3
|
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/index.ts"],"sourcesContent":["export type {RunnerReservationPromotionFailureReason} from './instance.js';\nexport {\n jobExecutionClaimedCount,\n jobExecutionEnqueuedCount,\n jobExecutionLeaseExpiredCount,\n providerRunnerAbsentTerminatedCount,\n providerRunnerCountDivergenceCount,\n providerRunnerReconcileCallCount,\n providerRunnerTerminateIntentHonoredCount,\n providerRunnerTerminateIntentIssuedCount,\n recordRunnerReservationPromotionFailure,\n recordRunnersRateLimitCheck,\n recordRunnersRateLimitPruneFailure,\n} from './instance.js';\nexport {registerRunnersServiceMetrics} from './service.js';\n"],"names":["jobExecutionClaimedCount","jobExecutionEnqueuedCount","jobExecutionLeaseExpiredCount","providerRunnerAbsentTerminatedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerTerminateIntentHonoredCount","providerRunnerTerminateIntentIssuedCount","recordRunnerReservationPromotionFailure","recordRunnersRateLimitCheck","recordRunnersRateLimitPruneFailure","registerRunnersServiceMetrics"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/index.ts"],"sourcesContent":["export type {\n RunnerActivationTokenNotIssuedReason,\n RunnerActivationTokenNotIssuedSurface,\n RunnerAssignmentSurface,\n RunnerLaunchKind,\n RunnerReservationCapacityFailureReason,\n RunnerReservationPromotionFailureReason,\n} from './instance.js';\nexport {\n jobExecutionClaimedCount,\n jobExecutionEnqueuedCount,\n jobExecutionLeaseExpiredCount,\n jobExecutionQueueTimeDuration,\n providerRunnerAbsentTerminatedCount,\n providerRunnerActivationOutcomeCount,\n providerRunnerActivationToFirstClaimDuration,\n providerRunnerAssignmentRejectedCount,\n providerRunnerAssignmentToActivationDuration,\n providerRunnerControlSessionToAssignmentDuration,\n providerRunnerCountDivergenceCount,\n providerRunnerCreatedToControlSessionDuration,\n providerRunnerReconcileCallCount,\n providerRunnerTerminateIntentHonoredCount,\n providerRunnerTerminateIntentIssuedCount,\n recordJobExecutionQueueTime,\n recordProviderRunnerActivationOutcome,\n recordProviderRunnerActivationToFirstClaim,\n recordProviderRunnerAssignmentRejected,\n recordProviderRunnerAssignmentToActivation,\n recordProviderRunnerControlSessionToAssignment,\n recordProviderRunnerCreatedToControlSession,\n recordRunnerActivationTokenNotIssued,\n recordRunnerReservationCapacityFailure,\n recordRunnerReservationPromotionFailure,\n recordRunnersRateLimitCheck,\n recordRunnersRateLimitPruneFailure,\n} from './instance.js';\nexport {registerRunnersServiceMetrics} from './service.js';\n"],"names":["jobExecutionClaimedCount","jobExecutionEnqueuedCount","jobExecutionLeaseExpiredCount","jobExecutionQueueTimeDuration","providerRunnerAbsentTerminatedCount","providerRunnerActivationOutcomeCount","providerRunnerActivationToFirstClaimDuration","providerRunnerAssignmentRejectedCount","providerRunnerAssignmentToActivationDuration","providerRunnerControlSessionToAssignmentDuration","providerRunnerCountDivergenceCount","providerRunnerCreatedToControlSessionDuration","providerRunnerReconcileCallCount","providerRunnerTerminateIntentHonoredCount","providerRunnerTerminateIntentIssuedCount","recordJobExecutionQueueTime","recordProviderRunnerActivationOutcome","recordProviderRunnerActivationToFirstClaim","recordProviderRunnerAssignmentRejected","recordProviderRunnerAssignmentToActivation","recordProviderRunnerControlSessionToAssignment","recordProviderRunnerCreatedToControlSession","recordRunnerActivationTokenNotIssued","recordRunnerReservationCapacityFailure","recordRunnerReservationPromotionFailure","recordRunnersRateLimitCheck","recordRunnersRateLimitPruneFailure","registerRunnersServiceMetrics"],"mappings":"AAQA,SACEA,wBAAwB,EACxBC,yBAAyB,EACzBC,6BAA6B,EAC7BC,6BAA6B,EAC7BC,mCAAmC,EACnCC,oCAAoC,EACpCC,4CAA4C,EAC5CC,qCAAqC,EACrCC,4CAA4C,EAC5CC,gDAAgD,EAChDC,kCAAkC,EAClCC,6CAA6C,EAC7CC,gCAAgC,EAChCC,yCAAyC,EACzCC,wCAAwC,EACxCC,2BAA2B,EAC3BC,qCAAqC,EACrCC,0CAA0C,EAC1CC,sCAAsC,EACtCC,0CAA0C,EAC1CC,8CAA8C,EAC9CC,2CAA2C,EAC3CC,oCAAoC,EACpCC,sCAAsC,EACtCC,uCAAuC,EACvCC,2BAA2B,EAC3BC,kCAAkC,QAC7B,gBAAgB;AACvB,SAAQC,6BAA6B,QAAO,eAAe"}
|
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
import type { RunnerAssignmentRejectionReason } from '#core/errors.js';
|
|
2
|
+
export type RunnerLaunchKind = 'demand' | 'warm' | 'manual';
|
|
3
|
+
export type RunnerAssignmentSurface = 'provisioner' | 'enrollment';
|
|
4
|
+
type ProviderRunnerLifecycleLabels = {
|
|
5
|
+
provider: string;
|
|
6
|
+
launch_kind: RunnerLaunchKind;
|
|
7
|
+
};
|
|
8
|
+
type ProviderRunnerAssignmentLifecycleLabels = ProviderRunnerLifecycleLabels & {
|
|
9
|
+
surface: RunnerAssignmentSurface;
|
|
10
|
+
};
|
|
11
|
+
type JobExecutionQueueTimeLabels = {
|
|
12
|
+
provider: string;
|
|
13
|
+
launch_kind: RunnerLaunchKind | 'unknown';
|
|
14
|
+
};
|
|
15
|
+
export interface JobExecutionQueueTimeObservation {
|
|
16
|
+
durationMilliseconds: number;
|
|
17
|
+
provider: string | null;
|
|
18
|
+
launchKind: RunnerLaunchKind | 'unknown';
|
|
19
|
+
}
|
|
20
|
+
export interface ProviderRunnerLifecycleObservation {
|
|
21
|
+
durationMilliseconds: number;
|
|
22
|
+
provider: string | null;
|
|
23
|
+
launchKind: RunnerLaunchKind;
|
|
24
|
+
runnerInstanceId?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ProviderRunnerAssignmentObservation extends ProviderRunnerLifecycleObservation {
|
|
27
|
+
surface: RunnerAssignmentSurface;
|
|
28
|
+
}
|
|
29
|
+
export declare const UNKNOWN_PROVIDER_KIND = "unknown";
|
|
30
|
+
export declare const providerRunnerCreatedToControlSessionDuration: import("@shipfox/node-opentelemetry").Histogram<ProviderRunnerLifecycleLabels>;
|
|
31
|
+
export declare const providerRunnerControlSessionToAssignmentDuration: import("@shipfox/node-opentelemetry").Histogram<ProviderRunnerAssignmentLifecycleLabels>;
|
|
32
|
+
export declare const providerRunnerAssignmentToActivationDuration: import("@shipfox/node-opentelemetry").Histogram<ProviderRunnerLifecycleLabels>;
|
|
33
|
+
export declare const providerRunnerActivationToFirstClaimDuration: import("@shipfox/node-opentelemetry").Histogram<ProviderRunnerLifecycleLabels>;
|
|
34
|
+
export declare const jobExecutionQueueTimeDuration: import("@shipfox/node-opentelemetry").Histogram<JobExecutionQueueTimeLabels>;
|
|
35
|
+
export declare const providerRunnerAssignmentRejectedCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
36
|
+
reason: RunnerAssignmentRejectionReason;
|
|
37
|
+
surface: RunnerAssignmentSurface;
|
|
38
|
+
}>;
|
|
1
39
|
export declare const jobExecutionEnqueuedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
2
40
|
export declare const jobExecutionClaimedCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
3
41
|
outcome: 'claimed' | 'empty';
|
|
@@ -9,6 +47,12 @@ export declare const providerRunnerReportCount: import("@shipfox/node-openteleme
|
|
|
9
47
|
export declare const runnerBootstrapExchangeCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
10
48
|
outcome: 'accepted' | 'rejected';
|
|
11
49
|
}>;
|
|
50
|
+
export type RunnerActivationTokenNotIssuedReason = 'runner-not-found' | 'missing-workspace' | 'existing-session' | 'not-running';
|
|
51
|
+
export type RunnerActivationTokenNotIssuedSurface = 'enrollment' | 'poll';
|
|
52
|
+
export declare const runnerActivationTokenNotIssuedCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
53
|
+
reason: RunnerActivationTokenNotIssuedReason;
|
|
54
|
+
surface: RunnerActivationTokenNotIssuedSurface;
|
|
55
|
+
}>;
|
|
12
56
|
export declare const runnerControlHeartbeatCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
13
57
|
export declare const providerRunnerReapedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
14
58
|
export declare const providerRunnerCountDivergenceCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
@@ -20,24 +64,50 @@ export declare const providerRunnerReconcileCallCount: import("@shipfox/node-ope
|
|
|
20
64
|
export declare const providerRunnerAbsentTerminatedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
21
65
|
export declare const providerRunnerTerminateIntentIssuedCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
22
66
|
surface: 'poll-demand' | 'reconcile';
|
|
23
|
-
reason: 'job-cancelled' | 'terminal-state';
|
|
67
|
+
reason: 'activation-timeout' | 'job-cancelled' | 'terminal-state';
|
|
24
68
|
}>;
|
|
25
69
|
export declare const providerRunnerTerminateIntentHonoredCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
26
|
-
reason: 'job-cancelled';
|
|
70
|
+
reason: 'activation-timeout' | 'job-cancelled';
|
|
71
|
+
}>;
|
|
72
|
+
export declare const providerRunnerActivationOutcomeCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
73
|
+
outcome: 'reaped' | 'rebound';
|
|
27
74
|
}>;
|
|
28
75
|
export declare const reservationReleasedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
29
76
|
export type RunnerReservationPromotionFailureReason = 'reservation-expired' | 'reservation-not-found' | 'already-assigned' | 'not-assignable';
|
|
30
77
|
export declare const runnerReservationPromotionFailureCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
31
78
|
reason: RunnerReservationPromotionFailureReason;
|
|
32
79
|
}>;
|
|
80
|
+
export type RunnerReservationCapacityFailureReason = 'reservation-not-found' | 'reservation-kind-mismatch' | 'reservation-expired' | 'capacity-exhausted';
|
|
81
|
+
export declare const runnerReservationCapacityFailureCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
82
|
+
reason: RunnerReservationCapacityFailureReason;
|
|
83
|
+
}>;
|
|
33
84
|
export type RunnersRateLimitAction = 'provisioner-mint' | 'ephemeral-register';
|
|
34
85
|
export type RunnersRateLimitScope = 'provisioner' | 'ephemeral-token';
|
|
35
86
|
export type RunnersRateLimitOutcome = 'allowed' | 'blocked' | 'unavailable';
|
|
87
|
+
export declare function recordProviderRunnerCreatedToControlSession(params: ProviderRunnerLifecycleObservation): void;
|
|
88
|
+
export declare function recordProviderRunnerControlSessionToAssignment(params: ProviderRunnerAssignmentObservation): void;
|
|
89
|
+
export declare function recordProviderRunnerAssignmentToActivation(params: ProviderRunnerLifecycleObservation): void;
|
|
90
|
+
export declare function recordProviderRunnerActivationToFirstClaim(params: ProviderRunnerLifecycleObservation): void;
|
|
91
|
+
export declare function recordJobExecutionQueueTime(params: JobExecutionQueueTimeObservation): void;
|
|
92
|
+
export declare function recordProviderRunnerAssignmentRejected(params: {
|
|
93
|
+
reason: RunnerAssignmentRejectionReason;
|
|
94
|
+
surface: RunnerAssignmentSurface;
|
|
95
|
+
}): void;
|
|
36
96
|
export declare function recordRunnerReservationPromotionFailure(reason: RunnerReservationPromotionFailureReason): void;
|
|
97
|
+
export declare function recordRunnerActivationTokenNotIssued(params: {
|
|
98
|
+
reason: RunnerActivationTokenNotIssuedReason;
|
|
99
|
+
surface: RunnerActivationTokenNotIssuedSurface;
|
|
100
|
+
}): void;
|
|
101
|
+
export declare function recordRunnerReservationCapacityFailure(reason: RunnerReservationCapacityFailureReason, count: number): void;
|
|
37
102
|
export declare function recordRunnersRateLimitCheck(params: {
|
|
38
103
|
action: RunnersRateLimitAction;
|
|
39
104
|
scope: RunnersRateLimitScope;
|
|
40
105
|
outcome: RunnersRateLimitOutcome;
|
|
41
106
|
}): void;
|
|
42
107
|
export declare function recordRunnersRateLimitPruneFailure(): void;
|
|
108
|
+
export declare function recordProviderRunnerActivationOutcome(params: {
|
|
109
|
+
outcome: 'reaped' | 'rebound';
|
|
110
|
+
count?: number;
|
|
111
|
+
}): void;
|
|
112
|
+
export {};
|
|
43
113
|
//# sourceMappingURL=instance.d.ts.map
|
|
@@ -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
|
});
|
|
@@ -15,6 +106,9 @@ export const providerRunnerReportCount = meter.createCounter('runners_provider_r
|
|
|
15
106
|
export const runnerBootstrapExchangeCount = meter.createCounter('runners_runner_bootstrap_exchange', {
|
|
16
107
|
description: 'Runner bootstrap-token exchanges by outcome'
|
|
17
108
|
});
|
|
109
|
+
export const runnerActivationTokenNotIssuedCount = meter.createCounter('runners_runner_activation_token_not_issued', {
|
|
110
|
+
description: 'Runner activation token issuance skips by reason and surface'
|
|
111
|
+
});
|
|
18
112
|
export const runnerControlHeartbeatCount = meter.createCounter('runners_runner_control_heartbeat', {
|
|
19
113
|
description: 'Pre-workspace runner-control heartbeats accepted'
|
|
20
114
|
});
|
|
@@ -36,12 +130,18 @@ export const providerRunnerTerminateIntentIssuedCount = meter.createCounter('run
|
|
|
36
130
|
export const providerRunnerTerminateIntentHonoredCount = meter.createCounter('runners_provider_runner_terminate_intent_honored', {
|
|
37
131
|
description: 'Provisioned runner terminate intents honored by first transition to terminated'
|
|
38
132
|
});
|
|
133
|
+
export const providerRunnerActivationOutcomeCount = meter.createCounter('runners_provider_runner_activation_outcome', {
|
|
134
|
+
description: 'Demand-backed runner activation outcomes by recovery action'
|
|
135
|
+
});
|
|
39
136
|
export const reservationReleasedCount = meter.createCounter('runners_reservation_released', {
|
|
40
137
|
description: 'Reservation units released from terminal provisioned runner reports'
|
|
41
138
|
});
|
|
42
139
|
export const runnerReservationPromotionFailureCount = meter.createCounter('runners_reservation_promotion_failures', {
|
|
43
140
|
description: 'Runner reservation promotion failures during enrollment by reason'
|
|
44
141
|
});
|
|
142
|
+
export const runnerReservationCapacityFailureCount = meter.createCounter('runners_reservation_capacity_failures', {
|
|
143
|
+
description: 'Runner reservation admission shortfalls by reason'
|
|
144
|
+
});
|
|
45
145
|
const rateLimitCheckCount = meter.createCounter('runners_rate_limit_checks', {
|
|
46
146
|
description: 'Runners rate limit checks by action, scope, and outcome'
|
|
47
147
|
});
|
|
@@ -55,11 +155,66 @@ function recordMetric(record) {
|
|
|
55
155
|
// Metrics must not affect runner or provisioner request outcomes.
|
|
56
156
|
}
|
|
57
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
|
+
}
|
|
58
204
|
export function recordRunnerReservationPromotionFailure(reason) {
|
|
59
205
|
recordMetric(()=>runnerReservationPromotionFailureCount.add(1, {
|
|
60
206
|
reason
|
|
61
207
|
}));
|
|
62
208
|
}
|
|
209
|
+
export function recordRunnerActivationTokenNotIssued(params) {
|
|
210
|
+
recordMetric(()=>runnerActivationTokenNotIssuedCount.add(1, params));
|
|
211
|
+
}
|
|
212
|
+
export function recordRunnerReservationCapacityFailure(reason, count) {
|
|
213
|
+
if (count <= 0) return;
|
|
214
|
+
recordMetric(()=>runnerReservationCapacityFailureCount.add(count, {
|
|
215
|
+
reason
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
63
218
|
export function recordRunnersRateLimitCheck(params) {
|
|
64
219
|
recordMetric(()=>rateLimitCheckCount.add(1, {
|
|
65
220
|
action: params.action,
|
|
@@ -70,5 +225,10 @@ export function recordRunnersRateLimitCheck(params) {
|
|
|
70
225
|
export function recordRunnersRateLimitPruneFailure() {
|
|
71
226
|
recordMetric(()=>rateLimitPruneFailureCount.add(1));
|
|
72
227
|
}
|
|
228
|
+
export function recordProviderRunnerActivationOutcome(params) {
|
|
229
|
+
recordMetric(()=>providerRunnerActivationOutcomeCount.add(params.count ?? 1, {
|
|
230
|
+
outcome: params.outcome
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
73
233
|
|
|
74
234
|
//# sourceMappingURL=instance.js.map
|
|
@@ -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 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: '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: '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 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 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 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"],"names":["instanceMetrics","meter","getMeter","jobExecutionEnqueuedCount","createCounter","description","jobExecutionClaimedCount","jobExecutionLeaseExpiredCount","providerRunnerReportCount","runnerBootstrapExchangeCount","runnerControlHeartbeatCount","providerRunnerReapedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerAbsentTerminatedCount","providerRunnerTerminateIntentIssuedCount","providerRunnerTerminateIntentHonoredCount","reservationReleasedCount","runnerReservationPromotionFailureCount","rateLimitCheckCount","rateLimitPruneFailureCount","recordMetric","record","recordRunnerReservationPromotionFailure","reason","add","recordRunnersRateLimitCheck","params","action","scope","outcome","recordRunnersRateLimitPruneFailure"],"mappings":"AAAA,SAAQA,eAAe,QAAO,8BAA8B;AAE5D,MAAMC,QAAQD,gBAAgBE,QAAQ,CAAC;AAEvC,OAAO,MAAMC,4BAA4BF,MAAMG,aAAa,CAC1D,kCACA;IACEC,aAAa;AACf,GACA;AAEF,OAAO,MAAMC,2BAA2BL,MAAMG,aAAa,CACzD,iCACA;IAACC,aAAa;AAAyC,GACvD;AAEF,OAAO,MAAME,gCAAgCN,MAAMG,aAAa,CAC9D,uCACA;IAACC,aAAa;AAAmE,GACjF;AAEF,OAAO,MAAMG,4BAA4BP,MAAMG,aAAa,CAEzD,oCAAoC;IACrCC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMI,+BAA+BR,MAAMG,aAAa,CAE5D,qCAAqC;IACtCC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMK,8BAA8BT,MAAMG,aAAa,CAC5D,oCACA;IAACC,aAAa;AAAkD,GAChE;AAEF,OAAO,MAAMM,4BAA4BV,MAAMG,aAAa,CAC1D,kCACA;IACEC,aAAa;AACf,GACA;AAEF,OAAO,MAAMO,qCAAqCX,MAAMG,aAAa,CAIlE,4CAA4C;IAC7CC,aACE;AACJ,GAAG;AAEH,OAAO,MAAMQ,mCAAmCZ,MAAMG,aAAa,CACjE,4CACA;IAACC,aAAa;AAA2D,GACzE;AAEF,OAAO,MAAMS,sCAAsCb,MAAMG,aAAa,CACpE,6CACA;IACEC,aACE;AACJ,GACA;AAEF,OAAO,MAAMU,2CAA2Cd,MAAMG,aAAa,CAGxE,mDAAmD;IACpDC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMW,4CAA4Cf,MAAMG,aAAa,CAEzE,oDAAoD;IACrDC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMY,2BAA2BhB,MAAMG,aAAa,CACzD,gCACA;IAACC,aAAa;AAAqE,GACnF;AAQF,OAAO,MAAMa,yCAAyCjB,MAAMG,aAAa,CAEtE,0CAA0C;IAC3CC,aAAa;AACf,GAAG;AAMH,MAAMc,sBAAsBlB,MAAMG,aAAa,CAI5C,6BAA6B;IAC9BC,aAAa;AACf;AAEA,MAAMe,6BAA6BnB,MAAMG,aAAa,CAAC,qCAAqC;IAC1FC,aAAa;AACf;AAEA,SAASgB,aAAaC,MAAkB;IACtC,IAAI;QACFA;IACF,EAAE,OAAM;IACN,kEAAkE;IACpE;AACF;AAEA,OAAO,SAASC,wCACdC,MAA+C;IAE/CH,aAAa,IAAMH,uCAAuCO,GAAG,CAAC,GAAG;YAACD;QAAM;AAC1E;AAEA,OAAO,SAASE,4BAA4BC,MAI3C;IACCN,aAAa,IACXF,oBAAoBM,GAAG,CAAC,GAAG;YACzBG,QAAQD,OAAOC,MAAM;YACrBC,OAAOF,OAAOE,KAAK;YACnBC,SAASH,OAAOG,OAAO;QACzB;AAEJ;AAEA,OAAO,SAASC;IACdV,aAAa,IAAMD,2BAA2BK,GAAG,CAAC;AACpD"}
|
|
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":"AAAA,SAAQA,eAAe,EAAEC,MAAM,QAAO,8BAA8B;AAGpE,MAAMC,QAAQF,gBAAgBG,QAAQ,CAAC;AAoCvC,OAAO,MAAMC,wBAAwB,UAAU;AAE/C,MAAMC,2BAA2B;IAC/BC,MAAM;QACJ;QAAK;QAAK;QAAO;QAAO;QAAQ;QAAQ;QAAQ;QAAQ;QAAQ;QAAQ;QAAQ;QAChF;QAAS;KACV;IACDC,OAAO;QAAC;QAAI;QAAI;QAAI;QAAK;QAAK;QAAK;QAAO;QAAO;KAAO;AAC1D;AAEA,MAAMC,+BAA+B;IACnC;IAAK;IAAK;IAAO;IAAO;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAS;IACzF;IAAS;IAAS;IAAW;IAAW;IAAW;CACpD;AAED,6FAA6F;AAC7F,yEAAyE;AACzE,OAAO,MAAMC,gDACXP,MAAMQ,eAAe,CACnB,sDACA;IACEC,aAAa;IACbC,MAAM;IACNC,QAAQ;QAACC,0BAA0BT,yBAAyBC,IAAI;IAAA;AAClE,GACA;AAEJ,OAAO,MAAMS,mDACXb,MAAMQ,eAAe,CACnB,yDACA;IACEC,aAAa;IACbC,MAAM;IACNC,QAAQ;QAACC,0BAA0BT,yBAAyBC,IAAI;IAAA;AAClE,GACA;AAEJ,OAAO,MAAMU,+CACXd,MAAMQ,eAAe,CACnB,oDACA;IACEC,aACE;IACFC,MAAM;IACNC,QAAQ;QAACC,0BAA0BT,yBAAyBE,KAAK;IAAA;AACnE,GACA;AAEJ,OAAO,MAAMU,+CACXf,MAAMQ,eAAe,CACnB,qDACA;IACEC,aAAa;IACbC,MAAM;IACNC,QAAQ;QAACC,0BAA0BT,yBAAyBE,KAAK;IAAA;AACnE,GACA;AAEJ,OAAO,MAAMW,gCAAgChB,MAAMQ,eAAe,CAChE,oCACA;IACEC,aAAa;IACbC,MAAM;IACNC,QAAQ;QAACC,0BAA0BN;IAA4B;AACjE,GACA;AAEF,OAAO,MAAMW,wCAAwCjB,MAAMkB,aAAa,CAGrE,+CAA+C;IAChDT,aAAa;AACf,GAAG;AAEH,OAAO,MAAMU,4BAA4BnB,MAAMkB,aAAa,CAC1D,kCACA;IACET,aAAa;AACf,GACA;AAEF,OAAO,MAAMW,2BAA2BpB,MAAMkB,aAAa,CACzD,iCACA;IAACT,aAAa;AAAyC,GACvD;AAEF,OAAO,MAAMY,gCAAgCrB,MAAMkB,aAAa,CAC9D,uCACA;IAACT,aAAa;AAAmE,GACjF;AAEF,OAAO,MAAMa,4BAA4BtB,MAAMkB,aAAa,CAEzD,oCAAoC;IACrCT,aAAa;AACf,GAAG;AAEH,OAAO,MAAMc,+BAA+BvB,MAAMkB,aAAa,CAE5D,qCAAqC;IACtCT,aAAa;AACf,GAAG;AAUH,OAAO,MAAMe,sCAAsCxB,MAAMkB,aAAa,CAGnE,8CAA8C;IAC/CT,aAAa;AACf,GAAG;AAEH,OAAO,MAAMgB,8BAA8BzB,MAAMkB,aAAa,CAC5D,oCACA;IAACT,aAAa;AAAkD,GAChE;AAEF,OAAO,MAAMiB,4BAA4B1B,MAAMkB,aAAa,CAC1D,kCACA;IACET,aAAa;AACf,GACA;AAEF,OAAO,MAAMkB,qCAAqC3B,MAAMkB,aAAa,CAIlE,4CAA4C;IAC7CT,aACE;AACJ,GAAG;AAEH,OAAO,MAAMmB,mCAAmC5B,MAAMkB,aAAa,CACjE,4CACA;IAACT,aAAa;AAA2D,GACzE;AAEF,OAAO,MAAMoB,sCAAsC7B,MAAMkB,aAAa,CACpE,6CACA;IACET,aACE;AACJ,GACA;AAEF,OAAO,MAAMqB,2CAA2C9B,MAAMkB,aAAa,CAGxE,mDAAmD;IACpDT,aAAa;AACf,GAAG;AAEH,OAAO,MAAMsB,4CAA4C/B,MAAMkB,aAAa,CAEzE,oDAAoD;IACrDT,aAAa;AACf,GAAG;AAEH,OAAO,MAAMuB,uCAAuChC,MAAMkB,aAAa,CAEpE,8CAA8C;IAC/CT,aAAa;AACf,GAAG;AAEH,OAAO,MAAMwB,2BAA2BjC,MAAMkB,aAAa,CACzD,gCACA;IAACT,aAAa;AAAqE,GACnF;AAQF,OAAO,MAAMyB,yCAAyClC,MAAMkB,aAAa,CAEtE,0CAA0C;IAC3CT,aAAa;AACf,GAAG;AAQH,OAAO,MAAM0B,wCAAwCnC,MAAMkB,aAAa,CAErE,yCAAyC;IAC1CT,aAAa;AACf,GAAG;AAMH,MAAM2B,sBAAsBpC,MAAMkB,aAAa,CAI5C,6BAA6B;IAC9BT,aAAa;AACf;AAEA,MAAM4B,6BAA6BrC,MAAMkB,aAAa,CAAC,qCAAqC;IAC1FT,aAAa;AACf;AAEA,SAAS6B,aAAaC,MAAkB;IACtC,IAAI;QACFA;IACF,EAAE,OAAM;IACN,kEAAkE;IACpE;AACF;AAEA,SAASC,oCAAoCC,MAG5C;IACC,IAAIA,OAAOC,QAAQ,EAAE,OAAOD,OAAOC,QAAQ;IAC3C3C,SAAS4C,KAAK,CACZ;QAACC,kBAAkBH,OAAOG,gBAAgB;IAAA,GAC1C;IAEF,OAAO1C;AACT;AAEA,OAAO,SAAS2C,4CACdJ,MAA0C;IAE1C,IAAIA,OAAOK,oBAAoB,GAAG,GAAG;IACrCR,aAAa,IACX/B,8CAA8CgC,MAAM,CAACE,OAAOK,oBAAoB,EAAE;YAChFJ,UAAUF,oCAAoCC;YAC9CM,aAAaN,OAAOO,UAAU;QAChC;AAEJ;AAEA,OAAO,SAASC,+CACdR,MAA2C;IAE3C,IAAIA,OAAOK,oBAAoB,GAAG,GAAG;IACrCR,aAAa,IACXzB,iDAAiD0B,MAAM,CAACE,OAAOK,oBAAoB,EAAE;YACnFJ,UAAUF,oCAAoCC;YAC9CM,aAAaN,OAAOO,UAAU;YAC9BE,SAAST,OAAOS,OAAO;QACzB;AAEJ;AAEA,OAAO,SAASC,2CACdV,MAA0C;IAE1C,IAAIA,OAAOK,oBAAoB,GAAG,GAAG;IACrCR,aAAa,IACXxB,6CAA6CyB,MAAM,CAACE,OAAOK,oBAAoB,EAAE;YAC/EJ,UAAUF,oCAAoCC;YAC9CM,aAAaN,OAAOO,UAAU;QAChC;AAEJ;AAEA,OAAO,SAASI,2CACdX,MAA0C;IAE1C,IAAIA,OAAOK,oBAAoB,GAAG,GAAG;IACrCR,aAAa,IACXvB,6CAA6CwB,MAAM,CAACE,OAAOK,oBAAoB,EAAE;YAC/EJ,UAAUF,oCAAoCC;YAC9CM,aAAaN,OAAOO,UAAU;QAChC;AAEJ;AAEA,OAAO,SAASK,4BAA4BZ,MAAwC;IAClF,IAAIA,OAAOK,oBAAoB,GAAG,GAAG;IACrCR,aAAa,IACXtB,8BAA8BuB,MAAM,CAACE,OAAOK,oBAAoB,EAAE;YAChEJ,UAAUD,OAAOC,QAAQ,IAAIxC;YAC7B6C,aAAaN,OAAOO,UAAU;QAChC;AAEJ;AAEA,OAAO,SAASM,uCAAuCb,MAGtD;IACCH,aAAa,IAAMrB,sCAAsCsC,GAAG,CAAC,GAAGd;AAClE;AAEA,OAAO,SAASe,wCACdC,MAA+C;IAE/CnB,aAAa,IAAMJ,uCAAuCqB,GAAG,CAAC,GAAG;YAACE;QAAM;AAC1E;AAEA,OAAO,SAASC,qCAAqCjB,MAGpD;IACCH,aAAa,IAAMd,oCAAoC+B,GAAG,CAAC,GAAGd;AAChE;AAEA,OAAO,SAASkB,uCACdF,MAA8C,EAC9CG,KAAa;IAEb,IAAIA,SAAS,GAAG;IAChBtB,aAAa,IAAMH,sCAAsCoB,GAAG,CAACK,OAAO;YAACH;QAAM;AAC7E;AAEA,OAAO,SAASI,4BAA4BpB,MAI3C;IACCH,aAAa,IACXF,oBAAoBmB,GAAG,CAAC,GAAG;YACzBO,QAAQrB,OAAOqB,MAAM;YACrBC,OAAOtB,OAAOsB,KAAK;YACnBC,SAASvB,OAAOuB,OAAO;QACzB;AAEJ;AAEA,OAAO,SAASC;IACd3B,aAAa,IAAMD,2BAA2BkB,GAAG,CAAC;AACpD;AAEA,OAAO,SAASW,sCAAsCzB,MAGrD;IACCH,aAAa,IACXN,qCAAqCuB,GAAG,CAACd,OAAOmB,KAAK,IAAI,GAAG;YAACI,SAASvB,OAAOuB,OAAO;QAAA;AAExF"}
|
|
@@ -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":"poll-demand.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/poll-demand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAEtD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,qBAAqB,
|
|
1
|
+
{"version":3,"file":"poll-demand.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/poll-demand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAEtD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,qBAAqB,CAqBvF"}
|