From fc6d0f8f15ba84acd282552e458fd7dad7c09d55 Mon Sep 17 00:00:00 2001 From: Hildebrando Chavez Date: Sun, 8 Mar 2026 14:08:54 -0600 Subject: [PATCH] Capture client hostname in events and UI Add client_hostname to Default and Azure session templates so events include the client host. Expose hostname in shared view template and the VS Code extension (model, panel, and view) and add a Host column. Also include small WinForms fixes: show InitialCatalog in recent connections, format AuthenticationMode display, and bump WinForms app version. --- .../Models/AzureSqlProfilerSessionTemplate.cs | 40 +++++++++---------- .../Models/DefaultProfilerSessionTemplate.cs | 40 +++++++++---------- .../Models/DefaultProfilerViewTemplate.cs | 6 +++ .../LightQueryProfiler.WinFormsApp.csproj | 2 +- .../Presenters/MainPresenter.cs | 2 +- .../Presenters/RecentConnectionsPresenter.cs | 13 +++++- vscode-extension/src/models/profiler-event.ts | 11 +++++ .../src/views/profiler-panel-provider.ts | 32 +++++++++++++-- .../src/views/profiler-view-provider.ts | 31 ++++++++++++-- 9 files changed, 126 insertions(+), 51 deletions(-) diff --git a/src/LightQueryProfiler.Shared/Models/AzureSqlProfilerSessionTemplate.cs b/src/LightQueryProfiler.Shared/Models/AzureSqlProfilerSessionTemplate.cs index 3220690..98698d6 100644 --- a/src/LightQueryProfiler.Shared/Models/AzureSqlProfilerSessionTemplate.cs +++ b/src/LightQueryProfiler.Shared/Models/AzureSqlProfilerSessionTemplate.cs @@ -26,26 +26,26 @@ DROP EVENT SESSION [{sessionName}] ON DATABASE END CREATE EVENT SESSION [{sessionName}] ON DATABASE - ADD EVENT sqlserver.attention( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), - ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1) - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)), - ADD EVENT sqlserver.login(SET collect_options_text=(1) - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)), - ADD EVENT sqlserver.logout( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)), - ADD EVENT sqlserver.rpc_completed( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), - ADD EVENT sqlserver.sql_batch_completed( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), - ADD EVENT sqlserver.sql_batch_starting( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))) - ADD TARGET package0.ring_buffer(SET max_events_limit=(1001)) - WITH (EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)"; + ADD EVENT sqlserver.attention( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), + ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1) + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)), + ADD EVENT sqlserver.login(SET collect_options_text=(1) + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)), + ADD EVENT sqlserver.logout( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)), + ADD EVENT sqlserver.rpc_completed( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), + ADD EVENT sqlserver.sql_batch_completed( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), + ADD EVENT sqlserver.sql_batch_starting( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.username,sqlserver.query_hash,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))) + ADD TARGET package0.ring_buffer(SET max_events_limit=(1001)) + WITH (MAX_MEMORY=16384KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)"; } } } diff --git a/src/LightQueryProfiler.Shared/Models/DefaultProfilerSessionTemplate.cs b/src/LightQueryProfiler.Shared/Models/DefaultProfilerSessionTemplate.cs index 0831212..0698437 100644 --- a/src/LightQueryProfiler.Shared/Models/DefaultProfilerSessionTemplate.cs +++ b/src/LightQueryProfiler.Shared/Models/DefaultProfilerSessionTemplate.cs @@ -23,26 +23,26 @@ DROP EVENT SESSION [{sessionName}] ON SERVER END CREATE EVENT SESSION [{sessionName}] ON SERVER - ADD EVENT sqlserver.attention( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), - ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1) - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)), - ADD EVENT sqlserver.login(SET collect_options_text=(1) - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)), - ADD EVENT sqlserver.logout( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)), - ADD EVENT sqlserver.rpc_completed( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), - ADD EVENT sqlserver.sql_batch_completed( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), - ADD EVENT sqlserver.sql_batch_starting( - ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) - WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))) - ADD TARGET package0.ring_buffer(SET max_events_limit=(1001)) - WITH (EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)"; + ADD EVENT sqlserver.attention( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), + ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1) + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)), + ADD EVENT sqlserver.login(SET collect_options_text=(1) + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)), + ADD EVENT sqlserver.logout( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)), + ADD EVENT sqlserver.rpc_completed( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), + ADD EVENT sqlserver.sql_batch_completed( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))), + ADD EVENT sqlserver.sql_batch_starting( + ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id) + WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))) + ADD TARGET package0.ring_buffer(SET max_events_limit=(1001)) + WITH (MAX_MEMORY=16384KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)"; } } } \ No newline at end of file diff --git a/src/LightQueryProfiler.Shared/Models/DefaultProfilerViewTemplate.cs b/src/LightQueryProfiler.Shared/Models/DefaultProfilerViewTemplate.cs index 2c81aae..bb4d2db 100644 --- a/src/LightQueryProfiler.Shared/Models/DefaultProfilerViewTemplate.cs +++ b/src/LightQueryProfiler.Shared/Models/DefaultProfilerViewTemplate.cs @@ -26,6 +26,12 @@ public DefaultProfilerViewTemplate() EventsMapped = new List() { "client_app_name" } }); + Columns.Add(new ColumnViewTemplate() + { + Name = "HostName", + EventsMapped = new List() { "client_hostname" } + }); + Columns.Add(new ColumnViewTemplate() { Name = "NTUserName", diff --git a/src/LightQueryProfiler.WinFormsApp/LightQueryProfiler.WinFormsApp.csproj b/src/LightQueryProfiler.WinFormsApp/LightQueryProfiler.WinFormsApp.csproj index b8c865c..eb81d21 100644 --- a/src/LightQueryProfiler.WinFormsApp/LightQueryProfiler.WinFormsApp.csproj +++ b/src/LightQueryProfiler.WinFormsApp/LightQueryProfiler.WinFormsApp.csproj @@ -8,7 +8,7 @@ enable true LightQueryProfiler - 1.2.0-dev.2 + 1.2.0-dev.3 1.2.0 1.2.0 Icons\light-query-profiler.ico diff --git a/src/LightQueryProfiler.WinFormsApp/Presenters/MainPresenter.cs b/src/LightQueryProfiler.WinFormsApp/Presenters/MainPresenter.cs index 4971790..0772e52 100644 --- a/src/LightQueryProfiler.WinFormsApp/Presenters/MainPresenter.cs +++ b/src/LightQueryProfiler.WinFormsApp/Presenters/MainPresenter.cs @@ -1005,7 +1005,7 @@ private async void OnImportEvents(object? sender, EventArgs e) // Add rows in the correct order foreach (var eventData in importResult.Events) { - var rowValues = new List(); + var rowValues = new List(); foreach (var columnName in importResult.ColumnNames) { eventData.TryGetValue(columnName, out var value); diff --git a/src/LightQueryProfiler.WinFormsApp/Presenters/RecentConnectionsPresenter.cs b/src/LightQueryProfiler.WinFormsApp/Presenters/RecentConnectionsPresenter.cs index 2f5ce9c..9e1645b 100644 --- a/src/LightQueryProfiler.WinFormsApp/Presenters/RecentConnectionsPresenter.cs +++ b/src/LightQueryProfiler.WinFormsApp/Presenters/RecentConnectionsPresenter.cs @@ -1,4 +1,5 @@ using LightQueryProfiler.Shared.Enums; +using LightQueryProfiler.Shared.Extensions; using LightQueryProfiler.Shared.Models; using LightQueryProfiler.Shared.Repositories.Interfaces; using LightQueryProfiler.WinFormsApp.Views; @@ -50,7 +51,7 @@ private void View_CellDoubleClick(object? sender, EventArgs e) } Connection connection = new(Convert.ToInt32(row.Cells[nameof(Connection.Id)].Value), - string.Empty, + row.Cells[nameof(Connection.InitialCatalog)].Value?.ToString() ?? string.Empty, Convert.ToDateTime(row.Cells["Creation Date"].Value), row.Cells[nameof(Connection.DataSource)].Value?.ToString() ?? string.Empty, Convert.ToBoolean(row.Cells[nameof(Connection.IntegratedSecurity)].Value), @@ -133,6 +134,14 @@ private void View_RecentConnectionsGridView_CellFormatting(object? sender, Event _event.Value = new string('*', _event.Value.ToString()?.Length ?? 0); _event.FormattingApplied = true; } + else if (view.RecentConnectionsGridView.Columns[_event.ColumnIndex].Name == nameof(Connection.AuthenticationMode) && _event.Value != null) + { + if (int.TryParse(_event.Value.ToString(), out int modeValue)) + { + _event.Value = ((AuthenticationMode)modeValue).GetString(); + _event.FormattingApplied = true; + } + } } } @@ -141,6 +150,7 @@ private DataTable GetDataTable(List connections) DataTable table = new DataTable(); table.Columns.Add(nameof(Connection.Id), typeof(int)); table.Columns.Add(nameof(Connection.DataSource), typeof(string)); + table.Columns.Add(nameof(Connection.InitialCatalog), typeof(string)); table.Columns.Add(nameof(Connection.UserId), typeof(string)); table.Columns.Add(nameof(Connection.Password), typeof(string)); table.Columns.Add(nameof(Connection.IntegratedSecurity), typeof(bool)); @@ -155,6 +165,7 @@ private DataTable GetDataTable(List connections) DataRow row = table.NewRow(); row[nameof(Connection.Id)] = c.Id; row[nameof(Connection.DataSource)] = c.DataSource; + row[nameof(Connection.InitialCatalog)] = (object?)c.InitialCatalog ?? DBNull.Value; row[nameof(Connection.UserId)] = (object?)c.UserId ?? DBNull.Value; row[nameof(Connection.Password)] = (object?)c.Password ?? DBNull.Value; row[nameof(Connection.IntegratedSecurity)] = c.IntegratedSecurity; diff --git a/vscode-extension/src/models/profiler-event.ts b/vscode-extension/src/models/profiler-event.ts index e8f8de6..1dea832 100644 --- a/vscode-extension/src/models/profiler-event.ts +++ b/vscode-extension/src/models/profiler-event.ts @@ -67,6 +67,11 @@ export interface ProfilerEventRow { */ applicationName?: string; + /** + * Client host name + */ + hostname?: string; + /** * Database name */ @@ -148,6 +153,11 @@ export function toEventRow(event: ProfilerEvent): ProfilerEventRow { ? actions['client_app_name'] : undefined; + const hostname = + typeof actions['client_hostname'] === 'string' + ? actions['client_hostname'] + : undefined; + const databaseName = typeof actions['database_name'] === 'string' ? actions['database_name'] @@ -170,6 +180,7 @@ export function toEventRow(event: ProfilerEvent): ProfilerEventRow { reads, writes, applicationName, + hostname, databaseName, loginName, sessionId, diff --git a/vscode-extension/src/views/profiler-panel-provider.ts b/vscode-extension/src/views/profiler-panel-provider.ts index bfece46..55ede20 100644 --- a/vscode-extension/src/views/profiler-panel-provider.ts +++ b/vscode-extension/src/views/profiler-panel-provider.ts @@ -336,6 +336,7 @@ export class ProfilerPanelProvider { reads: number; databaseName?: string; applicationName?: string; + hostname?: string; queryText?: string; }> = []; @@ -349,6 +350,7 @@ export class ProfilerPanelProvider { reads: (event.fields?.logical_reads as number) || 0, databaseName: event.actions?.database_name as string | undefined, applicationName: event.actions?.client_app_name as string | undefined, + hostname: event.actions?.client_hostname as string | undefined, queryText: event.fields?.statement as string | undefined, }; @@ -769,11 +771,12 @@ export class ProfilerPanelProvider { Reads Database Application + Host - No events captured yet. Click Start to begin profiling. + No events captured yet. Click Start to begin profiling. @@ -810,7 +813,7 @@ export class ProfilerPanelProvider { // Update auth mode visibility authMode.addEventListener('change', () => { const mode = parseInt(authMode.value); - const requiresCredentials = mode === 1 || mode === 3; + const requiresCredentials = mode === 1 || mode === 2; if (requiresCredentials) { usernameGroup.classList.remove('hidden'); @@ -824,6 +827,18 @@ export class ProfilerPanelProvider { // Trigger initial visibility update authMode.dispatchEvent(new Event('change')); + // Restore previously saved connection settings + const savedState = vscode.getState(); + if (savedState) { + if (savedState.server) { serverInput.value = savedState.server; } + if (savedState.database) { databaseInput.value = savedState.database; } + if (typeof savedState.authenticationMode === 'number') { + authMode.value = String(savedState.authenticationMode); + authMode.dispatchEvent(new Event('change')); + } + if (savedState.username) { usernameInput.value = savedState.username; } + } + // Button event handlers startBtn.addEventListener('click', () => { const settings = { @@ -834,6 +849,14 @@ export class ProfilerPanelProvider { password: passwordInput.value || undefined }; + // Persist connection settings (excluding password for security) + vscode.setState({ + server: settings.server, + database: settings.database, + authenticationMode: settings.authenticationMode, + username: settings.username, + }); + vscode.postMessage({ command: 'start', data: settings }); }); @@ -911,7 +934,7 @@ export class ProfilerPanelProvider { // Remove "no events" message if present if (eventsTableBody.children.length === 1 && eventsTableBody.children[0].children.length === 1 && - eventsTableBody.children[0].children[0].colSpan === 7) { + eventsTableBody.children[0].children[0].colSpan === 8) { eventsTableBody.innerHTML = ''; } @@ -923,7 +946,8 @@ export class ProfilerPanelProvider { '' + formatNumber(event.cpuTime) + '' + '' + formatNumber(event.reads) + '' + '' + escapeHtml(event.databaseName || '-') + '' + - '' + escapeHtml(event.applicationName || '-') + ''; + '' + escapeHtml(event.applicationName || '-') + '' + + '' + escapeHtml(event.hostname || '-') + ''; row.addEventListener('click', () => { selectRow(row, event); diff --git a/vscode-extension/src/views/profiler-view-provider.ts b/vscode-extension/src/views/profiler-view-provider.ts index e7899d2..b76c9e4 100644 --- a/vscode-extension/src/views/profiler-view-provider.ts +++ b/vscode-extension/src/views/profiler-view-provider.ts @@ -771,11 +771,12 @@ export class ProfilerViewProvider implements vscode.WebviewViewProvider { Reads Database Application + Host - + No events captured yet. Click Start to begin profiling. @@ -833,6 +834,14 @@ export class ProfilerViewProvider implements vscode.WebviewViewProvider { password: password.value, }; + // Persist connection settings (excluding password for security) + vscode.setState({ + server: settings.server, + database: settings.database, + authenticationMode: settings.authenticationMode, + username: settings.username, + }); + vscode.postMessage({ command: 'start', data: settings, @@ -913,7 +922,7 @@ export class ProfilerViewProvider implements vscode.WebviewViewProvider { // Remove "no events" message if present if (eventsTableBody.children.length === 1 && eventsTableBody.children[0].children.length === 1 && - eventsTableBody.children[0].children[0].colSpan === 7) { + eventsTableBody.children[0].children[0].colSpan === 8) { eventsTableBody.innerHTML = ''; } @@ -925,7 +934,8 @@ export class ProfilerViewProvider implements vscode.WebviewViewProvider { '' + formatNumber(event.cpuTime) + '' + '' + formatNumber(event.reads) + '' + '' + escapeHtml(event.databaseName || '-') + '' + - '' + escapeHtml(event.applicationName || '-') + ''; + '' + escapeHtml(event.applicationName || '-') + '' + + '' + escapeHtml(event.hostname || '-') + ''; row.addEventListener('click', () => { selectRow(row, event); @@ -953,7 +963,7 @@ export class ProfilerViewProvider implements vscode.WebviewViewProvider { function clearEvents() { eventsTableBody.innerHTML = '' + - '' + + '' + 'No events captured yet. Click Start to begin profiling.' + '' + ''; @@ -997,6 +1007,19 @@ export class ProfilerViewProvider implements vscode.WebviewViewProvider { // Initialize authMode.dispatchEvent(new Event('change')); + + // Restore previously saved connection settings + const savedState = vscode.getState(); + if (savedState) { + if (savedState.server) { server.value = savedState.server; } + if (savedState.database) { database.value = savedState.database; } + if (typeof savedState.authenticationMode === 'number') { + authMode.value = String(savedState.authenticationMode); + authMode.dispatchEvent(new Event('change')); + } + if (savedState.username) { username.value = savedState.username; } + } + vscode.postMessage({ command: 'ready' }); })();