Skip to content

Commit c19981d

Browse files
Update prod (#402)
* fix(releases): cover case with empty map body (#397) * imp(email): link to billing (#398) * imp(email): link to billing * chore(email): update patterns * imp(paymaster): add paid until field for workspace (#400) * feat(paymaster): support paid until workspace field * chore(paymaster): update types and test * chore(): lint fix * chore(): lint fix * imp(CI): update ubuntu version * test(paymaster): add new testcase * chore(paymaster): lint fix * feat(sentry): parse release from event contexts (#401) * feat(sentry): parse release from event contexts * imp(sentry): add task to js worker if release passed * chore(sentry): lint fix * chore(sentry): remove an outdated todo --------- Co-authored-by: e11sy <130844513+e11sy@users.noreply.github.com>
1 parent f6a7f44 commit c19981d

2 files changed

Lines changed: 132 additions & 3 deletions

File tree

workers/sentry/src/index.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { composeAddons, composeBacktrace, composeContext, composeTitle, composeU
88
import { b64decode } from './utils/base64';
99
import { DecodedEventData, EventAddons } from '@hawk.so/types';
1010
import { TextDecoder } from 'util';
11+
import { JavaScriptEventWorkerTask } from '../../javascript/types/javascript-event-worker-task';
1112
/**
1213
* Worker for handling Sentry events
1314
*/
@@ -25,8 +26,6 @@ export default class SentryEventWorker extends Worker {
2526
public async handle(event: SentryEventWorkerTask): Promise<void> {
2627
/**
2728
* Define event type
28-
*
29-
* @todo Rename to external/sentry because it is not a Hawk event
3029
*/
3130
this.type = 'external/sentry';
3231

@@ -71,6 +70,22 @@ export default class SentryEventWorker extends Worker {
7170

7271
const hawkEvent = this.transformToHawkFormat(envelopeHeaders as EventEnvelope[0], item as EventItem, projectId);
7372

73+
const payloadHasSDK = typeof itemPayload === 'object' && 'sdk' in itemPayload;
74+
75+
/**
76+
* @todo react-native could be added if we support source-map sending for Metro bundler
77+
*/
78+
const sentryJsSDK = ['browser', 'react', 'vue', 'angular', 'capacirtor', 'electron'];
79+
80+
/**
81+
* If we have release attached to the event
82+
*/
83+
if (payloadHasSDK && sentryJsSDK.includes(itemPayload.sdk.name) && hawkEvent.payload.release !== undefined) {
84+
await this.addTask(WorkerNames.JAVASCRIPT, hawkEvent as JavaScriptEventWorkerTask);
85+
86+
return;
87+
}
88+
7489
await this.addTask(WorkerNames.DEFAULT, hawkEvent as DefaultEventWorkerTask);
7590
} catch (error) {
7691
this.logger.error('Error handling envelope item:', error);
@@ -91,7 +106,7 @@ export default class SentryEventWorker extends Worker {
91106
envelopeHeader: EventEnvelope[0],
92107
eventItem: EventItem,
93108
projectId: string
94-
): DefaultEventWorkerTask {
109+
): DefaultEventWorkerTask | JavaScriptEventWorkerTask {
95110
/* eslint-disable @typescript-eslint/naming-convention */
96111
const { sent_at, trace } = envelopeHeader;
97112

workers/sentry/tests/index.test.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,120 @@ describe('SentryEventWorker', () => {
568568
});
569569
});
570570
});
571+
572+
describe('SDK validation and release handling', () => {
573+
beforeEach(() => {
574+
jest.spyOn(worker, 'addTask');
575+
});
576+
577+
it('should route to JavaScript worker when SDK is in sentryJsSDK list and release is present', async () => {
578+
const eventEnvelope: EventEnvelope = [
579+
{
580+
/* eslint-disable @typescript-eslint/naming-convention */
581+
event_id: '123e4567-e89b-12d3-a456-426614174000',
582+
sent_at: '2024-01-01T00:00:00.000Z',
583+
/* eslint-enable @typescript-eslint/naming-convention */
584+
},
585+
[
586+
[
587+
{ type: 'event' },
588+
{
589+
sdk: { name: 'browser' },
590+
release: '1.0.0',
591+
},
592+
],
593+
],
594+
];
595+
596+
await worker.handle({
597+
payload: {
598+
envelope: b64encode(serializeEnvelope(eventEnvelope) as string),
599+
},
600+
projectId: '123',
601+
catcherType: 'external/sentry',
602+
});
603+
604+
expect(worker.addTask).toHaveBeenCalledWith('errors/javascript', expect.objectContaining({
605+
catcherType: 'external/sentry',
606+
projectId: '123',
607+
payload: expect.objectContaining({
608+
release: '1.0.0',
609+
}),
610+
}));
611+
});
612+
613+
it('should route to Default worker when SDK is not in sentryJsSDK list', async () => {
614+
const eventEnvelope: EventEnvelope = [
615+
{
616+
/* eslint-disable @typescript-eslint/naming-convention */
617+
event_id: '123e4567-e89b-12d3-a456-426614174000',
618+
sent_at: '2024-01-01T00:00:00.000Z',
619+
/* eslint-enable @typescript-eslint/naming-convention */
620+
},
621+
[
622+
[
623+
{ type: 'event' },
624+
{
625+
sdk: { name: 'python' },
626+
release: '1.0.0',
627+
},
628+
],
629+
],
630+
];
631+
632+
await worker.handle({
633+
payload: {
634+
envelope: b64encode(serializeEnvelope(eventEnvelope) as string),
635+
},
636+
projectId: '123',
637+
catcherType: 'external/sentry',
638+
});
639+
640+
expect(worker.addTask).toHaveBeenCalledWith('errors/default', expect.objectContaining({
641+
catcherType: 'external/sentry',
642+
projectId: '123',
643+
payload: expect.objectContaining({
644+
release: '1.0.0',
645+
}),
646+
}));
647+
});
648+
649+
it('should route to Default worker when SDK is in sentryJsSDK list but release is missing', async () => {
650+
const eventEnvelope: EventEnvelope = [
651+
{
652+
/* eslint-disable @typescript-eslint/naming-convention */
653+
event_id: '123e4567-e89b-12d3-a456-426614174000',
654+
sent_at: '2024-01-01T00:00:00.000Z',
655+
/* eslint-enable @typescript-eslint/naming-convention */
656+
},
657+
[
658+
[
659+
{ type: 'event' },
660+
{
661+
sdk: { name: 'browser' },
662+
},
663+
],
664+
],
665+
];
666+
667+
await worker.handle({
668+
payload: {
669+
envelope: b64encode(serializeEnvelope(eventEnvelope) as string),
670+
},
671+
projectId: '123',
672+
catcherType: 'external/sentry',
673+
});
674+
675+
expect(worker.addTask).toHaveBeenCalledWith('errors/default', expect.objectContaining({
676+
catcherType: 'external/sentry',
677+
projectId: '123',
678+
payload: expect.not.objectContaining({
679+
release: expect.any(String),
680+
}),
681+
}));
682+
});
683+
});
684+
571685
describe('(real-data tests)', () => {
572686
it('should process real-world python error', async () => {
573687
const event = {

0 commit comments

Comments
 (0)