Skip to content

Use Telemetry v1.75 VSCode API - #4457

Merged
DanTup merged 20 commits into
masterfrom
unknown repository
Mar 29, 2023
Merged

DanTup merged 20 commits into
masterfrom
unknown repository

Conversation

@ghost

@ghost ghost commented Mar 24, 2023 •

Copy link
Copy Markdown

Migrates all telemetry code to the new TelemetrySender/TelemetryLogger API.

@ghost

ghost commented Mar 24, 2023 •

Copy link
Copy Markdown
Author

@DanTup Fixed some of the things on your comments

#4377

…nd keeps all of the business logic in wrapper `Analytics`
@ghost
ghost marked this pull request as draft March 24, 2023 15:09
@ghost

ghost commented Mar 25, 2023 •

Copy link
Copy Markdown
Author

I think some properties on the internal google analytics class need to be moved back there because the send method needs them like flutter sdk version, is using dap or lsp

@DanTup

DanTup commented Mar 27, 2023

Copy link
Copy Markdown
Member

@aitor-gomila

I think some properties on the internal google analytics class need to be moved back there because the send method needs them like flutter sdk version, is using dap or lsp

Do you mean move them to the TelemetrySender? If so, why can't we keep them on Analytics? I'd prefer the sender class to be only doing the web request, and the Analytics class to add in all other information. That way what the user sees if they look at the analytics logs is more accurate and there isn't extra info being added in after they see it.

@DanTup

DanTup commented Mar 27, 2023

Copy link
Copy Markdown
Member

@aitor-gomila I had a quick look through the analytics and here's a list of things I'd like to remove. I can do this on master but it may cause some unnecessary conflicts for you, so you're welcome to remove them here (or I can remove them later).

  • all time() calls - I don't think these timings are providing a lot of info, and it'll simplify the API slightly
  • logExtensionShutdown - there's not much value in this (it should always be the same number as the extension activates, except where the shutdown will abort it being recorded, so not much value)
  • logError (as previously discussed)
  • logDebuggerRestart & logDebuggerHotReload (these generate a lot of events and were originally to get an idea of whether people knew about hot restart/reload, which are now much more integrated and somewhat obvious)

@ghost

ghost commented Mar 27, 2023 •

Copy link
Copy Markdown
Author

Sorry for my terrible explanation.

The send method sends whatever you tell it to, plus some other device info (e.g. whether the user is using DAP or LSP).

GoogleAnalyticsTelemetrySender is merely a TelemetrySender implementation that is turned into a TelemetryLogger so Analytics can only call the methods and fields TelemetryLogger defines. In this case, logUsage, logError, and flush.

The problem is GoogleAnalyticsTelemetrySender needs to be able to access to workspaceContext and a few other things in order to have all the necessary information, and this is done by including workspaceContext and other things into the constructor.

So Analytics would just be a fancier way to call the TelemetryLogger.

Is that correct? Any feedback?

Just one more thing: I think one of the calls to this.event() which is now this.telemetryLogger.logUsage returned something. With TelemetryLogger this is no longer possible. Need to check what it does again.

@ghost

ghost commented Mar 27, 2023

Copy link
Copy Markdown
Author

@aitor-gomila I had a quick look through the analytics and here's a list of things I'd like to remove. I can do this on master but it may cause some unnecessary conflicts for you, so you're welcome to remove them here (or I can remove them later).

* all `time()` calls - I don't think these timings are providing a lot of info, and it'll simplify the API slightly

* `logExtensionShutdown` - there's not much value in this (it should always be the same number as the extension activates, except where the shutdown will abort it being recorded, so not much value)

* `logError` (as previously discussed)

* `logDebuggerRestart` & `logDebuggerHotReload` (these generate a lot of events and were originally to get an idea of whether people knew about hot restart/reload, which are now much more integrated and somewhat obvious)

Agreed, these cause unnecessary complexity, but I didn't want to change intended behaviour. logError I think needs to be kept but we can return; and call it a day. Flush can be removed safely and I intended to do so.

@DanTup

DanTup commented Mar 27, 2023 •

Copy link
Copy Markdown
Member

The problem is GoogleAnalyticsTelemetrySender needs to be able to access to workspaceContext and a few other things in order to have all the necessary information, and this is done by including workspaceContext and other things into the constructor.

This information is just added to custom dimensions though, so it should be possible to just include it in the data passed to logUsage?

Right now (before your changes), there's an event method in Analytics that just makes an object with all the data (including the SDK versions, etc.). I think we can still do that in Analytics, and have the GoogleAnalyticsTelemetrySender just receive that whole data and send it, without needing to add anything more to it?

logError I think needs to be kept but we can return; and call it a day. Flush can be removed safely and I intended to do so.

Sorry, my comment was ambiguous here :) I meant the logError in our Analytics class can be removed (and any calls to it). You're right that the one in the sender may need to stay (and can be empty).

@ghost

ghost commented Mar 27, 2023

Copy link
Copy Markdown
Author

This information is just added to custom dimensions though, so it should be possible to just include it in the data passed to logUsage?

Ok, giving it a thought, it makes sense to separate the concerns of Analytics and the Sender.

@ghost

ghost commented Mar 27, 2023 •

Copy link
Copy Markdown
Author

Ok @DanTup, updated some of the code.

  • Restored event method in Analytics class.
  • Return softly in sendErrorData.
  • Simplify sendEventData method in GoogleAnalyticsTelemetrySender.
  • Remove Analytics.time calls.
  • Remove handleError and logError in Analytics.

Since Analytics.event() now returns void instead of Promise<void>, some of the code is not working properly.

Also, some portions of GoogleAnalyticsTelemetrySender.send require a logger, I think it's fair to provide one in this case? I think we should pass those callbacks up and let Analytics handle it

