Skip to content

Commit ddf4e24

Browse files
author
Dinesh Sajwan
committed
feat(baseclass): added base class with observability functionality
1 parent e0f251b commit ddf4e24

File tree

11 files changed

+300
-242
lines changed

11 files changed

+300
-242
lines changed

src/common/base-class/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# BaseClass
2+
<!--BEGIN STABILITY BANNER-->
3+
4+
---
5+
6+
![Stability: Experimental](https://img.shields.io/badge/stability-Experimental-important.svg?style=for-the-badge)
7+
8+
> All classes are under active development and subject to non-backward compatible changes or removal in any
9+
> future version. These are not subject to the [Semantic Versioning](https://semver.org/) model.
10+
> This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package.
11+
12+
---
13+
<!--END STABILITY BANNER-->
14+
15+
The Baseclass includes the basic building blocks of the AWS Generative AI CDK Constructs library. It defines the core funnctions that are used in the rest of the constructs. The purpose is to standardize and accelerate development for builders.
16+
17+

src/common/base-class/base-class.ts

Lines changed: 101 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
1111
* and limitations under the License.
1212
*/
13-
import { Construct } from 'constructs';
14-
import { version } from '../helpers/utils';
15-
import * as lambda from 'aws-cdk-lib/aws-lambda';
1613
import { Stack } from 'aws-cdk-lib';
14+
import * as appsync from 'aws-cdk-lib/aws-appsync';
15+
import * as lambda from 'aws-cdk-lib/aws-lambda';
16+
import * as logs from 'aws-cdk-lib/aws-logs';
17+
import { Construct } from 'constructs';
18+
import { version } from '../helpers/utils';
19+
1720

1821
export interface BaseClassProps {
19-
/**
22+
/**
2023
* Value will be appended to resources name.
2124
*
2225
* @default - _dev
@@ -36,51 +39,116 @@ export interface BaseClassProps {
3639
*/
3740
readonly enableOperationalMetric?: boolean;
3841

39-
lambdaFunctions: lambda.DockerImageFunction[]
40-
constructorName: string
41-
constructId: string
42+
/**
43+
* name of the construct.
44+
*
45+
*/
46+
readonly constructorName: string;
47+
48+
/**
49+
* construct id.
50+
*
51+
*/
52+
readonly constructId: string;
53+
54+
/**
55+
* Enable observability. Warning: associated cost with the services
56+
* used. Best practice to enable by default.
57+
*
58+
* @default - true
59+
*/
60+
readonly observability?: boolean;
4261
}
4362

4463
export class BaseClass extends Construct {
4564

46-
readonly CONSTRUCT_TRACKING_CODE = 'uksb-1tupboc45';
65+
/**
66+
* construct tracking code, added in template description
67+
*/
68+
readonly constructTrackingCode = 'uksb-1tupboc45';
4769

48-
//static readonly solutionId = `genai_cdk_${version}/${this.constructor.name}/${id}`;
70+
/**
71+
* Value will be appended to resources name.
72+
*
73+
* @default - _dev
74+
*/
75+
stage!: string;
4976

50-
stage!: string;
77+
/**
78+
* enable disable lambda tracing
79+
*
80+
* @default - Active
81+
*/
82+
lambdaTracing: lambda.Tracing=lambda.Tracing.ACTIVE;
5183

52-
constructor(scope: Construct, id: string) {
53-
super(scope, id)
84+
/**
85+
* enable disable xray tracing
86+
*
87+
* @default - True
88+
*/
89+
enablexray: boolean = true;
5490

55-
}
91+
/**
92+
* Default log config for all constructs
93+
*/
94+
fieldLogLevel:appsync.FieldLogLevel=appsync.FieldLogLevel.ALL;
95+
96+
/**
97+
* Default log retention config for all constructs
98+
*/
99+
retention: logs.RetentionDays=logs.RetentionDays.TEN_YEARS;
100+
101+
102+
constructor(scope: Construct, id: string) {
103+
super(scope, id);
56104

57-
public updateEnvSuffix(props: BaseClassProps){
58-
let stage = '-dev';
59-
if (props?.stage) {
60-
stage = props.stage;
61-
}
62-
this.stage = stage;
63105
}
64106

65-
public updateConstructTrackingCode(props: BaseClassProps,scope: Construct){
66-
const enableOperationalMetric =
67-
props.enableOperationalMetric !== undefined &&
107+
//overwrite default env suffix
108+
protected updateEnvSuffix(props: BaseClassProps) {
109+
let stage = '-dev';
110+
if (props?.stage) {
111+
stage = props.stage;
112+
}
113+
this.stage = stage;
114+
}
115+
116+
/*
117+
* If enableOperationalMetric is set to true,
118+
* update template description with construct tracking code and
119+
* add AWS_SDK_UA_APP_ID to user agent on aws sdk.
120+
*/
121+
protected updateConstructTrackingCode(props: BaseClassProps, scope: Construct, lambdaFunctions: lambda.DockerImageFunction[],
122+
) {
123+
const solutionId = `genai_cdk_${version}/${props.constructorName}/${props.constructId}`;
124+
125+
const enableOperationalMetric =
126+
props.enableOperationalMetric !== undefined &&
68127
props.enableOperationalMetric !== null ? props.enableOperationalMetric : true;
69128

70129
if (enableOperationalMetric) {
71-
72-
// iterate props.lambdaFunction array
73-
const solutionId = `genai_cdk_${version}/${props.constructorName}/${props.constructId}`;
74-
for(let lambdaFunction of props.lambdaFunctions)
75-
{
130+
if (lambdaFunctions
131+
&& lambdaFunctions.length > 0) {
132+
for (let lambdaFunction of lambdaFunctions) {
76133
lambdaFunction.addEnvironment(
77-
'AWS_SDK_UA_APP_ID', solutionId,
78-
);
134+
'AWS_SDK_UA_APP_ID', solutionId,
135+
);
136+
}
79137
}
80-
// ADD unique key in CFN stack
81-
Stack.of(scope).templateOptions.description =solutionId
138+
// ADD unique key in template description
139+
// format (tracking id:usbxxxx) (version:1.xx) (construct name:awsappsyncxxxx) (construct id:awsappsyncxxxx)
140+
Stack.of(scope).templateOptions.description =`(tracking id:${this.constructTrackingCode}) (version:${version}) (construct name:${props.constructorName}) (construct id:${props.constructId})`;
141+
142+
};
143+
}
82144

145+
// observability
146+
protected addObservabilityToConstruct(props: BaseClassProps) {
147+
if (props.observability == false) {
148+
this.enablexray = false;
149+
this.lambdaTracing = lambda.Tracing.DISABLED;
150+
this.fieldLogLevel= appsync.FieldLogLevel.NONE,
151+
this.retention= logs.RetentionDays.TEN_YEARS;
83152
};
84153
}
85-
86-
}
154+
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ export { version } from './common/helpers/utils';
2424
export * from './common/props/DockerLambdaCustomProps';
2525
export * from './common/props/LangchainProps';
2626
export * from './common/props/AdapterProps';
27+
export * from './common/base-class';

src/patterns/gen-ai/aws-contentgen-appsync-lambda/index.ts

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ import * as logs from 'aws-cdk-lib/aws-logs';
2323
import * as s3 from 'aws-cdk-lib/aws-s3';
2424
import { NagSuppressions } from 'cdk-nag';
2525
import { Construct } from 'constructs';
26+
import { BaseClass, BaseClassProps } from '../../../common/base-class';
2627
import { buildDockerLambdaFunction } from '../../../common/helpers/lambda-builder-helper';
2728
import * as s3_bucket_helper from '../../../common/helpers/s3-bucket-helper';
28-
import { version, lambdaMemorySizeLimiter } from '../../../common/helpers/utils';
29+
import { lambdaMemorySizeLimiter } from '../../../common/helpers/utils';
2930
import * as vpc_helper from '../../../common/helpers/vpc-helper';
3031
import { DockerLambdaCustomProps } from '../../../common/props/DockerLambdaCustomProps';
3132

@@ -127,7 +128,7 @@ export interface ContentGenerationAppSyncLambdaProps {
127128
/**
128129
* @summary The ContentGenerationAppSyncLambda class.
129130
*/
130-
export class ContentGenerationAppSyncLambda extends Construct {
131+
export class ContentGenerationAppSyncLambda extends BaseClass {
131132
/**
132133
* Returns the instance of ec2.IVpc used by the construct
133134
*/
@@ -170,27 +171,16 @@ export class ContentGenerationAppSyncLambda extends Construct {
170171
constructor(scope: Construct, id: string, props: ContentGenerationAppSyncLambdaProps) {
171172
super(scope, id);
172173

173-
// stage
174-
let stage = '-dev';
175-
if (props?.stage) {
176-
stage = props.stage;
177-
}
178-
179-
// observability
180-
let lambda_tracing = lambda.Tracing.ACTIVE;
181-
let enable_xray = true;
182-
let api_log_config = {
183-
fieldLogLevel: appsync.FieldLogLevel.ALL,
184-
retention: logs.RetentionDays.TEN_YEARS,
174+
const baseProps: BaseClassProps={
175+
stage: props.stage,
176+
enableOperationalMetric: props.enableOperationalMetric,
177+
constructorName: this.constructor.name,
178+
constructId: id,
179+
observability: props.observability,
185180
};
186-
if (props.observability == false) {
187-
enable_xray = false;
188-
lambda_tracing = lambda.Tracing.DISABLED;
189-
api_log_config = {
190-
fieldLogLevel: appsync.FieldLogLevel.NONE,
191-
retention: logs.RetentionDays.TEN_YEARS,
192-
};
193-
}
181+
182+
this.updateEnvSuffix(baseProps);
183+
this.addObservabilityToConstruct(baseProps);
194184

195185
vpc_helper.CheckVpcProps(props);
196186
s3_bucket_helper.CheckS3Props({
@@ -211,7 +201,7 @@ export class ContentGenerationAppSyncLambda extends Construct {
211201
this.securityGroup = new ec2.SecurityGroup(this, 'securityGroup', {
212202
vpc: this.vpc,
213203
allowAllOutbound: true,
214-
securityGroupName: 'securityGroup' + stage,
204+
securityGroupName: 'securityGroup' + this.stage,
215205
});
216206
}
217207

@@ -230,7 +220,7 @@ export class ContentGenerationAppSyncLambda extends Construct {
230220
// bucket for storing server access logging
231221
const serverAccessLogBucket = new s3.Bucket(
232222
this,
233-
'serverAccessLogBucket' + stage,
223+
'serverAccessLogBucket' + this.stage,
234224
{
235225
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
236226
encryption: s3.BucketEncryption.S3_MANAGED,
@@ -250,10 +240,10 @@ export class ContentGenerationAppSyncLambda extends Construct {
250240
if (!props.existingGeneratedAssetsBucketObj) {
251241
let tmpBucket: s3.Bucket;
252242
if (!props.generatedAssetsBucketProps) {
253-
tmpBucket = new s3.Bucket(this, 'generatedAssetsBucket' + stage, {
243+
tmpBucket = new s3.Bucket(this, 'generatedAssetsBucket' + this.stage, {
254244
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
255245
encryption: s3.BucketEncryption.S3_MANAGED,
256-
bucketName: 'generated-asset-bucket' + stage + '-' + Aws.ACCOUNT_ID,
246+
bucketName: 'generated-asset-bucket' + this.stage + '-' + Aws.ACCOUNT_ID,
257247
serverAccessLogsBucket: serverAccessLogBucket,
258248
enforceSSL: true,
259249
versioned: true,
@@ -266,7 +256,7 @@ export class ContentGenerationAppSyncLambda extends Construct {
266256
} else {
267257
tmpBucket = new s3.Bucket(
268258
this,
269-
'generatedAssetsBucket' + stage,
259+
'generatedAssetsBucket' + this.stage,
270260
props.generatedAssetsBucketProps,
271261
);
272262
}
@@ -284,7 +274,7 @@ export class ContentGenerationAppSyncLambda extends Construct {
284274
this,
285275
'generateImageGraphqlApi',
286276
{
287-
name: 'generateImageGraphqlApi' + stage,
277+
name: 'generateImageGraphqlApi' + this.stage,
288278
definition: appsync.Definition.fromFile(
289279
path.join(
290280
__dirname,
@@ -302,8 +292,11 @@ export class ContentGenerationAppSyncLambda extends Construct {
302292
},
303293
],
304294
},
305-
xrayEnabled: enable_xray,
306-
logConfig: api_log_config,
295+
xrayEnabled: this.enablexray,
296+
logConfig: {
297+
fieldLogLevel: this.fieldLogLevel,
298+
retention: this.retention,
299+
},
307300
},
308301
);
309302

@@ -345,9 +338,9 @@ export class ContentGenerationAppSyncLambda extends Construct {
345338
if (!props.existingBusInterface) {
346339
this.generatedImageBus = new events.EventBus(
347340
this,
348-
'generateImageEventBus' + stage,
341+
'generateImageEventBus' + this.stage,
349342
{
350-
eventBusName: 'generateImageEventBus' + stage,
343+
eventBusName: 'generateImageEventBus' + this.stage,
351344
},
352345
);
353346
} else {
@@ -356,10 +349,10 @@ export class ContentGenerationAppSyncLambda extends Construct {
356349

357350
// create httpdatasource with generate_image_graphql_api
358351
const event_bridge_datasource = this.graphqlApi.addEventBridgeDataSource(
359-
'generateImageEventBridgeDataSource' + stage,
352+
'generateImageEventBridgeDataSource' + this.stage,
360353
this.generatedImageBus,
361354
{
362-
name: 'generateImageEventBridgeDataSource' + stage,
355+
name: 'generateImageEventBridgeDataSource' + this.stage,
363356
},
364357
);
365358

@@ -488,10 +481,10 @@ export class ContentGenerationAppSyncLambda extends Construct {
488481
'../../../../lambda/aws-contentgen-appsync-lambda/src',
489482
),
490483
),
491-
functionName: 'lambda_generate_image' + stage,
484+
functionName: 'lambda_generate_image' + this.stage,
492485
description: 'Lambda function for generating image',
493486
vpc: this.vpc,
494-
tracing: lambda_tracing,
487+
tracing: this.lambdaTracing,
495488
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
496489
securityGroups: [this.securityGroup],
497490
memorySize: lambdaMemorySizeLimiter(this, 1_769 * 4),
@@ -510,23 +503,16 @@ export class ContentGenerationAppSyncLambda extends Construct {
510503
};
511504

512505
const generate_image_function = buildDockerLambdaFunction(this,
513-
'lambda_content_generation' + stage,
506+
'lambda_content_generation' + this.stage,
514507
construct_docker_lambda_props,
515508
props.customDockerLambdaProps,
516509
);
517510

518511
generate_image_function.currentVersion;
519512

520-
const enableOperationalMetric =
521-
props.enableOperationalMetric !== undefined && props.enableOperationalMetric !== null ? props.enableOperationalMetric : true;
513+
const lambdaFunctions=[generate_image_function];
514+
this.updateConstructTrackingCode( baseProps, scope, lambdaFunctions);
522515

523-
if (enableOperationalMetric) {
524-
const solutionId = `genai_cdk_${version}/${this.constructor.name}/${id}`;
525-
generate_image_function.addEnvironment(
526-
'AWS_SDK_UA_APP_ID',
527-
solutionId,
528-
);
529-
}
530516

531517
// Add GraphQl permissions to the IAM role for the Lambda function
532518
generate_image_function.addToRolePolicy(
@@ -575,7 +561,7 @@ export class ContentGenerationAppSyncLambda extends Construct {
575561
),
576562
});
577563

578-
const rule = new events.Rule(this, 'textToImageRule' + stage, {
564+
const rule = new events.Rule(this, 'textToImageRule' + this.stage, {
579565
description: 'Rule to trigger textToImage function',
580566
eventBus: this.generatedImageBus,
581567
eventPattern: {

0 commit comments

Comments
 (0)