@@ -12,17 +12,21 @@ import type {
1212 FinishedCheckIn ,
1313 MonitorConfig ,
1414 Primitive ,
15+ Session ,
16+ SessionContext ,
1517 Severity ,
1618 SeverityLevel ,
1719 TransactionContext ,
1820 User ,
1921} from '@sentry/types' ;
20- import { isThenable , logger , timestampInSeconds , uuid4 } from '@sentry/utils' ;
22+ import { GLOBAL_OBJ , isThenable , logger , timestampInSeconds , uuid4 } from '@sentry/utils' ;
2123
24+ import { DEFAULT_ENVIRONMENT } from './constants' ;
2225import { DEBUG_BUILD } from './debug-build' ;
2326import type { Hub } from './hub' ;
24- import { getCurrentHub } from './hub' ;
27+ import { getCurrentHub , getIsolationScope } from './hub' ;
2528import type { Scope } from './scope' ;
29+ import { closeSession , makeSession , updateSession } from './session' ;
2630import type { ExclusiveEventHintOrCaptureContext } from './utils/prepareEvent' ;
2731import { parseEventHintOrCaptureContext } from './utils/prepareEvent' ;
2832
@@ -322,3 +326,99 @@ export function getClient<C extends Client>(): C | undefined {
322326export function getCurrentScope ( ) : Scope {
323327 return getCurrentHub ( ) . getScope ( ) ;
324328}
329+
330+ /**
331+ * Start a session on the current isolation scope.
332+ *
333+ * @param context (optional) additional properties to be applied to the returned session object
334+ *
335+ * @returns the new active session
336+ */
337+ export function startSession ( context ?: SessionContext ) : Session {
338+ const client = getClient ( ) ;
339+ const isolationScope = getIsolationScope ( ) ;
340+ const currentScope = getCurrentScope ( ) ;
341+
342+ const { release, environment = DEFAULT_ENVIRONMENT } = ( client && client . getOptions ( ) ) || { } ;
343+
344+ // Will fetch userAgent if called from browser sdk
345+ const { userAgent } = GLOBAL_OBJ . navigator || { } ;
346+
347+ const session = makeSession ( {
348+ release,
349+ environment,
350+ user : isolationScope . getUser ( ) ,
351+ ...( userAgent && { userAgent } ) ,
352+ ...context ,
353+ } ) ;
354+
355+ // End existing session if there's one
356+ const currentSession = isolationScope . getSession ( ) ;
357+ if ( currentSession && currentSession . status === 'ok' ) {
358+ updateSession ( currentSession , { status : 'exited' } ) ;
359+ }
360+
361+ endSession ( ) ;
362+
363+ // Afterwards we set the new session on the scope
364+ isolationScope . setSession ( session ) ;
365+
366+ // TODO (v8): Remove this and only use the isolation scope(?).
367+ // For v7 though, we can't "soft-break" people using getCurrentHub().getScope().setSession()
368+ currentScope . setSession ( session ) ;
369+
370+ return session ;
371+ }
372+
373+ /**
374+ * End the session on the current isolation scope.
375+ */
376+ export function endSession ( ) : void {
377+ const isolationScope = getIsolationScope ( ) ;
378+ const currentScope = getCurrentScope ( ) ;
379+
380+ const session = isolationScope . getSession ( ) ;
381+ if ( session ) {
382+ closeSession ( session ) ;
383+ }
384+ _sendSessionUpdate ( ) ;
385+
386+ // the session is over; take it off of the scope
387+ isolationScope . setSession ( ) ;
388+
389+ // TODO (v8): Remove this and only use the isolation scope(?).
390+ // For v7 though, we can't "soft-break" people using getCurrentHub().getScope().setSession()
391+ currentScope . setSession ( ) ;
392+ }
393+
394+ /**
395+ * Sends the current Session on the scope
396+ */
397+ function _sendSessionUpdate ( ) : void {
398+ const isolationScope = getIsolationScope ( ) ;
399+ const currentScope = getCurrentScope ( ) ;
400+ const client = getClient ( ) ;
401+ // TODO (v8): Remove currentScope and only use the isolation scope(?).
402+ // For v7 though, we can't "soft-break" people using getCurrentHub().getScope().setSession()
403+ const session = currentScope . getSession ( ) || isolationScope . getSession ( ) ;
404+ if ( session && client && client . captureSession ) {
405+ client . captureSession ( session ) ;
406+ }
407+ }
408+
409+ /**
410+ * Sends the current session on the scope to Sentry
411+ *
412+ * @param end If set the session will be marked as exited and removed from the scope.
413+ * Defaults to `false`.
414+ */
415+ export function captureSession ( end : boolean = false ) : void {
416+ // both send the update and pull the session from the scope
417+ if ( end ) {
418+ endSession ( ) ;
419+ return ;
420+ }
421+
422+ // only send the update
423+ _sendSessionUpdate ( ) ;
424+ }
0 commit comments