From c594f585133d7b2a732a2b802032cdea36fb06a8 Mon Sep 17 00:00:00 2001 From: Hoang Thuan Pham Date: Tue, 4 Jul 2023 11:49:33 -0400 Subject: [PATCH] Propagate new Trace Server url upon change This commit allow the VSCode extension to listen to the onDidChangeConfiguration event provided by VSCode and propagate the new URL to components. The new URL is sent as a message to the front end, then the TraceServerUrlProvider will run handlers that was registered to the TSPClientProvider. Signed-off-by: Hoang Thuan Pham --- .../src/client/tsp-client-provider-impl.ts | 25 +++++++++++-------- .../src/messages/vscode-message-manager.ts | 3 ++- .../src/server/trace-server-url-provider.ts | 13 ++++++++++ vscode-trace-extension/src/extension.ts | 16 ++++++++++-- ...plorer-available-views-webview-provider.ts | 6 +++++ ...explorer-opened-traces-webview-provider.ts | 6 +++++ .../trace-viewer-webview-panel.ts | 7 ++++++ .../vscode-trace-explorer-views-widget.tsx | 10 +++++++- ...de-trace-explorer-opened-traces-widget.tsx | 25 ++++++++++++------- .../vscode-trace-viewer-container.tsx | 10 +++++++- 10 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 vscode-trace-common/src/server/trace-server-url-provider.ts diff --git a/vscode-trace-common/src/client/tsp-client-provider-impl.ts b/vscode-trace-common/src/client/tsp-client-provider-impl.ts index 57f5b44b..8f4bd53b 100644 --- a/vscode-trace-common/src/client/tsp-client-provider-impl.ts +++ b/vscode-trace-common/src/client/tsp-client-provider-impl.ts @@ -4,6 +4,7 @@ import { ExperimentManager } from 'traceviewer-base/lib/experiment-manager'; import { TraceManager } from 'traceviewer-base/lib/trace-manager'; import { ITspClientProvider } from 'traceviewer-base/lib/tsp-client-provider'; import { VsCodeMessageManager } from '../messages/vscode-message-manager'; +import { TraceServerUrlProvider } from '../server/trace-server-url-provider'; export class TspClientProvider implements ITspClientProvider { @@ -12,9 +13,10 @@ export class TspClientProvider implements ITspClientProvider { private _experimentManager: ExperimentManager; private _signalHandler: VsCodeMessageManager | undefined; private _statusListener: ConnectionStatusListener; - // private _listeners: ((tspClient: TspClient) => void)[]; + private _urlProvider: TraceServerUrlProvider; + private _listeners: ((tspClient: TspClient) => void)[]; - constructor(traceServerUrl: string, signalHandler: VsCodeMessageManager | undefined + constructor(traceServerUrl: string, signalHandler: VsCodeMessageManager | undefined, _urlProvider: TraceServerUrlProvider ) { this._tspClient = new TspClient(traceServerUrl); this._traceManager = new TraceManager(this._tspClient); @@ -27,13 +29,14 @@ export class TspClientProvider implements ITspClientProvider { RestClient.addConnectionStatusListener(this._statusListener); this._tspClient.checkHealth(); - // this._listeners = []; - // tspUrlProvider.addTraceServerUrlChangedListener(url => { - // this._tspClient = new TspClient(url); - // this._traceManager = new TraceManager(this._tspClient); - // this._experimentManager = new ExperimentManager(this._tspClient, this._traceManager); - // this._listeners.forEach(listener => listener(this._tspClient)); - // }); + this._urlProvider = _urlProvider; + this._listeners = []; + this._urlProvider.onTraceServerUrlChange((url: string) => { + this._tspClient = new TspClient(url); + this._traceManager = new TraceManager(this._tspClient); + this._experimentManager = new ExperimentManager(this._tspClient, this._traceManager); + this._listeners.forEach(listener => listener(this._tspClient)); + }); } public getTspClient(): TspClient { @@ -53,7 +56,7 @@ export class TspClientProvider implements ITspClientProvider { * @param listener The listener function to be called when the url is * changed */ - addTspClientChangeListener(_listener: (tspClient: TspClient) => void): void { - // this._listeners.push(listener); + addTspClientChangeListener(listener: (tspClient: TspClient) => void): void { + this._listeners.push(listener); } } diff --git a/vscode-trace-common/src/messages/vscode-message-manager.ts b/vscode-trace-common/src/messages/vscode-message-manager.ts index e19c914c..343051dc 100644 --- a/vscode-trace-common/src/messages/vscode-message-manager.ts +++ b/vscode-trace-common/src/messages/vscode-message-manager.ts @@ -56,7 +56,8 @@ export const VSCODE_MESSAGES = { UPDATE_MARKER_CATEGORY_STATE: 'updateMarkerCategoryState', UPDATE_MARKER_SET_STATE: 'updateMarkerSetState', MARKER_SETS_CONTEXT: 'markerSetsContext', - MARKER_CATEGORIES_CONTEXT: 'markerCategoriesContext' + MARKER_CATEGORIES_CONTEXT: 'markerCategoriesContext', + TRACE_SERVER_URL_CHANGED: 'traceServerUrlChanged' }; export class VsCodeMessageManager extends Messages.MessageManager { diff --git a/vscode-trace-common/src/server/trace-server-url-provider.ts b/vscode-trace-common/src/server/trace-server-url-provider.ts new file mode 100644 index 00000000..f30030e1 --- /dev/null +++ b/vscode-trace-common/src/server/trace-server-url-provider.ts @@ -0,0 +1,13 @@ +export class TraceServerUrlProvider { + private onDidChangeConfigurationHandlers: ((url: string) => void)[] = []; + + public updateTraceServerUrl = (newUrl: string): void => { + this.onDidChangeConfigurationHandlers.forEach(handler => { + handler(newUrl); + }); + }; + + public onTraceServerUrlChange(handler: ((url: string) => void)): void{ + this.onDidChangeConfigurationHandlers.push(handler); + } +} diff --git a/vscode-trace-extension/src/extension.ts b/vscode-trace-extension/src/extension.ts index b7d2043c..6d2458b0 100644 --- a/vscode-trace-extension/src/extension.ts +++ b/vscode-trace-extension/src/extension.ts @@ -6,17 +6,18 @@ import { TraceExplorerAvailableViewsProvider } from './trace-explorer/available- import { TraceExplorerOpenedTracesViewProvider } from './trace-explorer/opened-traces/trace-explorer-opened-traces-webview-provider'; import { fileHandler, openOverviewHandler, resetZoomHandler, undoRedoHandler, zoomHandler, keyboardShortcutsHandler } from './trace-explorer/trace-tree'; import { TraceServerConnectionStatusService } from './utils/trace-server-status'; -import { getTspClientUrl, updateTspClient } from './utils/tspClient'; +import { getTraceServerUrl, getTspClientUrl, updateTspClient } from './utils/tspClient'; import { TraceExtensionLogger } from './utils/trace-extension-logger'; import { ExternalAPI, traceExtensionAPI} from './external-api/external-api'; import { TraceExtensionWebviewManager } from './utils/trace-extension-webview-manager'; import { VSCODE_MESSAGES } from 'vscode-trace-common/lib/messages/vscode-message-manager'; import { TraceViewerPanel } from './trace-viewer-panel/trace-viewer-webview-panel'; import { TspClientProvider } from 'vscode-trace-common/lib/client/tsp-client-provider-impl'; +import { TraceServerUrlProvider } from 'vscode-trace-common/lib/server/trace-server-url-provider'; export let traceLogger: TraceExtensionLogger; export const traceExtensionWebviewManager: TraceExtensionWebviewManager = new TraceExtensionWebviewManager(); -const tspClientProvider = new TspClientProvider(getTspClientUrl(), undefined); +const tspClientProvider = new TspClientProvider(getTspClientUrl(), undefined, new TraceServerUrlProvider()); export function activate(context: vscode.ExtensionContext): ExternalAPI { traceLogger = new TraceExtensionLogger('Trace Extension'); @@ -59,6 +60,17 @@ export function activate(context: vscode.ExtensionContext): ExternalAPI { if (e.affectsConfiguration('trace-compass.traceserver.url') || e.affectsConfiguration('trace-compass.traceserver.apiPath')) { updateTspClient(); } + + if (e.affectsConfiguration('trace-compass.traceserver.url')) { + const newUrl = getTraceServerUrl(); + + // Signal the change to the `Opened traces` and `Available views` webview + tracesProvider.updateTraceServerUrl(newUrl); + myAnalysisProvider.updateTraceServerUrl(newUrl); + + // Signal the change to all trace panels + TraceViewerPanel.updateTraceServerUrl(newUrl); + } })); const overViewOpenHandler = openOverviewHandler(); diff --git a/vscode-trace-extension/src/trace-explorer/available-views/trace-explorer-available-views-webview-provider.ts b/vscode-trace-extension/src/trace-explorer/available-views/trace-explorer-available-views-webview-provider.ts index daf6c8a1..d21581b4 100644 --- a/vscode-trace-extension/src/trace-explorer/available-views/trace-explorer-available-views-webview-provider.ts +++ b/vscode-trace-extension/src/trace-explorer/available-views/trace-explorer-available-views-webview-provider.ts @@ -30,6 +30,12 @@ export class TraceExplorerAvailableViewsProvider implements vscode.WebviewViewPr private readonly _statusService: TraceServerConnectionStatusService, ) { } + public updateTraceServerUrl(newUrl: string): void { + if (this._view) { + this._view.webview.postMessage({command: VSCODE_MESSAGES.TRACE_SERVER_URL_CHANGED, data: newUrl}); + } + } + public resolveWebviewView( webviewView: vscode.WebviewView, _context: vscode.WebviewViewResolveContext, diff --git a/vscode-trace-extension/src/trace-explorer/opened-traces/trace-explorer-opened-traces-webview-provider.ts b/vscode-trace-extension/src/trace-explorer/opened-traces/trace-explorer-opened-traces-webview-provider.ts index 68b5a34d..6ca0b9b7 100644 --- a/vscode-trace-extension/src/trace-explorer/opened-traces/trace-explorer-opened-traces-webview-provider.ts +++ b/vscode-trace-extension/src/trace-explorer/opened-traces/trace-explorer-opened-traces-webview-provider.ts @@ -52,6 +52,12 @@ export class TraceExplorerOpenedTracesViewProvider implements vscode.WebviewView } } + public updateTraceServerUrl(newUrl: string): void { + if (this._view) { + this._view.webview.postMessage({command: VSCODE_MESSAGES.TRACE_SERVER_URL_CHANGED, data: newUrl}); + } + } + public resolveWebviewView( webviewView: vscode.WebviewView, _context: vscode.WebviewViewResolveContext, diff --git a/vscode-trace-extension/src/trace-viewer-panel/trace-viewer-webview-panel.ts b/vscode-trace-extension/src/trace-viewer-panel/trace-viewer-webview-panel.ts index 7f2ddfd0..ee068d7d 100644 --- a/vscode-trace-extension/src/trace-viewer-panel/trace-viewer-webview-panel.ts +++ b/vscode-trace-extension/src/trace-viewer-panel/trace-viewer-webview-panel.ts @@ -126,6 +126,13 @@ export class TraceViewerPanel { } } + public static updateTraceServerUrl(newUrl: string): void { + Object.values(TraceViewerPanel.activePanels) + .forEach(trace => trace?._panel.webview.postMessage({ + command: VSCODE_MESSAGES.TRACE_SERVER_URL_CHANGED, data: newUrl + })); + } + private constructor(extensionUri: vscode.Uri, column: vscode.ViewColumn, name: string, statusService: TraceServerConnectionStatusService | undefined) { this._extensionUri = extensionUri; this._statusService = statusService; diff --git a/vscode-trace-webviews/src/trace-explorer/available-views/vscode-trace-explorer-views-widget.tsx b/vscode-trace-webviews/src/trace-explorer/available-views/vscode-trace-explorer-views-widget.tsx index 60a08f7e..46b3c9ce 100644 --- a/vscode-trace-webviews/src/trace-explorer/available-views/vscode-trace-explorer-views-widget.tsx +++ b/vscode-trace-webviews/src/trace-explorer/available-views/vscode-trace-explorer-views-widget.tsx @@ -12,6 +12,7 @@ import '../../style/react-contextify.css'; import '../../style/trace-viewer.css'; import JSONBigConfig from 'json-bigint'; import { convertSignalExperiment } from 'vscode-trace-common/lib/signals/vscode-signal-converter'; +import { TraceServerUrlProvider } from 'vscode-trace-common/lib/server/trace-server-url-provider'; const JSONBig = JSONBigConfig({ useNativeBigInt: true, @@ -23,6 +24,7 @@ interface AvailableViewsAppState { class TraceExplorerViewsWidget extends React.Component<{}, AvailableViewsAppState> { private _signalHandler: VsCodeMessageManager; + private _urlProvider: TraceServerUrlProvider; static ID = 'trace-explorer-analysis-widget'; static LABEL = 'Available Analyses'; @@ -41,7 +43,8 @@ class TraceExplorerViewsWidget extends React.Component<{}, AvailableViewsAppStat const message = event.data; // The JSON data our extension sent switch (message.command) { case VSCODE_MESSAGES.SET_TSP_CLIENT: - this.setState({ tspClientProvider: new TspClientProvider(message.data, this._signalHandler) }); + this._urlProvider = new TraceServerUrlProvider(); + this.setState({ tspClientProvider: new TspClientProvider(message.data, this._signalHandler, this._urlProvider) }); break; case VSCODE_MESSAGES.EXPERIMENT_SELECTED: let experiment: Experiment | undefined = undefined; @@ -50,6 +53,11 @@ class TraceExplorerViewsWidget extends React.Component<{}, AvailableViewsAppStat } signalManager().fireExperimentSelectedSignal(experiment); break; + case VSCODE_MESSAGES.TRACE_SERVER_URL_CHANGED: + if (message.data && this.state.tspClientProvider && this._urlProvider) { + this._urlProvider.updateTraceServerUrl(message.data); + } + break; } }); } diff --git a/vscode-trace-webviews/src/trace-explorer/opened-traces/vscode-trace-explorer-opened-traces-widget.tsx b/vscode-trace-webviews/src/trace-explorer/opened-traces/vscode-trace-explorer-opened-traces-widget.tsx index a03c5c8a..534830ab 100644 --- a/vscode-trace-webviews/src/trace-explorer/opened-traces/vscode-trace-explorer-opened-traces-widget.tsx +++ b/vscode-trace-webviews/src/trace-explorer/opened-traces/vscode-trace-explorer-opened-traces-widget.tsx @@ -15,6 +15,7 @@ import { convertSignalExperiment } from 'vscode-trace-common/lib/signals/vscode- import JSONBigConfig from 'json-bigint'; import { OpenedTracesUpdatedSignalPayload } from 'traceviewer-base/lib/signals/opened-traces-updated-signal-payload'; import { ReactExplorerPlaceholderWidget } from 'traceviewer-react-components/lib/trace-explorer/trace-explorer-placeholder-widget'; +import { TraceServerUrlProvider } from 'vscode-trace-common/lib/server/trace-server-url-provider'; const JSONBig = JSONBigConfig({ useNativeBigInt: true, @@ -30,6 +31,7 @@ const MENU_ID = 'traceExplorer.openedTraces.menuId'; class TraceExplorerOpenedTraces extends React.Component<{}, OpenedTracesAppState> { private _signalHandler: VsCodeMessageManager; private _experimentManager: ExperimentManager; + private _urlProvider: TraceServerUrlProvider; static ID = 'trace-explorer-opened-traces-widget'; static LABEL = 'Opened Traces'; @@ -57,20 +59,20 @@ class TraceExplorerOpenedTraces extends React.Component<{}, OpenedTracesAppState }; this._signalHandler = new VsCodeMessageManager(); window.addEventListener('message', event => { - const message = event.data; // The JSON data our extension sent switch (message.command) { case VSCODE_MESSAGES.SET_TSP_CLIENT: - const tspClientProvider: ITspClientProvider = new TspClientProvider(message.data, this._signalHandler); + this._urlProvider = new TraceServerUrlProvider(); + const tspClientProvider: ITspClientProvider = new TspClientProvider(message.data, this._signalHandler, this._urlProvider); this._experimentManager = tspClientProvider.getExperimentManager(); + + tspClientProvider.addTspClientChangeListener(() => { + if (tspClientProvider) { + this._experimentManager = tspClientProvider.getExperimentManager(); + } + }); + this.setState({ tspClientProvider: tspClientProvider }); - if (this.state.tspClientProvider) { - this.state.tspClientProvider.addTspClientChangeListener(() => { - if (this.state.tspClientProvider) { - this._experimentManager = this.state.tspClientProvider.getExperimentManager(); - } - }); - } break; case VSCODE_MESSAGES.TRACE_VIEWER_TAB_ACTIVATED: if (message.data) { @@ -90,6 +92,11 @@ class TraceExplorerOpenedTraces extends React.Component<{}, OpenedTracesAppState case VSCODE_MESSAGES.TRACE_SERVER_STARTED: signalManager().fireTraceServerStartedSignal(); this.setState({experimentsOpened: true}); + case VSCODE_MESSAGES.TRACE_SERVER_URL_CHANGED: + if (message.data && this.state.tspClientProvider && this._urlProvider) { + this._urlProvider.updateTraceServerUrl(message.data); + } + break; } }); // this.onOutputRemoved = this.onOutputRemoved.bind(this); diff --git a/vscode-trace-webviews/src/trace-viewer/vscode-trace-viewer-container.tsx b/vscode-trace-webviews/src/trace-viewer/vscode-trace-viewer-container.tsx index 91156bc0..c15278f5 100644 --- a/vscode-trace-webviews/src/trace-viewer/vscode-trace-viewer-container.tsx +++ b/vscode-trace-webviews/src/trace-viewer/vscode-trace-viewer-container.tsx @@ -17,6 +17,7 @@ import { MarkerSet } from 'tsp-typescript-client/lib/models/markerset'; import { VsCodeMessageManager, VSCODE_MESSAGES } from 'vscode-trace-common/lib/messages/vscode-message-manager'; import { convertSignalExperiment } from 'vscode-trace-common/lib/signals/vscode-signal-converter'; import '../style/trace-viewer.css'; +import { TraceServerUrlProvider } from 'vscode-trace-common/lib/server/trace-server-url-provider'; const JSONBig = JSONBigConfig({ useNativeBigInt: true, @@ -34,6 +35,7 @@ class TraceViewerContainer extends React.Component<{}, VscodeAppState> { private DEFAULT_OVERVIEW_DATA_PROVIDER_ID = 'org.eclipse.tracecompass.internal.tmf.core.histogram.HistogramDataProvider'; private _signalHandler: VsCodeMessageManager; + private _urlProvider: TraceServerUrlProvider; private _onProperties = (properties: { [key: string]: string }): void => this.doHandlePropertiesSignal(properties); private _onSaveAsCSV = (payload: {traceId: string, data: string}): void => this.doHandleSaveAsCSVSignal(payload); @@ -85,7 +87,8 @@ class TraceViewerContainer extends React.Component<{}, VscodeAppState> { this.doHandleExperimentSetSignal(convertSignalExperiment(JSONBig.parse(message.data)), false); break; case VSCODE_MESSAGES.SET_TSP_CLIENT: - this.setState({tspClientProvider: new TspClientProvider(message.data, this._signalHandler)}, () => { + this._urlProvider = new TraceServerUrlProvider(); + this.setState({tspClientProvider: new TspClientProvider(message.data, this._signalHandler, this._urlProvider)}, () => { if (message.experiment) { this.doHandleExperimentSetSignal(convertSignalExperiment(JSONBig.parse(message.experiment)), true); } @@ -137,6 +140,11 @@ class TraceViewerContainer extends React.Component<{}, VscodeAppState> { case VSCODE_MESSAGES.EXPERIMENT_SELECTED: this.doHandleExperimentSelectedSignal(convertSignalExperiment(JSONBig.parse(message.data))); break; + case VSCODE_MESSAGES.TRACE_SERVER_URL_CHANGED: + if (message.data && this.state.tspClientProvider && this._urlProvider) { + this._urlProvider.updateTraceServerUrl(message.data); + } + break; } }); window.addEventListener('resize', this.onResize);