Skip to content

Commit b0778a8

Browse files
committed
improvements
1 parent aad6770 commit b0778a8

File tree

10 files changed

+186
-200
lines changed

10 files changed

+186
-200
lines changed

dev-packages/rollup-utils/bundleHelpers.mjs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function makeBaseBundleConfig(options) {
5353
},
5454
},
5555
context: 'window',
56-
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin],
56+
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin, licensePlugin],
5757
};
5858

5959
// used by `@sentry/wasm` & pluggable integrations from core/browser (bundles which need to be combined with a stand-alone SDK bundle)
@@ -87,14 +87,23 @@ export function makeBaseBundleConfig(options) {
8787
// code to add after the CJS wrapper
8888
footer: '}(window));',
8989
},
90-
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin],
90+
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin, licensePlugin],
9191
};
9292

9393
const workerBundleConfig = {
9494
output: {
9595
format: 'esm',
9696
},
97-
plugins: [commonJSPlugin, makeTerserPlugin()],
97+
plugins: [commonJSPlugin, makeTerserPlugin(), licensePlugin],
98+
// Don't bundle any of Node's core modules
99+
external: builtinModules,
100+
};
101+
102+
const awsLambdaExtensionBundleConfig = {
103+
output: {
104+
format: 'esm',
105+
},
106+
plugins: [commonJSPlugin],
98107
// Don't bundle any of Node's core modules
99108
external: builtinModules,
100109
};
@@ -110,14 +119,15 @@ export function makeBaseBundleConfig(options) {
110119
strict: false,
111120
esModule: false,
112121
},
113-
plugins: [sucrasePlugin, nodeResolvePlugin, cleanupPlugin, licensePlugin],
122+
plugins: [sucrasePlugin, nodeResolvePlugin, cleanupPlugin],
114123
treeshake: 'smallest',
115124
};
116125

117126
const bundleTypeConfigMap = {
118127
standalone: standAloneBundleConfig,
119128
addon: addOnBundleConfig,
120129
'node-worker': workerBundleConfig,
130+
'lambda-extension': awsLambdaExtensionBundleConfig,
121131
};
122132

