alasio 7.0.0 → 9.0.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/cli/src/api-server.js +18 -0
- package/dist/cli/src/api-server.js.map +1 -0
- package/dist/cli/src/branches.js +123 -46
- package/dist/cli/src/branches.js.map +1 -1
- package/dist/cli/src/cluster/docker.js +25 -10
- package/dist/cli/src/cluster/docker.js.map +1 -1
- package/dist/cli/src/cluster/host.js +33 -7
- package/dist/cli/src/cluster/host.js.map +1 -1
- package/dist/cli/src/cluster/k3s.js +51 -12
- package/dist/cli/src/cluster/k3s.js.map +1 -1
- package/dist/cli/src/cluster/node.js +115 -33
- package/dist/cli/src/cluster/node.js.map +1 -1
- package/dist/cli/src/cluster/stargz.js +55 -0
- package/dist/cli/src/cluster/stargz.js.map +1 -0
- package/dist/cli/src/commands/branch.js +5 -4
- package/dist/cli/src/commands/branch.js.map +1 -1
- package/dist/cli/src/commands/common.js +9 -3
- package/dist/cli/src/commands/common.js.map +1 -1
- package/dist/cli/src/commands/folder.js +14 -0
- package/dist/cli/src/commands/folder.js.map +1 -0
- package/dist/cli/src/commands/init.js +54 -4
- package/dist/cli/src/commands/init.js.map +1 -1
- package/dist/cli/src/commands/lake.js +40 -6
- package/dist/cli/src/commands/lake.js.map +1 -1
- package/dist/cli/src/commands/restore-filer-store.js +40 -8
- package/dist/cli/src/commands/restore-filer-store.js.map +1 -1
- package/dist/cli/src/commands/status.js +216 -20
- package/dist/cli/src/commands/status.js.map +1 -1
- package/dist/cli/src/commands/uninstall.js +8 -9
- package/dist/cli/src/commands/uninstall.js.map +1 -1
- package/dist/cli/src/commands/up.js +11 -3
- package/dist/cli/src/commands/up.js.map +1 -1
- package/dist/cli/src/commands/upgrade.js +1 -1
- package/dist/cli/src/commands/upgrade.js.map +1 -1
- package/dist/cli/src/commands.js +2 -1
- package/dist/cli/src/commands.js.map +1 -1
- package/dist/cli/src/config.js +24 -9
- package/dist/cli/src/config.js.map +1 -1
- package/dist/cli/src/cpu-baseline.js +8 -4
- package/dist/cli/src/cpu-baseline.js.map +1 -1
- package/dist/cli/src/folders.js +67 -0
- package/dist/cli/src/folders.js.map +1 -0
- package/dist/cli/src/gateway-calls.js +58 -0
- package/dist/cli/src/gateway-calls.js.map +1 -0
- package/dist/cli/src/install.js +119 -17
- package/dist/cli/src/install.js.map +1 -1
- package/dist/cli/src/kept-releases.js +27 -20
- package/dist/cli/src/kept-releases.js.map +1 -1
- package/dist/cli/src/kube/api.js +11 -5
- package/dist/cli/src/kube/api.js.map +1 -1
- package/dist/cli/src/kube/apply.js +16 -73
- package/dist/cli/src/kube/apply.js.map +1 -1
- package/dist/cli/src/kube/rollout.js +84 -26
- package/dist/cli/src/kube/rollout.js.map +1 -1
- package/dist/cli/src/lake.js +124 -0
- package/dist/cli/src/lake.js.map +1 -0
- package/dist/cli/src/manifests/admission.js +381 -223
- package/dist/cli/src/manifests/admission.js.map +1 -1
- package/dist/cli/src/manifests/alasio.js +79 -362
- package/dist/cli/src/manifests/alasio.js.map +1 -1
- package/dist/cli/src/manifests/branch.js +10 -26
- package/dist/cli/src/manifests/branch.js.map +1 -1
- package/dist/cli/src/manifests/collector.js +250 -135
- package/dist/cli/src/manifests/collector.js.map +1 -1
- package/dist/cli/src/manifests/common.js +32 -2
- package/dist/cli/src/manifests/common.js.map +1 -1
- package/dist/cli/src/manifests/config.js +256 -92
- package/dist/cli/src/manifests/config.js.map +1 -1
- package/dist/cli/src/manifests/disruption.js +10 -0
- package/dist/cli/src/manifests/disruption.js.map +1 -1
- package/dist/cli/src/manifests/folders.js +128 -0
- package/dist/cli/src/manifests/folders.js.map +1 -0
- package/dist/cli/src/manifests/grafana.js +4 -2
- package/dist/cli/src/manifests/grafana.js.map +1 -1
- package/dist/cli/src/manifests/index.js +15 -8
- package/dist/cli/src/manifests/index.js.map +1 -1
- package/dist/cli/src/manifests/keda.js +2 -1
- package/dist/cli/src/manifests/keda.js.map +1 -1
- package/dist/cli/src/manifests/lake.js +350 -73
- package/dist/cli/src/manifests/lake.js.map +1 -1
- package/dist/cli/src/manifests/log.js +316 -0
- package/dist/cli/src/manifests/log.js.map +1 -0
- package/dist/cli/src/manifests/neon.js +128 -49
- package/dist/cli/src/manifests/neon.js.map +1 -1
- package/dist/cli/src/manifests/network-policies.js +263 -100
- package/dist/cli/src/manifests/network-policies.js.map +1 -1
- package/dist/cli/src/manifests/node-agent.js +24 -8
- package/dist/cli/src/manifests/node-agent.js.map +1 -1
- package/dist/cli/src/manifests/object-store.js +4 -2
- package/dist/cli/src/manifests/object-store.js.map +1 -1
- package/dist/cli/src/manifests/sandbox-gateway.js +663 -0
- package/dist/cli/src/manifests/sandbox-gateway.js.map +1 -0
- package/dist/cli/src/manifests/scalers.js +16 -5
- package/dist/cli/src/manifests/scalers.js.map +1 -1
- package/dist/cli/src/manifests/sizing.js +16 -8
- package/dist/cli/src/manifests/sizing.js.map +1 -1
- package/dist/cli/src/manifests/valkey.js +11 -5
- package/dist/cli/src/manifests/valkey.js.map +1 -1
- package/dist/cli/src/manifests/vpa.js +3 -1
- package/dist/cli/src/manifests/vpa.js.map +1 -1
- package/dist/cli/src/manifests/webhook.js +102 -0
- package/dist/cli/src/manifests/webhook.js.map +1 -0
- package/dist/cli/src/manifests/workspace-storage.js +174 -89
- package/dist/cli/src/manifests/workspace-storage.js.map +1 -1
- package/dist/cli/src/neon-storage.js +155 -0
- package/dist/cli/src/neon-storage.js.map +1 -0
- package/dist/cli/src/release.js +9 -6
- package/dist/cli/src/release.js.map +1 -1
- package/dist/cli/src/secrets.js +45 -4
- package/dist/cli/src/secrets.js.map +1 -1
- package/dist/cli/src/target.js +1 -1
- package/dist/cli/src/target.js.map +1 -1
- package/dist/cli/src/telegram.js +56 -10
- package/dist/cli/src/telegram.js.map +1 -1
- package/dist/cli/src/webhook.js +182 -0
- package/dist/cli/src/webhook.js.map +1 -0
- package/dist/cluster/node/pins.json +12 -2
- package/dist/neon/control/branches.js +126 -21
- package/dist/neon/control/branches.js.map +1 -1
- package/dist/neon/control/endpoints.js +9 -0
- package/dist/neon/control/endpoints.js.map +1 -1
- package/dist/neon/control/jwt.js +16 -3
- package/dist/neon/control/jwt.js.map +1 -1
- package/dist/neon/control/secrets.js +51 -7
- package/dist/neon/control/secrets.js.map +1 -1
- package/dist/src/binder/names.js +33 -0
- package/dist/src/binder/names.js.map +1 -0
- package/dist/src/binder/tokens.js +58 -0
- package/dist/src/binder/tokens.js.map +1 -0
- package/dist/src/branch/names.js +12 -2
- package/dist/src/branch/names.js.map +1 -1
- package/dist/src/events/names.js +7 -0
- package/dist/src/events/names.js.map +1 -0
- package/dist/src/gateway/names.js +201 -0
- package/dist/src/gateway/names.js.map +1 -0
- package/dist/src/harness/names.js +49 -0
- package/dist/src/harness/names.js.map +1 -0
- package/dist/src/kube/sandbox-shape.js +19 -69
- package/dist/src/kube/sandbox-shape.js.map +1 -1
- package/dist/src/node-agent/names.js +118 -2
- package/dist/src/node-agent/names.js.map +1 -1
- package/dist/src/sandbox/names.js +12 -20
- package/dist/src/sandbox/names.js.map +1 -1
- package/dist/src/sandbox/otlp-resource.js +173 -0
- package/dist/src/sandbox/otlp-resource.js.map +1 -0
- package/dist/src/sandbox/telemetry.js +43 -0
- package/dist/src/sandbox/telemetry.js.map +1 -0
- package/dist/src/telegram/deliveries.js +40 -0
- package/dist/src/telegram/deliveries.js.map +1 -0
- package/dist/src/telemetry/config.js +131 -0
- package/dist/src/telemetry/config.js.map +1 -0
- package/dist/src/telemetry/forward.js +154 -0
- package/dist/src/telemetry/forward.js.map +1 -0
- package/package.json +1 -1
- package/dist/cli/src/manifests/agent-sandbox.js +0 -92
- package/dist/cli/src/manifests/agent-sandbox.js.map +0 -1
- package/dist/cli/src/manifests/juicefs-csi.js +0 -319
- package/dist/cli/src/manifests/juicefs-csi.js.map +0 -1
- package/dist/cli/src/manifests/sandboxes.agents.x-k8s.io.json +0 -6295
- package/dist/src/kube/config.js +0 -143
- package/dist/src/kube/config.js.map +0 -1
|
@@ -8,6 +8,35 @@
|
|
|
8
8
|
*/
|
|
9
9
|
/** The port a node agent serves its API on, on its pod's address. */
|
|
10
10
|
export const NODE_AGENT_PORT = 8484;
|
|
11
|
+
/**
|
|
12
|
+
* The port a node agent serves the snapshots bucket on, to its node's restores, on its
|
|
13
|
+
* pod's address (../node-agent/store-proxy.ts): no network policy admits it, so the node
|
|
14
|
+
* alone reaches it, as a node reaches the pods it runs.
|
|
15
|
+
*/
|
|
16
|
+
export const STORE_PROXY_PORT = 8485;
|
|
17
|
+
/**
|
|
18
|
+
* Where a node agent keeps, on its node's /run, a tmpfs, what outlives it until the node
|
|
19
|
+
* restarts: the Unix domain socket it serves the snapshots bucket on to its node's restores
|
|
20
|
+
* too, which a restore's checkpoint gofer dials by its path, whatever pod the agent runs in
|
|
21
|
+
* (STORE_SOCKET), and those restores' tokens, read back as it starts again
|
|
22
|
+
* (STORE_TOKENS_FILE), each only root's. Of the pods alasio makes, the agent alone mounts the
|
|
23
|
+
* node's /run (cli/src/manifests/node-agent.ts), and the sessions' pods are held to their
|
|
24
|
+
* templates, which mount none of it (cli/src/manifests/admission.ts sandboxPodPolicy). The
|
|
25
|
+
* host profile's mounts, which the operator gives alasio and the folder's bayma, could reach
|
|
26
|
+
* it, but both run as the operator's user (1000 unless the profile says), whom the socket's
|
|
27
|
+
* and the file's mode, 0600 and root's, keep out.
|
|
28
|
+
*/
|
|
29
|
+
export const NODE_AGENT_RUN_DIR = "/run/alasio/node-agent";
|
|
30
|
+
/** The variable that moves NODE_AGENT_RUN_DIR, as a test of the agent's own process does. */
|
|
31
|
+
export const NODE_AGENT_RUN_DIR_VARIABLE = "ALASIO_NODE_AGENT_RUN_DIR";
|
|
32
|
+
/** The socket a node agent serves the snapshots bucket on, on its node, in `runDir` (NODE_AGENT_RUN_DIR). */
|
|
33
|
+
export const storeSocket = (runDir) => `${runDir}/store.sock`;
|
|
34
|
+
/** The file a node agent keeps its restores' tokens in, on its node, in `runDir` (NODE_AGENT_RUN_DIR). */
|
|
35
|
+
export const storeTokensFile = (runDir) => `${runDir}/tokens.json`;
|
|
36
|
+
/** The URL a restore's gofer names the store by through STORE_SOCKET, which it signs: no host's, as the socket alone is dialled. */
|
|
37
|
+
export const STORE_SOCKET_ENDPOINT = "http://alasio-node-agent";
|
|
38
|
+
/** The variable that gives a node agent its pod's address, which it serves the bucket to its node on. */
|
|
39
|
+
export const POD_IP_VARIABLE = "POD_IP";
|
|
11
40
|
/**
|
|
12
41
|
* Where a node keeps the gVisor releases alasio keeps, each in a directory of its own
|
|
13
42
|
* named after it, as its release archive has them: runsc, its shim, and gvisor-bin/, the
|
|
@@ -16,6 +45,50 @@ export const NODE_AGENT_PORT = 8484;
|
|
|
16
45
|
export const GVISOR_RELEASES = "/usr/local/lib/alasio/gvisor";
|
|
17
46
|
/** The directory of gVisor's `release` on a node. */
|
|
18
47
|
export const gvisorDirectory = (release) => `${GVISOR_RELEASES}/${release}`;
|
|
48
|
+
/**
|
|
49
|
+
* Whether gVisor's `release` restores a sandbox straight from the bucket, its images read
|
|
50
|
+
* through the checkpoint gofer as the restore goes: one of the fork's at or past `since`,
|
|
51
|
+
* the first release that does, as cluster/node/pins.json says it (restoresFromBucketSince)
|
|
52
|
+
* and the installation gives the node agent it (RESTORES_FROM_BUCKET_SINCE_VARIABLE), by
|
|
53
|
+
* its base's date and patch, then its own number. One before it, as the fork's
|
|
54
|
+
* 20260921.0-eaucoin.6, which ends the sandbox as it tries (`urpc method
|
|
55
|
+
* "containerManager.Restore" failed: EOF`), is fetched into the node's cache first and
|
|
56
|
+
* restored from there; so is one that names no release of the fork's, and every release
|
|
57
|
+
* where `since` names none.
|
|
58
|
+
*/
|
|
59
|
+
export function restoresFromBucket(release, since) {
|
|
60
|
+
return releaseAtOrPast(release, since);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether gVisor's `release` is the fork's `since` or one past it, by its base's date and
|
|
64
|
+
* patch, then its own number; never where either names no release of the fork's.
|
|
65
|
+
*/
|
|
66
|
+
function releaseAtOrPast(release, since) {
|
|
67
|
+
const parts = (named) => {
|
|
68
|
+
const matched = /^(\d{8})\.(\d+)-eaucoin\.(\d+)$/u.exec(named);
|
|
69
|
+
return matched ? matched.slice(1).map(Number) : null;
|
|
70
|
+
};
|
|
71
|
+
const [of, first] = [parts(release), parts(since)];
|
|
72
|
+
if (of === null || first === null)
|
|
73
|
+
return false;
|
|
74
|
+
const differs = of.findIndex((part, index) => part !== first[index]);
|
|
75
|
+
return differs === -1 || (of[differs] ?? 0) > (first[differs] ?? 0);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The gofer a restore of a snapshot taken under gVisor's `release` asks for: through a socket,
|
|
79
|
+
* reading again pages a read of failed, of one at or past `since`, the first release that
|
|
80
|
+
* restores so, as cluster/node/pins.json says it (gvisor.restoresThroughSocketSince); none,
|
|
81
|
+
* the agent's own way, over TCP, of one before it, and of every release where `since` names none.
|
|
82
|
+
*/
|
|
83
|
+
export const goferOf = (release, since) => (releaseAtOrPast(release, since) ? { transport: "socket", pagesRetry: true } : null);
|
|
84
|
+
/**
|
|
85
|
+
* The name of a restore's pod, as the gateway makes it (../gateway/names.ts restorePodName): its
|
|
86
|
+
* pool's, `-restore-`, then seven of base 36's digits; the one name whose directory the node
|
|
87
|
+
* agent makes for it, before the pod is made.
|
|
88
|
+
*/
|
|
89
|
+
export const RESTORE_POD = /^[a-z0-9]([-a-z0-9]*[a-z0-9])?-restore-[0-9a-z]{7}$/u;
|
|
90
|
+
/** The variable that gives the node agent the first gVisor release that restores straight from the bucket (restoresFromBucket). */
|
|
91
|
+
export const RESTORES_FROM_BUCKET_SINCE_VARIABLE = "ALASIO_GVISOR_RESTORES_FROM_BUCKET_SINCE";
|
|
19
92
|
/** Where k3s's containerd reads its template, and runsc its options. */
|
|
20
93
|
export const CONTAINERD = "/var/lib/rancher/k3s/agent/etc/containerd";
|
|
21
94
|
/** gVisor's `release` as a DNS label, which containerd's runtimes and Kubernetes' RuntimeClasses are named with: its dots made dashes. */
|
|
@@ -29,6 +102,13 @@ export const gvisorHandler = (release) => `runsc-${gvisorLabel(release)}`;
|
|
|
29
102
|
export const gvisorRuntimeClass = (release) => `gvisor-${gvisorLabel(release)}`;
|
|
30
103
|
/** The version runsc of gVisor's `release` reports, and saves its images with: its release's tag. */
|
|
31
104
|
export const runscVersion = (release) => `release-${release}`;
|
|
105
|
+
/**
|
|
106
|
+
* Where a node has workspace storage mounted, held by a pod of its own, each workspace's
|
|
107
|
+
* files at `<environment>/<workspace>/files`.
|
|
108
|
+
*/
|
|
109
|
+
export const WORKSPACES_ROOT = "/var/lib/alasio/workspaces";
|
|
110
|
+
/** Where a node keeps the directory of each pod of a sandbox pool, `<namespace>/<pod>`, which the pod mounts by `subPathExpr` of its namespace and its name. */
|
|
111
|
+
export const ATTACH_ROOT = "/var/lib/alasio/attach";
|
|
32
112
|
/** The root the gVisor shims run runsc with for Kubernetes' containers, under the node's /run. */
|
|
33
113
|
export const RUNSC_ROOT = "/run/containerd/runsc/k8s.io";
|
|
34
114
|
/** The node's snapshot cache, where its sandboxes are restored from, as the admission policy holds a restore to. */
|
|
@@ -61,14 +141,50 @@ export const UNSYNCED_DOWNLOAD_BYTES = SNAPSHOT_PARTS_AT_ONCE * SNAPSHOT_SYNC_BY
|
|
|
61
141
|
export const NODE_AGENT_OWN_BYTES = 160 * 1024 ** 2;
|
|
62
142
|
/** The least memory limit a node agent runs under: its own, and a download's budget beside it. */
|
|
63
143
|
export const NODE_AGENT_MEMORY_FLOOR = NODE_AGENT_OWN_BYTES + UNSYNCED_DOWNLOAD_BYTES;
|
|
64
|
-
/** The variable holding the token
|
|
144
|
+
/** The variable holding the token the sandbox gateway presents to a node agent. */
|
|
65
145
|
export const NODE_AGENT_TOKEN_VARIABLE = "ALASIO_NODE_AGENT_TOKEN";
|
|
146
|
+
/** The variable holding workspace storage's metadata engine's address, its password in it, which the agent sets workspaces' quotas on alone. */
|
|
147
|
+
export const META_URL_VARIABLE = "META_URL";
|
|
66
148
|
/** The variable holding the most bytes the node's snapshot cache keeps. */
|
|
67
149
|
export const SNAPSHOT_CACHE_BYTES_VARIABLE = "ALASIO_SNAPSHOT_CACHE_BYTES";
|
|
68
150
|
/**
|
|
69
151
|
* How long a checkpoint, a prepare or a copy may take: a sandbox's memory, through the store,
|
|
70
152
|
* both ways, or within it. alasio waits for one so long, and an agent that stops lets the
|
|
71
|
-
* ones it runs end within it (./operations.ts).
|
|
153
|
+
* ones it runs end within it (./operations.ts), after its restores' reads (nodeAgentStopSeconds).
|
|
72
154
|
*/
|
|
73
155
|
export const OPERATION_LIMIT_SECONDS = 15 * 60;
|
|
156
|
+
/**
|
|
157
|
+
* How long a restore from the bucket may take from its prepare to its resume, which its token
|
|
158
|
+
* lasts unless resumed before (./store-proxy.ts): the longest it takes, alasio waiting 3
|
|
159
|
+
* minutes for its pod to run (POD_RUNNING_TIMEOUT_MS in src/gateway/snapshots.ts), then for the
|
|
160
|
+
* agent's resume, and a margin.
|
|
161
|
+
*/
|
|
162
|
+
export const RESTORE_PREPARED_FOR_SECONDS = 5 * 60;
|
|
163
|
+
/** The variable holding how long, in seconds, a resumed restore from the bucket may read it through the node agent (backgroundReadSeconds). */
|
|
164
|
+
export const BACKGROUND_READ_SECONDS_VARIABLE = "ALASIO_BACKGROUND_READ_SECONDS";
|
|
165
|
+
/**
|
|
166
|
+
* The slowest a resumed restore is taken to read the rest of its sandbox through the node
|
|
167
|
+
* agent, in the background: half of what gate 4 measured on a runner's bundled SeaweedFS,
|
|
168
|
+
* 8.7 MB/s through the agent's proxy from the restore's start to its last read
|
|
169
|
+
* (program/progress/live-lazy.md).
|
|
170
|
+
*/
|
|
171
|
+
export const BACKGROUND_READ_BYTES_PER_SECOND = 4 * 1024 ** 2;
|
|
172
|
+
/**
|
|
173
|
+
* How long a resumed restore of a sandbox of at most `memoryBytes` may read the rest of it
|
|
174
|
+
* through the node agent, at the slowest (BACKGROUND_READ_BYTES_PER_SECOND), in seconds: a
|
|
175
|
+
* minute at least.
|
|
176
|
+
*/
|
|
177
|
+
export function backgroundReadSeconds(memoryBytes) {
|
|
178
|
+
return Math.max(60, Math.ceil(memoryBytes / BACKGROUND_READ_BYTES_PER_SECOND));
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* How long a node agent that stops may take, its sandboxes of at most `memoryBytes`: the
|
|
182
|
+
* restores that read the bucket through it done first, the last within its token's time (one
|
|
183
|
+
* prepared just before the stop taking as long as a restore takes to its resume, then as long
|
|
184
|
+
* as it takes to read its sandbox whole), then the checkpoints, prepares and copies it runs
|
|
185
|
+
* (OPERATION_LIMIT_SECONDS).
|
|
186
|
+
*/
|
|
187
|
+
export function nodeAgentStopSeconds(memoryBytes) {
|
|
188
|
+
return RESTORE_PREPARED_FOR_SECONDS + backgroundReadSeconds(memoryBytes) + OPERATION_LIMIT_SECONDS;
|
|
189
|
+
}
|
|
74
190
|
//# sourceMappingURL=names.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../../../src/node-agent/names.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qEAAqE;AACrE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,8BAA8B,CAAC;AAE9D,qDAAqD;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,GAAG,eAAe,IAAI,OAAO,EAAE,CAAC;AAE5F,wEAAwE;AACxE,MAAM,CAAC,MAAM,UAAU,GAAG,2CAA2C,CAAC;AAEtE,0IAA0I;AAC1I,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAErF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,SAAS,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;AAE1F,2GAA2G;AAC3G,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,UAAU,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;AAEhG,qGAAqG;AACrG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,WAAW,OAAO,EAAE,CAAC;AAE9E,kGAAkG;AAClG,MAAM,CAAC,MAAM,UAAU,GAAG,8BAA8B,CAAC;AAEzD,oHAAoH;AACpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AAQrD,uIAAuI;AACvI,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;AAElD,6HAA6H;AAC7H,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,0FAA0F;AAC1F,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;AAEpF;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC;AAEpD,kGAAkG;AAClG,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAAoB,GAAG,uBAAuB,CAAC;AAEtF,
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../../../src/node-agent/names.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Naming for session filesystems. A workspace is one of two kinds (see
|
|
3
3
|
* ../workspace/kind.ts): a folder, or a session filesystem identified by a volume id.
|
|
4
|
-
* A volume id is what alasio generates and stores, and its session's
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
import { Schema } from "effect";
|
|
8
|
-
/**
|
|
9
|
-
* The longest a volume id is: a DNS label's 63 characters, less a claim template's name
|
|
10
|
-
* of up to CLAIM_TEMPLATE_MAX and the hyphen after it, so its volume claims' names,
|
|
11
|
-
* `<template>-<id>` (../kube/sandboxes.ts claimName), are DNS labels too, as alasio's
|
|
12
|
-
* admission policy of its clones holds them to (cli/src/manifests/admission.ts).
|
|
4
|
+
* A volume id is what alasio generates and stores, and its session's workspace, which the
|
|
5
|
+
* sandbox gateway holds, is named for it (sessionKey).
|
|
13
6
|
*/
|
|
7
|
+
/** The longest a volume id is: a DNS label's 63 characters, with room to spare, as the ids alasio has stored are. */
|
|
14
8
|
export const VOLUME_ID_MAX = 58;
|
|
15
|
-
/** The longest a claim template's name is, of which a volume id's claims are named. */
|
|
16
|
-
export const CLAIM_TEMPLATE_MAX = 63 - 1 - VOLUME_ID_MAX;
|
|
17
9
|
/**
|
|
18
10
|
* A volume id is a DNS label of 3–58 characters from `[a-z0-9-]` that starts and ends
|
|
19
|
-
* with a letter or digit, as the names of
|
|
20
|
-
*
|
|
11
|
+
* with a letter or digit, as the names of what is made of it must be, a workspace's
|
|
12
|
+
* directory among them, of VOLUME_ID_MAX at most. alasio generates ids that already
|
|
21
13
|
* satisfy this, and this guards against any that would not.
|
|
22
14
|
*/
|
|
23
15
|
const VOLUME_ID_PATTERN = new RegExp(`^[a-z0-9][a-z0-9-]{1,${VOLUME_ID_MAX - 2}}[a-z0-9]$`, "u");
|
|
24
|
-
/** A volume id, as what comes from outside alasio is decoded. */
|
|
25
|
-
const VolumeId = Schema.String.check(Schema.isPattern(VOLUME_ID_PATTERN));
|
|
26
|
-
/**
|
|
27
|
-
* A session's token, `<volumeId>.<random>` (../kube/sandboxes.ts newToken), decoded into
|
|
28
|
-
* the session it names and the rest.
|
|
29
|
-
*/
|
|
30
|
-
export const SessionToken = Schema.TemplateLiteralParser([VolumeId, ".", Schema.NonEmptyString]);
|
|
31
16
|
export function isValidVolumeId(volumeId) {
|
|
32
17
|
return typeof volumeId === "string" && VOLUME_ID_PATTERN.test(volumeId);
|
|
33
18
|
}
|
|
@@ -41,4 +26,11 @@ export function assertValidVolumeId(volumeId) {
|
|
|
41
26
|
export function newVolumeId(random = () => crypto.randomUUID()) {
|
|
42
27
|
return `fs-${random().replace(/-/g, "").slice(0, 12)}`;
|
|
43
28
|
}
|
|
29
|
+
/** The key a session filesystem's workspace is bound by in the sandbox service: `sessionfs:<volumeId>`. */
|
|
30
|
+
export const sessionKey = (volumeId) => `sessionfs:${volumeId}`;
|
|
31
|
+
/** The volume id of the session filesystem `key` binds, where it binds one; else null. */
|
|
32
|
+
export function volumeIdOfKey(key) {
|
|
33
|
+
const volumeId = key.startsWith("sessionfs:") ? key.slice("sessionfs:".length) : "";
|
|
34
|
+
return isValidVolumeId(volumeId) ? volumeId : null;
|
|
35
|
+
}
|
|
44
36
|
//# sourceMappingURL=names.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../../../src/sandbox/names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../../../src/sandbox/names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qHAAqH;AACrH,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG,IAAI,MAAM,CAAC,wBAAwB,aAAa,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;AAEjG,MAAM,UAAU,eAAe,CAAC,QAAiB;IAC/C,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAiB;IACnD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,aAAa,kEAAkE,CAAC,CAAC;IACrK,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,WAAW,CAAC,MAAM,GAAiB,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE;IAC1E,OAAO,MAAM,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,2GAA2G;AAC3G,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAgB,EAAU,EAAE,CAAC,aAAa,QAAQ,EAAE,CAAC;AAEhF,0FAA0F;AAC1F,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpF,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
const RESOURCE_LISTS = {
|
|
2
|
+
traces: ["resourceSpans", "scopeSpans"],
|
|
3
|
+
metrics: ["resourceMetrics", "scopeMetrics"],
|
|
4
|
+
logs: ["resourceLogs", "scopeLogs"],
|
|
5
|
+
};
|
|
6
|
+
/** Thrown for a request that does not parse as one, which is then not exported. */
|
|
7
|
+
export class MalformedRequest extends Error {
|
|
8
|
+
name = "MalformedRequest";
|
|
9
|
+
}
|
|
10
|
+
function isStamped(key, stamp) {
|
|
11
|
+
return Object.hasOwn(stamp, key) || key.startsWith("alasio.");
|
|
12
|
+
}
|
|
13
|
+
// --- Binary protobuf ----------------------------------------------------------
|
|
14
|
+
// The levels the resource is at, by field number, the same for all three signals:
|
|
15
|
+
// Export{Trace,Metrics,Logs}ServiceRequest 1: repeated Resource{Spans,Metrics,Logs}
|
|
16
|
+
// Resource{Spans,Metrics,Logs} 1: Resource
|
|
17
|
+
// Resource 1: repeated KeyValue attributes
|
|
18
|
+
// KeyValue 1: string key, 2: AnyValue value
|
|
19
|
+
// AnyValue 1: string string_value
|
|
20
|
+
const VARINT = 0;
|
|
21
|
+
const FIXED64 = 1;
|
|
22
|
+
const LEN = 2;
|
|
23
|
+
const FIXED32 = 5;
|
|
24
|
+
function readVarint(buf, at) {
|
|
25
|
+
let value = 0;
|
|
26
|
+
for (let shift = 0; shift < 64; shift += 7) {
|
|
27
|
+
const byte = buf[at++];
|
|
28
|
+
if (byte === undefined)
|
|
29
|
+
throw new MalformedRequest("truncated varint");
|
|
30
|
+
value += (byte & 0x7f) * 2 ** shift;
|
|
31
|
+
if ((byte & 0x80) === 0)
|
|
32
|
+
return [value, at];
|
|
33
|
+
}
|
|
34
|
+
throw new MalformedRequest("overlong varint");
|
|
35
|
+
}
|
|
36
|
+
/** Each field of a message: its number, wire type, whole encoding, and value. */
|
|
37
|
+
function* fields(buf) {
|
|
38
|
+
let at = 0;
|
|
39
|
+
while (at < buf.length) {
|
|
40
|
+
const start = at;
|
|
41
|
+
let tag;
|
|
42
|
+
[tag, at] = readVarint(buf, at);
|
|
43
|
+
const field = Math.floor(tag / 8);
|
|
44
|
+
const wire = tag % 8;
|
|
45
|
+
if (field === 0)
|
|
46
|
+
throw new MalformedRequest("field number 0");
|
|
47
|
+
let valueStart = at;
|
|
48
|
+
if (wire === VARINT)
|
|
49
|
+
[, at] = readVarint(buf, at);
|
|
50
|
+
else if (wire === FIXED64)
|
|
51
|
+
at += 8;
|
|
52
|
+
else if (wire === FIXED32)
|
|
53
|
+
at += 4;
|
|
54
|
+
else if (wire === LEN) {
|
|
55
|
+
let length;
|
|
56
|
+
[length, valueStart] = readVarint(buf, at);
|
|
57
|
+
at = valueStart + length;
|
|
58
|
+
}
|
|
59
|
+
else
|
|
60
|
+
throw new MalformedRequest(`wire type ${wire}`);
|
|
61
|
+
if (at > buf.length)
|
|
62
|
+
throw new MalformedRequest("truncated field");
|
|
63
|
+
yield { field, wire, whole: buf.subarray(start, at), value: buf.subarray(valueStart, at) };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** A message field's value, which must be length-delimited. */
|
|
67
|
+
function message({ field, wire, value }) {
|
|
68
|
+
if (wire !== LEN)
|
|
69
|
+
throw new MalformedRequest(`field ${field} has wire type ${wire}`);
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
function varint(value) {
|
|
73
|
+
const bytes = [];
|
|
74
|
+
for (; value >= 0x80; value = Math.floor(value / 128))
|
|
75
|
+
bytes.push((value % 128) | 0x80);
|
|
76
|
+
bytes.push(value);
|
|
77
|
+
return Buffer.from(bytes);
|
|
78
|
+
}
|
|
79
|
+
function lengthDelimited(field, bytes) {
|
|
80
|
+
return Buffer.concat([varint(field * 8 + LEN), varint(bytes.length), bytes]);
|
|
81
|
+
}
|
|
82
|
+
/** A KeyValue's key, the last given as protobuf merges them, or "" for none. */
|
|
83
|
+
function keyOf(keyValue) {
|
|
84
|
+
let key = "";
|
|
85
|
+
for (const field of fields(keyValue)) {
|
|
86
|
+
if (field.field === 1)
|
|
87
|
+
key = message(field).toString("utf8");
|
|
88
|
+
}
|
|
89
|
+
return key;
|
|
90
|
+
}
|
|
91
|
+
function stampedAttributesProtobuf(stamp) {
|
|
92
|
+
return Object.entries(stamp).map(([key, value]) => lengthDelimited(1, Buffer.concat([
|
|
93
|
+
lengthDelimited(1, Buffer.from(key, "utf8")),
|
|
94
|
+
lengthDelimited(2, lengthDelimited(1, Buffer.from(value, "utf8"))),
|
|
95
|
+
])));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* A Resource{Spans,Metrics,Logs} with one Resource: every Resource it held merged as
|
|
99
|
+
* protobuf merges repeated occurrences, less the stamped attributes, plus the stamp.
|
|
100
|
+
*/
|
|
101
|
+
function stampResourcePart(part, stamp) {
|
|
102
|
+
const resource = [];
|
|
103
|
+
const rest = [];
|
|
104
|
+
for (const field of fields(part)) {
|
|
105
|
+
if (field.field !== 1) {
|
|
106
|
+
rest.push(field.whole);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
for (const resourceField of fields(message(field))) {
|
|
110
|
+
if (resourceField.field === 1 && isStamped(keyOf(message(resourceField)), stamp))
|
|
111
|
+
continue;
|
|
112
|
+
resource.push(resourceField.whole);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return Buffer.concat([lengthDelimited(1, Buffer.concat([...resource, ...stampedAttributesProtobuf(stamp)])), ...rest]);
|
|
116
|
+
}
|
|
117
|
+
function stampProtobuf(body, stamp) {
|
|
118
|
+
return Buffer.concat([...fields(body)].map((field) => field.field === 1 ? lengthDelimited(1, stampResourcePart(message(field), stamp)) : field.whole));
|
|
119
|
+
}
|
|
120
|
+
// --- JSON ---------------------------------------------------------------------
|
|
121
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
122
|
+
function list(value, what) {
|
|
123
|
+
if (value === undefined)
|
|
124
|
+
return [];
|
|
125
|
+
if (!Array.isArray(value))
|
|
126
|
+
throw new MalformedRequest(`${what} is not a list`);
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
function object(value, what) {
|
|
130
|
+
if (value === undefined)
|
|
131
|
+
return {};
|
|
132
|
+
if (!isObject(value))
|
|
133
|
+
throw new MalformedRequest(`${what} is not an object`);
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
/** The fields of `source` named by `names` that it has. */
|
|
137
|
+
function only(source, names) {
|
|
138
|
+
return Object.fromEntries(names.filter((name) => source[name] !== undefined).map((name) => [name, source[name]]));
|
|
139
|
+
}
|
|
140
|
+
function stampJson(signal, body, stamp) {
|
|
141
|
+
let request;
|
|
142
|
+
try {
|
|
143
|
+
request = JSON.parse(body.toString("utf8"));
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
throw new MalformedRequest(error instanceof Error ? error.message : String(error));
|
|
147
|
+
}
|
|
148
|
+
const [partsName, scopesName] = RESOURCE_LISTS[signal];
|
|
149
|
+
const parts = list(object(request, "the request")[partsName], partsName).map((value) => {
|
|
150
|
+
const part = object(value, partsName);
|
|
151
|
+
const resource = object(part["resource"], "resource");
|
|
152
|
+
const attributes = list(resource["attributes"], "resource.attributes")
|
|
153
|
+
.filter((attribute) => !(isObject(attribute) && typeof attribute["key"] === "string" && isStamped(attribute["key"], stamp)));
|
|
154
|
+
return {
|
|
155
|
+
resource: {
|
|
156
|
+
...only(resource, ["droppedAttributesCount", "entityRefs"]),
|
|
157
|
+
attributes: [...attributes, ...Object.entries(stamp).map(([key, value]) => ({ key, value: { stringValue: value } }))],
|
|
158
|
+
},
|
|
159
|
+
...only(part, [scopesName, "schemaUrl"]),
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
return Buffer.from(JSON.stringify({ [partsName]: parts }), "utf8");
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* `body`, an OTLP export request for `signal` in `encoding` ("protobuf" or "json"),
|
|
166
|
+
* with its resources stamped. Throws MalformedRequest for one that does not parse.
|
|
167
|
+
*/
|
|
168
|
+
export function stampResources(signal, encoding, body, stamp) {
|
|
169
|
+
if (!Object.hasOwn(RESOURCE_LISTS, signal))
|
|
170
|
+
throw new Error(`unknown signal ${signal}`);
|
|
171
|
+
return encoding === "json" ? stampJson(signal, body, stamp) : stampProtobuf(body, stamp);
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=otlp-resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otlp-resource.js","sourceRoot":"","sources":["../../../../src/sandbox/otlp-resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What bayma inside a session's sandbox exports its telemetry with, and what is stamped on
|
|
3
|
+
* it. A pool's pod's one way out without internet is the sandbox service's receiver
|
|
4
|
+
* (../receiver/receiver.ts), so its bayma exports there, with its binding's token, each signal
|
|
5
|
+
* the sandbox gateway exports, as the gateway tells the node agent attaching the workspace
|
|
6
|
+
* (../gateway/sessions.ts); the receiver stamps what arrives with what is known of the session
|
|
7
|
+
* and exports it where the stack's telemetry goes.
|
|
8
|
+
*/
|
|
9
|
+
import { parseKeyValueList, resolveTelemetry, sharedResourceAttributes, SIGNALS, telemetryEnabled } from "../telemetry/config.js";
|
|
10
|
+
/**
|
|
11
|
+
* The standard variables bayma inside a sandbox exports with, but for the endpoint and the
|
|
12
|
+
* token it sends, which are the sandbox's own: each signal `env`, the gateway's, exports, in
|
|
13
|
+
* the protocol it exports it in, and no other. Empty where it exports nothing.
|
|
14
|
+
*/
|
|
15
|
+
export function sandboxBaymaTelemetryEnv(env = process.env) {
|
|
16
|
+
const telemetry = resolveTelemetry(env);
|
|
17
|
+
if (!telemetryEnabled(telemetry))
|
|
18
|
+
return {};
|
|
19
|
+
const settings = {};
|
|
20
|
+
for (const signal of SIGNALS) {
|
|
21
|
+
const upper = signal.toUpperCase();
|
|
22
|
+
const exporter = telemetry[signal];
|
|
23
|
+
settings[`OTEL_${upper}_EXPORTER`] = exporter ? "otlp" : "none";
|
|
24
|
+
if (exporter)
|
|
25
|
+
settings[`OTEL_EXPORTER_OTLP_${upper}_PROTOCOL`] = exporter.protocol;
|
|
26
|
+
}
|
|
27
|
+
return settings;
|
|
28
|
+
}
|
|
29
|
+
/** The resource attributes a session's telemetry is stamped with. */
|
|
30
|
+
export function sandboxResource(volumeId, env = process.env) {
|
|
31
|
+
return { ...parseKeyValueList(sharedResourceAttributes(env)), "service.name": "bayma", "alasio.volume.id": volumeId };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What a folder conversation's instance's telemetry is stamped with: bayma's, of the
|
|
35
|
+
* conversation, as alasio's own of the conversation is, and the harness it is under.
|
|
36
|
+
*/
|
|
37
|
+
export const folderResource = (harness, conversation, env = process.env) => ({
|
|
38
|
+
...parseKeyValueList(sharedResourceAttributes(env)),
|
|
39
|
+
"service.name": "bayma",
|
|
40
|
+
"alasio.conversation.id": conversation,
|
|
41
|
+
"alasio.harness": harness,
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../../../src/sandbox/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAGlI;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAG,GAAgC,OAAO,CAAC,GAAG;IACrF,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAC5C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QACnC,QAAQ,CAAC,QAAQ,KAAK,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAChE,IAAI,QAAQ;YAAE,QAAQ,CAAC,sBAAsB,KAAK,WAAW,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC;IACrF,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,GAAG,GAAgC,OAAO,CAAC,GAAG;IAC9F,OAAO,EAAE,GAAG,iBAAiB,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CAAC;AACxH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,YAAoB,EAAE,GAAG,GAAgC,OAAO,CAAC,GAAG,EAAiB,EAAE,CAAC,CAAC;IACvI,GAAG,iBAAiB,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IACnD,cAAc,EAAE,OAAO;IACvB,wBAAwB,EAAE,YAAY;IACtC,gBAAgB,EAAE,OAAO;CAC1B,CAAC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How Telegram's deliveries of a bot's updates to the webhook intake fare, as the bot's
|
|
3
|
+
* getWebhookInfo says, which is where alone Telegram says a delivery failed: alike for
|
|
4
|
+
* alasio, which watches its own bot's (./delivery-watch.ts), and for alasio status, which
|
|
5
|
+
* says each environment's. Free of anything but the language's own, so the command line
|
|
6
|
+
* takes it without the server.
|
|
7
|
+
*/
|
|
8
|
+
/** How long a failed delivery is a failure now, as Telegram keeps its last error after it delivers again. */
|
|
9
|
+
const LATELY_SECONDS = 600;
|
|
10
|
+
/**
|
|
11
|
+
* Telegram's errors that say it could not connect to the intake at all, as where the
|
|
12
|
+
* networks it delivers from are not among install.webhook.sources, which the intake's
|
|
13
|
+
* NetworkPolicy and a LoadBalancer admit alone: the connection is dropped, and times out,
|
|
14
|
+
* or refused.
|
|
15
|
+
*/
|
|
16
|
+
const UNREACHABLE = /^(Connection timed out|Connection refused|No route to host|Network is unreachable)\b/u;
|
|
17
|
+
/** Telegram's error that says the name it is told to deliver to resolves to no address. */
|
|
18
|
+
const UNRESOLVED = /^Failed to resolve host\b/u;
|
|
19
|
+
/** The fix Telegram's error `error` points to, null where it points to none. */
|
|
20
|
+
function fixOf(error) {
|
|
21
|
+
if (UNREACHABLE.test(error)) {
|
|
22
|
+
return "Telegram cannot connect to it, as where its networks have changed from those install.webhook.sources lists: list Telegram's (core.telegram.org/bots/webhooks) there, and alasio up admits them";
|
|
23
|
+
}
|
|
24
|
+
if (UNRESOLVED.test(error))
|
|
25
|
+
return "Telegram cannot resolve install.webhook.publicAddress: give the name an address, or set the address itself, and alasio up registers each bot with it";
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether `deliveries` fail at `now` (milliseconds): updates wait, and Telegram's last
|
|
30
|
+
* delivery failed lately; null where they do not, as where nothing waits, every update
|
|
31
|
+
* delivered since.
|
|
32
|
+
*/
|
|
33
|
+
export function failingDeliveries(deliveries, now) {
|
|
34
|
+
const { pending_update_count: pending, last_error_date: date, last_error_message: error = "no reason given" } = deliveries;
|
|
35
|
+
if (pending === 0 || date === undefined || now / 1000 - date >= LATELY_SECONDS)
|
|
36
|
+
return null;
|
|
37
|
+
const at = new Date(date * 1000).toISOString().replace(/\.\d{3}Z$/u, "Z");
|
|
38
|
+
return { description: `${pending} update${pending === 1 ? "" : "s"} waiting; Telegram's last delivery failed at ${at}: ${error}`, fix: fixOf(error) };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=deliveries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliveries.js","sourceRoot":"","sources":["../../../../src/telegram/deliveries.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,6GAA6G;AAC7G,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,WAAW,GAAG,uFAAuF,CAAC;AAE5G,2FAA2F;AAC3F,MAAM,UAAU,GAAG,4BAA4B,CAAC;AAEhD,gFAAgF;AAChF,SAAS,KAAK,CAAC,KAAa;IAC1B,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,gMAAgM,CAAC;IAC1M,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,sJAAsJ,CAAC;IAC1L,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAsB,EAAE,GAAW;IACnE,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,GAAG,iBAAiB,EAAE,GAAG,UAAU,CAAC;IAC3H,IAAI,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,SAAS,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,cAAc;QAAE,OAAO,IAAI,CAAC;IAC5F,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IAC1E,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,gDAAgD,EAAE,KAAK,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AACxJ,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which of alasio's signals are exported, and where, decided from the standard
|
|
3
|
+
* OpenTelemetry environment variables alone, so any OTLP backend works and none is
|
|
4
|
+
* assumed.
|
|
5
|
+
*
|
|
6
|
+
* A signal is exported when it has an endpoint, its own
|
|
7
|
+
* (`OTEL_EXPORTER_OTLP_<SIGNAL>_ENDPOINT`) or the shared one
|
|
8
|
+
* (`OTEL_EXPORTER_OTLP_ENDPOINT`), and `OTEL_<SIGNAL>_EXPORTER` is unset or `otlp`;
|
|
9
|
+
* `OTEL_SDK_DISABLED=true` turns every signal off. With no endpoint at all alasio
|
|
10
|
+
* exports nothing and loads no SDK.
|
|
11
|
+
*/
|
|
12
|
+
export const SIGNALS = ["traces", "metrics", "logs"];
|
|
13
|
+
const DEFAULT_PROTOCOL = "http/protobuf";
|
|
14
|
+
/** Variables that configure telemetry, which alasio hands no child as it is. */
|
|
15
|
+
const TELEMETRY_VARIABLE = /^(OTEL_.*|TRACEPARENT|TRACESTATE)$/u;
|
|
16
|
+
function setting(env, name) {
|
|
17
|
+
return env[name]?.trim() || null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The OTLP endpoint a signal is sent to: its own as given, else the shared one, to
|
|
21
|
+
* which OTLP over HTTP adds the signal's path and OTLP over gRPC adds nothing.
|
|
22
|
+
*/
|
|
23
|
+
function signalEndpoint(env, signal, protocol) {
|
|
24
|
+
const own = setting(env, `OTEL_EXPORTER_OTLP_${signal.toUpperCase()}_ENDPOINT`);
|
|
25
|
+
if (own)
|
|
26
|
+
return own;
|
|
27
|
+
const shared = setting(env, "OTEL_EXPORTER_OTLP_ENDPOINT");
|
|
28
|
+
if (!shared || protocol === "grpc")
|
|
29
|
+
return shared;
|
|
30
|
+
return `${shared.replace(/\/+$/u, "")}/v1/${signal}`;
|
|
31
|
+
}
|
|
32
|
+
/** How `signal` is exported, or null when it is not. */
|
|
33
|
+
function signalExporter(env, signal, disabled) {
|
|
34
|
+
const upper = signal.toUpperCase();
|
|
35
|
+
const exporter = setting(env, `OTEL_${upper}_EXPORTER`) ?? "otlp";
|
|
36
|
+
const protocol = setting(env, `OTEL_EXPORTER_OTLP_${upper}_PROTOCOL`)
|
|
37
|
+
?? setting(env, "OTEL_EXPORTER_OTLP_PROTOCOL")
|
|
38
|
+
?? DEFAULT_PROTOCOL;
|
|
39
|
+
const endpoint = signalEndpoint(env, signal, protocol);
|
|
40
|
+
if (disabled || exporter !== "otlp" || !endpoint) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return { endpoint, protocol, headers: signalHeaders(env, signal) };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `{ traces, metrics, logs }`, each `{ endpoint, protocol, headers }` for a signal
|
|
47
|
+
* alasio exports or null for one it does not. `headers` is the standard
|
|
48
|
+
* `key=value,key=value` list, or null.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveTelemetry(env = process.env) {
|
|
51
|
+
const disabled = setting(env, "OTEL_SDK_DISABLED")?.toLowerCase() === "true";
|
|
52
|
+
return {
|
|
53
|
+
traces: signalExporter(env, "traces", disabled),
|
|
54
|
+
metrics: signalExporter(env, "metrics", disabled),
|
|
55
|
+
logs: signalExporter(env, "logs", disabled),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A signal's OTLP exporter setting `name` (HEADERS, TIMEOUT, ...): its own
|
|
60
|
+
* (`OTEL_EXPORTER_OTLP_<SIGNAL>_<NAME>`), else the shared one, or null.
|
|
61
|
+
*/
|
|
62
|
+
export function signalSetting(env, signal, name) {
|
|
63
|
+
return setting(env, `OTEL_EXPORTER_OTLP_${signal.toUpperCase()}_${name}`) ?? setting(env, `OTEL_EXPORTER_OTLP_${name}`);
|
|
64
|
+
}
|
|
65
|
+
/** The headers a signal is sent with: its own, else the shared ones, or null. */
|
|
66
|
+
export function signalHeaders(env, signal) {
|
|
67
|
+
return signalSetting(env, signal, "HEADERS");
|
|
68
|
+
}
|
|
69
|
+
/** Whether any signal is exported. */
|
|
70
|
+
export function telemetryEnabled(telemetry) {
|
|
71
|
+
return SIGNALS.some((signal) => telemetry[signal]);
|
|
72
|
+
}
|
|
73
|
+
/** An environment without the variables that configure telemetry. */
|
|
74
|
+
export function withoutTelemetry(env) {
|
|
75
|
+
return Object.fromEntries(Object.entries(env).filter(([name]) => !TELEMETRY_VARIABLE.test(name)));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The resource attributes a harness exporting telemetry of its own shares with alasio:
|
|
79
|
+
* the operator's `OTEL_RESOURCE_ATTRIBUTES`, which describe the deployment, without
|
|
80
|
+
* `service.name`, which is alasio's. The standard `key=value,key=value` list, or null.
|
|
81
|
+
*/
|
|
82
|
+
export function sharedResourceAttributes(env = process.env) {
|
|
83
|
+
const shared = (setting(env, "OTEL_RESOURCE_ATTRIBUTES") ?? "")
|
|
84
|
+
.split(",")
|
|
85
|
+
.filter((pair) => pair.trim() && pair.split("=")[0]?.trim() !== "service.name");
|
|
86
|
+
return shared.length ? shared.join(",") : null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The standard variables that have a process serving one conversation, Claude Code
|
|
90
|
+
* or bayma, export each signal alasio exports where alasio exports it, and no other:
|
|
91
|
+
* each exported signal's exporter, endpoint, protocol, and headers, every other
|
|
92
|
+
* signal's exporter none, and the deployment's resource attributes with the
|
|
93
|
+
* conversation's. Nothing when alasio exports nothing.
|
|
94
|
+
*/
|
|
95
|
+
export function conversationTelemetryEnv({ conversationId }, env = process.env) {
|
|
96
|
+
const telemetry = resolveTelemetry(env);
|
|
97
|
+
if (!telemetryEnabled(telemetry))
|
|
98
|
+
return {};
|
|
99
|
+
const settings = {
|
|
100
|
+
OTEL_RESOURCE_ATTRIBUTES: [sharedResourceAttributes(env), `alasio.conversation.id=${encodeURIComponent(conversationId)}`]
|
|
101
|
+
.filter(Boolean)
|
|
102
|
+
.join(","),
|
|
103
|
+
};
|
|
104
|
+
for (const signal of SIGNALS) {
|
|
105
|
+
const upper = signal.toUpperCase();
|
|
106
|
+
const exporter = telemetry[signal];
|
|
107
|
+
settings[`OTEL_${upper}_EXPORTER`] = exporter ? "otlp" : "none";
|
|
108
|
+
if (!exporter)
|
|
109
|
+
continue;
|
|
110
|
+
settings[`OTEL_EXPORTER_OTLP_${upper}_ENDPOINT`] = exporter.endpoint;
|
|
111
|
+
settings[`OTEL_EXPORTER_OTLP_${upper}_PROTOCOL`] = exporter.protocol;
|
|
112
|
+
if (exporter.headers)
|
|
113
|
+
settings[`OTEL_EXPORTER_OTLP_${upper}_HEADERS`] = exporter.headers;
|
|
114
|
+
}
|
|
115
|
+
return settings;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* A standard `key=value,key=value` list, such as OTLP headers or resource attributes, as
|
|
119
|
+
* an object, values URL-decoded.
|
|
120
|
+
*/
|
|
121
|
+
export function parseKeyValueList(list) {
|
|
122
|
+
if (!list)
|
|
123
|
+
return {};
|
|
124
|
+
return Object.fromEntries(list.split(",").flatMap((pair) => {
|
|
125
|
+
const at = pair.indexOf("=");
|
|
126
|
+
if (at <= 0)
|
|
127
|
+
return [];
|
|
128
|
+
return [[pair.slice(0, at).trim(), decodeURIComponent(pair.slice(at + 1).trim())]];
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=config.js.map
|