提交 d5736304 编写于 作者: R Rob Lourens

Settings search - fix feedback and telemetry to handle extension setting results

上级 6ae8a18c
......@@ -294,20 +294,24 @@ export class PreferencesEditor extends BaseEditor {
}
}
private reportFilteringUsed(filter: string, counts: IStringDictionary<number>, metadata?: IFilterMetadata): void {
private reportFilteringUsed(filter: string, counts: IStringDictionary<number>, metadata?: IStringDictionary<IFilterMetadata>): void {
if (filter && filter !== this._lastReportedFilter) {
let durations: any;
if (metadata) {
durations = Object.create(null);
Object.keys(metadata).forEach(key => durations[key] = metadata[key].duration);
}
let data = {
filter,
duration: metadata ? metadata.duration : undefined,
context: metadata ? metadata.context : undefined,
durations,
counts
};
/* __GDPR__
"defaultSettings.filter" : {
"filter": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"context" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"durations" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"counts" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
......@@ -352,7 +356,7 @@ class SettingsNavigator implements INavigator<ISetting> {
interface IFilterOrSearchResult {
defaultSettingsGroupCounts: IStringDictionary<number>;
metadata: IFilterMetadata;
metadata: IStringDictionary<IFilterMetadata>;
}
class PreferencesRenderersController extends Disposable {
......
......@@ -113,7 +113,6 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend
if (this.filterResult) {
data['query'] = this.filterResult.query;
data['duration'] = this.filterResult.metadata && this.filterResult.metadata.duration;
data['index'] = source.index;
data['groupId'] = source.groupId;
data['editableSide'] = !!fromEditableSettings;
......@@ -123,9 +122,8 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend
"defaultSettingsActions.copySetting" : {
"userConfigurationKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"query" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"index" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"editableSide" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
......@@ -622,31 +620,35 @@ export class FeedbackWidgetRenderer extends Disposable {
}
const result = this._currentResult;
const actualResults = result.metadata.scoredResults;
const metadata = result.metadata['nlpResult']; // Feedback only on nlpResult set for now
const marketplaceExtensionsResults = result.metadata['newExtensionsResult'] && result.metadata['newExtensionsResult'].scoredResults;
const actualResults = metadata ? metadata.scoredResults : {};
const actualResultIds = Object.keys(actualResults);
const feedbackQuery: any = {};
feedbackQuery['comment'] = FeedbackWidgetRenderer.DEFAULT_COMMENT_TEXT;
feedbackQuery['queryString'] = result.query;
feedbackQuery['resultScores'] = {};
feedbackQuery['resultScores'] = [];
actualResultIds.forEach(settingId => {
const outputKey = actualResults[settingId].key;
feedbackQuery['resultScores'][outputKey] = 10;
feedbackQuery['resultScores'].push({
packageID: actualResults[settingId].packageId,
key: actualResults[settingId].key,
score: 10
});
});
feedbackQuery['alts'] = [];
const contents = FeedbackWidgetRenderer.INSTRUCTION_TEXT + '\n' +
JSON.stringify(feedbackQuery, undefined, ' ') + '\n\n' +
actualResultIds.map(name => {
return `// ${actualResults[name].key}: ${actualResults[name].score}`;
}).join('\n');
this.getScoreText(actualResults) + '\n\n' +
this.getScoreText(marketplaceExtensionsResults) + '\n';
this.editorService.openEditor({ contents, language: 'jsonc' }, /*sideBySide=*/true).then(feedbackEditor => {
const sendFeedbackWidget = this._register(this.instantiationService.createInstance(FloatingClickWidget, feedbackEditor.getControl(), 'Send feedback', null));
sendFeedbackWidget.render();
this._register(sendFeedbackWidget.onClick(() => {
this.sendFeedback(feedbackEditor.getControl() as ICodeEditor, result, result.metadata.scoredResults).then(() => {
this.sendFeedback(feedbackEditor.getControl() as ICodeEditor, result, metadata.scoredResults).then(() => {
sendFeedbackWidget.dispose();
this.messageService.show(Severity.Info, 'Feedback sent successfully');
}, err => {
......@@ -656,6 +658,17 @@ export class FeedbackWidgetRenderer extends Disposable {
});
}
private getScoreText(results?: IScoredResults): string {
if (!results) {
return '';
}
return Object.keys(results)
.map(name => {
return `// ${results[name].key}: ${results[name].score}`;
}).join('\n');
}
private sendFeedback(feedbackEditor: ICodeEditor, result: IFilterResult, actualResults: IScoredResults): TPromise<void> {
const model = feedbackEditor.getModel();
const expectedQueryLines = model.getLinesContent()
......@@ -685,11 +698,9 @@ export class FeedbackWidgetRenderer extends Disposable {
"settingsSearchResultFeedback" : {
"query" : { "classification": "CustomContent", "purpose": "FeatureInsight" },
"userComment" : { "classification": "CustomerContent", "purpose": "FeatureInsight" },
"actualResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"expectedResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"url" : { "classification": "CustomerContent", "purpose": "FeatureInsight" },
"actualResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"timestamp" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
return this.telemetryService.publicLog('settingsSearchResultFeedback', {
......@@ -697,9 +708,7 @@ export class FeedbackWidgetRenderer extends Disposable {
userComment,
actualResults,
expectedResults: expectedQuery.resultScores,
url: result.metadata.remoteUrl,
duration: result.metadata.duration,
timestamp: result.metadata.timestamp,
duration: result.metadata['nlpResult'].duration,
buildNumber: this.environmentService.settingsSearchBuildId,
alts,
autoIngest
......
......@@ -16,6 +16,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { join } from 'vs/base/common/paths';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import Event from 'vs/base/common/event';
import { IStringDictionary } from 'vs/base/common/collections';
export interface IWorkbenchSettingsConfiguration {
workbench: {
......@@ -79,7 +80,7 @@ export interface IFilterResult {
filteredGroups: ISettingsGroup[];
allGroups: ISettingsGroup[];
matches: IRange[];
metadata?: IFilterMetadata;
metadata?: IStringDictionary<IFilterMetadata>;
}
export interface ISettingMatch {
......@@ -104,7 +105,8 @@ export interface IRemoteSetting {
}
export interface IFilterMetadata {
remoteUrl: string;
requestUrl: string;
requestBody: string;
timestamp: number;
duration: number;
scoredResults: IScoredResults;
......
......@@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import { assign } from 'vs/base/common/objects';
import * as map from 'vs/base/common/map';
import { tail, flatten, first } from 'vs/base/common/arrays';
import { tail, flatten } from 'vs/base/common/arrays';
import URI from 'vs/base/common/uri';
import { IReference, Disposable } from 'vs/base/common/lifecycle';
import Event, { Emitter } from 'vs/base/common/event';
......@@ -15,12 +15,13 @@ import { visit, JSONVisitor } from 'vs/base/common/json';
import { ITextModel, IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
import { EditorModel } from 'vs/workbench/common/editor';
import { IConfigurationNode, IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN, IConfigurationPropertySchema, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { ISettingsEditorModel, IKeybindingsEditorModel, ISettingsGroup, ISetting, IFilterResult, IGroupFilter, ISettingMatcher, ISettingMatch, ISearchResultGroup } from 'vs/workbench/parts/preferences/common/preferences';
import { ISettingsEditorModel, IKeybindingsEditorModel, ISettingsGroup, ISetting, IFilterResult, IGroupFilter, ISettingMatcher, ISettingMatch, ISearchResultGroup, IFilterMetadata } from 'vs/workbench/parts/preferences/common/preferences';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ITextEditorModel } from 'vs/editor/common/services/resolverService';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { Selection } from 'vs/editor/common/core/selection';
import { IStringDictionary } from 'vs/base/common/collections';
export abstract class AbstractSettingsModel extends EditorModel {
......@@ -114,6 +115,19 @@ export abstract class AbstractSettingsModel extends EditorModel {
};
}
protected collectMetadata(groups: ISearchResultGroup[]): IStringDictionary<IFilterMetadata> {
const metadata = Object.create(null);
let hasMetadata = false;
groups.forEach(g => {
if (g.result.metadata) {
metadata[g.id] = g.result.metadata;
hasMetadata = true;
}
});
return hasMetadata ? metadata : null;
}
protected get filterGroups(): ISettingsGroup[] {
return this.settingsGroups;
......@@ -205,12 +219,12 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti
};
}
const groupWithMetadata = first(resultGroups, group => !!group.result.metadata);
const metadata = this.collectMetadata(resultGroups);
return <IFilterResult>{
allGroups: this.settingsGroups,
filteredGroups: filteredGroup ? [filteredGroup] : [],
matches,
metadata: groupWithMetadata && groupWithMetadata.result.metadata
metadata
};
}
}
......@@ -648,13 +662,13 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
const startLine = tail(this.settingsGroups).range.endLineNumber + 2;
const { settingsGroups: filteredGroups, matches } = this.writeResultGroups(nonEmptyResultGroups, startLine);
const groupWithMetadata = first(resultGroups, group => !!group.result.metadata);
const metadata = this.collectMetadata(resultGroups);
return resultGroups.length ?
<IFilterResult>{
allGroups: this.settingsGroups,
filteredGroups,
matches,
metadata: groupWithMetadata && groupWithMetadata.result.metadata
metadata
} :
null;
}
......
......@@ -243,7 +243,8 @@ class RemoteSearchProvider implements ISearchProvider {
});
return <IFilterMetadata>{
remoteUrl: details.url, // telemetry for filter text?
requestUrl: details.url,
requestBody: details.body,
duration,
timestamp,
scoredResults,
......@@ -337,7 +338,7 @@ class RemoteSearchProvider implements ISearchProvider {
function getSettingKey(name: string, packageId?: string): string {
return packageId ?
packageId + '_' + name :
packageId + '##' + name :
name;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册