Skip to content

meta(changelog): Update changelog for 8.40.0 #14425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,8 @@ jobs:
# - The build job was successful, not skipped
# - AND if the profiling node bindings were either successful or skipped
if: |
always() && needs.job_build.result == 'success' &&
always() &&
needs.job_build.result == 'success' &&
(needs.job_compile_bindings_profiling_node.result == 'success' || needs.job_compile_bindings_profiling_node.result == 'skipped')
needs: [job_get_metadata, job_build, job_compile_bindings_profiling_node]
runs-on: ubuntu-20.04-large-js
Expand Down Expand Up @@ -981,13 +982,16 @@ jobs:
directory: dev-packages/e2e-tests
token: ${{ secrets.CODECOV_TOKEN }}

# - We skip optional tests on release branches
job_optional_e2e_tests:
name: E2E ${{ matrix.label || matrix.test-application }} Test
# We only run E2E tests for non-fork PRs because the E2E tests require secrets to work and they can't be accessed from forks
# We need to add the `always()` check here because the previous step has this as well :(
# See: https://github.com/actions/runner/issues/2205
if:
always() && needs.job_e2e_prepare.result == 'success' &&
always() &&
needs.job_get_metadata.outputs.is_release != 'true' &&
needs.job_e2e_prepare.result == 'success' &&
needs.job_e2e_prepare.outputs.matrix-optional != '{"include":[]}' &&
(github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) &&
github.actor != 'dependabot[bot]'
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@
### Other Changes

- feat(browser): Send additional LCP timing info ([#14372](https://github.com/getsentry/sentry-javascript/pull/14372))
- feat(replay): Clear event buffer when full and in buffer mode ([#14078](https://github.com/getsentry/sentry-javascript/pull/14078))
- feat(core): Ensure `normalizedRequest` on `sdkProcessingMetadata` is merged ([#14315](https://github.com/getsentry/sentry-javascript/pull/14315))
- feat(core): Hoist everything from `@sentry/utils` into `@sentry/core` ([#14382](https://github.com/getsentry/sentry-javascript/pull/14382))
- fix(core): Do not throw when trying to fill readonly properties ([#14402](https://github.com/getsentry/sentry-javascript/pull/14402))
- fix(feedback): Fix `__self` and `__source` attributes on feedback nodes ([#14356](https://github.com/getsentry/sentry-javascript/pull/14356))
- fix(feedback): Fix non-wrapping form title ([#14355](https://github.com/getsentry/sentry-javascript/pull/14355))
- fix(nextjs): Update check for not found navigation error ([#14378](https://github.com/getsentry/sentry-javascript/pull/14378))

## 8.39.0
Expand Down
23 changes: 13 additions & 10 deletions packages/feedback/src/modal/components/Dialog.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const DIALOG = `
gap: 16px;
padding: var(--dialog-padding, 24px);
max-width: 100%;
width: 100%;
width: var(--form-width, 272px);
max-height: 100%;
overflow: auto;

Expand All @@ -71,17 +71,26 @@ const DIALOG = `
transform: translate(0, 0) scale(1);
transition: transform 0.2s ease-in-out;
}

@media (max-width: 600px) {
.dialog__content {
width: var(--form-width, 100%);
}
}

`;

const DIALOG_HEADER = `
.dialog__header {
display: flex;
align-items: center;
gap: 4px;
justify-content: space-between;
font-weight: var(--dialog-header-weight, 600);
margin: 0;
}

.dialog__title {
align-self: center;
}
.brand-link {
display: inline-flex;
}
Expand All @@ -101,18 +110,12 @@ const FORM = `

.form__right {
flex: 0 0 auto;
width: var(--form-width, 272px);
display: flex;
overflow: auto;
flex-direction: column;
justify-content: space-between;
gap: 20px;
}

@media (max-width: 600px) {
.form__right {
width: var(--form-width, 100%);
}
width: 100%;
}

.form__top {
Expand Down
2 changes: 1 addition & 1 deletion packages/feedback/src/modal/components/DialogHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function DialogHeader({ options }: Props): VNode {

return (
<h2 class="dialog__header">
{options.formTitle}
<span class="dialog__title">{options.formTitle}</span>
{options.showBranding ? (
<a
class="brand-link"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ export class EventBufferArray implements EventBuffer {
/** @inheritdoc */
public hasCheckout: boolean;

/** @inheritdoc */
public waitForCheckout: boolean;

private _totalSize: number;

public constructor() {
this.events = [];
this._totalSize = 0;
this.hasCheckout = false;
this.waitForCheckout = false;
}

/** @inheritdoc */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export class EventBufferCompressionWorker implements EventBuffer {
/** @inheritdoc */
public hasCheckout: boolean;

/** @inheritdoc */
public waitForCheckout: boolean;

private _worker: WorkerHandler;
private _earliestTimestamp: number | null;
private _totalSize;
Expand All @@ -25,6 +28,7 @@ export class EventBufferCompressionWorker implements EventBuffer {
this._earliestTimestamp = null;
this._totalSize = 0;
this.hasCheckout = false;
this.waitForCheckout = false;
}

/** @inheritdoc */
Expand Down
14 changes: 13 additions & 1 deletion packages/replay-internal/src/eventBuffer/EventBufferProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export class EventBufferProxy implements EventBuffer {
this._ensureWorkerIsLoadedPromise = this._ensureWorkerIsLoaded();
}

/** @inheritdoc */
public get waitForCheckout(): boolean {
return this._used.waitForCheckout;
}

/** @inheritdoc */
public get type(): EventBufferType {
return this._used.type;
Expand All @@ -44,6 +49,12 @@ export class EventBufferProxy implements EventBuffer {
this._used.hasCheckout = value;
}

/** @inheritdoc */
// eslint-disable-next-line @typescript-eslint/adjacent-overload-signatures
public set waitForCheckout(value: boolean) {
this._used.waitForCheckout = value;
}

/** @inheritDoc */
public destroy(): void {
this._fallback.destroy();
Expand Down Expand Up @@ -99,14 +110,15 @@ export class EventBufferProxy implements EventBuffer {

/** Switch the used buffer to the compression worker. */
private async _switchToCompressionWorker(): Promise<void> {
const { events, hasCheckout } = this._fallback;
const { events, hasCheckout, waitForCheckout } = this._fallback;

const addEventPromises: Promise<void>[] = [];
for (const event of events) {
addEventPromises.push(this._compression.addEvent(event));
}

this._compression.hasCheckout = hasCheckout;
this._compression.waitForCheckout = waitForCheckout;

// We switch over to the new buffer immediately - any further events will be added
// after the previously buffered ones
Expand Down
6 changes: 6 additions & 0 deletions packages/replay-internal/src/types/replay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,12 @@ export interface EventBuffer {
*/
hasCheckout: boolean;

/**
* If the event buffer needs to wait for a checkout event before it
* starts buffering events.
*/
waitForCheckout: boolean;

/**
* Destroy the event buffer.
*/
Expand Down
27 changes: 21 additions & 6 deletions packages/replay-internal/src/util/addEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,22 @@ async function _addEvent(
event: RecordingEvent,
isCheckout?: boolean,
): Promise<AddEventResult | null> {
if (!replay.eventBuffer) {
const { eventBuffer } = replay;

if (!eventBuffer || (eventBuffer.waitForCheckout && !isCheckout)) {
return null;
}

const isBufferMode = replay.recordingMode === 'buffer';

try {
if (isCheckout && replay.recordingMode === 'buffer') {
replay.eventBuffer.clear();
if (isCheckout && isBufferMode) {
eventBuffer.clear();
}

if (isCheckout) {
replay.eventBuffer.hasCheckout = true;
eventBuffer.hasCheckout = true;
eventBuffer.waitForCheckout = false;
}

const replayOptions = replay.getOptions();
Expand All @@ -75,9 +80,19 @@ async function _addEvent(
return;
}

return await replay.eventBuffer.addEvent(eventAfterPossibleCallback);
return await eventBuffer.addEvent(eventAfterPossibleCallback);
} catch (error) {
const reason = error && error instanceof EventBufferSizeExceededError ? 'addEventSizeExceeded' : 'addEvent';
const isExceeded = error && error instanceof EventBufferSizeExceededError;
const reason = isExceeded ? 'addEventSizeExceeded' : 'addEvent';

if (isExceeded && isBufferMode) {
// Clear buffer and wait for next checkout
eventBuffer.clear();
eventBuffer.waitForCheckout = true;

return null;
}

replay.handleException(error);

await replay.stop({ reason });
Expand Down
75 changes: 75 additions & 0 deletions packages/replay-internal/test/integration/eventBuffer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* @vitest-environment jsdom
*/

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { WINDOW } from '../../src/constants';
import type { Replay } from '../../src/integration';
import type { ReplayContainer } from '../../src/replay';
import { addEvent } from '../../src/util/addEvent';

// mock functions need to be imported first
import { BASE_TIMESTAMP, mockSdk } from '../index';
import { getTestEventCheckout, getTestEventIncremental } from '../utils/getTestEvent';
import { useFakeTimers } from '../utils/use-fake-timers';

useFakeTimers();

describe('Integration | eventBuffer | Event Buffer Max Size', () => {
let replay: ReplayContainer;
let integration: Replay;
const prevLocation = WINDOW.location;

beforeEach(async () => {
vi.setSystemTime(new Date(BASE_TIMESTAMP));

({ replay, integration } = await mockSdk());

await vi.runAllTimersAsync();
vi.clearAllMocks();
});

afterEach(async () => {
vi.setSystemTime(new Date(BASE_TIMESTAMP));
integration && (await integration.stop());
Object.defineProperty(WINDOW, 'location', {
value: prevLocation,
writable: true,
});
vi.clearAllMocks();
});

it('does not add replay breadcrumb when stopped due to event buffer limit', async () => {
const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP });

vi.mock('../../src/constants', async requireActual => ({
...(await requireActual<any>()),
REPLAY_MAX_EVENT_BUFFER_SIZE: 500,
}));

await integration.stop();
integration.startBuffering();

await addEvent(replay, TEST_EVENT);

expect(replay.eventBuffer?.hasEvents).toBe(true);
expect(replay.eventBuffer?.['hasCheckout']).toBe(true);

// This should should go over max buffer size
await addEvent(replay, TEST_EVENT);
// buffer should be cleared and wait for next checkout
expect(replay.eventBuffer?.hasEvents).toBe(false);
expect(replay.eventBuffer?.['hasCheckout']).toBe(false);

await addEvent(replay, TEST_EVENT);
expect(replay.eventBuffer?.hasEvents).toBe(false);
expect(replay.eventBuffer?.['hasCheckout']).toBe(false);

await addEvent(replay, getTestEventCheckout({ timestamp: Date.now() }), true);
expect(replay.eventBuffer?.hasEvents).toBe(true);
expect(replay.eventBuffer?.['hasCheckout']).toBe(true);

vi.resetAllMocks();
});
});
Loading
Loading