@ashishpandeyone/cdk-lambda-web-function 0.1.2 → 0.1.4
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/.jsii +1250 -185
- package/.jsii.tabl.json +1 -1
- package/API.md +1406 -131
- package/README.md +70 -8
- package/assets/web-function-provider/index.js +26 -26
- package/lib/nodejs-web-function.js +1 -1
- package/lib/private/code-bucket.d.ts +3 -0
- package/lib/private/code-bucket.js +18 -2
- package/lib/private/metrics.d.ts +23 -0
- package/lib/private/metrics.js +49 -0
- package/lib/private/provider-protocol.d.ts +30 -0
- package/lib/private/provider-protocol.js +13 -2
- package/lib/private/provider.d.ts +4 -3
- package/lib/private/provider.js +36 -5
- package/lib/private/regional-alarm.d.ts +23 -0
- package/lib/private/regional-alarm.js +40 -0
- package/lib/private/rollback.d.ts +9 -0
- package/lib/private/rollback.js +3 -0
- package/lib/private/traffic-shift.d.ts +2 -0
- package/lib/private/traffic-shift.js +3 -2
- package/lib/web-function-deployment.d.ts +64 -0
- package/lib/web-function-deployment.js +41 -6
- package/lib/web-function-endpoint.d.ts +46 -0
- package/lib/web-function-endpoint.js +155 -2
- package/lib/web-function-grants.d.ts +7 -1
- package/lib/web-function-grants.js +15 -7
- package/lib/web-function-revision.js +1 -1
- package/lib/web-function.d.ts +105 -5
- package/lib/web-function.js +126 -9
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -156,6 +156,25 @@ const signed = await signer.sign(
|
|
|
156
156
|
const response = await fetch(`https://${host}/`, { headers: signed.headers });
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
+
### Functions defined elsewhere
|
|
160
|
+
|
|
161
|
+
Import a Web Function defined in another stack or app to grant access to it, read its metrics, or reference its revisions:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
const orders = WebFunction.fromWebFunctionArn(this, 'Orders', 'arn:aws:lambda:us-east-1:111122223333:web-function/orders');
|
|
165
|
+
orders.grantInvoke(consumerRole); // every endpoint of the function
|
|
166
|
+
|
|
167
|
+
const live = WebFunction.fromWebFunctionAttributes(this, 'Live', {
|
|
168
|
+
webFunctionName: 'orders', // in this stack's account and region
|
|
169
|
+
endpointName: 'live', // grantInvoke allows this endpoint only
|
|
170
|
+
});
|
|
171
|
+
live.metricConcurrentRequests().createAlarm(this, 'Busy', { threshold: 60, evaluationPeriods: 3 });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
An imported function's metrics default to its own region. Its endpoints, revisions and log groups stay with the stack that defines it.
|
|
175
|
+
|
|
176
|
+
`grantInvoke` adds to the caller's IAM policy, which is all a caller in the function's account needs. A caller in another account also needs the function's resource policy to allow it, which this library doesn't manage yet.
|
|
177
|
+
|
|
159
178
|
## Configuration
|
|
160
179
|
|
|
161
180
|
```ts
|
|
@@ -207,7 +226,9 @@ new NodejsWebFunction(this, 'Api', {
|
|
|
207
226
|
|
|
208
227
|
`code` takes any `lambda.Code` that produces a zip in S3: `fromAsset`, `fromBucket`/`fromBucketV2`, `fromCustomCommand`, `fromDockerBuild`. Inline code and container images fail at synth time.
|
|
209
228
|
|
|
210
|
-
Lambda Web Functions download code as the `lambda.amazonaws.com` service principal, from a **versioned** bucket, and the CDK bootstrap bucket allows neither. So each stack gets a small code bucket, and the code is copied into it on deploy.
|
|
229
|
+
Lambda Web Functions download code as the `lambda.amazonaws.com` service principal, from a **versioned** bucket, and the CDK bootstrap bucket allows neither. So each stack gets a small code bucket, and the code is copied into it on deploy. The bucket is emptied and deleted with the stack.
|
|
230
|
+
|
|
231
|
+
Code copies, log groups in other regions, revision cleanup and the bucket's emptying run in one custom resource Lambda per stack. Its logs go to a log group the stack owns, kept for a month and deleted with the stack.
|
|
211
232
|
|
|
212
233
|
## Revisions
|
|
213
234
|
|
|
@@ -250,18 +271,18 @@ fn.addEndpoint('Stable', { authType: WebFunctionAuthType.AWS_IAM, revision: prev
|
|
|
250
271
|
By default an endpoint moves all its traffic to a new revision at once. With `deployment`, it moves in steps instead, watching CloudWatch alarms: if one goes into ALARM, the endpoint goes back to the revision it served before and the deployment fails, so CloudFormation rolls the stack back.
|
|
251
272
|
|
|
252
273
|
```ts
|
|
253
|
-
// errorRate: a cloudwatch.IAlarm, for example on the share of 5xx responses
|
|
254
274
|
const api = new WebFunction(this, 'Api', {
|
|
255
275
|
runtime: lambda.Runtime.NODEJS_24_X,
|
|
256
276
|
code: lambda.Code.fromAsset('dist'),
|
|
257
277
|
authType: WebFunctionAuthType.AWS_IAM,
|
|
258
278
|
endpoint: {
|
|
259
|
-
// 10% of the traffic for 10 minutes, then all of it.
|
|
260
|
-
deployment: WebFunctionDeployment.canary({ percent: 10, bake: Duration.minutes(10),
|
|
279
|
+
// 10% of the traffic for 10 minutes, then all of it; back if more than 2% of requests get a 5XX.
|
|
280
|
+
deployment: WebFunctionDeployment.canary({ percent: 10, bake: Duration.minutes(10), rollbackOn: { serverErrorRate: 2 } }),
|
|
261
281
|
},
|
|
262
282
|
});
|
|
263
283
|
|
|
264
|
-
// 25% more every 5 minutes. Each endpoint has its own deployment.
|
|
284
|
+
// 25% more every 5 minutes, watching an alarm of your own. Each endpoint has its own deployment.
|
|
285
|
+
// errorRate: any cloudwatch.IAlarm, e.g. on a metric your application publishes.
|
|
265
286
|
api.addEndpoint('Public', {
|
|
266
287
|
authType: WebFunctionAuthType.NONE,
|
|
267
288
|
deployment: WebFunctionDeployment.linear({ percent: 25, interval: Duration.minutes(5), alarms: [errorRate] }),
|
|
@@ -284,10 +305,52 @@ How it works:
|
|
|
284
305
|
- A deployment can take up to an hour: CloudFormation waits for it before it updates the endpoint. Deployments of different endpoints run in parallel.
|
|
285
306
|
- A canary or linear endpoint always moves to the current revision, so it can't also use `revision`, `additionalRevisions` or `routeTraffic()`. Use `allAtOnce()` to deploy a fix immediately, for example while an alarm is in ALARM.
|
|
286
307
|
|
|
287
|
-
|
|
308
|
+
#### Rollback alarms
|
|
309
|
+
|
|
310
|
+
`rollbackOn` makes the endpoint create alarms on its own error rates, and the deployment watches them alongside any `alarms` you pass:
|
|
311
|
+
|
|
312
|
+
| `rollbackOn` | Default | |
|
|
313
|
+
|---|---|---|
|
|
314
|
+
| `serverErrorRate` | none | roll back when more than this % of requests get a 5XX |
|
|
315
|
+
| `clientErrorRate` | none | the same for 4XX (including 429s from `rateLimit` and `maxEnvironments`) |
|
|
316
|
+
| `minimumRequests` | 10 | periods with fewer requests don't count, so one failed request out of two doesn't roll back |
|
|
317
|
+
| `period`, `evaluationPeriods` | 1 minute, 2 | consecutive periods over the threshold before rolling back |
|
|
318
|
+
|
|
319
|
+
- **One alarm per threshold in every region the endpoint serves from.** Metrics are published in the region that served the request, and an alarm can only watch metrics in its own region. The home region's alarm is a normal CloudFormation alarm; the others are created and deleted with the endpoint by a custom resource, and named `LambdaWeb-<function>-<endpoint>-5xx-rate` (or `-4xx-rate`). `endpoint.rollbackAlarms` lists them all, e.g. to add notifications to the home region's.
|
|
320
|
+
- **The alarms see the whole endpoint.** Lambda Web Function metrics have no revision dimension, so at 10% a new revision's errors are about a tenth of the endpoint's: set the threshold low enough to notice that, or alarm on metrics your application publishes with its version.
|
|
321
|
+
- **5XX includes the platform's 503s** while the endpoint scales up for a sudden burst, not only your application's errors.
|
|
322
|
+
- **A step should outlast the alarm.** CloudWatch needs `period` × `evaluationPeriods`, plus a couple of minutes of delay, to fire; the construct warns when a canary's bake or a linear interval is shorter.
|
|
288
323
|
|
|
289
324
|
The deployment runs in a few resources per stack, created on first use: two Lambda functions, a Step Functions state machine that calls them every 15 seconds, and a log group.
|
|
290
325
|
|
|
326
|
+
## Metrics
|
|
327
|
+
|
|
328
|
+
Endpoints and functions have helpers for their CloudWatch metrics (namespace `AWS/Lambda/Web`), like `lambda.Function`'s:
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
fn.endpoint.metricServerErrorRate().createAlarm(this, 'ErrorRate', { threshold: 1, evaluationPeriods: 3 });
|
|
332
|
+
fn.endpoint.metricRequestThrottles().createAlarm(this, 'Throttled', { threshold: 10, evaluationPeriods: 3 });
|
|
333
|
+
fn.metricConcurrentRequests().createAlarm(this, 'Saturated', { threshold: 60, evaluationPeriods: 3 });
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
| Endpoint | Metric |
|
|
337
|
+
|---|---|
|
|
338
|
+
| `metricRequests()` | `ExecutedRequests` (there's no separate 2XX count) |
|
|
339
|
+
| `metricClientErrors()`, `metricServerErrors()` | `HTTPResponseStatusClass4XX`, `HTTPResponseStatusClass5XX` |
|
|
340
|
+
| `metricClientErrorRate()`, `metricServerErrorRate()` | 4XX or 5XX as a % of requests (math expression) |
|
|
341
|
+
| `metricActiveEnvironments()` | `EndpointActiveEnvironments`, to compare with `maxEnvironments` |
|
|
342
|
+
| `metricRequestThrottles()`, `metricEnvironmentThrottles()` | 429s from `rateLimit` and from `maxEnvironments` |
|
|
343
|
+
|
|
344
|
+
| Function | Metric |
|
|
345
|
+
|---|---|
|
|
346
|
+
| `metricConcurrentRequests()` | `EnvironmentConcurrentRequests` (maximum), to compare with `maxConcurrencyPerEnvironment` |
|
|
347
|
+
| `metricMaxMemoryUsage()` | `EnvironmentMaxMemoryUsage` (maximum) |
|
|
348
|
+
| `metricActiveTime()`, `metricCpuTime()`, `metricResponseBytes()` | `EnvironmentActiveTime`, `EnvironmentCPUTime`, `ResponseBytes` |
|
|
349
|
+
|
|
350
|
+
- **Metrics stay in the region that served the request**; unlike logs, they aren't copied to the home region. Every helper takes `region`. Dashboards can show any region, but an alarm can only use metrics from its own stack's region.
|
|
351
|
+
- 4XX, 5XX and the throttle metrics only exist once they're non-zero: alarm on them with `treatMissingData: NOT_BREACHING`. The rate helpers count missing errors as 0.
|
|
352
|
+
- There's no latency metric. Publish one from your application (e.g. with the CloudWatch embedded metric format).
|
|
353
|
+
|
|
291
354
|
## Logs in every region
|
|
292
355
|
|
|
293
356
|
Web Functions log in two tiers:
|
|
@@ -322,10 +385,9 @@ new WebFunction(this, 'Api', {
|
|
|
322
385
|
|
|
323
386
|
## Limitations
|
|
324
387
|
|
|
325
|
-
- Not yet supported:
|
|
388
|
+
- Not yet supported: VPC access (network connectors), resource-policy permissions, KMS encryption, tracing, and a CloudFront origin.
|
|
326
389
|
- `cdk deploy --hotswap` and `cdk watch` don't support Web Functions.
|
|
327
390
|
- Quotas: 10 endpoints and about 50 revisions per function (Lambda cleans up older revisions automatically), and 10,000 requests per second per endpoint. Per account and region: 100,000 requests per second and 2,000 Arm64 vCPUs (each execution environment uses 2). The account quotas are adjustable, and new accounts start lower. See [Lambda quotas](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html).
|
|
328
|
-
- The stack's custom resource provider Lambda keeps its own log group after the stack is deleted, as with other CDK custom resources.
|
|
329
391
|
|
|
330
392
|
## Development
|
|
331
393
|
|