Vue Router Integration

The Vue Tracing Integration allows you to track rendering performance during an initial application load.

Sentry uses mixins functionality to provide access to a Vue component during its life cycle stages. When Sentry encounters a component named root, which is a top-level Vue instance (as in new Vue({})), we use our BrowserTracing integration, and create a new span named Vue Application Render. Once the Vue Application Render span has been created, it will wait until all of its child components render before marking the span as finished.

The described instrumentation functionality will give you very high-level information about the rendering performance of the Vue instance. However, the integration can also provide more fine-grained details about what actually happened during a specific activity. To do that, you need to specify which components to track and what hooks to listen to (you can find a list of all available hooks here). You can also turn on tracking for all the components. However, it may be rather noisy if your app consists of hundreds of components. We encourage being more specific. If you don't provide hooks, Sentry will track a component's mount and update hooks.

Note that when specifying hooks we use the simple verb rather than before and -ed pairs. For example, destroy is correct. beforeDestroy and destroyed are incorrect.

To set up the Vue Tracing Integration, you will first need to configure the BrowserTracing integration itself. For details on how to do this, check out our Performance documentation. Once you've configured the BrowserTracing integration, move on to configuring the Vue integration itself. Sentry built the new tracing capabilities into the original Vue error handler integrations, so there is no need to add any new packages. You only need to provide an appropriate configuration.

The most basic configuration for tracing your Vue app, which would track only the top-level component, looks like this:

Copied
import Vue from "vue";
import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";

Sentry.init({
  // ...
  integrations: [new Integrations.BrowserTracing()],

  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});

If you want to track child components, and see more details about the rendering process, configure the integration to track them all:

Copied
Sentry.init({
  Vue,
  trackComponents: true,
});

Or, you can choose more granularity:

Copied
Sentry.init({
  Vue,
  integrations: [new Integrations.BrowserTracing()],
  trackComponents: [
    "App",
    "RwvHeader",
    "RwvFooter",
    "RwvArticleList",
    "Pagination",
  ],
});

If you want to know if some components are, for example, removed during the initial page load, add a destroy hook to the default:

Copied
Sentry.init({
  Vue,
  integrations: [new Integrations.BrowserTracing()],
  trackComponents: [
    "App",
    "RwvHeader",
    "RwvFooter",
    "RwvArticleList",
    "Pagination",
  ],
  hooks: ["mount", "update", "destroy"],
});

You can specify how long a top-level activity should wait for the last component to render. Every new rendering cycle is debouncing the timeout, and it starts counting from the beginning. Once the timeout is reached, tracking is completed, and all the information is sent to Sentry.

Copied
Sentry.init({
  Vue,
  integrations: [new Integrations.BrowserTracing()],
  trackComponents: true,
  timeout: 4000,
});

Configuration

Copied
tracingOptions: {
  /**
   * Decides whether to track components by hooking into its lifecycle methods.
   * Can be either set to `boolean` to enable/disable tracking for all of them.
   * Or to an array of specific component names (case-sensitive).
   * Default: false
   */
  trackComponents: boolean | string[];
  /**
   * How long to wait (in ms) until the tracked root activity is marked as finished and sent to Sentry
   * Default: 2000
   */
  timeout: number;
  /**
   * List of hooks to keep track of during component lifecycle.
   * Available hooks: 'activate' | 'create' | 'destroy' | 'mount' | 'unmount' | 'update'
   * Based on https://vuejs.org/v2/api/#Options-Lifecycle-Hooks
   */
  hooks: string[];
}

Using Vue Router

If you are using Vue Router, you can use our provided integration for better transaction names. Here is a full example how to use it:

Copied
import Vue from "vue";
import App from "./App";
import * as Sentry from "@sentry/vue";
import { Integrations } from "@sentry/tracing";
import Router from "vue-router";
import HelloWorld from "@/components/HelloWorld";

Vue.use(Router);

const Foo = { template: "<div>foo</div>" };
const Bar = { template: "<div>bar</div>" };

const router = new Router({
  routes: [
    {
      path: "/",
      name: "HelloWorld",
      component: HelloWorld,
    },
    { path: "/foo/:id", component: Foo },
    { path: "/bar", component: Bar },
  ],
});

Vue.config.productionTip = false;

Sentry.init({
  Vue: Vue,
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  tracesSampleRate: 1.0,
  integrations: [
    new Integrations.BrowserTracing({
      routingInstrumentation: Sentry.vueRouterInstrumentation(router),
    }),
  ],
  trackComponents: true,
});

/* eslint-disable no-new */
new Vue({
  el: "#app",
  router,
  components: { App },
  template: "<App/>",
});