Skip to content

Latest commit

 

History

History
279 lines (207 loc) · 10.2 KB

File metadata and controls

279 lines (207 loc) · 10.2 KB

On this page you will learn how to manually propagate trace information into and out of your JavaScript application.

Distributed tracing will be set up automatically if:

  • You've Set Up Tracing, or
  • You're using one of the SDKs that include tracing propagation out of the box:
    • @sentry/nextjs
    • @sentry/sveltekit
    • @sentry/remix
    • @sentry/astro

If you are using a different package, and have not enabled tracing, you can manually set up your application for distributed tracing to work.

Enabling Distributed Tracing

<PlatformCategorySection supported={['browser']}>

To enable distributed tracing for your frontend, add browserTracingIntegration to your Sentry.init() options as described in the Automatic Instrumentation docs.

If you want to use distributed tracing but not tracing, set the tracesSampleRate option to 0.

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [Sentry.browserTracingIntegration()],

  // If this is 0, tracing is disabled
  // but distributed tracing is not
  tracesSampleRate: 0,
});

Continuing a Trace Manually

By default, the browserTracingIntegration will automatically continue a trace found in a <meta> tags - see Automatic Trace Propagation for details. If you want to continue a different trace, for example because you cannot propagate the trace through meta tags but through some different mechanism, you can do this as follows:

const client = Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    Sentry.browserTracingIntegration({
      // Disable default pageload instrumentation
      instrumentPageLoad: false,
    }),
  ],
});

// Start the pageload span manually
const sentryTrace = getSentryTraceStringFromSomewhere();
const baggage = getBaggageStringFromSomewhere();

Sentry.startBrowserTracingPageLoadSpan(
  client,
  {
    name: window.location.pathname,
  },
  { sentryTrace, baggage }
);

Enabling Distributed Tracing without browserTracingIntegration

If you don't want to use the browserTracingIntegration integration, you can manually extract and inject tracing data in your application to connect multiple systems. For this, you must:

  • Extract and store incoming tracing information from HTML <meta> tags when loading the page.
  • Inject tracing information to any outgoing requests.

To learn more about distributed tracing, see our Distributed Tracing docs.

Extract Tracing Information From HTML meta Tags

If you have a server that renders your application's HTML (SSR) and is also running a Sentry SDK, you can connect your backend to your backend via tracing.

To do this, have your server render HTML <meta> tags with the Sentry trace information. In your frontend, extract that tracing information when the page is loading and use it to create new transactions connected to that incoming backend trace.

Some Sentry backend SDKs provide a built-in way to inject these <meta> tags into rendered HTML. For example:

Then, on pageload you can do the following:

import { propagationContextFromHeaders } from "@sentry/core"; // Before version 8.40.0, import from "@sentry/utils"
import * as Sentry from "@sentry/browser";

// Read meta tag values
const sentryTrace = document.querySelector("meta[name=sentry-trace]")?.content;
const baggage = document.querySelector("meta[name=baggage]")?.content;

// Generate a propagation context from the meta tags
const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);
Sentry.getCurrentScope().setPropagationContext(propagationContext);

Sentry.startSpan(
  {
    name: `Pageload: ${window.location.pathname}`,
    op: "pageload",
  },
  () => {
    // do something
  }
);

In this example, we create a new root span that is attached to the trace specified in the sentry-trace and baggage HTML <meta> tags.

<PlatformCategorySection supported={['server', 'serverless']}> If you want to use distributed tracing but not tracing, set the tracesSampleRate option to 0.

Sentry.init({
  dsn: "___PUBLIC_DSN___",

  // If this is 0, tracing is disabled
  // but distributed tracing is not
  tracesSampleRate: 0,
});

Manually Extracting and Injecting Distributed Tracing Information

You can also manually extract and inject tracing data into your application. For this, you must:

  • Extract and store incoming tracing information from incoming request headers or similar.
  • Inject tracing information to any outgoing requests.

To learn more about distributed tracing, see our Distributed Tracing docs.

Extracting Incoming Tracing Information

