Add remote debugging support for Node.js on Linux App Service plans (#1458)
This commit is contained in:
Родитель
5d9891c914
Коммит
58bef37800
|
@ -37,8 +37,10 @@ Install the prerequisites for your desired language:
|
|||
* Stream logs from your Azure Function Apps
|
||||
* View and manage deployment slots
|
||||
> **NOTE**: To enable, set `azureFunctions.enableSlots` to true.
|
||||
* Debug Java function project in Azure (experimental)
|
||||
* Debug Node.js function project in Azure (experimental)
|
||||
> **NOTE**: To enable, set `azureFunctions.enableRemoteDebugging` to true.
|
||||
* Debug Java function project in Azure (experimental)
|
||||
> **NOTE**: To enable, set `azureFunctions.enableJavaRemoteDebugging` to true.
|
||||
|
||||
### Create New Project
|
||||
|
||||
|
|
30
package.json
30
package.json
|
@ -48,7 +48,8 @@
|
|||
"onCommand:azureFunctions.deleteFunction",
|
||||
"onCommand:azureFunctions.deploy",
|
||||
"onCommand:azureFunctions.configureDeploymentSource",
|
||||
"onCommand:azureFunctions.debugFunctionAppOnAzure",
|
||||
"onCommand:azureFunctions.startRemoteDebug",
|
||||
"onCommand:azureFunctions.startJavaRemoteDebug",
|
||||
"onCommand:azureFunctions.appSettings.add",
|
||||
"onCommand:azureFunctions.appSettings.download",
|
||||
"onCommand:azureFunctions.appSettings.upload",
|
||||
|
@ -176,8 +177,13 @@
|
|||
"category": "Azure Functions"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.debugFunctionAppOnAzure",
|
||||
"title": "%azFunc.debugFunctionAppOnAzure%",
|
||||
"command": "azureFunctions.startRemoteDebug",
|
||||
"title": "%azFunc.startRemoteDebug%",
|
||||
"category": "Azure Functions"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.startJavaRemoteDebug",
|
||||
"title": "%azFunc.startJavaRemoteDebug%",
|
||||
"category": "Azure Functions"
|
||||
},
|
||||
{
|
||||
|
@ -452,10 +458,15 @@
|
|||
"group": "4@2"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.debugFunctionAppOnAzure",
|
||||
"command": "azureFunctions.startRemoteDebug",
|
||||
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/ && config.azureFunctions.enableRemoteDebugging == true",
|
||||
"group": "5@1"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.startJavaRemoteDebug",
|
||||
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/ && config.azureFunctions.enableJavaRemoteDebugging == true",
|
||||
"group": "5@2"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.viewProperties",
|
||||
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
|
||||
|
@ -646,9 +657,13 @@
|
|||
"when": "never"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.debugFunctionAppOnAzure",
|
||||
"command": "azureFunctions.startRemoteDebug",
|
||||
"when": "config.azureFunctions.enableRemoteDebugging == true"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.startJavaRemoteDebug",
|
||||
"when": "config.azureFunctions.enableJavaRemoteDebugging == true"
|
||||
},
|
||||
{
|
||||
"command": "azureFunctions.createSlot",
|
||||
"when": "config.azureFunctions.enableSlots == true"
|
||||
|
@ -831,6 +846,11 @@
|
|||
"description": "%azFunc.enableRemoteDebugging%",
|
||||
"default": false
|
||||
},
|
||||
"azureFunctions.enableJavaRemoteDebugging": {
|
||||
"type": "boolean",
|
||||
"description": "%azFunc.enableJavaRemoteDebugging%",
|
||||
"default": false
|
||||
},
|
||||
"azureFunctions.showProjectWarning": {
|
||||
"type": "boolean",
|
||||
"description": "%azFunc.showProjectWarningDescription%",
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
"azFunc.projectLanguageDescription": "The default language to use when performing operations in the Azure Functions extension (e.g. \"Create New Function\").",
|
||||
"azFunc.deploy": "Deploy to Function App...",
|
||||
"azFunc.configureDeploymentSource": "Configure Deployment Source...",
|
||||
"azFunc.debugFunctionAppOnAzure": "Attach Debugger",
|
||||
"azFunc.startRemoteDebug": "Start Remote Debugging",
|
||||
"azFunc.startJavaRemoteDebug": "Attach Debugger",
|
||||
"azFunc.appSettings.add": "Add New Setting...",
|
||||
"azFunc.appSettings.download": "Download Remote Settings...",
|
||||
"azFunc.appSettings.upload": "Upload Local Settings...",
|
||||
|
@ -46,7 +47,8 @@
|
|||
"azFunc.showDeploySubpathWarningDescription": "Show a warning when the \"deploySubpath\" setting does not match the selected folder for deploying.",
|
||||
"azFunc.startStreamingLogs": "Start Streaming Logs",
|
||||
"azFunc.stopStreamingLogs": "Stop Streaming Logs",
|
||||
"azFunc.enableRemoteDebugging": "Enable remote debugging, an experimental feature that only supports Java-based Functions Apps.",
|
||||
"azFunc.enableRemoteDebugging": "Enable remote debugging for Node.js Function Apps running on Linux App Service plans. Consumption plans are not supported. (experimental)",
|
||||
"azFunc.enableJavaRemoteDebugging": "Enable remote debugging for Java Functions Apps running on Windows. (experimental)",
|
||||
"azFunc.deleteProxy": "Delete Proxy...",
|
||||
"azFunc.pickProcessTimeoutDescription": "The timeout (in seconds) to be used when searching for the Azure Functions host process. Since a build is required every time you F5, you may need to adjust this based on how long your build takes.",
|
||||
"azFunc.templateVersion": "A runtime release version (any runtime) that species which templates will be used rather than the latest templates. This version will be used for ALL runtimes. (Requires a restart of VS Code to take effect)",
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { WebSiteManagementModels } from 'azure-arm-website';
|
||||
|
||||
export function checkForRemoteDebugSupport(siteConfig: WebSiteManagementModels.SiteConfig): void {
|
||||
// Read siteConfig.linuxFxVersion to determine debugging support
|
||||
// If the Function App is running on Windows, it will be empty
|
||||
// If the Function App is running on Linux consumption, it will be empty
|
||||
// If the Function App is running on a Linux App Service plan, it will contain Docker registry information, e.g. "DOCKER|repo.azurecr.io/image:tag"
|
||||
// The blessed Node.js Docker image will be something like "DOCKER|mcr.microsoft.com/azure-functions/node:2.0-node8-appservice"
|
||||
if (siteConfig.linuxFxVersion && siteConfig.linuxFxVersion.startsWith('DOCKER|mcr.microsoft.com/azure-functions/node')) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('Azure Remote Debugging is currently only supported for Node.js Function Apps running on Linux App Service plans. Consumption plans are not supported.');
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { WebSiteManagementModels } from 'azure-arm-website';
|
||||
import * as vscode from 'vscode';
|
||||
import * as appservice from 'vscode-azureappservice';
|
||||
import { IActionContext } from 'vscode-azureextensionui';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
|
||||
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
|
||||
import { checkForRemoteDebugSupport } from './checkForRemoteDebugSupport';
|
||||
|
||||
export async function startRemoteDebug(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
|
||||
if (!node) {
|
||||
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
|
||||
}
|
||||
|
||||
const siteClient: appservice.SiteClient = node.root.client;
|
||||
const siteConfig: WebSiteManagementModels.SiteConfig = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async progress => {
|
||||
appservice.reportMessage('Fetching site configuration...', progress);
|
||||
return await siteClient.getSiteConfig();
|
||||
});
|
||||
|
||||
checkForRemoteDebugSupport(siteConfig);
|
||||
|
||||
await appservice.startRemoteDebug(siteClient, siteConfig);
|
||||
}
|
|
@ -8,17 +8,17 @@ import * as portfinder from 'portfinder';
|
|||
import * as vscode from 'vscode';
|
||||
import { SiteClient } from 'vscode-azureappservice';
|
||||
import { DialogResponses, IActionContext } from 'vscode-azureextensionui';
|
||||
import { DebugProxy } from '../DebugProxy';
|
||||
import { ext } from '../extensionVariables';
|
||||
import { localize } from '../localize';
|
||||
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
|
||||
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
|
||||
import { openUrl } from '../utils/openUrl';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { localize } from '../../localize';
|
||||
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
|
||||
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
|
||||
import { openUrl } from '../../utils/openUrl';
|
||||
import { DebugProxy } from './DebugProxy';
|
||||
|
||||
const HTTP_PLATFORM_DEBUG_PORT: string = '8898';
|
||||
const JAVA_OPTS: string = `-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=127.0.0.1:${HTTP_PLATFORM_DEBUG_PORT}`;
|
||||
|
||||
export async function remoteDebugFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
|
||||
export async function remoteDebugJavaFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
|
||||
if (!node) {
|
||||
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
|
||||
}
|
|
@ -39,7 +39,8 @@ import { startStreamingLogs } from './commands/logstream/startStreamingLogs';
|
|||
import { stopStreamingLogs } from './commands/logstream/stopStreamingLogs';
|
||||
import { openInPortal } from './commands/openInPortal';
|
||||
import { pickFuncProcess } from './commands/pickFuncProcess';
|
||||
import { remoteDebugFunctionApp } from './commands/remoteDebugFunctionApp';
|
||||
import { startRemoteDebug } from './commands/remoteDebug/startRemoteDebug';
|
||||
import { remoteDebugJavaFunctionApp } from './commands/remoteDebugJava/remoteDebugJavaFunctionApp';
|
||||
import { renameAppSetting } from './commands/renameAppSetting';
|
||||
import { restartFunctionApp } from './commands/restartFunctionApp';
|
||||
import { startFunctionApp } from './commands/startFunctionApp';
|
||||
|
@ -128,7 +129,8 @@ export async function activateInternal(context: vscode.ExtensionContext, perfSta
|
|||
registerCommand('azureFunctions.appSettings.encrypt', encryptLocalSettings);
|
||||
registerCommand('azureFunctions.appSettings.delete', async (actionContext: IActionContext, node?: AzExtTreeItem) => await deleteNode(actionContext, AppSettingTreeItem.contextValue, node));
|
||||
registerCommand('azureFunctions.appSettings.toggleSlotSetting', toggleSlotSetting);
|
||||
registerCommand('azureFunctions.debugFunctionAppOnAzure', remoteDebugFunctionApp);
|
||||
registerCommand('azureFunctions.startRemoteDebug', startRemoteDebug);
|
||||
registerCommand('azureFunctions.startJavaRemoteDebug', remoteDebugJavaFunctionApp);
|
||||
registerCommand('azureFunctions.deleteProxy', async (actionContext: IActionContext, node?: AzExtTreeItem) => await deleteNode(actionContext, ProxyTreeItem.contextValue, node));
|
||||
registerCommand('azureFunctions.installOrUpdateFuncCoreTools', installOrUpdateFuncCoreTools);
|
||||
registerCommand('azureFunctions.uninstallFuncCoreTools', uninstallFuncCoreTools);
|
||||
|
|
Загрузка…
Ссылка в новой задаче