Skip to content
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

feat(node)!: Remove fine grained registerEsmLoaderHooks option and addOpenTelemetryInstrumentation() #14606

Merged
merged 14 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
10 changes: 6 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
branches:
- develop
- master
- v9
- v8
- release/**
pull_request:
merge_group:
Expand Down Expand Up @@ -105,7 +107,7 @@ jobs:
outputs:
commit_label: '${{ env.COMMIT_SHA }}: ${{ env.COMMIT_MESSAGE }}'
# Note: These next three have to be checked as strings ('true'/'false')!
is_develop: ${{ github.ref == 'refs/heads/develop' }}
is_base_branch: ${{ github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/v9' || github.ref == 'refs/heads/v8'}}
is_release: ${{ startsWith(github.ref, 'refs/heads/release/') }}
changed_profiling_node: ${{ steps.changed.outputs.profiling_node == 'true' }}
changed_ci: ${{ steps.changed.outputs.workflow == 'true' }}
Expand All @@ -126,7 +128,7 @@ jobs:
timeout-minutes: 15
if: |
needs.job_get_metadata.outputs.changed_any_code == 'true' ||
needs.job_get_metadata.outputs.is_develop == 'true' ||
needs.job_get_metadata.outputs.is_base_branch == 'true' ||
needs.job_get_metadata.outputs.is_release == 'true' ||
(needs.job_get_metadata.outputs.is_gitflow_sync == 'false' && needs.job_get_metadata.outputs.has_gitflow_label == 'false')
steps:
Expand Down Expand Up @@ -171,7 +173,7 @@ jobs:
key: nx-Linux-${{ github.ref }}-${{ env.HEAD_COMMIT || github.sha }}
# On develop branch, we want to _store_ the cache (so it can be used by other branches), but never _restore_ from it
restore-keys:
${{needs.job_get_metadata.outputs.is_develop == 'false' && env.NX_CACHE_RESTORE_KEYS || 'nx-never-restore'}}
${{needs.job_get_metadata.outputs.is_base_branch == 'false' && env.NX_CACHE_RESTORE_KEYS || 'nx-never-restore'}}

- name: Build packages
# Set the CODECOV_TOKEN for Bundle Analysis
Expand Down Expand Up @@ -219,7 +221,7 @@ jobs:
timeout-minutes: 15
runs-on: ubuntu-20.04
if:
github.event_name == 'pull_request' || needs.job_get_metadata.outputs.is_develop == 'true' ||
github.event_name == 'pull_request' || needs.job_get_metadata.outputs.is_base_branch == 'true' ||
needs.job_get_metadata.outputs.is_release == 'true'
steps:
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/enforce-license-compliance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ name: "CI: Enforce License Compliance"

on:
push:
branches: [master, develop, release/*]
branches:
- develop
- master
- v9
- v8
- release/**
pull_request:
branches: [master, develop]
branches:
- develop
- master
- v9
- v8

jobs:
enforce-license-compliance:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
"@trpc/react-query": "^11.0.0-rc.446",
"@trpc/server": "^11.0.0-rc.446",
"geist": "^1.3.0",
"next": "^14.2.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"next": "14.2.4",
"react": "18.3.1",
"react-dom": "18.3.1",
"server-only": "^0.0.1",
"superjson": "^2.2.1",
"zod": "^3.23.3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'server-only';

import { createHydrationHelpers } from '@trpc/react-query/rsc';
import { headers } from 'next/headers';
import { cache } from 'react';

import { type AppRouter, createCaller } from '~/server/api/root';
import { createTRPCContext } from '~/server/api/trpc';
Expand All @@ -12,16 +11,16 @@ import { createQueryClient } from './query-client';
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(() => {
const createContext = () => {
const heads = new Headers(headers());
heads.set('x-trpc-source', 'rsc');

return createTRPCContext({
headers: heads,
});
});
};

const getQueryClient = cache(createQueryClient);
const getQueryClient = createQueryClient;
const caller = createCaller(createContext);

export const { trpc: api, HydrateClient } = createHydrationHelpers<AppRouter>(caller, getQueryClient);
22 changes: 22 additions & 0 deletions docs/migration/draft-v9-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,28 @@
});
```

## `@sentry/nuxt` and `@sentry/vue`

- When component tracking is enabled, "update" spans are no longer created by default.
Add an `"update"` item to the `tracingOptions.hooks` option via the `vueIntegration()` to restore this behavior.

```ts
Sentry.init({
integrations: [
Sentry.vueIntegration({
tracingOptions: {
trackComponents: true,
hooks: [
'mount',
'update', // <--
'unmount',
],
},
}),
],
});
```

## `@sentry/astro`

- Deprecated passing `dsn`, `release`, `environment`, `sampleRate`, `tracesSampleRate`, `replaysSessionSampleRate` to the integration. Use the runtime-specific `Sentry.init()` calls for passing these options instead.
Expand Down
2 changes: 0 additions & 2 deletions packages/astro/src/index.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export {
addEventProcessor,
addIntegration,
// eslint-disable-next-line deprecation/deprecation
addOpenTelemetryInstrumentation,
// eslint-disable-next-line deprecation/deprecation
addRequestDataToEvent,
amqplibIntegration,
anrIntegration,
Expand Down
2 changes: 0 additions & 2 deletions packages/aws-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ export {
spanToTraceHeader,
spanToBaggageHeader,
trpcMiddleware,
// eslint-disable-next-line deprecation/deprecation
addOpenTelemetryInstrumentation,
zodErrorsIntegration,
profiler,
amqplibIntegration,
Expand Down
2 changes: 0 additions & 2 deletions packages/bun/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ export {
spanToTraceHeader,
spanToBaggageHeader,
trpcMiddleware,
// eslint-disable-next-line deprecation/deprecation
addOpenTelemetryInstrumentation,
zodErrorsIntegration,
profiler,
amqplibIntegration,
Expand Down
2 changes: 0 additions & 2 deletions packages/google-cloud-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ export {
spanToTraceHeader,
spanToBaggageHeader,
trpcMiddleware,
// eslint-disable-next-line deprecation/deprecation
addOpenTelemetryInstrumentation,
zodErrorsIntegration,
profiler,
amqplibIntegration,
Expand Down
8 changes: 0 additions & 8 deletions packages/nextjs/src/common/captureRequestError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,3 @@ export function captureRequestError(error: unknown, request: RequestInfo, errorC
});
});
}

/**
* Reports errors passed to the the Next.js `onRequestError` instrumentation hook.
*
* @deprecated Use `captureRequestError` instead.
*/
// TODO(v9): Remove this export
export const experimental_captureRequestError = captureRequestError;
3 changes: 1 addition & 2 deletions packages/nextjs/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ export { wrapMiddlewareWithSentry } from './wrapMiddlewareWithSentry';
export { wrapPageComponentWithSentry } from './pages-router-instrumentation/wrapPageComponentWithSentry';
export { wrapGenerationFunctionWithSentry } from './wrapGenerationFunctionWithSentry';
export { withServerActionInstrumentation } from './withServerActionInstrumentation';
// eslint-disable-next-line deprecation/deprecation
export { experimental_captureRequestError, captureRequestError } from './captureRequestError';
export { captureRequestError } from './captureRequestError';
3 changes: 1 addition & 2 deletions packages/nextjs/src/index.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,4 @@ export declare function wrapApiHandlerWithSentryVercelCrons<F extends (...args:
*/
export declare function wrapPageComponentWithSentry<C>(WrappingTarget: C): C;

// eslint-disable-next-line deprecation/deprecation
export { experimental_captureRequestError, captureRequestError } from './common/captureRequestError';
export { captureRequestError } from './common/captureRequestError';
2 changes: 0 additions & 2 deletions packages/node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ export type { NodeOptions } from './types';
export { addRequestDataToEvent, DEFAULT_USER_INCLUDES, extractRequestData } from '@sentry/core';

export {
// eslint-disable-next-line deprecation/deprecation
addOpenTelemetryInstrumentation,
// These are custom variants that need to be used instead of the core one
// As they have slightly different implementations
continueTrace,
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ function _init(
}

if (!isCjs() && options.registerEsmLoaderHooks !== false) {
maybeInitializeEsmLoader(options.registerEsmLoaderHooks === true ? undefined : options.registerEsmLoaderHooks);
maybeInitializeEsmLoader();
}

setOpenTelemetryContextAsyncContextStrategy();
Expand Down
34 changes: 7 additions & 27 deletions packages/node/src/sdk/initOtel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { SentryPropagator, SentrySampler, SentrySpanProcessor } from '@sentry/op
import { createAddHookMessageChannel } from 'import-in-the-middle';
import { getOpenTelemetryInstrumentationToPreload } from '../integrations/tracing';
import { SentryContextManager } from '../otel/contextManager';
import type { EsmLoaderHookOptions } from '../types';
import { isCjs } from '../utils/commonjs';
import type { NodeClient } from './client';

Expand All @@ -30,30 +29,8 @@ export function initOpenTelemetry(client: NodeClient): void {
client.traceProvider = provider;
}

type ImportInTheMiddleInitData = Pick<EsmLoaderHookOptions, 'include' | 'exclude'> & {
addHookMessagePort?: unknown;
};

interface RegisterOptions {
data?: ImportInTheMiddleInitData;
transferList?: unknown[];
}

function getRegisterOptions(esmHookConfig?: EsmLoaderHookOptions): RegisterOptions {
// TODO(v9): Make onlyIncludeInstrumentedModules: true the default behavior.
if (esmHookConfig?.onlyIncludeInstrumentedModules) {
const { addHookMessagePort } = createAddHookMessageChannel();
// If the user supplied include, we need to use that as a starting point or use an empty array to ensure no modules
// are wrapped if they are not hooked
// eslint-disable-next-line deprecation/deprecation
return { data: { addHookMessagePort, include: esmHookConfig.include || [] }, transferList: [addHookMessagePort] };
}

return { data: esmHookConfig };
}

/** Initialize the ESM loader. */
export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions): void {
export function maybeInitializeEsmLoader(): void {
const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);

// Register hook was added in v20.6.0 and v18.19.0
Expand All @@ -64,8 +41,12 @@ export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions):

if (!GLOBAL_OBJ._sentryEsmLoaderHookRegistered && importMetaUrl) {
try {
const { addHookMessagePort } = createAddHookMessageChannel();
// @ts-expect-error register is available in these versions
moduleModule.register('import-in-the-middle/hook.mjs', importMetaUrl, getRegisterOptions(esmHookConfig));
moduleModule.register('import-in-the-middle/hook.mjs', importMetaUrl, {
data: { addHookMessagePort },
transferList: [addHookMessagePort],
});
GLOBAL_OBJ._sentryEsmLoaderHookRegistered = true;
} catch (error) {
logger.warn('Failed to register ESM hook', error);
Expand All @@ -84,7 +65,6 @@ export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions):
interface NodePreloadOptions {
debug?: boolean;
integrations?: string[];
registerEsmLoaderHooks?: EsmLoaderHookOptions;
}

/**
Expand All @@ -101,7 +81,7 @@ export function preloadOpenTelemetry(options: NodePreloadOptions = {}): void {
}

if (!isCjs()) {
maybeInitializeEsmLoader(options.registerEsmLoaderHooks);
maybeInitializeEsmLoader();
}

// These are all integrations that we need to pre-load to ensure they are set up before any other code runs
Expand Down
52 changes: 1 addition & 51 deletions packages/node/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,6 @@ import type { ClientOptions, Options, SamplingContext, Scope, Span, TracePropaga

import type { NodeTransportOptions } from './transports';

/**
* Note: In the next major version of the Sentry SDK this interface will be removed and the SDK will by default only wrap
* ESM modules that are required to be wrapped by OpenTelemetry Instrumentation.
*/
export interface EsmLoaderHookOptions {
/**
* Provide a list of modules to wrap with `import-in-the-middle`.
*
* @deprecated It is recommended to use `onlyIncludeInstrumentedModules: true` instead of manually defining modules to include and exclude.
*/
include?: Array<string | RegExp>;

/**
* Provide a list of modules to prevent them from being wrapped with `import-in-the-middle`.
*
* @deprecated It is recommended to use `onlyIncludeInstrumentedModules: true` instead of manually defining modules to include and exclude.
*/
exclude?: Array<string | RegExp>;

/**
* When set to `true`, `import-in-the-middle` will only wrap ESM modules that are specifically instrumented by
* OpenTelemetry plugins. This is useful to avoid issues where `import-in-the-middle` is not compatible with some of
* your dependencies.
*
* **Note**: This feature will only work if you `Sentry.init()` the SDK before the instrumented modules are loaded.
* This can be achieved via the Node `--import` CLI flag or by loading your app via async `import()` after calling
* `Sentry.init()`.
*
* Defaults to `false`.
*
* Note: In the next major version of the Sentry SDK this option will be removed and the SDK will by default only wrap
* ESM modules that are required to be wrapped by OpenTelemetry Instrumentation.
*/
// TODO(v9): Make `onlyIncludeInstrumentedModules: true` the default behavior.
onlyIncludeInstrumentedModules?: boolean;
}

export interface BaseNodeOptions {
/**
* List of strings/regex controlling to which outgoing requests
Expand Down Expand Up @@ -138,22 +101,9 @@ export interface BaseNodeOptions {
* with certain libraries. If you run into problems running your app with this enabled,
* please raise an issue in https://github.com/getsentry/sentry-javascript.
*
* You can optionally exclude specific modules or only include specific modules from being instrumented by providing
* an object with `include` or `exclude` properties.
*
* ```js
* registerEsmLoaderHooks: {
* exclude: ['openai'],
* }
* ```
*
* Defaults to `true`.
*
* Note: In the next major version of the SDK, the possibility to provide fine-grained control will be removed from this option.
* This means that it will only be possible to pass `true` or `false`. The default value will continue to be `true`.
*/
// TODO(v9): Only accept true | false | undefined.
registerEsmLoaderHooks?: boolean | EsmLoaderHookOptions;
registerEsmLoaderHooks?: boolean;

/**
* Configures in which interval client reports will be flushed. Defaults to `60_000` (milliseconds).
Expand Down
23 changes: 0 additions & 23 deletions packages/nuxt/src/server/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import type { SentryNuxtServerOptions } from '../common/types';
export function init(options: SentryNuxtServerOptions): Client | undefined {
const sentryOptions = {
...options,
registerEsmLoaderHooks: mergeRegisterEsmLoaderHooks(options),
defaultIntegrations: getNuxtDefaultIntegrations(options),
};

Expand Down Expand Up @@ -92,28 +91,6 @@ function getNuxtDefaultIntegrations(options: NodeOptions): Integration[] {
];
}

/**
* Adds /vue/ to the registerEsmLoaderHooks options and merges it with the old values in the array if one is defined.
* If the registerEsmLoaderHooks option is already a boolean, nothing is changed.
*
* Only exported for Testing purposes.
*/
export function mergeRegisterEsmLoaderHooks(
options: SentryNuxtServerOptions,
): SentryNuxtServerOptions['registerEsmLoaderHooks'] {
if (typeof options.registerEsmLoaderHooks === 'object' && options.registerEsmLoaderHooks !== null) {
return {
// eslint-disable-next-line deprecation/deprecation
exclude: Array.isArray(options.registerEsmLoaderHooks.exclude)
? // eslint-disable-next-line deprecation/deprecation
[...options.registerEsmLoaderHooks.exclude, /vue/]
: // eslint-disable-next-line deprecation/deprecation
options.registerEsmLoaderHooks.exclude ?? [/vue/],
};
}
return options.registerEsmLoaderHooks ?? { exclude: [/vue/] };
}

/**
* Flushes pending Sentry events with a 2-second timeout and in a way that cannot create unhandled promise rejections.
*/
Expand Down
Loading
Loading