Skip to content

Commit e4ef56e

Browse files
committed
ref(core): Expose prepateEvent util function
1 parent 23a58b9 commit e4ef56e

File tree

3 files changed

+197
-165
lines changed

3 files changed

+197
-165
lines changed

packages/core/src/baseclient.ts

Lines changed: 4 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -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

3935
import { getEnvelopeEndpointWithUrlEncodedAuth } from './api';
4036
import { createEventEnvelope, createSessionEnvelope } from './envelope';
4137
import { IntegrationIndex, setupIntegrations } from './integration';
4238
import { Scope } from './scope';
4339
import { updateSession } from './session';
40+
import { prepareEvent } from './utils/prepareEvent';
4441

4542
const 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
/**
@@ -644,7 +483,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
644483
);
645484
}
646485

647-
return this._prepareEvent(event, hint, scope)
486+
return prepareEvent(options, event, hint, scope)
648487
.then(prepared => {
649488
if (prepared === null) {
650489
this.recordDroppedEvent('event_processor', event.type || 'error', event);

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export { createTransport } from './transports/base';
2727
export { SDK_VERSION } from './version';
2828
export { getIntegrationsToSetup } from './integration';
2929
export { FunctionToString, InboundFilters } from './integrations';
30+
export { prepareEvent } from './utils/prepareEvent';
3031

3132
import * as Integrations from './integrations';
3233

0 commit comments

Comments
 (0)