• Home
  • Setup and configuration
  • Set up Dynatrace on cloud platforms
  • Google Cloud Platform
  • Monitor Google Cloud Functions
  • Integrate OpenTelemetry Node.js on Google Cloud Functions

Integrate OpenTelemetry Node.js on Google Cloud Functions

The @dynatrace/opentelemetry-gcf module provides APIs for tracing Node.js on Google Cloud Functions (GCF).

So far, only HTTP triggers are supported.

Installation

To set up OpenTelemetry Node.js integration on Google Cloud Functions, run the command below.

bash
npm install --save @dynatrace/opentelemetry-gcf

Usage

To export traces to Dynatrace

  1. Select one of the two ways below to initialize tracing.
    • NodeTracerProvider used to initialize tracing is more lightweight than NodeSDK
    • NodeSDK typically is used if you're interested in additional OpenTelemetry signals such as metrics
Using `NodeTracerProvider` - recommended

Example:

typescript
import { Resource } from "@opentelemetry/resources"; import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node"; import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions"; import { DtSpanExporter, DtSpanProcessor, DtTextMapPropagator, DtSampler } from "@dynatrace/opentelemetry-core"; const provider = new NodeTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: "My Service", }), sampler: new DtSampler(), // ...other configurations }); const exporter = new DtSpanExporter(); const processor = new DtSpanProcessor(exporter); provider.addSpanProcessor(processor); provider.register({ propagator: new DtTextMapPropagator(), // ...other configurations });
Using `NodeSDK`

Example:

typescript
import { Resource } from "@opentelemetry/resources"; import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions"; import { NodeSDK } from "@opentelemetry/sdk-node"; import { DtSpanExporter, DtSpanProcessor, DtTextMapPropagator, DtSampler } from "@dynatrace/opentelemetry-core"; const sdk = new NodeSDK({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: "My Service" }), sampler: new DtSampler(), spanProcessor: new DtSpanProcessor(new DtSpanExporter()), textMapPropagator: new DtTextMapPropagator(), // ...other configurations }); sdk.start().then(() => { // Resources have been detected and SDK is started });
  1. Start the root Google Cloud Function server span, using one of the two general patterns in OpenTelemetry below:
Start the span and make it active immediately with `startActiveHttpSpan()` - recommended

Example:

javascript
const { startActiveHttpSpan, endHttpSpanAndFlush } = require('@dynatrace/opentelemetry-gcf'); async function handler(req, res) { await startActiveHttpSpan(req, async (span) => { let error; try { // do something } catch (e) { error = e; } // status should be set before span ends res.status(error != null ? 500 : 200); /** * Span must be ended and flushed before handler sends response. * This limitiation comes from GCF, for details see: * https://cloud.google.com/functions/docs/concepts/nodejs-runtime#signal-termination */ await endHttpSpanAndFlush(span, res, error); res.send("hello world"); }); }
Start the span and make it active later with `startHttpSpan()`

Example:

javascript
const { context, trace, ROOT_CONTEXT } = require('@opentelemetry/api'); const { startHttpSpan, endHttpSpanAndFlush } = require('@dynatrace/opentelemetry-gcf'); async function handler(req, res) { const span = await startHttpSpan(req); let error; await context.with(trace.setSpan(ROOT_CONTEXT, span), async () => { try { // do something } catch (e) { error = e; } }); // status should be set before span ends res.status(error != null ? 500 : 200); /** * Span must be ended and flushed before handler sends response. * This limitiation comes from GCF, for details see: * https://cloud.google.com/functions/docs/concepts/nodejs-runtime#signal-termination */ await endHttpSpanAndFlush(span, res, error); res.send("hello world"); }

Cold start

Starting a Google Cloud Function span during cold starts produces additional HTTP requests to fetch metadata from your Google Cloud Platform environment and set the attributes required for Dynatrace to process the spans.

Span flush

You need to flush the spans before a function's response is sent to the client. For details on this limitation, see Signalling function termination.

You can use endHttpSpan() and flushSpans() separately instead of endHttpSpanAndFlush() when needed.

Note: Flushing spans in the function's code results in longer execution time, as this operation becomes part of the function's execution logic. Experiments have shown that, usually, not flushing spans explicitly results in correctly exported spans as well (enabled via continuous background export). However, since a Google Cloud Function could be suspended immediately after sending its response, it might result in span loss.

Caveats

You need to pay special attention to cases like unhandled exceptions or function timeouts. If not handled properly, they could lead to a non-ended, and therefore non-exported, span.

Dynatrace overhead

  • Because span export and metadata fetch take some time during cold starts, they increase the duration of the function, and subsequently increase costs.
  • Pay attention to infrequently invoked functions (usually with cold starts), which might require more time for the TCP handshake during the span export.
  • Any network problem between the exporter and Dynatrace backend might also lead to unexpected high overhead.
Related topics
  • Google Cloud Platform monitoring

    Monitor Google Cloud Platform with Dynatrace.

  • Google Cloud monitoring