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: add support for function logs streaming to sandbox #1492
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: c4d423e The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
const backendOutput: BackendOutput = | ||
await this.backendOutputClient.getOutput(sandboxBackendId); | ||
|
||
const definedFunctionsPayload = | ||
backendOutput[functionOutputKey]?.payload.definedFunctions; | ||
const deployedFunctionNames = definedFunctionsPayload | ||
? (JSON.parse(definedFunctionsPayload) as 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.
Can we use DeployedBackendClient.getBackendMetadata()
instead? That returns a list of FunctionConfiguration objects which should eliminate the need to depend on backend-output-schemas
directly in this package
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.
We shouldn't. DeployedBackendClient.getBackendMetadata()
is a pretty heavy command as it loads all the nested stacks and all resources.
We need something as lightweight as possible since this method gets called every time sandbox gets idle.
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.
Maybe we need some sort of "filter" prop for getBackendMetadata
where it can be instructed to only load metadata from certain verticals? So in this case, we could use it to only load function metadata
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.
We don't even need the function stack as technically what we are loading is not a metadata
unless we start adding the "friendly name" in the metadata or outputs section. In that case we can continue to use getOutput
here.
I also don't see any issues with depending on backend-output-schemas
here. backendOutputClient.getOutput
is the right abstraction here.
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.
Taking a closer look at this, it looks like we're only using the functionOutputKey from that package. However, getOutput
should already have typed keys so we can just use the string directly here and we'll get typechecking without having to import the schema package.
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 will update it to using the key "AWS::Amplify::Function"
directly, but wouldn't it just add duplicity. Not that we are ever going to change it but I don't understand the drawback of this dependency?
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.
It's not a huge deal. In my head, the deployed-backend-client
is the "entry point" by which all readers should get info about the backend. the schema
package is meant to be a contract between the backend-client
package and the places where the output is written (the constructs). Ideally the schema shouldn't be needed directly by consumers of deployed-backend-client
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.
It makes sense to have one writer, but I believe it's fine to have multiple readers. We already have client-config
and model-generator
private readonly refreshRate: number = 500 | ||
) {} | ||
) { | ||
// if not running in tty, turn off colors |
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.
why is this class manipulating colors?
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.
Since this is a central place for performing logging, it's better to turn off/on colors here rather than at the consumers place. Especially since this $
is a global variable, the colors will only change when one consumer changes it making the colors inconsistent.
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.
Aren't the methods in format
already a noop if colors are not enabled? Why do we need additional logic for it here?
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.
format
uses supportColors
which only looks at the environment/terminal you are running in and decides whether to enable or disable colors. E.g. in CI/CD the colors might be disabled. See https://github.com/isaacs/color-support
In the printer, we might be piping the data in some other place as well (e.g. writing to a file) supportColors
doesn't know that and will keep the colors enabled.
.option('stream-function-logs', { | ||
describe: | ||
'Whether to stream function execution logs. Default: false. Use --function-names to filter for specific functions to stream logs from', | ||
boolean: true, | ||
global: false, | ||
group: 'Options to configure streaming of lambda function logs', | ||
}) | ||
.option('function-name', { |
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.
Could stream-function-logs
be a boolean or array? ie you can specify --stream-function-logs
to stream all logs or you can specify --stream-function-logs name1 name2
to only stream those two lambdas. Then we wouldn't need a separate arg for function-name
.
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 is a TBD since requirements are pending (hence PR being in draft).
I think it is fine to merge the options, my reasoning is that it impacts discoverability as hints are hidden under the --stream-function-logs
option's help description. With an explicit option, that shows up clearly in the help for easy discoverability.
Resource: entry.arn, | ||
}) | ||
); | ||
const friendlyFunctionName = |
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.
using getBackendMetadata()
will do this filtering for us
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.
Do we get the tagged names there? I thought it was only the physical Arn
amplify-backend/packages/deployed-backend-client/src/deployed_backend_client.ts
Lines 346 to 363 in 57a5138
customerFunctionNames.forEach((functionName) => { | |
const resource = functionResources.find( | |
(func) => func.physicalResourceId === functionName | |
); | |
if (resource) { | |
functionConfigurations.push({ | |
status: this.stackStatusMapper.translateStackStatus( | |
resource.resourceStatus | |
), | |
lastUpdated: | |
resource.lastUpdated ?? | |
functionStack.LastUpdatedTime ?? | |
functionStack.CreationTime, | |
functionName, | |
}); | |
} | |
}); |
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.
ah, yeah if we need the friendly name, we'd need to do some extra processing or expand the interface the deployed backend client
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 don't think we are at a point that warrants to expand the interface of deployed backend client. Also one can argue that tags
(or other resource specific properties) are not considered metadata
and shouldn't be part of this package. We can look into adding the friendly-name
to stack outputs to avoid lambda:list-tags
, but I don't think we are there yet.
export type Color = Colorize; | ||
export type ColorName = keyof typeof colors; | ||
|
||
export const colors = { |
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 is still exporting kleur functions. Why not have
export enum Color {
GREEN = 'green';
YELLOW = 'yellow';
etc
}
Then internally map those enum values to the kleur function.
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.
Updated to not export the colors
object but just a type and enumerated color names.
Changes
Add support for streaming function logs in sandbox
CLI
--stream-function-logs
--once
should not stream function logsDisplay
Functionality
Validation
Unit tests added
Checklist
run-e2e
label set.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.