diff --git a/package-lock.json b/package-lock.json index fb77982..fd490e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { - "name": "vscode-azureerraform", - "version": "0.0.1", + "name": "vscode-azureterraform", + "version": "0.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -90,6 +90,11 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "applicationinsights": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz", + "integrity": "sha1-Fi67SKODQIvE3kTbMrQXMH9Fu8E=" + }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", @@ -156,6 +161,15 @@ "lodash": "4.17.4" } }, + "async-listener": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.9.tgz", + "integrity": "sha512-E7Z2/QMs0EPt/o9wpYO/J3hmMCDdr1aVDS3ttlur5D5JlZtxhfuOwi4e7S8zbYIxA5qOOYdxfqGj97XAfdNvkQ==", + "requires": { + "semver": "5.4.1", + "shimmer": "1.2.0" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -501,6 +515,15 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "continuation-local-storage": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", + "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "requires": { + "async-listener": "0.6.9", + "emitter-listener": "1.1.1" + } + }, "convert-source-map": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", @@ -645,6 +668,14 @@ "safe-buffer": "5.1.1" } }, + "emitter-listener": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.1.tgz", + "integrity": "sha1-6Lu+gkS8jg0LTvcc0UKUx/JBx+w=", + "requires": { + "shimmer": "1.2.0" + } + }, "end-of-stream": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", @@ -2521,6 +2552,11 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, + "shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-xTCx2vohXC2EWWDqY/zb4+5Mu28D+HYNSOuFzsyRDRvI/e1ICb69afwaUwfjr+25ZXldbOLyp+iDUZHq8UnTag==" + }, "sntp": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", @@ -3029,11 +3065,48 @@ "vinyl-source-stream": "1.1.0" } }, + "vscode-extension-telemetry": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.10.tgz", + "integrity": "sha512-5yiT9MAsdipdTV+xUK485PKluNL40jqhTy94TGDweTO/ecPS/qy4qSaJGI9gaKBwpOr5oP6jiI8Bm3yIOjB/2w==", + "requires": { + "applicationinsights": "0.18.0", + "winreg": "1.2.3" + } + }, + "vscode-extension-telemetry-wrapper": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry-wrapper/-/vscode-extension-telemetry-wrapper-0.2.0.tgz", + "integrity": "sha1-p/2oI1P1bEZ3kxrO0dvu5w9TJhw=", + "requires": { + "continuation-local-storage": "3.2.1", + "fs-extra": "5.0.0", + "uuid": "3.1.0", + "vscode-extension-telemetry": "0.0.10" + }, + "dependencies": { + "fs-extra": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + } + } + }, "vscode-nls": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz", "integrity": "sha1-gIUiOAhEuK0VNJmvXDsDkhrqAto=" }, + "winreg": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz", + "integrity": "sha1-k60RayaW2ofVj3JlqPzqUlSpZdU=" + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index a374721..8ac8842 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,9 @@ "name": "vscode-azureterraform", "displayName": "Azure Terraform", "description": "VS Code extension for developing with Terraform on Azure", - "version": "0.0.1", + "version": "0.1.0", "publisher": "Microsoft", + "aiKey": "ae482601-060f-4c71-8567-ebd5085483c9", "icon": "images/terraform.png", "repository": { "type": "git", @@ -35,6 +36,10 @@ "azureTerraform.terminal": { "type": "string", "default": "cloudshell", + "enum": [ + "cloudshell", + "integrated" + ], "description": "Specifies terminal used to run Terraform commands. Valid settings are `cloudshell` or `integrated`" }, "azureTerraform.files": { @@ -116,6 +121,7 @@ "opn": "5.1.0", "request-promise": "4.2.1", "semver": "5.4.1", + "vscode-extension-telemetry-wrapper": "^0.2.0", "vscode-nls": "2.0.2", "ws": "3.1.0" }, diff --git a/src/cloudConsole.ts b/src/cloudConsole.ts index 4036cbe..28b0247 100644 --- a/src/cloudConsole.ts +++ b/src/cloudConsole.ts @@ -4,6 +4,7 @@ import * as fsExtra from "fs-extra"; import * as path from "path"; import { clearInterval, setInterval } from "timers"; import { commands, window } from "vscode"; +import { TelemetryWrapper } from "vscode-extension-telemetry-wrapper"; import * as nls from "vscode-nls"; import { AzureAccount, AzureSession, AzureSubscription } from "./azure-account.api"; import { @@ -46,6 +47,7 @@ export async function openCloudConsole(api: AzureAccount, subscription: AzureSub if (isWindows && !await isNodeVersionValid()) { progress.cancel(); openUrlHint("Opening a Cloud Shell currently requires Node.js 6 or later being installed.", "https://nodejs.org"); + TelemetryWrapper.error("nodeNotValid"); return; } @@ -54,6 +56,7 @@ export async function openCloudConsole(api: AzureAccount, subscription: AzureSub progress.cancel(); await commands.executeCommand("azure-account.askForLogin"); if (!(await api.waitForLogin())) { + TelemetryWrapper.error("notLoginIn"); return; } } @@ -64,6 +67,7 @@ export async function openCloudConsole(api: AzureAccount, subscription: AzureSub if (!result) { progress.cancel(); openUrlHint("First launch of Cloud Shell requires setup in the Azure portal.", "https://portal.azure.com"); + TelemetryWrapper.error("needSetupCloudShell"); return; } @@ -104,6 +108,7 @@ export async function openCloudConsole(api: AzureAccount, subscription: AzureSub if (err && err.message === Errors.DeploymentOsTypeConflict) { return deploymentConflict(retry, result.token.accessToken, armEndpoint); } + TelemetryWrapper.error(err); throw err; } @@ -147,6 +152,7 @@ export async function openCloudConsole(api: AzureAccount, subscription: AzureSub terraformChannel.appendLine("Connecting to CloudShell failed with error: " + err); terraformChannel.show(); progress.cancel(); + TelemetryWrapper.error(err); throw err; }); } diff --git a/src/cloudShell.ts b/src/cloudShell.ts index 80a22c0..02fccb8 100644 --- a/src/cloudShell.ts +++ b/src/cloudShell.ts @@ -6,6 +6,7 @@ import * as os from "os"; import * as path from "path"; import * as vscode from "vscode"; import { MessageItem } from "vscode"; +import { TelemetryWrapper } from "vscode-extension-telemetry-wrapper"; import { AzureAccount, AzureSubscription } from "./azure-account.api"; import { BaseShell } from "./baseShell"; import { openCloudConsole, OSes } from "./cloudConsole"; @@ -133,6 +134,7 @@ export class CloudShell extends BaseShell { } await delay(500); } + TelemetryWrapper.error("sendToTerminalFail"); return false; } diff --git a/src/extension.ts b/src/extension.ts index 8619c8c..3e92763 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,6 +1,7 @@ "use strict"; import * as vscode from "vscode"; +import { TelemetryWrapper } from "vscode-extension-telemetry-wrapper"; import { BaseShell } from "./baseShell"; import { CloudShell } from "./cloudShell"; import { IntegratedShell } from "./integratedShell"; @@ -10,41 +11,49 @@ let cloudShell: CloudShell; let integratedShell: IntegratedShell; function getShell(): BaseShell { - if (terminalSetToCloudshell()) { + const isCloudShell: boolean = terminalSetToCloudshell(); + const session = TelemetryWrapper.currentSession(); + if (session && session.extraProperties) { + session.extraProperties.isCloudShell = isCloudShell; + } + + if (isCloudShell) { return cloudShell; } return integratedShell; } -export function activate(ctx: vscode.ExtensionContext) { +export async function activate(ctx: vscode.ExtensionContext) { cloudShell = new CloudShell(); integratedShell = new IntegratedShell(); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.init", () => { + await TelemetryWrapper.initilizeFromJsonFile(ctx.asAbsolutePath("./package.json")); + + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.init", () => { getShell().runTerraformCmd("terraform init"); })); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.plan", () => { + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.plan", () => { getShell().runTerraformCmd("terraform plan"); })); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.apply", () => { + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.apply", () => { getShell().runTerraformCmd("terraform apply"); })); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.destroy", () => { + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.destroy", () => { getShell().runTerraformCmd("terraform destroy"); })); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.refresh", () => { + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.refresh", () => { getShell().runTerraformCmd("terraform refresh"); })); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.validate", () => { + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.validate", () => { getShell().runTerraformCmd("terraform validate"); })); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.visualize", async () => { + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.visualize", async () => { if (terminalSetToCloudshell()) { const choice: vscode.MessageItem = await vscode.window.showInformationMessage( "Visualization only works locally. Would you like to run it in the integrated terminal?", @@ -58,7 +67,7 @@ export function activate(ctx: vscode.ExtensionContext) { await integratedShell.visualize(); })); - ctx.subscriptions.push(vscode.commands.registerCommand("azureTerraform.push", async () => { + ctx.subscriptions.push(TelemetryWrapper.registerCommand("azureTerraform.push", async () => { if (terminalSetToCloudshell()) { const tfFiles: vscode.Uri[] = await vscode.workspace.findFiles(filesGlobSetting()); await cloudShell.pushFiles(tfFiles); diff --git a/src/integratedShell.ts b/src/integratedShell.ts index 703db52..bbedf43 100644 --- a/src/integratedShell.ts +++ b/src/integratedShell.ts @@ -5,6 +5,7 @@ import * as os from "os"; import * as path from "path"; import * as vscode from "vscode"; import { commands, Uri, ViewColumn } from "vscode"; +import { TelemetryWrapper } from "vscode-extension-telemetry-wrapper"; import { BaseShell } from "./baseShell"; import { Constants } from "./constants"; import { TerminalType, TestOption, TFTerminal } from "./shared"; @@ -23,10 +24,12 @@ export class IntegratedShell extends BaseShell { // Creates a png of terraform resource graph to visualize the resources under management. public async visualize(): Promise { if (!await isDotInstalled()) { + TelemetryWrapper.error("dotNotInstalled"); return; } const cwd: string = await selectWorkspaceFolder(); if (!cwd) { + TelemetryWrapper.error("noWorkspaceSelected"); return; } await this.deletePng(cwd); @@ -54,12 +57,14 @@ export class IntegratedShell extends BaseShell { public async runTerraformTests(TestType: string, workingDirectory: string) { if (!await isDockerInstalled()) { + TelemetryWrapper.error("dockerNotInstalled"); return; } const containerName: string = vscode.workspace.getConfiguration("azureTerraform").get("test-container"); terraformChannel.appendLine("Checking Azure Service Principal environment variables..."); if (!isServicePrincipalSetInEnv()) { + TelemetryWrapper.error("servicePrincipalEnvInvalid"); return; }