Skip to content

Commit

Permalink
[AXON-130] experiment auth UI flow analytics (#133)
Browse files Browse the repository at this point in the history
* AXON-130: refactor login action message flow to include better error handling and analytic posting

* AXON-130: updated athenticated event to include if it is onboarding or not
  • Loading branch information
cabella-dot authored Feb 19, 2025
1 parent ea30071 commit 734f180
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 26 deletions.
4 changes: 2 additions & 2 deletions src/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ export async function featureChangeEvent(featureId: string, enabled: boolean): P
return trackEvent(action, 'feature', { actionSubjectId: featureId });
}

export async function authenticatedEvent(site: DetailedSiteInfo): Promise<TrackEvent> {
export async function authenticatedEvent(site: DetailedSiteInfo, isOnboarding?: boolean): Promise<TrackEvent> {
return instanceTrackEvent(site, 'authenticated', 'atlascode', {
attributes: { machineId: Container.machineId, hostProduct: site.product.name },
attributes: { machineId: Container.machineId, hostProduct: site.product.name, onboarding: isOnboarding },
});
}

Expand Down
13 changes: 7 additions & 6 deletions src/atlclients/loginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ export class LoginManager {
}

// this is *only* called when login buttons are clicked by the user
public async userInitiatedOAuthLogin(site: SiteInfo, callback: string): Promise<void> {
public async userInitiatedOAuthLogin(site: SiteInfo, callback: string, isOnboarding?: boolean): Promise<void> {
const provider = oauthProviderForSite(site)!;
if (!provider) {
throw new Error(`No provider found for ${site.host}`);
}
const resp = await this._dancer.doDance(provider, site, callback);
this.saveDetails(provider, site, resp);
this.saveDetails(provider, site, resp, isOnboarding);
}

private async saveDetails(provider: OAuthProvider, site: SiteInfo, resp: OAuthResponse) {
private async saveDetails(provider: OAuthProvider, site: SiteInfo, resp: OAuthResponse, isOnboarding?: boolean) {
try {
const oauthInfo: OAuthInfo = {
access: resp.access,
Expand All @@ -75,7 +75,7 @@ export class LoginManager {
siteDetails.forEach(async (siteInfo) => {
await this._credentialManager.saveAuthInfo(siteInfo, oauthInfo);
this._siteManager.addSites([siteInfo]);
authenticatedEvent(siteInfo).then((e) => {
authenticatedEvent(siteInfo, isOnboarding).then((e) => {
this._analyticsClient.sendTrackEvent(e);
});
});
Expand All @@ -101,11 +101,12 @@ export class LoginManager {
return [];
}

public async userInitiatedServerLogin(site: SiteInfo, authInfo: AuthInfo): Promise<void> {
public async userInitiatedServerLogin(site: SiteInfo, authInfo: AuthInfo, isOnboarding?: boolean): Promise<void> {
if (isBasicAuthInfo(authInfo) || isPATAuthInfo(authInfo)) {
try {
const siteDetails = await this.saveDetailsForServerSite(site, authInfo);
authenticatedEvent(siteDetails).then((e) => {

authenticatedEvent(siteDetails, isOnboarding).then((e) => {
this._analyticsClient.sendTrackEvent(e);
});
} catch (err) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,23 @@ export class OnboardingWebviewController implements WebviewController<SectionCha
}
case OnboardingActionType.Login: {
let isCloud = true;
if (isBasicAuthInfo(msg.authInfo)) {
isCloud = false;
try {
this._analytics.fireAuthenticateButtonEvent(id, msg.siteInfo, isCloud);
try {
if (isBasicAuthInfo(msg.authInfo)) {
isCloud = false;
await this._api.authenticateServer(msg.siteInfo, msg.authInfo);
} catch (e) {
const err = new Error(`Authentication error: ${e}`);
this._logger.error(err);
this.postMessage({
type: CommonMessageType.Error,
reason: formatError(e, 'Authentication error'),
});
} else {
await this._api.authenticateCloud(msg.siteInfo, this._onboardingUrl);
}
} else {
await this._api.authenticateCloud(msg.siteInfo, this._onboardingUrl);
this.postMessage({ type: OnboardingMessageType.LoginResponse });
} catch (e) {
const env = isCloud ? 'cloud' : 'server';
this._logger.error(new Error(`${env} onboarding authentication error: ${e}`));
this.postMessage({
type: CommonMessageType.Error,
reason: formatError(e, `${env} onboarding authentication error`),
});
}
this.postMessage({ type: OnboardingMessageType.LoginResponse });
this._analytics.fireAuthenticateButtonEvent(id, msg.siteInfo, isCloud);
break;
}
case OnboardingActionType.SaveSettings: {
Expand Down
4 changes: 2 additions & 2 deletions src/vscAnalyticsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export class VSCAnalyticsApi implements AnalyticsApi {
});
}

public async fireAuthenticatedEvent(site: DetailedSiteInfo): Promise<void> {
return authenticatedEvent(site).then((e) => {
public async fireAuthenticatedEvent(site: DetailedSiteInfo, isOnboarding?: boolean): Promise<void> {
return authenticatedEvent(site, isOnboarding).then((e) => {
this._analyticsClient.sendTrackEvent(e);
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/webview/onboarding/vscOnboardingActionApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ export class VSCOnboardingActionApi implements OnboardingActionApi {
}

public async authenticateServer(site: SiteInfo, authInfo: AuthInfo): Promise<void> {
return await Container.loginManager.userInitiatedServerLogin(site, authInfo);
return await Container.loginManager.userInitiatedServerLogin(site, authInfo, true);
}

public async authenticateCloud(site: SiteInfo, callback: string): Promise<void> {
return Container.loginManager.userInitiatedOAuthLogin(site, callback);
return Container.loginManager.userInitiatedOAuthLogin(site, callback, true);
}

public async clearAuth(site: DetailedSiteInfo): Promise<void> {
Expand Down

0 comments on commit 734f180

Please sign in to comment.