@@ -21,26 +21,23 @@ import {
2121 addItemToEnvelope ,
2222 checkOrSetAlreadyCaught ,
2323 createAttachmentEnvelopeItem ,
24- dateTimestampInSeconds ,
2524 isPlainObject ,
2625 isPrimitive ,
2726 isThenable ,
2827 logger ,
2928 makeDsn ,
30- normalize ,
3129 rejectedSyncPromise ,
3230 resolvedSyncPromise ,
3331 SentryError ,
3432 SyncPromise ,
35- truncate ,
36- uuid4 ,
3733} from '@sentry/utils' ;
3834
3935import { getEnvelopeEndpointWithUrlEncodedAuth } from './api' ;
4036import { createEventEnvelope , createSessionEnvelope } from './envelope' ;
4137import { IntegrationIndex , setupIntegrations } from './integration' ;
4238import { Scope } from './scope' ;
4339import { updateSession } from './session' ;
40+ import { prepareEvent } from './utils/prepareEvent' ;
4441
4542const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured." ;
4643
@@ -320,7 +317,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
320317 // Note: we use `event` in replay, where we overwrite this hook.
321318
322319 if ( this . _options . sendClientReports ) {
323- // We want to track each category (error, transaction, session) separately
320+ // We want to track each category (error, transaction, session, replay_event ) separately
324321 // but still keep the distinction between different type of outcomes.
325322 // We could use nested maps, but it's much easier to read and type this way.
326323 // A correct type for map-based implementation if we want to go that route
@@ -417,166 +414,8 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
417414 * @returns A new event with more information.
418415 */
419416 protected _prepareEvent ( event : Event , hint : EventHint , scope ?: Scope ) : PromiseLike < Event | null > {
420- const { normalizeDepth = 3 , normalizeMaxBreadth = 1_000 } = this . getOptions ( ) ;
421- const prepared : Event = {
422- ...event ,
423- event_id : event . event_id || hint . event_id || uuid4 ( ) ,
424- timestamp : event . timestamp || dateTimestampInSeconds ( ) ,
425- } ;
426-
427- this . _applyClientOptions ( prepared ) ;
428- this . _applyIntegrationsMetadata ( prepared ) ;
429-
430- // If we have scope given to us, use it as the base for further modifications.
431- // This allows us to prevent unnecessary copying of data if `captureContext` is not provided.
432- let finalScope = scope ;
433- if ( hint . captureContext ) {
434- finalScope = Scope . clone ( finalScope ) . update ( hint . captureContext ) ;
435- }
436-
437- // We prepare the result here with a resolved Event.
438- let result = resolvedSyncPromise < Event | null > ( prepared ) ;
439-
440- // This should be the last thing called, since we want that
441- // {@link Hub.addEventProcessor } gets the finished prepared event.
442- //
443- // We need to check for the existence of `finalScope.getAttachments`
444- // because `getAttachments` can be undefined if users are using an older version
445- // of `@sentry/core` that does not have the `getAttachments` method.
446- // See: https://github.com/getsentry/sentry-javascript/issues/5229
447- if ( finalScope && finalScope . getAttachments ) {
448- // Collect attachments from the hint and scope
449- const attachments = [ ...( hint . attachments || [ ] ) , ...finalScope . getAttachments ( ) ] ;
450-
451- if ( attachments . length ) {
452- hint . attachments = attachments ;
453- }
454-
455- // In case we have a hub we reassign it.
456- result = finalScope . applyToEvent ( prepared , hint ) ;
457- }
458-
459- return result . then ( evt => {
460- if ( typeof normalizeDepth === 'number' && normalizeDepth > 0 ) {
461- return this . _normalizeEvent ( evt , normalizeDepth , normalizeMaxBreadth ) ;
462- }
463- return evt ;
464- } ) ;
465- }
466-
467- /**
468- * Applies `normalize` function on necessary `Event` attributes to make them safe for serialization.
469- * Normalized keys:
470- * - `breadcrumbs.data`
471- * - `user`
472- * - `contexts`
473- * - `extra`
474- * @param event Event
475- * @returns Normalized event
476- */
477- protected _normalizeEvent ( event : Event | null , depth : number , maxBreadth : number ) : Event | null {
478- if ( ! event ) {
479- return null ;
480- }
481-
482- const normalized : Event = {
483- ...event ,
484- ...( event . breadcrumbs && {
485- breadcrumbs : event . breadcrumbs . map ( b => ( {
486- ...b ,
487- ...( b . data && {
488- data : normalize ( b . data , depth , maxBreadth ) ,
489- } ) ,
490- } ) ) ,
491- } ) ,
492- ...( event . user && {
493- user : normalize ( event . user , depth , maxBreadth ) ,
494- } ) ,
495- ...( event . contexts && {
496- contexts : normalize ( event . contexts , depth , maxBreadth ) ,
497- } ) ,
498- ...( event . extra && {
499- extra : normalize ( event . extra , depth , maxBreadth ) ,
500- } ) ,
501- } ;
502-
503- // event.contexts.trace stores information about a Transaction. Similarly,
504- // event.spans[] stores information about child Spans. Given that a
505- // Transaction is conceptually a Span, normalization should apply to both
506- // Transactions and Spans consistently.
507- // For now the decision is to skip normalization of Transactions and Spans,
508- // so this block overwrites the normalized event to add back the original
509- // Transaction information prior to normalization.
510- if ( event . contexts && event . contexts . trace && normalized . contexts ) {
511- normalized . contexts . trace = event . contexts . trace ;
512-
513- // event.contexts.trace.data may contain circular/dangerous data so we need to normalize it
514- if ( event . contexts . trace . data ) {
515- normalized . contexts . trace . data = normalize ( event . contexts . trace . data , depth , maxBreadth ) ;
516- }
517- }
518-
519- // event.spans[].data may contain circular/dangerous data so we need to normalize it
520- if ( event . spans ) {
521- normalized . spans = event . spans . map ( span => {
522- // We cannot use the spread operator here because `toJSON` on `span` is non-enumerable
523- if ( span . data ) {
524- span . data = normalize ( span . data , depth , maxBreadth ) ;
525- }
526- return span ;
527- } ) ;
528- }
529-
530- return normalized ;
531- }
532-
533- /**
534- * Enhances event using the client configuration.
535- * It takes care of all "static" values like environment, release and `dist`,
536- * as well as truncating overly long values.
537- * @param event event instance to be enhanced
538- */
539- protected _applyClientOptions ( event : Event ) : void {
540417 const options = this . getOptions ( ) ;
541- const { environment, release, dist, maxValueLength = 250 } = options ;
542-
543- if ( ! ( 'environment' in event ) ) {
544- event . environment = 'environment' in options ? environment : 'production' ;
545- }
546-
547- if ( event . release === undefined && release !== undefined ) {
548- event . release = release ;
549- }
550-
551- if ( event . dist === undefined && dist !== undefined ) {
552- event . dist = dist ;
553- }
554-
555- if ( event . message ) {
556- event . message = truncate ( event . message , maxValueLength ) ;
557- }
558-
559- const exception = event . exception && event . exception . values && event . exception . values [ 0 ] ;
560- if ( exception && exception . value ) {
561- exception . value = truncate ( exception . value , maxValueLength ) ;
562- }
563-
564- const request = event . request ;
565- if ( request && request . url ) {
566- request . url = truncate ( request . url , maxValueLength ) ;
567- }
568- }
569-
570- /**
571- * This function adds all used integrations to the SDK info in the event.
572- * @param event The event that will be filled with all integrations.
573- */
574- protected _applyIntegrationsMetadata ( event : Event ) : void {
575- const integrationsArray = Object . keys ( this . _integrations ) ;
576- if ( integrationsArray . length > 0 ) {
577- event . sdk = event . sdk || { } ;
578- event . sdk . integrations = [ ...( event . sdk . integrations || [ ] ) , ...integrationsArray ] ;
579- }
418+ return prepareEvent ( options , event , hint , scope ) ;
580419 }
581420
582421 /**
0 commit comments