@@ -23,6 +23,7 @@ import { Iterable } from '../../../../base/common/iterator.js';
23
23
import { KeyCode } from '../../../../base/common/keyCodes.js' ;
24
24
import { Disposable , DisposableStore , dispose , type IDisposable , MutableDisposable } from '../../../../base/common/lifecycle.js' ;
25
25
import * as platform from '../../../../base/common/platform.js' ;
26
+ import { StopWatch } from '../../../../base/common/stopwatch.js' ;
26
27
import { ThemeIcon } from '../../../../base/common/themables.js' ;
27
28
import { URI } from '../../../../base/common/uri.js' ;
28
29
import { ILanguageService } from '../../../../editor/common/languages/language.js' ;
@@ -58,7 +59,7 @@ import { nullRange, Settings2EditorModel } from '../../../services/preferences/c
58
59
import { IUserDataProfileService } from '../../../services/userDataProfile/common/userDataProfile.js' ;
59
60
import { IUserDataSyncWorkbenchService } from '../../../services/userDataSync/common/userDataSync.js' ;
60
61
import { SuggestEnabledInput } from '../../codeEditor/browser/suggestEnabledInput/suggestEnabledInput.js' ;
61
- import { CONTEXT_SETTINGS_EDITOR , CONTEXT_SETTINGS_ROW_FOCUS , CONTEXT_SETTINGS_SEARCH_FOCUS , CONTEXT_TOC_ROW_FOCUS , ENABLE_LANGUAGE_FILTER , EXTENSION_FETCH_TIMEOUT_MS , EXTENSION_SETTING_TAG , FEATURE_SETTING_TAG , getExperimentalExtensionToggleData , ID_SETTING_TAG , IPreferencesSearchService , ISearchProvider , LANGUAGE_SETTING_TAG , MODIFIED_SETTING_TAG , POLICY_SETTING_TAG , REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG , SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS , SETTINGS_EDITOR_COMMAND_SHOW_AI_RESULTS , SETTINGS_EDITOR_COMMAND_SUGGEST_FILTERS , WorkbenchSettingsEditorSettings , WORKSPACE_TRUST_SETTING_TAG } from '../common/preferences.js' ;
62
+ import { CONTEXT_SETTINGS_EDITOR , CONTEXT_SETTINGS_ROW_FOCUS , CONTEXT_SETTINGS_SEARCH_FOCUS , CONTEXT_TOC_ROW_FOCUS , EMBEDDINGS_SEARCH_PROVIDER_NAME , ENABLE_LANGUAGE_FILTER , EXTENSION_FETCH_TIMEOUT_MS , EXTENSION_SETTING_TAG , FEATURE_SETTING_TAG , FILTER_MODEL_SEARCH_PROVIDER_NAME , getExperimentalExtensionToggleData , ID_SETTING_TAG , IPreferencesSearchService , ISearchProvider , LANGUAGE_SETTING_TAG , LLM_RANKED_SEARCH_PROVIDER_NAME , MODIFIED_SETTING_TAG , POLICY_SETTING_TAG , REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG , SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS , SETTINGS_EDITOR_COMMAND_SHOW_AI_RESULTS , SETTINGS_EDITOR_COMMAND_SUGGEST_FILTERS , STRING_MATCH_SEARCH_PROVIDER_NAME , TF_IDF_SEARCH_PROVIDER_NAME , WorkbenchSettingsEditorSettings , WORKSPACE_TRUST_SETTING_TAG } from '../common/preferences.js' ;
62
63
import { settingsHeaderBorder , settingsSashBorder , settingsTextInputBorder } from '../common/settingsEditorColorRegistry.js' ;
63
64
import './media/settingsEditor2.css' ;
64
65
import { preferencesAiResultsIcon , preferencesClearInputIcon , preferencesFilterIcon } from './preferencesIcons.js' ;
@@ -191,6 +192,8 @@ export class SettingsEditor2 extends EditorPane {
191
192
private searchInProgress : CancellationTokenSource | null = null ;
192
193
private aiSearchPromise : CancelablePromise < void > | null = null ;
193
194
195
+ private stopWatch : StopWatch ;
196
+
194
197
private showAiResultsAction : Action | null = null ;
195
198
196
199
private searchInputDelayer : Delayer < void > ;
@@ -276,6 +279,7 @@ export class SettingsEditor2 extends EditorPane {
276
279
this . settingRowFocused = CONTEXT_SETTINGS_ROW_FOCUS . bindTo ( contextKeyService ) ;
277
280
278
281
this . scheduledRefreshes = new Map < string , DisposableStore > ( ) ;
282
+ this . stopWatch = new StopWatch ( false ) ;
279
283
280
284
this . editorMemento = this . getEditorMemento < ISettingsEditor2State > ( editorGroupService , textResourceConfigurationService , SETTINGS_EDITOR_STATE_KEY ) ;
281
285
@@ -1778,7 +1782,7 @@ export class SettingsEditor2 extends EditorPane {
1778
1782
matchType : SettingMatchType . None ,
1779
1783
keyMatchScore : 0 ,
1780
1784
score : 0 ,
1781
- providerName : 'filterModel'
1785
+ providerName : FILTER_MODEL_SEARCH_PROVIDER_NAME
1782
1786
} ) ;
1783
1787
}
1784
1788
}
@@ -1857,15 +1861,15 @@ export class SettingsEditor2 extends EditorPane {
1857
1861
1858
1862
private doLocalSearch ( query : string , token : CancellationToken ) : Promise < ISearchResult | null > {
1859
1863
const localSearchProvider = this . preferencesSearchService . getLocalSearchProvider ( query ) ;
1860
- return this . searchWithProvider ( SearchResultIdx . Local , localSearchProvider , token ) ;
1864
+ return this . searchWithProvider ( SearchResultIdx . Local , localSearchProvider , STRING_MATCH_SEARCH_PROVIDER_NAME , token ) ;
1861
1865
}
1862
1866
1863
1867
private doRemoteSearch ( query : string , token : CancellationToken ) : Promise < ISearchResult | null > {
1864
1868
const remoteSearchProvider = this . preferencesSearchService . getRemoteSearchProvider ( query ) ;
1865
1869
if ( ! remoteSearchProvider ) {
1866
1870
return Promise . resolve ( null ) ;
1867
1871
}
1868
- return this . searchWithProvider ( SearchResultIdx . Remote , remoteSearchProvider , token ) ;
1872
+ return this . searchWithProvider ( SearchResultIdx . Remote , remoteSearchProvider , TF_IDF_SEARCH_PROVIDER_NAME , token ) ;
1869
1873
}
1870
1874
1871
1875
private async doAiSearch ( query : string , token : CancellationToken ) : Promise < ISearchResult | null > {
@@ -1874,7 +1878,7 @@ export class SettingsEditor2 extends EditorPane {
1874
1878
return null ;
1875
1879
}
1876
1880
1877
- const embeddingsResults = await this . searchWithProvider ( SearchResultIdx . Embeddings , aiSearchProvider , token ) ;
1881
+ const embeddingsResults = await this . searchWithProvider ( SearchResultIdx . Embeddings , aiSearchProvider , EMBEDDINGS_SEARCH_PROVIDER_NAME , token ) ;
1878
1882
if ( ! embeddingsResults || token . isCancellationRequested ) {
1879
1883
return null ;
1880
1884
}
@@ -1896,26 +1900,62 @@ export class SettingsEditor2 extends EditorPane {
1896
1900
return null ;
1897
1901
}
1898
1902
1903
+ this . stopWatch . reset ( ) ;
1899
1904
const result = await aiSearchProvider . getLLMRankedResults ( token ) ;
1900
- if ( ! result || token . isCancellationRequested ) {
1905
+ this . stopWatch . stop ( ) ;
1906
+
1907
+ if ( token . isCancellationRequested ) {
1901
1908
return null ;
1902
1909
}
1903
1910
1911
+ // Only log the elapsed time if there are actual results.
1912
+ if ( result && result . filterMatches . length > 0 ) {
1913
+ const elapsed = this . stopWatch . elapsed ( ) ;
1914
+ this . logSearchPerformance ( LLM_RANKED_SEARCH_PROVIDER_NAME , elapsed ) ;
1915
+ }
1916
+
1904
1917
this . searchResultModel ! . setResult ( SearchResultIdx . AiSelected , result ) ;
1905
1918
return result ;
1906
1919
}
1907
1920
1908
- private async searchWithProvider ( type : SearchResultIdx , searchProvider : ISearchProvider , token : CancellationToken ) : Promise < ISearchResult | null > {
1921
+ private async searchWithProvider ( type : SearchResultIdx , searchProvider : ISearchProvider , providerName : string , token : CancellationToken ) : Promise < ISearchResult | null > {
1922
+ this . stopWatch . reset ( ) ;
1909
1923
const result = await this . _searchPreferencesModel ( this . defaultSettingsEditorModel , searchProvider , token ) ;
1924
+ this . stopWatch . stop ( ) ;
1925
+
1910
1926
if ( token . isCancellationRequested ) {
1911
1927
// Handle cancellation like this because cancellation is lost inside the search provider due to async/await
1912
1928
return null ;
1913
1929
}
1930
+
1931
+ // Only log the elapsed time if there are actual results.
1932
+ if ( result && result . filterMatches . length > 0 ) {
1933
+ const elapsed = this . stopWatch . elapsed ( ) ;
1934
+ this . logSearchPerformance ( providerName , elapsed ) ;
1935
+ }
1936
+
1914
1937
this . searchResultModel ??= this . instantiationService . createInstance ( SearchResultModel , this . viewState , this . settingsOrderByTocIndex , this . workspaceTrustManagementService . isWorkspaceTrusted ( ) ) ;
1915
1938
this . searchResultModel . setResult ( type , result ) ;
1916
1939
return result ;
1917
1940
}
1918
1941
1942
+ private logSearchPerformance ( providerName : string , elapsed : number ) : void {
1943
+ type SettingsEditorSearchPerformanceEvent = {
1944
+ providerName : string | undefined ;
1945
+ elapsedMs : number ;
1946
+ } ;
1947
+ type SettingsEditorSearchPerformanceClassification = {
1948
+ providerName : { classification : 'SystemMetaData' ; purpose : 'FeatureInsight' ; comment : 'The name of the search provider, if applicable.' } ;
1949
+ elapsedMs : { classification : 'SystemMetaData' ; purpose : 'FeatureInsight' ; comment : 'The time taken to perform the search, in milliseconds.' } ;
1950
+ owner : 'rzhao271' ;
1951
+ comment : 'Event emitted when the Settings editor calls a search provider to search for a setting' ;
1952
+ } ;
1953
+ this . telemetryService . publicLog2 < SettingsEditorSearchPerformanceEvent , SettingsEditorSearchPerformanceClassification > ( 'settingsEditor.searchPerformance' , {
1954
+ providerName,
1955
+ elapsedMs : elapsed ,
1956
+ } ) ;
1957
+ }
1958
+
1919
1959
private renderResultCountMessages ( showAiResultsMessage : boolean ) {
1920
1960
if ( ! this . currentSettingsModel ) {
1921
1961
return ;
0 commit comments