-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(cli): cdk watch for Lambdas with Advanced Logging Controls do not stream logs to the terminal #29451
fix(cli): cdk watch for Lambdas with Advanced Logging Controls do not stream logs to the terminal #29451
Changes from all commits
589e2d8
567adf5
d62dd4b
49089d0
ce4a051
398732b
dcc39a0
f8bcdfc
1acf29d
6dc6827
95f7904
c22a3a2
b51b6fe
1d8d8a5
5cebbcf
e3f49b7
1d9bf61
0abae7e
802e1db
0fe76ca
cad211c
48a9b05
77105bd
28c6ecf
ae37db2
750aa2b
f5794c0
1b35bbf
5761504
830ee9c
33a37e9
32981b2
f941cde
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,12 @@ | ||
import * as cxapi from '@aws-cdk/cx-api'; | ||
import { CloudFormation } from 'aws-sdk'; | ||
import { Mode, SdkProvider, ISDK } from '../aws-auth'; | ||
import { ISDK, Mode, SdkProvider } from '../aws-auth'; | ||
import { Deployments } from '../deployments'; | ||
import { EvaluateCloudFormationTemplate, LazyListStackResources } from '../evaluate-cloudformation-template'; | ||
|
||
// resource types that have associated CloudWatch Log Groups that should _not_ be monitored | ||
const IGNORE_LOGS_RESOURCE_TYPES = ['AWS::EC2::FlowLog', 'AWS::CloudTrail::Trail', 'AWS::CodeBuild::Project']; | ||
|
||
// Resource types that will create a CloudWatch log group with a specific name if one is not provided. | ||
// The keys are CFN resource types, and the values are the name of the physical name property of that resource | ||
// and the service name that is used in the automatically created CloudWatch log group. | ||
const RESOURCE_TYPES_WITH_IMPLICIT_LOGS: { [cfnResourceType: string]: { [key: string]: string } } = { | ||
'AWS::Lambda::Function': { | ||
PhysicalNamePropertyName: 'FunctionName', | ||
LogGroupServiceName: 'lambda', | ||
}, | ||
}; | ||
|
||
/** | ||
* Configuration needed to monitor CloudWatch Log Groups | ||
* found in a given CloudFormation Stack | ||
|
@@ -84,38 +74,68 @@ function isReferencedFromIgnoredResource( | |
logGroupResource: CloudFormation.StackResourceSummary, | ||
evaluateCfnTemplate: EvaluateCloudFormationTemplate, | ||
): boolean { | ||
let foundReference = false; | ||
const resourcesReferencingLogGroup = evaluateCfnTemplate.findReferencesTo(logGroupResource.LogicalResourceId); | ||
for (const reference of resourcesReferencingLogGroup) { | ||
if (IGNORE_LOGS_RESOURCE_TYPES.includes(reference.Type)) { | ||
foundReference = true; | ||
} | ||
} | ||
return foundReference; | ||
return resourcesReferencingLogGroup.some(reference => { | ||
return IGNORE_LOGS_RESOURCE_TYPES.includes(reference.Type); | ||
}); | ||
} | ||
|
||
type CloudWatchLogsResolver = ( | ||
resource: CloudFormation.StackResourceSummary, | ||
evaluateCfnTemplate: EvaluateCloudFormationTemplate | ||
) => string | undefined; | ||
|
||
const cloudWatchLogsResolvers: Record<string, CloudWatchLogsResolver> = { | ||
'AWS::Logs::LogGroup': (resource, evaluateCfnTemplate) => { | ||
if (isReferencedFromIgnoredResource(resource, evaluateCfnTemplate)) { | ||
return undefined; | ||
} | ||
return resource.PhysicalResourceId?.toString(); | ||
}, | ||
|
||
// Resource types that will create a CloudWatch log group with a specific name if one is not provided. | ||
// The keys are CFN resource types, and the values are the name of the physical name property of that resource | ||
// and the service name that is used in the automatically created CloudWatch log group. | ||
'AWS::Lambda::Function': (resource, evaluateCfnTemplate) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lambda is not the only service that creates custom There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I though about that while making this change but as the only reference I had was the Lambda one I thought in not adding more stuff than the things that already exists, but I can definitely work on that extras on upcoming PRs now that I got familiarity with the codebase. |
||
const loggingConfig = evaluateCfnTemplate.getResourceProperty(resource.LogicalResourceId, 'LoggingConfig'); | ||
if (loggingConfig?.LogGroup) { | ||
// if LogGroup is a string then use it as the LogGroupName as it is referred by LogGroup.fromLogGroupArn in CDK | ||
if (typeof loggingConfig.LogGroup === 'string') { | ||
return loggingConfig.LogGroup; | ||
} | ||
|
||
// if { Ref: '...' } is used then try to resolve the LogGroupName from the referenced resource in the template | ||
if (typeof loggingConfig.LogGroup === 'object') { | ||
if (loggingConfig.LogGroup.Ref) { | ||
return evaluateCfnTemplate.getResourceProperty(loggingConfig.LogGroup.Ref, 'LogGroupName'); | ||
} | ||
} | ||
} | ||
|
||
return `/aws/lambda/${resource.PhysicalResourceId}`; | ||
}, | ||
}; | ||
|
||
/** | ||
* Find all CloudWatch Log Groups in the deployed template. | ||
* This will find both explicitely created Log Groups (excluding those associated with ignored resources) | ||
* as well as Log Groups created implicitely (i.e. Lambda Functions) | ||
* This will find both explicitly created Log Groups (excluding those associated with ignored resources) | ||
* and Log Groups created implicitly (i.e. Lambda Functions) | ||
*/ | ||
function findAllLogGroupNames( | ||
stackResources: CloudFormation.StackResourceSummary[], | ||
evaluateCfnTemplate: EvaluateCloudFormationTemplate, | ||
): string[] { | ||
return stackResources.reduce((logGroupNames: string[], resource) => { | ||
let logGroupName; | ||
if (resource.ResourceType === 'AWS::Logs::LogGroup') { | ||
if (!isReferencedFromIgnoredResource(resource, evaluateCfnTemplate)) { | ||
logGroupName = resource.PhysicalResourceId; | ||
const logGroupNames: string[] = []; | ||
|
||
for (const resource of stackResources) { | ||
const logGroupResolver = cloudWatchLogsResolvers[resource.ResourceType]; | ||
if (logGroupResolver) { | ||
const logGroupName = logGroupResolver(resource, evaluateCfnTemplate); | ||
if (logGroupName) { | ||
logGroupNames.push(logGroupName); | ||
} | ||
} else if (RESOURCE_TYPES_WITH_IMPLICIT_LOGS[resource.ResourceType]) { | ||
const servicePart = RESOURCE_TYPES_WITH_IMPLICIT_LOGS[resource.ResourceType].LogGroupServiceName; | ||
logGroupName = `/aws/${servicePart}/${resource.PhysicalResourceId}`; | ||
} | ||
if (logGroupName) { | ||
logGroupNames.push(logGroupName); | ||
} | ||
return logGroupNames; | ||
}, []); | ||
} | ||
|
||
return logGroupNames; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has no functionality change, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, it was looping the resourcesReferencingLogGroup and returning true if some Type is in the IGNORE_LOGS_RESOURCE_TYPES.
Which summarizes as a
.some
.