Skip to content

Commit 65abf6a

Browse files
author
Kamil Sobol
authored
Functions logging (#2245)
* Functions logging * changeset * more * conversation handler * conversation handler * this works * more tests * more tests * more tests * fix build * fix build * pr feedback * pr feedback * api * pr feedback
1 parent 72b2fe0 commit 65abf6a

27 files changed

+699
-2
lines changed

.changeset/poor-moons-refuse.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@aws-amplify/ai-constructs': minor
3+
'@aws-amplify/backend-ai': minor
4+
'@aws-amplify/backend-function': minor
5+
'@aws-amplify/backend': minor
6+
'@aws-amplify/platform-core': minor
7+
---
8+
9+
Add options to control log settings

package-lock.json

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ai-constructs/API.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
/// <reference types="node" />
88

99
import { AIConversationOutput } from '@aws-amplify/backend-output-schemas';
10+
import { ApplicationLogLevel } from 'aws-cdk-lib/aws-lambda';
1011
import { BackendOutputStorageStrategy } from '@aws-amplify/plugin-types';
1112
import * as bedrock from '@aws-sdk/client-bedrock-runtime';
1213
import { Construct } from 'constructs';
1314
import { FunctionResources } from '@aws-amplify/plugin-types';
1415
import * as jsonSchemaToTypeScript from 'json-schema-to-ts';
1516
import { ResourceProvider } from '@aws-amplify/plugin-types';
17+
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
1618

1719
declare namespace __export__conversation {
1820
export {
@@ -55,6 +57,10 @@ type ConversationHandlerFunctionProps = {
5557
region?: string;
5658
}>;
5759
memoryMB?: number;
60+
logging?: {
61+
level?: ApplicationLogLevel;
62+
retention?: RetentionDays;
63+
};
5864
outputStorageStrategy?: BackendOutputStorageStrategy<AIConversationOutput>;
5965
};
6066

packages/ai-constructs/src/conversation/conversation_handler_construct.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { ConversationHandlerFunction } from './conversation_handler_construct';
55
import { Template } from 'aws-cdk-lib/assertions';
66
import path from 'path';
77
import { StackMetadataBackendOutputStorageStrategy } from '@aws-amplify/backend-output-storage';
8+
import { ApplicationLogLevel } from 'aws-cdk-lib/aws-lambda';
9+
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
810

911
void describe('Conversation Handler Function construct', () => {
1012
void it('creates handler with log group with JWT token redacting policy', () => {
@@ -284,4 +286,41 @@ void describe('Conversation Handler Function construct', () => {
284286
}, new Error('memoryMB must be a whole number between 128 and 10240 inclusive'));
285287
});
286288
});
289+
290+
void describe('logging options', () => {
291+
void it('sets log level', () => {
292+
const app = new App();
293+
const stack = new Stack(app);
294+
new ConversationHandlerFunction(stack, 'conversationHandler', {
295+
models: [],
296+
logging: {
297+
level: ApplicationLogLevel.DEBUG,
298+
},
299+
});
300+
const template = Template.fromStack(stack);
301+
302+
template.hasResourceProperties('AWS::Lambda::Function', {
303+
LoggingConfig: {
304+
ApplicationLogLevel: 'DEBUG',
305+
LogFormat: 'JSON',
306+
},
307+
});
308+
});
309+
310+
void it('sets log retention', () => {
311+
const app = new App();
312+
const stack = new Stack(app);
313+
new ConversationHandlerFunction(stack, 'conversationHandler', {
314+
models: [],
315+
logging: {
316+
retention: RetentionDays.ONE_YEAR,
317+
},
318+
});
319+
const template = Template.fromStack(stack);
320+
321+
template.hasResourceProperties('AWS::Logs::LogGroup', {
322+
RetentionInDays: 365,
323+
});
324+
});
325+
});
287326
});

