Skip to content
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

Add logging of user tier in the telemetry #1132

Merged
merged 5 commits into from
Mar 27, 2024

Conversation

pkukielka
Copy link
Contributor

@pkukielka pkukielka commented Mar 19, 2024

Fixes:
#550
sourcegraph/cody#2467

Changes

  1. Added CodyAccount::getActiveAccountTier method with result caching.
  2. Added tier logging in GraphQlLogger
  3. Refactored account change notification logic to be concentrated in one place (CodyAccount::setActiveAccount)
  4. Added periodic and on focus change querying of the account state (see CodyAuthenticationManager::init)

Test plan

Manual verification if proper entries are in the GraphQL

Copy link
Contributor

@mkondratek mkondratek left a comment

Choose a reason for hiding this comment

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

The issue: sourcegraph/cody#2467


comments, comments everywhere 🗯️

val tier =
if (getIsCurrentUserPro == null) CodyBundle.getString("my-account-tab.loading-label")
else if (getIsCurrentUserPro) CodyBundle.getString("my-account-tab.cody-pro-label")
if (isPro == null) CodyBundle.getString("my-account-tab.loading-label")

This comment was marked as resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

if (isDotcomAccount()) isProUser(project).thenApply { it.not() }
else CompletableFuture.completedFuture(false)

fun isProUser(project: Project): CompletableFuture<Boolean> {
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe deriveIsCurrentUserPro? to be more precise and reflect the fact that it's not an instant quick "get" but a call to agent

Copy link
Contributor

Choose a reason for hiding this comment

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

oh, I just realised - we are caching the pro state now... 🤔

When a user upgrades to pro they are informed that they need to restart the IDE to see the changes. What when a user downgrades to free during the usage?

Copy link
Contributor Author

@pkukielka pkukielka Mar 20, 2024

Choose a reason for hiding this comment

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

What when a user downgrades to free during the usage?\

Good question :)
#550
I will address that and some other improvements in a follow-up PR.

else CodyBundle.getString("my-account-tab.cody-free-label")
row { label("<html>Current tier: <b>$tier</b><html/>") }
row {
if (getIsCurrentUserPro != null && !getIsCurrentUserPro) {
if (isPro != null && !isPro) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: isn't that simply isPro == false?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

val upgradeButton =
button("Upgrade") { BrowserUtil.browse(ConfigUtil.DOTCOM_URL + "cody/subscription") }
upgradeButton.component.putClientProperty(DarculaButtonUI.DEFAULT_STYLE_KEY, true)
}
button("Check Usage") { BrowserUtil.browse(ConfigUtil.DOTCOM_URL + "cody/manage") }
}
if (getIsCurrentUserPro != null && !getIsCurrentUserPro) {
if (isPro != null && !isPro) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: isn't that simply isPro == false?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

}

