-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
82b6027
commit 4c0ca4c
Showing
6 changed files
with
230 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
packages/modules/edge-api-sdk/src/sentry/serialize-envelope.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { Envelope } from '@sentry/types' | ||
|
||
const encodeUTF8 = (input: string) => new TextEncoder().encode(input) | ||
|
||
export function serializeEnvelope(envelope: Envelope): string | Uint8Array { | ||
const [envHeaders, items] = envelope | ||
|
||
// Initially we construct our envelope as a string and only convert to binary chunks if we encounter binary data | ||
let parts: string | Uint8Array[] = JSON.stringify(envHeaders) | ||
|
||
function append(next: string | Uint8Array): void { | ||
if (typeof parts === 'string') { | ||
parts = typeof next === 'string' ? parts + next : [encodeUTF8(parts), next] | ||
} else { | ||
parts.push(typeof next === 'string' ? encodeUTF8(next) : next) | ||
} | ||
} | ||
|
||
for (const item of items) { | ||
const [itemHeaders, payload] = item | ||
|
||
append(`\n${JSON.stringify(itemHeaders)}\n`) | ||
|
||
if (typeof payload === 'string' || payload instanceof Uint8Array) { | ||
append(payload) | ||
} else { | ||
append(JSON.stringify(payload)) | ||
} | ||
} | ||
|
||
return typeof parts === 'string' ? parts : concatBuffers(parts) | ||
} | ||
|
||
function concatBuffers(buffers: Uint8Array[]): Uint8Array { | ||
const totalLength = buffers.reduce((acc, buf) => acc + buf.length, 0) | ||
|
||
const merged = new Uint8Array(totalLength) | ||
let offset = 0 | ||
for (const buffer of buffers) { | ||
merged.set(buffer, offset) | ||
offset += buffer.length | ||
} | ||
|
||
return merged | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { enableFetchMocks } from 'jest-fetch-mock' | ||
import fetchMock from 'jest-fetch-mock' | ||
enableFetchMocks() | ||
|
||
import { JSONRequest } from '../src' | ||
import { init } from '../src/sentry/sentry' | ||
import { generateCloudfrontRequest } from './logger.test' | ||
import { LogEntry, LogPayload } from '../src/logger' | ||
|
||
const generateLogPayload = (entries: LogEntry[]): LogPayload => { | ||
const event = generateCloudfrontRequest({}) | ||
const request: JSONRequest<any, any> = { | ||
env: {}, | ||
headers: { | ||
host: ['google.com'], | ||
}, | ||
method: 'GET', | ||
host: 'google.com', | ||
path: '/', | ||
region: 'eu-west-2', | ||
cookies: [], | ||
body: {}, | ||
meta: { | ||
event, | ||
functionName: 'function-name', | ||
functionVersion: 'function-version', | ||
invocationId: 'invocation-id', | ||
sessionId: 'session-id', | ||
}, | ||
} | ||
|
||
return { | ||
centralize: true, | ||
entries, | ||
event, | ||
functionName: 'functionName', | ||
functionVersion: 'functionVersion', | ||
invocationId: '', | ||
region: '', | ||
request, | ||
timestamp: new Date(0), | ||
sessionId: 'sessionId', | ||
} | ||
} | ||
|
||
describe('sentry logger transport', () => { | ||
beforeEach(() => { | ||
fetchMock.resetMocks() | ||
}) | ||
it('should init', () => { | ||
init({ | ||
dsn: 'https://asdf@qwerty.ingest.sentry.io/123456', | ||
environment: 'environment', | ||
release: 'release', | ||
}) | ||
}) | ||
|
||
it('should send exceptions to sentry', async () => { | ||
const report = init({ | ||
dsn: 'https://asdf@qwerty.ingest.sentry.io/123456', | ||
environment: 'environment', | ||
release: 'release', | ||
}) | ||
|
||
await report( | ||
generateLogPayload([ | ||
{ | ||
level: 'critical', | ||
message: 'the error message', | ||
timestamp: new Date(0), | ||
error: new Error('oh no'), | ||
}, | ||
]), | ||
) | ||
|
||
const [endpoint, reqInit] = fetchMock.mock.calls[0] | ||
expect(endpoint).toBe('https://qwerty.ingest.sentry.io/api/123456/envelope/?sentry_key=asdf&sentry_version=7') | ||
expect(reqInit?.method).toBe('post') | ||
const [, eventType, exception] = (reqInit?.body as string)?.split('\n').map((str) => JSON.parse(str)) ?? [] | ||
expect(eventType.type).toBe('event') | ||
const values = exception.exception.values | ||
expect(values[0].type).toEqual('Error') | ||
expect(values[0].value).toEqual('oh no') | ||
}) | ||
|
||
it('should send prior log entries as breadcrumbs', async () => { | ||
const report = init({ | ||
dsn: 'https://asdf@qwerty.ingest.sentry.io/123456', | ||
environment: 'environment', | ||
release: 'release', | ||
}) | ||
|
||
await report( | ||
generateLogPayload([ | ||
{ | ||
level: 'info', | ||
message: 'something interesting here', | ||
timestamp: new Date(0), | ||
}, | ||
{ | ||
level: 'critical', | ||
message: 'the error message', | ||
timestamp: new Date(1), | ||
error: new Error('oh no'), | ||
}, | ||
]), | ||
) | ||
const [, reqInit] = fetchMock.mock.calls[0] | ||
const [, , exception] = (reqInit?.body as string)?.split('\n').map((str) => JSON.parse(str)) ?? [] | ||
expect(exception.breadcrumbs).toEqual([ | ||
{ level: 'info', message: 'something interesting here', timestamp: 0 }, | ||
{ level: 'fatal', message: 'the error message', timestamp: 1 }, | ||
]) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters