Skip to content

feat(v8/vue): Remove all deprecated exports from vue #10533

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
Feb 16, 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: 1 addition & 7 deletions packages/vue/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
export * from '@sentry/browser';

export { init } from './sdk';
// eslint-disable-next-line deprecation/deprecation
export { vueRouterInstrumentation } from './router';
export { browserTracingIntegration } from './browserTracingIntegration';
export { attachErrorHandler } from './errorhandler';
export { createTracingMixins } from './tracing';
export {
vueIntegration,
// eslint-disable-next-line deprecation/deprecation
VueIntegration,
} from './integration';
export { vueIntegration } from './integration';
48 changes: 20 additions & 28 deletions packages/vue/src/integration.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { convertIntegrationFnToClass, defineIntegration, hasTracingEnabled } from '@sentry/core';
import type { Client, Integration, IntegrationClass, IntegrationFn } from '@sentry/types';
import { defineIntegration, hasTracingEnabled } from '@sentry/core';
import type { Client, IntegrationFn } from '@sentry/types';
import { GLOBAL_OBJ, arrayify, consoleSandbox } from '@sentry/utils';

import { DEFAULT_HOOKS } from './constants';
import { DEBUG_BUILD } from './debug-build';
import { attachErrorHandler } from './errorhandler';
import { createTracingMixins } from './tracing';
import type { Options, Vue, VueOptions } from './types';
Expand Down Expand Up @@ -33,17 +34,6 @@ const _vueIntegration = ((integrationOptions: Partial<VueOptions> = {}) => {

export const vueIntegration = defineIntegration(_vueIntegration);

/**
* Initialize Vue error & performance tracking.
*
* @deprecated Use `vueIntegration()` instead.
*/
// eslint-disable-next-line deprecation/deprecation
export const VueIntegration = convertIntegrationFnToClass(
INTEGRATION_NAME,
vueIntegration,
) as IntegrationClass<Integration>;

function _setupIntegration(client: Client, integrationOptions: Partial<VueOptions>): void {
const options: Options = { ...DEFAULT_CONFIG, ...client.getOptions(), ...integrationOptions };
if (!options.Vue && !options.app) {
Expand All @@ -67,23 +57,25 @@ Update your \`Sentry.init\` call with an appropriate config option:
}

const vueInit = (app: Vue, options: Options): void => {
// Check app is not mounted yet - should be mounted _after_ init()!
// This is _somewhat_ private, but in the case that this doesn't exist we simply ignore it
// See: https://github.com/vuejs/core/blob/eb2a83283caa9de0a45881d860a3cbd9d0bdd279/packages/runtime-core/src/component.ts#L394
const appWithInstance = app as Vue & {
_instance?: {
isMounted?: boolean;
if (DEBUG_BUILD) {
// Check app is not mounted yet - should be mounted _after_ init()!
// This is _somewhat_ private, but in the case that this doesn't exist we simply ignore it
// See: https://github.com/vuejs/core/blob/eb2a83283caa9de0a45881d860a3cbd9d0bdd279/packages/runtime-core/src/component.ts#L394
const appWithInstance = app as Vue & {
_instance?: {
isMounted?: boolean;
};
};
};

const isMounted = appWithInstance._instance && appWithInstance._instance.isMounted;
if (isMounted === true) {
consoleSandbox(() => {
// eslint-disable-next-line no-console
console.warn(
'[@sentry/vue]: Misconfigured SDK. Vue app is already mounted. Make sure to call `app.mount()` after `Sentry.init()`.',
);
});
const isMounted = appWithInstance._instance && appWithInstance._instance.isMounted;
if (isMounted === true) {
consoleSandbox(() => {
// eslint-disable-next-line no-console
console.warn(
'[@sentry/vue]: Misconfigured SDK. Vue app is already mounted. Make sure to call `app.mount()` after `Sentry.init()`.',
);
});
}
}

attachErrorHandler(app, options);
Expand Down
111 changes: 37 additions & 74 deletions packages/vue/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
import { WINDOW, captureException } from '@sentry/browser';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, spanToJSON } from '@sentry/core';
import type { SpanAttributes, Transaction, TransactionContext, TransactionSource } from '@sentry/types';

import { getActiveTransaction } from './tracing';

interface VueRouterInstrumationOptions {
/**
* What to use for route labels.
* By default, we use route.name (if set) and else the path.
*
* Default: 'name'
*/
routeLabel: 'name' | 'path';
}

export type VueRouterInstrumentation = <T extends Transaction>(
startTransaction: (context: TransactionContext) => T | undefined,
startTransactionOnPageLoad?: boolean,
startTransactionOnLocationChange?: boolean,
) => void;
import { captureException } from '@sentry/browser';
import {
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
getActiveSpan,
getRootSpan,
spanToJSON,
} from '@sentry/core';
import type { Span, SpanAttributes, TransactionContext, TransactionSource } from '@sentry/types';

// The following type is an intersection of the Route type from VueRouter v2, v3, and v4.
// This is not great, but kinda necessary to make it work with all versions at the same time.
Expand All @@ -43,57 +31,18 @@ interface VueRouter {
beforeEach: (fn: (to: Route, from: Route, next?: () => void) => void) => void;
}

/**
* Creates routing instrumentation for Vue Router v2, v3 and v4
*
* You can optionally pass in an options object with the available option:
* * `routeLabel`: Set this to `route` to opt-out of using `route.name` for transaction names.
*
* @param router The Vue Router instance that is used
*
* @deprecated Use `browserTracingIntegration()` from `@sentry/vue` instead - this includes the vue router instrumentation.
*/
export function vueRouterInstrumentation(
router: VueRouter,
options: Partial<VueRouterInstrumationOptions> = {},
): VueRouterInstrumentation {
return (
startTransaction: (context: TransactionContext) => Transaction | undefined,
startTransactionOnPageLoad: boolean = true,
startTransactionOnLocationChange: boolean = true,
) => {
// We have to start the pageload transaction as early as possible (before the router's `beforeEach` hook
// is called) to not miss child spans of the pageload.
// We check that window & window.location exists in order to not run this code in SSR environments.
if (startTransactionOnPageLoad && WINDOW && WINDOW.location) {
startTransaction({
name: WINDOW.location.pathname,
op: 'pageload',
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.vue',
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
},
});
}

instrumentVueRouter(
router,
{
routeLabel: options.routeLabel || 'name',
instrumentNavigation: startTransactionOnLocationChange,
instrumentPageLoad: startTransactionOnPageLoad,
},
startTransaction,
);
};
}

/**
* Instrument the Vue router to create navigation spans.
*/
export function instrumentVueRouter(
router: VueRouter,
options: {
/**
* What to use for route labels.
* By default, we use route.name (if set) and else the path.
*
* Default: 'name'
*/
routeLabel: 'name' | 'path';
instrumentPageLoad: boolean;
instrumentNavigation: boolean;
Expand Down Expand Up @@ -139,17 +88,16 @@ export function instrumentVueRouter(
}

if (options.instrumentPageLoad && isPageLoadNavigation) {
// eslint-disable-next-line deprecation/deprecation
const pageloadTransaction = getActiveTransaction();
if (pageloadTransaction) {
const existingAttributes = spanToJSON(pageloadTransaction).data || {};
const activeRootSpan = getActiveRootSpan();
if (activeRootSpan) {
const existingAttributes = spanToJSON(activeRootSpan).data || {};
if (existingAttributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] !== 'custom') {
pageloadTransaction.updateName(transactionName);
pageloadTransaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, transactionSource);
activeRootSpan.updateName(transactionName);
activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, transactionSource);
}
// Set router attributes on the existing pageload transaction
// This will the origin, and add params & query attributes
pageloadTransaction.setAttributes({
// This will override the origin, and add params & query attributes
activeRootSpan.setAttributes({
...attributes,
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.vue',
});
Expand All @@ -158,6 +106,7 @@ export function instrumentVueRouter(

if (options.instrumentNavigation && !isPageLoadNavigation) {
attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] = transactionSource;
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.navigation.vue';
startNavigationSpanFn({
name: transactionName,
op: 'navigation',
Expand All @@ -173,3 +122,17 @@ export function instrumentVueRouter(
}
});
}

function getActiveRootSpan(): Span | undefined {
const span = getActiveSpan();
const rootSpan = span ? getRootSpan(span) : undefined;

if (!rootSpan) {
return undefined;
}

const op = spanToJSON(rootSpan).op;

// Only use this root span if it is a pageload or navigation span
return op === 'navigation' || op === 'pageload' ? rootSpan : undefined;
}
14 changes: 2 additions & 12 deletions packages/vue/src/tracing.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getActiveSpan, getCurrentScope, startInactiveSpan } from '@sentry/browser';
import type { Span, Transaction } from '@sentry/types';
import { getActiveSpan, startInactiveSpan } from '@sentry/browser';
import type { Span } from '@sentry/types';
import { logger, timestampInSeconds } from '@sentry/utils';

import { DEFAULT_HOOKS } from './constants';
Expand Down Expand Up @@ -32,16 +32,6 @@ const HOOKS: { [key in Operation]: Hook[] } = {
update: ['beforeUpdate', 'updated'],
};

/**
* Grabs active transaction off scope.
*
* @deprecated You should not rely on the transaction, but just use `startSpan()` APIs instead.
*/
export function getActiveTransaction(): Transaction | undefined {
// eslint-disable-next-line deprecation/deprecation
return getCurrentScope().getTransaction();
}

/** Finish top-level span and activity with a debounce configured using `timeout` option */
function finishRootSpan(vm: VueSentry, timestamp: number, timeout: number): void {
if (vm.$_sentryRootSpanTimer) {
Expand Down
Loading