@opengeni/observability 0.8.28-canary.0 → 0.8.29-canary.0

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/dist/index.d.ts CHANGED
@@ -111,6 +111,7 @@ export type SandboxOperationMetricObservation = {
111
111
  op: string;
112
112
  outcome: "ok" | "not_found" | "failed";
113
113
  durationMs: number;
114
+ materializationFailureReason?: string;
114
115
  };
115
116
  export declare function createObservability(settings: ObservabilitySettings, options: ObservabilityOptions): Observability;
116
117
  export declare class Observability {
@@ -236,6 +237,16 @@ export type WorkspaceInsightsMetricObservation = {
236
237
  * tenant ids and caller-supplied provider/model values out of telemetry.
237
238
  */
238
239
  export declare function workspaceInsightsMetricObserver(observability: Observability | null | undefined): (observation: WorkspaceInsightsMetricObservation) => void;
240
+ /** Dispatcher observations count attempts, including repeated observations of
241
+ * the same revision. Transport acceptance is never an admission receipt. */
242
+ export declare function recordWorkflowWakeReconciliation(observability: Observability, result: {
243
+ signaled: number;
244
+ delivered: number;
245
+ pendingAdmission: number;
246
+ unconfirmed: number;
247
+ failed: number;
248
+ pendingAdmissionBlockers: Record<string, number | undefined>;
249
+ }): void;
239
250
  export type StartupDependencyRetryEvent = {
240
251
  label: string;
241
252
  attempt: number;
package/dist/index.js CHANGED
@@ -376,6 +376,17 @@ var PUBLIC_TELEMETRY_ERROR_ORIGINS = /* @__PURE__ */ new Set([
376
376
  "worker",
377
377
  "worker-lifecycle"
378
378
  ]);
379
+ var MATERIALIZATION_FAILURE_REASONS = /* @__PURE__ */ new Set([
380
+ "path_not_visible",
381
+ "command_failed",
382
+ "command_pending",
383
+ "invalid_response",
384
+ "command_error"
385
+ ]);
386
+ var MATERIALIZATION_FAILURE_METRIC = {
387
+ name: "opengeni_sandbox_materialization_verification_failures_total",
388
+ help: "Sandbox destination visibility-check failures by bounded reason; exact command evidence is retained in the session failure event."
389
+ };
379
390
  function createObservability(settings, options) {
380
391
  return new Observability(settings, options);
381
392
  }
@@ -409,6 +420,25 @@ var Observability = class {
409
420
  });
410
421
  this.registerSandboxRolloutConfig();
411
422
  this.registerTenancyCompatibilityLanes();
423
+ if (["worker", "worker-control", "worker-turn", "api"].includes(options.component)) {
424
+ for (const backend of [...SANDBOX_OPERATION_BACKENDS, "unknown"]) {
425
+ for (const reason of [...MATERIALIZATION_FAILURE_REASONS, "unknown"]) {
426
+ this.incrementCounter({
427
+ ...MATERIALIZATION_FAILURE_METRIC,
428
+ labels: { backend, reason },
429
+ amount: 0
430
+ });
431
+ }
432
+ }
433
+ }
434
+ if (options.component === "worker" || options.component === "worker-control") {
435
+ for (const outcome of WORKFLOW_WAKE_OUTCOMES) {
436
+ this.incrementCounter({ ...WORKFLOW_WAKE_METRIC, labels: { outcome }, amount: 0 });
437
+ }
438
+ for (const reason of [...WORKFLOW_WAKE_ADMISSION_BLOCKERS, "unknown"]) {
439
+ this.incrementCounter({ ...WORKFLOW_WAKE_BLOCKER_METRIC, labels: { reason }, amount: 0 });
440
+ }
441
+ }
412
442
  }
413
443
  }
414
444
  registry = new Registry();
@@ -738,6 +768,13 @@ function sandboxOperationMetricObserver(observability) {
738
768
  labels: { backend, op },
739
769
  value: Math.max(0, observation.durationMs) / 1e3
740
770
  });
