@@ -2,10 +2,11 @@ import * as crypto from 'crypto';
2
2
import * as cdk from 'aws-cdk-lib' ;
3
3
import * as events from 'aws-cdk-lib/aws-events' ;
4
4
import * as targets from 'aws-cdk-lib/aws-events-targets' ;
5
+ import * as iam from 'aws-cdk-lib/aws-iam' ;
5
6
import * as sns from 'aws-cdk-lib/aws-sns' ;
6
7
import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions' ;
7
- // import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
8
- // import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks';
8
+ import * as sfn from 'aws-cdk-lib/aws-stepfunctions' ;
9
+ import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks' ;
9
10
import { Construct } from 'constructs' ;
10
11
11
12
export interface NotificationsProperty {
@@ -34,7 +35,89 @@ export class LambdaFunctionInvokeErrorNotificationStack extends cdk.Stack {
34
35
topic . addSubscription ( new subscriptions . EmailSubscription ( email ) ) ;
35
36
}
36
37
37
- // EventBridgeルールの作成
38
+ // Prepare Message
39
+ const prepareMessage : sfn . Pass = new sfn . Pass ( this , 'PrepareMessage' , {
40
+ parameters : {
41
+ Subject : sfn . JsonPath . format ( '😵 [Failur] AWS Lambda Function Invocation Failur Notification [{}][{}]' ,
42
+ sfn . JsonPath . stringAt ( '$.account' ) ,
43
+ sfn . JsonPath . stringAt ( '$.region' ) ,
44
+ ) ,
45
+ Message : sfn . JsonPath . format ( 'Account : {}\nRegion : {}\nFunction : {}\nErrorMessage : {}\nTrace : \n{}' ,
46
+ sfn . JsonPath . stringAt ( '$.account' ) ,
47
+ sfn . JsonPath . stringAt ( '$.region' ) ,
48
+ sfn . JsonPath . stringAt ( '$.detail.requestContext.functionArn' ) ,
49
+ sfn . JsonPath . stringAt ( '$.detail.responsePayload.errorMessage' ) ,
50
+ sfn . JsonPath . stringAt ( '$.Prepare.Concatenated.Trace' ) ,
51
+ ) ,
52
+ } ,
53
+ resultPath : '$.Prepare.Sns.Topic' ,
54
+ } ) ;
55
+
56
+ const init : sfn . Pass = new sfn . Pass ( this , 'Init' , {
57
+ result : sfn . Result . fromString ( '' ) ,
58
+ resultPath : '$.Prepare.Concatenated.Trace' ,
59
+ } ) ;
60
+
61
+ const traceLinces : sfn . Pass = new sfn . Pass ( this , 'TraceLinces' , {
62
+ parameters : {
63
+ Lines : sfn . JsonPath . stringAt ( '$.detail.responsePayload.trace' ) ,
64
+ } ,
65
+ resultPath : '$.TempTrace' ,
66
+ } ) ;
67
+
68
+ init . next ( traceLinces ) ;
69
+
70
+ const getTraceLine = new sfn . Pass ( this , 'GetTraceLine' , {
71
+ parameters : {
72
+ Line : sfn . JsonPath . arrayGetItem ( sfn . JsonPath . stringAt ( '$.TempTrace.Lines' ) , 0 ) ,
73
+ } ,
74
+ resultPath : '$.Temp.GetTrace' ,
75
+ } ) ;
76
+
77
+ const checkUntreatedTranceLinesExist : sfn . Choice = new sfn . Choice ( this , 'CheckUntreatedTranceLinesExist' )
78
+ . when ( sfn . Condition . isPresent ( '$.TempTrace.Lines[0]' ) , getTraceLine )
79
+ . otherwise ( prepareMessage ) ;
80
+
81
+ traceLinces . next ( checkUntreatedTranceLinesExist ) ;
82
+
83
+ const concatenateValue : sfn . Pass = new sfn . Pass ( this , 'Concatenate' , {
84
+ parameters : {
85
+ Trace : sfn . JsonPath . format ( '{}{}\n' , sfn . JsonPath . stringAt ( '$.Prepare.Concatenated.Trace' ) , sfn . JsonPath . stringAt ( '$.Temp.GetTrace.Line' ) ) ,
86
+ } ,
87
+ resultPath : '$.Prepare.Concatenated' ,
88
+ } ) ;
89
+
90
+ getTraceLine . next ( concatenateValue ) ;
91
+
92
+ const untreatedTranceLines : sfn . Pass = new sfn . Pass ( this , 'UntreatedTranceLines' , {
93
+ parameters : {
94
+ Lines : sfn . JsonPath . stringAt ( '$.TempTrace.Lines[1:]' ) ,
95
+ } ,
96
+ resultPath : '$.TempTrace' ,
97
+ } ) ;
98
+
99
+ concatenateValue . next ( untreatedTranceLines ) ;
100
+
101
+ untreatedTranceLines . next ( checkUntreatedTranceLinesExist ) ;
102
+
103
+ const sendNotification : tasks . SnsPublish = new tasks . SnsPublish ( this , 'SendNotification' , {
104
+ topic : topic ,
105
+ inputPath : '$.Prepare.Sns.Topic' ,
106
+ subject : sfn . JsonPath . stringAt ( '$.Subject' ) ,
107
+ message : sfn . TaskInput . fromJsonPathAt ( '$.Message' ) ,
108
+ resultPath : '$.Result.Sns.Topic' ,
109
+ } ) ;
110
+
111
+ prepareMessage . next ( sendNotification ) ;
112
+
113
+ // Step Functions State Machine
114
+ const stateMachine : sfn . StateMachine = new sfn . StateMachine ( this , 'StateMachine' , {
115
+ stateMachineName : `lambda-func-invoke-error-notification-${ random } -state-machine` ,
116
+ timeout : cdk . Duration . minutes ( 5 ) ,
117
+ definitionBody : sfn . DefinitionBody . fromChainable ( init ) ,
118
+ } ) ;
119
+
120
+ // EventBridge Rule
38
121
new events . Rule ( this , 'LambdaFunctionInvokeErrorCatchRule' , {
39
122
ruleName : `lambda-func-invoke-error-catch-${ random } -rule` ,
40
123
eventPattern : {
@@ -49,7 +132,26 @@ export class LambdaFunctionInvokeErrorNotificationStack extends cdk.Stack {
49
132
} ,
50
133
} ,
51
134
targets : [
52
- new targets . SnsTopic ( topic ) ,
135
+ new targets . SfnStateMachine ( stateMachine , {
136
+ role : new iam . Role ( this , 'StartExecMachineRole' , {
137
+ roleName : `lambda-func-invoke-error-start-exec-machine-${ random } -role` ,
138
+ description : 'lambda func invoke error start exec machine (send notification).' ,
139
+ assumedBy : new iam . ServicePrincipal ( 'events.amazonaws.com' ) ,
140
+ inlinePolicies : {
141
+ 'states-start-execution-policy' : new iam . PolicyDocument ( {
142
+ statements : [
143
+ new iam . PolicyStatement ( {
144
+ effect : iam . Effect . ALLOW ,
145
+ actions : [
146
+ 'states:StartExecution' ,
147
+ ] ,
148
+ resources : [ '*' ] ,
149
+ } ) ,
150
+ ] ,
151
+ } ) ,
152
+ } ,
153
+ } ) ,
154
+ } ) ,
53
155
] ,
54
156
} ) ;
55
157
}
0 commit comments