agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
159 lines • 7.66 kB
TypeScript
/**
* cloudwatchObservability — Generic AWS CloudWatch Logs adapter.
*
* Ships every `AgentfootprintEvent` to a CloudWatch Logs stream. Use
* when you want agent telemetry alongside the rest of your AWS
* observability stack — CloudWatch Insights queries, alarms,
* cross-service correlation. Same SDK as `agentcoreObservability`
* but **without** the AgentCore-specific defaults (log-stream
* convention, format opinions). Use this when:
*
* 1. You're shipping to CloudWatch but NOT running inside Bedrock
* AgentCore (most common case).
* 2. You want full control over log group / stream / format and
* don't need AgentCore's hosted-agent telemetry conventions.
*
* Subpath: `agentfootprint/observe`
* Peer dep: `@aws-sdk/client-cloudwatch-logs` (OPTIONAL — installed
* only when this adapter is used; declared via
* `peerDependenciesMeta.{name}.optional = true`).
*
* This module also exports the underlying base function used by
* `agentcoreObservability` — keeps the per-event hot path in one
* place so improvements (batching, retry, backpressure) flow to
* every CloudWatch-shaped adapter automatically.
*
* @example
* ```ts
* import { cloudwatchObservability } from 'agentfootprint/observe';
* import { microtaskBatchDriver } from 'footprintjs/detach';
*
* agent.enable.observability({
* strategy: cloudwatchObservability({
* region: 'us-east-1',
* logGroupName: '/myapp/agent-prod',
* logStreamName: `${process.env.HOSTNAME}/${Date.now()}`,
* }),
* detach: { driver: microtaskBatchDriver, mode: 'forget' },
* });
* ```
*/
import type { AgentfootprintEvent } from '../../events/registry.js';
import type { ObservabilityStrategy } from '../../strategies/types.js';
export interface CloudwatchObservabilityOptions {
/** AWS region. Falls back to AWS_REGION / AWS_DEFAULT_REGION env. */
readonly region?: string;
/** CloudWatch Logs log group. **Required, and it must already exist.**
* This adapter never creates it: a log group carries retention and
* encryption decisions that belong to whoever provisions your account
* (a group created with default retention never expires — an unbounded
* bill), so provisioning it is control-plane work, same as the rest of
* your infrastructure. Naming a group that does not exist means no
* telemetry is delivered; the failure is reported through
* {@link CloudwatchObservabilityOptions.onError}. */
readonly logGroupName: string;
/** CloudWatch Logs log stream within the group. Conventionally
* `<host>/<startTime>` so multi-instance deployments don't collide.
* Created on first delivery if it does not exist — your role must allow
* `logs:CreateLogStream`. The log GROUP is not created for you (see
* {@link CloudwatchObservabilityOptions.logGroupName}). Defaults to
* `agentfootprint`. */
readonly logStreamName?: string;
/** Max events buffered before forced flush. Default 100. A trigger, not a
* request size: however many events are waiting when a put starts, one
* put never carries more than CloudWatch accepts (10,000 events,
* 1,048,576 bytes) — the rest go in the next put, right after. */
readonly maxBatchEvents?: number;
/** Max payload bytes (UTF-8) buffered before forced flush. Default
* 10240 (10 KB). CloudWatch hard caps at 1 MB / batch but we keep
* the default low so latency stays bounded. A trigger too: a backlog
* larger than one request is split into requests CloudWatch accepts. */
readonly maxBatchBytes?: number;
/** Forced-flush interval when traffic is sparse. Default 1000ms.
* `0` disables time-based flush — only size triggers fire. */
readonly flushIntervalMs?: number;
/**
* Where delivery failures go (8.11.0).
*
* Shipping telemetry is network I/O and it fails: a missing log group, an
* IAM denial, throttling, a batch CloudWatch rejects. Without this, those
* failures reach the default sink — a rate-limited `console.error` — because
* **telemetry that fails invisibly is indistinguishable from telemetry that
* works**, and an exporter silently dropping every event is the worst
* outcome this adapter can produce.
*
* Set this to route failures into your own logger instead. You receive
* EVERY failure (the rate limiting applies only to the console fallback);
* the batch that failed is dropped, never requeued, so an outage cannot
* grow the buffer without bound.
*
* Equivalent to assigning the strategy's `_onError` property after
* construction, but visible at the call site.
*/
readonly onError?: (error: Error, event?: AgentfootprintEvent) => void;
/** Test injection — bypasses SDK lazy-require entirely. When set,
* `region` / IAM are ignored. */
readonly _client?: CloudWatchLikeClient;
/** @internal Test injection (9.4.0) — the AWS SDK module, so the real shim
* (`send(new Command(...))`) runs against a fake SDK and the command names
* it dispatches can be asserted. Ignored when `_client` is set. */
readonly _sdk?: CloudWatchSdkModule;
}
export interface CloudWatchLikeClient {
putLogEvents(input: {
logGroupName: string;
logStreamName: string;
logEvents: ReadonlyArray<{
timestamp: number;
message: string;
}>;
}): Promise<unknown>;
/**
* Create the log stream (8.11.0). OPTIONAL so an existing `_client` test
* double that only implements `putLogEvents` still type-checks — the real
* SDK-backed client always provides it. When a put fails because the stream
* does not exist and this is absent, the adapter reports the failure rather
* than creating anything.
*/
createLogStream?(input: {
logGroupName: string;
logStreamName: string;
}): Promise<unknown>;
}
/**
* The slice of `@aws-sdk/client-cloudwatch-logs` this shim touches.
*
* Exported since 9.4.0 so `opts._sdk` can name it — which is what lets the
* shared command-name pin (test/adapters/aws/) assert the OPERATIONS this
* adapter dispatches without an AWS account or the peer dep installed. A
* `_client` double proves the batching; only an `_sdk` double can prove the
* adapter reaches for `PutLogEvents` and not something that does not exist.
*/
export interface CloudWatchSdkModule {
readonly CloudWatchLogsClient?: new (config: {
region?: string;
}) => unknown;
readonly PutLogEventsCommand?: new (input: unknown) => unknown;
readonly CreateLogStreamCommand?: new (input: unknown) => unknown;
}
/**
* Internal: shared CloudWatch Logs base used by every adapter that
* ships to CWL. `cloudwatchObservability` is the public generic
* factory; `agentcoreObservability` calls this with AgentCore-flavored
* defaults.
*
* Exported for adapter authors only — consumers should call
* `cloudwatchObservability` or `agentcoreObservability` directly.
*
* @internal
*/
export declare function _buildCloudWatchObservability(opts: CloudwatchObservabilityOptions, strategyName: string): ObservabilityStrategy;
/**
* Generic CloudWatch Logs observability adapter. See
* `CloudwatchObservabilityOptions` for the per-option contract.
*
* For AgentCore-specific conventions, use `agentcoreObservability`
* which thin-wraps this with AgentCore-flavored defaults.
*/
export declare function cloudwatchObservability(opts: CloudwatchObservabilityOptions): ObservabilityStrategy;
//# sourceMappingURL=cloudwatch.d.ts.map