@inquir/compute 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +162 -6
- package/dist/app-observability.d.ts +117 -0
- package/dist/app-observability.d.ts.map +1 -0
- package/dist/app-observability.js +100 -0
- package/dist/app-observability.js.map +1 -0
- package/dist/app-observability.types.d.ts +365 -0
- package/dist/app-observability.types.d.ts.map +1 -0
- package/dist/app-observability.types.js +2 -0
- package/dist/app-observability.types.js.map +1 -0
- package/dist/apps.d.ts +215 -3
- package/dist/apps.d.ts.map +1 -1
- package/dist/apps.js +25 -2
- package/dist/apps.js.map +1 -1
- package/dist/build-timeout-policy.d.ts +13 -0
- package/dist/build-timeout-policy.d.ts.map +1 -0
- package/dist/build-timeout-policy.js +11 -0
- package/dist/build-timeout-policy.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/invocation-observation.d.ts +23 -0
- package/dist/invocation-observation.d.ts.map +1 -0
- package/dist/invocation-observation.js +79 -0
- package/dist/invocation-observation.js.map +1 -0
- package/dist/projects.d.ts +10 -1
- package/dist/projects.d.ts.map +1 -1
- package/dist/projects.js +13 -1
- package/dist/projects.js.map +1 -1
- package/dist/release-commands.d.ts +80 -0
- package/dist/release-commands.d.ts.map +1 -0
- package/dist/release-commands.js +147 -0
- package/dist/release-commands.js.map +1 -0
- package/dist/source-command-http.d.ts +7 -0
- package/dist/source-command-http.d.ts.map +1 -0
- package/dist/source-command-http.js +87 -0
- package/dist/source-command-http.js.map +1 -0
- package/dist/source-command-protocol.d.ts +137 -0
- package/dist/source-command-protocol.d.ts.map +1 -0
- package/dist/source-command-protocol.js +311 -0
- package/dist/source-command-protocol.js.map +1 -0
- package/dist/source-commands.d.ts +33 -0
- package/dist/source-commands.d.ts.map +1 -0
- package/dist/source-commands.js +116 -0
- package/dist/source-commands.js.map +1 -0
- package/dist/transport.d.ts +27 -2
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +56 -7
- package/dist/transport.js.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
Workspace-first SDK for defining, discovering, generating, and running Inquir Compute assets.
|
|
4
4
|
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
Requires Node.js 22 or newer. Version 0.3 groups only long-lived container applications in projects; functions and pipelines remain separate assets.
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Requires Node.js 22 or newer. Version 0.3 groups only long-lived container applications in projects; functions and pipelines remain separate assets.
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install @inquir/compute zod@^3.23.8
|
|
10
|
+
npm install @inquir/compute zod@^3.23.8
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
> Release order: publish this SDK before the CLI that depends on it. CLI 0.4.0
|
|
14
|
+
> needs SDK 0.4.0 (`isPromoteAccepted`, `getApplicationRollout`); the next CLI
|
|
15
|
+
> needs SDK 0.4.1 (`listAppInstances`, `matchAppInstance`); see
|
|
16
|
+
> `packages/cli/README.md`, "Publishing to npm".
|
|
17
|
+
|
|
13
18
|
## What It Includes
|
|
14
19
|
|
|
15
20
|
- `defineFunction()` and `definePipeline()` for code-first assets.
|
|
@@ -17,8 +22,82 @@ npm install @inquir/compute zod@^3.23.8
|
|
|
17
22
|
- `discoverAssets()` for workspace asset scanning.
|
|
18
23
|
- `generateCodegenArtifacts()` / `generateAndWriteCodegenArtifacts()` for typed client + `registry.json`.
|
|
19
24
|
- `runLocally()` for local function execution/debug harness.
|
|
20
|
-
- HTTP transport helpers (`createClient`, `invokeRemote`, deploy/list helpers).
|
|
21
|
-
- Application project helpers (`listProjects`, `createProject`, `getProject`, `addProjectResource`) group long-lived containers: web services, APIs, databases, and workers. Project members use `kind: 'application'`; serverless functions are managed separately. `createApplication` accepts `projectId` (ID or slug); omitting it creates a project named after the application.
|
|
25
|
+
- HTTP transport helpers (`createClient`, `invokeRemote`, deploy/list helpers).
|
|
26
|
+
- Application project helpers (`listProjects`, `createProject`, `getProject`, `addProjectResource`) group long-lived containers: web services, APIs, databases, and workers. Project members use `kind: 'application'`; serverless functions are managed separately. `createApplication` accepts `projectId` (ID or slug); omitting it creates a project named after the application. Archiving a project also archives all its applications, including an application shared with another project. Removing a membership leaves it running. Project lifecycle actions require `projects:write` and `apps:promote`.
|
|
27
|
+
|
|
28
|
+
## Pending synchronous invocations
|
|
29
|
+
|
|
30
|
+
When the server admits a finite cold invocation, `invokeRemote()` submits once
|
|
31
|
+
and follows only the authenticated invocation's `/resume` endpoint. Hot
|
|
32
|
+
invocations keep their existing path. Save each handle from `onPending` if the
|
|
33
|
+
caller must survive a restart:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { invokeRemote, resumeRemoteInvocation, cancelRemoteInvocation,
|
|
37
|
+
RemoteInvocationObservationEndedError } from '@inquir/compute';
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const result = await invokeRemote(client, 'my-function', event, {
|
|
41
|
+
timeoutMs: 120_000, signal, onPending: saveHandle,
|
|
42
|
+
});
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error instanceof RemoteInvocationObservationEndedError) {
|
|
45
|
+
saveHandle(error.pending); // PENDING/RECOVERY_HELD is not FAILED.
|
|
46
|
+
// Later: await resumeRemoteInvocation(client, error.pending);
|
|
47
|
+
// Explicit intent: await cancelRemoteInvocation(client, error.pending);
|
|
48
|
+
} else throw error;
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Abort/timeout stops observation, not execution. A cancellation receipt records
|
|
53
|
+
intent, not a terminal outcome. If the initial POST reply is lost before a handle
|
|
54
|
+
arrives, this adapter cannot recover an unknown server ID and never repeats that
|
|
55
|
+
POST. Server admission remains independently gated; this client does not enable
|
|
56
|
+
gateway, pipeline, durable or streaming finite execution.
|
|
57
|
+
|
|
58
|
+
## Durable source commands
|
|
59
|
+
|
|
60
|
+
Source execution uses an explicit operation instead of synchronous writable
|
|
61
|
+
`/exec`. Save a lowercase UUID v4 before preparing, and atomically retain every
|
|
62
|
+
record supplied by the callback in private storage. Records contain command/env
|
|
63
|
+
secrets; they contain a credential hash rather than the credential itself.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { createClient, prepareSourceCommand, restoreSourceCommand } from '@inquir/compute';
|
|
67
|
+
|
|
68
|
+
const client = createClient({ baseUrl: apiUrl, apiKey, workspaceId });
|
|
69
|
+
const operation = await prepareSourceCommand(client, {
|
|
70
|
+
function: 'my-function', requestId: savedUuid,
|
|
71
|
+
input: { command: 'npm install', timeoutMs: 60_000 },
|
|
72
|
+
retain: savePrivateRecordAtomically,
|
|
73
|
+
});
|
|
74
|
+
await operation.submit(); // no automatic POST retry
|
|
75
|
+
const state = await operation.status(); // GET only
|
|
76
|
+
const publication = await operation.reconcile(); // explicit source publication
|
|
77
|
+
// await operation.cancel(); // explicit cancellation intent
|
|
78
|
+
const restored = await restoreSourceCommand(client, savedRecord, {
|
|
79
|
+
retain: savePrivateRecordAtomically,
|
|
80
|
+
}); // no HTTP or submission
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The retained API, credential hash, original workspace selector and resolved
|
|
84
|
+
workspace/function IDs must match on restore. Later actions stay pinned to those
|
|
85
|
+
IDs even if the client changes. A lost response keeps the same operation UUID;
|
|
86
|
+
inspect status or explicitly retry the same action. Poll timeout/abort stops
|
|
87
|
+
observation and does not cancel or publish. `EXITED` and `CANCEL_REQUESTED` do not
|
|
88
|
+
prove physical removal or capacity release. A GET with `publication: null` does
|
|
89
|
+
not prove that an earlier explicit publication never happened.
|
|
90
|
+
|
|
91
|
+
Acceptance identity is retained before an action returns and after each poll
|
|
92
|
+
response. If storage fails, further HTTP is blocked until the pending record is
|
|
93
|
+
saved; `operation.persist()` retries storage without HTTP. Keep the updated
|
|
94
|
+
record returned by `record()` for reloads. The server must enable the source
|
|
95
|
+
command API after its activation gates; a 503 never falls back to writable exec.
|
|
96
|
+
|
|
97
|
+
`result.logFailure` and `sourcePublicationState(outcome) === 'CAPTURE_FAILED'`
|
|
98
|
+
mark unavailable log capture, preserving the real termination and exit code.
|
|
99
|
+
Blank Base64 fields then mean unavailable capture rather than successful empty
|
|
100
|
+
logs; workspace output is absent and cannot be published.
|
|
22
101
|
|
|
23
102
|
## Concepts
|
|
24
103
|
|
|
@@ -98,3 +177,80 @@ const client = createClient({ baseUrl: 'http://localhost:3000', apiKey: process.
|
|
|
98
177
|
const response = await invokeRemote(client, 'hello', { name: 'World' });
|
|
99
178
|
```
|
|
100
179
|
|
|
180
|
+
## Readonly published-release commands (scoped rollout)
|
|
181
|
+
|
|
182
|
+
`prepareReleaseCommand` retains the caller's original UUID, workspace and command
|
|
183
|
+
before the first HTTP submission. It uses the dedicated readonly release API;
|
|
184
|
+
it does not invoke the writable source-command API or a function handler.
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { randomUUID } from 'node:crypto';
|
|
188
|
+
import { prepareReleaseCommand, restoreReleaseCommand } from '@inquir/compute';
|
|
189
|
+
|
|
190
|
+
const operation = await prepareReleaseCommand(client, {
|
|
191
|
+
functionId,
|
|
192
|
+
requestId: randomUUID(),
|
|
193
|
+
input: { command: 'cat package.json', timeoutMs: 60_000 },
|
|
194
|
+
retain: async record => saveCommandRecord(record), // Durable caller storage.
|
|
195
|
+
});
|
|
196
|
+
const first = await operation.submit(); // Submit once. Keep the retained record on a lost reply.
|
|
197
|
+
const outcome = first.state === 'PENDING' || first.state === 'RECOVERY_HELD'
|
|
198
|
+
? await restoreReleaseCommand(client, operation.record()).observe()
|
|
199
|
+
: first;
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Observation resumes the same ID and never repeats the initial POST. An expired
|
|
203
|
+
or aborted observer keeps that handle; `operation.cancel()` separately requests
|
|
204
|
+
durable cancellation. Cancellation acknowledgement is an intent, while `REMOVED`
|
|
205
|
+
is a validated terminal result after physical task/container cleanup. Scope or
|
|
206
|
+
artifact uncertainty remains held rather than becoming a fabricated failure.
|
|
207
|
+
`CANCELLED_WITHOUT_CONTAINER` separately proves an admitted reservation was
|
|
208
|
+
cancelled and physically retired before CREATE; its `result` is `null` because
|
|
209
|
+
no shell ran. `CANCELLED_BEFORE_ADMISSION` has no reservation to retire.
|
|
210
|
+
|
|
211
|
+
This path is disabled by default. Each exact runtime image, readonly process,
|
|
212
|
+
source/input mount, resource and network profile must receive native
|
|
213
|
+
qualification before its scoped operator approval and rollout switches enable
|
|
214
|
+
admission. The initial source tests do not constitute that qualification.
|
|
215
|
+
|
|
216
|
+
## Application observability
|
|
217
|
+
|
|
218
|
+
The SDK exposes resource and HTTP history, persisted runtime/HTTP logs and configurable app alerts. Every helper uses the client's credentials and workspace selector:
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
import {
|
|
222
|
+
createClient, getAppMetrics, getAppHttpMetrics, getAppLogHistory,
|
|
223
|
+
createAppAlertRule, updateAppAlertRule, listAppAlertIncidents,
|
|
224
|
+
} from '@inquir/compute';
|
|
225
|
+
|
|
226
|
+
const client = createClient({
|
|
227
|
+
baseUrl: 'https://inquir.org/api',
|
|
228
|
+
apiKey: process.env.INQUIR_TOKEN,
|
|
229
|
+
workspaceId: process.env.INQUIR_WORKSPACE,
|
|
230
|
+
});
|
|
231
|
+
const to = new Date().toISOString();
|
|
232
|
+
const from = new Date(Date.now() - 60 * 60 * 1000).toISOString();
|
|
233
|
+
const resources = await getAppMetrics(client, appId, { from, to });
|
|
234
|
+
const http = await getAppHttpMetrics(client, appId, { from, to });
|
|
235
|
+
const logs = await getAppLogHistory(client, appId, {
|
|
236
|
+
from, to, releaseId, allocationId, allocationFence: 4, level: 'error', limit: 100,
|
|
237
|
+
});
|
|
238
|
+
if (logs.nextCursor) {
|
|
239
|
+
const older = await getAppLogHistory(client, appId, {
|
|
240
|
+
from: logs.from, to: logs.to, releaseId, allocationId, allocationFence: 4,
|
|
241
|
+
level: 'error', limit: 100, cursor: logs.nextCursor,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const { rule } = await createAppAlertRule(client, appId, {
|
|
246
|
+
name: 'High RAM', enabled: true, metric: 'memory_percent',
|
|
247
|
+
threshold: 85, forSeconds: 120, recoveryThreshold: 65,
|
|
248
|
+
recoveryForSeconds: 60, noDataSeconds: 180, noData: 'alert', channels: [],
|
|
249
|
+
});
|
|
250
|
+
await updateAppAlertRule(client, appId, rule.id, { threshold: 90 });
|
|
251
|
+
const { incidents } = await listAppAlertIncidents(client, appId, { limit: 25 });
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`getAppHttpLogHistory`, `listAppAlertRules` and `deleteAppAlertRule` complete the API. Deletion disables the rule and resolves its active incidents; retained history is still available. Omit `channels` in a patch to preserve existing destinations, or pass an empty array to remove them. `webhook`/`slack` channel URLs are write-only; response types expose only channel id, type and configured status. Never log alert request inputs containing a secret URL.
|
|
255
|
+
|
|
256
|
+
Resource and HTTP retention is 30 days; runtime logs are retained for 7 days. Runtime history is attributed to the exact release, allocation/fence, runner/epoch and container, including replaced containers. Paging is newest-first and requires an unchanged date window and filters. Resource history retains unavailable values as `null`; use `status`, `latestSampleAt` and `truncated` to detect stale or incomplete results. Network and block I/O rates are measured separately; block I/O is not volume space usage. CPU/RAM alert percentages are relative to enforced limits, and the continuous maximum across current production replicas determines threshold firing.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { type TransportClient } from './transport.js';
|
|
2
|
+
import type { AppMetricsHistoryResponse, AppHttpMetricsResponse, AppLogHistoryResponse, AppRuntimeLogEntry, AppHttpLogEntry, AppAlertRuleInput, AppAlertRuleDto, AppAlertIncidentDto, AppResourceRecommendationResponse, AppDescribeResponse } from './app-observability.types.js';
|
|
3
|
+
export * from './app-observability.types.js';
|
|
4
|
+
/** ISO 8601 timestamps. Preserve the same window when following a log cursor. */
|
|
5
|
+
export interface AppObservationRange {
|
|
6
|
+
from?: string;
|
|
7
|
+
to?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AppRuntimeLogQuery extends AppObservationRange {
|
|
10
|
+
limit?: number;
|
|
11
|
+
cursor?: string;
|
|
12
|
+
releaseId?: string;
|
|
13
|
+
allocationId?: string;
|
|
14
|
+
allocationFence?: number;
|
|
15
|
+
runnerId?: string;
|
|
16
|
+
runnerEpoch?: number;
|
|
17
|
+
containerId?: string;
|
|
18
|
+
stream?: AppRuntimeLogEntry['stream'];
|
|
19
|
+
level?: Exclude<AppRuntimeLogEntry['level'], null>;
|
|
20
|
+
search?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface AppHttpLogQuery extends AppObservationRange {
|
|
23
|
+
limit?: number;
|
|
24
|
+
cursor?: string;
|
|
25
|
+
releaseId?: string;
|
|
26
|
+
statusCode?: number;
|
|
27
|
+
query?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Actual resource history, up to 30 days; CPU/RAM percentages use enforced limits. */
|
|
30
|
+
export declare function getAppMetrics(client: TransportClient, appId: string, range?: AppObservationRange): Promise<AppMetricsHistoryResponse>;
|
|
31
|
+
/**
|
|
32
|
+
* Read-only CPU/RAM right-sizing advice from observed usage over the last
|
|
33
|
+
* `days` days (1 to 7, default 7). Nothing changes until the figures are
|
|
34
|
+
* applied with an application update and a redeploy.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getAppResourceRecommendation(client: TransportClient, appId: string, options?: {
|
|
37
|
+
days?: number;
|
|
38
|
+
}): Promise<AppResourceRecommendationResponse>;
|
|
39
|
+
/**
|
|
40
|
+
* Why the application is (not) running: conditions of the application, its
|
|
41
|
+
* releases, replica attempts and runners, the plan capacity and recent events.
|
|
42
|
+
* Read-only.
|
|
43
|
+
*/
|
|
44
|
+
export declare function describeApp(client: TransportClient, appId: string): Promise<AppDescribeResponse>;
|
|
45
|
+
/** One replica of an application, the pod analog (docs/design/REPLICA_SELECTION.md). */
|
|
46
|
+
export interface AppInstance {
|
|
47
|
+
/** `<app>-<replicaIndex>-<allocationId[0..8]>`: stable for one attempt, new for a replacement. */
|
|
48
|
+
name: string;
|
|
49
|
+
/** Null only for a legacy (pre-allocation) single container. */
|
|
50
|
+
allocationId: string | null;
|
|
51
|
+
releaseId: string;
|
|
52
|
+
production: boolean;
|
|
53
|
+
replicaIndex: number;
|
|
54
|
+
incarnation: number;
|
|
55
|
+
/** Earlier attempts of this slot in this release. */
|
|
56
|
+
restarts: number;
|
|
57
|
+
state: string;
|
|
58
|
+
/** Serving production traffic right now. */
|
|
59
|
+
ready: boolean;
|
|
60
|
+
console: 'available' | 'remote_unsupported' | 'unavailable';
|
|
61
|
+
runner: {
|
|
62
|
+
id: string;
|
|
63
|
+
provider: string;
|
|
64
|
+
region: string | null;
|
|
65
|
+
} | null;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
startedAt: string | null;
|
|
68
|
+
readyAt: string | null;
|
|
69
|
+
failure: string | null;
|
|
70
|
+
usage: {
|
|
71
|
+
cpuUsedCores: number | null;
|
|
72
|
+
cpuPercent: number | null;
|
|
73
|
+
memoryWorkingSetBytes: number | null;
|
|
74
|
+
memoryPercent: number | null;
|
|
75
|
+
sampledAt: string;
|
|
76
|
+
} | null;
|
|
77
|
+
conditions: AppDescribeResponse['application']['conditions'];
|
|
78
|
+
}
|
|
79
|
+
export interface AppInstancesResponse {
|
|
80
|
+
applicationId: string;
|
|
81
|
+
productionReleaseId: string | null;
|
|
82
|
+
generatedAt: string;
|
|
83
|
+
instances: AppInstance[];
|
|
84
|
+
}
|
|
85
|
+
/** The application's replicas: name, state, runner, readiness, restarts, CPU/memory now. */
|
|
86
|
+
export declare function listAppInstances(client: TransportClient, appId: string): Promise<AppInstancesResponse>;
|
|
87
|
+
/**
|
|
88
|
+
* Resolve a replica selector the way the server does: exact allocation id,
|
|
89
|
+
* instance name (`...-<index>-<id8>`), bare replica index (the ready one
|
|
90
|
+
* first), or a unique allocation-id prefix of at least 8 characters.
|
|
91
|
+
*/
|
|
92
|
+
export declare function matchAppInstance(selector: string, instances: readonly AppInstance[]): AppInstance | null;
|
|
93
|
+
/** HTTP gateway observations; private TCP traffic is not HTTP request telemetry. */
|
|
94
|
+
export declare function getAppHttpMetrics(client: TransportClient, appId: string, range?: AppObservationRange): Promise<AppHttpMetricsResponse>;
|
|
95
|
+
/** One descending timestamp/id page of persisted runtime logs (7-day retention). */
|
|
96
|
+
export declare function getAppLogHistory(client: TransportClient, appId: string, query?: AppRuntimeLogQuery): Promise<AppLogHistoryResponse<AppRuntimeLogEntry>>;
|
|
97
|
+
/** One descending timestamp/id page of HTTP access logs (30-day retention). */
|
|
98
|
+
export declare function getAppHttpLogHistory(client: TransportClient, appId: string, query?: AppHttpLogQuery): Promise<AppLogHistoryResponse<AppHttpLogEntry>>;
|
|
99
|
+
export declare function listAppAlertRules(client: TransportClient, appId: string): Promise<{
|
|
100
|
+
rules: AppAlertRuleDto[];
|
|
101
|
+
}>;
|
|
102
|
+
/** URLs are write-only secrets. Returned channels contain only id/type/configured. */
|
|
103
|
+
export declare function createAppAlertRule(client: TransportClient, appId: string, input: AppAlertRuleInput): Promise<{
|
|
104
|
+
rule: AppAlertRuleDto;
|
|
105
|
+
}>;
|
|
106
|
+
/** Omit channels to keep configured destinations; [] removes them. */
|
|
107
|
+
export declare function updateAppAlertRule(client: TransportClient, appId: string, ruleId: string, input: Partial<AppAlertRuleInput>): Promise<{
|
|
108
|
+
rule: AppAlertRuleDto;
|
|
109
|
+
}>;
|
|
110
|
+
/** Disables the rule and resolves its incidents; history is retained. No response body. */
|
|
111
|
+
export declare function deleteAppAlertRule(client: TransportClient, appId: string, ruleId: string): Promise<void>;
|
|
112
|
+
export declare function listAppAlertIncidents(client: TransportClient, appId: string, options?: {
|
|
113
|
+
limit?: number;
|
|
114
|
+
}): Promise<{
|
|
115
|
+
incidents: AppAlertIncidentDto[];
|
|
116
|
+
}>;
|
|
117
|
+
//# sourceMappingURL=app-observability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-observability.d.ts","sourceRoot":"","sources":["../src/app-observability.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { rawRequest } from './transport.js';
|
|
2
|
+
export * from './app-observability.types.js';
|
|
3
|
+
function appPath(id, suffix) {
|
|
4
|
+
return `/v1/apps/${encodeURIComponent(id)}/${suffix}`;
|
|
5
|
+
}
|
|
6
|
+
function queryString(options) {
|
|
7
|
+
const query = new URLSearchParams();
|
|
8
|
+
for (const [key, value] of Object.entries(options)) {
|
|
9
|
+
// Zero is significant (notably runner epoch); unknown observations remain null in responses.
|
|
10
|
+
if (value !== undefined)
|
|
11
|
+
query.set(key, String(value));
|
|
12
|
+
}
|
|
13
|
+
return query.size ? `?${query}` : '';
|
|
14
|
+
}
|
|
15
|
+
/** Actual resource history, up to 30 days; CPU/RAM percentages use enforced limits. */
|
|
16
|
+
export function getAppMetrics(client, appId, range = {}) {
|
|
17
|
+
return rawRequest(client, 'GET', appPath(appId, 'metrics') + queryString(range));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read-only CPU/RAM right-sizing advice from observed usage over the last
|
|
21
|
+
* `days` days (1 to 7, default 7). Nothing changes until the figures are
|
|
22
|
+
* applied with an application update and a redeploy.
|
|
23
|
+
*/
|
|
24
|
+
export function getAppResourceRecommendation(client, appId, options = {}) {
|
|
25
|
+
return rawRequest(client, 'GET', appPath(appId, 'resources/recommendation') + queryString(options));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Why the application is (not) running: conditions of the application, its
|
|
29
|
+
* releases, replica attempts and runners, the plan capacity and recent events.
|
|
30
|
+
* Read-only.
|
|
31
|
+
*/
|
|
32
|
+
export function describeApp(client, appId) {
|
|
33
|
+
return rawRequest(client, 'GET', appPath(appId, 'describe'));
|
|
34
|
+
}
|
|
35
|
+
/** The application's replicas: name, state, runner, readiness, restarts, CPU/memory now. */
|
|
36
|
+
export function listAppInstances(client, appId) {
|
|
37
|
+
return rawRequest(client, 'GET', appPath(appId, 'instances'));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a replica selector the way the server does: exact allocation id,
|
|
41
|
+
* instance name (`...-<index>-<id8>`), bare replica index (the ready one
|
|
42
|
+
* first), or a unique allocation-id prefix of at least 8 characters.
|
|
43
|
+
*/
|
|
44
|
+
export function matchAppInstance(selector, instances) {
|
|
45
|
+
const value = selector.trim();
|
|
46
|
+
const candidates = instances.filter((instance) => instance.allocationId !== null);
|
|
47
|
+
if (!value)
|
|
48
|
+
return null;
|
|
49
|
+
const unique = (matches) => (matches.length === 1 ? matches[0] : null);
|
|
50
|
+
const exact = candidates.filter((instance) => instance.allocationId === value || instance.name === value);
|
|
51
|
+
if (exact.length)
|
|
52
|
+
return unique(exact);
|
|
53
|
+
const named = /-(\d{1,4})-([A-Za-z0-9]{8})$/u.exec(value);
|
|
54
|
+
if (named) {
|
|
55
|
+
const matches = candidates.filter((instance) => instance.replicaIndex === Number(named[1]) &&
|
|
56
|
+
instance.allocationId.toLowerCase().startsWith(named[2].toLowerCase()));
|
|
57
|
+
if (matches.length)
|
|
58
|
+
return unique(matches);
|
|
59
|
+
}
|
|
60
|
+
if (/^\d{1,4}$/u.test(value)) {
|
|
61
|
+
const slot = candidates.filter((instance) => instance.replicaIndex === Number(value));
|
|
62
|
+
// A slot can hold a ready attempt and its replacement or a failed one: prefer the production ready one.
|
|
63
|
+
return unique(slot.filter((instance) => instance.production && instance.ready)) ?? unique(slot.filter((instance) => instance.production)) ?? unique(slot);
|
|
64
|
+
}
|
|
65
|
+
if (value.length >= 8 && /^[A-Za-z0-9-]+$/u.test(value)) {
|
|
66
|
+
return unique(candidates.filter((instance) => instance.allocationId.toLowerCase().startsWith(value.toLowerCase())));
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/** HTTP gateway observations; private TCP traffic is not HTTP request telemetry. */
|
|
71
|
+
export function getAppHttpMetrics(client, appId, range = {}) {
|
|
72
|
+
return rawRequest(client, 'GET', appPath(appId, 'http-metrics') + queryString(range));
|
|
73
|
+
}
|
|
74
|
+
/** One descending timestamp/id page of persisted runtime logs (7-day retention). */
|
|
75
|
+
export function getAppLogHistory(client, appId, query = {}) {
|
|
76
|
+
return rawRequest(client, 'GET', appPath(appId, 'logs/runtime') + queryString(query));
|
|
77
|
+
}
|
|
78
|
+
/** One descending timestamp/id page of HTTP access logs (30-day retention). */
|
|
79
|
+
export function getAppHttpLogHistory(client, appId, query = {}) {
|
|
80
|
+
return rawRequest(client, 'GET', appPath(appId, 'http-logs') + queryString(query));
|
|
81
|
+
}
|
|
82
|
+
export function listAppAlertRules(client, appId) {
|
|
83
|
+
return rawRequest(client, 'GET', appPath(appId, 'alert-rules'));
|
|
84
|
+
}
|
|
85
|
+
/** URLs are write-only secrets. Returned channels contain only id/type/configured. */
|
|
86
|
+
export function createAppAlertRule(client, appId, input) {
|
|
87
|
+
return rawRequest(client, 'POST', appPath(appId, 'alert-rules'), input);
|
|
88
|
+
}
|
|
89
|
+
/** Omit channels to keep configured destinations; [] removes them. */
|
|
90
|
+
export function updateAppAlertRule(client, appId, ruleId, input) {
|
|
91
|
+
return rawRequest(client, 'PATCH', appPath(appId, `alert-rules/${encodeURIComponent(ruleId)}`), input);
|
|
92
|
+
}
|
|
93
|
+
/** Disables the rule and resolves its incidents; history is retained. No response body. */
|
|
94
|
+
export async function deleteAppAlertRule(client, appId, ruleId) {
|
|
95
|
+
await rawRequest(client, 'DELETE', appPath(appId, `alert-rules/${encodeURIComponent(ruleId)}`));
|
|
96
|
+
}
|
|
97
|
+
export function listAppAlertIncidents(client, appId, options = {}) {
|
|
98
|
+
return rawRequest(client, 'GET', appPath(appId, 'alert-incidents') + queryString(options));
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=app-observability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-observability.js","sourceRoot":"","sources":["../src/app-observability.ts"],"names":[],"mappings":"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"}
|