agentfootprint 11.1.0 → 11.2.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/CAPABILITIES.md +1 -0
- package/dist/adapters/mcp/agentcoreRuntime/sessionBusy.js +35 -4
- package/dist/adapters/mcp/agentcoreRuntime/sessionBusy.js.map +1 -1
- package/dist/adapters/mcp/agentcoreRuntime/transport.js +48 -22
- package/dist/adapters/mcp/agentcoreRuntime/transport.js.map +1 -1
- package/dist/adapters/observability/cloudwatch.js +101 -110
- package/dist/adapters/observability/cloudwatch.js.map +1 -1
- package/dist/adapters/observability/file.js +48 -71
- package/dist/adapters/observability/file.js.map +1 -1
- package/dist/adapters/observability/outbox.js +217 -0
- package/dist/adapters/observability/outbox.js.map +1 -0
- package/dist/adapters/observability/xray.js +56 -70
- package/dist/adapters/observability/xray.js.map +1 -1
- package/dist/core/RunnerBase.js +20 -1
- package/dist/core/RunnerBase.js.map +1 -1
- package/dist/esm/adapters/mcp/agentcoreRuntime/sessionBusy.d.ts +6 -2
- package/dist/esm/adapters/mcp/agentcoreRuntime/sessionBusy.js +35 -4
- package/dist/esm/adapters/mcp/agentcoreRuntime/sessionBusy.js.map +1 -1
- package/dist/esm/adapters/mcp/agentcoreRuntime/transport.d.ts +38 -12
- package/dist/esm/adapters/mcp/agentcoreRuntime/transport.js +47 -21
- package/dist/esm/adapters/mcp/agentcoreRuntime/transport.js.map +1 -1
- package/dist/esm/adapters/observability/cloudwatch.d.ts +6 -2
- package/dist/esm/adapters/observability/cloudwatch.js +101 -110
- package/dist/esm/adapters/observability/cloudwatch.js.map +1 -1
- package/dist/esm/adapters/observability/file.d.ts +8 -4
- package/dist/esm/adapters/observability/file.js +48 -71
- package/dist/esm/adapters/observability/file.js.map +1 -1
- package/dist/esm/adapters/observability/outbox.d.ts +104 -0
- package/dist/esm/adapters/observability/outbox.js +213 -0
- package/dist/esm/adapters/observability/outbox.js.map +1 -0
- package/dist/esm/adapters/observability/xray.js +56 -70
- package/dist/esm/adapters/observability/xray.js.map +1 -1
- package/dist/esm/core/RunnerBase.d.ts +18 -0
- package/dist/esm/core/RunnerBase.js +20 -1
- package/dist/esm/core/RunnerBase.js.map +1 -1
- package/dist/esm/core/runner.d.ts +1 -0
- package/dist/esm/lib/longTimeout.d.ts +34 -0
- package/dist/esm/lib/longTimeout.js +56 -0
- package/dist/esm/lib/longTimeout.js.map +1 -0
- package/dist/esm/lib/sleep.d.ts +2 -0
- package/dist/esm/lib/sleep.js +2 -0
- package/dist/esm/lib/sleep.js.map +1 -1
- package/dist/esm/mcp/backoff.d.ts +81 -0
- package/dist/esm/mcp/backoff.js +158 -0
- package/dist/esm/mcp/backoff.js.map +1 -0
- package/dist/esm/mcp/mcpClient.js +3 -1
- package/dist/esm/mcp/mcpClient.js.map +1 -1
- package/dist/esm/mcp/throttleRetry.d.ts +198 -28
- package/dist/esm/mcp/throttleRetry.js +428 -83
- package/dist/esm/mcp/throttleRetry.js.map +1 -1
- package/dist/esm/mcp/types.d.ts +16 -7
- package/dist/esm/strategies/attach.js +3 -0
- package/dist/esm/strategies/attach.js.map +1 -1
- package/dist/esm/strategies/flushDeadline.d.ts +47 -0
- package/dist/esm/strategies/flushDeadline.js +96 -0
- package/dist/esm/strategies/flushDeadline.js.map +1 -0
- package/dist/lib/longTimeout.js +60 -0
- package/dist/lib/longTimeout.js.map +1 -0
- package/dist/lib/sleep.js +2 -0
- package/dist/lib/sleep.js.map +1 -1
- package/dist/mcp/backoff.js +163 -0
- package/dist/mcp/backoff.js.map +1 -0
- package/dist/mcp/mcpClient.js +3 -1
- package/dist/mcp/mcpClient.js.map +1 -1
- package/dist/mcp/throttleRetry.js +432 -85
- package/dist/mcp/throttleRetry.js.map +1 -1
- package/dist/strategies/attach.js +3 -0
- package/dist/strategies/attach.js.map +1 -1
- package/dist/strategies/flushDeadline.js +102 -0
- package/dist/strategies/flushDeadline.js.map +1 -0
- package/dist/types/adapters/mcp/agentcoreRuntime/sessionBusy.d.ts +6 -2
- package/dist/types/adapters/mcp/agentcoreRuntime/sessionBusy.d.ts.map +1 -1
- package/dist/types/adapters/mcp/agentcoreRuntime/transport.d.ts +38 -12
- package/dist/types/adapters/mcp/agentcoreRuntime/transport.d.ts.map +1 -1
- package/dist/types/adapters/observability/cloudwatch.d.ts +6 -2
- package/dist/types/adapters/observability/cloudwatch.d.ts.map +1 -1
- package/dist/types/adapters/observability/file.d.ts +8 -4
- package/dist/types/adapters/observability/file.d.ts.map +1 -1
- package/dist/types/adapters/observability/outbox.d.ts +105 -0
- package/dist/types/adapters/observability/outbox.d.ts.map +1 -0
- package/dist/types/adapters/observability/xray.d.ts.map +1 -1
- package/dist/types/core/RunnerBase.d.ts +18 -0
- package/dist/types/core/RunnerBase.d.ts.map +1 -1
- package/dist/types/core/runner.d.ts +1 -0
- package/dist/types/core/runner.d.ts.map +1 -1
- package/dist/types/lib/longTimeout.d.ts +35 -0
- package/dist/types/lib/longTimeout.d.ts.map +1 -0
- package/dist/types/lib/sleep.d.ts +2 -0
- package/dist/types/lib/sleep.d.ts.map +1 -1
- package/dist/types/mcp/backoff.d.ts +82 -0
- package/dist/types/mcp/backoff.d.ts.map +1 -0
- package/dist/types/mcp/throttleRetry.d.ts +198 -28
- package/dist/types/mcp/throttleRetry.d.ts.map +1 -1
- package/dist/types/mcp/types.d.ts +16 -7
- package/dist/types/mcp/types.d.ts.map +1 -1
- package/dist/types/strategies/attach.d.ts.map +1 -1
- package/dist/types/strategies/flushDeadline.d.ts +48 -0
- package/dist/types/strategies/flushDeadline.d.ts.map +1 -0
- package/package.json +2 -2
package/CAPABILITIES.md
CHANGED
|
@@ -20,6 +20,7 @@ not in this table, search `src/index.ts` for the nearest noun before writing cod
|
|
|
20
20
|
|
|
21
21
|
| If you are about to build… | It is | Where | Since |
|
|
22
22
|
|---|---|---|---|
|
|
23
|
+
| tuning how an MCP call waits before asking again — the first wait, how it grows, jitter, a cap on the scheduled wait, a deadline for the whole call — and keeping a 429 retry and AgentCore Runtime's session-busy retry from multiplying requests: each call is ONE footprintjs `attempt()` series, the 429 rule JOINS a transport's own series instead of wrapping it (one attempt count, one waiting total, one deadline), a `Retry-After` is waited whole (never cut by the cap), and `onRetry` reports the refusal's `kind` but never arguments or answers | `retryOnThrottle` / `agentCoreRuntimeMcpTransport({ retry })` / `retryingFetch(fetch, options)`: `baseDelayMs`, `multiplier`, `jitter` (none, equal or full), `maxDelayMs`, `maxElapsedMs` beside `maxAttempts`, `maxWaitMs`, `onRetry` (`agentfootprint/providers`); AgentCore default 500 ms doubling, 5 attempts = 3.75–7.5 s of waiting | `src/mcp/throttleRetry.ts` | 11.2.0 |
|
|
23
24
|
| refusing invalid memory list and search request sizes uniformly before backend reads or empty-result shortcuts, while keeping optional defaults, adapter upper caps and list continuation intact | `ListOptions` + `SearchOptions` | `src/memory/store/types.ts` | 10.8.1 |
|
|
24
25
|
| reading AgentCore memory with a large portable page request while obeying AWS's 100-event wire bound and keeping every continuation cursor; validating its configured page size before SDK construction; bundled hosts supplying the SDK as a public typed option, with extraction writes refused when an older serializer cannot carry them | `AgentCoreStore` + `AgentCoreStoreOptions.sdk` + `BedrockAgentCoreSdkModule` + `ListResult.cursor` (`agentfootprint/memory`) | `src/adapters/memory/agentcore.ts` | 10.8.1 |
|
|
25
26
|
| giving a tool the credential that arrived WITH the incoming request (an encrypted per-request token, a session key) — sealed per run so no copy, log or state carries it, read only by the run that carried it (its composition members included, at any depth; a resume serves the resume's request), failing closed by name when absent; strategies for bearer, API-key header and decrypt-then-read; through a host, the app seals each request's credential from its headers (`sealRequest`) and the host hands it to that request's run only — a handle returned twice refused, a sealer's throw refused in fixed words | `requestContext` + `requestCredentials` + `asBearer` / `asApiKey` / `decodedWith` + `RequestCredentialError` (`agentfootprint/security`), `run(input, { request })`; `sealRequest` + `RequestSealer` on `standingAgent` / `streamHandler` (`agentfootprint/hosting`) | `src/identity/requestCredentials.ts` | 10.5.0 |
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* ── Why asking again is safe ─────────────────────────────────────────────────
|
|
22
22
|
* The refusal is the PLATFORM's, about the session, made before the request
|
|
23
23
|
* reached the MCP server: nothing ran. That is the license a 429 holds, and the
|
|
24
|
-
* only one
|
|
24
|
+
* only one the retry series accepts (see `mcp/throttleRetry.ts` ·
|
|
25
25
|
* `RetryDecision`).
|
|
26
26
|
*
|
|
27
27
|
* ── What it must NOT match ───────────────────────────────────────────────────
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
*/
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.isSessionBusyReply = exports.sessionBusy = exports.SESSION_BUSY_CODE = void 0;
|
|
46
|
+
const abort_js_1 = require("../../../lib/abort.js");
|
|
46
47
|
const errorType_js_1 = require("./errorType.js");
|
|
47
48
|
/** The JSON-RPC error code the contract gives `RetryableConflictException`. */
|
|
48
49
|
exports.SESSION_BUSY_CODE = -32005;
|
|
@@ -62,8 +63,12 @@ const SESSION_BUSY_MESSAGE = /session operation in progress/i;
|
|
|
62
63
|
* Reads a CLONE of the body, so the response is delivered intact either way.
|
|
63
64
|
* Answers `{}` (wait the loop's own backoff, then send the same request again)
|
|
64
65
|
* or `undefined` (deliver it).
|
|
66
|
+
*
|
|
67
|
+
* `signal` is the request's: when it fires mid-read (the call's deadline, the
|
|
68
|
+
* caller's cancellation), the clone's read is cancelled and released, and this
|
|
69
|
+
* rejects with the abort — a stalled body never leaves a reader behind.
|
|
65
70
|
*/
|
|
66
|
-
async function sessionBusy(response) {
|
|
71
|
+
async function sessionBusy(response, signal) {
|
|
67
72
|
if (response.status === 409) {
|
|
68
73
|
return (0, errorType_js_1.awsErrorType)(response.headers) === SESSION_BUSY_TYPE ? {} : undefined;
|
|
69
74
|
}
|
|
@@ -73,9 +78,12 @@ async function sessionBusy(response) {
|
|
|
73
78
|
return undefined;
|
|
74
79
|
let text;
|
|
75
80
|
try {
|
|
76
|
-
text = await response
|
|
81
|
+
text = await cloneText(response, signal);
|
|
77
82
|
}
|
|
78
|
-
catch {
|
|
83
|
+
catch (error) {
|
|
84
|
+
// A stopped request is the caller's word, never "not busy": pass it on.
|
|
85
|
+
if (signal?.aborted)
|
|
86
|
+
throw error;
|
|
79
87
|
return undefined;
|
|
80
88
|
}
|
|
81
89
|
// A cheap gate before parsing: a large tool result does not contain the
|
|
@@ -107,6 +115,29 @@ function isSessionBusyReply(body) {
|
|
|
107
115
|
return (code === exports.SESSION_BUSY_CODE && typeof message === 'string' && SESSION_BUSY_MESSAGE.test(message));
|
|
108
116
|
}
|
|
109
117
|
exports.isSessionBusyReply = isSessionBusyReply;
|
|
118
|
+
/**
|
|
119
|
+
* The text of a clone of `response`'s body, read under `signal`: an abort
|
|
120
|
+
* cancels the clone's reader and releases it (`lib/abort.ts` · `bodyChunks`).
|
|
121
|
+
* Decoded as `Response.text()` decodes: UTF-8, a leading BOM dropped.
|
|
122
|
+
*/
|
|
123
|
+
async function cloneText(response, signal) {
|
|
124
|
+
const body = response.clone().body;
|
|
125
|
+
if (body === null)
|
|
126
|
+
return '';
|
|
127
|
+
const chunks = [];
|
|
128
|
+
let length = 0;
|
|
129
|
+
for await (const chunk of (0, abort_js_1.bodyChunks)(body, signal)) {
|
|
130
|
+
chunks.push(chunk);
|
|
131
|
+
length += chunk.byteLength;
|
|
132
|
+
}
|
|
133
|
+
const bytes = new Uint8Array(length);
|
|
134
|
+
let at = 0;
|
|
135
|
+
for (const chunk of chunks) {
|
|
136
|
+
bytes.set(chunk, at);
|
|
137
|
+
at += chunk.byteLength;
|
|
138
|
+
}
|
|
139
|
+
return new TextDecoder().decode(bytes);
|
|
140
|
+
}
|
|
110
141
|
/** `application/json`, with or without parameters, in any case. */
|
|
111
142
|
function isJson(contentType) {
|
|
112
143
|
if (contentType === null)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionBusy.js","sourceRoot":"","sources":["../../../../src/adapters/mcp/agentcoreRuntime/sessionBusy.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;;;
|
|
1
|
+
{"version":3,"file":"sessionBusy.js","sourceRoot":"","sources":["../../../../src/adapters/mcp/agentcoreRuntime/sessionBusy.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
* a handle the transport issues)
|
|
32
32
|
* retry (`sessionBusy.ts`) the session-busy refusal, retried with bounded
|
|
33
33
|
* backoff by the SAME loop `mcpClient` uses for a
|
|
34
|
-
* 429 (`mcp/throttleRetry.ts` · `
|
|
34
|
+
* 429 (`mcp/throttleRetry.ts` · `retryingFetchFor`,
|
|
35
|
+
* one footprintjs `attempt()` series per request)
|
|
35
36
|
* auth (`invoke.ts`) 'sigv4' through the AWS SDK's InvokeAgentRuntime,
|
|
36
37
|
* or a bearer token over the documented HTTPS
|
|
37
38
|
* endpoint — the SDK has no bearer scheme, and the
|
|
@@ -42,7 +43,12 @@
|
|
|
42
43
|
* signed (or vended) afresh, the ordering `mcp/throttleRetry.ts` requires.
|
|
43
44
|
* What the MCP client reads of a failure is rewritten from the library's own
|
|
44
45
|
* fixed sentences and safe ids (`safeAnswer.ts`), never the service's text.
|
|
45
|
-
*
|
|
46
|
+
*
|
|
47
|
+
* `mcpClient`'s own 429 retry does not wrap this fetch: the fetch is joinable
|
|
48
|
+
* (`joinableRetry`), so the 429 rule joins the transport's series INSIDE the
|
|
49
|
+
* session and the rewrite. One request is one series — one attempt count, one
|
|
50
|
+
* waiting total, one deadline — so the two retries can never multiply requests,
|
|
51
|
+
* and every attempt, a 429's included, lands in the same runtime session.
|
|
46
52
|
*
|
|
47
53
|
* ── What it does NOT do ──────────────────────────────────────────────────────
|
|
48
54
|
* Deploy or manage a runtime (a control-plane job), or host one (that is
|
|
@@ -52,15 +58,31 @@
|
|
|
52
58
|
* Pattern: Facade over three Strategies. Role: outer ring, vendor adapter.
|
|
53
59
|
*/
|
|
54
60
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
-
exports.agentCoreRuntimeUrl = exports.agentCoreRuntimeMcpTransport = void 0;
|
|
61
|
+
exports.agentCoreRuntimeUrl = exports.agentCoreRuntimeMcpTransport = exports.SESSION_BUSY_RETRY_DEFAULTS = void 0;
|
|
56
62
|
const gatewayTransport_js_1 = require("../../../mcp/gatewayTransport.js");
|
|
57
63
|
const throttleRetry_js_1 = require("../../../mcp/throttleRetry.js");
|
|
58
64
|
const invoke_js_1 = require("./invoke.js");
|
|
59
65
|
const safeAnswer_js_1 = require("./safeAnswer.js");
|
|
60
66
|
const session_js_1 = require("./session.js");
|
|
61
67
|
const sessionBusy_js_1 = require("./sessionBusy.js");
|
|
62
|
-
/**
|
|
63
|
-
|
|
68
|
+
/**
|
|
69
|
+
* The session-busy retry's defaults, chosen by their MINIMUM total wait.
|
|
70
|
+
* AgentCore can take about 2.5 s, and up to about 3.4 s, to bring a runtime
|
|
71
|
+
* session up. 500 ms doubling with equal jitter over 5 attempts waits
|
|
72
|
+
* 250 + 500 + 1000 + 2000 = 3750 ms at the shortest draw and
|
|
73
|
+
* 500 + 1000 + 2000 + 4000 = 7500 ms at the longest: the slowest start is
|
|
74
|
+
* covered on every draw, and the longest stays inside the 10 s ceiling on
|
|
75
|
+
* waiting, so the ceiling never cuts the schedule short.
|
|
76
|
+
*/
|
|
77
|
+
exports.SESSION_BUSY_RETRY_DEFAULTS = Object.freeze({
|
|
78
|
+
maxAttempts: 5,
|
|
79
|
+
maxWaitMs: 10_000,
|
|
80
|
+
maxElapsedMs: Infinity,
|
|
81
|
+
baseDelayMs: 500,
|
|
82
|
+
multiplier: 2,
|
|
83
|
+
jitter: 'equal',
|
|
84
|
+
maxDelayMs: Infinity,
|
|
85
|
+
});
|
|
64
86
|
/** What a bearer token is vended for, unless the caller names another service. */
|
|
65
87
|
const DEFAULT_BEARER_SERVICE = 'runtime';
|
|
66
88
|
/** A region is a DNS label run, nothing more — it is spliced into a hostname. */
|
|
@@ -77,12 +99,27 @@ const REGION_SHAPE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
77
99
|
function agentCoreRuntimeMcpTransport(options) {
|
|
78
100
|
const url = agentCoreRuntimeUrl(options);
|
|
79
101
|
const send = authStrategy(options, url);
|
|
80
|
-
const
|
|
102
|
+
const busy = (0, throttleRetry_js_1.retryRule)('session-busy', sessionBusy_js_1.sessionBusy, options.retry, exports.SESSION_BUSY_RETRY_DEFAULTS, 'agentCoreRuntimeMcpTransport: `retry`');
|
|
81
103
|
const session = (0, session_js_1.sessionStrategy)(options.session ?? 'per-call');
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
104
|
+
return {
|
|
105
|
+
transport: 'http',
|
|
106
|
+
url,
|
|
107
|
+
fetch: sessionedFetch(session, send, busy === undefined ? [] : [busy]),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
exports.agentCoreRuntimeMcpTransport = agentCoreRuntimeMcpTransport;
|
|
111
|
+
/**
|
|
112
|
+
* The transport's fetch: the session around ONE retry series around the auth.
|
|
113
|
+
*
|
|
114
|
+
* The session is applied ONCE per request the MCP client makes, outside the
|
|
115
|
+
* series: every attempt of one request goes to the same runtime session (a busy
|
|
116
|
+
* refusal is about THAT session coming up), and only the final answer binds
|
|
117
|
+
* anything. Joinable: a rule `retryingFetch` offers (`mcpClient`'s 429 retry) is
|
|
118
|
+
* rebuilt into this same series, inside the session and the rewrite — never
|
|
119
|
+
* wrapped around them as a second loop.
|
|
120
|
+
*/
|
|
121
|
+
function sessionedFetch(session, send, rules) {
|
|
122
|
+
const retried = (0, throttleRetry_js_1.retryingFetchFor)(send, rules);
|
|
86
123
|
const sessioned = async (input, init) => {
|
|
87
124
|
const headers = new Headers(init?.headers);
|
|
88
125
|
const step = session.request(headers, (init?.method ?? 'GET').toUpperCase());
|
|
@@ -93,9 +130,8 @@ function agentCoreRuntimeMcpTransport(options) {
|
|
|
93
130
|
// ONE rule for both auth paths, after the retry has read the original.
|
|
94
131
|
return step.settle(await (0, safeAnswer_js_1.safeAnswer)(response));
|
|
95
132
|
};
|
|
96
|
-
return
|
|
133
|
+
return (0, throttleRetry_js_1.joinableRetry)(sessioned, (rule) => sessionedFetch(session, send, [...rules, rule]));
|
|
97
134
|
}
|
|
98
|
-
exports.agentCoreRuntimeMcpTransport = agentCoreRuntimeMcpTransport;
|
|
99
135
|
/**
|
|
100
136
|
* The HTTPS endpoint of a runtime's MCP server:
|
|
101
137
|
* `https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{url-encoded ARN}/invocations`,
|
|
@@ -195,16 +231,6 @@ function injectedSdk(options) {
|
|
|
195
231
|
}
|
|
196
232
|
return sdk ?? legacy;
|
|
197
233
|
}
|
|
198
|
-
// ── The retry strategy's configuration ────────────────────────────────
|
|
199
|
-
function retryConfig(retry) {
|
|
200
|
-
if (retry === false)
|
|
201
|
-
return false;
|
|
202
|
-
const given = typeof retry === 'object' && retry !== null ? retry : {};
|
|
203
|
-
// An explicitly `undefined` field means "not set" — it must fall back to this
|
|
204
|
-
// transport's default, not erase it (and land on the loop's own default).
|
|
205
|
-
const set = Object.fromEntries(Object.entries(given).filter(([, v]) => v !== undefined));
|
|
206
|
-
return { ...DEFAULT_RETRY, ...set };
|
|
207
|
-
}
|
|
208
234
|
/**
|
|
209
235
|
* A refused value, described by SHAPE — never echoed. A mistyped `auth` can be
|
|
210
236
|
* the token itself (`auth: process.env.RUNTIME_TOKEN`), and an error message is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/adapters/mcp/agentcoreRuntime/transport.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/adapters/mcp/agentcoreRuntime/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,6 +44,23 @@ exports.cloudwatchObservability = exports._buildCloudWatchObservability = void 0
|
|
|
44
44
|
const lazyRequire_js_1 = require("../../lib/lazyRequire.js");
|
|
45
45
|
const wireJson_js_1 = require("../../lib/wireJson.js");
|
|
46
46
|
const deliveryErrors_js_1 = require("./deliveryErrors.js");
|
|
47
|
+
const outbox_js_1 = require("./outbox.js");
|
|
48
|
+
/**
|
|
49
|
+
* What ONE `PutLogEvents` request may carry — CloudWatch Logs' documented
|
|
50
|
+
* per-request limits (PutLogEvents API reference): "The maximum number of log
|
|
51
|
+
* events in a batch is 10,000", and "The maximum batch size is 1,048,576
|
|
52
|
+
* bytes. This size is calculated as the sum of all event messages in UTF-8,
|
|
53
|
+
* plus 26 bytes for each log event."
|
|
54
|
+
*
|
|
55
|
+
* These split a delivery into legal requests; they are NOT triggers.
|
|
56
|
+
* `maxBatchEvents` / `maxBatchBytes` still decide when a delivery starts,
|
|
57
|
+
* exactly as before. The split matters because puts now go one at a time
|
|
58
|
+
* (#223): a slow put lets a backlog build behind it, and without the split
|
|
59
|
+
* the next delivery sent the whole backlog as one request CloudWatch refuses.
|
|
60
|
+
*/
|
|
61
|
+
const PUT_LOG_EVENTS_MAX_EVENTS = 10_000;
|
|
62
|
+
const PUT_LOG_EVENTS_MAX_BYTES = 1_048_576;
|
|
63
|
+
const PUT_LOG_EVENTS_BYTES_PER_EVENT = 26;
|
|
47
64
|
// ─── Generic base — also used by agentcoreObservability ──────────────
|
|
48
65
|
/**
|
|
49
66
|
* Internal: shared CloudWatch Logs base used by every adapter that
|
|
@@ -65,11 +82,8 @@ function _buildCloudWatchObservability(opts, strategyName) {
|
|
|
65
82
|
const maxBatchEvents = opts.maxBatchEvents ?? 100;
|
|
66
83
|
const maxBatchBytes = opts.maxBatchBytes ?? 10_240;
|
|
67
84
|
const flushIntervalMs = opts.flushIntervalMs ?? 1000;
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
let bufferBytes = 0;
|
|
71
|
-
let lastFlushPromise = Promise.resolve();
|
|
72
|
-
let timer;
|
|
85
|
+
// Set by `stop()`: no more events accepted. NOT a guard on delivery (8.11.1):
|
|
86
|
+
// stopping does not authorise throwing away what was already accepted.
|
|
73
87
|
let stopped = false;
|
|
74
88
|
// What we know about the log stream (8.11.0). This is the per-(group,stream)
|
|
75
89
|
// create latch — group and stream are fixed for the life of a strategy, so
|
|
@@ -94,14 +108,6 @@ function _buildCloudWatchObservability(opts, strategyName) {
|
|
|
94
108
|
client = createCloudWatchClient(opts.region, strategyName, opts._sdk);
|
|
95
109
|
return client;
|
|
96
110
|
}
|
|
97
|
-
function scheduleTimedFlush() {
|
|
98
|
-
if (timer || flushIntervalMs <= 0 || stopped)
|
|
99
|
-
return;
|
|
100
|
-
timer = setTimeout(() => {
|
|
101
|
-
timer = undefined;
|
|
102
|
-
void doFlush();
|
|
103
|
-
}, flushIntervalMs);
|
|
104
|
-
}
|
|
105
111
|
/** Route a delivery failure through whatever `_onError` IS RIGHT NOW.
|
|
106
112
|
* Reading it at call time (rather than capturing a hook at construction)
|
|
107
113
|
* is the whole fix: a consumer who assigns `_onError` after building the
|
|
@@ -117,90 +123,89 @@ function _buildCloudWatchObservability(opts, strategyName) {
|
|
|
117
123
|
logEvents: batch,
|
|
118
124
|
});
|
|
119
125
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// progress — an infinite microtask spin that starved the event loop of
|
|
126
|
-
// the very process trying to shut down. Same stance as `auditExport`:
|
|
127
|
-
// stop observing, never destroy what was collected.
|
|
128
|
-
if (buffer.length === 0)
|
|
129
|
-
return;
|
|
130
|
-
// Snapshot + clear so concurrent emits during the in-flight put
|
|
131
|
-
// accumulate into the next batch.
|
|
132
|
-
const batch = buffer.splice(0);
|
|
133
|
-
bufferBytes = 0;
|
|
126
|
+
/** Ship one batch. Throws when it could not — the outbox drops the batch
|
|
127
|
+
* and reports it once. Runs inside the outbox's queue, so two puts are
|
|
128
|
+
* never in flight at once and CloudWatch's per-stream order holds. */
|
|
129
|
+
async function shipBatch(batch) {
|
|
130
|
+
const client = ensureClient();
|
|
134
131
|
try {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
await putBatch(client, batch);
|
|
138
|
-
streamState = 'created'; // a successful put proves the stream is there
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
catch (err) {
|
|
142
|
-
// The one recoverable shape: CloudWatch rejects a put into a stream
|
|
143
|
-
// that doesn't exist. Before 8.11.0 this adapter asserted that
|
|
144
|
-
// precondition and never established it, so any stream name that
|
|
145
|
-
// didn't already exist dropped every event, forever, in silence —
|
|
146
|
-
// and the documented `${HOSTNAME}/${Date.now()}` convention can never
|
|
147
|
-
// pre-exist, so following the docs guaranteed the bug.
|
|
148
|
-
if (!isMissingStreamError(err) || streamState === 'unavailable')
|
|
149
|
-
throw err;
|
|
150
|
-
if (!client.createLogStream) {
|
|
151
|
-
throw new Error(`log stream '${logStreamName}' does not exist in log group ` +
|
|
152
|
-
`'${opts.logGroupName}', and the injected \`_client\` has no ` +
|
|
153
|
-
`\`createLogStream\` to create it.`);
|
|
154
|
-
}
|
|
155
|
-
try {
|
|
156
|
-
await client.createLogStream({
|
|
157
|
-
logGroupName: opts.logGroupName,
|
|
158
|
-
logStreamName,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
catch (createErr) {
|
|
162
|
-
// Two processes racing to create the same stream is normal and
|
|
163
|
-
// expected — whoever lost the race still has a usable stream.
|
|
164
|
-
if (!isAlreadyExistsError(createErr)) {
|
|
165
|
-
// Anything else (no `logs:CreateLogStream`, or the log GROUP
|
|
166
|
-
// itself is missing) will not fix itself. Latch it off so we
|
|
167
|
-
// never loop, and say which of the two it probably is.
|
|
168
|
-
streamState = 'unavailable';
|
|
169
|
-
throw new Error(`could not create log stream '${logStreamName}' in log group ` +
|
|
170
|
-
`'${opts.logGroupName}': ${errorMessage(createErr)}. Check that the log ` +
|
|
171
|
-
`GROUP exists (this adapter never creates one) and that the role allows ` +
|
|
172
|
-
`\`logs:CreateLogStream\`.`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
streamState = 'created';
|
|
176
|
-
// Exactly ONE re-put of the same batch. Not a retry loop: if this
|
|
177
|
-
// fails the events are gone, and saying so is better than growing a
|
|
178
|
-
// buffer during an outage.
|
|
179
|
-
await putBatch(client, batch);
|
|
180
|
-
}
|
|
132
|
+
await putBatch(client, batch);
|
|
133
|
+
streamState = 'created'; // a successful put proves the stream is there
|
|
181
134
|
}
|
|
182
135
|
catch (err) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
136
|
+
// The one recoverable shape: CloudWatch rejects a put into a stream
|
|
137
|
+
// that doesn't exist. Before 8.11.0 this adapter asserted that
|
|
138
|
+
// precondition and never established it, so any stream name that
|
|
139
|
+
// didn't already exist dropped every event, forever, in silence —
|
|
140
|
+
// and the documented `${HOSTNAME}/${Date.now()}` convention can never
|
|
141
|
+
// pre-exist, so following the docs guaranteed the bug.
|
|
142
|
+
if (!isMissingStreamError(err) || streamState === 'unavailable')
|
|
143
|
+
throw err;
|
|
144
|
+
await createStream(client);
|
|
145
|
+
// Exactly ONE re-put of the same batch. Not a retry loop: if this
|
|
146
|
+
// fails the events are gone, and saying so is better than growing a
|
|
147
|
+
// buffer during an outage.
|
|
148
|
+
await putBatch(client, batch);
|
|
186
149
|
}
|
|
187
150
|
}
|
|
151
|
+
/** Create the missing stream, or latch it off for good when retrying cannot
|
|
152
|
+
* help. Losing a create race to another process is success. */
|
|
153
|
+
async function createStream(client) {
|
|
154
|
+
if (!client.createLogStream) {
|
|
155
|
+
throw new Error(`log stream '${logStreamName}' does not exist in log group ` +
|
|
156
|
+
`'${opts.logGroupName}', and the injected \`_client\` has no ` +
|
|
157
|
+
`\`createLogStream\` to create it.`);
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
await client.createLogStream({ logGroupName: opts.logGroupName, logStreamName });
|
|
161
|
+
}
|
|
162
|
+
catch (createErr) {
|
|
163
|
+
// Two processes racing to create the same stream is normal and
|
|
164
|
+
// expected — whoever lost the race still has a usable stream.
|
|
165
|
+
if (!isAlreadyExistsError(createErr)) {
|
|
166
|
+
// Anything else (no `logs:CreateLogStream`, or the log GROUP itself is
|
|
167
|
+
// missing) will not fix itself. Latch it off so we never loop, and say
|
|
168
|
+
// which of the two it probably is.
|
|
169
|
+
streamState = 'unavailable';
|
|
170
|
+
throw new Error(`could not create log stream '${logStreamName}' in log group ` +
|
|
171
|
+
`'${opts.logGroupName}': ${errorMessage(createErr)}. Check that the log ` +
|
|
172
|
+
`GROUP exists (this adapter never creates one) and that the role allows ` +
|
|
173
|
+
`\`logs:CreateLogStream\`.`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
streamState = 'created';
|
|
177
|
+
}
|
|
178
|
+
// Buffered log events, and the one queue every put goes through — size
|
|
179
|
+
// trigger, timer, `flush()`, shutdown (outbox.ts; #223).
|
|
180
|
+
const outbox = (0, outbox_js_1.createOutbox)({
|
|
181
|
+
name: strategyName,
|
|
182
|
+
// When a delivery starts — compared as given, as before.
|
|
183
|
+
maxItems: maxBatchEvents,
|
|
184
|
+
maxBytes: maxBatchBytes,
|
|
185
|
+
// What one put may carry: the oldest events that fit; the rest ship in
|
|
186
|
+
// the next put, right after, in order. The byte measure is the one `add`
|
|
187
|
+
// records (UTF-8 message bytes) plus CloudWatch's 26 per event. An event
|
|
188
|
+
// too large for any request is still sent — alone — as it was before;
|
|
189
|
+
// CloudWatch refuses it and that one event is reported dropped, without
|
|
190
|
+
// taking its neighbours with it.
|
|
191
|
+
maxItemsPerDelivery: PUT_LOG_EVENTS_MAX_EVENTS,
|
|
192
|
+
maxBytesPerDelivery: PUT_LOG_EVENTS_MAX_BYTES,
|
|
193
|
+
overheadBytesPerItem: PUT_LOG_EVENTS_BYTES_PER_EVENT,
|
|
194
|
+
flushIntervalMs,
|
|
195
|
+
// An un-stopped strategy lingers up to `flushIntervalMs` so the timer can
|
|
196
|
+
// still ship the tail (see `stop()`).
|
|
197
|
+
timerHoldsProcess: true,
|
|
198
|
+
deliver: shipBatch,
|
|
199
|
+
dropped: (batch, cause) => new Error(`${batch.length} event(s) dropped shipping to log group '${opts.logGroupName}' ` +
|
|
200
|
+
`stream '${logStreamName}': ${errorMessage(cause)}`),
|
|
201
|
+
report: reportFailure,
|
|
202
|
+
});
|
|
188
203
|
function enqueue(event) {
|
|
189
204
|
if (stopped)
|
|
190
205
|
return;
|
|
191
206
|
// The wire rule (`lib/wireJson.ts`) — an Error's custom properties never ship.
|
|
192
207
|
const message = (0, wireJson_js_1.toWireJson)(event);
|
|
193
|
-
|
|
194
|
-
buffer.push({ timestamp: Date.now(), message });
|
|
195
|
-
bufferBytes += bytes;
|
|
196
|
-
if (buffer.length >= maxBatchEvents || bufferBytes >= maxBatchBytes) {
|
|
197
|
-
// Size trigger — flush immediately. Chain onto last to preserve
|
|
198
|
-
// CloudWatch's per-stream ordering requirement.
|
|
199
|
-
lastFlushPromise = lastFlushPromise.then(doFlush, doFlush);
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
scheduleTimedFlush();
|
|
203
|
-
}
|
|
208
|
+
outbox.add({ timestamp: Date.now(), message }, Buffer.byteLength(message, 'utf8'));
|
|
204
209
|
}
|
|
205
210
|
const strategy = {
|
|
206
211
|
name: strategyName,
|
|
@@ -221,25 +226,14 @@ function _buildCloudWatchObservability(opts, strategyName) {
|
|
|
221
226
|
* since 8.11.1: a flush after a stop still ships what was already
|
|
222
227
|
* accepted.
|
|
223
228
|
*/
|
|
224
|
-
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
-
for (;;) {
|
|
233
|
-
const pending = buffer.length;
|
|
234
|
-
// Chain, never replace: CloudWatch requires per-stream ordering, so a
|
|
235
|
-
// drain waits for the in-flight put rather than racing it.
|
|
236
|
-
lastFlushPromise = lastFlushPromise.then(doFlush, doFlush);
|
|
237
|
-
await lastFlushPromise;
|
|
238
|
-
if (buffer.length === 0)
|
|
239
|
-
return;
|
|
240
|
-
if (buffer.length >= pending)
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
229
|
+
flush() {
|
|
230
|
+
// Resolves once every event accepted before the call is shipped (or
|
|
231
|
+
// dropped and reported) — one a timed put already had in flight
|
|
232
|
+
// included — after one more sweep of what arrived while it waited; it
|
|
233
|
+
// does not chase a producer that keeps emitting. A put that never
|
|
234
|
+
// settles holds it. Since 8.11.1 delivery ignores `stop()`, so a flush
|
|
235
|
+
// after a stop still ships and never spins.
|
|
236
|
+
return outbox.drain();
|
|
243
237
|
},
|
|
244
238
|
/** Stop the flush timer and stop accepting events. **The framework does
|
|
245
239
|
* not call this for you** — an un-stopped strategy keeps a `setTimeout`
|
|
@@ -251,10 +245,7 @@ function _buildCloudWatchObservability(opts, strategyName) {
|
|
|
251
245
|
* `stop()` still ships it (8.11.1). */
|
|
252
246
|
stop() {
|
|
253
247
|
stopped = true;
|
|
254
|
-
|
|
255
|
-
clearTimeout(timer);
|
|
256
|
-
timer = undefined;
|
|
257
|
-
}
|
|
248
|
+
outbox.stop();
|
|
258
249
|
},
|
|
259
250
|
/**
|
|
260
251
|
* Where errors go. Two callers: the dispatch layer (when `exportEvent`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudwatch.js","sourceRoot":"","sources":["../../../src/adapters/observability/cloudwatch.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;;;AAGH,6DAAuD;AACvD,uDAAmD;AAGnD,2DAA6D;
|
|
1
|
+
{"version":3,"file":"cloudwatch.js","sourceRoot":"","sources":["../../../src/adapters/observability/cloudwatch.ts"],"names":[],"mappings":"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"}
|