@RequiresBackgroundThread
private fun ensureUserIdMatchInAgent(jetbrainsUserId: String, server: CodyAgentServer) {
Copy link
Contributor

Choose a reason for hiding this comment

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

so this is redundant? nice 🚀

Copy link
Contributor

Choose a reason for hiding this comment

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

tested - indeed it seems to work

return AccountType.ENTERPRISE
@Volatile private var isProUser: Boolean? = null

fun getAccountType(project: Project): String {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't like that change. The difference b/w enterprise and free/pro is different than the difference b/w free and pro. We can call the first category "account type" and the second a "tier". And my feeling is that we are adjusting the model to the telemetry requirements (which feel bad).

If we really need to consider enterprise/free/pro as a same category maybe let's introduce an enum for them. Is AccountType still needed or should we deprecate it?

Also, if we do the agent call here the method name should be altered to reflect the hidden process - "derive" instead of "get"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can move this code the the logger as it's not user anywhere else so far.

!didSendFirstMessage && !(activeAccountType.isEnterpriseAccount() || model.size <= 1)
val isEnterpriseAccount =
CodyAuthenticationManager.instance.getActiveAccount(project)?.isEnterpriseAccount() ?: false
isEnabled = !didSendFirstMessage && !isEnterpriseAccount && model.size > 1
Copy link
Contributor

Choose a reason for hiding this comment

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

hah - it looks much better now 😅

image

var event = createEvent(ConfigUtil.getServerPath(project), "CodyInstalled", new JsonObject());
var event =
createEvent(
project, ConfigUtil.getServerPath(project), "CodyInstalled", new JsonObject());
Copy link
Contributor

Choose a reason for hiding this comment

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

btw, can we have an enum class for the event name? 🙏 it would be easier to navigate b/w then and see which are already in the code in a one place

@@ -65,9 +75,15 @@ private static Event createEvent(

@NotNull
private static JsonObject addGlobalEventParameters(
Copy link
Contributor

Choose a reason for hiding this comment

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

ah, now I see why we need to cache the tier... 🕵️

Copy link
Contributor

Choose a reason for hiding this comment

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

I just noted new additional entries in the logs:

2024-03-19 23:48:44,484 [  20502]   WARN - #c.s.c.a.CodyAgentClient - Cody by Sourcegraph: █ GraphQLTelemetryExporter: telemetry: failed to evaluate server version: Error: accessing Sourcegraph GraphQL API: Error: HTTP status code 401: Private mode requires authentication.
 (https://sg02.sourcegraphcloud.com/.api/graphql?SiteProductVersion)
2024-03-19 23:48:44,867 [  20885]   WARN - #c.s.c.a.CodyAgentClient - Cody by Sourcegraph: █ GraphQLTelemetryExporter: Error exporting telemetry events: Error: accessing Sourcegraph GraphQL API: Error: HTTP status code 401: Private mode requires authentication.

Steps:

  1. runIde
  2. switch accounts from the settings

I tested it against v5.4.5 - no GraphQLTelemetryExporter entries there in the same scenario

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's a false alarm - sorry for confusion.

The issue (#454 (comment)) seems to be there already. The two mentioned lines of logs seem to appear when switching to sg02 instance account (in particular).

@pkukielka pkukielka force-pushed the pkukielka/add-user-tier-logging-telemetry branch 2 times, most recently from ea6d66a to 0fe55e6 Compare March 25, 2024 14:06
@Service
class CodyAuthenticationManager internal constructor() {
@Service(Service.Level.PROJECT)
class CodyAuthenticationManager(val project: Project) : Disposable {
Copy link
Contributor

Choose a reason for hiding this comment

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

good point about revamping it into a project-level service 👍

val accessTokenChanged: Boolean = false
)
val accessTokenChanged: Boolean = false,
val accountTierChanged: Boolean = false
Copy link
Contributor

Choose a reason for hiding this comment

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

💟

Copy link
Contributor

Choose a reason for hiding this comment

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

but it's unused 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was added mostly for clarity so e.g. in debugger when you will notice AccountSettingChangeContext it will be clear why it was emitted. With just two other properties set to false it could look like a bug.

class LlmDropdown(
private val project: Project,
private val onSetSelectedItem: (ChatModelsResponse.ChatModelProvider) -> Unit,
private val chatModelProviderFromState: ChatModelsResponse.ChatModelProvider?,
) : ComboBox<ChatModelsResponse.ChatModelProvider>(MutableCollectionComboBoxModel()) {

private var didSendFirstMessage: Boolean = false
var isCurrentUserFree = true
Copy link
Contributor

Choose a reason for hiding this comment

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

iirc that is the place you mentioned - the scenario is that a user has an open chat with no message in and changes their account tier - that change will not be reflected in the dropdown. is that right?

can you please put a comment on this field? this place looks a bit extraordinary compared to the rest of the codebase after your changes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we should just fix it, I kind of forgot about it afterwards.

Comment on lines -155 to -156
val activeAccount = accountsModel.activeAccount
activeAccountHolder.account = activeAccount
Copy link
Contributor

Choose a reason for hiding this comment

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

iiuc this logic (setting the active account in the holder) is executed anyway by CodyAuthenticationManager.getInstance(project).setActiveAccount(activeAccount)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct

agent.server.configurationDidChange(ConfigUtil.getAgentConfiguration(project))
}
CodyAgentService.getInstance(project).restartAgent(project)
if (ConfigUtil.isCodyEnabled() && context.accountChanged()) {
CodyToolWindowContent.executeOnInstanceIfNotDisposed(project) {
removeAllChatSessions()
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm, if I change the token it makes accountChanged == true but that is not necessarily mean the account changed - I mean - I can change my own token to another token of the same account

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe we should adjust the name. accountConfigurationChanged?

@pkukielka pkukielka force-pushed the pkukielka/add-user-tier-logging-telemetry branch from 27ded74 to 9602860 Compare March 27, 2024 16:31
@pkukielka pkukielka force-pushed the pkukielka/add-user-tier-logging-telemetry branch from 9602860 to 5a01768 Compare March 27, 2024 16:50
@pkukielka pkukielka merged commit 57070c5 into main Mar 27, 2024
5 checks passed
@pkukielka pkukielka deleted the pkukielka/add-user-tier-logging-telemetry branch March 27, 2024 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants