Skip to content

feat: Rework how we track sessions #3224

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

Merged
merged 7 commits into from
Feb 4, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 6 additions & 55 deletions packages/browser/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,61 +201,10 @@ function startSessionTracking(): void {

const hub = getCurrentHub();

/**
* We should be using `Promise.all([windowLoaded, firstContentfulPaint])` here,
* but, as always, it's not available in the IE10-11. Thanks IE.
*/
let loadResolved = document.readyState === 'complete';
let fcpResolved = false;
const possiblyEndSession = (): void => {
if (fcpResolved && loadResolved) {
hub.endSession();
}
};
const resolveWindowLoaded = (): void => {
loadResolved = true;
possiblyEndSession();
window.removeEventListener('load', resolveWindowLoaded);
};

hub.startSession();

if (!loadResolved) {
// IE doesn't support `{ once: true }` for event listeners, so we have to manually
// attach and then detach it once completed.
window.addEventListener('load', resolveWindowLoaded);
}

try {
const po = new PerformanceObserver((entryList, po) => {
entryList.getEntries().forEach(entry => {
if (entry.name === 'first-contentful-paint' && entry.startTime < firstHiddenTime) {
po.disconnect();
fcpResolved = true;
possiblyEndSession();
}
});
});

// There's no need to even attach this listener if `PerformanceObserver` constructor will fail,
// so we do it below here.
let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
document.addEventListener(
'visibilitychange',
event => {
firstHiddenTime = Math.min(firstHiddenTime, event.timeStamp);
},
{ once: true },
);

po.observe({
type: 'paint',
buffered: true,
});
} catch (e) {
fcpResolved = true;
possiblyEndSession();
}
// We end the session without removing it from the scope
// which is equal to sending it.
hub.endSession(false);

// We want to create a session for every navigation as well
addInstrumentationHandler({
Expand All @@ -266,7 +215,9 @@ function startSessionTracking(): void {
?.getSession()
) {
hub.startSession();
hub.endSession();
// We end the session without removing it from the scope
// which is equal to sending it.
hub.endSession(false);
}
},
type: 'history',
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/baseclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ export abstract class BaseClient<B extends Backend, O extends Options> implement
logger.warn('Discarded session because of missing release');
} else {
this._sendSession(session);
// After sending, we set init false to inidcate it's not the first occurence
session.update({ init: false });
}
}

Expand Down Expand Up @@ -252,6 +254,7 @@ export abstract class BaseClient<B extends Backend, O extends Options> implement
userAgent,
errors: session.errors + Number(errored || crashed),
});
this.captureSession(session);
}

/** Deliver captured session to Sentry */
Expand Down
19 changes: 13 additions & 6 deletions packages/hub/src/hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
Transaction,
TransactionContext,
User,
SessionStatus,
} from '@sentry/types';
import { consoleSandbox, dateTimestampInSeconds, getGlobalObject, isNodeEnv, logger, uuid4 } from '@sentry/utils';

Expand Down Expand Up @@ -361,9 +362,6 @@ export class Hub implements HubInterface {
* @inheritDoc
*/
public startSession(context?: SessionContext): Session {
// End existing session if there's one
this.endSession();

const { scope, client } = this.getStackTop();
const { release, environment } = (client && client.getOptions()) || {};
const session = new Session({
Expand All @@ -373,6 +371,14 @@ export class Hub implements HubInterface {
...context,
});
if (scope) {
// End existing session if there's one
const session = scope.getSession && scope.getSession();
if (session) {
session.update({ status: SessionStatus.Exited });
}
this.endSession();

// Afterwards we set the new session on the scope
scope.setSession(session);
}
return session;
Expand All @@ -381,17 +387,18 @@ export class Hub implements HubInterface {
/**
* @inheritDoc
*/
public endSession(): void {
public endSession(clearSessionFromScope: boolean = true): void {
const { scope, client } = this.getStackTop();
if (!scope) return;

const session = scope.getSession && scope.getSession();
if (session) {
session.close();
if (client && client.captureSession) {
client.captureSession(session);
}
scope.setSession();
if (clearSessionFromScope) {
scope.setSession();
}
}
}

Expand Down
6 changes: 5 additions & 1 deletion packages/hub/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class Session implements SessionInterface {
public status: SessionStatus = SessionStatus.Ok;
public environment?: string;
public ipAddress?: string;
public init: boolean = true;

constructor(context?: Omit<SessionContext, 'started' | 'status'>) {
if (context) {
Expand All @@ -42,6 +43,9 @@ export class Session implements SessionInterface {
// Good enough uuid validation. — Kamil
this.sid = context.sid.length === 32 ? context.sid : uuid4();
}
if (context.init !== undefined) {
this.init = context.init;
}
if (context.did) {
this.did = `${context.did}`;
}
Expand Down Expand Up @@ -103,7 +107,7 @@ export class Session implements SessionInterface {
} {
return dropUndefinedKeys({
sid: `${this.sid}`,
init: true,
init: this.init,
started: new Date(this.started).toISOString(),
timestamp: new Date(this.timestamp).toISOString(),
status: this.status,
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface Session extends SessionContext {
export interface SessionContext {
sid?: string;
did?: string;
init?: boolean;
timestamp?: number;
started?: number;
duration?: number;
Expand Down