Skip to content

Commit b34541a

Browse files
committed
fix it better??
1 parent 7709fba commit b34541a

File tree

7 files changed

+91
-97
lines changed

7 files changed

+91
-97
lines changed

packages/browser-utils/src/metrics/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ export function startStandaloneWebVitalSpan(options: StandaloneWebVitalSpanOptio
108108
// For example: Chrome vs. Chrome Mobile
109109
'user_agent.original': WINDOW.navigator?.userAgent,
110110

111+
// This tells Sentry to infer the IP address from the request
112+
'client.address': '{{auto}}',
113+
111114
...passedAttributes,
112115
};
113116

packages/browser/src/client.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
ParameterizedString,
99
Scope,
1010
SeverityLevel,
11+
User,
1112
} from '@sentry/core';
1213
import { Client, applySdkMetadata, getSDKSource } from '@sentry/core';
1314
import { eventFromException, eventFromMessage } from './eventbuilder';
@@ -82,6 +83,23 @@ export class BrowserClient extends Client<BrowserClientOptions> {
8283
}
8384
});
8485
}
86+
87+
this.on('postprocessEvent', event => {
88+
addAutoIpAddressToUser(event);
89+
});
90+
91+
this.on('beforeSendSession', session => {
92+
if ('aggregates' in session) {
93+
if (session.attrs?.['ip_address'] === undefined) {
94+
session.attrs = {
95+
...session.attrs,
96+
ip_address: '{{auto}}',
97+
};
98+
}
99+
} else {
100+
addAutoIpAddressToUser(session);
101+
}
102+
});
85103
}
86104

87105
/**
@@ -113,22 +131,18 @@ export class BrowserClient extends Client<BrowserClientOptions> {
113131
): PromiseLike<Event | null> {
114132
event.platform = event.platform || 'javascript';
115133

116-
return super._prepareEvent(event, hint, currentScope, isolationScope).then(prepared => {
117-
if (!prepared) {
118-
return prepared;
119-
}
120-
121-
// By default, we want to infer the IP address, unless this is explicitly set to `null`
122-
// We do this after all other processing is done
123-
// If `ip_address` is explicitly set to `null` or a value, we leave it as is
124-
if (prepared.user?.ip_address === undefined) {
125-
prepared.user = {
126-
...prepared.user,
127-
ip_address: '{{auto}}',
128-
};
129-
}
134+
return super._prepareEvent(event, hint, currentScope, isolationScope);
135+
}
136+
}
130137

131-
return prepared;
132-
});
138+
// By default, we want to infer the IP address, unless this is explicitly set to `null`
139+
// We do this after all other processing is done
140+
// If `ip_address` is explicitly set to `null` or a value, we leave it as is
141+
function addAutoIpAddressToUser(objWithMaybeUser: { user?: User | null }): void {
142+
if (objWithMaybeUser.user?.ip_address === undefined) {
143+
objWithMaybeUser.user = {
144+
...objWithMaybeUser.user,
145+
ip_address: '{{auto}}',
146+
};
133147
}
134148
}

packages/core/src/client.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
411411
}
412412
sessionAttrs.release = sessionAttrs.release || clientReleaseOption;
413413
sessionAttrs.environment = sessionAttrs.environment || clientEnvironmentOption;
414+
session.attrs = sessionAttrs;
414415
} else {
415416
if (!session.release && !clientReleaseOption) {
416417
DEBUG_BUILD && logger.warn(MISSING_RELEASE_FOR_SESSION_ERROR);
@@ -420,6 +421,8 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
420421
session.environment = session.environment || clientEnvironmentOption;
421422
}
422423

424+
this.emit('beforeSendSession', session);
425+
423426
const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel);
424427

425428
// sendEnvelope should not throw
@@ -503,6 +506,13 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
503506
*/
504507
public on(hook: 'beforeSendEvent', callback: (event: Event, hint?: EventHint | undefined) => void): () => void;
505508

509+
/**
510+
* Register a callback for before sending a session or session aggregrates..
511+
* Receives the session/aggregate as second argument.
512+
* @returns {() => void} A function that, when executed, removes the registered callback.
513+
*/
514+
public on(hook: 'beforeSendSession', callback: (session: Session | SessionAggregates) => void): () => void;
515+
506516
/**
507517
* Register a callback for preprocessing an event,
508518
* before it is passed to (global) event processors.
@@ -511,6 +521,14 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
511521
*/
512522
public on(hook: 'preprocessEvent', callback: (event: Event, hint?: EventHint | undefined) => void): () => void;
513523

524+
/**
525+
* Register a callback for postprocessing an event,
526+
* after it was passed to (global) event processors, before it is being sent.
527+
* Receives an Event & EventHint as arguments.
528+
* @returns {() => void} A function that, when executed, removes the registered callback.
529+
*/
530+
public on(hook: 'postprocessEvent', callback: (event: Event, hint?: EventHint | undefined) => void): () => void;
531+
514532
/**
515533
* Register a callback for when an event has been sent.
516534
* @returns {() => void} A function that, when executed, removes the registered callback.
@@ -636,12 +654,24 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
636654
*/
637655
public emit(hook: 'beforeSendEvent', event: Event, hint?: EventHint): void;
638656

657+
/**
658+
* Fire a hook event before sending a session/aggregates.
659+
* Expects to be given the prepared session/aggregates as second argument.
660+
*/
661+
public emit(hook: 'beforeSendSession', session: Session | SessionAggregates): void;
662+
639663
/**
640664
* Fire a hook event to process events before they are passed to (global) event processors.
641665
* Expects to be given an Event & EventHint as the second/third argument.
642666
*/
643667
public emit(hook: 'preprocessEvent', event: Event, hint?: EventHint): void;
644668

669+
/**
670+
* Fire a hook event to process a user on an event before it is sent to Sentry, after all other processors have run.
671+
* Expects to be given an Event & EventHint as the second/third argument.
672+
*/
673+
public emit(hook: 'postprocessEvent', event: Event, hint?: EventHint): void;
674+
645675
/*
646676
* Fire a hook event after sending an event. Expects to be given an Event as the
647677
* second argument.
@@ -831,6 +861,8 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
831861
return evt;
832862
}
833863

864+
this.emit('postprocessEvent', evt, hint);
865+
834866
evt.contexts = {
835867
trace: getTraceContextFromScope(currentScope),
836868
...evt.contexts,

packages/core/src/types-hoist/session.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export interface SessionAggregates {
3737
attrs?: {
3838
environment?: string;
3939
release?: string;
40+
ip_address?: string | null;
4041
};
4142
aggregates: Array<AggregationCounts>;
4243
}

packages/profiling-node/src/integration.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ function setupAutomatedSpanProfiling(client: NodeClient): void {
147147
client.emit('preprocessEvent', profile, {
148148
event_id: profiledTransaction.event_id,
149149
});
150+
151+
// @ts-expect-error profile does not inherit from Event
152+
client.emit('postprocessEvent', profile, {
153+
event_id: profiledTransaction.event_id,
154+
});
150155
}
151156

152157
addProfilesToEnvelope(envelope, profilesToAddToEnvelope);

packages/replay-internal/src/util/prepareReplayEvent.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export async function prepareReplayEvent({
4040
return null;
4141
}
4242

43+
client.emit('postprocessEvent', preparedEvent, eventHint);
44+
4345
// This normally happens in browser client "_prepareEvent"
4446
// but since we do not use this private method from the client, but rather the plain import
4547
// we need to do this manually.
@@ -55,15 +57,5 @@ export async function prepareReplayEvent({
5557
version: version || '0.0.0',
5658
};
5759

58-
// By default, we want to infer the IP address, unless this is explicitly set to `null`
59-
// We do this after all other processing is done
60-
// If `ip_address` is explicitly set to `null` or a value, we leave it as is
61-
if (preparedEvent.user?.ip_address === undefined) {
62-
preparedEvent.user = {
63-
...preparedEvent.user,
64-
ip_address: '{{auto}}',
65-
};
66-
}
67-
6860
return preparedEvent;
6961
}

packages/replay-internal/test/unit/util/prepareReplayEvent.test.ts

Lines changed: 18 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -77,21 +77,20 @@ describe('Unit | util | prepareReplayEvent', () => {
7777
name: 'sentry.javascript.testSdk',
7878
version: '1.0.0',
7979
},
80-
user: {
81-
ip_address: '{{auto}}',
82-
},
8380
sdkProcessingMetadata: expect.any(Object),
8481
breadcrumbs: undefined,
8582
});
8683
});
8784

88-
it('sets user', async () => {
85+
it('emits hooks', async () => {
8986
const client = getClient()!;
9087
const scope = getCurrentScope().clone();
9188

92-
scope.setUser({ id: 'user-id' });
89+
const preprocessEvent = vi.fn();
90+
const postprocessEvent = vi.fn();
9391

94-
expect(client).toBeDefined();
92+
const removeHook1 = client.on('preprocessEvent', preprocessEvent);
93+
const removeHook2 = client.on('postprocessEvent', postprocessEvent);
9594

9695
const replayId = 'replay-ID';
9796
const event: ReplayEvent = {
@@ -111,11 +110,7 @@ describe('Unit | util | prepareReplayEvent', () => {
111110
},
112111
};
113112

114-
const replayEvent = await prepareReplayEvent({ scope, client, replayId, event });
115-
116-
expect(client.getSdkMetadata).toHaveBeenCalledTimes(1);
117-
118-
expect(replayEvent).toEqual({
113+
const processedEvent = {
119114
type: 'replay_event',
120115
timestamp: 1670837008.634,
121116
error_ids: ['error-ID'],
@@ -137,73 +132,25 @@ describe('Unit | util | prepareReplayEvent', () => {
137132
name: 'sentry.javascript.testSdk',
138133
version: '1.0.0',
139134
},
140-
user: {
141-
id: 'user-id',
142-
ip_address: '{{auto}}',
143-
},
144135
sdkProcessingMetadata: expect.any(Object),
145136
breadcrumbs: undefined,
146-
});
147-
});
148-
149-
it('allows to set user.ip_address=null', async () => {
150-
const client = getClient()!;
151-
const scope = getCurrentScope().clone();
152-
153-
scope.setUser({ id: 'user-id', ip_address: null });
154-
155-
expect(client).toBeDefined();
156-
157-
const replayId = 'replay-ID';
158-
const event: ReplayEvent = {
159-
type: REPLAY_EVENT_NAME,
160-
timestamp: 1670837008.634,
161-
error_ids: ['error-ID'],
162-
trace_ids: ['trace-ID'],
163-
urls: ['https://sentry.io/'],
164-
replay_id: replayId,
165-
replay_type: 'session',
166-
segment_id: 3,
167-
contexts: {
168-
replay: {
169-
error_sample_rate: 1.0,
170-
session_sample_rate: 0.1,
171-
},
172-
},
173137
};
174138

175-
const replayEvent = await prepareReplayEvent({ scope, client, replayId, event });
139+
await prepareReplayEvent({ scope, client, replayId, event });
176140

177-
expect(client.getSdkMetadata).toHaveBeenCalledTimes(1);
141+
expect(preprocessEvent).toHaveBeenCalledTimes(1);
142+
expect(preprocessEvent).toHaveBeenCalledWith(event, {
143+
event_id: 'replay-ID',
144+
integrations: [],
145+
});
178146

179-
expect(replayEvent).toEqual({
180-
type: 'replay_event',
181-
timestamp: 1670837008.634,
182-
error_ids: ['error-ID'],
183-
trace_ids: ['trace-ID'],
184-
urls: ['https://sentry.io/'],
185-
replay_id: 'replay-ID',
186-
replay_type: 'session',
187-
segment_id: 3,
188-
platform: 'javascript',
147+
expect(postprocessEvent).toHaveBeenCalledTimes(1);
148+
expect(postprocessEvent).toHaveBeenCalledWith(processedEvent, {
189149
event_id: 'replay-ID',
190-
environment: 'production',
191-
contexts: {
192-
replay: {
193-
error_sample_rate: 1.0,
194-
session_sample_rate: 0.1,
195-
},
196-
},
197-
sdk: {
198-
name: 'sentry.javascript.testSdk',
199-
version: '1.0.0',
200-
},
201-
user: {
202-
id: 'user-id',
203-
ip_address: null,
204-
},
205-
sdkProcessingMetadata: expect.any(Object),
206-
breadcrumbs: undefined,
150+
integrations: [],
207151
});
152+
153+
removeHook1();
154+
removeHook2();
208155
});
209156
});

0 commit comments

Comments
 (0)