771
+ if (op === "materializeEntry" && observation.outcome === "failed" && observation.materializationFailureReason) {
772
+ const reason = MATERIALIZATION_FAILURE_REASONS.has(observation.materializationFailureReason) ? observation.materializationFailureReason : "unknown";
773
+ observability.incrementCounter({
774
+ ...MATERIALIZATION_FAILURE_METRIC,
775
+ labels: { backend, reason }
776
+ });
777
+ }
741
778
  } catch {
742
779
  try {
743
780
  observability.incrementCounter({
@@ -858,6 +895,70 @@ function workspaceInsightsMetricObserver(observability) {
858
895
  function boundedMetricEnum(allowed, value) {
859
896
  return allowed.has(value) ? value : "unknown";
860
897
  }
898
+ var WORKFLOW_WAKE_ADMISSION_BLOCKERS = /* @__PURE__ */ new Set([
899
+ "pending_agent_steer",
900
+ "pending_prompt_turn",
901
+ "pending_quiescence",
902
+ "pending_machine_input",
903
+ "pending_input_wait"
904
+ ]);
905
+ var WORKFLOW_WAKE_OUTCOMES = [
906
+ "signal_accepted",
907
+ "acknowledged",
908
+ "pending_admission",
909
+ "unconfirmed",
910
+ "failed"
911
+ ];
912
+ var WORKFLOW_WAKE_METRIC = {
913
+ name: "opengeni_session_workflow_wake_observations_total",
914
+ help: "Workflow wake dispatch observations; signal acceptance overlaps with admission outcomes, and retries are counted again."
915
+ };
916
+ var WORKFLOW_WAKE_BLOCKER_METRIC = {
917
+ name: "opengeni_session_workflow_wake_admission_blockers_total",
918
+ help: "Workflow wake dispatch attempts awaiting durable admission, by bounded blocker; repeated revisions count again."
919
+ };
920
+ function recordWorkflowWakeReconciliation(observability, result) {
921
+ const count = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : 0;
922
+ try {
923
+ for (const [outcome, amount] of [
924
+ ["signal_accepted", result.signaled],
925
+ ["acknowledged", result.delivered],
926
+ ["pending_admission", result.pendingAdmission],
927
+ ["unconfirmed", result.unconfirmed],
928
+ ["failed", result.failed]
929
+ ]) {
930
+ observability.incrementCounter({
931
+ ...WORKFLOW_WAKE_METRIC,
932
+ labels: { outcome },
933
+ amount: count(amount)
934
+ });
935
+ if (count(amount) > 0) {
936
+ observability.info("Session workflow wake dispatch observed", {
937
+ surface: "session_workflow_wake",
938
+ outcome,
939
+ attempts: count(amount)
940
+ });
941
+ }
942
+ }
943
+ for (const [blocker, amount] of Object.entries(result.pendingAdmissionBlockers)) {
944
+ if (count(amount) === 0) continue;
945
+ const reason = boundedMetricEnum(WORKFLOW_WAKE_ADMISSION_BLOCKERS, blocker);
946
+ observability.incrementCounter({
947
+ ...WORKFLOW_WAKE_BLOCKER_METRIC,
948
+ labels: { reason },
949
+ amount: count(amount)
950
+ });
951
+ observability.info("Session workflow wake admission pending", {
952
+ surface: "session_workflow_wake",
953
+ outcome: "pending_admission",
954
+ reason,
955
+ attempts: count(amount)
956
+ });
957
+ }
958
+ } catch {
959
+ recordObserverFailure(observability, "session_workflow_wake");
960
+ }
961
+ }
861
962
  function boundedMetricDuration(durationMs) {
862
963
  return Number.isFinite(durationMs) ? Math.max(0, durationMs) / 1e3 : 0;
863
964
  }
@@ -1060,6 +1161,7 @@ export {
1060
1161
  logStartupDependencyRetry,
1061
1162
  parseHeaders,
1062
1163
  recordTenancyCompatibilityLaneUse,
1164
+ recordWorkflowWakeReconciliation,
1063
1165
  sandboxLeaseTelemetryKey,
1064
1166
  sandboxOperationMetricObserver,
1065
1167
  workspaceInsightsMetricObserver
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { collectDefaultMetrics, Counter, Gauge, Histogram, Registry } from \"prom-client\";\nimport { SandboxBackend } from \"@opengeni/contracts\";\n\nexport type AttributeValue = string | number | boolean | null | undefined;\nexport type Attributes = Record<string, AttributeValue>;\n\nexport type ObservabilitySettings = {\n serviceName: string;\n environment: string;\n deploymentRevision?: string | undefined;\n observabilityStructuredLogs: boolean;\n observabilityMetricsEnabled: boolean;\n observabilityOtlpEndpoint?: string | undefined;\n observabilityOtlpHeaders: string;\n sandboxOwnershipEnabled?: boolean | undefined;\n sandboxLazyProvisionEnabled?: boolean | undefined;\n rigVerificationLeaseOwnershipEnabled?: boolean | undefined;\n};\n\nexport type ObservabilityOptions = {\n component: string;\n now?: () => number;\n exporter?: (url: string, body: unknown, headers: Record<string, string>) => Promise<void>;\n};\n\nexport type Span = {\n traceId: string;\n spanId: string;\n end: (input?: { attributes?: Attributes; error?: unknown }) => void;\n};\n\nexport type MetricLabels = Record<string, AttributeValue>;\n\n/**\n * Stable, non-reversible correlation key for one logical sandbox lease. Public\n * telemetry intentionally drops workspace/group identifiers; this key lets an\n * operator correlate API, worker, and reaper failures without publishing\n * either UUID. The domain separator prevents reuse as a generic identifier\n * digest.\n */\nexport function sandboxLeaseTelemetryKey(workspaceId: string, sandboxGroupId: string): string {\n return `slk_${createHash(\"sha256\")\n .update(\"opengeni:sandbox-lease-telemetry:v1\\0\")\n .update(workspaceId)\n .update(\"\\0\")\n .update(sandboxGroupId)\n .digest(\"hex\")\n .slice(0, 32)}`;\n}\n\n/**\n * Stable selectors shared by OpenGeni's runtime metrics and optional\n * Prometheus/Grafana distribution. Operators can use these values for custom\n * namespaces and dashboard ConfigMaps without duplicating chart internals.\n */\nexport const OPENGENI_OBSERVABILITY_DISTRIBUTION = {\n monitoringNamespaceLabel: \"opengeni.ai/monitoring\",\n monitoringNamespaceLabelValue: \"enabled\",\n grafanaDashboardLabel: \"grafana_dashboard\",\n grafanaDashboardLabelValue: \"1\",\n} as const;\n\nconst httpHistogramBuckets = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\nconst durationHistogramBuckets = [\n 0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300, 900, 1800, 3600,\n];\n\nconst SANDBOX_OPERATION_BACKENDS = new Set<string>([...SandboxBackend.options, \"unprovisioned\"]);\n\nconst SANDBOX_OPERATION_NAMES = new Set([\n \"desktopInput\",\n \"screenshot\",\n \"exec\",\n \"execCommand\",\n \"writeStdin\",\n \"cancelExecCommand\",\n \"readFile\",\n \"writeFile\",\n \"listDir\",\n \"pathExists\",\n \"viewImage\",\n \"materializeEntry\",\n \"editor.createFile\",\n \"editor.updateFile\",\n \"editor.deleteFile\",\n \"resolveExposedPort\",\n \"serializeSessionState\",\n]);\n\n/**\n * Closed set of organization-tenancy compatibility lanes (the tenancy\n * migration's validate phase; see `docs/organization-tenancy.md`).\n *\n * Each entry names one legacy behaviour a live request can still take today.\n * The metric built from them is deliberately a COUNTER of lane USES, and it\n * measures exactly one thing: **is this lane still being exercised?** That is\n * the question the tenancy cutover gate (\"zero incompatible writers\") actually\n * asks, and it is answerable.\n *\n * It is emphatically NOT a burndown of unmigrated rows, and must never be\n * relabelled as one. Every one of these lanes is still *open*: the live write\n * paths keep producing rows in it, so no row-count predicate over any of them\n * can reach zero and a backlog gauge would read as a permanent, untruthful\n * unmigrated backlog. `docs/organization-tenancy.md` records, per lane, why -\n * including the lanes deliberately left uninstrumented because no truthful\n * signal exists for them yet.\n *\n * The recorded value is the lane name and nothing else. No organization,\n * workspace, session, subject, connection, or resource identity, and no\n * credential, name, or content, may ever become a label here.\n */\nexport const TENANCY_COMPATIBILITY_LANES = [\n /**\n * A provider connection carrying `authority_scope = 'legacy_user'` was\n * resolved for accepted use: a personal row with no common authority or\n * grant, admitted through `legacy_user_compatibility` provenance instead of\n * an explicit delegation. Migration 0256 backfilled the existing rows, but\n * its `bind_connection_authority` trigger still classifies a NEW personal\n * connection this way whenever the inserting subject has no active\n * organization membership, so this counter is expected to stay above zero\n * until that classification changes. That is the finding, not a defect.\n */\n \"connection_legacy_user\",\n /**\n * A workspace-scope connection ref carried no connection id, so the\n * accepted-use authority (migration 0279) could not identify the exact row\n * and the request fell back to the unprivileged pre-snapshot resolution.\n * This lane writes no `connection_use_audit_facts` row and leaves no durable\n * trace of any kind, so a use counter is the only possible evidence it was\n * taken at all.\n */\n \"connection_pre_snapshot_ref\",\n /**\n * A NEW persistable `/workspace` mutation was refused because the writer\n * behind it has no recorded authority (`authority_unattributed`): either a\n * direct request whose principal froze the pre-0096 legacy initiator, or a\n * retained process whose pre-0277 row has no tenancy half. This counts\n * REFUSED MUTATIONS, not unattributed rows - the turn and process admission\n * lanes deliberately still accept a `legacy_unattributed` initiator, and\n * nothing may invent the missing authority or disturb the running provider\n * process.\n */\n \"workspace_writer_unattributed\",\n] as const;\nexport type TenancyCompatibilityLane = (typeof TENANCY_COMPATIBILITY_LANES)[number];\n\nconst TENANCY_COMPATIBILITY_LANE_SET = new Set<string>(TENANCY_COMPATIBILITY_LANES);\n\nconst TENANCY_COMPATIBILITY_LANE_METRIC = {\n name: \"opengeni_tenancy_compatibility_lane_uses_total\",\n help: \"Live uses of an organization-tenancy compatibility lane, by lane.\",\n} as const;\n\n/**\n * Record one live use of a tenancy compatibility lane. Fail-safe by\n * construction: telemetry must never change an authorization or credential\n * outcome, so a registry failure is counted best-effort and swallowed here.\n */\nexport function recordTenancyCompatibilityLaneUse(\n observability: Observability | null | undefined,\n lane: TenancyCompatibilityLane,\n): void {\n if (!observability) return;\n // An unreviewed lane name must not silently mint a new series.\n if (!TENANCY_COMPATIBILITY_LANE_SET.has(lane)) return;\n try {\n observability.incrementCounter({ ...TENANCY_COMPATIBILITY_LANE_METRIC, labels: { lane } });\n } catch {\n recordObserverFailure(observability, \"tenancy_compatibility_lane\");\n }\n}\n\nconst INTERACTION_RESOURCES = new Set([\"browser\", \"computer\"]);\nconst INTERACTION_OPERATIONS = new Set([\n \"create\",\n \"end\",\n \"suspend\",\n \"resume\",\n \"publish\",\n \"observe\",\n \"act\",\n \"open_target\",\n \"select_target\",\n \"close_target\",\n \"attach\",\n \"auth_start\",\n \"auth_report\",\n \"auth_fill\",\n \"auth_verify\",\n \"intervention_create\",\n \"intervention_resolve\",\n]);\nconst INTERACTION_OUTCOMES = new Set([\n \"prepared\",\n \"dispatched\",\n \"completed\",\n \"failed\",\n \"outcome_unknown\",\n \"stale\",\n \"cancelled\",\n]);\nconst INTERACTION_MODES = new Set([\n \"semantic\",\n \"coordinate\",\n \"keyboard\",\n \"clipboard\",\n \"permission\",\n \"lifecycle\",\n \"media\",\n \"auth\",\n \"human\",\n]);\nconst INTERACTION_AUTH_STATES = new Set([\n \"discovering\",\n \"awaiting_choice\",\n \"awaiting_secret\",\n \"awaiting_external_action\",\n \"working\",\n \"verified\",\n \"failed\",\n \"cancelled\",\n]);\nconst INTERACTION_INTERVENTION_KINDS = new Set([\n \"manual_login\",\n \"mfa\",\n \"external_action\",\n \"confirmation\",\n \"other\",\n]);\nconst INTERACTION_INTERVENTION_OUTCOMES = new Set([\n \"opened\",\n \"completed\",\n \"dismissed\",\n \"expired\",\n \"cancelled\",\n]);\nconst WORKSPACE_INSIGHTS_RANGES = new Set([\"today\", \"week\", \"month\", \"ytd\"]);\nconst WORKSPACE_INSIGHTS_OUTCOMES = new Set([\"completed\", \"failed\"]);\nconst workspaceInsightsDurationHistogramBuckets = [0.05, 0.1, 0.25, 0.5, 1, 1.5, 2, 3, 5, 10, 30];\nconst PUBLIC_STARTUP_DEPENDENCIES = new Set([\n \"Modal private-registry image\",\n \"NATS\",\n \"PostgreSQL runtime posture\",\n \"Temporal\",\n \"Temporal client\",\n \"Temporal schedule (file upload reaper)\",\n \"Temporal schedule (sandbox reaper)\",\n \"Temporal schedule (session-workflow wake dispatcher)\",\n \"Temporal schedule (site auth maintenance)\",\n]);\n\n/**\n * External logs and OTLP are public/third-party projections, not canonical\n * OpenGeni storage. Only this reviewed closed set of operational fields may\n * cross that boundary. Unknown keys are omitted regardless of their value, so\n * a new diagnostic, identifier, command, response, or provider field cannot\n * become public by accident. This is schema projection, never value inspection\n * or rewriting.\n */\nconst PUBLIC_TELEMETRY_ATTRIBUTE_KEYS = new Set([\n \"http.request.method\",\n \"http.response.status_code\",\n \"opengeni.route\",\n \"opengeni.duration_ms\",\n \"opengeni.finalization_duration_ms\",\n \"opengeni.trigger_kind\",\n \"opengeni.status\",\n \"error.type\",\n \"error.status_code\",\n \"method\",\n \"route\",\n \"status\",\n \"durationMs\",\n \"attempt\",\n \"attempts\",\n \"delayMs\",\n \"provider\",\n \"providerApi\",\n \"model\",\n \"inputTokens\",\n \"outputTokens\",\n \"cachedTokens\",\n \"cacheWriteTokens\",\n \"reasoningTokens\",\n \"accountChangedFromPrevCall\",\n \"rejectedFields\",\n \"dependency\",\n \"activity\",\n \"backend\",\n \"op\",\n \"outcome\",\n \"eventType\",\n \"surface\",\n \"reason\",\n \"originalBytes\",\n \"deliveredBytes\",\n \"estimatedOriginalTokens\",\n \"estimatedDeliveredTokens\",\n \"fullEvidenceAvailable\",\n \"retainedOutputKind\",\n]);\n\n/** Opaque correlation fields require both a reviewed name and a closed value\n * grammar. Merely adding one to the ordinary allow-list would let an unrelated\n * caller accidentally publish a raw identifier under that name. */\nconst PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS = new Map<string, RegExp>([\n [\"sandboxLeaseKey\", /^slk_[0-9a-f]{32}$/],\n [\"correlationId\", /^[A-Za-z0-9._:-]{1,128}$/],\n]);\n\nconst PUBLIC_CHANNEL_A_OPERATIONS = new Set([\n \"fs.list\",\n \"fs.list-batch\",\n \"fs.read\",\n \"fs.write\",\n \"fs.delete\",\n \"fs.move\",\n \"fs.mkdir\",\n \"git.status\",\n \"git.diff\",\n \"git.read-batch\",\n \"git.log\",\n \"git.show\",\n \"terminal.exec\",\n \"terminal.pty.open\",\n \"terminal.pty.write\",\n \"terminal.pty.resize\",\n \"terminal.pty.close\",\n \"read\",\n \"mutation\",\n]);\n\nconst PUBLIC_CHANNEL_A_FAILURE_REASONS = new Set([\n \"request_cancelled\",\n \"provider_read_busy\",\n \"provider_unavailable\",\n \"lifecycle_conflict\",\n \"request_rejected\",\n \"unexpected\",\n]);\n\nconst PUBLIC_API_FATAL_PHASES = new Set([\"startup\", \"running\"]);\nconst PUBLIC_API_FATAL_REASON_KINDS = new Set([\n \"bigint\",\n \"boolean\",\n \"error\",\n \"function\",\n \"null\",\n \"number\",\n \"object\",\n \"string\",\n \"symbol\",\n \"undefined\",\n]);\n\n/**\n * Public diagnostic values are protocol constants, never values inferred from\n * an exception's name, constructor, code, message, or enumerable properties.\n * Unknown classes collapse to one fixed fallback; unknown codes and origins\n * are omitted rather than copied through based on syntax.\n */\nconst PUBLIC_TELEMETRY_ERROR_CLASSES = new Set([\n \"ApiFatalOperationError\",\n \"OperationError\",\n \"CodexCheckpointOperationError\",\n \"CodexFleetShadowOperationError\",\n \"ComputerActionTimeoutError\",\n \"ComputerUnavailableError\",\n \"CredentialRenewalOperationError\",\n \"CredentialReadOperationError\",\n \"EventPublishOperationError\",\n \"GitCredentialRenewalOperationError\",\n \"HostExportOperationError\",\n \"HttpOperationError\",\n \"McpLifecycleError\",\n \"McpOperationError\",\n \"MemoryEmbeddingOperationError\",\n \"MemorySearchOperationError\",\n \"NatsAuthCalloutOperationError\",\n \"OAuthOperationError\",\n \"RunCredentialRenewalOperationError\",\n \"RunStateCompatibilityError\",\n \"SandboxChannelAOperationError\",\n \"SnapshotOperationError\",\n \"StartupDependencyError\",\n \"TelemetryExportError\",\n \"CodemodeOperationError\",\n \"CodemodeTokenRenewalOperationError\",\n \"WorkerLifecycleOperation\",\n \"WorkerLifecycleOperationError\",\n \"WorkerOperationError\",\n \"WorkflowWakeOperationError\",\n]);\n\nconst PUBLIC_TELEMETRY_ERROR_CODES = new Set([\n \"agent_command_wake_failed\",\n \"api_startup_failed\",\n \"api_uncaught_exception\",\n \"api_unhandled_rejection\",\n \"artifact_materializer_native_input_framing_failed\",\n \"artifact_materializer_native_snapshot_open_failed\",\n \"artifact_materializer_native_state_mismatch\",\n \"artifact_materializer_source_content_type_mismatch\",\n \"artifact_materializer_source_open_failed\",\n \"artifact_materializer_source_revalidation_failed\",\n \"artifact_materializer_source_stream_identity_mismatch\",\n \"cleared_goal_live_publish_failed\",\n \"codex_failover_checkpoint_failed\",\n \"codex_fleet_shadow_failed\",\n \"codex_lease_loss_checkpoint_failed\",\n \"codex_active_credential_read_failed\",\n \"command_yield_timeout\",\n \"conflict\",\n \"control_wake_dispatch_failed\",\n \"fenced_event_live_publish_failed\",\n \"forbidden\",\n \"host_export_batch_delivery_failed\",\n \"host_export_failure_settlement_stale\",\n \"host_export_pump_iteration_failed\",\n \"host_export_retention_prune_failed\",\n \"idempotency_conflict\",\n \"incompatible_exposed_ports\",\n \"internal_error\",\n \"limit_exceeded\",\n \"mcp_close_failed\",\n \"mcp_connect_failed\",\n \"mcp_tool_call_failed\",\n \"mcp_tools_list_failed\",\n \"mcp_transport_failed\",\n \"memory_edit_embedding_failed\",\n \"memory_hybrid_vector_failed\",\n \"memory_save_embedding_failed\",\n \"nats_auth_callout_start_failed\",\n \"nested_agent_depth_exceeded\",\n \"nested_agent_depth_override_forbidden\",\n \"not_found\",\n \"oauth_operation_failed\",\n \"otlp_export_failed\",\n \"payment_required\",\n \"provider_verification_failed\",\n \"sandbox_channel_a_cancelled\",\n \"sandbox_channel_a_lifecycle_conflict\",\n \"sandbox_channel_a_operation_failed\",\n \"sandbox_channel_a_provider_busy\",\n \"sandbox_channel_a_provider_unavailable\",\n \"screenshot_capture_failed\",\n \"session_event_live_publish_failed\",\n \"session_workflow_wake_failed\",\n \"snapshot_operation_failed\",\n \"startup_dependency_retry\",\n \"tool_list_too_large\",\n \"tool_result_too_large\",\n \"codemode_operation_failed\",\n \"unauthenticated\",\n \"upstream_unavailable\",\n \"validation_failed\",\n \"worker_draining\",\n \"worker_operation_failed\",\n \"worker_shutdown_request_failed\",\n \"workspace_control_live_publish_failed\",\n]);\n\nconst PUBLIC_TELEMETRY_ERROR_ORIGINS = new Set([\n \"api\",\n \"core\",\n \"db\",\n \"events\",\n \"host-export\",\n \"oauth\",\n \"observability\",\n \"runtime\",\n \"sandbox-resume\",\n \"codemode\",\n \"worker\",\n \"worker-lifecycle\",\n]);\n\nexport type SandboxOperationMetricObservation = {\n backend: string;\n op: string;\n outcome: \"ok\" | \"not_found\" | \"failed\";\n durationMs: number;\n};\n\nexport function createObservability(\n settings: ObservabilitySettings,\n options: ObservabilityOptions,\n): Observability {\n return new Observability(settings, options);\n}\n\ntype MetricRegistration = {\n kind: \"counter\" | \"gauge\" | \"histogram\";\n labelNames: string[];\n};\n\nexport class Observability {\n private readonly registry = new Registry();\n private readonly counters = new Map<string, Counter<string>>();\n private readonly gauges = new Map<string, Gauge<string>>();\n private readonly histograms = new Map<string, Histogram<string>>();\n private readonly registrations = new Map<string, MetricRegistration>();\n private readonly pendingExports = new Set<Promise<void>>();\n private readonly now: () => number;\n private readonly exporter: (\n url: string,\n body: unknown,\n headers: Record<string, string>,\n ) => Promise<void>;\n private readonly resourceAttributes: Attributes;\n\n constructor(\n private readonly settings: ObservabilitySettings,\n private readonly options: ObservabilityOptions,\n ) {\n this.now = options.now ?? Date.now;\n this.exporter = options.exporter ?? defaultExporter;\n this.resourceAttributes = {\n \"service.name\": settings.serviceName,\n \"deployment.environment\": settings.environment,\n \"opengeni.component\": options.component,\n };\n this.registry.setDefaultLabels({\n service: settings.serviceName,\n environment: settings.environment,\n component: options.component,\n deployment_revision: settings.deploymentRevision ?? \"dev\",\n });\n if (settings.observabilityMetricsEnabled) {\n collectDefaultMetrics({ register: this.registry, prefix: \"opengeni_\" });\n this.setGauge({\n name: \"opengeni_build_info\",\n help: \"OpenGeni build information.\",\n labels: {\n version: buildVersion(),\n revision: settings.deploymentRevision ?? \"dev\",\n },\n value: 1,\n });\n this.registerSandboxRolloutConfig();\n this.registerTenancyCompatibilityLanes();\n }\n }\n\n /**\n * Publish every compatibility lane at zero on startup. Without this an\n * un-exercised lane has no series at all, and an operator cannot tell \"this\n * lane is dormant\" from \"this lane was never wired up\" - the two readings\n * that matter most to a cutover gate.\n */\n private registerTenancyCompatibilityLanes(): void {\n for (const lane of TENANCY_COMPATIBILITY_LANES) {\n this.incrementCounter({ ...TENANCY_COMPATIBILITY_LANE_METRIC, labels: { lane }, amount: 0 });\n }\n }\n\n private registerSandboxRolloutConfig(): void {\n const ownership = this.settings.sandboxOwnershipEnabled;\n const lazyConfigured = this.settings.sandboxLazyProvisionEnabled;\n const rigVerification = this.settings.rigVerificationLeaseOwnershipEnabled;\n if (\n typeof ownership !== \"boolean\" ||\n typeof lazyConfigured !== \"boolean\" ||\n typeof rigVerification !== \"boolean\"\n ) {\n return;\n }\n\n const values = [\n [\"ownership\", \"configured\", ownership],\n [\"ownership\", \"effective\", ownership],\n [\"lazy_provision\", \"configured\", lazyConfigured],\n [\"lazy_provision\", \"effective\", ownership && lazyConfigured],\n [\"rig_verification_lease_ownership\", \"configured\", rigVerification],\n [\"rig_verification_lease_ownership\", \"effective\", rigVerification],\n ] as const;\n for (const [feature, state, enabled] of values) {\n this.setGauge({\n name: \"opengeni_sandbox_rollout_config\",\n help: \"Configured and effective sandbox rollout state for this workload revision.\",\n labels: { feature, state },\n value: enabled ? 1 : 0,\n });\n }\n }\n\n debug(message: string, attributes: Attributes = {}): void {\n this.log(\"debug\", message, attributes);\n }\n\n info(message: string, attributes: Attributes = {}): void {\n this.log(\"info\", message, attributes);\n }\n\n warn(message: string, attributes: Attributes = {}): void {\n this.log(\"warn\", message, attributes);\n }\n\n error(message: string, attributes: Attributes = {}): void {\n this.log(\"error\", message, attributes);\n }\n\n log(\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n attributes: Attributes = {},\n ): void {\n const publicAttributes = projectPublicTelemetryAttributes(attributes);\n if (!this.settings.observabilityStructuredLogs) {\n if (level === \"warn\") {\n console.warn(message);\n } else if (level === \"error\") {\n console.error(message);\n } else {\n console.log(message);\n }\n return;\n }\n const record = {\n timestamp: new Date(this.now()).toISOString(),\n level,\n message,\n service: this.settings.serviceName,\n environment: this.settings.environment,\n component: this.options.component,\n ...cleanAttributes(publicAttributes),\n };\n const serialized = JSON.stringify(record);\n if (level === \"warn\") {\n console.warn(serialized);\n } else if (level === \"error\") {\n console.error(serialized);\n } else {\n console.log(serialized);\n }\n }\n\n startSpan(name: string, attributes: Attributes = {}): Span {\n const traceId = randomHex(16);\n const spanId = randomHex(8);\n const startMs = this.now();\n let ended = false;\n return {\n traceId,\n spanId,\n end: (input = {}) => {\n if (ended) {\n return;\n }\n ended = true;\n const telemetryError =\n input.error !== undefined && input.error !== null\n ? projectSpanErrorForTelemetry(input.error)\n : undefined;\n const errorAttributes = telemetryError ? errorToAttributes(telemetryError) : {};\n this.exportSpan({\n traceId,\n spanId,\n name,\n startMs,\n endMs: this.now(),\n attributes: {\n ...projectPublicTelemetryAttributes({\n ...attributes,\n ...input.attributes,\n ...errorAttributes,\n }),\n },\n ...(telemetryError ? { error: telemetryError } : {}),\n });\n },\n };\n }\n\n recordHttpRequest(input: {\n method: string;\n route: string;\n status: number;\n durationSeconds: number;\n }): void {\n this.incrementCounter({\n name: \"opengeni_http_requests_total\",\n help: \"Total HTTP requests handled by OpenGeni.\",\n labels: {\n method: input.method,\n route: input.route,\n status: String(input.status),\n component: this.options.component,\n },\n });\n this.observeHistogram({\n name: \"opengeni_http_request_duration_seconds\",\n help: \"HTTP request duration in seconds.\",\n buckets: httpHistogramBuckets,\n value: input.durationSeconds,\n labels: {\n method: input.method,\n route: input.route,\n component: this.options.component,\n },\n });\n }\n\n recordWorkerActivity(input: { activity: string; status: string; durationSeconds: number }): void {\n this.incrementCounter({\n name: \"opengeni_worker_activity_runs_total\",\n help: \"Total worker activity executions.\",\n labels: {\n activity: input.activity,\n status: input.status,\n component: this.options.component,\n },\n });\n this.observeHistogram({\n name: \"opengeni_worker_activity_duration_seconds\",\n help: \"Worker activity duration in seconds.\",\n buckets: durationHistogramBuckets,\n value: input.durationSeconds,\n labels: {\n activity: input.activity,\n component: this.options.component,\n },\n });\n }\n\n incrementCounter(input: {\n name: string;\n help?: string;\n labels?: MetricLabels;\n amount?: number;\n }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const counter = this.counter(\n input.name,\n input.help ?? `${input.name} counter.`,\n Object.keys(labels),\n );\n counter.inc(labels as never, input.amount ?? 1);\n }\n\n setGauge(input: { name: string; help?: string; labels?: MetricLabels; value: number }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const gauge = this.gauge(input.name, input.help ?? `${input.name} gauge.`, Object.keys(labels));\n gauge.set(labels as never, input.value);\n }\n\n incrementGauge(input: {\n name: string;\n help?: string;\n labels?: MetricLabels;\n amount?: number;\n }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const gauge = this.gauge(input.name, input.help ?? `${input.name} gauge.`, Object.keys(labels));\n gauge.inc(labels as never, input.amount ?? 1);\n }\n\n observeHistogram(input: {\n name: string;\n help?: string;\n labels?: MetricLabels;\n value: number;\n buckets?: number[];\n }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const histogram = this.histogram(\n input.name,\n input.help ?? `${input.name} histogram.`,\n Object.keys(labels),\n input.buckets ?? durationHistogramBuckets,\n );\n histogram.observe(labels as never, input.value);\n }\n\n async prometheusMetrics(): Promise<string> {\n if (!this.settings.observabilityMetricsEnabled) {\n return \"\";\n }\n return await this.registry.metrics();\n }\n\n /** Wait for every OTLP export accepted before or during this drain. */\n async flush(): Promise<void> {\n while (this.pendingExports.size > 0) {\n await Promise.allSettled([...this.pendingExports]);\n }\n }\n\n private counter(name: string, help: string, labelNames: string[]): Counter<string> {\n const existing = this.counters.get(name);\n if (existing) {\n this.assertRegistration(name, \"counter\", labelNames);\n return existing;\n }\n this.register(name, \"counter\", labelNames);\n const metric = new Counter({ name, help, labelNames, registers: [this.registry] });\n this.counters.set(name, metric);\n return metric;\n }\n\n private gauge(name: string, help: string, labelNames: string[]): Gauge<string> {\n const existing = this.gauges.get(name);\n if (existing) {\n this.assertRegistration(name, \"gauge\", labelNames);\n return existing;\n }\n this.register(name, \"gauge\", labelNames);\n const metric = new Gauge({ name, help, labelNames, registers: [this.registry] });\n this.gauges.set(name, metric);\n return metric;\n }\n\n private histogram(\n name: string,\n help: string,\n labelNames: string[],\n buckets: number[],\n ): Histogram<string> {\n const existing = this.histograms.get(name);\n if (existing) {\n this.assertRegistration(name, \"histogram\", labelNames);\n return existing;\n }\n this.register(name, \"histogram\", labelNames);\n const metric = new Histogram({ name, help, labelNames, buckets, registers: [this.registry] });\n this.histograms.set(name, metric);\n return metric;\n }\n\n private register(name: string, kind: MetricRegistration[\"kind\"], labelNames: string[]): void {\n const sorted = [...labelNames].sort();\n this.registrations.set(name, { kind, labelNames: sorted });\n }\n\n private assertRegistration(\n name: string,\n kind: MetricRegistration[\"kind\"],\n labelNames: string[],\n ): void {\n const registration = this.registrations.get(name);\n const sorted = [...labelNames].sort();\n if (\n !registration ||\n registration.kind !== kind ||\n registration.labelNames.length !== sorted.length ||\n registration.labelNames.some((label, index) => label !== sorted[index])\n ) {\n throw new Error(\n `Metric ${name} was already registered as ${registration?.kind ?? \"unknown\"} ` +\n `with labels [${registration?.labelNames.join(\",\") ?? \"\"}], not ${kind} [${sorted.join(\",\")}]`,\n );\n }\n }\n\n private exportSpan(span: {\n traceId: string;\n spanId: string;\n name: string;\n startMs: number;\n endMs: number;\n attributes: Attributes;\n error?: TelemetrySpanError;\n }): void {\n if (!this.settings.observabilityOtlpEndpoint) {\n return;\n }\n const endpoint = `${this.settings.observabilityOtlpEndpoint.replace(/\\/$/, \"\")}/v1/traces`;\n const body = {\n resourceSpans: [\n {\n resource: {\n attributes: otlpAttributes(this.resourceAttributes),\n },\n scopeSpans: [\n {\n scope: {\n name: \"@opengeni/observability\",\n version: \"0.1.0\",\n },\n spans: [\n {\n traceId: span.traceId,\n spanId: span.spanId,\n name: span.name,\n kind: 1,\n startTimeUnixNano: millisToNanos(span.startMs),\n endTimeUnixNano: millisToNanos(span.endMs),\n attributes: otlpAttributes(span.attributes),\n status: span.error ? { code: 2, message: span.error.statusMessage } : { code: 1 },\n },\n ],\n },\n ],\n },\n ],\n };\n let pendingExport: Promise<void>;\n pendingExport = Promise.resolve()\n .then(() =>\n this.exporter(endpoint, body, parseHeaders(this.settings.observabilityOtlpHeaders)),\n )\n .catch(() => {\n this.warn(\"OTLP span export failed\", {\n errorClass: \"TelemetryExportError\",\n errorCode: \"otlp_export_failed\",\n origin: \"observability\",\n });\n })\n .finally(() => {\n this.pendingExports.delete(pendingExport);\n });\n this.pendingExports.add(pendingExport);\n }\n}\n\n/**\n * Convert routed sandbox-provider observations into one bounded Prometheus\n * contract shared by API-direct and worker-turn execution. Provider/session\n * identifiers, commands, paths, and other request data can never become labels:\n * a future backend or operation is deliberately collapsed to `unknown` until\n * this allowlist is reviewed.\n *\n * The returned callback is fail-safe. Metrics must never change the provider\n * operation's result; a registration/exporter error is counted best-effort and\n * then swallowed at this telemetry boundary.\n */\nexport function sandboxOperationMetricObserver(\n observability: Observability,\n): (observation: SandboxOperationMetricObservation) => void {\n return (observation) => {\n const backend = SANDBOX_OPERATION_BACKENDS.has(observation.backend)\n ? observation.backend\n : \"unknown\";\n const op = SANDBOX_OPERATION_NAMES.has(observation.op) ? observation.op : \"unknown\";\n try {\n observability.incrementCounter({\n name: \"opengeni_sandbox_operations_total\",\n help: \"Physical routed sandbox provider operations by backend, operation, and outcome.\",\n labels: { backend, op, outcome: observation.outcome },\n });\n observability.observeHistogram({\n name: \"opengeni_sandbox_operation_duration_seconds\",\n help: \"Physical routed sandbox provider-operation duration in seconds.\",\n labels: { backend, op },\n value: Math.max(0, observation.durationMs) / 1_000,\n });\n } catch {\n try {\n observability.incrementCounter({\n name: \"opengeni_observability_observer_errors_total\",\n help: \"Observability observer failures isolated from product execution.\",\n labels: { observer: \"sandbox_operation\" },\n });\n } catch {\n // The metrics registry itself is unhealthy. Product execution remains\n // authoritative and must not inherit an observability failure.\n }\n }\n };\n}\n\nexport type InteractionOperationMetricObservation = {\n resource: string;\n operation: string;\n outcome: string;\n mode: string;\n durationMs: number;\n replayed?: boolean | undefined;\n};\n\n/** Safe low-cardinality telemetry for Browser/Computer control operations.\n * Resource ids, URLs, locators, page/app text, and input values are excluded by\n * construction. Unknown future enum values collapse until explicitly reviewed. */\nexport function interactionOperationMetricObserver(\n observability: Observability | null | undefined,\n): (observation: InteractionOperationMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n if (observation.replayed) return;\n const resource = boundedMetricEnum(INTERACTION_RESOURCES, observation.resource);\n const operation = boundedMetricEnum(INTERACTION_OPERATIONS, observation.operation);\n const outcome = boundedMetricEnum(INTERACTION_OUTCOMES, observation.outcome);\n const mode = boundedMetricEnum(INTERACTION_MODES, observation.mode);\n try {\n observability.incrementCounter({\n name: \"opengeni_interaction_operations_total\",\n help: \"Browser and Computer operations by bounded resource, operation, mode, and outcome.\",\n labels: { resource, operation, mode, outcome },\n });\n observability.observeHistogram({\n name: \"opengeni_interaction_operation_duration_seconds\",\n help: \"Browser and Computer operation duration in seconds.\",\n labels: { resource, operation, mode },\n value: boundedMetricDuration(observation.durationMs),\n });\n } catch {\n recordObserverFailure(observability, \"interaction_operation\");\n }\n };\n}\n\nexport type InteractionAuthMetricObservation = {\n state: string;\n durationMs: number;\n replayed?: boolean | undefined;\n};\n\nexport function interactionAuthMetricObserver(\n observability: Observability | null | undefined,\n): (observation: InteractionAuthMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n if (observation.replayed) return;\n const state = boundedMetricEnum(INTERACTION_AUTH_STATES, observation.state);\n try {\n observability.incrementCounter({\n name: \"opengeni_interaction_auth_transitions_total\",\n help: \"Browser authentication transitions by bounded resulting state.\",\n labels: { state },\n });\n observability.observeHistogram({\n name: \"opengeni_interaction_auth_transition_duration_seconds\",\n help: \"Browser authentication transition request duration in seconds.\",\n labels: { state },\n value: boundedMetricDuration(observation.durationMs),\n });\n } catch {\n recordObserverFailure(observability, \"interaction_auth\");\n }\n };\n}\n\nexport type InteractionInterventionMetricObservation = {\n kind: string;\n outcome: string;\n waitMs?: number | undefined;\n replayed?: boolean | undefined;\n};\n\nexport function interactionInterventionMetricObserver(\n observability: Observability | null | undefined,\n): (observation: InteractionInterventionMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n if (observation.replayed) return;\n const kind = boundedMetricEnum(INTERACTION_INTERVENTION_KINDS, observation.kind);\n const outcome = boundedMetricEnum(INTERACTION_INTERVENTION_OUTCOMES, observation.outcome);\n try {\n observability.incrementCounter({\n name: \"opengeni_interaction_interventions_total\",\n help: \"Human browser/computer interventions by bounded kind and outcome.\",\n labels: { kind, outcome },\n });\n if (observation.waitMs !== undefined) {\n observability.observeHistogram({\n name: \"opengeni_interaction_intervention_wait_seconds\",\n help: \"Time an interaction intervention remained open before settlement.\",\n labels: { kind, outcome },\n value: boundedMetricDuration(observation.waitMs),\n });\n }\n } catch {\n recordObserverFailure(observability, \"interaction_intervention\");\n }\n };\n}\n\nexport type WorkspaceInsightsMetricObservation = {\n range: string;\n providerFiltered: boolean;\n modelFiltered: boolean;\n outcome: string;\n durationMs: number;\n};\n\n/**\n * Identity-free route timing for Workspace Insights. The dedicated two-second\n * bucket is the service target; fixed enums and filter-presence flags keep\n * tenant ids and caller-supplied provider/model values out of telemetry.\n */\nexport function workspaceInsightsMetricObserver(\n observability: Observability | null | undefined,\n): (observation: WorkspaceInsightsMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n const range = boundedMetricEnum(WORKSPACE_INSIGHTS_RANGES, observation.range);\n const outcome = boundedMetricEnum(WORKSPACE_INSIGHTS_OUTCOMES, observation.outcome);\n const providerFilter = observation.providerFiltered ? \"filtered\" : \"all\";\n const modelFilter = observation.modelFiltered ? \"filtered\" : \"all\";\n const durationSeconds = boundedMetricDuration(observation.durationMs);\n try {\n observability.observeHistogram({\n name: \"opengeni_workspace_insights_request_duration_seconds\",\n help: \"Workspace Insights route service duration by bounded range, filter presence, and outcome.\",\n buckets: workspaceInsightsDurationHistogramBuckets,\n labels: {\n range,\n provider_filter: providerFilter,\n model_filter: modelFilter,\n outcome,\n },\n value: durationSeconds,\n });\n observability.info(\"Workspace Insights request measured\", {\n surface: \"workspace_insights\",\n eventType: \"request_latency\",\n route: \"/v1/workspaces/:workspaceId/insights\",\n outcome,\n durationMs: Math.round(durationSeconds * 1_000),\n });\n } catch {\n recordObserverFailure(observability, \"workspace_insights\");\n }\n };\n}\n\nfunction boundedMetricEnum(allowed: ReadonlySet<string>, value: string): string {\n return allowed.has(value) ? value : \"unknown\";\n}\n\nfunction boundedMetricDuration(durationMs: number): number {\n return Number.isFinite(durationMs) ? Math.max(0, durationMs) / 1_000 : 0;\n}\n\nfunction recordObserverFailure(observability: Observability, observer: string): void {\n try {\n observability.incrementCounter({\n name: \"opengeni_observability_observer_errors_total\",\n help: \"Observability observer failures isolated from product execution.\",\n labels: { observer },\n });\n } catch {\n // The metrics registry itself is unhealthy. Product execution remains\n // authoritative and must not inherit an observability failure.\n }\n}\n\nexport type StartupDependencyRetryEvent = {\n label: string;\n attempt: number;\n attempts: number;\n delayMs: number;\n error: unknown;\n};\n\nexport function logStartupDependencyRetry(\n observability: Observability,\n event: StartupDependencyRetryEvent,\n): void {\n const dependency = PUBLIC_STARTUP_DEPENDENCIES.has(event.label) ? event.label : \"Dependency\";\n observability.warn(\n `Startup dependency ${dependency} connection failed; retrying (${event.attempt}/${event.attempts} in ${event.delayMs}ms)`,\n {\n dependency,\n attempt: event.attempt,\n attempts: event.attempts,\n delayMs: event.delayMs,\n errorClass: \"StartupDependencyError\",\n errorCode: \"startup_dependency_retry\",\n origin: \"observability\",\n },\n );\n}\n\nfunction normalizeLabels(labels: MetricLabels = {}): Record<string, string> {\n return Object.fromEntries(\n Object.entries(labels)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]): [string, string] => [key, String(value)])\n .sort((left, right) => left[0].localeCompare(right[0])),\n );\n}\n\nfunction buildVersion(): string {\n return process.env.OPENGENI_VERSION ?? process.env.npm_package_version ?? \"dev\";\n}\n\nfunction cleanAttributes(attributes: Attributes): Record<string, string | number | boolean | null> {\n return Object.fromEntries(\n Object.entries(attributes).filter(([, value]) => value !== undefined),\n ) as Record<string, string | number | boolean | null>;\n}\n\nfunction projectPublicTelemetryAttributes(attributes: Attributes): Attributes {\n if (\"errorClass\" in attributes || \"errorCode\" in attributes) {\n return {\n ...projectStartupDependencyAttributes(attributes),\n ...projectPublicChannelADiagnosticAttributes(attributes),\n ...projectApiFatalDiagnosticAttributes(attributes),\n ...projectPublicDiagnosticAttributes(attributes),\n };\n }\n return Object.fromEntries(\n Object.entries(attributes).filter(([key, value]) => {\n if (value === undefined) return false;\n if (PUBLIC_TELEMETRY_ATTRIBUTE_KEYS.has(key)) return true;\n const pattern = PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS.get(key);\n return typeof value === \"string\" && pattern?.test(value) === true;\n }),\n );\n}\n\nfunction projectApiFatalDiagnosticAttributes(attributes: Attributes): Attributes {\n if (attributes.errorClass !== \"ApiFatalOperationError\") return {};\n const phase = attributes.phase;\n const reasonKind = attributes.reasonKind;\n return {\n ...(typeof phase === \"string\" && PUBLIC_API_FATAL_PHASES.has(phase) ? { phase } : {}),\n ...(typeof reasonKind === \"string\" && PUBLIC_API_FATAL_REASON_KINDS.has(reasonKind)\n ? { reasonKind }\n : {}),\n };\n}\n\nfunction projectStartupDependencyAttributes(attributes: Attributes): Attributes {\n if (\n attributes.errorClass !== \"StartupDependencyError\" ||\n attributes.errorCode !== \"startup_dependency_retry\"\n ) {\n return {};\n }\n const dependency = attributes.dependency;\n const attempt = attributes.attempt;\n const attempts = attributes.attempts;\n const delayMs = attributes.delayMs;\n return {\n ...(typeof dependency === \"string\" && PUBLIC_STARTUP_DEPENDENCIES.has(dependency)\n ? { dependency }\n : {}),\n ...(typeof attempt === \"number\" && Number.isInteger(attempt) && attempt > 0 ? { attempt } : {}),\n ...(typeof attempts === \"number\" && Number.isInteger(attempts) && attempts > 0\n ? { attempts }\n : {}),\n ...(typeof delayMs === \"number\" && Number.isFinite(delayMs) && delayMs >= 0 ? { delayMs } : {}),\n };\n}\n\nfunction projectPublicChannelADiagnosticAttributes(attributes: Attributes): Attributes {\n if (attributes.errorClass !== \"SandboxChannelAOperationError\") return {};\n const backend = attributes.backend;\n const op = attributes.op;\n const outcome = attributes.outcome;\n const reason = attributes.reason;\n const durationMs = attributes.durationMs;\n const sandboxLeaseKey = attributes.sandboxLeaseKey;\n return {\n ...(typeof backend === \"string\" && SANDBOX_OPERATION_BACKENDS.has(backend) ? { backend } : {}),\n ...(typeof op === \"string\" && PUBLIC_CHANNEL_A_OPERATIONS.has(op) ? { op } : {}),\n ...(outcome === \"failed\" ? { outcome } : {}),\n ...(typeof reason === \"string\" && PUBLIC_CHANNEL_A_FAILURE_REASONS.has(reason)\n ? { reason }\n : {}),\n ...(typeof durationMs === \"number\" && Number.isFinite(durationMs) && durationMs >= 0\n ? { durationMs }\n : {}),\n ...(typeof sandboxLeaseKey === \"string\" &&\n PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS.get(\"sandboxLeaseKey\")?.test(sandboxLeaseKey)\n ? { sandboxLeaseKey }\n : {}),\n };\n}\n\nfunction projectPublicDiagnosticAttributes(attributes: Attributes): Attributes {\n const errorClass = attributes.errorClass;\n const errorCode = attributes.errorCode;\n const status = attributes.status;\n const origin = attributes.origin;\n const correlationId = attributes.correlationId;\n return {\n errorClass:\n typeof errorClass === \"string\" && PUBLIC_TELEMETRY_ERROR_CLASSES.has(errorClass)\n ? errorClass\n : \"OperationError\",\n ...(typeof errorCode === \"string\" && PUBLIC_TELEMETRY_ERROR_CODES.has(errorCode)\n ? { errorCode }\n : {}),\n ...(typeof status === \"number\" && Number.isInteger(status) && status >= 100 && status <= 599\n ? { status }\n : {}),\n ...(typeof origin === \"string\" && PUBLIC_TELEMETRY_ERROR_ORIGINS.has(origin) ? { origin } : {}),\n ...(typeof correlationId === \"string\" &&\n PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS.get(\"correlationId\")?.test(correlationId)\n ? { correlationId }\n : {}),\n };\n}\n\ntype TelemetrySpanError = {\n type: string;\n statusCode?: number;\n statusMessage: string;\n};\n\n/**\n * External OTLP projection. It intentionally exports only error class/status\n * metadata and never mutates canonical OpenGeni errors, events, or history.\n */\nfunction projectSpanErrorForTelemetry(error: unknown): TelemetrySpanError {\n const statusCode = errorStatusCode(error);\n return {\n type: \"OperationError\",\n ...(statusCode === undefined ? {} : { statusCode }),\n statusMessage: statusCode === undefined ? \"operation failed\" : `HTTP ${statusCode}`,\n };\n}\n\nfunction errorStatusCode(error: unknown): number | undefined {\n if (typeof error !== \"object\" || error === null) return undefined;\n try {\n const value = (error as { status?: unknown; statusCode?: unknown }).status;\n const statusCode =\n Number.isInteger(value) && typeof value === \"number\"\n ? value\n : (error as { statusCode?: unknown }).statusCode;\n return Number.isInteger(statusCode) &&\n typeof statusCode === \"number\" &&\n statusCode >= 100 &&\n statusCode <= 599\n ? statusCode\n : undefined;\n } catch {\n // OTLP projection must never mask the exact internal failure.\n return undefined;\n }\n}\n\nfunction errorToAttributes(error: TelemetrySpanError): Attributes {\n return {\n \"error.type\": error.type,\n ...(error.statusCode === undefined ? {} : { \"error.status_code\": error.statusCode }),\n };\n}\n\nfunction otlpAttributes(\n attributes: Attributes,\n): Array<{ key: string; value: Record<string, string | number | boolean> }> {\n return Object.entries(cleanAttributes(attributes)).map(([key, value]) => ({\n key,\n value: otlpValue(value),\n }));\n}\n\nfunction otlpValue(\n value: string | number | boolean | null,\n): Record<string, string | number | boolean> {\n if (typeof value === \"number\") {\n return Number.isInteger(value) ? { intValue: value } : { doubleValue: value };\n }\n if (typeof value === \"boolean\") {\n return { boolValue: value };\n }\n return { stringValue: value === null ? \"\" : boundedOtlpString(value) };\n}\n\nfunction boundedOtlpString(value: string): string {\n const bytes = new TextEncoder().encode(value);\n if (bytes.byteLength <= 512) return value;\n return `${new TextDecoder().decode(bytes.slice(0, 509))}…`;\n}\n\nfunction millisToNanos(ms: number): string {\n return String(BigInt(Math.round(ms)) * 1_000_000n);\n}\n\nfunction randomHex(bytes: number): string {\n const values = crypto.getRandomValues(new Uint8Array(bytes));\n return Array.from(values, (value) => value.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport function parseHeaders(value: string): Record<string, string> {\n if (!value.trim()) {\n return {};\n }\n const entries: Array<[string, string]> = value\n .split(\",\")\n .map((pair): [string, string] => {\n const separator = pair.indexOf(\"=\");\n if (separator === -1) {\n return [pair.trim(), \"\"];\n }\n return [pair.slice(0, separator).trim(), pair.slice(separator + 1).trim()];\n })\n .filter(([key]) => key.length > 0);\n return Object.fromEntries(entries);\n}\n\nasync function defaultExporter(\n url: string,\n body: unknown,\n headers: Record<string, string>,\n): Promise<void> {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...headers,\n },\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n throw new Error(`OTLP endpoint returned HTTP ${response.status}`);\n }\n}\n"],"mappings":"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,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,+BAA+B,oBAAI,IAAI;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iCAAiC,oBAAI,IAAI;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASM,SAAS,oBACd,UACA,SACe;AACf,SAAO,IAAI,cAAc,UAAU,OAAO;AAC5C;AAOO,IAAM,gBAAN,MAAoB;AA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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { collectDefaultMetrics, Counter, Gauge, Histogram, Registry } from \"prom-client\";\nimport { SandboxBackend } from \"@opengeni/contracts\";\n\nexport type AttributeValue = string | number | boolean | null | undefined;\nexport type Attributes = Record<string, AttributeValue>;\n\nexport type ObservabilitySettings = {\n serviceName: string;\n environment: string;\n deploymentRevision?: string | undefined;\n observabilityStructuredLogs: boolean;\n observabilityMetricsEnabled: boolean;\n observabilityOtlpEndpoint?: string | undefined;\n observabilityOtlpHeaders: string;\n sandboxOwnershipEnabled?: boolean | undefined;\n sandboxLazyProvisionEnabled?: boolean | undefined;\n rigVerificationLeaseOwnershipEnabled?: boolean | undefined;\n};\n\nexport type ObservabilityOptions = {\n component: string;\n now?: () => number;\n exporter?: (url: string, body: unknown, headers: Record<string, string>) => Promise<void>;\n};\n\nexport type Span = {\n traceId: string;\n spanId: string;\n end: (input?: { attributes?: Attributes; error?: unknown }) => void;\n};\n\nexport type MetricLabels = Record<string, AttributeValue>;\n\n/**\n * Stable, non-reversible correlation key for one logical sandbox lease. Public\n * telemetry intentionally drops workspace/group identifiers; this key lets an\n * operator correlate API, worker, and reaper failures without publishing\n * either UUID. The domain separator prevents reuse as a generic identifier\n * digest.\n */\nexport function sandboxLeaseTelemetryKey(workspaceId: string, sandboxGroupId: string): string {\n return `slk_${createHash(\"sha256\")\n .update(\"opengeni:sandbox-lease-telemetry:v1\\0\")\n .update(workspaceId)\n .update(\"\\0\")\n .update(sandboxGroupId)\n .digest(\"hex\")\n .slice(0, 32)}`;\n}\n\n/**\n * Stable selectors shared by OpenGeni's runtime metrics and optional\n * Prometheus/Grafana distribution. Operators can use these values for custom\n * namespaces and dashboard ConfigMaps without duplicating chart internals.\n */\nexport const OPENGENI_OBSERVABILITY_DISTRIBUTION = {\n monitoringNamespaceLabel: \"opengeni.ai/monitoring\",\n monitoringNamespaceLabelValue: \"enabled\",\n grafanaDashboardLabel: \"grafana_dashboard\",\n grafanaDashboardLabelValue: \"1\",\n} as const;\n\nconst httpHistogramBuckets = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\nconst durationHistogramBuckets = [\n 0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300, 900, 1800, 3600,\n];\n\nconst SANDBOX_OPERATION_BACKENDS = new Set<string>([...SandboxBackend.options, \"unprovisioned\"]);\n\nconst SANDBOX_OPERATION_NAMES = new Set([\n \"desktopInput\",\n \"screenshot\",\n \"exec\",\n \"execCommand\",\n \"writeStdin\",\n \"cancelExecCommand\",\n \"readFile\",\n \"writeFile\",\n \"listDir\",\n \"pathExists\",\n \"viewImage\",\n \"materializeEntry\",\n \"editor.createFile\",\n \"editor.updateFile\",\n \"editor.deleteFile\",\n \"resolveExposedPort\",\n \"serializeSessionState\",\n]);\n\n/**\n * Closed set of organization-tenancy compatibility lanes (the tenancy\n * migration's validate phase; see `docs/organization-tenancy.md`).\n *\n * Each entry names one legacy behaviour a live request can still take today.\n * The metric built from them is deliberately a COUNTER of lane USES, and it\n * measures exactly one thing: **is this lane still being exercised?** That is\n * the question the tenancy cutover gate (\"zero incompatible writers\") actually\n * asks, and it is answerable.\n *\n * It is emphatically NOT a burndown of unmigrated rows, and must never be\n * relabelled as one. Every one of these lanes is still *open*: the live write\n * paths keep producing rows in it, so no row-count predicate over any of them\n * can reach zero and a backlog gauge would read as a permanent, untruthful\n * unmigrated backlog. `docs/organization-tenancy.md` records, per lane, why -\n * including the lanes deliberately left uninstrumented because no truthful\n * signal exists for them yet.\n *\n * The recorded value is the lane name and nothing else. No organization,\n * workspace, session, subject, connection, or resource identity, and no\n * credential, name, or content, may ever become a label here.\n */\nexport const TENANCY_COMPATIBILITY_LANES = [\n /**\n * A provider connection carrying `authority_scope = 'legacy_user'` was\n * resolved for accepted use: a personal row with no common authority or\n * grant, admitted through `legacy_user_compatibility` provenance instead of\n * an explicit delegation. Migration 0256 backfilled the existing rows, but\n * its `bind_connection_authority` trigger still classifies a NEW personal\n * connection this way whenever the inserting subject has no active\n * organization membership, so this counter is expected to stay above zero\n * until that classification changes. That is the finding, not a defect.\n */\n \"connection_legacy_user\",\n /**\n * A workspace-scope connection ref carried no connection id, so the\n * accepted-use authority (migration 0279) could not identify the exact row\n * and the request fell back to the unprivileged pre-snapshot resolution.\n * This lane writes no `connection_use_audit_facts` row and leaves no durable\n * trace of any kind, so a use counter is the only possible evidence it was\n * taken at all.\n */\n \"connection_pre_snapshot_ref\",\n /**\n * A NEW persistable `/workspace` mutation was refused because the writer\n * behind it has no recorded authority (`authority_unattributed`): either a\n * direct request whose principal froze the pre-0096 legacy initiator, or a\n * retained process whose pre-0277 row has no tenancy half. This counts\n * REFUSED MUTATIONS, not unattributed rows - the turn and process admission\n * lanes deliberately still accept a `legacy_unattributed` initiator, and\n * nothing may invent the missing authority or disturb the running provider\n * process.\n */\n \"workspace_writer_unattributed\",\n] as const;\nexport type TenancyCompatibilityLane = (typeof TENANCY_COMPATIBILITY_LANES)[number];\n\nconst TENANCY_COMPATIBILITY_LANE_SET = new Set<string>(TENANCY_COMPATIBILITY_LANES);\n\nconst TENANCY_COMPATIBILITY_LANE_METRIC = {\n name: \"opengeni_tenancy_compatibility_lane_uses_total\",\n help: \"Live uses of an organization-tenancy compatibility lane, by lane.\",\n} as const;\n\n/**\n * Record one live use of a tenancy compatibility lane. Fail-safe by\n * construction: telemetry must never change an authorization or credential\n * outcome, so a registry failure is counted best-effort and swallowed here.\n */\nexport function recordTenancyCompatibilityLaneUse(\n observability: Observability | null | undefined,\n lane: TenancyCompatibilityLane,\n): void {\n if (!observability) return;\n // An unreviewed lane name must not silently mint a new series.\n if (!TENANCY_COMPATIBILITY_LANE_SET.has(lane)) return;\n try {\n observability.incrementCounter({ ...TENANCY_COMPATIBILITY_LANE_METRIC, labels: { lane } });\n } catch {\n recordObserverFailure(observability, \"tenancy_compatibility_lane\");\n }\n}\n\nconst INTERACTION_RESOURCES = new Set([\"browser\", \"computer\"]);\nconst INTERACTION_OPERATIONS = new Set([\n \"create\",\n \"end\",\n \"suspend\",\n \"resume\",\n \"publish\",\n \"observe\",\n \"act\",\n \"open_target\",\n \"select_target\",\n \"close_target\",\n \"attach\",\n \"auth_start\",\n \"auth_report\",\n \"auth_fill\",\n \"auth_verify\",\n \"intervention_create\",\n \"intervention_resolve\",\n]);\nconst INTERACTION_OUTCOMES = new Set([\n \"prepared\",\n \"dispatched\",\n \"completed\",\n \"failed\",\n \"outcome_unknown\",\n \"stale\",\n \"cancelled\",\n]);\nconst INTERACTION_MODES = new Set([\n \"semantic\",\n \"coordinate\",\n \"keyboard\",\n \"clipboard\",\n \"permission\",\n \"lifecycle\",\n \"media\",\n \"auth\",\n \"human\",\n]);\nconst INTERACTION_AUTH_STATES = new Set([\n \"discovering\",\n \"awaiting_choice\",\n \"awaiting_secret\",\n \"awaiting_external_action\",\n \"working\",\n \"verified\",\n \"failed\",\n \"cancelled\",\n]);\nconst INTERACTION_INTERVENTION_KINDS = new Set([\n \"manual_login\",\n \"mfa\",\n \"external_action\",\n \"confirmation\",\n \"other\",\n]);\nconst INTERACTION_INTERVENTION_OUTCOMES = new Set([\n \"opened\",\n \"completed\",\n \"dismissed\",\n \"expired\",\n \"cancelled\",\n]);\nconst WORKSPACE_INSIGHTS_RANGES = new Set([\"today\", \"week\", \"month\", \"ytd\"]);\nconst WORKSPACE_INSIGHTS_OUTCOMES = new Set([\"completed\", \"failed\"]);\nconst workspaceInsightsDurationHistogramBuckets = [0.05, 0.1, 0.25, 0.5, 1, 1.5, 2, 3, 5, 10, 30];\nconst PUBLIC_STARTUP_DEPENDENCIES = new Set([\n \"Modal private-registry image\",\n \"NATS\",\n \"PostgreSQL runtime posture\",\n \"Temporal\",\n \"Temporal client\",\n \"Temporal schedule (file upload reaper)\",\n \"Temporal schedule (sandbox reaper)\",\n \"Temporal schedule (session-workflow wake dispatcher)\",\n \"Temporal schedule (site auth maintenance)\",\n]);\n\n/**\n * External logs and OTLP are public/third-party projections, not canonical\n * OpenGeni storage. Only this reviewed closed set of operational fields may\n * cross that boundary. Unknown keys are omitted regardless of their value, so\n * a new diagnostic, identifier, command, response, or provider field cannot\n * become public by accident. This is schema projection, never value inspection\n * or rewriting.\n */\nconst PUBLIC_TELEMETRY_ATTRIBUTE_KEYS = new Set([\n \"http.request.method\",\n \"http.response.status_code\",\n \"opengeni.route\",\n \"opengeni.duration_ms\",\n \"opengeni.finalization_duration_ms\",\n \"opengeni.trigger_kind\",\n \"opengeni.status\",\n \"error.type\",\n \"error.status_code\",\n \"method\",\n \"route\",\n \"status\",\n \"durationMs\",\n \"attempt\",\n \"attempts\",\n \"delayMs\",\n \"provider\",\n \"providerApi\",\n \"model\",\n \"inputTokens\",\n \"outputTokens\",\n \"cachedTokens\",\n \"cacheWriteTokens\",\n \"reasoningTokens\",\n \"accountChangedFromPrevCall\",\n \"rejectedFields\",\n \"dependency\",\n \"activity\",\n \"backend\",\n \"op\",\n \"outcome\",\n \"eventType\",\n \"surface\",\n \"reason\",\n \"originalBytes\",\n \"deliveredBytes\",\n \"estimatedOriginalTokens\",\n \"estimatedDeliveredTokens\",\n \"fullEvidenceAvailable\",\n \"retainedOutputKind\",\n]);\n\n/** Opaque correlation fields require both a reviewed name and a closed value\n * grammar. Merely adding one to the ordinary allow-list would let an unrelated\n * caller accidentally publish a raw identifier under that name. */\nconst PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS = new Map<string, RegExp>([\n [\"sandboxLeaseKey\", /^slk_[0-9a-f]{32}$/],\n [\"correlationId\", /^[A-Za-z0-9._:-]{1,128}$/],\n]);\n\nconst PUBLIC_CHANNEL_A_OPERATIONS = new Set([\n \"fs.list\",\n \"fs.list-batch\",\n \"fs.read\",\n \"fs.write\",\n \"fs.delete\",\n \"fs.move\",\n \"fs.mkdir\",\n \"git.status\",\n \"git.diff\",\n \"git.read-batch\",\n \"git.log\",\n \"git.show\",\n \"terminal.exec\",\n \"terminal.pty.open\",\n \"terminal.pty.write\",\n \"terminal.pty.resize\",\n \"terminal.pty.close\",\n \"read\",\n \"mutation\",\n]);\n\nconst PUBLIC_CHANNEL_A_FAILURE_REASONS = new Set([\n \"request_cancelled\",\n \"provider_read_busy\",\n \"provider_unavailable\",\n \"lifecycle_conflict\",\n \"request_rejected\",\n \"unexpected\",\n]);\n\nconst PUBLIC_API_FATAL_PHASES = new Set([\"startup\", \"running\"]);\nconst PUBLIC_API_FATAL_REASON_KINDS = new Set([\n \"bigint\",\n \"boolean\",\n \"error\",\n \"function\",\n \"null\",\n \"number\",\n \"object\",\n \"string\",\n \"symbol\",\n \"undefined\",\n]);\n\n/**\n * Public diagnostic values are protocol constants, never values inferred from\n * an exception's name, constructor, code, message, or enumerable properties.\n * Unknown classes collapse to one fixed fallback; unknown codes and origins\n * are omitted rather than copied through based on syntax.\n */\nconst PUBLIC_TELEMETRY_ERROR_CLASSES = new Set([\n \"ApiFatalOperationError\",\n \"OperationError\",\n \"CodexCheckpointOperationError\",\n \"CodexFleetShadowOperationError\",\n \"ComputerActionTimeoutError\",\n \"ComputerUnavailableError\",\n \"CredentialRenewalOperationError\",\n \"CredentialReadOperationError\",\n \"EventPublishOperationError\",\n \"GitCredentialRenewalOperationError\",\n \"HostExportOperationError\",\n \"HttpOperationError\",\n \"McpLifecycleError\",\n \"McpOperationError\",\n \"MemoryEmbeddingOperationError\",\n \"MemorySearchOperationError\",\n \"NatsAuthCalloutOperationError\",\n \"OAuthOperationError\",\n \"RunCredentialRenewalOperationError\",\n \"RunStateCompatibilityError\",\n \"SandboxChannelAOperationError\",\n \"SnapshotOperationError\",\n \"StartupDependencyError\",\n \"TelemetryExportError\",\n \"CodemodeOperationError\",\n \"CodemodeTokenRenewalOperationError\",\n \"WorkerLifecycleOperation\",\n \"WorkerLifecycleOperationError\",\n \"WorkerOperationError\",\n \"WorkflowWakeOperationError\",\n]);\n\nconst PUBLIC_TELEMETRY_ERROR_CODES = new Set([\n \"agent_command_wake_failed\",\n \"api_startup_failed\",\n \"api_uncaught_exception\",\n \"api_unhandled_rejection\",\n \"artifact_materializer_native_input_framing_failed\",\n \"artifact_materializer_native_snapshot_open_failed\",\n \"artifact_materializer_native_state_mismatch\",\n \"artifact_materializer_source_content_type_mismatch\",\n \"artifact_materializer_source_open_failed\",\n \"artifact_materializer_source_revalidation_failed\",\n \"artifact_materializer_source_stream_identity_mismatch\",\n \"cleared_goal_live_publish_failed\",\n \"codex_failover_checkpoint_failed\",\n \"codex_fleet_shadow_failed\",\n \"codex_lease_loss_checkpoint_failed\",\n \"codex_active_credential_read_failed\",\n \"command_yield_timeout\",\n \"conflict\",\n \"control_wake_dispatch_failed\",\n \"fenced_event_live_publish_failed\",\n \"forbidden\",\n \"host_export_batch_delivery_failed\",\n \"host_export_failure_settlement_stale\",\n \"host_export_pump_iteration_failed\",\n \"host_export_retention_prune_failed\",\n \"idempotency_conflict\",\n \"incompatible_exposed_ports\",\n \"internal_error\",\n \"limit_exceeded\",\n \"mcp_close_failed\",\n \"mcp_connect_failed\",\n \"mcp_tool_call_failed\",\n \"mcp_tools_list_failed\",\n \"mcp_transport_failed\",\n \"memory_edit_embedding_failed\",\n \"memory_hybrid_vector_failed\",\n \"memory_save_embedding_failed\",\n \"nats_auth_callout_start_failed\",\n \"nested_agent_depth_exceeded\",\n \"nested_agent_depth_override_forbidden\",\n \"not_found\",\n \"oauth_operation_failed\",\n \"otlp_export_failed\",\n \"payment_required\",\n \"provider_verification_failed\",\n \"sandbox_channel_a_cancelled\",\n \"sandbox_channel_a_lifecycle_conflict\",\n \"sandbox_channel_a_operation_failed\",\n \"sandbox_channel_a_provider_busy\",\n \"sandbox_channel_a_provider_unavailable\",\n \"screenshot_capture_failed\",\n \"session_event_live_publish_failed\",\n \"session_workflow_wake_failed\",\n \"snapshot_operation_failed\",\n \"startup_dependency_retry\",\n \"tool_list_too_large\",\n \"tool_result_too_large\",\n \"codemode_operation_failed\",\n \"unauthenticated\",\n \"upstream_unavailable\",\n \"validation_failed\",\n \"worker_draining\",\n \"worker_operation_failed\",\n \"worker_shutdown_request_failed\",\n \"workspace_control_live_publish_failed\",\n]);\n\nconst PUBLIC_TELEMETRY_ERROR_ORIGINS = new Set([\n \"api\",\n \"core\",\n \"db\",\n \"events\",\n \"host-export\",\n \"oauth\",\n \"observability\",\n \"runtime\",\n \"sandbox-resume\",\n \"codemode\",\n \"worker\",\n \"worker-lifecycle\",\n]);\n\nexport type SandboxOperationMetricObservation = {\n backend: string;\n op: string;\n outcome: \"ok\" | \"not_found\" | \"failed\";\n durationMs: number;\n materializationFailureReason?: string;\n};\n\nconst MATERIALIZATION_FAILURE_REASONS = new Set([\n \"path_not_visible\",\n \"command_failed\",\n \"command_pending\",\n \"invalid_response\",\n \"command_error\",\n]);\nconst MATERIALIZATION_FAILURE_METRIC = {\n name: \"opengeni_sandbox_materialization_verification_failures_total\",\n help: \"Sandbox destination visibility-check failures by bounded reason; exact command evidence is retained in the session failure event.\",\n} as const;\n\nexport function createObservability(\n settings: ObservabilitySettings,\n options: ObservabilityOptions,\n): Observability {\n return new Observability(settings, options);\n}\n\ntype MetricRegistration = {\n kind: \"counter\" | \"gauge\" | \"histogram\";\n labelNames: string[];\n};\n\nexport class Observability {\n private readonly registry = new Registry();\n private readonly counters = new Map<string, Counter<string>>();\n private readonly gauges = new Map<string, Gauge<string>>();\n private readonly histograms = new Map<string, Histogram<string>>();\n private readonly registrations = new Map<string, MetricRegistration>();\n private readonly pendingExports = new Set<Promise<void>>();\n private readonly now: () => number;\n private readonly exporter: (\n url: string,\n body: unknown,\n headers: Record<string, string>,\n ) => Promise<void>;\n private readonly resourceAttributes: Attributes;\n\n constructor(\n private readonly settings: ObservabilitySettings,\n private readonly options: ObservabilityOptions,\n ) {\n this.now = options.now ?? Date.now;\n this.exporter = options.exporter ?? defaultExporter;\n this.resourceAttributes = {\n \"service.name\": settings.serviceName,\n \"deployment.environment\": settings.environment,\n \"opengeni.component\": options.component,\n };\n this.registry.setDefaultLabels({\n service: settings.serviceName,\n environment: settings.environment,\n component: options.component,\n deployment_revision: settings.deploymentRevision ?? \"dev\",\n });\n if (settings.observabilityMetricsEnabled) {\n collectDefaultMetrics({ register: this.registry, prefix: \"opengeni_\" });\n this.setGauge({\n name: \"opengeni_build_info\",\n help: \"OpenGeni build information.\",\n labels: {\n version: buildVersion(),\n revision: settings.deploymentRevision ?? \"dev\",\n },\n value: 1,\n });\n this.registerSandboxRolloutConfig();\n this.registerTenancyCompatibilityLanes();\n if ([\"worker\", \"worker-control\", \"worker-turn\", \"api\"].includes(options.component)) {\n // Publish the finite series at startup so a first failure has a zero\n // baseline and healthy zeroes differ from a missing instrumentation path.\n for (const backend of [...SANDBOX_OPERATION_BACKENDS, \"unknown\"]) {\n for (const reason of [...MATERIALIZATION_FAILURE_REASONS, \"unknown\"]) {\n this.incrementCounter({\n ...MATERIALIZATION_FAILURE_METRIC,\n labels: { backend, reason },\n amount: 0,\n });\n }\n }\n }\n if (options.component === \"worker\" || options.component === \"worker-control\") {\n for (const outcome of WORKFLOW_WAKE_OUTCOMES) {\n this.incrementCounter({ ...WORKFLOW_WAKE_METRIC, labels: { outcome }, amount: 0 });\n }\n for (const reason of [...WORKFLOW_WAKE_ADMISSION_BLOCKERS, \"unknown\"]) {\n this.incrementCounter({ ...WORKFLOW_WAKE_BLOCKER_METRIC, labels: { reason }, amount: 0 });\n }\n }\n }\n }\n\n /**\n * Publish every compatibility lane at zero on startup. Without this an\n * un-exercised lane has no series at all, and an operator cannot tell \"this\n * lane is dormant\" from \"this lane was never wired up\" - the two readings\n * that matter most to a cutover gate.\n */\n private registerTenancyCompatibilityLanes(): void {\n for (const lane of TENANCY_COMPATIBILITY_LANES) {\n this.incrementCounter({ ...TENANCY_COMPATIBILITY_LANE_METRIC, labels: { lane }, amount: 0 });\n }\n }\n\n private registerSandboxRolloutConfig(): void {\n const ownership = this.settings.sandboxOwnershipEnabled;\n const lazyConfigured = this.settings.sandboxLazyProvisionEnabled;\n const rigVerification = this.settings.rigVerificationLeaseOwnershipEnabled;\n if (\n typeof ownership !== \"boolean\" ||\n typeof lazyConfigured !== \"boolean\" ||\n typeof rigVerification !== \"boolean\"\n ) {\n return;\n }\n\n const values = [\n [\"ownership\", \"configured\", ownership],\n [\"ownership\", \"effective\", ownership],\n [\"lazy_provision\", \"configured\", lazyConfigured],\n [\"lazy_provision\", \"effective\", ownership && lazyConfigured],\n [\"rig_verification_lease_ownership\", \"configured\", rigVerification],\n [\"rig_verification_lease_ownership\", \"effective\", rigVerification],\n ] as const;\n for (const [feature, state, enabled] of values) {\n this.setGauge({\n name: \"opengeni_sandbox_rollout_config\",\n help: \"Configured and effective sandbox rollout state for this workload revision.\",\n labels: { feature, state },\n value: enabled ? 1 : 0,\n });\n }\n }\n\n debug(message: string, attributes: Attributes = {}): void {\n this.log(\"debug\", message, attributes);\n }\n\n info(message: string, attributes: Attributes = {}): void {\n this.log(\"info\", message, attributes);\n }\n\n warn(message: string, attributes: Attributes = {}): void {\n this.log(\"warn\", message, attributes);\n }\n\n error(message: string, attributes: Attributes = {}): void {\n this.log(\"error\", message, attributes);\n }\n\n log(\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n attributes: Attributes = {},\n ): void {\n const publicAttributes = projectPublicTelemetryAttributes(attributes);\n if (!this.settings.observabilityStructuredLogs) {\n if (level === \"warn\") {\n console.warn(message);\n } else if (level === \"error\") {\n console.error(message);\n } else {\n console.log(message);\n }\n return;\n }\n const record = {\n timestamp: new Date(this.now()).toISOString(),\n level,\n message,\n service: this.settings.serviceName,\n environment: this.settings.environment,\n component: this.options.component,\n ...cleanAttributes(publicAttributes),\n };\n const serialized = JSON.stringify(record);\n if (level === \"warn\") {\n console.warn(serialized);\n } else if (level === \"error\") {\n console.error(serialized);\n } else {\n console.log(serialized);\n }\n }\n\n startSpan(name: string, attributes: Attributes = {}): Span {\n const traceId = randomHex(16);\n const spanId = randomHex(8);\n const startMs = this.now();\n let ended = false;\n return {\n traceId,\n spanId,\n end: (input = {}) => {\n if (ended) {\n return;\n }\n ended = true;\n const telemetryError =\n input.error !== undefined && input.error !== null\n ? projectSpanErrorForTelemetry(input.error)\n : undefined;\n const errorAttributes = telemetryError ? errorToAttributes(telemetryError) : {};\n this.exportSpan({\n traceId,\n spanId,\n name,\n startMs,\n endMs: this.now(),\n attributes: {\n ...projectPublicTelemetryAttributes({\n ...attributes,\n ...input.attributes,\n ...errorAttributes,\n }),\n },\n ...(telemetryError ? { error: telemetryError } : {}),\n });\n },\n };\n }\n\n recordHttpRequest(input: {\n method: string;\n route: string;\n status: number;\n durationSeconds: number;\n }): void {\n this.incrementCounter({\n name: \"opengeni_http_requests_total\",\n help: \"Total HTTP requests handled by OpenGeni.\",\n labels: {\n method: input.method,\n route: input.route,\n status: String(input.status),\n component: this.options.component,\n },\n });\n this.observeHistogram({\n name: \"opengeni_http_request_duration_seconds\",\n help: \"HTTP request duration in seconds.\",\n buckets: httpHistogramBuckets,\n value: input.durationSeconds,\n labels: {\n method: input.method,\n route: input.route,\n component: this.options.component,\n },\n });\n }\n\n recordWorkerActivity(input: { activity: string; status: string; durationSeconds: number }): void {\n this.incrementCounter({\n name: \"opengeni_worker_activity_runs_total\",\n help: \"Total worker activity executions.\",\n labels: {\n activity: input.activity,\n status: input.status,\n component: this.options.component,\n },\n });\n this.observeHistogram({\n name: \"opengeni_worker_activity_duration_seconds\",\n help: \"Worker activity duration in seconds.\",\n buckets: durationHistogramBuckets,\n value: input.durationSeconds,\n labels: {\n activity: input.activity,\n component: this.options.component,\n },\n });\n }\n\n incrementCounter(input: {\n name: string;\n help?: string;\n labels?: MetricLabels;\n amount?: number;\n }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const counter = this.counter(\n input.name,\n input.help ?? `${input.name} counter.`,\n Object.keys(labels),\n );\n counter.inc(labels as never, input.amount ?? 1);\n }\n\n setGauge(input: { name: string; help?: string; labels?: MetricLabels; value: number }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const gauge = this.gauge(input.name, input.help ?? `${input.name} gauge.`, Object.keys(labels));\n gauge.set(labels as never, input.value);\n }\n\n incrementGauge(input: {\n name: string;\n help?: string;\n labels?: MetricLabels;\n amount?: number;\n }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const gauge = this.gauge(input.name, input.help ?? `${input.name} gauge.`, Object.keys(labels));\n gauge.inc(labels as never, input.amount ?? 1);\n }\n\n observeHistogram(input: {\n name: string;\n help?: string;\n labels?: MetricLabels;\n value: number;\n buckets?: number[];\n }): void {\n if (!this.settings.observabilityMetricsEnabled) {\n return;\n }\n const labels = normalizeLabels(input.labels);\n const histogram = this.histogram(\n input.name,\n input.help ?? `${input.name} histogram.`,\n Object.keys(labels),\n input.buckets ?? durationHistogramBuckets,\n );\n histogram.observe(labels as never, input.value);\n }\n\n async prometheusMetrics(): Promise<string> {\n if (!this.settings.observabilityMetricsEnabled) {\n return \"\";\n }\n return await this.registry.metrics();\n }\n\n /** Wait for every OTLP export accepted before or during this drain. */\n async flush(): Promise<void> {\n while (this.pendingExports.size > 0) {\n await Promise.allSettled([...this.pendingExports]);\n }\n }\n\n private counter(name: string, help: string, labelNames: string[]): Counter<string> {\n const existing = this.counters.get(name);\n if (existing) {\n this.assertRegistration(name, \"counter\", labelNames);\n return existing;\n }\n this.register(name, \"counter\", labelNames);\n const metric = new Counter({ name, help, labelNames, registers: [this.registry] });\n this.counters.set(name, metric);\n return metric;\n }\n\n private gauge(name: string, help: string, labelNames: string[]): Gauge<string> {\n const existing = this.gauges.get(name);\n if (existing) {\n this.assertRegistration(name, \"gauge\", labelNames);\n return existing;\n }\n this.register(name, \"gauge\", labelNames);\n const metric = new Gauge({ name, help, labelNames, registers: [this.registry] });\n this.gauges.set(name, metric);\n return metric;\n }\n\n private histogram(\n name: string,\n help: string,\n labelNames: string[],\n buckets: number[],\n ): Histogram<string> {\n const existing = this.histograms.get(name);\n if (existing) {\n this.assertRegistration(name, \"histogram\", labelNames);\n return existing;\n }\n this.register(name, \"histogram\", labelNames);\n const metric = new Histogram({ name, help, labelNames, buckets, registers: [this.registry] });\n this.histograms.set(name, metric);\n return metric;\n }\n\n private register(name: string, kind: MetricRegistration[\"kind\"], labelNames: string[]): void {\n const sorted = [...labelNames].sort();\n this.registrations.set(name, { kind, labelNames: sorted });\n }\n\n private assertRegistration(\n name: string,\n kind: MetricRegistration[\"kind\"],\n labelNames: string[],\n ): void {\n const registration = this.registrations.get(name);\n const sorted = [...labelNames].sort();\n if (\n !registration ||\n registration.kind !== kind ||\n registration.labelNames.length !== sorted.length ||\n registration.labelNames.some((label, index) => label !== sorted[index])\n ) {\n throw new Error(\n `Metric ${name} was already registered as ${registration?.kind ?? \"unknown\"} ` +\n `with labels [${registration?.labelNames.join(\",\") ?? \"\"}], not ${kind} [${sorted.join(\",\")}]`,\n );\n }\n }\n\n private exportSpan(span: {\n traceId: string;\n spanId: string;\n name: string;\n startMs: number;\n endMs: number;\n attributes: Attributes;\n error?: TelemetrySpanError;\n }): void {\n if (!this.settings.observabilityOtlpEndpoint) {\n return;\n }\n const endpoint = `${this.settings.observabilityOtlpEndpoint.replace(/\\/$/, \"\")}/v1/traces`;\n const body = {\n resourceSpans: [\n {\n resource: {\n attributes: otlpAttributes(this.resourceAttributes),\n },\n scopeSpans: [\n {\n scope: {\n name: \"@opengeni/observability\",\n version: \"0.1.0\",\n },\n spans: [\n {\n traceId: span.traceId,\n spanId: span.spanId,\n name: span.name,\n kind: 1,\n startTimeUnixNano: millisToNanos(span.startMs),\n endTimeUnixNano: millisToNanos(span.endMs),\n attributes: otlpAttributes(span.attributes),\n status: span.error ? { code: 2, message: span.error.statusMessage } : { code: 1 },\n },\n ],\n },\n ],\n },\n ],\n };\n let pendingExport: Promise<void>;\n pendingExport = Promise.resolve()\n .then(() =>\n this.exporter(endpoint, body, parseHeaders(this.settings.observabilityOtlpHeaders)),\n )\n .catch(() => {\n this.warn(\"OTLP span export failed\", {\n errorClass: \"TelemetryExportError\",\n errorCode: \"otlp_export_failed\",\n origin: \"observability\",\n });\n })\n .finally(() => {\n this.pendingExports.delete(pendingExport);\n });\n this.pendingExports.add(pendingExport);\n }\n}\n\n/**\n * Convert routed sandbox-provider observations into one bounded Prometheus\n * contract shared by API-direct and worker-turn execution. Provider/session\n * identifiers, commands, paths, and other request data can never become labels:\n * a future backend or operation is deliberately collapsed to `unknown` until\n * this allowlist is reviewed.\n *\n * The returned callback is fail-safe. Metrics must never change the provider\n * operation's result; a registration/exporter error is counted best-effort and\n * then swallowed at this telemetry boundary.\n */\nexport function sandboxOperationMetricObserver(\n observability: Observability,\n): (observation: SandboxOperationMetricObservation) => void {\n return (observation) => {\n const backend = SANDBOX_OPERATION_BACKENDS.has(observation.backend)\n ? observation.backend\n : \"unknown\";\n const op = SANDBOX_OPERATION_NAMES.has(observation.op) ? observation.op : \"unknown\";\n try {\n observability.incrementCounter({\n name: \"opengeni_sandbox_operations_total\",\n help: \"Physical routed sandbox provider operations by backend, operation, and outcome.\",\n labels: { backend, op, outcome: observation.outcome },\n });\n observability.observeHistogram({\n name: \"opengeni_sandbox_operation_duration_seconds\",\n help: \"Physical routed sandbox provider-operation duration in seconds.\",\n labels: { backend, op },\n value: Math.max(0, observation.durationMs) / 1_000,\n });\n if (\n op === \"materializeEntry\" &&\n observation.outcome === \"failed\" &&\n observation.materializationFailureReason\n ) {\n const reason = MATERIALIZATION_FAILURE_REASONS.has(observation.materializationFailureReason)\n ? observation.materializationFailureReason\n : \"unknown\";\n observability.incrementCounter({\n ...MATERIALIZATION_FAILURE_METRIC,\n labels: { backend, reason },\n });\n }\n } catch {\n try {\n observability.incrementCounter({\n name: \"opengeni_observability_observer_errors_total\",\n help: \"Observability observer failures isolated from product execution.\",\n labels: { observer: \"sandbox_operation\" },\n });\n } catch {\n // The metrics registry itself is unhealthy. Product execution remains\n // authoritative and must not inherit an observability failure.\n }\n }\n };\n}\n\nexport type InteractionOperationMetricObservation = {\n resource: string;\n operation: string;\n outcome: string;\n mode: string;\n durationMs: number;\n replayed?: boolean | undefined;\n};\n\n/** Safe low-cardinality telemetry for Browser/Computer control operations.\n * Resource ids, URLs, locators, page/app text, and input values are excluded by\n * construction. Unknown future enum values collapse until explicitly reviewed. */\nexport function interactionOperationMetricObserver(\n observability: Observability | null | undefined,\n): (observation: InteractionOperationMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n if (observation.replayed) return;\n const resource = boundedMetricEnum(INTERACTION_RESOURCES, observation.resource);\n const operation = boundedMetricEnum(INTERACTION_OPERATIONS, observation.operation);\n const outcome = boundedMetricEnum(INTERACTION_OUTCOMES, observation.outcome);\n const mode = boundedMetricEnum(INTERACTION_MODES, observation.mode);\n try {\n observability.incrementCounter({\n name: \"opengeni_interaction_operations_total\",\n help: \"Browser and Computer operations by bounded resource, operation, mode, and outcome.\",\n labels: { resource, operation, mode, outcome },\n });\n observability.observeHistogram({\n name: \"opengeni_interaction_operation_duration_seconds\",\n help: \"Browser and Computer operation duration in seconds.\",\n labels: { resource, operation, mode },\n value: boundedMetricDuration(observation.durationMs),\n });\n } catch {\n recordObserverFailure(observability, \"interaction_operation\");\n }\n };\n}\n\nexport type InteractionAuthMetricObservation = {\n state: string;\n durationMs: number;\n replayed?: boolean | undefined;\n};\n\nexport function interactionAuthMetricObserver(\n observability: Observability | null | undefined,\n): (observation: InteractionAuthMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n if (observation.replayed) return;\n const state = boundedMetricEnum(INTERACTION_AUTH_STATES, observation.state);\n try {\n observability.incrementCounter({\n name: \"opengeni_interaction_auth_transitions_total\",\n help: \"Browser authentication transitions by bounded resulting state.\",\n labels: { state },\n });\n observability.observeHistogram({\n name: \"opengeni_interaction_auth_transition_duration_seconds\",\n help: \"Browser authentication transition request duration in seconds.\",\n labels: { state },\n value: boundedMetricDuration(observation.durationMs),\n });\n } catch {\n recordObserverFailure(observability, \"interaction_auth\");\n }\n };\n}\n\nexport type InteractionInterventionMetricObservation = {\n kind: string;\n outcome: string;\n waitMs?: number | undefined;\n replayed?: boolean | undefined;\n};\n\nexport function interactionInterventionMetricObserver(\n observability: Observability | null | undefined,\n): (observation: InteractionInterventionMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n if (observation.replayed) return;\n const kind = boundedMetricEnum(INTERACTION_INTERVENTION_KINDS, observation.kind);\n const outcome = boundedMetricEnum(INTERACTION_INTERVENTION_OUTCOMES, observation.outcome);\n try {\n observability.incrementCounter({\n name: \"opengeni_interaction_interventions_total\",\n help: \"Human browser/computer interventions by bounded kind and outcome.\",\n labels: { kind, outcome },\n });\n if (observation.waitMs !== undefined) {\n observability.observeHistogram({\n name: \"opengeni_interaction_intervention_wait_seconds\",\n help: \"Time an interaction intervention remained open before settlement.\",\n labels: { kind, outcome },\n value: boundedMetricDuration(observation.waitMs),\n });\n }\n } catch {\n recordObserverFailure(observability, \"interaction_intervention\");\n }\n };\n}\n\nexport type WorkspaceInsightsMetricObservation = {\n range: string;\n providerFiltered: boolean;\n modelFiltered: boolean;\n outcome: string;\n durationMs: number;\n};\n\n/**\n * Identity-free route timing for Workspace Insights. The dedicated two-second\n * bucket is the service target; fixed enums and filter-presence flags keep\n * tenant ids and caller-supplied provider/model values out of telemetry.\n */\nexport function workspaceInsightsMetricObserver(\n observability: Observability | null | undefined,\n): (observation: WorkspaceInsightsMetricObservation) => void {\n if (!observability) return () => undefined;\n return (observation) => {\n const range = boundedMetricEnum(WORKSPACE_INSIGHTS_RANGES, observation.range);\n const outcome = boundedMetricEnum(WORKSPACE_INSIGHTS_OUTCOMES, observation.outcome);\n const providerFilter = observation.providerFiltered ? \"filtered\" : \"all\";\n const modelFilter = observation.modelFiltered ? \"filtered\" : \"all\";\n const durationSeconds = boundedMetricDuration(observation.durationMs);\n try {\n observability.observeHistogram({\n name: \"opengeni_workspace_insights_request_duration_seconds\",\n help: \"Workspace Insights route service duration by bounded range, filter presence, and outcome.\",\n buckets: workspaceInsightsDurationHistogramBuckets,\n labels: {\n range,\n provider_filter: providerFilter,\n model_filter: modelFilter,\n outcome,\n },\n value: durationSeconds,\n });\n observability.info(\"Workspace Insights request measured\", {\n surface: \"workspace_insights\",\n eventType: \"request_latency\",\n route: \"/v1/workspaces/:workspaceId/insights\",\n outcome,\n durationMs: Math.round(durationSeconds * 1_000),\n });\n } catch {\n recordObserverFailure(observability, \"workspace_insights\");\n }\n };\n}\n\nfunction boundedMetricEnum(allowed: ReadonlySet<string>, value: string): string {\n return allowed.has(value) ? value : \"unknown\";\n}\n\nconst WORKFLOW_WAKE_ADMISSION_BLOCKERS = new Set([\n \"pending_agent_steer\",\n \"pending_prompt_turn\",\n \"pending_quiescence\",\n \"pending_machine_input\",\n \"pending_input_wait\",\n]);\nconst WORKFLOW_WAKE_OUTCOMES = [\n \"signal_accepted\",\n \"acknowledged\",\n \"pending_admission\",\n \"unconfirmed\",\n \"failed\",\n] as const;\nconst WORKFLOW_WAKE_METRIC = {\n name: \"opengeni_session_workflow_wake_observations_total\",\n help: \"Workflow wake dispatch observations; signal acceptance overlaps with admission outcomes, and retries are counted again.\",\n};\nconst WORKFLOW_WAKE_BLOCKER_METRIC = {\n name: \"opengeni_session_workflow_wake_admission_blockers_total\",\n help: \"Workflow wake dispatch attempts awaiting durable admission, by bounded blocker; repeated revisions count again.\",\n};\n\n/** Dispatcher observations count attempts, including repeated observations of\n * the same revision. Transport acceptance is never an admission receipt. */\nexport function recordWorkflowWakeReconciliation(\n observability: Observability,\n result: {\n signaled: number;\n delivered: number;\n pendingAdmission: number;\n unconfirmed: number;\n failed: number;\n pendingAdmissionBlockers: Record<string, number | undefined>;\n },\n): void {\n const count = (value: number | undefined) =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0 ? value : 0;\n try {\n for (const [outcome, amount] of [\n [\"signal_accepted\", result.signaled],\n [\"acknowledged\", result.delivered],\n [\"pending_admission\", result.pendingAdmission],\n [\"unconfirmed\", result.unconfirmed],\n [\"failed\", result.failed],\n ] as const) {\n observability.incrementCounter({\n ...WORKFLOW_WAKE_METRIC,\n labels: { outcome },\n amount: count(amount),\n });\n if (count(amount) > 0) {\n // Use the reviewed public telemetry vocabulary. Arbitrary aggregate\n // property names are intentionally omitted by the external sink.\n observability.info(\"Session workflow wake dispatch observed\", {\n surface: \"session_workflow_wake\",\n outcome,\n attempts: count(amount),\n });\n }\n }\n for (const [blocker, amount] of Object.entries(result.pendingAdmissionBlockers)) {\n if (count(amount) === 0) continue;\n const reason = boundedMetricEnum(WORKFLOW_WAKE_ADMISSION_BLOCKERS, blocker);\n observability.incrementCounter({\n ...WORKFLOW_WAKE_BLOCKER_METRIC,\n labels: { reason },\n amount: count(amount),\n });\n observability.info(\"Session workflow wake admission pending\", {\n surface: \"session_workflow_wake\",\n outcome: \"pending_admission\",\n reason,\n attempts: count(amount),\n });\n }\n } catch {\n recordObserverFailure(observability, \"session_workflow_wake\");\n }\n}\n\nfunction boundedMetricDuration(durationMs: number): number {\n return Number.isFinite(durationMs) ? Math.max(0, durationMs) / 1_000 : 0;\n}\n\nfunction recordObserverFailure(observability: Observability, observer: string): void {\n try {\n observability.incrementCounter({\n name: \"opengeni_observability_observer_errors_total\",\n help: \"Observability observer failures isolated from product execution.\",\n labels: { observer },\n });\n } catch {\n // The metrics registry itself is unhealthy. Product execution remains\n // authoritative and must not inherit an observability failure.\n }\n}\n\nexport type StartupDependencyRetryEvent = {\n label: string;\n attempt: number;\n attempts: number;\n delayMs: number;\n error: unknown;\n};\n\nexport function logStartupDependencyRetry(\n observability: Observability,\n event: StartupDependencyRetryEvent,\n): void {\n const dependency = PUBLIC_STARTUP_DEPENDENCIES.has(event.label) ? event.label : \"Dependency\";\n observability.warn(\n `Startup dependency ${dependency} connection failed; retrying (${event.attempt}/${event.attempts} in ${event.delayMs}ms)`,\n {\n dependency,\n attempt: event.attempt,\n attempts: event.attempts,\n delayMs: event.delayMs,\n errorClass: \"StartupDependencyError\",\n errorCode: \"startup_dependency_retry\",\n origin: \"observability\",\n },\n );\n}\n\nfunction normalizeLabels(labels: MetricLabels = {}): Record<string, string> {\n return Object.fromEntries(\n Object.entries(labels)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]): [string, string] => [key, String(value)])\n .sort((left, right) => left[0].localeCompare(right[0])),\n );\n}\n\nfunction buildVersion(): string {\n return process.env.OPENGENI_VERSION ?? process.env.npm_package_version ?? \"dev\";\n}\n\nfunction cleanAttributes(attributes: Attributes): Record<string, string | number | boolean | null> {\n return Object.fromEntries(\n Object.entries(attributes).filter(([, value]) => value !== undefined),\n ) as Record<string, string | number | boolean | null>;\n}\n\nfunction projectPublicTelemetryAttributes(attributes: Attributes): Attributes {\n if (\"errorClass\" in attributes || \"errorCode\" in attributes) {\n return {\n ...projectStartupDependencyAttributes(attributes),\n ...projectPublicChannelADiagnosticAttributes(attributes),\n ...projectApiFatalDiagnosticAttributes(attributes),\n ...projectPublicDiagnosticAttributes(attributes),\n };\n }\n return Object.fromEntries(\n Object.entries(attributes).filter(([key, value]) => {\n if (value === undefined) return false;\n if (PUBLIC_TELEMETRY_ATTRIBUTE_KEYS.has(key)) return true;\n const pattern = PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS.get(key);\n return typeof value === \"string\" && pattern?.test(value) === true;\n }),\n );\n}\n\nfunction projectApiFatalDiagnosticAttributes(attributes: Attributes): Attributes {\n if (attributes.errorClass !== \"ApiFatalOperationError\") return {};\n const phase = attributes.phase;\n const reasonKind = attributes.reasonKind;\n return {\n ...(typeof phase === \"string\" && PUBLIC_API_FATAL_PHASES.has(phase) ? { phase } : {}),\n ...(typeof reasonKind === \"string\" && PUBLIC_API_FATAL_REASON_KINDS.has(reasonKind)\n ? { reasonKind }\n : {}),\n };\n}\n\nfunction projectStartupDependencyAttributes(attributes: Attributes): Attributes {\n if (\n attributes.errorClass !== \"StartupDependencyError\" ||\n attributes.errorCode !== \"startup_dependency_retry\"\n ) {\n return {};\n }\n const dependency = attributes.dependency;\n const attempt = attributes.attempt;\n const attempts = attributes.attempts;\n const delayMs = attributes.delayMs;\n return {\n ...(typeof dependency === \"string\" && PUBLIC_STARTUP_DEPENDENCIES.has(dependency)\n ? { dependency }\n : {}),\n ...(typeof attempt === \"number\" && Number.isInteger(attempt) && attempt > 0 ? { attempt } : {}),\n ...(typeof attempts === \"number\" && Number.isInteger(attempts) && attempts > 0\n ? { attempts }\n : {}),\n ...(typeof delayMs === \"number\" && Number.isFinite(delayMs) && delayMs >= 0 ? { delayMs } : {}),\n };\n}\n\nfunction projectPublicChannelADiagnosticAttributes(attributes: Attributes): Attributes {\n if (attributes.errorClass !== \"SandboxChannelAOperationError\") return {};\n const backend = attributes.backend;\n const op = attributes.op;\n const outcome = attributes.outcome;\n const reason = attributes.reason;\n const durationMs = attributes.durationMs;\n const sandboxLeaseKey = attributes.sandboxLeaseKey;\n return {\n ...(typeof backend === \"string\" && SANDBOX_OPERATION_BACKENDS.has(backend) ? { backend } : {}),\n ...(typeof op === \"string\" && PUBLIC_CHANNEL_A_OPERATIONS.has(op) ? { op } : {}),\n ...(outcome === \"failed\" ? { outcome } : {}),\n ...(typeof reason === \"string\" && PUBLIC_CHANNEL_A_FAILURE_REASONS.has(reason)\n ? { reason }\n : {}),\n ...(typeof durationMs === \"number\" && Number.isFinite(durationMs) && durationMs >= 0\n ? { durationMs }\n : {}),\n ...(typeof sandboxLeaseKey === \"string\" &&\n PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS.get(\"sandboxLeaseKey\")?.test(sandboxLeaseKey)\n ? { sandboxLeaseKey }\n : {}),\n };\n}\n\nfunction projectPublicDiagnosticAttributes(attributes: Attributes): Attributes {\n const errorClass = attributes.errorClass;\n const errorCode = attributes.errorCode;\n const status = attributes.status;\n const origin = attributes.origin;\n const correlationId = attributes.correlationId;\n return {\n errorClass:\n typeof errorClass === \"string\" && PUBLIC_TELEMETRY_ERROR_CLASSES.has(errorClass)\n ? errorClass\n : \"OperationError\",\n ...(typeof errorCode === \"string\" && PUBLIC_TELEMETRY_ERROR_CODES.has(errorCode)\n ? { errorCode }\n : {}),\n ...(typeof status === \"number\" && Number.isInteger(status) && status >= 100 && status <= 599\n ? { status }\n : {}),\n ...(typeof origin === \"string\" && PUBLIC_TELEMETRY_ERROR_ORIGINS.has(origin) ? { origin } : {}),\n ...(typeof correlationId === \"string\" &&\n PUBLIC_TELEMETRY_OPAQUE_ATTRIBUTE_PATTERNS.get(\"correlationId\")?.test(correlationId)\n ? { correlationId }\n : {}),\n };\n}\n\ntype TelemetrySpanError = {\n type: string;\n statusCode?: number;\n statusMessage: string;\n};\n\n/**\n * External OTLP projection. It intentionally exports only error class/status\n * metadata and never mutates canonical OpenGeni errors, events, or history.\n */\nfunction projectSpanErrorForTelemetry(error: unknown): TelemetrySpanError {\n const statusCode = errorStatusCode(error);\n return {\n type: \"OperationError\",\n ...(statusCode === undefined ? {} : { statusCode }),\n statusMessage: statusCode === undefined ? \"operation failed\" : `HTTP ${statusCode}`,\n };\n}\n\nfunction errorStatusCode(error: unknown): number | undefined {\n if (typeof error !== \"object\" || error === null) return undefined;\n try {\n const value = (error as { status?: unknown; statusCode?: unknown }).status;\n const statusCode =\n Number.isInteger(value) && typeof value === \"number\"\n ? value\n : (error as { statusCode?: unknown }).statusCode;\n return Number.isInteger(statusCode) &&\n typeof statusCode === \"number\" &&\n statusCode >= 100 &&\n statusCode <= 599\n ? statusCode\n : undefined;\n } catch {\n // OTLP projection must never mask the exact internal failure.\n return undefined;\n }\n}\n\nfunction errorToAttributes(error: TelemetrySpanError): Attributes {\n return {\n \"error.type\": error.type,\n ...(error.statusCode === undefined ? {} : { \"error.status_code\": error.statusCode }),\n };\n}\n\nfunction otlpAttributes(\n attributes: Attributes,\n): Array<{ key: string; value: Record<string, string | number | boolean> }> {\n return Object.entries(cleanAttributes(attributes)).map(([key, value]) => ({\n key,\n value: otlpValue(value),\n }));\n}\n\nfunction otlpValue(\n value: string | number | boolean | null,\n): Record<string, string | number | boolean> {\n if (typeof value === \"number\") {\n return Number.isInteger(value) ? { intValue: value } : { doubleValue: value };\n }\n if (typeof value === \"boolean\") {\n return { boolValue: value };\n }\n return { stringValue: value === null ? \"\" : boundedOtlpString(value) };\n}\n\nfunction boundedOtlpString(value: string): string {\n const bytes = new TextEncoder().encode(value);\n if (bytes.byteLength <= 512) return value;\n return `${new TextDecoder().decode(bytes.slice(0, 509))}…`;\n}\n\nfunction millisToNanos(ms: number): string {\n return String(BigInt(Math.round(ms)) * 1_000_000n);\n}\n\nfunction randomHex(bytes: number): string {\n const values = crypto.getRandomValues(new Uint8Array(bytes));\n return Array.from(values, (value) => value.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport function parseHeaders(value: string): Record<string, string> {\n if (!value.trim()) {\n return {};\n }\n const entries: Array<[string, string]> = value\n .split(\",\")\n .map((pair): [string, string] => {\n const separator = pair.indexOf(\"=\");\n if (separator === -1) {\n return [pair.trim(), \"\"];\n }\n return [pair.slice(0, separator).trim(), pair.slice(separator + 1).trim()];\n })\n .filter(([key]) => key.length > 0);\n return Object.fromEntries(entries);\n}\n\nasync function defaultExporter(\n url: string,\n body: unknown,\n headers: Record<string, string>,\n): Promise<void> {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...headers,\n },\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n throw new Error(`OTLP endpoint returned HTTP ${response.status}`);\n }\n}\n"],"mappings":"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,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,+BAA+B,oBAAI,IAAI;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iCAAiC,oBAAI,IAAI;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAUD,IAAM,kCAAkC,oBAAI,IAAI;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CA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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/observability",
3
- "version": "0.8.28-canary.0",
3
+ "version": "0.8.29-canary.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
32
32
  },
33
33
  "dependencies": {
34
- "@opengeni/contracts": "^4.0.0-canary.0",
34
+ "@opengeni/contracts": "^4.1.0-canary.0",
35
35
  "prom-client": "^15.1.3"
36
36
  }
37
37
  }
package/src/index.ts CHANGED
@@ -481,8 +481,21 @@ export type SandboxOperationMetricObservation = {
481
481
  op: string;
482
482
  outcome: "ok" | "not_found" | "failed";
483
483
  durationMs: number;
484
+ materializationFailureReason?: string;
484
485
  };
485
486
 
487
+ const MATERIALIZATION_FAILURE_REASONS = new Set([
488
+ "path_not_visible",
489
+ "command_failed",
490
+ "command_pending",
491
+ "invalid_response",
492
+ "command_error",
493
+ ]);
494
+ const MATERIALIZATION_FAILURE_METRIC = {
495
+ name: "opengeni_sandbox_materialization_verification_failures_total",
496
+ help: "Sandbox destination visibility-check failures by bounded reason; exact command evidence is retained in the session failure event.",
497
+ } as const;
498
+
486
499
  export function createObservability(
487
500
  settings: ObservabilitySettings,
488
501
  options: ObservabilityOptions,
@@ -540,6 +553,27 @@ export class Observability {
540
553
  });
541
554
  this.registerSandboxRolloutConfig();
542
555
  this.registerTenancyCompatibilityLanes();
556
+ if (["worker", "worker-control", "worker-turn", "api"].includes(options.component)) {
557
+ // Publish the finite series at startup so a first failure has a zero
558
+ // baseline and healthy zeroes differ from a missing instrumentation path.
559
+ for (const backend of [...SANDBOX_OPERATION_BACKENDS, "unknown"]) {
560
+ for (const reason of [...MATERIALIZATION_FAILURE_REASONS, "unknown"]) {
561
+ this.incrementCounter({
562
+ ...MATERIALIZATION_FAILURE_METRIC,
563
+ labels: { backend, reason },
564
+ amount: 0,
565
+ });
566
+ }
567
+ }
568
+ }
569
+ if (options.component === "worker" || options.component === "worker-control") {
570
+ for (const outcome of WORKFLOW_WAKE_OUTCOMES) {
571
+ this.incrementCounter({ ...WORKFLOW_WAKE_METRIC, labels: { outcome }, amount: 0 });
572
+ }
573
+ for (const reason of [...WORKFLOW_WAKE_ADMISSION_BLOCKERS, "unknown"]) {
574
+ this.incrementCounter({ ...WORKFLOW_WAKE_BLOCKER_METRIC, labels: { reason }, amount: 0 });
575
+ }
576
+ }
543
577
  }
544
578
  }
