Skip to content

Commit 1996083

Browse files
frankliu20FrankLiu4138Copilotwenytang-ms
authored
chore: improve java upgrade telemetry tracking and extension installation flow (#1030)
* Add source/install telemetry and drop unreliable activation check Follow-up to v0.27.5 telemetry analysis (devdiv-azure-service-dmitryr/azure-java-migration-copilot-vscode-extension#5979): - Add a source field (SOURCE_CVE / SOURCE_JAVA_UPGRADE) to the upgradeNotification.show event so NOTIFY-level data can be split by CVE vs upgrade and aligned with downstream funnel stages. - Emit an installSucceeded event (with the initial extensionState, so fresh installs and updates can be told apart) right after installExtension resolves. - Drop the post-install getExtensionState re-check that produced false activation-timeout results; the not-installed path now reports proceeded and returns true after install completes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Drop dedicated installSucceeded telemetry event Address review: avoid adding a new business operationName for the install step. Install success is already implied by the subsequent upgradeFlow.result event under the same operation ID. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Track install-success as a dimension on the result event Address review: instead of a dedicated installSucceeded operationName, reuse the stable java.dependency.upgradeFlow.result event and mark the install step with an upgradeFlowStep dimension (plus extensionState so fresh installs and updates can be told apart). Easier to query and evolve. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Label install step by action instead of pre-install state Address review: extensionState was the pre-install value, so tagging a 'succeeded' event with 'not-installed'/'outdated' was contradictory. Replace it with installType ('installed' vs 'updated') derived from the pre-install state, which is unambiguous and avoids an unreliable post-install state recompute (the original activation-race bug). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Don't prompt to enable extension in upgrade flow extensions.getExtension() returns undefined both when the extension is disabled and when it is freshly installed but not yet activated, so the 'seems disabled, enable it manually' prompt is misleading right after a successful install. Skip it on the upgrade path; the function and the modernization caller are left unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Wait for extension registration via onDidChange instead of fixed sleep Replace the fixed 2s wait after a fresh install with an event-driven wait: resolve immediately if the extension is already registered, otherwise listen on extensions.onDidChange and proceed as soon as it appears, with a 5s timeout fallback. Returns as early as possible while still bounding the wait. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Frank Liu <haital@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: wenyt <75360946+wenytang-ms@users.noreply.github.com>
1 parent 0dc2467 commit 1996083

2 files changed

Lines changed: 33 additions & 10 deletions

File tree

src/upgrade/display/notificationManager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class NotificationManager implements IUpgradeIssuesRenderer {
9393
sendInfo(operationId, {
9494
operationName: "java.dependency.upgradeNotification.show",
9595
extensionState,
96+
source: hasCVEIssue ? Upgrade.SOURCE_CVE : Upgrade.SOURCE_JAVA_UPGRADE,
9697
});
9798

9899
const buttons = hasCVEIssue

src/upgrade/utility.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ export async function checkOrInstallAppModExtensionForUpgrade(
197197
}
198198

199199
await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
200+
sendInfo(operationId, {
201+
operationName: "java.dependency.upgradeFlow.result",
202+
upgradeFlowStep: "installSucceeded",
203+
installType: state === "outdated" ? "updated" : "installed",
204+
});
200205

201206
if (state === "outdated") {
202207
// Extension was updated (not freshly installed) — reload required
@@ -219,18 +224,35 @@ export async function checkOrInstallAppModExtensionForUpgrade(
219224
return false;
220225
}
221226

222-
await checkOrPromptToEnableAppModExtension("upgrade");
227+
// Wait until the freshly installed extension is registered, returning as
228+
// soon as it is ready, or after a 5s timeout fallback at the latest.
229+
await waitForExtensionReady(extensionIdToCheck, 5000);
223230

224-
// Wait briefly for the newly installed extension to activate
225-
await new Promise(resolve => setTimeout(resolve, 2000));
226-
227-
// Re-check if the newly installed extension is active and meets version requirement
228-
const newState = getExtensionState(extensionIdToCheck);
229-
const canProceed = newState === "up-to-date";
230231
sendInfo(operationId, {
231232
operationName: "java.dependency.upgradeFlow.result",
232-
upgradeFlowResult: canProceed ? "proceeded" : "activation-timeout",
233+
upgradeFlowResult: "proceeded",
233234
});
234-
return canProceed;
235+
return true;
235236
})();
236-
}
237+
}
238+
239+
function waitForExtensionReady(extensionId: string, timeoutMs: number): Promise<void> {
240+
return new Promise<void>(resolve => {
241+
if (extensions.getExtension(extensionId)) {
242+
resolve();
243+
return;
244+
}
245+
let timer: NodeJS.Timeout;
246+
const disposable = extensions.onDidChange(() => {
247+
if (extensions.getExtension(extensionId)) {
248+
clearTimeout(timer);
249+
disposable.dispose();
250+
resolve();
251+
}
252+
});
253+
timer = setTimeout(() => {
254+
disposable.dispose();
255+
resolve();
256+
}, timeoutMs);
257+
});
258+
}

0 commit comments

Comments
 (0)