1import * as Alchemy from "alchemy";
2import * as AWS from "alchemy/AWS";
3import * as Output from "alchemy/Output";
4import * as Effect from "effect/Effect";
5import JobFunction from "./src/JobFunction.ts";
6
7// AWS.providers() already provides AWSEnvironment from the SSO profile
8// named by $AWS_PROFILE (defaults to "default"). To pin a different
9// profile per stage, wrap with `Layer.provide(AWS.makeEnvironment({...}))`.
10const aws = AWS.providers();
11const dashboardRegion = process.env.AWS_REGION ?? "us-west-2";
12
13export default Alchemy.Stack(
14 "JobLambda",
15 {
16 providers: aws,
17 state: Alchemy.localState(),
18 },
19 Effect.gen(function* () {
20 const func = yield* JobFunction;
21 const dashboard = yield* AWS.CloudWatch.Dashboard("JobDashboard", {
22 DashboardBody: func.functionName.pipe(
23 Output.map((functionName) => ({
24 widgets: [
25 {
26 type: "metric",
27 x: 0,
28 y: 0,
29 width: 12,
30 height: 6,
31 properties: {
32 title: "Lambda Invocations and Errors",
33 region: dashboardRegion,
34 stat: "Sum",
35 period: 300,
36 metrics: [
37 ["AWS/Lambda", "Invocations", "FunctionName", functionName],
38 ["AWS/Lambda", "Errors", "FunctionName", functionName],
39 ],
40 },
41 },
42 {
43 type: "metric",
44 x: 12,
45 y: 0,
46 width: 12,
47 height: 6,
48 properties: {
49 title: "Lambda Duration",
50 region: dashboardRegion,
51 stat: "Average",
52 period: 300,
53 metrics: [
54 ["AWS/Lambda", "Duration", "FunctionName", functionName],
55 ],
56 },
57 },
58 ],
59 })),
60 ),
61 });
62 const alarm = yield* AWS.CloudWatch.Alarm("JobFunctionErrorsAlarm", {
63 AlarmDescription:
64 "Alerts when the example Lambda function reports errors.",
65 MetricName: "Errors",
66 Namespace: "AWS/Lambda",
67 Statistic: "Sum",
68 Period: 300,
69 EvaluationPeriods: 1,
70 Threshold: 1,
71 ComparisonOperator: "GreaterThanOrEqualToThreshold",
72 TreatMissingData: "notBreaching",
73 Dimensions: [
74 {
75 Name: "FunctionName",
76 Value: func.functionName,
77 },
78 ],
79 });
80 return {
81 url: Output.interpolate`${func.functionUrl}?jobId=foo`,
82 dashboardName: dashboard.dashboardName,
83 alarmName: alarm.alarmName,
84 };
85 }),
86);