No results found

Your search did not match any results.

We suggest you try the following to help find what you're looking for:

  • Check the spelling of your keyword search.
  • Use synonyms for the keyword you typed, for example, try "application" instead of "software."
  • Try one of the popular searches shown below.
  • Start a new search.
Trending Questions

Tracing A Node.js with OCI Application Performance Monitoring and Zipkin

OCI Application Performance Monitoring (APM) provides a comprehensive set of features to monitor applications and diagnose performance issues.

Author: Javier Mugueta


OCI Application Performance Monitoring (APM) provides a comprehensive set of features to monitor applications and diagnose performance issues.

Application Performance Monitoring integrates with open-source tracing system tools (open-source tracers) such as Jaeger and Zipkin and enables you to upload trace data. It also supports context propagation between Application Performance Monitoring agents and open-source tracers.

STEP 1: Configure APM

Go to APM->Administration, click in [Create APM Domain] button and provide the information requested in popup window.

STEP 2: Grab domain details

In the APM domain details you created, get the [Data Upload Endpoint] URL and the auto_generated_public_datakey values, we’ll need them in step 3.

STEP 3: Configure your Node.js app

Follow the steps here to configure Zipkin in your app. Here’s the doc from OCI APM with detailled instructions for the OCI part.

If you want to use an example, use this, as it’s the code we’re going to use for this post. Clone the repo and edit file web/recorder.js according to the instructions below (note the changes we’ll make):

/* eslint-env browser */

                    const {
                      jsonEncoder: {JSON_V2}
                    } = require(' zipkin');
                                    const {HttpLogger} =

Replace the last line with:

const CLSContext = require('zipkin-context-cls');


We continue with:

const debug = 'undefined' !== typeof window

                      ?'debug') !== -1
                      : process.env.DEBUG;

Of course, the BaseURL will not be a localhost, so remove the line below the comment here:

// Send spans to Zipkin asynchronously over HTTP

                    const zipkinBaseUrl = 'http://localhost:9411';
                    // data upload endpoint example is something like

And replace const zipkinBaseUrl = ‘http://localhost:9411;’ with:

const httpLogger = new HttpLogger({

                      endpoint: '<domain data upload endpoint in step 2>/20200101/observations/public-span?dataFormat=zipkin&dataFormatVersion=2&dataKey=<public data key in step 2>',
                      jsonEncoder: JSON_V2

Here we’ll remove this logger and add a tracer. First remove this:

const httpLogger = new HttpLogger({

                      endpoint: `${zipkinBaseUrl}/api/v2/spans`,
                      jsonEncoder: JSON_V2

And add this:

// Setup the tracer

                    const tracer = new Tracer({
                      ctxImpl: new CLSContext('zipkin'), // implicit in-process context
                      recorder: new BatchRecorder({
                        logger: httpLogger
                      }), // batched http recorder
                      localServiceName: 'mytest', // name of this application
                      supportsJoin: false //Span join disable setting

The rest should look like this:

function recorder(serviceName) {

                      return debug ? debugRecorder(serviceName) : new BatchRecorder({logger: httpLogger});
                    function debugRecorder(serviceName) {
                      // This is a hack that lets you see the data sent to Zipkin!
                      const logger = {
                        logSpan: (span) => {
                          const json = JSON_V2.encode(span);
                          console.log(`${serviceName} reporting: ${json}`);
                      const batchRecorder = new BatchRecorder({logger});
                      // This is a hack that lets you see which annotations become which spans
                      return ({
                        record: (rec) => {
                          const {spanId, traceId} = rec.traceId;
                          console.log(`${serviceName} recording: ${traceId}/${spanId} ${rec.annotation.toString()}`);
                    module.exports.recorder = recorder; 

STEP 4: Restart your node app


Go to APM Trace explorer and run a query

Traces can be observed in the list!

That’s all, hope it helps!! 🙂

If you’re curious about the goings-on of Oracle Developers in their natural habitat, come join us on our public Slack channel!

And don’t forget our free tier, where you can try out what we just discussed.