-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat(aws-appmesh): adds access logging configuration to Virtual Nodes #10490
Conversation
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.
LGTM! One small comment, feel free to remove the pr/do-not-merge
label if you decide to tackle it, and the PR will get merged automatically.
Thanks for the contribution!
/** | ||
* Path to a file to write access logs to | ||
*/ | ||
readonly filePath: string; |
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.
Question (for @skinny85 I think): We represent the options in this struct as a "union" in our APIs, which means only one value (e.g. filePath
or something else) can be provided. In the future if we add a new option that's not a filePath
, is this the right interface/approach?
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.
If that is the case, we have a different pattern in the CDK for that: the union-like class. Basically, you type this property as an abstract class:
export abstract class AccessLog {
// ...
}
export interface VirtualNodeBaseProps {
// ..
readonly accessLog?: AccessLog;
}
And then have static factory methods that create instances of it:
export abstract class AccessLog {
public static fromFilePath(filePath: string): AccessLog {
// ...
}
// ...
}
If, in the future, you need other types of AccessLog
, you just add new static factory methods to the AccessLog
class.
Does this make sense?
accessLog: { | ||
file: { | ||
path: '/dev/stdout', |
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.
Would defaulting the filePath
to /dev/stdout
be reasonable? It's the most common configuration we expect for folks using access logs.
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.
Let me ask you this.
Is it reasonable to leave this property unset (by that I mean null
, as this property is optional in CloudFormation)? Is it a legitimate thing that customers might want to do?
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.
Path itself cannot be null
(required in CFN: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-fileaccesslog.html). However, nulling the access log field in total is acceptable, and just means that no access logging will be configured for the resource
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.
So, is it reasonable for a customer to want to turn off logging by setting this (entire) property to null
? Because if it is, we need to to take this requirement into account when designing this functionality.
I see 2 ways of allowing that:
- Don't default this field (this way, not setting it in the CDK = passing
null
through CloudFormation). - If you want to go with the union-like pattern that I mentioned in this comment, you can have a "magic"
AccessLog
static factory method likenone
:
export abstract class AccessLog {
public static none(): AccessLog { ... }
// ...
}
which will set this field in the implementation of VirtualNode
to null
. In this case, keep the default for this field same it is today (so, { file: { path: '/dev/stdout' } }
).
Which one to choose between the two (assuming you're both on-board with the "union-like" approach here) I think depends on what you see the common case being. If file: { path: '/dev/stdout' }
is a sensible default that many customers will be happy with, I would go with nr 2. If disabling logging is a common thing that a lot customers want (for example: does it have some cost implications?), though, I would go with nr 1.
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.
For Virtual Nodes, wouldn't the equivalent to having no access logging be:
new VirtualNode(stack, 'testVn', {
mesh: mesh,
virtualNodeName: 'exampleVirtualNodeName',
})
Then if you wanted to enable the default access logging you could do something like:
new VirtualNode(stack, 'testVnWithDefaultAccessLogging', {
mesh: mesh,
virtualNodeName: 'exampleVirtualNodeName',
accessLog: {},
})
or are the two equivalent?
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.
I think we're talking about 2 different defaults here 🙂.
Today, this:
new VirtualNode(stack, 'testVn', {
mesh: mesh,
virtualNodeName: 'exampleVirtualNodeName',
});
will result in the CDK default for logging of { file: { path: '/dev/stdout' } }
. I believe we're discussing in this comment whether to keep this default, or to get rid of it (see @bcelenza's original comment).
If you do this:
new VirtualNode(stack, 'testVnWithDefaultAccessLogging', {
mesh: mesh,
virtualNodeName: 'exampleVirtualNodeName',
accessLog: {},
});
you will get the service default instead, which I believe is "no logging is enabled" (but I'm sure you know it better than I do 🙂)
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.
Yeah, there are actually two questions here:
- Should we enable access logging by default?
- Should the default path of that access log be
/dev/stdout
?
Having given this some thought, my view is the answer to both is no. With /dev/stdout
, the access logs are mixed in with the logs from the proxy process, so I think it's important folks understand the impact of that (namely they need to parse two formats from the same sink). Also, /dev/stdout
is *nix specific and while we don't support Windows now, I can't definitively say we wouldn't support it in the future.
…tual exclusive properties
Pull request has been modified.
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.
I have a suggestion for AccessLog.bind()
that I think will simplify this greatly 🙂.
* | ||
* @default - no file based access logging | ||
*/ | ||
readonly filePath?: string; |
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.
Here's my suggestion 🙂.
To make bind()
in AccessLog
more flexible, let's actually have AccessLogConfig
have an (optional) property called accessLog
with the type CfnVirtualNode.AccessLogProperty
.
Yes, I know we say we don't use L1 properties in our L2s, but that only applies to input properties. This is an output property. Complicated, I know 🙂.
Then, in VritualNode
, you can simply do:
const accessLoggingConfig = props.accessLog?.bind(this);
const node = new CfnVirtualNode(this, 'Resource', {
// ...
logging: {
accessLog: accessLoggingConfig.accessLog,
},
// ...
This has the huge benefit that customers don't have to wait for you to implement new access logging types - they have an "escape hatch" of updating their L1 layer, and then extending AccessLog
themselves.
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.
Would this pattern support Virtual Gateways as well? https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualgateway-virtualgatewaylogging.html
Would you implement the bind
method to also set a CfnVirtualGateway.VirtualGatewayAccessLogProperty;
property on the AccessLogConfig
as well?
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.
If that's your plan, then I would eventually shoot for AccessLogConfig
to have both properties!
export interface AccessLogConfig {
readonly virtualNodeLogging?: CfnVirtualNode.AccessLogProperty;
readonly virtualGatewayLogging?: CfnVirtualGateway.VirtualGatewayAccessLogProperty;
}
export class AccessLog {
public static fromFilePath(filePath: string): AccessLog {
return new FilePathAccessLog(filePath);
}
public abstract bind(scope: Construct): AccessLogConfig;
}
class FilePathAccessLog extends AccessLog {
public constructor(private readonly filePath: string) {
}
public bind(_scope: Construct): AccessLogConfig {
return {
virtualNodeLogging: {
file { path: this.filePath },
},
virtualGatewayLogging: {
file: { path: this.filePath },
},
};
}
}
And then both VirtualNode
and VirtualGateway
read their respective fields after calling bind()
.
The only way I could see this backfiring is if you were 100% convinced you would not ever have any differences between CfnVirtualNode.AccessLogProperty
and CfnVirtualGateway.VirtualGatewayAccessLogProperty
(but if that's the case, I would question why would you have 2 separate property types for them in CloudFormation).
/** | ||
* Configuration for Envoy Access logs for mesh endpoints | ||
*/ | ||
export class FileAccessLog extends AccessLog { |
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.
Let's actually not export this class from this file, and keep it module-private (just remove the export
keyword).
@@ -267,13 +275,13 @@ export class VirtualNode extends VirtualNodeBase { | |||
attributes: renderAttributes(props.cloudMapServiceInstanceAttributes), | |||
} : undefined, | |||
}, | |||
logging: { | |||
logging: accessLogging !== undefined ? { |
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.
If you take my suggestion from above, this code should be simplified greatly 🙂.
Pull request has been modified.
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.
Looks great!
One more thing - can you please update the ReadMe with the new class? Just using it in the existing example that creates a VirtualNode
class instance to fill the accessLog
property of it will be enough 🙂.
Thanks!
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.
Awesome, thanks for the first (of hopefully many 🙂) contributions @dfezzie !
Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
Pull request has been modified.
Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Addresses the first point on #9490 by allow access logging to be configured through props
AccessLog
shared-interface as it can be reused in Virtual Gateways and Virtual NodesBREAKING CHANGE: VirtualNode no longer has accessLog set to "/dev/stdout" by default
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license