packages/ai-constructs/src/conversation/conversation_handler_construct.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import { Duration, Stack, Tags } from 'aws-cdk-lib';
77
import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam';
88
import {
9+
ApplicationLogLevel,
910
CfnFunction,
1011
Runtime as LambdaRuntime,
1112
LoggingFormat,
@@ -40,6 +41,12 @@ export type ConversationHandlerFunctionProps = {
4041
* Default is 512MB.
4142
*/
4243
memoryMB?: number;
44+
45+
logging?: {
46+
level?: ApplicationLogLevel;
47+
retention?: RetentionDays;
48+
};
49+
4350
/**
4451
* @internal
4552
*/
@@ -100,8 +107,9 @@ export class ConversationHandlerFunction
100107
bundleAwsSDK: !!this.props.entry,
101108
},
102109
loggingFormat: LoggingFormat.JSON,
110+
applicationLogLevelV2: this.props.logging?.level,
103111
logGroup: new LogGroup(this, 'conversationHandlerFunctionLogGroup', {
104-
retention: RetentionDays.INFINITE,
112+
retention: this.props.logging?.retention ?? RetentionDays.INFINITE,
105113
dataProtectionPolicy: new DataProtectionPolicy({
106114
identifiers: [
107115
new CustomDataIdentifier(

packages/backend-ai/API.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@ import { AiModel } from '@aws-amplify/data-schema-types';
88
import { ConstructFactory } from '@aws-amplify/plugin-types';
99
import { ConversationTurnEventVersion } from '@aws-amplify/ai-constructs/conversation';
1010
import { FunctionResources } from '@aws-amplify/plugin-types';
11+
import { LogLevel } from '@aws-amplify/plugin-types';
12+
import { LogRetention } from '@aws-amplify/plugin-types';
1113
import { ResourceProvider } from '@aws-amplify/plugin-types';
1214
import * as runtime from '@aws-amplify/ai-constructs/conversation/runtime';
1315

1416
declare namespace __export__conversation {
1517
export {
1618
ConversationHandlerFunctionFactory,
19+
ConversationHandlerFunctionLogLevel,
20+
ConversationHandlerFunctionLogRetention,
21+
ConversationHandlerFunctionLoggingOptions,
1722
DefineConversationHandlerFunctionProps,
1823
defineConversationHandlerFunction
1924
}
@@ -36,6 +41,18 @@ type ConversationHandlerFunctionFactory = ConstructFactory<ResourceProvider<Func
3641
readonly eventVersion: ConversationTurnEventVersion;
3742
};
3843

44+
// @public (undocumented)
45+
type ConversationHandlerFunctionLoggingOptions = {
46+
retention?: ConversationHandlerFunctionLogRetention;
47+
level?: ConversationHandlerFunctionLogLevel;
48+
};
49+
50+
// @public (undocumented)
51+
type ConversationHandlerFunctionLogLevel = LogLevel;
52+
53+
// @public (undocumented)
54+
type ConversationHandlerFunctionLogRetention = LogRetention;
55+
3956
// @public (undocumented)
4057
type ConversationTurnEvent = runtime.ConversationTurnEvent;
4158

@@ -54,6 +71,7 @@ type DefineConversationHandlerFunctionProps = {
5471
region?: string;
5572
}>;
5673
memoryMB?: number;
74+
logging?: ConversationHandlerFunctionLoggingOptions;
5775
};
5876

5977
// @public (undocumented)

packages/backend-ai/src/conversation/factory.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,41 @@ void describe('ConversationHandlerFactory', () => {
203203
MemorySize: 271,
204204
});
205205
});
206+
207+
void it('passes log level to construct', () => {
208+
const factory = defineConversationHandlerFunction({
209+
entry: './test-assets/with-default-entry/handler.ts',
210+
name: 'testHandlerName',
211+
models: [],
212+
logging: {
213+
level: 'debug',
214+
},
215+
});
216+
const lambda = factory.getInstance(getInstanceProps);
217+
const template = Template.fromStack(Stack.of(lambda.resources.lambda));
218+
template.resourceCountIs('AWS::Lambda::Function', 1);
219+
template.hasResourceProperties('AWS::Lambda::Function', {
220+
LoggingConfig: {
221+
ApplicationLogLevel: 'DEBUG',
222+
LogFormat: 'JSON',
223+
},
224+
});
225+
});
226+
227+
void it('passes log retention to construct', () => {
228+
const factory = defineConversationHandlerFunction({
229+
entry: './test-assets/with-default-entry/handler.ts',
230+
name: 'testHandlerName',
231+
models: [],
232+
logging: {
233+
retention: '1 day',
234+
},
235+
});
236+
const lambda = factory.getInstance(getInstanceProps);
237+
const template = Template.fromStack(Stack.of(lambda.resources.lambda));
238+
template.resourceCountIs('AWS::Lambda::Function', 1);
239+
template.hasResourceProperties('AWS::Logs::LogGroup', {
240+
RetentionInDays: 1,
241+
});
242+
});
206243
});

packages/backend-ai/src/conversation/factory.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
ConstructFactoryGetInstanceProps,
88
FunctionResources,
99
GenerateContainerEntryProps,
10+
LogLevel,
11+
LogRetention,
1012
ResourceProvider,
1113
} from '@aws-amplify/plugin-types';
1214
import {
@@ -17,6 +19,10 @@ import {
1719
import path from 'path';
1820
import { CallerDirectoryExtractor } from '@aws-amplify/platform-core';
1921
import { AiModel } from '@aws-amplify/data-schema-types';
22+
import {
23+
LogLevelConverter,
24+
LogRetentionConverter,
25+
} from '@aws-amplify/platform-core/cdk';
2026

2127
class ConversationHandlerFunctionGenerator
2228
implements ConstructContainerEntryGenerator
@@ -47,6 +53,18 @@ class ConversationHandlerFunctionGenerator
4753
outputStorageStrategy: this.outputStorageStrategy,
4854
memoryMB: this.props.memoryMB,
4955
};
56+
const logging: typeof constructProps.logging = {};
57+
if (this.props.logging?.level) {
58+
logging.level = new LogLevelConverter().toCDKLambdaApplicationLogLevel(
59+
this.props.logging.level
60+
);
61+
}
62+
if (this.props.logging?.retention) {
63+
logging.retention = new LogRetentionConverter().toCDKRetentionDays(
64+
this.props.logging.retention
65+
);
66+
}
67+
constructProps.logging = logging;
5068
const conversationHandlerFunction = new ConversationHandlerFunction(
5169
scope,
5270
this.props.name,
@@ -115,6 +133,15 @@ class DefaultConversationHandlerFunctionFactory
115133
};
116134
}
117135

136+
export type ConversationHandlerFunctionLogLevel = LogLevel;
137+
138+
export type ConversationHandlerFunctionLogRetention = LogRetention;
139+
140+
export type ConversationHandlerFunctionLoggingOptions = {
141+
retention?: ConversationHandlerFunctionLogRetention;
142+
level?: ConversationHandlerFunctionLogLevel;
143+
};
144+
118145
export type DefineConversationHandlerFunctionProps = {
119146
name: string;
120147
entry?: string;
@@ -128,6 +155,7 @@ export type DefineConversationHandlerFunctionProps = {
128155
* Default is 512MB.
129156
*/
130157
memoryMB?: number;
158+
logging?: ConversationHandlerFunctionLoggingOptions;
131159
};
132160

133161
/**
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import {
22
ConversationHandlerFunctionFactory,
3+
ConversationHandlerFunctionLogLevel,
4+
ConversationHandlerFunctionLogRetention,
5+
ConversationHandlerFunctionLoggingOptions,
36
DefineConversationHandlerFunctionProps,
47
defineConversationHandlerFunction,
58
} from './factory.js';
69

710
export {
811
ConversationHandlerFunctionFactory,
12+
ConversationHandlerFunctionLogLevel,
13+
ConversationHandlerFunctionLogRetention,
14+
ConversationHandlerFunctionLoggingOptions,
915
DefineConversationHandlerFunctionProps,
1016
defineConversationHandlerFunction,
1117
};

packages/backend-function/API.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { AmplifyResourceGroupName } from '@aws-amplify/plugin-types';
88
import { BackendSecret } from '@aws-amplify/plugin-types';
99
import { ConstructFactory } from '@aws-amplify/plugin-types';
1010
import { FunctionResources } from '@aws-amplify/plugin-types';
11+
import { LogLevel } from '@aws-amplify/plugin-types';
12+
import { LogRetention } from '@aws-amplify/plugin-types';
1113
import { ResourceAccessAcceptorFactory } from '@aws-amplify/plugin-types';
1214
import { ResourceProvider } from '@aws-amplify/plugin-types';
1315
import { StackProvider } from '@aws-amplify/plugin-types';
@@ -28,6 +30,22 @@ export type FunctionBundlingOptions = {
2830
minify?: boolean;
2931
};
3032

33+
// @public (undocumented)
34+
export type FunctionLoggingOptions = ({
35+
format: 'json';
36+
level?: FunctionLogLevel;
37+
} | {
38+
format?: 'text';
39+
}) & {
40+
retention?: FunctionLogRetention;
41+
};
42+
43+
// @public (undocumented)
44+
export type FunctionLogLevel = LogLevel;
45+
46+
// @public (undocumented)
47+
export type FunctionLogRetention = LogRetention;
48+
3149
// @public (undocumented)
3250
export type FunctionProps = {
3351
name?: string;
@@ -40,6 +58,7 @@ export type FunctionProps = {
4058
layers?: Record<string, string>;
4159
bundling?: FunctionBundlingOptions;
4260
resourceGroupName?: AmplifyResourceGroupName;
61+
logging?: FunctionLoggingOptions;
4362
};
4463

4564
// @public (undocumented)

0 commit comments

Comments
 (0)