Skip to content
An implementation of Opentracing API for honeycomb.io
Branch: master
Clone or download
Latest commit 73c636f Apr 8, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github
examples
src Prevent sending more than once (#17) Mar 12, 2019
test
types
.gitignore
.npmignore
README.md
package.json
tsconfig.json

README.md

@zeit/tracing-js

npm install size codecov

A partial implementation of the OpenTracing JavaScript API for honeycomb.io backend.

homecomb-ui

Getting Started

The minimum code you need to get started is the following:

import { Tracer } from '@zeit/tracing-js';
const tracer = new Tracer({ serviceName }, { writeKey, dataset });
const span = tracer.startSpan(spanName);
functionToTrace();
span.finish();

Connecting Traces Across Multiple Services

You can set a parent trace, even if you don't have a reference to the Span object.

Instead, you can create a new SpanContext.

You'll need the traceId and parentSpanId (typically found in req.headers).

const spanContext = new SpanContext(traceId, parentSpanId);
const childSpan = tracer.startSpan('child', { childOf: spanContext });
// ...do work here, call function, etc
childSpan.finish();

But a better solution is to use the setupHttpTracing helper function like the following:

async function handler(req: IncomingMessage, res: ServerResponse) {
  const spanContext = setupHttpTracing({ tracer, req, res });
  const fetch = setupFetchTracing({ spanContext });
  await sleep(100, spanContext);
  const output = await fetch(upstreamUrl);
  res.write(output);
}

Advanced Usage

This is the canonical usage in most API services with a couple of example child functions we can trace called sleep and route.

We take advantage of the SpanContext of the parent span when creating a child span.

We also use a DeterministicSampler so that all services will use the same sample rate because one trace might have multiple services and we don't want to lose part of a trace due to sampling.

import micro from 'micro';
import { Tracer, SpanContext, DeterministicSampler } from '@zeit/tracing-js';

const tracer = new Tracer(
  {
    serviceName: 'my-first-service',
    environment: process.env.ENVIRONMENT,
    dc: process.env.DC,
    podName: process.env.POD_NAME,
    nodeName: process.env.NODE_NAME,
    sampler: new DeterministicSampler(process.env.TRACE_SAMPLE_RATE),
  },
  {
    writeKey: process.env.HONEYCOMB_KEY!,
    dataset: process.env.HONEYCOMB_DATASET!,
  },
);

// example child function we wish to trace
async function sleep(ms: number, childOf: SpanContext) {
  const span = tracer.startSpan(sleep.name, { childOf });
  return new Promise(resolve =>
    setTimeout(() => {
      span.finish();
      resolve();
    }, ms),
  );
}

// example child function we wish to trace
async function route(path: string, childOf: SpanContext) {
  const span = tracer.startSpan(route.name, { childOf });
  await sleep(200, span.context());

  if (!path || path === '/') {
    span.finish();
    return 'Home page';
  } else if (path === '/next') {
    span.finish();
    return 'Next page';
  } else {
    span.finish();
    throw new Error('Page not found');
  }
}

// example parent function we wish to trace
async function handler(req: IncomingMessage, res: ServerResponse) {
  const span = tracer.startSpan(handler.name);
  const spanContext = span.context();
  await sleep(100, spanContext);
  const output = await route(req.url, spanContext);
  res.end(output);
  span.finish();
}

micro(handler).listen(3000);

See a complete example of multi-service tracing in the examples directory.

You can’t perform that action at this time.