Comment thread src/extension/analytics.ts Outdated
Comment on lines 69 to 71
const data = {
aip: 1,
an: "Dart Code",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be adding all of this info inside the Analytics class. Otherwise the user won't be able to see the data being sent (since VS Code is presumably only showing what's passed in to this method).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the change is in my local branch. Pushing ASAP. Thanks for letting me know.

@ghost

ghost commented Mar 27, 2023

Copy link
Copy Markdown
Author

Things to fix:

  • send method uses logger and handleError.
  • calling this.event doesn't return a promise anymore

Don't tell me how to do these, I want to learn problem solving myself. But PR is almost 99% done. Needs some testing before merging, though

@DanTup

DanTup commented Mar 28, 2023

Copy link
Copy Markdown
Member

Don't tell me how to do these, I want to learn problem solving myself

Sure! Let me know when you want me to take a look and make comments.

Thanks for your work on this so far! :-)

@ghost

ghost commented Mar 28, 2023 •

Copy link
Copy Markdown
Author

I've got a question. Send uses a handleError function. But since it's a promise, why not reject and let Analytics handle it?

In this line I'm getting a TypeError, but you are not:

req.write(querystring.stringify(data));

data is any, so it doesn't accept it, but you are using any too and it works? Is it because you are using Object.assign?

@DanTup

DanTup commented Mar 28, 2023

Copy link
Copy Markdown
Member

I've got a question. Send uses a handleError function. But since it's a promise, why not reject and let Analytics handle it?

I think you're right, we could change:

this.handleError(e);
resolve();

to:

reject(e);

and then wrap a try/catch around the code starting await new Promise<void>( and instead call handleError in a catch block.

It's been a long time since I wrote this so I'm not sure if there was a reason it was done this way, but you're welcome to change it as long as we ensure we're handling the error here (and not relying on the caller to catch it).

data is any, so it doesn't accept it, but you are using any too and it works? Is it because you are using Object.assign?

In the original code, data is not any inside send. customData is any, but data's type is inferred from the object literal where it is defined:

Screenshot 2023-03-28 at 15 39 19

We should probably avoid using explicit anys where possible (TS complains about it more than it used to). Perhaps Record<String, unknown> or Record<String, any> would work for data's type?

@ghost

ghost commented Mar 28, 2023 via email •

Copy link
Copy Markdown
Author

@DanTup

DanTup commented Mar 29, 2023

Copy link
Copy Markdown
Member

Why not use .catch(logger.info) instead of try/catch?

I think either will work. I generally prefer using await/try/catch rather than .then()/.catch() because I think the resulting code is usually easier to read (it's more like non-promise code), but sometimes I use the latter. Whichever seems to fit best for the code you're writing is fine (generally performance isn't a real concern here.. we should be sending analytics so infrequently that the time will be negligible, and hopefully exceptions are even less common).

Just one more thing: do you use ESLint/Prettier?

ES Lint should be set up. You can run npm run lint, but it should just show up in VS Code too (you might need the dbaeumer.vscode-eslint extension which is noted in .vscode/extensions.json).

@ghost

ghost commented Mar 29, 2023 •

Copy link
Copy Markdown
Author

except try/catch is synchronous code which defeats the purpose of Promises. Await too. If you don't use this frequently it's okay. But try to avoid it.

But do whatever. Not trying to sound nitpicky :)

Now I need to re-introduce that large object const data = {...}

@ghost
ghost requested a review from DanTup March 29, 2023 13:38
@ghost

ghost commented Mar 29, 2023

Copy link
Copy Markdown
Author

Everything seems to be ready. Make sure to test it well because I have not tried any of these changes If you need me to do any changes let me know ;)

@ghost
ghost marked this pull request as ready for review March 29, 2023 13:39
@DanTup

DanTup commented Mar 29, 2023

Copy link
Copy Markdown
Member

except try/catch is synchronous code which defeats the purpose of Promises. await too.

This isn't accurate :) Using await/try/catch with promises is still async code, it's just the same as using .then() and .catch(). The code is still asynchronous at awaits. I (generally) prefer it because it reduces the differences between async/sync code - you can use the same pattern (try/catch) for handling your errors.

I'll try out the changes and add feedback shortly - thanks again!

@ghost

ghost commented Mar 29, 2023 via email

Copy link
Copy Markdown
Author

@DanTup

DanTup commented Mar 29, 2023

Copy link
Copy Markdown
Member

@aitor-gomila this all looks great! I can see the analytics being sent, and they show up in the new VS Code output pane ("Extension Telemetry") when log level is set to trace:

Screenshot 2023-03-29 at 15 59 06

Thank you for the contribution!

@DanTup
DanTup merged commit 1dba6ed into Dart-Code:master Mar 29, 2023
@DanTup DanTup added this to the v3.62.0 milestone Mar 29, 2023
@DanTup DanTup added the is enhancement An enhancement or improvement that should be listed in release notes but is not a bug fix. label Mar 29, 2023
@ghost

ghost commented Mar 29, 2023 •

Copy link
Copy Markdown
Author

:,)

We should have a more visual way for thw user to see them, though!

VSCode's fault most likely tho.

Its nice to see this was born out of a confusion.

@DanTup

DanTup commented Mar 29, 2023

Copy link
Copy Markdown
Member

We should have a more visual way for thw user to see them, though!

That would be nice, but I think it's a bit out of scope for the extension - it would be better if something like that was handled by VS Code (since it should apply to all extensions and not be something specific to Dart). Maybe it's something they'll consider if everyone adopts this new unified API :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

is enhancement An enhancement or improvement that should be listed in release notes but is not a bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant