Skip to content
Open
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
3 changes: 2 additions & 1 deletion packages/core/src/browser-exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ export {
startSpan,
startInactiveSpan,
startSpanManual,
startIdleSpan,
_INTERNAL_ensureBrowserSpanStreaming,
} from './tracing/browserSpanApi';

export { startIdleSpan } from './tracing/idleSpan';

export { spanStreamingIntegration } from './integrations/browserSpanStreaming';

export {
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ export * from './browser-exports';
// `server-exports` and `browser-exports` both export these APIs.
// We need to re-export them here to disambiguate the exports for anyone importing
// from `@sentry/core`. Server exports win over browser exports.
export { startSpan, startInactiveSpan, startSpanManual } from './tracing/trace';
export { startIdleSpan } from './tracing/idleSpan';
export { spanStreamingIntegration } from './integrations/spanStreaming';
export { startSpan, startInactiveSpan, startSpanManual } from './server-exports';
export { spanStreamingIntegration } from './server-exports';
1 change: 0 additions & 1 deletion packages/core/src/server-exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

export { startSpan, startInactiveSpan, startSpanManual } from './tracing/trace';
export { startIdleSpan } from './tracing/idleSpan';
export { spanStreamingIntegration } from './integrations/spanStreaming';

export type { ServerRuntimeClientOptions } from './server-runtime-client';
Expand Down
14 changes: 0 additions & 14 deletions packages/core/src/tracing/browserSpanApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { getClient } from '../currentScopes';
import { spanStreamingIntegration } from '../integrations/browserSpanStreaming';
import type { Span } from '../types/span';
import type { StartSpanOptions } from '../types/startSpanOptions';
import { startIdleSpan as coreStartIdleSpan } from './idleSpan';
import { hasSpanStreamingEnabled } from './spans/hasSpanStreamingEnabled';
import {
startInactiveSpan as coreStartInactiveSpan,
Expand Down Expand Up @@ -70,16 +69,3 @@ export function startInactiveSpan(options: StartSpanOptions): Span {
_INTERNAL_ensureBrowserSpanStreaming();
return coreStartInactiveSpan(options);
}

/**
* Starts an idle span that automatically ends once no activity happens for a while.
*
* See {@link startIdleSpan} in `@sentry/core` for details.
*
* Typed via `typeof` because `IdleSpanOptions` is intentionally not part of the public type surface,
* and re-declaring the signature here would have to widen it.
*/
export const startIdleSpan: typeof coreStartIdleSpan = (startSpanOptions, options) => {
_INTERNAL_ensureBrowserSpanStreaming();
return coreStartIdleSpan(startSpanOptions, options);
};
20 changes: 8 additions & 12 deletions packages/core/src/tracing/idleSpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
spanToStaticSpanJSON,
} from '../utils/spanUtils';
import { timestampInSeconds } from '../utils/time';
import { _INTERNAL_ensureBrowserSpanStreaming } from './browserSpanApi';
import { SentryNonRecordingSpan, spanIsNonRecordingSpan } from './sentryNonRecordingSpan';
import { SentrySpan } from './sentrySpan';
import { SPAN_STATUS_ERROR, SPAN_STATUS_OK } from './spanstatus';
Expand Down Expand Up @@ -89,6 +90,9 @@ interface IdleSpanOptions {
* An idle span is always the active span.
*/
export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Partial<IdleSpanOptions> = {}): Span {
const client = getClient();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The startIdleSpan function in core now unconditionally installs a browser-specific span streaming integration, which will cause issues if the function is called in a server environment.
Severity: MEDIUM

Suggested Fix

The startIdleSpan function should not unconditionally install the browser-specific integration. Instead, it should perform an environment check to ensure the correct integration is installed, or the responsibility for installing the appropriate integration should be moved to the environment-specific SDKs (browser/server) rather than being handled in shared core code.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/core/src/tracing/idleSpan.ts#L93

Potential issue: The `startIdleSpan` function, located in the shared
`packages/core/src/tracing/idleSpan.ts`, now unconditionally calls
`_INTERNAL_ensureBrowserSpanStreaming()`. This function proceeds to install a
browser-specific span streaming integration. Although `startIdleSpan` is intended for
browser environments, it remains accessible and exportable from the top-level
`@sentry/core` package. If a server-side SDK or a non-browser environment imports and
executes `startIdleSpan`, it will incorrectly install the browser integration. This
leads to a mismatch, as the browser integration depends on browser-specific APIs and
event handling mechanisms that are not present in a server environment, causing
incorrect behavior.

Did we get this right? 👍 / 👎 to inform future reviews.

_INTERNAL_ensureBrowserSpanStreaming(client);
Comment thread
cursor[bot] marked this conversation as resolved.

// Activities store a list of active spans
const activities = new Map<string, boolean>();

Expand All @@ -115,7 +119,6 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
trimIdleSpanEndTimestamp = true,
} = options;

const client = getClient();
const scope = getCurrentScope();

if (!client || !hasSpansEnabled()) {
Expand All @@ -131,7 +134,10 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
}

const previousActiveSpan = getActiveSpan();
const span = _startIdleSpan(startSpanOptions);

const span = startInactiveSpan(startSpanOptions);
_setSpanForScope(getCurrentScope(), span);
DEBUG_BUILD && debug.log('[Tracing] Started span is an idle span');

// We patch span.end to ensure we can run some things before the span is ended
// eslint-disable-next-line @typescript-eslint/unbound-method
Expand Down Expand Up @@ -413,13 +419,3 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti

return span;
}

function _startIdleSpan(options: StartSpanOptions): Span {
const span = startInactiveSpan(options);

_setSpanForScope(getCurrentScope(), span);

DEBUG_BUILD && debug.log('[Tracing] Started span is an idle span');

return span;
}
1 change: 0 additions & 1 deletion packages/core/test/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { spanStreamingIntegration as plainSpanStreamingIntegration } from '../src/integrations/spanStreaming';
import * as serverEntry from '../src/server';
import * as browserSpanApi from '../src/tracing/browserSpanApi';
import { startIdleSpan as plainStartIdleSpan } from '../src/tracing/idleSpan';

Check failure on line 8 in packages/core/test/exports.test.ts

View workflow job for this annotation

GitHub Actions / Lint

eslint(no-unused-vars)

Identifier 'plainStartIdleSpan' is imported but never used.
import {
startInactiveSpan as plainStartInactiveSpan,
startSpan as plainStartSpan,
Expand All @@ -21,7 +21,6 @@
['startSpan', plainStartSpan, browserSpanApi.startSpan],
['startInactiveSpan', plainStartInactiveSpan, browserSpanApi.startInactiveSpan],
['startSpanManual', plainStartSpanManual, browserSpanApi.startSpanManual],
['startIdleSpan', plainStartIdleSpan, browserSpanApi.startIdleSpan],
['spanStreamingIntegration', plainSpanStreamingIntegration, browserSpanStreamingIntegration],
] as const;

Expand Down
Loading