You must extract and store incoming tracing information in memory for later use. Sentry provides the continueTrace() function to help you with this. Incoming tracing information can come from different places:

  • In a web environment, it's sent with HTTP headers, for example, by another Sentry SDK used in your frontend project.
  • In a job queue, it can be retrieved from meta or header variables.
  • You also can pick up tracing information from environment variables.

Here's an example of how to extract and store incoming tracing information using continueTrace():

const http = require("http");

http.createServer((request, response) => {
  const sentryTraceHeaders = request.headers["sentry-trace"];
  const sentryTrace = Array.isArray(sentryTraceHeaders)
    ? sentryTraceHeaders.join(",")
    : sentryTraceHeaders;
  const baggage = request.headers["baggage"];

  Sentry.continueTrace({ sentryTrace, baggage }, () => {
    Sentry.startSpan(
      {,
        name: "my request",
        op: "http.server",
      },
      () => {
        // Your API code...
      }
    );
  });
});

In this example, we create a new transaction that is attached to the trace specified in the sentry-trace and baggage headers.

Inject Tracing Information into Outgoing Requests

For distributed tracing to work, the two headers that you extracted and stored in the active root span, sentry-trace and baggage, must be added to outgoing HTTP requests.

Here's an example of how to collect and inject this tracing information to outgoing requests:

const activeSpan = Sentry.getActiveSpan();
const rootSpan = activeSpan ? Sentry.getRootSpan(activeSpan) : undefined;

// Create `sentry-trace` header
const sentryTraceHeader = rootSpan
  ? Sentry.spanToTraceHeader(rootSpan)
  : undefined;

// Create `baggage` header
const sentryBaggageHeader = rootSpan
  ? Sentry.spanToBaggageHeader(rootSpan)
  : undefined;

// Make outgoing request
fetch("https://example.com", {
  method: "GET",
  headers: {
    baggage: sentryBaggageHeader,
    "sentry-trace": sentryTraceHeader,
  },
}).then((response) => {
  // ...
});

In this example, tracing information is propagated to the project running at https://example.com. If this project uses a Sentry SDK, it will extract and save the tracing information for later use.

The two services are now connected with your custom distributed tracing implementation.

<PlatformCategorySection notSupported={['browser']}>

Injecting Tracing Information into HTML

If you're server-side rendering HTML and you use a Sentry SDK in your browser application, you can connect the backend and frontend traces by injecting your server's tracing information as <meta> tags into the HTML that's initially served to the browser. When the frontend SDK is initialized, it will automatically pick up the tracing information from the <meta> tags and continue the trace. Note, that your browser SDK needs to register browserTracingIntegration for this to work.

The easiest and recommended way to do this is to use the Sentry.getTraceMetaTags():

function renderHtml() {
  return `
    <html>
      <head>
        ${Sentry.getTraceMetaTags()}
      </head>
      <body>
        <!-- Your HTML content -->
      </body>
    </html>
  `;
}

Alternatively, if you need more control over how meta tags are generated, you can use Sentry.getTraceData() to get only the meta tag values and generate the meta tags yourself:

function renderHtml() {
  const metaTagValues = Sentry.getTraceData();

  return `
    <html>
      <head>
        <meta name="sentry-trace" content="${metaTagValues["sentry-trace"]}">
        <meta name="baggage" content="${metaTagValues.baggage}">
      </head>
      <body>
        <!-- Your HTML content -->
      </body>
    </html>
  `;
}

Starting a New Trace

Available since SDK version 8.5.0.

In case the SDK's default behavior for the trace duration does not fit your needs, you can manually start a new trace that will no longer be connected to the current (distributed) trace. This means that spans or errors collected by the SDK during this new trace will not be connected to spans or errors collected before or after this new trace.

To start a new trace that remains valid throughout the duration of a callback, use startNewTrace:

myButton.addEventListener("click", async () => {
  Sentry.startNewTrace(() => {
    Sentry.startSpan(
      { op: "ui.interaction.click", name: "fetch click" },
      async () => {
        await fetch("http://example.com");
      }
    );
  });
});

Once the callback ends, the SDK will continue the previous trace (if available).

Verification

If you make outgoing requests from your project to other services, check if the headers sentry-trace and baggage are present in the request. If so, distributed tracing is working.