Azure / azure-dev

A developer CLI that reduces the time it takes for you to get started on Azure. The Azure Developer CLI (azd) provides a set of developer-friendly commands that map to key stages in your workflow - code, build, deploy, monitor, repeat.
https://aka.ms/azd
MIT License
408 stars 196 forks source link

[Issue] `azd show` consistently takes ~3s to complete #792

Open philliphoff opened 2 years ago

philliphoff commented 2 years ago

Output from azd version

azd version 0.3.0-beta.1 (commit c5344160ed49bfda75281fba28b5e9ac7b96670e)

Output from az version

{
  "azure-cli": "2.40.0",
  "azure-cli-core": "2.40.0",
  "azure-cli-telemetry": "1.0.8",
  "extensions": {
    "containerapp": "0.2.0",
    "fidalgo": "0.1.0",
    "log-analytics": "0.2.2"
  }
}

Describe the bug Running azd show consistently takes ~3s to complete but can also take as much as 5s; rarely have I seen it less than 2s. This is on a M1 16GB MacBook Pro (macOS 12.6) running no other applications.

To Reproduce Run time azd show --output json on a newly-created application created from the todo-nodejs-mongo template.

Expected behavior While I don't have any specific performance criteria in mind, 3s seems like a long wait for a command solely intended for the use of tooling, as tooling tends to run such commands more frequently than users in order to ensure that its related UX is up to date. <2s seems more reasonable, <1s probably ideal.

ellismg commented 2 years ago

A majority of the time here is spent just pulling state from Azure (so we can discover the Azure resources for your application and correlate them to resources in the azure.yaml file). The overhead of running these az CLI commands can't be helping us here, but as designed this command is always going to reach out to the cloud to get information.

We actually have this cost spread across a lot of our components - we may want to consider caching information instead of hitting the cloud every time. For example, if azd provision cached the result of the deployment (and maybe did some post processing work to cache other related peices of information) we could quickly pull that in and find all the resources without having to do expensive queries.

I imagine that in this world azd env refresh would be used to control these caches. You could imagine a top level --refresh argument which would allow a user to force a refresh of the cache when using individual commands.

This does lead to the problem of a user having to understand if they need to run refresh or pass --refresh to a command, but I think we can end up in a place where that's not needed unless you end up modifying infrastructure outside of of azd provision (since azd provision can know to update the cache because something is changing)

If we didn't want to do the caching, there's also perhaps a design to explore where azd show prints a restricted set of information (that we can compute without hitting the cloud) and then something like azd show --full or something pulls in all the information, but takes longer (and perhaps editors could call azd show first to get some information to populate UI and then call azd show --full and update the UI once that had completed), but it feels like some level of caching is going to be important here long term.

@philliphoff do you have thoughts on what a good design might be here? I know you also mentioned some sort of design some other tools use where they can stream output back to a tool over a period of time (I'm guessing this looks more or less like a language server, where we'd have a long running azd process that the editor communicates with over standard in/standard out or via a HTTP request/response model).

philliphoff commented 2 years ago

I think the larger question is how to efficiently and promptly detect and respond to changes to the Azure Dev CLI context. The azd show command was intended to shield tools from implementation details such as configuration file formats, which is good. But tools also need to know when to next call azd show.

One approach is to periodically poll. This requires balancing the desire for immediacy in the UX (i.e. users expect near instant responses to changes, even those made outside of the IDE, such as in a terminal) with minimizing resources consumed during the poll (e.g. CPU/Internet/etc.). For purely local resources this tends to be less of an issue than for azd which makes HTTP calls. This could be mitigated, as you suggest, by caching data within azd such that invocations are both quicker as well as less resource intensive.

Another approach is to have the tools monitor changes to key files, such as .azure/config.json and azure.yaml. The disadvantage is, obviously, the tools must now know implementation details such as all files that might be written during a change in context, which seems counter to the purpose of azd show.

I had earlier mentioned docker, for example, which has a sophisticated events command that streams data back to the tools and is used by tools to trigger immediate refreshes of state. While that works really well, it does assume an always-running "daemon-like" architecture which I don't think could apply to azd. That said, it might be reasonbly feasible to have a long running azd events command that does the necessary file monitoring (as it knows and can be most easily kept in sync with those implementation details) and sends notifications via stdout, that then triggers tools to make the next azd show command.

ellismg commented 2 years ago

Another approach is to have the tools monitor changes to key files, such as .azure/config.json and azure.yaml. The disadvantage is, obviously, the tools must now know implementation details such as all files that might be written during a change in context, which seems counter to the purpose of azd show.

One possibility here would be to have some file with a well-known name (perhaps in .azure) and have the azd touch it (or write a timestamp if we wanted the contents to change) when things have changed? Then, editors could monitor that file and when there are changes re-run azd show? That would at least mean the editor would be shielded from having to understand every file that might cause a change (and would also support cases where changes happen even without changes on the local file-system (e.g. azd show can't show resource information until azd provision has run).

philliphoff commented 2 years ago

One possibility here would be to have some file with a well-known name (perhaps in .azure) and have the azd touch it (or write a timestamp if we wanted the contents to change) when things have changed? Then, editors could monitor that file and when there are changes re-run azd show? That would at least mean the editor would be shielded from having to understand every file that might cause a change (and would also support cases where changes happen even without changes on the local file-system (e.g. azd show can't show resource information until azd provision has run).

That might be a reasonable compromise; the tools need not poll but also not have to know every detail about azd file updates, and file watching is built into many tooling platforms. I would assume that such a file would not be intended to be part of the repo and excluded directly/indirectly via .gitignore as part of template creation?