添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

If you’re using a JavaScript stack like PostgreSQL, Express, React, and Node.js (PERN) to deploy a full-stack web application, you might be considering options for monitoring your application.
You’ve already chosen to use PostgreSQL as the database, Express as the web application framework for Node.js, and React as the UI framework, because they all play nicely together —so well that PERN is one of the most common stacks in web development. So, how easy is it to add observability to your full-stack JavaScript app with the open source OpenTelemetry framework? This blog post breaks it down into actionable steps.

OpenTelemetry is a vendor-neutral observability framework that simplifies the collection of telemetry data. You’ll find it useful for monitoring and tracing the performance and behavior of your applications across different environments. With robust support for many programming languages, OpenTelemetry is evolving rapidly to enhance its support. OpenTelemetry generates telemetry data that can help you optimize and debug your JavaScript apps proactively. Also, distributed tracing can help you identify the correct pain points in larger systems.

This blog post guides you through setting up and configuring OpenTelemetry for each stack layer, and shows examples of what you can see using OpenTelemetry and New Relic. You’ll learn how to set up OpenTelemetry for a JavaScript application using a PERN stack, including:

  • Understanding common OpenTelemetry APIs and packages—and their purpose for setting up instrumentation for JavaScript applications.
  • Instrumenting your backend Node.js and Express apps.
  • Instrumenting your frontend React app.
  • Instrumenting your PostgreSQL database.
  • Exporting the collected telemetry data to New Relic without using an OpenTelemetry collector.
  • Before you begin

    Here’s what you’ll need to follow along with all the steps in this blog post:

  • A New Relic ingest license key (Log into your New Relic account or sign up for a free account .)
  • Basic knowledge of OpenTelemetry
  • Understanding APIs and packages to use with OpenTelemetry and JavaScript

    Here’s a brief overview of some common APIs and packages you need to set up instrumentation for JavaScript applications. Each section describes the package and its purpose.

    @opentelemetry/core

    The @opentelemetry/core package provides default implementations of the OpenTelemetry API for traces and metrics. This blog post uses these APIs:

  • W3CTraceContextPropagator: This function, based on the W3C Trace Context specification , propagates SpanContext through trace context format propagation.
  • W3CBaggagePropagator: This function propagates baggage through context format propagation, based on the W3C Baggage specification .
  • CompositePropagator: This function combines multiple propagators into a single propagator.
  • To learn more, see the OpenTelemetry API propagators documentation.

    @opentelemetry/sdk-node

    The @opentelemetry/sdk-node package provides the complete OpenTelemetry SDK for Node.js, including tracing and metrics. You can use this package along with the meta package @opentelemetry/auto-instrumentations-node to set up automatic instrumentation for Node.js.

    @opentelemetry/sdk-trace-web

    The @opentelemetry/sdk-trace-web module provides automated instrumentation and tracing for web applications. It provides an API named WebTracerProvider that automatically creates the traces within the browser.

    OTLPTraceExporter

    The OTLPTraceExporter is a common API provided in the @opentelemetry/exporter-trace-otlp-http and @opentelemetry/exporter-trace-otlp-proto packages for exporting the collected telemetry to a collector or a choice of backend. This blog post shows how to use the New Relic native OTLP Endpoint to export your telemetry data.

    Instrument your backend Node.js and Express apps

    You’ll start by instrumenting your backend Node.js app. OpenTelemetry includes the @opentelemetry/auto-instrumentations-node meta package for easy instrumentation. This package helps instrument the most popular libraries directly from one package.

    The meta package already contains instrumentation for both Express and PostgreSQL, as @opentelemetry/instrumentation-express and @opentelemetry/instrumentation-pg. You’ll just need to enable the configuration to be able to instrument them.

    Step 1: Install the packages.

    First, install all the required packages for Node.js. Copy this command and run it in the root of your Node app:

    const opentelemetry = require("@opentelemetry/sdk-node"); const { getNodeAutoInstrumentations } = require("@opentelemetry/auto-instrumentations-node"); const { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator, } = require("@opentelemetry/core"); const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-proto"); // For troubleshooting, set the log level to DiagLogLevel.DEBUG const { diag, DiagConsoleLogger, DiagLogLevel } = require("@opentelemetry/api"); diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); const COLLECTOR_STRING = "<https://otlp.nr-data.net:4318/v1/traces>"; // The `newRelicExporter` is an instance of OTLPTraceExporter configured to send traces to New Relic's OTLP-compatible backend. // Make sure you have added your New Relic Ingest License to NR_LICENSE env-var const newRelicExporter = new OTLPTraceExporter({ url: COLLECTOR_STRING, headers: { "api-key": `${process.env.NR_LICENSE}`, const sdk = new opentelemetry.NodeSDK({ // The name of the service, configured below, is how you will // identify your app in New Relic serviceName: "node-express-otel", traceExporter: newRelicExporter, // Configure the propagator to enable context propagation between services using the W3C Trace Headers textMapPropagator: new CompositePropagator({ propagators: [new W3CBaggagePropagator(), new W3CTraceContextPropagator()], instrumentations: [ getNodeAutoInstrumentations({ // Enable Instrumentations for PostgreSQL Database "@opentelemetry/instrumentation-pg": { requireParentSpan: true, enhancedDatabaseReporting: true, "@opentelemetry/instrumentation-http": { ignoreIncomingRequestHook(req) { // Ignore routes to avoid the trace capture, e.g. RegEx to ignore the incoming route /api/telemetry const isIgnoredRoute = !!req.url.match( /^(https?:\\/\\/)?([\\da-z\\.-]+)(\\/[\\d|\\w]{2})(\\/api\\/traces)/ return isIgnoredRoute; "@opentelemetry/instrumentation-express": { enabled: true, autoDetectResources: true, // Register the SDK instance as the global OpenTelemetry tracer provider sdk.start();

    Step 4: Review your data in New Relic

    Now that you’ve set up the instrumentation for your Node backend, how does the telemetry data look?

    After you’ve found your Node app in your New Relic account on the APM & Services page, you can view your distributed traces, along with the top five trace groups by trace count.

    In this trace, you can also view details about your database calls, such as the name of the executed queries and the duration of each.

    Select Databases for your Node.js entity to review all the collated database calls and insights like the top 20 database calls.

    Instrument your frontend React app

    For the frontend web application, OpenTelemetry provides a meta package called @opentelemetry/auto-instrumentations-web. Similar to the Node version, this package includes all the necessary plugins to set up instrumentation for aspects of a web application such as document load, user interactions, and HTTP requests.

    Step 1: Install the packages

    Install the required packages for the JavaScript web application, copy this command, and run it in the root of your React app:

    @opentelemetry/sdk-trace-web @opentelemetry/sdk-trace-base @opentelemetry/auto-instrumentations-web @opentelemetry/api @opentelemetry/context-zone @opentelemetry/core @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/instrumentation @opentelemetry/exporter-trace-otlp-http

    Step 2: Configure OpenTelemetry

    After installing all the packages, you’ll set up OpenTelemetry configurations for your React web application.

    Create a file named opentelemetry.js in the src directory of your app (the directory might be different depending on your app structure).

    Copy this code and paste it into the file:

    import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
    import { getWebAutoInstrumentations } from "@opentelemetry/auto-instrumentations-web";
    import { ZoneContextManager } from "@opentelemetry/context-zone";
    import {
      CompositePropagator,
      W3CBaggagePropagator,
      W3CTraceContextPropagator,
    } from "@opentelemetry/core";
    import { Resource } from "@opentelemetry/resources";
    import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
    import { registerInstrumentations } from "@opentelemetry/instrumentation";
    //exporters
    import {
      ConsoleSpanExporter,
      SimpleSpanProcessor,
      BatchSpanProcessor,
    } from "@opentelemetry/sdk-trace-base";
    import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
    const COLLECTOR_STRING = `${import.meta.env.VITE_APP_OTLP_URL}`;
    //console.log(`CollectorString: ${COLLECTOR_STRING}`);
    // The SemanticResourceAttributes is an enum that provides a set of predefined attribute keys for commonly used attributes in OpenTelemetry to maintain consistency across different OpenTelemetry implementations
    const resourceSettings = new Resource({
      [SemanticResourceAttributes.SERVICE_NAME]: "react-tutorials-otel",
      [SemanticResourceAttributes.SERVICE_VERSION]: '0.0.1',
    // The `newRelicExporter` is an instance of OTLPTraceExporter configured to send traces to New Relic's OTPL-compatible backend.
    // Make sure you have added your New Relic Ingest License to VITE_APP_NR_LICENSE env-var of your React App
    const newRelicExporter = new OTLPTraceExporter({
      url: COLLECTOR_STRING,
      headers: {
        "api-key": `${import.meta.env.VITE_APP_NR_LICENSE}`
    const provider = new WebTracerProvider({resource: resourceSettings});
    //Uncomment this to enable debugging using consoleExporter
    //provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
    // The BatchSpanProcessor is responsible for batching and exporting spans to the configured exporter (newRelicExporter in this case).
    provider.addSpanProcessor(
    new BatchSpanProcessor(
      newRelicExporter,
       //Optional BatchSpanProcessor Configurations
          // The maximum queue size. After the size is reached spans are dropped.
          maxQueueSize: 100,
          // The maximum batch size of every export. It must be smaller or equal to maxQueueSize.
          maxExportBatchSize: 50,
          // The interval between two consecutive exports
          scheduledDelayMillis: 500,
          // How long the export can run before it is cancelled
          exportTimeoutMillis: 30000,
    // ZoneContextManager is a context manager implementation based on the Zone.js library. It enables context propagation within the application using zones.
    provider.register({
    contextManager: new ZoneContextManager(),
    // Configure the propagator to enable context propagation between services using the W3C Trace Headers
    propagator: new CompositePropagator({
      propagators: [new W3CBaggagePropagator(), new W3CTraceContextPropagator()],
    const startOtelInstrumentation = () => {
      console.error(`Registering Otel ${new Date().getMilliseconds()}`);
      // Registering instrumentations
      registerInstrumentations({
        instrumentations: [
          getWebAutoInstrumentations({
            "@opentelemetry/instrumentation-xml-http-request": {
              enabled:true,
              ignoreUrls: ["/localhost:8081/sockjs-node"],
              clearTimingResources: true,
              propagateTraceHeaderCorsUrls: [/.+/g]
            "@opentelemetry/instrumentation-document-load": {
              enabled: true
            "@opentelemetry/instrumentation-user-interaction": {
              enabled:true
    export { startOtelInstrumentation };
                  

    Then, import the opentelemetry.js file in the main.jsx or index.jsx or index.js file, depending on your project setup entry file.

    Step 3: Instrument for additional events beyond the click event (Optional)

    In the plugin @opentelemetry/instrumentation-user-interaction, by default only the click event is instrumented. To enable instrumentation for additional events, update the plugin configuration as shown in this example:

    Note for distributed traces:  For the propagateTraceHeaderCorsUrls property under the @opentelemetry/instrumentation-xml-http-request plugin, the regex in the previous code sample will allow all the URLs to be propagated with trace headers. This is useful when you want to capture all the traces from your web app.

    But if the origins for the frontend and backend don’t match, or if you want to capture traces for only certain selected endpoints, you’ll need to specify a regex for the specific URLs. Use this example code snippet to filter out URLs for your distributed traces. In this example, notice that it only allows localhost, 127.0.0.1, and URL patterns similar to https://api.twitter.com/v1/api/analytics.

            "@opentelemetry/instrumentation-xml-http-request": {
              enabled:true,
              ignoreUrls: ["/localhost:8081/sockjs-node"],
              clearTimingResources: true,
              propagateTraceHeaderCorsUrls: [
                /http:\\/\\/127\\.0\\.0\\.1:\\d+\\.*/,
                /http:\\/\\/localhost:\\d+\\.*/,
                // matches URL of pattern for =>  "<https://api.twitter.com/v1/api/analytics>"
                ^(http|https):\\/\\/[a-z0-9-]+(?:\\.[a-z0-9-]+)(.\\w*)+\\/?\\w?\\d?\\/api\\/\\w+\\.*
    import { startOtelInstrumentation } from './opentelemetry';
    // Add this before the initialization of your main App, so it can capture all the traces.
    startOtelInstrumentation();
    ReactDOM.createRoot(document.getElementById('root')).render(
      <BrowserRouter>
        <App />
      </BrowserRouter>,
                  

    Step 5: Deploy and review results in New Relic

    Start your React application by running npm start.
    After you’ve deployed your React application, traces will be generated by the OpenTelemetry instrumentation you added. You can view the traces that were captured, including your HTTP calls, by selecting Distributed tracing:

  • When you select a trace, you can see the entity map. In this example you see that the React app has made one call to the Node app (node-express-otel).
  • In addition, you can see more details about each span. This example shows selecting one of the PostgreSQL database spans.
  • From here, you can see details about this span, such as the query that was executed for this HTTP call.
  • As you’ve learned in this blog post, when setting up OpenTelemetry for full-stack JavaScript applications, you need to consider the right packages for both web apps and Node.js: the @opentelemetry/core package, the @opentelemetry/sdk-node package, the @opentelemetry/sdk-trace-web module, and the OTLPTraceExporter API. OpenTelemetry offers many official npm packages, many of them contributed by the community. Not all packages will be suitable for your needs, and loading unnecessary packages can increase the build size of your apps.

    After you’ve integrated OpenTelemetry instrumentation into your apps, it generates telemetry data that can be really useful for proactively optimizing and debugging your JavaScript apps. Distributed traces can also help you identify the correct pain points in larger systems.

    Next steps

    You can explore OpenTelemetry by using the sample application with the PERN stack provided in this GitHub repository: github.com/newrelic-experimental/pern-js-otel.

    To learn more about what you can do with OpenTelemetry and New Relic see OpenTelemetry for Node.js, and check out OpenTelemetry: an open source data collection standard, a 90-minute self-paced course with New Relic University.

    OpenTelemetry is continuing to evolve rapidly, including adding wider support for the JavaScript ecosystem. Keep up-to-date with the documentation about OpenTelemetry API, SDK, and tools for JavaScript.

    Zameer Fouzan is a Senior Developer Relations Engineer at New Relic with a solid background in full-stack development. He is passionate about web development, Cloud Native, OSS & O11y, and enjoys staying up-to-date with the latest trends in the developer community. Zameer derives deep contentment in sharing his knowledge & assisting fellow developers in maximizing their potential.

    The views expressed on this blog are those of the author and do not necessarily reflect the views of New Relic. Any solutions offered by the author are environment-specific and not part of the commercial solutions or support offered by New Relic. Please join us exclusively at the Explorers Hub (discuss.newrelic.com) for questions and support related to this blog post. This blog may contain links to content on third-party sites. By providing such links, New Relic does not adopt, guarantee, approve or endorse the information, views or products available on such sites.