Skip to content

Instantly share code, notes, and snippets.

@heckj
Created May 21, 2019 00:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heckj/00701e2971cb2f307326eede6cb7e058 to your computer and use it in GitHub Desktop.
Save heckj/00701e2971cb2f307326eede6cb7e058 to your computer and use it in GitHub Desktop.
import * as opentracing from 'opentracing';
import { DocumentQuery } from 'mongoose';
// Notes and light documentation at <https://github.com/jaegertracing/jaeger-client-node>
// templates for running Jaeger pieces in Kubernetes at <https://github.com/jaegertracing/jaeger-kubernetes>
// If you're working in local development and want to see what's up here, you can run a local instance
// of Jaeger in a docker container to capture any generated traces locally. This works with running the
// unit tests and traces they generate.
//
// from <https://www.jaegertracing.io/docs/1.8/getting-started/>
// docker run -d --name jaeger \
// -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
// -p 5775:5775/udp \
// -p 6831:6831/udp \
// -p 6832:6832/udp \
// -p 5778:5778 \
// -p 16686:16686 \
// -p 14268:14268 \
// -p 9411:9411 \
// jaegertracing/all-in-one:1.8
// to clean up after:
// docker rm /jaeger
// the web UI for this is exposed on port 16686...
// open http://localhost:16686
// once that's up and running, do something that will generate traces, such as running the tests:
// npm test -- --filter='API /sites/{site}/trackers'
// and after that, the trace's UI will have some data to poke through...
// If you're using this on a Mac, you might start seeing some EMSGERROR responses. MacOS constrains
// the size of the max UDP header below where Jaeger is happy. You can bump it up though:
// $ sysctl net.inet.udp.maxdgram
// net.inet.udp.maxdgram: 9216
// $ sudo sysctl net.inet.udp.maxdgram=65536
// net.inet.udp.maxdgram: 9216 -> 65536
// $ sudo sysctl net.inet.udp.maxdgram
// net.inet.udp.maxdgram: 65536
// If you're missing traces you expect to see, check this setting!
// When instrumenting code with trace Spans, you add tags to help identify the spans later.
// The semantic definitions from OpenTracing for common tag names and usages are detailed at
// <https://github.com/opentracing/specification/blob/master/semantic_conventions.md>
const initJaegerTracer = require('jaeger-client').initTracer;
function initTracer(serviceName: string) {
const config = {
serviceName: serviceName,
// sampler details: <https://www.jaegertracing.io/docs/1.7/sampling/#client-sampling-configuration>
sampler: {
type: 'probabilistic',
param: 0.5, // traces roughly half the calls
},
reporter: {
logSpans: false, // this logs whenever we send a span
},
};
const options = {
logger: {
info: function logInfo(msg: string) {
console.log('INFO ', msg);
},
error: function logError(msg: string) {
console.log('ERROR ', msg);
},
},
};
return initJaegerTracer(config, options);
}
export const tracer = initTracer('vertex-api') as opentracing.Tracer;
export function createSchemaSpan(schemaName: string, operation: string, parentSpan?: opentracing.Span) {
if (parentSpan) {
return tracer.startSpan(operation, {
childOf: parentSpan,
tags: {
[opentracing.Tags.SPAN_KIND]: opentracing.Tags.SPAN_KIND_RPC_SERVER,
[opentracing.Tags.COMPONENT]: schemaName
}
});
} else {
return tracer.startSpan(operation, {
tags: {
[opentracing.Tags.SPAN_KIND]: opentracing.Tags.SPAN_KIND_RPC_SERVER,
[opentracing.Tags.COMPONENT]: schemaName
}
});
}
}
export function createControllerSpan(controller: string, operation: string, headers: any) {
let traceSpan: opentracing.Span;
// NOTE(heckj): OpenTracing type definitions at
// <https://github.com/opentracing/opentracing-javascript/blob/master/src/tracer.ts>
const parentSpanContext = tracer.extract(opentracing.FORMAT_HTTP_HEADERS, headers);
if (parentSpanContext) {
traceSpan = tracer.startSpan(operation, {
childOf: parentSpanContext,
tags: {
[opentracing.Tags.SPAN_KIND]: opentracing.Tags.SPAN_KIND_RPC_SERVER,
[opentracing.Tags.COMPONENT]: controller
}
});
} else {
traceSpan = tracer.startSpan(operation, {
tags: {
[opentracing.Tags.SPAN_KIND]: opentracing.Tags.SPAN_KIND_RPC_SERVER,
[opentracing.Tags.COMPONENT]: controller
}
});
}
return traceSpan;
}
export function finishSpanWithResult(span: opentracing.Span, status: Number, errorTag?: boolean) {
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, status);
if (errorTag) {
span.setTag(opentracing.Tags.ERROR, true);
}
span.finish();
}
export async function traceMongoQuery(parentSpan: opentracing.Span, traceName: string, documentQuery: DocumentQuery<any, any>) {
const traceSpan = tracer.startSpan(traceName, {
childOf: parentSpan,
tags: {
[opentracing.Tags.SPAN_KIND]: opentracing.Tags.SPAN_KIND_RPC_SERVER,
[opentracing.Tags.COMPONENT]: 'mongodb'
}
});
const documentResult = await documentQuery;
traceSpan.finish();
return documentResult;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment