From 5ea0af3ecefb18d3e2ec1f0ac786448145ace54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20J=2E=20Wal?= Date: Thu, 9 Jul 2026 11:30:34 +0200 Subject: [PATCH 1/6] Rebrand Logtail references to Better Stack - README: point badge and clone URL at the logtail org, link the Better Stack HTTP source docs and dashboard instead of Logtail - package.json: add a description - Rename the forwarder logtailLogForwarder -> betterStackLogForwarder (src/forwarders/logtail.ts -> betterStack.ts) and its test file --- README.md | 8 ++++---- package.json | 2 +- src/extension.ts | 4 ++-- src/forwarders/{logtail.test.ts => betterStack.test.ts} | 8 ++++---- src/forwarders/{logtail.ts => betterStack.ts} | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/forwarders/{logtail.test.ts => betterStack.test.ts} (91%) rename src/forwarders/{logtail.ts => betterStack.ts} (98%) diff --git a/README.md b/README.md index 1e356ad..c80c61c 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # logtail-lambda-extension -[![Test logtail-lambda-extension](https://github.com/stockstory/logtail-lambda-extension/actions/workflows/test.yml/badge.svg)](https://github.com/stockstory/logtail-lambda-extension/actions/workflows/test.yml) +[![Test logtail-lambda-extension](https://github.com/logtail/logtail-lambda-extension/actions/workflows/test.yml/badge.svg)](https://github.com/logtail/logtail-lambda-extension/actions/workflows/test.yml) -[AWS Lambda Extension](https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html) that uses the [Lambda Telemetry API](https://docs.aws.amazon.com/lambda/latest/dg/telemetry-api-reference.html) to forward logs to a [Logtail HTTP API source](https://docs.logtail.com/integrations/rest-api). +[AWS Lambda Extension](https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html) that uses the [Lambda Telemetry API](https://docs.aws.amazon.com/lambda/latest/dg/telemetry-api-reference.html) to forward logs to a [Better Stack HTTP source](https://betterstack.com/docs/logs/http-rest-api/). # Usage In order to use the extension you must first build and deploy it into your AWS infrastructure: ```shell -$ git clone git@github.com:stockstory/logtail-lambda-extension.git +$ git clone git@github.com:logtail/logtail-lambda-extension.git $ cd logtail-lambda-extension $ pnpm install $ pnpm run build @@ -20,7 +20,7 @@ $ aws lambda publish-layer-version \ ``` Once deployed set the `LOGTAIL_TOKEN` environment variable on your Lambda to your HTTP API source from Logtail, and [add the layer](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html) to your Lambda function. -On next invocation your Lambda logs should start appearing in your Logtail console. +On next invocation your Lambda logs should start appearing in [Better Stack](https://telemetry.betterstack.com/). ## Environment Variables diff --git a/package.json b/package.json index 738d624..96fcb6f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "logtail-lambda-extension", "version": "1.0.0", - "description": "", + "description": "AWS Lambda extension that forwards function logs to Better Stack.", "main": "index.js", "engines": { "node": ">=16.0.0", diff --git a/src/extension.ts b/src/extension.ts index ab022fe..3c73caa 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,7 +3,7 @@ import { EnvironmentVars } from '~/env'; import { pollForNextEvent, registerExtension } from '~/aws/api'; import { startTelemetryHttpListener } from '~/httpListener'; import { subscribeTelemetry, SubscriptionBody } from '~/aws/subscribe'; -import { logtailLogForwarder } from '~/forwarders/logtail'; +import { betterStackLogForwarder } from '~/forwarders/betterStack'; import { AbortHandler } from '~/abortHandler'; // noinspection HttpUrlsUsage @@ -53,7 +53,7 @@ export const createExtension = ( ), ), TE.bind('forwardLogs', ({ LOGTAIL_TOKEN, LOGTAIL_HTTP_API_URL, listener }) => - TE.of(logtailLogForwarder(LOGTAIL_TOKEN, LOGTAIL_HTTP_API_URL, listener)), + TE.of(betterStackLogForwarder(LOGTAIL_TOKEN, LOGTAIL_HTTP_API_URL, listener)), ), TE.map(({ EXTENSION_NAME, extensionId, extensionBaseUrl, forwardLogs, listener }) => F.pipe( diff --git a/src/forwarders/logtail.test.ts b/src/forwarders/betterStack.test.ts similarity index 91% rename from src/forwarders/logtail.test.ts rename to src/forwarders/betterStack.test.ts index c9a0952..f740b6b 100644 --- a/src/forwarders/logtail.test.ts +++ b/src/forwarders/betterStack.test.ts @@ -1,10 +1,10 @@ import fetchMock from 'jest-fetch-mock'; import { Request } from 'node-fetch'; import { either as E } from 'fp-ts'; -import { logtailLogForwarder, parseMessageWithPowertoolsLogFormat } from '~/forwarders/logtail'; +import { betterStackLogForwarder, parseMessageWithPowertoolsLogFormat } from '~/forwarders/betterStack'; import { FunctionLogEvent } from '~/aws/events'; -describe('test logtail log forwarding', () => { +describe('test Better Stack log forwarding', () => { beforeEach(() => { fetchMock.resetMocks(); }); @@ -27,7 +27,7 @@ describe('test logtail log forwarding', () => { logsQueue: [log, log, log], }; - const result = await logtailLogForwarder(token, ingestionUrl, listener)(); + const result = await betterStackLogForwarder(token, ingestionUrl, listener)(); expect(E.left(result)).toBeTruthy(); @@ -53,7 +53,7 @@ describe('test logtail log forwarding', () => { logsQueue: [log, log, log], }; - const result = await logtailLogForwarder(token, ingestionUrl, listener)(); + const result = await betterStackLogForwarder(token, ingestionUrl, listener)(); expect(E.left(result)).toBeTruthy(); diff --git a/src/forwarders/logtail.ts b/src/forwarders/betterStack.ts similarity index 98% rename from src/forwarders/logtail.ts rename to src/forwarders/betterStack.ts index c8583bd..5770c2a 100644 --- a/src/forwarders/logtail.ts +++ b/src/forwarders/betterStack.ts @@ -35,7 +35,7 @@ export const parseMessageWithPowertoolsLogFormat = (message: string): E.Either (): Promise => { const logs = listener.logsQueue.splice(0); From d98de54afef27fc986dab45dfaf984f050bb4bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20J=2E=20Wal?= Date: Thu, 9 Jul 2026 11:37:43 +0200 Subject: [PATCH 2/6] Ingest to Better Stack with SOURCE_TOKEN/INGESTING_HOST env vars Update the ingestion endpoint from in.logtail.com to in.logs.betterstack.com and introduce Better Stack-named env vars while keeping the legacy ones as fallbacks (non-breaking for existing deployments): - env.ts: prefer SOURCE_TOKEN / INGESTING_HOST, fall back to LOGTAIL_TOKEN / LOGTAIL_HTTP_API_URL; default host in.logs.betterstack.com; resolve to sourceToken / ingestionUrl - extension.ts: consume the resolved sourceToken / ingestionUrl - README: document the new variables, defaults, and legacy fallbacks - tests: cover precedence, legacy fallback, default host, and missing token --- README.md | 8 ++-- src/env.test.ts | 77 +++++++++++++++++++++++++----- src/env.ts | 34 +++++++++++-- src/extension.ts | 4 +- src/forwarders/betterStack.test.ts | 2 +- 5 files changed, 102 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index c80c61c..eb9f396 100644 --- a/README.md +++ b/README.md @@ -19,15 +19,15 @@ $ aws lambda publish-layer-version \ --compatible-architectures x86_64 arm64 ``` -Once deployed set the `LOGTAIL_TOKEN` environment variable on your Lambda to your HTTP API source from Logtail, and [add the layer](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html) to your Lambda function. +Once deployed set the `SOURCE_TOKEN` environment variable on your Lambda to your Better Stack source token, and [add the layer](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html) to your Lambda function. On next invocation your Lambda logs should start appearing in [Better Stack](https://telemetry.betterstack.com/). ## Environment Variables | Variable | Description | Default | | ---------------------------------------- | ------------------------------------------------------- | ------------------------------------ | -| LOGTAIL_TOKEN | Logtail source bearer token | **required** | -| LOGTAIL_HTTP_API_URL | Logtail HTTP source ingestion API URL | `https://in.logtail.com/` | +| SOURCE_TOKEN | Better Stack source bearer token | **required** | +| INGESTING_HOST | Better Stack ingesting host | `in.logs.betterstack.com` | | EXTENSION_NAME | Name of the lambda extension | `logtail-lambda-extension` | | RECEIVER_ADDRESS | Address of the logs http receiver | `sandbox` | | RECEIVER_PORT | Port of the logs http receiver | `4243` | @@ -38,6 +38,8 @@ On next invocation your Lambda logs should start appearing in [Better Stack](htt | AWS_LAMBDA_RUNTIME_EXTENSION_API_VERSION | Lambda Extension API version date | `2020-01-01` | | AWS_LAMBDA_RUNTIME_TELEMETRY_API_VERSION | Telemetry API version date | `2022-07-01` | +`SOURCE_TOKEN` and `INGESTING_HOST` fall back to the legacy `LOGTAIL_TOKEN` and `LOGTAIL_HTTP_API_URL` (a full URL) variables when they are not set. + ### License Unless explicitly stated otherwise all files in this repository are licensed under the MIT License. See [LICENSE](./LICENSE) for more information. diff --git a/src/env.test.ts b/src/env.test.ts index 5639e7a..b83f298 100644 --- a/src/env.test.ts +++ b/src/env.test.ts @@ -2,11 +2,12 @@ import { either as E } from 'fp-ts'; import { parseEnvironmentVariables } from '~/env'; import { ZodError } from 'zod'; -describe('test parseEnvironment`', () => { - test('should succeed and populate defaults', () => { +describe('parseEnvironmentVariables', () => { + test('resolves new names and populates defaults', () => { const env = { AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', - LOGTAIL_TOKEN: 'test_token', + SOURCE_TOKEN: 'source_token', + INGESTING_HOST: 's123.eu.betterstack.com', }; const result = parseEnvironmentVariables(env); @@ -14,26 +15,76 @@ describe('test parseEnvironment`', () => { expect(result).toStrictEqual({ _tag: 'Right', right: { + NODE_ENV: 'production', AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', AWS_LAMBDA_RUNTIME_EXTENSION_API_VERSION: '2020-01-01', AWS_LAMBDA_RUNTIME_TELEMETRY_API_VERSION: '2022-07-01', EXTENSION_NAME: 'logtail-lambda-extension', - LOGTAIL_HTTP_API_URL: 'https://in.logtail.com/', - LOGTAIL_TOKEN: 'test_token', - MAX_BYTES: 262144, - MAX_ITEMS: 10000, - NODE_ENV: 'production', RECEIVER_ADDRESS: 'sandbox', - RECEIVER_PORT: 4243, + MAX_ITEMS: 10000, + MAX_BYTES: 262144, TIMEOUT_MS: 1000, + RECEIVER_PORT: 4243, + sourceToken: 'source_token', + ingestionUrl: 'https://s123.eu.betterstack.com/', }, }); }); - test('should fail when required fields are missing', () => { - const env = {}; - const result = parseEnvironmentVariables(env); + test('falls back to legacy token and full URL used as-is', () => { + const result = parseEnvironmentVariables({ + AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', + LOGTAIL_TOKEN: 'legacy_token', + LOGTAIL_HTTP_API_URL: 'https://in.logtail.com/', + }); + + if (!E.isRight(result)) throw new Error('expected Right'); + expect(result.right.sourceToken).toBe('legacy_token'); + expect(result.right.ingestionUrl).toBe('https://in.logtail.com/'); + }); + + test('defaults the ingestion host when no host or legacy URL is set', () => { + const result = parseEnvironmentVariables({ + AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', + SOURCE_TOKEN: 'source_token', + }); + + if (!E.isRight(result)) throw new Error('expected Right'); + expect(result.right.ingestionUrl).toBe('https://in.logs.betterstack.com/'); + }); + + test('SOURCE_TOKEN wins over LOGTAIL_TOKEN', () => { + const result = parseEnvironmentVariables({ + AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', + SOURCE_TOKEN: 'preferred', + LOGTAIL_TOKEN: 'legacy', + }); + + if (!E.isRight(result)) throw new Error('expected Right'); + expect(result.right.sourceToken).toBe('preferred'); + }); + + test('INGESTING_HOST wins over LOGTAIL_HTTP_API_URL', () => { + const result = parseEnvironmentVariables({ + AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', + SOURCE_TOKEN: 'source_token', + INGESTING_HOST: 's123.eu.betterstack.com', + LOGTAIL_HTTP_API_URL: 'https://in.logtail.com/', + }); + + if (!E.isRight(result)) throw new Error('expected Right'); + expect(result.right.ingestionUrl).toBe('https://s123.eu.betterstack.com/'); + }); + + test('fails with ZodError when a runtime API is set but no token', () => { + const result = parseEnvironmentVariables({ AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/' }); + + expect(E.isLeft(result) && result.left instanceof ZodError).toBe(true); + }); + + test('fails with ZodError on completely empty env', () => { + const result = parseEnvironmentVariables({}); - expect(E.isLeft(result) && result.left instanceof ZodError).toStrictEqual(true); + expect(E.isLeft(result) && result.left instanceof ZodError).toBe(true); }); }); diff --git a/src/env.ts b/src/env.ts index f8faca7..5d73f0d 100644 --- a/src/env.ts +++ b/src/env.ts @@ -6,7 +6,10 @@ const envNumber = z .transform((val) => Number(val)) .refine((val) => !isNaN(val)); -const envSchema = z.object({ +// Better Stack's general-purpose ingesting host; per-source hosts also live under betterstack.com. +const DEFAULT_INGESTING_HOST = 'in.logs.betterstack.com'; + +const baseSchema = z.object({ NODE_ENV: z.union([z.literal('production'), z.literal('development'), z.literal('test')]).default('production'), AWS_LAMBDA_RUNTIME_API: z.string(), // Provided by the Lambda Env, usually http://127.0.0.1:9001/ AWS_LAMBDA_RUNTIME_EXTENSION_API_VERSION: z.string().default('2020-01-01'), // Extension API version @@ -17,17 +20,40 @@ const envSchema = z.object({ MAX_BYTES: envNumber.default('262144'), // Maximum size in bytes that the logs are buffered in memory. TIMEOUT_MS: envNumber.default('1000'), // Maximum time (in milliseconds) that a batch is buffered. RECEIVER_PORT: envNumber.default('4243'), // HTTP server receiving port - LOGTAIL_HTTP_API_URL: z.string().url().default('https://in.logtail.com/'), // Logtail HTTP API ingestion URL - LOGTAIL_TOKEN: z.string(), // Logtail token, obtain yours via the sources UI + // Better Stack source token; SOURCE_TOKEN is preferred, LOGTAIL_TOKEN is kept as a fallback. + SOURCE_TOKEN: z.string().optional(), + LOGTAIL_TOKEN: z.string().optional(), + // Better Stack ingesting host; INGESTING_HOST is preferred, LOGTAIL_HTTP_API_URL (a full URL) is kept as a fallback. + INGESTING_HOST: z.string().optional(), + LOGTAIL_HTTP_API_URL: z.string().url().optional(), }); +const envSchema = baseSchema.transform( + ({ SOURCE_TOKEN, LOGTAIL_TOKEN, INGESTING_HOST, LOGTAIL_HTTP_API_URL, ...rest }, ctx) => { + const sourceToken = SOURCE_TOKEN || LOGTAIL_TOKEN; + if (!sourceToken) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Missing source token: set SOURCE_TOKEN (or the legacy LOGTAIL_TOKEN).', + }); + return z.NEVER; + } + + const ingestionUrl = INGESTING_HOST + ? `https://${INGESTING_HOST}/` + : LOGTAIL_HTTP_API_URL || `https://${DEFAULT_INGESTING_HOST}/`; + + return { ...rest, sourceToken, ingestionUrl }; + }, +); + export type EnvironmentVars = z.infer; export const parseEnvironmentVariables = ( env: Record = process.env, ): E.Either => F.pipe( - envSchema.shape, + baseSchema.shape, R.mapWithIndex((key) => env[key]), (vars) => envSchema.safeParse(vars), (parsed) => (parsed.success ? E.right(parsed.data) : E.left(parsed.error)), diff --git a/src/extension.ts b/src/extension.ts index 3c73caa..4a95232 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -52,8 +52,8 @@ export const createExtension = ( (body) => subscribeTelemetry(telemetryBaseUrl, extensionId, body), ), ), - TE.bind('forwardLogs', ({ LOGTAIL_TOKEN, LOGTAIL_HTTP_API_URL, listener }) => - TE.of(betterStackLogForwarder(LOGTAIL_TOKEN, LOGTAIL_HTTP_API_URL, listener)), + TE.bind('forwardLogs', ({ sourceToken, ingestionUrl, listener }) => + TE.of(betterStackLogForwarder(sourceToken, ingestionUrl, listener)), ), TE.map(({ EXTENSION_NAME, extensionId, extensionBaseUrl, forwardLogs, listener }) => F.pipe( diff --git a/src/forwarders/betterStack.test.ts b/src/forwarders/betterStack.test.ts index f740b6b..66057a9 100644 --- a/src/forwarders/betterStack.test.ts +++ b/src/forwarders/betterStack.test.ts @@ -9,7 +9,7 @@ describe('test Better Stack log forwarding', () => { fetchMock.resetMocks(); }); - const ingestionUrl = 'https://in.logtail.com/'; + const ingestionUrl = 'https://in.logs.betterstack.com/'; const token = 'd4ed7843'; const log: FunctionLogEvent = { From 8d5b134e771cec762c7739ce9c6540949b51fb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20J=2E=20Wal?= Date: Thu, 9 Jul 2026 12:43:43 +0200 Subject: [PATCH 3/6] Point ingesting-host docs at betterstackdata.com hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-source ingesting hosts live under betterstackdata.com (e.g. s123456.lu-trq-1.betterstackdata.com), not betterstack.com. Fix the env.ts comment, tell the README to set INGESTING_HOST from the source settings, and use a made-up cluster host in the env tests. No logic change — INGESTING_HOST stays an opaque host, so nothing to validate. --- README.md | 2 +- src/env.test.ts | 8 ++++---- src/env.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eb9f396..5d1a614 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ $ aws lambda publish-layer-version \ --compatible-architectures x86_64 arm64 ``` -Once deployed set the `SOURCE_TOKEN` environment variable on your Lambda to your Better Stack source token, and [add the layer](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html) to your Lambda function. +Once deployed set the `SOURCE_TOKEN` and `INGESTING_HOST` environment variables on your Lambda to the token and ingesting host from your Better Stack source settings (the ingesting host looks like `s123456.lu-trq-1.betterstackdata.com`), and [add the layer](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html) to your Lambda function. On next invocation your Lambda logs should start appearing in [Better Stack](https://telemetry.betterstack.com/). ## Environment Variables diff --git a/src/env.test.ts b/src/env.test.ts index b83f298..c5164e3 100644 --- a/src/env.test.ts +++ b/src/env.test.ts @@ -7,7 +7,7 @@ describe('parseEnvironmentVariables', () => { const env = { AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', SOURCE_TOKEN: 'source_token', - INGESTING_HOST: 's123.eu.betterstack.com', + INGESTING_HOST: 's123456.lu-trq-1.betterstackdata.com', }; const result = parseEnvironmentVariables(env); @@ -26,7 +26,7 @@ describe('parseEnvironmentVariables', () => { TIMEOUT_MS: 1000, RECEIVER_PORT: 4243, sourceToken: 'source_token', - ingestionUrl: 'https://s123.eu.betterstack.com/', + ingestionUrl: 'https://s123456.lu-trq-1.betterstackdata.com/', }, }); }); @@ -68,12 +68,12 @@ describe('parseEnvironmentVariables', () => { const result = parseEnvironmentVariables({ AWS_LAMBDA_RUNTIME_API: 'http://127.0.0.1:9001/', SOURCE_TOKEN: 'source_token', - INGESTING_HOST: 's123.eu.betterstack.com', + INGESTING_HOST: 's123456.lu-trq-1.betterstackdata.com', LOGTAIL_HTTP_API_URL: 'https://in.logtail.com/', }); if (!E.isRight(result)) throw new Error('expected Right'); - expect(result.right.ingestionUrl).toBe('https://s123.eu.betterstack.com/'); + expect(result.right.ingestionUrl).toBe('https://s123456.lu-trq-1.betterstackdata.com/'); }); test('fails with ZodError when a runtime API is set but no token', () => { diff --git a/src/env.ts b/src/env.ts index 5d73f0d..f619904 100644 --- a/src/env.ts +++ b/src/env.ts @@ -6,7 +6,7 @@ const envNumber = z .transform((val) => Number(val)) .refine((val) => !isNaN(val)); -// Better Stack's general-purpose ingesting host; per-source hosts also live under betterstack.com. +// Better Stack's general-purpose ingesting host; a source's own host looks like s123456.lu-trq-1.betterstackdata.com. const DEFAULT_INGESTING_HOST = 'in.logs.betterstack.com'; const baseSchema = z.object({ From 73d77ca5d04a625178012525a833aec365c9d153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20J=2E=20Wal?= Date: Thu, 9 Jul 2026 12:59:28 +0200 Subject: [PATCH 4/6] Reword per review: source token, Telemetry Live tail - "source bearer token" -> "source token" (Better Stack's term) - point the success step at Telemetry -> Live tail --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5d1a614..7a630fe 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ $ aws lambda publish-layer-version \ ``` Once deployed set the `SOURCE_TOKEN` and `INGESTING_HOST` environment variables on your Lambda to the token and ingesting host from your Better Stack source settings (the ingesting host looks like `s123456.lu-trq-1.betterstackdata.com`), and [add the layer](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html) to your Lambda function. -On next invocation your Lambda logs should start appearing in [Better Stack](https://telemetry.betterstack.com/). +On next invocation your Lambda logs should start appearing in **Telemetry** -> [Live tail](https://telemetry.betterstack.com/team/0/tail). ## Environment Variables | Variable | Description | Default | | ---------------------------------------- | ------------------------------------------------------- | ------------------------------------ | -| SOURCE_TOKEN | Better Stack source bearer token | **required** | +| SOURCE_TOKEN | Better Stack source token | **required** | | INGESTING_HOST | Better Stack ingesting host | `in.logs.betterstack.com` | | EXTENSION_NAME | Name of the lambda extension | `logtail-lambda-extension` | | RECEIVER_ADDRESS | Address of the logs http receiver | `sandbox` | From 7290b02c6903f739e79b67e7c0f7df6a8313edaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20J=2E=20Wal?= Date: Thu, 9 Jul 2026 13:00:33 +0200 Subject: [PATCH 5/6] Target current Node runtimes (nodejs22.x/24.x), drop deprecated node20 nodejs20.x reached end-of-life on 2026-04-30; move to the current runtimes. - README: advertise nodejs22.x and nodejs24.x as compatible runtimes - build: esbuild target node22 - CI: build and test on node 22 --- .github/workflows/test.yml | 2 +- README.md | 2 +- scripts/build.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dff0524..05369a3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: - name: Setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: Cache node_modules uses: actions/cache@v4 diff --git a/README.md b/README.md index 7a630fe..7da867f 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ $ pnpm run build $ aws lambda publish-layer-version \ --layer-name "logtail-lambda-extension" \ --zip-file "fileb://./dist/extension.zip" \ - --compatible-runtimes nodejs20.x \ + --compatible-runtimes nodejs22.x nodejs24.x \ --compatible-architectures x86_64 arm64 ``` diff --git a/scripts/build.ts b/scripts/build.ts index 2fcdfcc..dc69044 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -44,7 +44,7 @@ const run = () => bundle: true, minify: false, platform: 'node', - target: 'node20', + target: 'node22', outfile: outputIndex, }), (error) => new Error(`Error during build: ${error instanceof Error ? error.message : error}`), From 90a08bee4ffc944e86f259b092010339158b04d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20J=2E=20Wal?= Date: Thu, 9 Jul 2026 13:14:28 +0200 Subject: [PATCH 6/6] Run CI on pull_request and pushes to main - pull_request: validate PRs (including from forks) against the merge result - push: main only, so post-merge/badge CI runs without double-firing on same-repo feature-branch PRs - keep workflow_dispatch for manual runs Takes effect once this workflow is on main; GitHub evaluates pull_request triggers from the base branch's copy of the workflow. --- .github/workflows/test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 05369a3..bb4b5a0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,10 @@ name: Test logtail-lambda-extension -on: [push, workflow_dispatch] +on: + push: + branches: [main] + pull_request: + workflow_dispatch: jobs: test: runs-on: ubuntu-22.04