@@ -2,10 +2,11 @@ import * as crypto from 'crypto';
22import * as cdk from 'aws-cdk-lib' ;
33import * as events from 'aws-cdk-lib/aws-events' ;
44import * as targets from 'aws-cdk-lib/aws-events-targets' ;
5+ import * as iam from 'aws-cdk-lib/aws-iam' ;
56import * as sns from 'aws-cdk-lib/aws-sns' ;
67import * 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' ;
910import { Construct } from 'constructs' ;
1011
1112export interface NotificationsProperty {
@@ -34,7 +35,89 @@ export class LambdaFunctionInvokeErrorNotificationStack extends cdk.Stack {
3435 topic . addSubscription ( new subscriptions . EmailSubscription ( email ) ) ;
3536 }
3637
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
38121 new events . Rule ( this , 'LambdaFunctionInvokeErrorCatchRule' , {
39122 ruleName : `lambda-func-invoke-error-catch-${ random } -rule` ,
40123 eventPattern : {
@@ -49,7 +132,26 @@ export class LambdaFunctionInvokeErrorNotificationStack extends cdk.Stack {
49132 } ,
50133 } ,
51134 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+ } ) ,
53155 ] ,
54156 } ) ;
55157 }
0 commit comments