New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@W-14955790 BazelEventsExtensionAPI #108
Conversation
spuliaiev-sfdc
commented
Mar 4, 2024
- Adding BazelEventsExtensionAPI:
- onSyncStarted event - An event which is fired on start of a Bazel Sync session.
- onSyncEnded event - An event which is fired on end of a Bazel Sync session.
- onBazelProjectFileCreated - An event which is fired on creation of a .bazelproject file.
- onBazelProjectFileUpdated - An event which is fired on updates to the .bazelproject file.
- onSyncDirectoriesStarted - An event which is fired on start of a Bazel Sync Directories session.
- onSyncDirectoriesEnded - An event which is fired on end of a Bazel Sync Directories session.
- Adding some logging to track the extension activities, including extension activation
Signed-off-by: Sergii Puliaiev <spuliaiev@salesforce.com>
…into spuliaiev/api Signed-off-by: Sergii Puliaiev <spuliaiev@salesforce.com>
Signed-off-by: Sergii Puliaiev <spuliaiev@salesforce.com>
Signed-off-by: Sergii Puliaiev <spuliaiev@salesforce.com>
onBazelProjectFileCreated, | ||
onBazelProjectFileUpdated, | ||
onSyncDirectoriesStarted, | ||
onSyncDirectoriesEnded, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a lot of APIs. Can it be consolidated into less? I don't see why we need separate calls for start and end. We can submit just the result.
/**
* Event emitted when a sync operations completed.
* @param syncMode - mode of synchronization (full, directories)
* @param status - ok or cancelled or failed
* @param workspacePath - the Bazel workspace that was synchronized
* @param durationInMilliseconds - the duration of the synchronization in milliseconds
*/
public onSyncFinished(syncMode: enum, status: string, workspacePath: string, durationInMilliseconds: number);
Also, it's a bit confusing why this is API. Would we expose/export a way to add event listeners and these listeners need to implement an interface with that method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added an interface to add event listeners for the BazelTerminalLog - via patterns.
Removed onSyncEnded - because it is based on the log - so it will be configured from telemetry extension
src/loggingTCPServer.ts
Outdated
@@ -13,6 +14,7 @@ let server: Server | undefined; | |||
function startTCPServer(attempts = 0): Promise<number> { | |||
let port = 0; | |||
if (workspace.getConfiguration('java').has('jdt.ls.vmargs')) { | |||
LOGGER.info('Adjusting vmargs for TCP Server.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug not info
src/loggingTCPServer.ts
Outdated
@@ -28,6 +30,7 @@ function startTCPServer(attempts = 0): Promise<number> { | |||
|
|||
return new Promise((resolve) => { | |||
if (!server) { | |||
LOGGER.info('Starting TCP Server.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug not info?
src/loggingTCPServer.ts
Outdated
@@ -50,10 +53,12 @@ function startTCPServer(attempts = 0): Promise<number> { | |||
BazelLanguageServerTerminal.debug( | |||
`Bazel log server listening on port ${port}` | |||
); | |||
LOGGER.info(`Bazel log server listening on port ${port}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug not info?
src/loggingTCPServer.ts
Outdated
resolve(port); | ||
} | ||
} else { | ||
BazelLanguageServerTerminal.error(`Failed to start bazel TCP server`); | ||
LOGGER.info('Failed to start bazel TCP server'); | ||
BazelLanguageServerTerminal.error('Failed to start bazel TCP server'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why log twice? I would expect the error be surfaced alrady?
src/util.ts
Outdated
@@ -41,6 +46,9 @@ export function initBazelProjectFile() { | |||
join(workspaceRoot, '.eclipse', '.bazelproject'), | |||
BAZELPROJECT_TEMPLATE | |||
); | |||
apiHandler.fireBazelProjectFileCreated( | |||
join(workspaceRoot, '.eclipse', '.bazelproject') | |||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the value of this creation event? Why would someone interested in this not just register regular file watches?
src/extension.ts
Outdated
@@ -42,7 +45,7 @@ export async function activate(context: ExtensionContext) { | |||
// fetch all projects loaded into LS and display those too | |||
// show both .vscode and .eclipse folders | |||
// | |||
|
|||
LOGGER.info('Extension bazel-vscode-java is being activated'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug instead of info?
src/extension.ts
Outdated
toggleBazelProjectSyncStatus(doc); | ||
apiHandler.fireBazelProjectFileUpdated(doc.uri); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the value of this creation event? Why would someone interested in this not just register regular file watch?
src/extension.ts
Outdated
@@ -71,6 +78,7 @@ export async function activate(context: ExtensionContext) { | |||
); | |||
// create .eclipse/.bazelproject file is DNE | |||
if (isBazelWorkspaceRoot()) { | |||
LOGGER.info('Bazel Workspace Root detected.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug instead of info; also, additional details would be useful (location)
src/extension.ts
Outdated
@@ -84,6 +92,8 @@ export async function activate(context: ExtensionContext) { | |||
openBazelProjectFile() | |||
) | |||
); | |||
} else { | |||
LOGGER.info('Bazel Workspace Root not detected.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug instead of info?
} | ||
|
||
export function deactivate() {} | ||
|
||
function syncProjectView(): void { | ||
if (!isRedhatJavaReady()) { | ||
LOGGER.warn('RedHat Java is not ready for Bazel Project Sync.'); | ||
window.showErrorMessage( | ||
'Unable to sync project view. Java language server is not ready' | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the value of duplicate messages?
|
||
apiHandler.fireSyncStarted(workspaceRoot); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the value of this creation event? Why not start measuring here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we are not doing telemetry here. Just triggering events.
measuring and creation of spans is done in a separate extensions.
.get('notification'); | ||
LOGGER.info( | ||
`toggleBazelProjectSyncStatus: Is notification to be shown ${showNotification}` | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug instead of info
} else { | ||
LOGGER.error( | ||
`toggleBazelProjectSyncStatus: Unexpected value returned from showWarningMessage ${val}` | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that should raise an error, a log message is useless and requires extra support work to investigat/handle/diagnose
@@ -322,9 +362,12 @@ async function syncProjectViewDirectories() { | |||
); | |||
} | |||
}); | |||
apiHandler.fireSyncDirectoriesEnded(bazelProjectFile.directories); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to be adapted to api including workspace path, event type, result message and duration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no duration - it is calculated in a telemetry extension.
No event type - as we do not have onSyncEnded now - so there is no sense to create a typed event.
The only thing left is workspace path - so it's only that provided as parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's brittle. What if there is a crash or something else and events are received/fired out of order?
This API is not good. We should measure duration here and then submit one single event, similar to how the Bazel LS extension does it.
LOGGER.info(`Synchronization Summary detected. TimeTook ${timeTook}`); | ||
apiHandler.fireSyncEnded(workspaceRoot, timeTook); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a brittle contract. We should not be doing this. Instead we should hook into the Java side and emit the event reliably. API already exists
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you mean the LanguageClient api - this api client is created in RedHat Java - and not visible for all the other extensions.
Multiple connections to the same LanguageServer is still not supported unfortunately, and the client is not exposed in the redhat extension.
microsoft/language-server-protocol#1359
microsoft/language-server-protocol#1160
microsoft/vscode-languageserver-node#837
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can adjust the RedHat java extension, but that would not be easy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lonhutt suggested to hook on the terminal and catch log messages to identify events.
That's what is done now.
It might be more configurable - to just hold the list of patterns and trigger events basing on matches.
So we can configure them from the interested extensions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added that configurable patterns into PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@spuliaiev-sfdc I am talking about this extension in the Bazel LS extension: https://github.com/salesforce/bazel-eclipse/blob/main/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/SynchronizationParticipant.java
That's much more stable for telemetry.
Signed-off-by: Sergii Puliaiev <spuliaiev@salesforce.com>
* Removed Project file events * removed BazelSyncEnd event - instead added configurable BazelTerminalLog patterns * changed logging to debug - now they are not visible in the output panel Signed-off-by: Sergii Puliaiev <spuliaiev@salesforce.com>
Signed-off-by: Sergii Puliaiev <spuliaiev@salesforce.com>
resolve(port); | ||
} | ||
} else { | ||
BazelLanguageServerTerminal.error(`Failed to start bazel TCP server`); | ||
LOGGER.info('Failed to start bazel TCP server'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need port here?