545
579
 
@@ -957,6 +991,19 @@ export function sandboxOperationMetricObserver(
957
991
  labels: { backend, op },
958
992
  value: Math.max(0, observation.durationMs) / 1_000,
959
993
  });
994
+ if (
995
+ op === "materializeEntry" &&
996
+ observation.outcome === "failed" &&
997
+ observation.materializationFailureReason
998
+ ) {
999
+ const reason = MATERIALIZATION_FAILURE_REASONS.has(observation.materializationFailureReason)
1000
+ ? observation.materializationFailureReason
1001
+ : "unknown";
1002
+ observability.incrementCounter({
1003
+ ...MATERIALIZATION_FAILURE_METRIC,
1004
+ labels: { backend, reason },
1005
+ });
1006
+ }
960
1007
  } catch {
961
1008
  try {
962
1009
  observability.incrementCounter({
@@ -1131,6 +1178,87 @@ function boundedMetricEnum(allowed: ReadonlySet<string>, value: string): string
1131
1178
  return allowed.has(value) ? value : "unknown";
1132
1179
  }
1133
1180
 
1181
+ const WORKFLOW_WAKE_ADMISSION_BLOCKERS = new Set([
1182
+ "pending_agent_steer",
1183
+ "pending_prompt_turn",
1184
+ "pending_quiescence",
1185
+ "pending_machine_input",
1186
+ "pending_input_wait",
1187
+ ]);
1188
+ const WORKFLOW_WAKE_OUTCOMES = [
1189
+ "signal_accepted",
1190
+ "acknowledged",
1191
+ "pending_admission",
1192
+ "unconfirmed",
1193
+ "failed",
1194
+ ] as const;
1195
+ const WORKFLOW_WAKE_METRIC = {
1196
+ name: "opengeni_session_workflow_wake_observations_total",
1197
+ help: "Workflow wake dispatch observations; signal acceptance overlaps with admission outcomes, and retries are counted again.",
1198
+ };
1199
+ const WORKFLOW_WAKE_BLOCKER_METRIC = {
1200
+ name: "opengeni_session_workflow_wake_admission_blockers_total",
1201
+ help: "Workflow wake dispatch attempts awaiting durable admission, by bounded blocker; repeated revisions count again.",
1202
+ };
1203
+
1204
+ /** Dispatcher observations count attempts, including repeated observations of
1205
+ * the same revision. Transport acceptance is never an admission receipt. */
1206
+ export function recordWorkflowWakeReconciliation(
1207
+ observability: Observability,
1208
+ result: {
1209
+ signaled: number;
1210
+ delivered: number;
1211
+ pendingAdmission: number;
1212
+ unconfirmed: number;
1213
+ failed: number;
1214
+ pendingAdmissionBlockers: Record<string, number | undefined>;
1215
+ },
1216
+ ): void {
1217
+ const count = (value: number | undefined) =>
1218
+ typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : 0;
1219
+ try {
1220
+ for (const [outcome, amount] of [
1221
+ ["signal_accepted", result.signaled],
1222
+ ["acknowledged", result.delivered],
1223
+ ["pending_admission", result.pendingAdmission],
1224
+ ["unconfirmed", result.unconfirmed],
1225
+ ["failed", result.failed],
1226
+ ] as const) {
1227
+ observability.incrementCounter({
1228
+ ...WORKFLOW_WAKE_METRIC,
1229
+ labels: { outcome },
1230
+ amount: count(amount),
1231
+ });
1232
+ if (count(amount) > 0) {
1233
+ // Use the reviewed public telemetry vocabulary. Arbitrary aggregate
1234
+ // property names are intentionally omitted by the external sink.
1235
+ observability.info("Session workflow wake dispatch observed", {
1236
+ surface: "session_workflow_wake",
1237
+ outcome,
1238
+ attempts: count(amount),
1239
+ });
1240
+ }
1241
+ }
1242
+ for (const [blocker, amount] of Object.entries(result.pendingAdmissionBlockers)) {
1243
+ if (count(amount) === 0) continue;
1244
+ const reason = boundedMetricEnum(WORKFLOW_WAKE_ADMISSION_BLOCKERS, blocker);
1245
+ observability.incrementCounter({
1246
+ ...WORKFLOW_WAKE_BLOCKER_METRIC,
1247
+ labels: { reason },
1248
+ amount: count(amount),
1249
+ });
1250
+ observability.info("Session workflow wake admission pending", {
1251
+ surface: "session_workflow_wake",
1252
+ outcome: "pending_admission",
1253
+ reason,
1254
+ attempts: count(amount),
1255
+ });
1256
+ }
1257
+ } catch {
1258
+ recordObserverFailure(observability, "session_workflow_wake");
1259
+ }
1260
+ }
1261
+
1134
1262
  function boundedMetricDuration(durationMs: number): number {
1135
1263
  return Number.isFinite(durationMs) ? Math.max(0, durationMs) / 1_000 : 0;
1136
1264
  }