Merge pull request #985 from vector-im/dbkr/fix_posthog_exception

Fix exception when loading PostHog
This commit is contained in:
David Baker 2023-04-05 15:23:54 +01:00 committed by GitHub
commit b2317dac84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 19 deletions

View file

@ -342,6 +342,9 @@ export const ClientProvider: FC<Props> = ({ children }) => {
useEffect(() => { useEffect(() => {
window.matrixclient = client; window.matrixclient = client;
window.isPasswordlessUser = isPasswordlessUser; window.isPasswordlessUser = isPasswordlessUser;
if (PosthogAnalytics.hasInstance())
PosthogAnalytics.instance.onLoginStatusChanged();
}, [client, isPasswordlessUser]); }, [client, isPasswordlessUser]);
if (error) { if (error) {

View file

@ -102,6 +102,10 @@ export class PosthogAnalytics {
private platformSuperProperties = {}; private platformSuperProperties = {};
private registrationType: RegistrationType = RegistrationType.Guest; private registrationType: RegistrationType = RegistrationType.Guest;
public static hasInstance(): boolean {
return Boolean(this.internalInstance);
}
public static get instance(): PosthogAnalytics { public static get instance(): PosthogAnalytics {
if (!this.internalInstance) { if (!this.internalInstance) {
this.internalInstance = new PosthogAnalytics(posthog); this.internalInstance = new PosthogAnalytics(posthog);
@ -227,7 +231,7 @@ export class PosthogAnalytics {
.join(""); .join("");
} }
public async identifyUser(analyticsIdGenerator: () => string) { private async identifyUser(analyticsIdGenerator: () => string) {
if (this.anonymity == Anonymity.Pseudonymous && this.enabled) { if (this.anonymity == Anonymity.Pseudonymous && this.enabled) {
// Check the user's account_data for an analytics ID to use. Storing the ID in account_data allows // Check the user's account_data for an analytics ID to use. Storing the ID in account_data allows
// different devices to send the same ID. // different devices to send the same ID.
@ -319,7 +323,12 @@ export class PosthogAnalytics {
this.setAnonymity(Anonymity.Disabled); this.setAnonymity(Anonymity.Disabled);
} }
public updateSuperProperties() { public onLoginStatusChanged(): void {
const optInAnalytics = getSetting("opt-in-analytics", false);
this.updateAnonymityAndIdentifyUser(optInAnalytics);
}
private updateSuperProperties() {
// Update super properties in posthog with our platform (app version, platform). // Update super properties in posthog with our platform (app version, platform).
// These properties will be subsequently passed in every event. // These properties will be subsequently passed in every event.
// //
@ -339,7 +348,7 @@ export class PosthogAnalytics {
return this.eventSignup.getSignupEndTime() > new Date(0); return this.eventSignup.getSignupEndTime() > new Date(0);
} }
public async updateAnonymityAndIdentifyUser( private async updateAnonymityAndIdentifyUser(
pseudonymousOptIn: boolean pseudonymousOptIn: boolean
): Promise<void> { ): Promise<void> {
// Update this.anonymity based on the user's analytics opt-in settings // Update this.anonymity based on the user's analytics opt-in settings
@ -348,6 +357,10 @@ export class PosthogAnalytics {
: Anonymity.Disabled; : Anonymity.Disabled;
this.setAnonymity(anonymity); this.setAnonymity(anonymity);
// We may not yet have a Matrix client at this point, if not, bail. This should get
// triggered again by onLoginStatusChanged once we do have a client.
if (!window.matrixclient) return;
if (anonymity === Anonymity.Pseudonymous) { if (anonymity === Anonymity.Pseudonymous) {
this.setRegistrationType( this.setRegistrationType(
window.matrixclient.isGuest() || window.isPasswordlessUser window.matrixclient.isGuest() || window.isPasswordlessUser
@ -385,7 +398,7 @@ export class PosthogAnalytics {
this.capture(eventName, properties, options); this.capture(eventName, properties, options);
} }
public startListeningToSettingsChanges(): void { private startListeningToSettingsChanges(): void {
// Listen to account data changes from sync so we can observe changes to relevant flags and update. // Listen to account data changes from sync so we can observe changes to relevant flags and update.
// This is called - // This is called -
// * On page load, when the account data is first received by sync // * On page load, when the account data is first received by sync

View file

@ -124,6 +124,8 @@ export class OTelGroupCallMembership {
} }
public onJoinCall() { public onJoinCall() {
if (!ElementCallOpenTelemetry.instance) return;
// Create the main span that tracks the time we intend to be in the call // Create the main span that tracks the time we intend to be in the call
this.callMembershipSpan = this.callMembershipSpan =
ElementCallOpenTelemetry.instance.tracer.startSpan( ElementCallOpenTelemetry.instance.tracer.startSpan(
@ -174,21 +176,23 @@ export class OTelGroupCallMembership {
for (const [userId, userCalls] of calls.entries()) { for (const [userId, userCalls] of calls.entries()) {
for (const [deviceId, call] of userCalls.entries()) { for (const [deviceId, call] of userCalls.entries()) {
if (!this.callsByCallId.has(call.callId)) { if (!this.callsByCallId.has(call.callId)) {
const span = ElementCallOpenTelemetry.instance.tracer.startSpan( if (ElementCallOpenTelemetry.instance) {
`matrix.call`, const span = ElementCallOpenTelemetry.instance.tracer.startSpan(
undefined, `matrix.call`,
this.groupCallContext undefined,
); this.groupCallContext
// XXX: anonymity );
span.setAttribute("matrix.call.target.userId", userId); // XXX: anonymity
span.setAttribute("matrix.call.target.deviceId", deviceId); span.setAttribute("matrix.call.target.userId", userId);
const displayName = span.setAttribute("matrix.call.target.deviceId", deviceId);
this.groupCall.room.getMember(userId)?.name ?? "unknown"; const displayName =
span.setAttribute("matrix.call.target.displayName", displayName); this.groupCall.room.getMember(userId)?.name ?? "unknown";
this.callsByCallId.set( span.setAttribute("matrix.call.target.displayName", displayName);
call.callId, this.callsByCallId.set(
new OTelCall(userId, deviceId, call, span) call.callId,
); new OTelCall(userId, deviceId, call, span)
);
}
} }
} }
} }
@ -321,6 +325,8 @@ export class OTelGroupCallMembership {
public onConnectionStatsReport( public onConnectionStatsReport(
statsReport: GroupCallStatsReport<ConnectionStatsReport> statsReport: GroupCallStatsReport<ConnectionStatsReport>
) { ) {
if (!ElementCallOpenTelemetry.instance) return;
const type = OTelStatsReportType.ConnectionReport; const type = OTelStatsReportType.ConnectionReport;
const data = const data =
ObjectFlattener.flattenConnectionStatsReportObject(statsReport); ObjectFlattener.flattenConnectionStatsReportObject(statsReport);
@ -330,6 +336,8 @@ export class OTelGroupCallMembership {
public onByteSentStatsReport( public onByteSentStatsReport(
statsReport: GroupCallStatsReport<ByteSentStatsReport> statsReport: GroupCallStatsReport<ByteSentStatsReport>
) { ) {
if (!ElementCallOpenTelemetry.instance) return;
const type = OTelStatsReportType.ByteSentReport; const type = OTelStatsReportType.ByteSentReport;
const data = ObjectFlattener.flattenByteSentStatsReportObject(statsReport); const data = ObjectFlattener.flattenByteSentStatsReportObject(statsReport);
this.buildStatsEventSpan({ type, data }); this.buildStatsEventSpan({ type, data });
@ -338,6 +346,8 @@ export class OTelGroupCallMembership {
public onSummaryStatsReport( public onSummaryStatsReport(
statsReport: GroupCallStatsReport<SummaryStatsReport> statsReport: GroupCallStatsReport<SummaryStatsReport>
) { ) {
if (!ElementCallOpenTelemetry.instance) return;
const type = OTelStatsReportType.SummaryReport; const type = OTelStatsReportType.SummaryReport;
const data = ObjectFlattener.flattenSummaryStatsReportObject(statsReport); const data = ObjectFlattener.flattenSummaryStatsReportObject(statsReport);
this.buildStatsEventSpan({ type, data }); this.buildStatsEventSpan({ type, data });