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