Skip to content

LogEventSink

Source: src/AWS/Logs/LogEventSink.ts

A batching sink over CloudWatch Logs PutLogEvents (10,000 events / 1,048,576 bytes per call, where each event costs its UTF-8 message size plus 26 bytes of overhead).

Each input element is a raw InputLogEvent, so ordering stays with the caller: PutLogEvents requires events in chronological order by timestamp, and the time span within one batch must not exceed 24 hours.

Events the API reports via rejectedLogEventsInfo (older than 14 days or the group’s retention period, expired, or more than 2 hours in the future) are permanently rejected — they are dropped and surfaced with a warning, never retried. The remaining valid events in the batch are still ingested by the API.

Drain a Stream of Events into a Log Stream

const sink = yield* AWS.Logs.LogEventSink(logGroup, {
logStreamName: "audit-stream",
});
// Inside a handler: drain fully before returning.
yield* Stream.fromIterable(entries).pipe(
Stream.map((entry) => ({ timestamp: entry.at, message: entry.text })),
Stream.run(sink),
);

Wire into a Lambda Function

// LogEventSinkHttp batches over the PutLogEvents binding, so provide
// PutLogEventsHttp into it with Layer.provideMerge.
export default IngestFunction.make(
{ main: import.meta.url, url: true },
Effect.gen(function* () {
const logGroup = yield* AWS.Logs.LogGroup("IngestLogs", {});
yield* AWS.Logs.LogStream("IngestStream", {
logGroupName: logGroup.logGroupName,
logStreamName: "ingest-stream",
});
const sink = yield* AWS.Logs.LogEventSink(logGroup, {
logStreamName: "ingest-stream",
});
// ... run streams of InputLogEvents into `sink` in the fetch handler
return { fetch: handler };
}).pipe(
Effect.provide(
Layer.provideMerge(AWS.Logs.LogEventSinkHttp, AWS.Logs.PutLogEventsHttp),
),
),
);