123133
return deepMerge.all([sharedBundleConfig, bundleTypeConfigMap[bundleType], packageSpecificConfig || {}], {

packages/aws-serverless/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
},
8080
"scripts": {
8181
"build": "run-p build:transpile build:types",
82-
"build:layer": "yarn ts-node scripts/buildLambdaLayer.ts",
82+
"build:layer": "rollup -c rollup.lambda-extension.config.mjs && yarn ts-node scripts/buildLambdaLayer.ts",
8383
"build:dev": "run-p build:transpile build:types",
8484
"build:transpile": "rollup -c rollup.npm.config.mjs && yarn build:layer",
8585
"build:types": "run-s build:types:core build:types:downlevel",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { makeBaseBundleConfig, makeBundleConfigVariants } from '@sentry-internal/rollup-utils';
2+
3+
export default [
4+
...makeBundleConfigVariants(
5+
makeBaseBundleConfig({
6+
bundleType: 'lambda-extension',
7+
entrypoints: ['src/sentry-extension/index.ts'],
8+
outputFileBase: () => 'index',
9+
packageSpecificConfig: {
10+
output: {
11+
dir: 'build/aws/dist-serverless/sentry-extension',
12+
sourcemap: false,
13+
},
14+
},
15+
}),
16+
{ variants: ['.js'] },
17+
),
18+
];

packages/aws-serverless/rollup.npm.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default [
66
// TODO: `awslambda-auto.ts` is a file which the lambda layer uses to automatically init the SDK. Does it need to be
77
// in the npm package? Is it possible that some people are using it themselves in the same way the layer uses it (in
88
// which case removing it would be a breaking change)? Should it stay here or not?
9-
entrypoints: ['src/index.ts', 'src/awslambda-auto.ts', 'src/sentry-extension/index.ts'],
9+
entrypoints: ['src/index.ts', 'src/awslambda-auto.ts'],
1010
// packages with bundles have a different build directory structure
1111
hasBundles: true,
1212
packageSpecificConfig: {

packages/aws-serverless/scripts/buildLambdaLayer.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ async function buildLambdaLayer(): Promise<void> {
4646
replaceSDKSource();
4747

4848
fsForceMkdirSync('./build/aws/dist-serverless/extensions');
49-
fsForceMkdirSync('./build/aws/dist-serverless/sentry-extension');
50-
fs.renameSync(
51-
'./build/aws/dist-serverless/nodejs/node_modules/@sentry/aws-serverless/build/npm/esm/sentry-extension',
52-
'./build/aws/dist-serverless/sentry-extension',
53-
);
5449
fs.copyFileSync('./src/extensions/sentry-extension', './build/aws/dist-serverless/extensions/sentry-extension');
5550
fs.chmodSync('./build/aws/dist-serverless/extensions/sentry-extension', 0o755);
5651

@@ -81,7 +76,6 @@ async function pruneNodeModules(): Promise<void> {
8176
'./build/aws/dist-serverless/nodejs/node_modules/@sentry/aws-serverless/build/npm/cjs/index.js',
8277
'./build/aws/dist-serverless/nodejs/node_modules/@sentry/aws-serverless/build/npm/cjs/awslambda-auto.js',
8378
'./build/aws/dist-serverless/nodejs/node_modules/@sentry/aws-serverless/build/npm/esm/awslambda-auto.js',
84-
'./build/aws/dist-serverless/nodejs/node_modules/@sentry/aws-serverless/build/npm/esm/sentry-extension/index.js',
8579
];
8680

8781
const { fileList } = await nodeFileTrace(entrypoints);
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
#!/bin/bash
2-
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3-
# SPDX-License-Identifier: MIT-0
4-
52
set -euo pipefail
63

74
OWN_FILENAME="$(basename $0)"
85
LAMBDA_EXTENSION_NAME="$OWN_FILENAME" # (external) extension name has to match the filename
96

10-
echo "${LAMBDA_EXTENSION_NAME} launching extension"
117
unset NODE_OPTIONS
128
exec "/opt/${LAMBDA_EXTENSION_NAME}/index.js"

packages/aws-serverless/src/init.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ export function init(options: NodeOptions = {}): NodeClient | undefined {
2525
...options,
2626
};
2727

28-
applySdkMetadata(opts, 'aws-serverless', ['aws-serverless'], getSDKSource());
28+
const sdkSource = getSDKSource();
29+
30+
if (sdkSource === 'aws-lambda-layer' && !opts.tunnel) {
31+
opts.tunnel = 'http://localhost:9000/envelope';
32+
}
33+
34+
applySdkMetadata(opts, 'aws-serverless', ['aws-serverless'], sdkSource);
2935

3036
return initWithoutDefaultIntegrations(opts);
3137
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import * as http from 'node:http';
2+
import { buffer } from 'node:stream/consumers';
3+
4+
/**
5+
* The Extension API Client.
6+
*/
7+
export class AwsLambdaExtension {
8+
private readonly _baseUrl: string;
9+
private _extensionId: string | null;
10+
11+
public constructor() {
12+
this._baseUrl = `http://${process.env.AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension`;
13+
this._extensionId = null;
14+
}
15+
16+
/**
17+
* Register this extension as an external extension with AWS.
18+
* @returns The extension identifier, or null if the extension was not registered.
19+
*/
20+
public async register(): Promise<string | null> {
21+
const res = await fetch(`${this._baseUrl}/register`, {
22+
method: 'POST',
23+
body: JSON.stringify({
24+
events: ['INVOKE', 'SHUTDOWN'],
25+
}),
26+
headers: {
27+
'Content-Type': 'application/json',
28+
'Lambda-Extension-Name': 'sentry-extension',
29+
},
30+
});
31+
32+
if (!res.ok) {
33+
throw new Error(`Failed to register with the extension API: ${await res.text()}`);
34+
}
35+
36+
this._extensionId = res.headers.get('lambda-extension-identifier');
37+
return res.headers.get('lambda-extension-identifier');
38+
}
39+
40+
/**
41+
* Advances the extension to the next event.
42+
* @param extensionId The extension identifier.
43+
* @returns The event data, or null if the extension is not ready to process events.
44+
*/
45+
public async next(): Promise<void> {
46+
if (!this._extensionId) {
47+
throw new Error('Extension ID is not set');
48+
}
49+
50+
const res = await fetch(`${this._baseUrl}/event/next`, {
51+
headers: {
52+
'Lambda-Extension-Identifier': this._extensionId,
53+
'Content-Type': 'application/json',
54+
},
55+
});
56+
57+
if (!res.ok) {
58+
throw new Error(`Failed to advance to next event: ${await res.text()}`);
59+
}
60+
61+
const event = await res.json();
62+
63+
console.log('EXTENSION EVENT', event);
64+
}
65+
66+
/**
67+
* Reports an error to the extension API.
68+
* @param extensionId The extension identifier.
69+
* @param phase The phase of the extension.
70+
* @param err The error to report.
71+
*/
72+
public async error(phase: string, err: Error): Promise<never> {
73+
if (!this._extensionId) {
74+
throw new Error('Extension ID is not set');
75+
}
76+
77+
const errorType = `Extension.${err.name || 'UnknownError'}`;
78+
79+
const res = await fetch(`${this._baseUrl}/${phase}/error`, {
80+
method: 'POST',
81+
body: JSON.stringify({
82+
errorMessage: err.message || err.toString(),
83+
errorType,
84+
stackTrace: [err.stack],
85+
}),
86+
headers: {
87+
'Content-Type': 'application/json',
88+
'Lambda-Extension-Identifier': this._extensionId,
89+
'Lambda-Extension-Function-Error': errorType,
90+
},
91+
});
92+
93+
if (!res.ok) {
94+
throw new Error(`Failed to report error: ${await res.text()}`);
95+
}
96+
97+
throw err;
98+
}
99+
100+
/**
101+
* Starts the Sentry tunnel.
102+
*/
103+
public startSentryTunnel(): void {
104+
const server = http.createServer(async (req, res) => {
105+
if (req.url?.startsWith('/envelope')) {
106+
try {
107+
const buf = await buffer(req);
108+
const envelopeBytes = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
109+
const envelope = new TextDecoder().decode(envelopeBytes);
110+
const piece = envelope.split('\n')[0];
111+
const header = JSON.parse(piece ?? '{}') as { dsn?: string };
112+
const dsn = new URL(header.dsn || '');
113+
const projectId = dsn.pathname.replace('/', '');
114+
const upstreamSentryUrl = `https://${dsn.hostname}/api/${projectId}/envelope/`;
115+
116+
console.log('tunneling to sentry', { upstreamSentryUrl });
117+
console.log('headers', req.headers);
118+
119+
fetch(upstreamSentryUrl, {
120+
method: 'POST',
121+
body: envelopeBytes,
122+
}).catch(err => {
123+
console.error('error tunneling to sentry', err);
124+
});
125+
126+
res.writeHead(200, { 'Content-Type': 'application/json' });
127+
res.end(JSON.stringify({}));
128+
} catch (e) {
129+
console.error('error tunneling to sentry', e);
130+
res.writeHead(500, { 'Content-Type': 'application/json' });
131+
res.end(JSON.stringify({ error: 'error tunneling to sentry' }));
132+
}
133+
}
134+
});
135+
136+
server.listen(9000, () => {
137+
console.log('server listening on port 9000');
138+
});
139+
}
140+
}

packages/aws-serverless/src/sentry-extension/extensions-api.ts

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)