diff --git a/CHANGELOG.md b/CHANGELOG.md index 01e04d928..0408af70f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## 0.6.1 + +### New Features & Improvements + +- **Feedback Optimization**: Introduces privacy consent and feedback signal controls for the Query Insights feature, primarily to ensure compliance with organizational data protection requirements and user telemetry settings. It also disables survey functionality and refines the feedback dialog UI. [#392](https://github.com/microsoft/vscode-documentdb/pull/392) + +### Fixes + +- **Privacy Policy Link**: Updated the outdated privacy policy link in the README to the current Microsoft privacy statement URL. [#388](https://github.com/microsoft/vscode-documentdb/pull/388) + ## 0.6.0 ### New Features & Improvements diff --git a/README.md b/README.md index 80366fc35..06ad20704 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ This project may contain trademarks or logos for projects, products, or services # Telemetry -VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). +VS Code collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkId=521839) to learn more. If you don’t wish to send usage data to Microsoft, you can set the `telemetry.enableTelemetry` setting to `false`. Learn more in our [FAQ](https://code.visualstudio.com/docs/supporting/faq#_how-to-disable-telemetry-reporting). # License diff --git a/docs/index.md b/docs/index.md index 277b9b5a5..31379ec01 100644 --- a/docs/index.md +++ b/docs/index.md @@ -64,7 +64,7 @@ The User Manual provides guidance on using DocumentDB for VS Code. It contains d Explore the history of updates and improvements to the DocumentDB for VS Code extension. Each release brings new features, enhancements, and fixes to improve your experience. -- [0.6](./release-notes/0.6) +- [0.6](./release-notes/0.6), [0.6.1](./release-notes/0.6#patch-release-v061) - [0.5](./release-notes/0.5), [0.5.1](./release-notes/0.5#patch-release-v051), [0.5.2](./release-notes/0.5#patch-release-v052) - [0.4](./release-notes/0.4), [0.4.1](./release-notes/0.4#patch-release-v041) - [0.3](./release-notes/0.3), [0.3.1](./release-notes/0.3#patch-release-v031) diff --git a/docs/release-notes/0.6.md b/docs/release-notes/0.6.md index 02756df84..c6e8ef7db 100644 --- a/docs/release-notes/0.6.md +++ b/docs/release-notes/0.6.md @@ -12,34 +12,34 @@ We are excited to announce the release of **DocumentDB for VS Code Extension v0. We are introducing a major new feature: **Query Insights with Performance Advisor**. This powerful tool helps you understand and optimize your queries directly within VS Code. When you run a `find` query against your DocumentDB or MongoDB API database, a new **"Query Insights"** tab appears, providing a three-stage analysis of your query's performance. -

Authentication Method Selection

+

Authentication Method Selection

-- **Stage 1: Initial Performance View** - The first stage provides an immediate, low-cost static analysis of your query. It visualizes the query plan, showing how the database intends to execute your query. This helps you understand performance bottlenecks and the query's processing stages without re-running it. +- **Stage 1: Initial Performance View** + The first stage provides an immediate, low-cost static analysis of your query. It visualizes the query plan, showing how the database intends to execute your query. This helps you understand performance bottlenecks and the query's processing stages without re-running it. -- **Stage 2: Detailed Execution Analysis** - For a deeper dive, the second stage runs a detailed execution analysis using `executionStats` to gather authoritative metrics. You'll see precise counts for documents and keys examined, server-side execution time, and a detailed breakdown of each stage in the execution plan. This provides clear insights into how your query actually performed. +- **Stage 2: Detailed Execution Analysis** + For a deeper dive, the second stage runs a detailed execution analysis using `executionStats` to gather authoritative metrics. You'll see precise counts for documents and keys examined, server-side execution time, and a detailed breakdown of each stage in the execution plan. This provides clear insights into how your query actually performed. - The complex JSON response from the database is translated into an easy-to-comprehend chart, making it simple to visualize the query's execution flow. + The complex JSON response from the database is translated into an easy-to-comprehend chart, making it simple to visualize the query's execution flow. - Additionally, a **Query Efficiency Analysis** card provides a quick performance assessment. It highlights key aspects of the query's execution, such as the execution strategy, index usage, and whether an in-memory sort occurred. A performance rating (Good, Fair, or Poor) helps you quickly identify an inefficient or slow query. + Additionally, a **Query Efficiency Analysis** card provides a quick performance assessment. It highlights key aspects of the query's execution, such as the execution strategy, index usage, and whether an in-memory sort occurred. A performance rating (Good, Fair, or Poor) helps you quickly identify an inefficient or slow query. -- **Stage 3: AI-Powered Recommendations with GitHub Copilot** - The final stage brings the power of AI to your query optimization workflow. By clicking `Get AI Performance Insights`, the extension sends the query shape and execution statistics to a service powered by **GitHub Copilot**. For more details, please see our [documentation](https://learn.microsoft.com/en-us/azure/documentdb/index-advisor). +- **Stage 3: AI-Powered Recommendations with GitHub Copilot** + The final stage brings the power of AI to your query optimization workflow. By clicking `Get AI Performance Insights`, the extension sends the query shape and execution statistics to a service powered by **GitHub Copilot**. For more details, please see our [documentation](https://learn.microsoft.com/en-us/azure/documentdb/index-advisor). - The AI assistant provides: + The AI assistant provides: - > πŸ•΅οΈβ€β™‚οΈ **Analysis** - > - > A summary of the query's performance. + > πŸ•΅οΈβ€β™‚οΈ **Analysis** + > + > A summary of the query's performance. - > πŸ“ˆ **Actionable Recommendations** - > - > Suggestions for creating, hiding, or unhiding indexes to improve performance, with an option to apply them directly. + > πŸ“ˆ **Actionable Recommendations** + > + > Suggestions for creating, hiding, or unhiding indexes to improve performance, with an option to apply them directly. - > πŸŽ“ **Detailed Explanations** - > - > A breakdown of the execution plan to help you understand how the query was processed. + > πŸŽ“ **Detailed Explanations** + > + > A breakdown of the execution plan to help you understand how the query was processed. The **"Query Insights"** feature helps solve performance issues and educates users on query best practices for DocumentDB and MongoDB API databases. @@ -49,7 +49,7 @@ We've enhanced the query authoring experience to support more sophisticated quer The `projection` and `sort` fields also support the same rich autocompletion that was previously available for the `filter` field. -

Authentication Method Selection

+

Authentication Method Selection

### ⭐ Index Management from the Tree View @@ -69,3 +69,24 @@ Hovering over an index will show you its details, and the context menu provides See the full changelog entry for this release: ➑️ [CHANGELOG.md#060](https://github.com/microsoft/vscode-documentdb/blob/main/CHANGELOG.md#060) + +--- + +## Patch Release v0.6.1 + +This patch release introduces feedback optimization and fixes a broken link. + +### What's Changed in v0.6.1 + +#### **Feedback Optimization** ([#392](https://github.com/microsoft/vscode-documentdb/pull/392)) + +Introduces privacy consent and feedback signal controls for the Query Insights feature, primarily to ensure compliance with organizational data protection requirements and user telemetry settings. It also disables survey functionality and refines the feedback dialog UI. + +#### **Privacy Policy Link Update** ([#388](https://github.com/microsoft/vscode-documentdb/pull/388)) + +Updated the outdated privacy policy link in the README to the current Microsoft privacy statement URL. + +### Changelog + +See the full changelog entry for this release: +➑️ [CHANGELOG.md#061](https://github.com/microsoft/vscode-documentdb/blob/main/CHANGELOG.md#061) diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 73a612d08..7e7e9b43d 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -384,6 +384,7 @@ "HIGH PRIORITY": "HIGH PRIORITY", "How do you want to connect?": "How do you want to connect?", "How would you rate Query Insights?": "How would you rate Query Insights?", + "I have read and agree to the ": "I have read and agree to the ", "I like it": "I like it", "I want to choose the server from an online registry.": "I want to choose the server from an online registry.", "I want to connect to a local DocumentDB instance.": "I want to connect to a local DocumentDB instance.", @@ -484,6 +485,7 @@ "Manage Azure Accounts": "Manage Azure Accounts", "Manually enter a custom tenant ID": "Manually enter a custom tenant ID", "MEDIUM PRIORITY": "MEDIUM PRIORITY", + "Microsoft will process the feedback data you submit on behalf of your organization in accordance with the Data Protection Addendum between your organization and Microsoft.": "Microsoft will process the feedback data you submit on behalf of your organization in accordance with the Data Protection Addendum between your organization and Microsoft.", "Migration of connections from the Azure Databases VS Code Extension to the DocumentDB for VS Code Extension completed: {migratedCount} connections migrated.": "Migration of connections from the Azure Databases VS Code Extension to the DocumentDB for VS Code Extension completed: {migratedCount} connections migrated.", "Missing important information": "Missing important information", "Modify index?": "Modify index?", @@ -558,10 +560,10 @@ "Port number is required": "Port number is required", "Port number must be a number": "Port number must be a number", "Port number must be between 1 and 65535": "Port number must be between 1 and 65535", + "Privacy Statement": "Privacy Statement", "Procedure not found: {name}": "Procedure not found: {name}", "Process exited: \"{command}\"": "Process exited: \"{command}\"", "Project": "Project", - "Provide Feedback": "Provide Feedback", "Provider \"{0}\" does not have resource type \"{1}\".": "Provider \"{0}\" does not have resource type \"{1}\".", "Query Efficiency Analysis": "Query Efficiency Analysis", "Query Execution Failed": "Query Execution Failed", diff --git a/package-lock.json b/package-lock.json index c490e9fe8..b0239bddd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-documentdb", - "version": "0.6.0", + "version": "0.6.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-documentdb", - "version": "0.6.0", + "version": "0.6.1", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@azure/arm-compute": "^22.4.0", diff --git a/package.json b/package.json index ac3f3928e..3219dee4d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vscode-documentdb", - "version": "0.6.0", + "version": "0.6.1", "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", "publisher": "ms-azuretools", "displayName": "DocumentDB for VS Code", diff --git a/src/commands/openCollectionView/openCollectionView.ts b/src/commands/openCollectionView/openCollectionView.ts index 0c4a6fb03..9de16d3e3 100644 --- a/src/commands/openCollectionView/openCollectionView.ts +++ b/src/commands/openCollectionView/openCollectionView.ts @@ -5,6 +5,8 @@ import { type IActionContext } from '@microsoft/vscode-azext-utils'; import * as l10n from '@vscode/l10n'; +import * as vscode from 'vscode'; + import { ClusterSession } from '../../documentdb/ClusterSession'; import { type CollectionItem } from '../../tree/documentdb/CollectionItem'; import { CollectionViewController } from '../../webviews/documentdb/collectionView/collectionViewController'; @@ -37,11 +39,23 @@ export async function openCollectionViewInternal( */ const sessionId = await ClusterSession.initNewSession(props.clusterId); + // Enable feedback signals only when telemetry level is set to "all" + // See: https://code.visualstudio.com/docs/setup/enterprise#_configure-telemetry-level + let feedbackSignalsEnabled = false; + try { + const telemetryLevel = vscode.workspace.getConfiguration('telemetry').get('telemetryLevel'); + feedbackSignalsEnabled = telemetryLevel === 'all'; + } catch { + // If we fail to read telemetry settings, default to false + feedbackSignalsEnabled = false; + } + const view = new CollectionViewController({ sessionId: sessionId, clusterId: props.clusterId, databaseName: props.databaseName, collectionName: props.collectionName, + feedbackSignalsEnabled: feedbackSignalsEnabled, }); view.revealToForeground(); diff --git a/src/utils/survey.initSurvey.test.ts b/src/utils/survey.initSurvey.test.ts index 99eff26f8..bc599f3d5 100644 --- a/src/utils/survey.initSurvey.test.ts +++ b/src/utils/survey.initSurvey.test.ts @@ -81,6 +81,9 @@ describe('Survey Initialization', () => { // This directly modifies the surveyState object in the survey.ts module surveyStateRef.isCandidate = undefined; + // Enable survey for tests (it's disabled in production) + SurveyConfig.settings.DISABLE_SURVEY = false; + // Set up default A/B test mocks for passing mockABTestPassing(); diff --git a/src/utils/survey.prompt.test.ts b/src/utils/survey.prompt.test.ts index bc37bc741..7ab8b3fa9 100644 --- a/src/utils/survey.prompt.test.ts +++ b/src/utils/survey.prompt.test.ts @@ -78,6 +78,9 @@ describe('Survey Prompt', () => { surveyState.wasPromptedInSession = false; surveyState.isCandidate = true; + // Enable survey for tests (it's disabled in production) + surveyConfig.settings.DISABLE_SURVEY = false; + // Reset mocks jest.clearAllMocks(); diff --git a/src/utils/survey.scoring.test.ts b/src/utils/survey.scoring.test.ts index 125cad12e..5453c351c 100644 --- a/src/utils/survey.scoring.test.ts +++ b/src/utils/survey.scoring.test.ts @@ -56,6 +56,9 @@ describe('Survey Scoring', () => { surveyState.usageScore = 0; surveyState.wasPromptedInSession = false; + // Enable survey for tests (it's disabled in production) + surveyConfig.settings.DISABLE_SURVEY = false; + // Clear mock calls between tests jest.clearAllMocks(); }); diff --git a/src/utils/survey.ts b/src/utils/survey.ts index 0b8836fa3..719f9820e 100644 --- a/src/utils/survey.ts +++ b/src/utils/survey.ts @@ -18,7 +18,7 @@ const SurveyConfig = { }, settings: { DEBUG_ALWAYS_PROMPT: false, // Forces survey prompt regardless of conditions - DISABLE_SURVEY: false, // Completely disables survey functionality + DISABLE_SURVEY: true, // Completely disables survey functionality PROBABILITY: 1, // Probability to become candidate (0-1), Azure Tools uses 0.15 A_B_TEST_SELECTION: 1, // change this value to adjust the candidate selection (e.g. 0.50 for 50% of users) PROMPT_ENGLISH_ONLY: false, // Whether to limit survey to English locales diff --git a/src/webviews/documentdb/collectionView/collectionViewController.ts b/src/webviews/documentdb/collectionView/collectionViewController.ts index 5b15d307e..6c41fac51 100644 --- a/src/webviews/documentdb/collectionView/collectionViewController.ts +++ b/src/webviews/documentdb/collectionView/collectionViewController.ts @@ -15,6 +15,7 @@ export type CollectionViewWebviewConfigurationType = { databaseName: string; collectionName: string; defaultPageSize: number; + feedbackSignalsEnabled: boolean; }; export class CollectionViewController extends WebviewController { diff --git a/src/webviews/documentdb/collectionView/components/queryInsightsTab/QueryInsightsTab.tsx b/src/webviews/documentdb/collectionView/components/queryInsightsTab/QueryInsightsTab.tsx index f327337d8..f2985ab77 100644 --- a/src/webviews/documentdb/collectionView/components/queryInsightsTab/QueryInsightsTab.tsx +++ b/src/webviews/documentdb/collectionView/components/queryInsightsTab/QueryInsightsTab.tsx @@ -35,8 +35,10 @@ import { ChatMailRegular, SparkleRegular, WarningRegular } from '@fluentui/react import { CollapseRelaxed } from '@fluentui/react-motion-components-preview'; import * as l10n from '@vscode/l10n'; import { useCallback, useContext, useEffect, useState, type JSX } from 'react'; +import { useConfiguration } from '../../../../api/webview-client/useConfiguration'; import { useTrpcClient } from '../../../../api/webview-client/useTrpcClient'; import { CollectionViewContext } from '../../collectionViewContext'; +import { type CollectionViewWebviewConfigurationType } from '../../collectionViewController'; import { type ImprovementCard as ImprovementCardConfig } from '../../types/queryInsights'; import { extractErrorCode } from '../../utils/errorCodeExtractor'; import { AnimatedCardList, FeedbackCard, FeedbackDialog, type AnimatedCardItem } from './components'; @@ -62,6 +64,11 @@ export const QueryInsightsMain = (): JSX.Element => { // Stage 3: AI-Powered Recommendations (opt-in) // See: docs/design-documents/performance-advisor.md + /** + * Use the configuration object to access the data passed to the webview at its creation. + */ + const configuration = useConfiguration(); + const { trpcClient } = useTrpcClient(); const [currentContext, setCurrentContext] = useContext(CollectionViewContext); const { queryInsights: queryInsightsState } = currentContext; @@ -858,9 +865,10 @@ export const QueryInsightsMain = (): JSX.Element => { /> {/* Feedback Card - hidden for RU accounts where Query Insights is not available */} - {queryInsightsState.stage1ErrorCode !== 'QUERY_INSIGHTS_PLATFORM_NOT_SUPPORTED_RU' && ( - - )} + {configuration.feedbackSignalsEnabled && + queryInsightsState.stage1ErrorCode !== 'QUERY_INSIGHTS_PLATFORM_NOT_SUPPORTED_RU' && ( + + )} diff --git a/src/webviews/documentdb/collectionView/components/queryInsightsTab/components/FeedbackDialog.tsx b/src/webviews/documentdb/collectionView/components/queryInsightsTab/components/FeedbackDialog.tsx index 6fd278059..006700c72 100644 --- a/src/webviews/documentdb/collectionView/components/queryInsightsTab/components/FeedbackDialog.tsx +++ b/src/webviews/documentdb/collectionView/components/queryInsightsTab/components/FeedbackDialog.tsx @@ -12,6 +12,7 @@ import { DialogContent, DialogSurface, DialogTitle, + Divider, Link, Text, } from '@fluentui/react-components'; @@ -36,11 +37,13 @@ export interface FeedbackDialogProps { export const FeedbackDialog = ({ open, onClose, sentiment, onSubmit }: FeedbackDialogProps): JSX.Element => { const [selectedReasons, setSelectedReasons] = useState>(new Set()); const [isSubmitting, setIsSubmitting] = useState(false); + const [consentChecked, setConsentChecked] = useState(false); - // Reset selected reasons when sentiment changes + // Reset selected reasons and consent when sentiment changes or dialog closes useEffect(() => { setSelectedReasons(new Set()); - }, [sentiment]); + setConsentChecked(false); + }, [sentiment, open]); const positiveReasons = [ l10n.t('Data shown was correct'), @@ -88,10 +91,15 @@ export const FeedbackDialog = ({ open, onClose, sentiment, onSubmit }: FeedbackD const handleClose = () => { if (!isSubmitting) { setSelectedReasons(new Set()); + setConsentChecked(false); onClose(); } }; + const consentNoticeText = l10n.t( + 'Microsoft will process the feedback data you submit on behalf of your organization in accordance with the Data Protection Addendum between your organization and Microsoft.', + ); + return ( !data.open && handleClose()}> @@ -141,11 +149,10 @@ export const FeedbackDialog = ({ open, onClose, sentiment, onSubmit }: FeedbackD gap: '8px', }} > - + {l10n.t( 'These signals help us improve, but more context in a discussion, issue report, or a direct message adds even more value. ', )} -
+ + {/* Horizontal divider */} + + + {/* Privacy consent section */} +
+ {/* Consent checkbox */} + setConsentChecked(data.checked === true)} + label={ + + {l10n.t('I have read and agree to the ')}{' '} + + {l10n.t('Privacy Statement')} + + + } + /> + + {/* Privacy notice text */} + {consentNoticeText} +
-