Named Tracers / Tracer Registry (#582)
* feat: spike of named tracer registry * chore: mysql/mongo tracer registry support * fix: lint * chore: add getTracer back * chore: change default tracer name to empty string * fix: lint * chore: update examples for registry * chore(tracer-registry): make name required * chore: lint * chore: update examples for required tracer name * chore: remove unused tracer delegate * chore: remove references to basic tracer * chore: remove references to NodeTracer * chore: update xhr for tracer registry * chore: update tracer names to match package names * chore: add version script to all packages * chore: update plugins to use version script * chore: add jsdoc to noop tracer registry * chore: update ioredis for tracer registry * chore: update pg pool for tracer registry * fix: lint * chore: fix tests * chore: lint * chore: lint Co-authored-by: Mayur Kale <mayurkale@google.com>
This commit is contained in:
parent
059595a215
commit
18c6aa4f19
|
@ -71,6 +71,7 @@ docs
|
||||||
|
|
||||||
#lerna
|
#lerna
|
||||||
.changelog
|
.changelog
|
||||||
|
package.json.lerna_backup
|
||||||
|
|
||||||
# OS generated files
|
# OS generated files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
|
@ -2,26 +2,26 @@
|
||||||
|
|
||||||
const benchmark = require('./benchmark');
|
const benchmark = require('./benchmark');
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { BasicTracer, BatchSpanProcessor, InMemorySpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { BasicTracerRegistry, BatchSpanProcessor, InMemorySpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const exporter = new InMemorySpanExporter();
|
const exporter = new InMemorySpanExporter();
|
||||||
const logger = new opentelemetry.NoopLogger();
|
const logger = new opentelemetry.NoopLogger();
|
||||||
|
|
||||||
const setups = [
|
const setups = [
|
||||||
{
|
{
|
||||||
name: 'BasicTracer',
|
name: 'BasicTracerRegistry',
|
||||||
tracer: new BasicTracer({ logger })
|
registry: new BasicTracerRegistry({ logger })
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'NodeTracer',
|
name: 'NodeTracerRegistry',
|
||||||
tracer: new NodeTracer({ logger })
|
registry: new NodeTracerRegistry({ logger })
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const setup of setups) {
|
for (const setup of setups) {
|
||||||
console.log(`Beginning ${setup.name} Benchmark...`);
|
console.log(`Beginning ${setup.name} Benchmark...`);
|
||||||
const tracer = setup.tracer;
|
const tracer = setup.registry.getTracer("benchmark");
|
||||||
const suite = benchmark()
|
const suite = benchmark()
|
||||||
.add('#startSpan', function () {
|
.add('#startSpan', function () {
|
||||||
const span = tracer.startSpan('op');
|
const span = tracer.startSpan('op');
|
||||||
|
@ -55,7 +55,7 @@ for (const setup of setups) {
|
||||||
.add('#startSpan with SimpleSpanProcessor', function () {
|
.add('#startSpan with SimpleSpanProcessor', function () {
|
||||||
const simpleSpanProcessor = new SimpleSpanProcessor(exporter);
|
const simpleSpanProcessor = new SimpleSpanProcessor(exporter);
|
||||||
|
|
||||||
tracer.addSpanProcessor(simpleSpanProcessor);
|
registry.addSpanProcessor(simpleSpanProcessor);
|
||||||
const span = tracer.startSpan('op');
|
const span = tracer.startSpan('op');
|
||||||
span.end();
|
span.end();
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ for (const setup of setups) {
|
||||||
.add('#startSpan with BatchSpanProcessor', function () {
|
.add('#startSpan with BatchSpanProcessor', function () {
|
||||||
const batchSpanProcessor = new BatchSpanProcessor(exporter);
|
const batchSpanProcessor = new BatchSpanProcessor(exporter);
|
||||||
|
|
||||||
tracer.addSpanProcessor(batchSpanProcessor);
|
registry.addSpanProcessor(batchSpanProcessor);
|
||||||
const span = tracer.startSpan('op');
|
const span = tracer.startSpan('op');
|
||||||
span.end();
|
span.end();
|
||||||
batchSpanProcessor.shutdown();
|
batchSpanProcessor.shutdown();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { BasicTracer, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { BasicTracerRegistry, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
|
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
|
||||||
|
@ -20,16 +20,17 @@ if (EXPORTER.toLowerCase().startsWith('z')) {
|
||||||
exporter = new CollectorExporter(options);
|
exporter = new CollectorExporter(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tracer = new BasicTracer();
|
const registry = new BasicTracerRegistry();
|
||||||
|
|
||||||
// Configure span processor to send spans to the provided exporter
|
// Configure span processor to send spans to the provided exporter
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
|
const tracer = opentelemetry.getTracer('example-basic-tracer-node')
|
||||||
|
|
||||||
// Create a span. A span must be closed.
|
// Create a span. A span must be closed.
|
||||||
const span = opentelemetry.getTracer().startSpan('main');
|
const span = tracer.startSpan('main');
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
doWork(span);
|
doWork(span);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +43,7 @@ exporter.shutdown();
|
||||||
function doWork(parent) {
|
function doWork(parent) {
|
||||||
// Start another span. In this example, the main method already started a
|
// Start another span. In this example, the main method already started a
|
||||||
// span, so that'll be the parent span, and this will be a child span.
|
// span, so that'll be the parent span, and this will be a child span.
|
||||||
const span = opentelemetry.getTracer().startSpan('doWork', {
|
const span = tracer.startSpan('doWork', {
|
||||||
parent: parent
|
parent: parent
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { BasicTracer, BatchSpanProcessor, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { BasicTracerRegistry, BatchSpanProcessor, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
|
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
|
||||||
|
|
||||||
const tracer = new BasicTracer();
|
const registry = new BasicTracerRegistry();
|
||||||
|
|
||||||
const zipkinExporter = new ZipkinExporter({serviceName: 'basic-service'});
|
const zipkinExporter = new ZipkinExporter({serviceName: 'basic-service'});
|
||||||
const jaegerExporter = new JaegerExporter({
|
const jaegerExporter = new JaegerExporter({
|
||||||
|
@ -14,21 +14,22 @@ const collectorExporter = new CollectorExporter({serviceName: 'basic-service'});
|
||||||
|
|
||||||
// It is recommended to use this BatchSpanProcessor for better performance
|
// It is recommended to use this BatchSpanProcessor for better performance
|
||||||
// and optimization, especially in production.
|
// and optimization, especially in production.
|
||||||
tracer.addSpanProcessor(new BatchSpanProcessor(zipkinExporter, {
|
registry.addSpanProcessor(new BatchSpanProcessor(zipkinExporter, {
|
||||||
bufferSize: 10 // This is added for example, default size is 100.
|
bufferSize: 10 // This is added for example, default size is 100.
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// It is recommended to use SimpleSpanProcessor in case of Jaeger exporter as
|
// It is recommended to use SimpleSpanProcessor in case of Jaeger exporter as
|
||||||
// it's internal client already handles the spans with batching logic.
|
// it's internal client already handles the spans with batching logic.
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(jaegerExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(jaegerExporter));
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(collectorExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(collectorExporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
|
const tracer = opentelemetry.getTracer('default');
|
||||||
|
|
||||||
// Create a span. A span must be closed.
|
// Create a span. A span must be closed.
|
||||||
const span = opentelemetry.getTracer().startSpan('main');
|
const span = tracer.startSpan('main');
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
doWork(span);
|
doWork(span);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +44,7 @@ collectorExporter.shutdown();
|
||||||
function doWork(parent) {
|
function doWork(parent) {
|
||||||
// Start another span. In this example, the main method already started a
|
// Start another span. In this example, the main method already started a
|
||||||
// span, so that'll be the parent span, and this will be a child span.
|
// span, so that'll be the parent span, and this will be a child span.
|
||||||
const span = opentelemetry.getTracer().startSpan('doWork', {
|
const span = tracer.startSpan('doWork', {
|
||||||
parent: parent
|
parent: parent
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ const config = require('./setup');
|
||||||
config.setupTracerAndExporters('dns-client-service');
|
config.setupTracerAndExporters('dns-client-service');
|
||||||
|
|
||||||
const dns = require('dns').promises;
|
const dns = require('dns').promises;
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-dns');
|
||||||
|
|
||||||
/** A function which makes a dns lookup and handles response. */
|
/** A function which makes a dns lookup and handles response. */
|
||||||
function makeLookup() {
|
function makeLookup() {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
const EXPORTER = process.env.EXPORTER || '';
|
const EXPORTER = process.env.EXPORTER || '';
|
||||||
|
|
||||||
function setupTracerAndExporters(service) {
|
function setupTracerAndExporters(service) {
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
dns: {
|
dns: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -30,10 +30,10 @@ function setupTracerAndExporters(service) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setupTracerAndExporters = setupTracerAndExporters;
|
exports.setupTracerAndExporters = setupTracerAndExporters;
|
||||||
|
|
|
@ -14,7 +14,7 @@ const grpc = require('grpc');
|
||||||
const messages = require('./helloworld_pb');
|
const messages = require('./helloworld_pb');
|
||||||
const services = require('./helloworld_grpc_pb');
|
const services = require('./helloworld_grpc_pb');
|
||||||
const PORT = 50051;
|
const PORT = 50051;
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-grpc-client');
|
||||||
|
|
||||||
/** A function which makes requests and handles response. */
|
/** A function which makes requests and handles response. */
|
||||||
function main() {
|
function main() {
|
||||||
|
|
|
@ -10,7 +10,7 @@ const config = require('./setup');
|
||||||
config.setupTracerAndExporters('grpc-server-service');
|
config.setupTracerAndExporters('grpc-server-service');
|
||||||
|
|
||||||
const grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-grpc-server');
|
||||||
|
|
||||||
const messages = require('./helloworld_pb');
|
const messages = require('./helloworld_pb');
|
||||||
const services = require('./helloworld_grpc_pb');
|
const services = require('./helloworld_grpc_pb');
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
const EXPORTER = process.env.EXPORTER || '';
|
const EXPORTER = process.env.EXPORTER || '';
|
||||||
|
|
||||||
function setupTracerAndExporters(service) {
|
function setupTracerAndExporters(service) {
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
grpc: {
|
grpc: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -29,10 +29,10 @@ function setupTracerAndExporters(service) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setupTracerAndExporters = setupTracerAndExporters;
|
exports.setupTracerAndExporters = setupTracerAndExporters;
|
||||||
|
|
|
@ -13,7 +13,7 @@ const path = require('path');
|
||||||
const grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
const protoLoader = require('@grpc/proto-loader');
|
const protoLoader = require('@grpc/proto-loader');
|
||||||
|
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-grpc-capitalize-client');
|
||||||
|
|
||||||
const PROTO_PATH = path.join(__dirname, 'protos/defs.proto');
|
const PROTO_PATH = path.join(__dirname, 'protos/defs.proto');
|
||||||
const PROTO_OPTIONS = { keepCase: true, enums: String, defaults: true, oneofs: true };
|
const PROTO_OPTIONS = { keepCase: true, enums: String, defaults: true, oneofs: true };
|
||||||
|
|
|
@ -19,7 +19,7 @@ const PROTO_OPTIONS = { keepCase: true, enums: String, defaults: true, oneofs: t
|
||||||
const definition = protoLoader.loadSync(PROTO_PATH, PROTO_OPTIONS);
|
const definition = protoLoader.loadSync(PROTO_PATH, PROTO_OPTIONS);
|
||||||
const rpcProto = grpc.loadPackageDefinition(definition).rpc;
|
const rpcProto = grpc.loadPackageDefinition(definition).rpc;
|
||||||
|
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-grpc-capitalize-server');
|
||||||
|
|
||||||
/** Implements the Capitalize RPC method. */
|
/** Implements the Capitalize RPC method. */
|
||||||
function capitalize(call, callback) {
|
function capitalize(call, callback) {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
const EXPORTER = process.env.EXPORTER || '';
|
const EXPORTER = process.env.EXPORTER || '';
|
||||||
|
|
||||||
function setupTracerAndExporters(service) {
|
function setupTracerAndExporters(service) {
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
grpc: {
|
grpc: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -31,10 +31,10 @@ function setupTracerAndExporters(service) {
|
||||||
|
|
||||||
// It is recommended to use this `BatchSpanProcessor` for better performance
|
// It is recommended to use this `BatchSpanProcessor` for better performance
|
||||||
// and optimization, especially in production.
|
// and optimization, especially in production.
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setupTracerAndExporters = setupTracerAndExporters;
|
exports.setupTracerAndExporters = setupTracerAndExporters;
|
||||||
|
|
|
@ -10,7 +10,7 @@ const config = require('./setup');
|
||||||
config.setupTracerAndExporters('http-client-service');
|
config.setupTracerAndExporters('http-client-service');
|
||||||
|
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-http-client');
|
||||||
|
|
||||||
/** A function which makes requests and handles response. */
|
/** A function which makes requests and handles response. */
|
||||||
function makeRequest() {
|
function makeRequest() {
|
||||||
|
|
|
@ -9,7 +9,7 @@ const config = require('./setup');
|
||||||
config.setupTracerAndExporters('http-server-service');
|
config.setupTracerAndExporters('http-server-service');
|
||||||
|
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-http-server');
|
||||||
|
|
||||||
/** Starts a HTTP server that receives requests on sample server port. */
|
/** Starts a HTTP server that receives requests on sample server port. */
|
||||||
function startServer (port) {
|
function startServer (port) {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
const EXPORTER = process.env.EXPORTER || '';
|
const EXPORTER = process.env.EXPORTER || '';
|
||||||
|
|
||||||
function setupTracerAndExporters(service) {
|
function setupTracerAndExporters(service) {
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
|
|
||||||
let exporter;
|
let exporter;
|
||||||
if (EXPORTER.toLowerCase().startsWith('z')) {
|
if (EXPORTER.toLowerCase().startsWith('z')) {
|
||||||
|
@ -21,10 +21,10 @@ function setupTracerAndExporters(service) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setupTracerAndExporters = setupTracerAndExporters;
|
exports.setupTracerAndExporters = setupTracerAndExporters;
|
||||||
|
|
|
@ -9,7 +9,7 @@ const config = require('./setup');
|
||||||
config.setupTracerAndExporters('https-client-service');
|
config.setupTracerAndExporters('https-client-service');
|
||||||
|
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-https-client');
|
||||||
|
|
||||||
/** A function which makes requests and handles response. */
|
/** A function which makes requests and handles response. */
|
||||||
function makeRequest() {
|
function makeRequest() {
|
||||||
|
|
|
@ -10,7 +10,7 @@ const config = require('./setup');
|
||||||
config.setupTracerAndExporters('https-server-service');
|
config.setupTracerAndExporters('https-server-service');
|
||||||
|
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-https-server');
|
||||||
|
|
||||||
/** Starts a HTTPs server that receives requests on sample server port. */
|
/** Starts a HTTPs server that receives requests on sample server port. */
|
||||||
function startServer (port) {
|
function startServer (port) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
|
@ -9,7 +9,7 @@ const EXPORTER = process.env.EXPORTER || '';
|
||||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||||
function setupTracerAndExporters(service) {
|
function setupTracerAndExporters(service) {
|
||||||
let exporter;
|
let exporter;
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
|
|
||||||
if (EXPORTER.toLowerCase().startsWith('z')) {
|
if (EXPORTER.toLowerCase().startsWith('z')) {
|
||||||
exporter = new ZipkinExporter({
|
exporter = new ZipkinExporter({
|
||||||
|
@ -21,10 +21,10 @@ function setupTracerAndExporters(service) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setupTracerAndExporters = setupTracerAndExporters;
|
exports.setupTracerAndExporters = setupTracerAndExporters;
|
||||||
|
|
|
@ -10,7 +10,7 @@ const config = require('./setup');
|
||||||
config.setupTracerAndExporters('http-client-service');
|
config.setupTracerAndExporters('http-client-service');
|
||||||
|
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-mysql-http-client');
|
||||||
|
|
||||||
/** A function which makes requests and handles response. */
|
/** A function which makes requests and handles response. */
|
||||||
function makeRequest() {
|
function makeRequest() {
|
||||||
|
|
|
@ -11,7 +11,7 @@ config.setupTracerAndExporters('http-mysql-server-service');
|
||||||
const mysql = require('mysql');
|
const mysql = require('mysql');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
|
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-mysql-http-server');
|
||||||
|
|
||||||
const pool = mysql.createPool({
|
const pool = mysql.createPool({
|
||||||
host : 'localhost',
|
host : 'localhost',
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
|
|
||||||
function setupTracerAndExporters(service) {
|
function setupTracerAndExporters(service) {
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
mysql: {
|
mysql: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -20,15 +20,15 @@ function setupTracerAndExporters(service) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(new ZipkinExporter({
|
registry.addSpanProcessor(new SimpleSpanProcessor(new ZipkinExporter({
|
||||||
serviceName: service,
|
serviceName: service,
|
||||||
})));
|
})));
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(new JaegerExporter({
|
registry.addSpanProcessor(new SimpleSpanProcessor(new JaegerExporter({
|
||||||
serviceName: service,
|
serviceName: service,
|
||||||
})));
|
})));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setupTracerAndExporters = setupTracerAndExporters;
|
exports.setupTracerAndExporters = setupTracerAndExporters;
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { NodeTracer } = require("@opentelemetry/node");
|
const { NodeTracerRegistry } = require("@opentelemetry/node");
|
||||||
const { SimpleSpanProcessor } = require("@opentelemetry/tracing");
|
const { SimpleSpanProcessor } = require("@opentelemetry/tracing");
|
||||||
const { JaegerExporter } = require("@opentelemetry/exporter-jaeger");
|
const { JaegerExporter } = require("@opentelemetry/exporter-jaeger");
|
||||||
const { ZipkinExporter } = require("@opentelemetry/exporter-zipkin");
|
const { ZipkinExporter } = require("@opentelemetry/exporter-zipkin");
|
||||||
const { TracerShim } = require("@opentelemetry/shim-opentracing");
|
const { TracerShim } = require("@opentelemetry/shim-opentracing");
|
||||||
|
|
||||||
function shim(serviceName) {
|
function shim(serviceName) {
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(getExporter(serviceName)));
|
registry.addSpanProcessor(new SimpleSpanProcessor(getExporter(serviceName)));
|
||||||
|
|
||||||
return new TracerShim(tracer);
|
return new TracerShim(registry.getTracer("opentracing-shim"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getExporter(serviceName) {
|
function getExporter(serviceName) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ const opentelemetry = require('@opentelemetry/core');
|
||||||
const types = require('@opentelemetry/types');
|
const types = require('@opentelemetry/types');
|
||||||
const config = require('./setup');
|
const config = require('./setup');
|
||||||
config.setupTracerAndExporters('redis-client-service');
|
config.setupTracerAndExporters('redis-client-service');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-redis-client');
|
||||||
const axios = require('axios').default;
|
const axios = require('axios').default;
|
||||||
|
|
||||||
function makeRequest() {
|
function makeRequest() {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const config = require('./setup');
|
const config = require('./setup');
|
||||||
config.setupTracerAndExporters('redis-server-service');
|
config.setupTracerAndExporters('redis-server-service');
|
||||||
const tracer = opentelemetry.getTracer();
|
const tracer = opentelemetry.getTracer('example-redis-server');
|
||||||
|
|
||||||
// Require in rest of modules
|
// Require in rest of modules
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
|
||||||
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
|
||||||
const EXPORTER = process.env.EXPORTER || '';
|
const EXPORTER = process.env.EXPORTER || '';
|
||||||
|
|
||||||
function setupTracerAndExporters(service) {
|
function setupTracerAndExporters(service) {
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
|
|
||||||
let exporter;
|
let exporter;
|
||||||
if (EXPORTER.toLowerCase().startsWith('z')) {
|
if (EXPORTER.toLowerCase().startsWith('z')) {
|
||||||
|
@ -21,10 +21,10 @@ function setupTracerAndExporters(service) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setupTracerAndExporters = setupTracerAndExporters;
|
exports.setupTracerAndExporters = setupTracerAndExporters;
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
|
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
|
||||||
import { WebTracer } from '@opentelemetry/web';
|
import { WebTracerRegistry } from '@opentelemetry/web';
|
||||||
import { DocumentLoad } from '@opentelemetry/plugin-document-load';
|
import { DocumentLoad } from '@opentelemetry/plugin-document-load';
|
||||||
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
|
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
|
||||||
import { CollectorExporter } from '@opentelemetry/exporter-collector'
|
import { CollectorExporter } from '@opentelemetry/exporter-collector'
|
||||||
|
|
||||||
const webTracer = new WebTracer({
|
const registry = new WebTracerRegistry({
|
||||||
plugins: [
|
plugins: [
|
||||||
new DocumentLoad()
|
new DocumentLoad()
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
webTracer.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
|
registry.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
|
||||||
|
|
||||||
const webTracerWithZone = new WebTracer({
|
const registryWithZone = new WebTracerRegistry({
|
||||||
scopeManager: new ZoneScopeManager(),
|
scopeManager: new ZoneScopeManager(),
|
||||||
plugins: [
|
plugins: [
|
||||||
new DocumentLoad()
|
new DocumentLoad()
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
|
registryWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
|
||||||
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorExporter()));
|
registryWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorExporter()));
|
||||||
|
|
||||||
console.log('Current span is window', webTracerWithZone.getCurrentSpan() === window);
|
const tracerWithZone = registryWithZone.getTracer('example-tracer-web');
|
||||||
|
console.log('Current span is window', tracerWithZone.getCurrentSpan() === window);
|
||||||
|
|
||||||
// example of keeping track of scope between async operations
|
// example of keeping track of scope between async operations
|
||||||
const prepareClickEvent = () => {
|
const prepareClickEvent = () => {
|
||||||
|
@ -28,33 +29,33 @@ const prepareClickEvent = () => {
|
||||||
const url2 = 'https://raw.githubusercontent.com/open-telemetry/opentelemetry-js/master/packages/opentelemetry-web/package.json';
|
const url2 = 'https://raw.githubusercontent.com/open-telemetry/opentelemetry-js/master/packages/opentelemetry-web/package.json';
|
||||||
|
|
||||||
const element = document.getElementById('button1');
|
const element = document.getElementById('button1');
|
||||||
let mainSpan = webTracerWithZone.startSpan('main-span');
|
let mainSpan = tracerWithZone.startSpan('main-span');
|
||||||
webTracerWithZone.bind(element, mainSpan);
|
tracerWithZone.bind(element, mainSpan);
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
const span1 = webTracerWithZone.startSpan(`files-series-info-1`, {
|
const span1 = tracerWithZone.startSpan(`files-series-info-1`, {
|
||||||
parent: webTracerWithZone.getCurrentSpan()
|
parent: tracerWithZone.getCurrentSpan()
|
||||||
});
|
});
|
||||||
|
|
||||||
const span2 = webTracerWithZone.startSpan(`files-series-info-2`, {
|
const span2 = tracerWithZone.startSpan(`files-series-info-2`, {
|
||||||
parent: webTracerWithZone.getCurrentSpan()
|
parent: tracerWithZone.getCurrentSpan()
|
||||||
});
|
});
|
||||||
|
|
||||||
webTracerWithZone.withSpan(span1, () => {
|
tracerWithZone.withSpan(span1, () => {
|
||||||
getData(url1).then((data) => {
|
getData(url1).then((data) => {
|
||||||
console.log('current span is span1', webTracerWithZone.getCurrentSpan() === span1);
|
console.log('current span is span1', tracerWithZone.getCurrentSpan() === span1);
|
||||||
console.log('info from package.json', data.description, data.version);
|
console.log('info from package.json', data.description, data.version);
|
||||||
webTracerWithZone.getCurrentSpan().addEvent('fetching-span1-completed');
|
tracerWithZone.getCurrentSpan().addEvent('fetching-span1-completed');
|
||||||
span1.end();
|
span1.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
webTracerWithZone.withSpan(span2, () => {
|
tracerWithZone.withSpan(span2, () => {
|
||||||
getData(url2).then((data) => {
|
getData(url2).then((data) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log('current span is span2', webTracerWithZone.getCurrentSpan() === span2);
|
console.log('current span is span2', tracerWithZone.getCurrentSpan() === span2);
|
||||||
console.log('info from package.json', data.description, data.version);
|
console.log('info from package.json', data.description, data.version);
|
||||||
webTracerWithZone.getCurrentSpan().addEvent('fetching-span2-completed');
|
tracerWithZone.getCurrentSpan().addEvent('fetching-span2-completed');
|
||||||
span2.end();
|
span2.end();
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,10 +27,10 @@ export * from './trace/globaltracer-utils';
|
||||||
export * from './trace/instrumentation/BasePlugin';
|
export * from './trace/instrumentation/BasePlugin';
|
||||||
export * from './trace/NoopSpan';
|
export * from './trace/NoopSpan';
|
||||||
export * from './trace/NoopTracer';
|
export * from './trace/NoopTracer';
|
||||||
|
export * from './trace/NoopTracerRegistry';
|
||||||
export * from './trace/NoRecordingSpan';
|
export * from './trace/NoRecordingSpan';
|
||||||
export * from './trace/sampler/ProbabilitySampler';
|
export * from './trace/sampler/ProbabilitySampler';
|
||||||
export * from './trace/spancontext-utils';
|
export * from './trace/spancontext-utils';
|
||||||
export * from './trace/TracerDelegate';
|
|
||||||
export * from './trace/TraceState';
|
export * from './trace/TraceState';
|
||||||
export * from './metrics/NoopMeter';
|
export * from './metrics/NoopMeter';
|
||||||
export * from './utils/url';
|
export * from './utils/url';
|
||||||
|
|
|
@ -59,3 +59,5 @@ export class NoopTracer implements Tracer {
|
||||||
return NOOP_HTTP_TEXT_FORMAT;
|
return NOOP_HTTP_TEXT_FORMAT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const noopTracer = new NoopTracer();
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*!
|
||||||
|
* Copyright 2019, OpenTelemetry Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as types from '@opentelemetry/types';
|
||||||
|
import { noopTracer } from './NoopTracer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of the {@link TracerRegistry} which returns an impotent Tracer
|
||||||
|
* for all calls to `getTracer`
|
||||||
|
*/
|
||||||
|
export class NoopTracerRegistry implements types.TracerRegistry {
|
||||||
|
getTracer(_name?: string, _version?: string): types.Tracer {
|
||||||
|
return noopTracer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,101 +0,0 @@
|
||||||
/*!
|
|
||||||
* Copyright 2019, OpenTelemetry Authors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as types from '@opentelemetry/types';
|
|
||||||
import { NoopTracer } from './NoopTracer';
|
|
||||||
|
|
||||||
// Acts a bridge to the global tracer that can be safely called before the
|
|
||||||
// global tracer is initialized. The purpose of the delegation is to avoid the
|
|
||||||
// sometimes nearly intractable initialization order problems that can arise in
|
|
||||||
// applications with a complex set of dependencies. Also allows for the tracer
|
|
||||||
// to be changed/disabled during runtime without needing to change reference
|
|
||||||
// to the global tracer
|
|
||||||
export class TracerDelegate implements types.Tracer {
|
|
||||||
private _currentTracer: types.Tracer;
|
|
||||||
private readonly _tracer: types.Tracer | null;
|
|
||||||
private readonly _fallbackTracer: types.Tracer;
|
|
||||||
|
|
||||||
// Wrap a tracer with a TracerDelegate. Provided tracer becomes the default
|
|
||||||
// fallback tracer for when a global tracer has not been initialized
|
|
||||||
constructor(tracer?: types.Tracer, fallbackTracer?: types.Tracer) {
|
|
||||||
this._tracer = tracer || null;
|
|
||||||
this._fallbackTracer = fallbackTracer || new NoopTracer();
|
|
||||||
this._currentTracer = this._tracer || this._fallbackTracer; // equivalent to this.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Begin using the user provided tracer. Stop always falling back to fallback tracer
|
|
||||||
start(): void {
|
|
||||||
this._currentTracer = this._tracer || this._fallbackTracer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop the delegate from using the provided tracer. Begin to use the fallback tracer
|
|
||||||
stop(): void {
|
|
||||||
this._currentTracer = this._fallbackTracer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Tracer interface implementation below -- //
|
|
||||||
|
|
||||||
getCurrentSpan(): types.Span | undefined {
|
|
||||||
return this._currentTracer.getCurrentSpan.apply(
|
|
||||||
this._currentTracer,
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
arguments as any
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind<T>(target: T, span?: types.Span): T {
|
|
||||||
return (this._currentTracer.bind.apply(
|
|
||||||
this._currentTracer,
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
arguments as any
|
|
||||||
) as unknown) as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
startSpan(name: string, options?: types.SpanOptions): types.Span {
|
|
||||||
return this._currentTracer.startSpan.apply(
|
|
||||||
this._currentTracer,
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
arguments as any
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
withSpan<T extends (...args: unknown[]) => ReturnType<T>>(
|
|
||||||
span: types.Span,
|
|
||||||
fn: T
|
|
||||||
): ReturnType<T> {
|
|
||||||
return this._currentTracer.withSpan.apply(
|
|
||||||
this._currentTracer,
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
arguments as any
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getBinaryFormat(): types.BinaryFormat {
|
|
||||||
return this._currentTracer.getBinaryFormat.apply(
|
|
||||||
this._currentTracer,
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
arguments as any
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHttpTextFormat(): types.HttpTextFormat {
|
|
||||||
return this._currentTracer.getHttpTextFormat.apply(
|
|
||||||
this._currentTracer,
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
arguments as any
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,21 +15,31 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as types from '@opentelemetry/types';
|
import * as types from '@opentelemetry/types';
|
||||||
import { TracerDelegate } from './TracerDelegate';
|
import { NoopTracerRegistry } from './NoopTracerRegistry';
|
||||||
|
|
||||||
let globalTracerDelegate = new TracerDelegate();
|
let globalTracerRegistry: types.TracerRegistry = new NoopTracerRegistry();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current global tracer. Returns the initialized global tracer
|
* Set the current global tracer. Returns the initialized global tracer
|
||||||
*/
|
*/
|
||||||
export function initGlobalTracer(tracer: types.Tracer): types.Tracer {
|
export function initGlobalTracerRegistry(
|
||||||
return (globalTracerDelegate = new TracerDelegate(tracer));
|
tracerRegistry: types.TracerRegistry
|
||||||
|
): types.TracerRegistry {
|
||||||
|
return (globalTracerRegistry = tracerRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the global tracer
|
* Returns the global tracer registry.
|
||||||
*/
|
*/
|
||||||
export function getTracer(): types.Tracer {
|
export function getTracerRegistry(): types.TracerRegistry {
|
||||||
// Return the global tracer delegate
|
// Return the global tracer registry
|
||||||
return globalTracerDelegate;
|
return globalTracerRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a tracer from the global tracer registry.
|
||||||
|
*/
|
||||||
|
export function getTracer(name: string, version?: string): types.Tracer {
|
||||||
|
// Return the global tracer registry
|
||||||
|
return globalTracerRegistry.getTracer(name, version);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
PluginConfig,
|
PluginConfig,
|
||||||
PluginInternalFiles,
|
PluginInternalFiles,
|
||||||
PluginInternalFilesVersion,
|
PluginInternalFilesVersion,
|
||||||
|
TracerRegistry,
|
||||||
} from '@opentelemetry/types';
|
} from '@opentelemetry/types';
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
@ -39,14 +40,22 @@ export abstract class BasePlugin<T> implements Plugin<T> {
|
||||||
protected readonly _internalFilesList?: PluginInternalFiles; // required for internalFilesExports
|
protected readonly _internalFilesList?: PluginInternalFiles; // required for internalFilesExports
|
||||||
protected _config!: PluginConfig;
|
protected _config!: PluginConfig;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected readonly _tracerName: string,
|
||||||
|
protected readonly _tracerVersion?: string
|
||||||
|
) {}
|
||||||
|
|
||||||
enable(
|
enable(
|
||||||
moduleExports: T,
|
moduleExports: T,
|
||||||
tracer: Tracer,
|
tracerRegistry: TracerRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
config?: PluginConfig
|
config?: PluginConfig
|
||||||
): T {
|
): T {
|
||||||
this._moduleExports = moduleExports;
|
this._moduleExports = moduleExports;
|
||||||
this._tracer = tracer;
|
this._tracer = tracerRegistry.getTracer(
|
||||||
|
this._tracerName,
|
||||||
|
this._tracerVersion
|
||||||
|
);
|
||||||
this._logger = logger;
|
this._logger = logger;
|
||||||
this._internalFilesExports = this._loadInternalFilesExports();
|
this._internalFilesExports = this._loadInternalFilesExports();
|
||||||
if (config) this._config = config;
|
if (config) this._config = config;
|
||||||
|
|
|
@ -14,12 +14,13 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BasePlugin, NoopTracer, NoopLogger } from '../../src';
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import { BasePlugin, NoopLogger } from '../../src';
|
||||||
|
import { NoopTracerRegistry } from '../../src/trace/NoopTracerRegistry';
|
||||||
import * as types from './fixtures/test-package/foo/bar/internal';
|
import * as types from './fixtures/test-package/foo/bar/internal';
|
||||||
|
|
||||||
const tracer = new NoopTracer();
|
const registry = new NoopTracerRegistry();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
|
|
||||||
describe('BasePlugin', () => {
|
describe('BasePlugin', () => {
|
||||||
|
@ -28,7 +29,7 @@ describe('BasePlugin', () => {
|
||||||
const testPackage = require('./fixtures/test-package');
|
const testPackage = require('./fixtures/test-package');
|
||||||
const plugin = new TestPlugin();
|
const plugin = new TestPlugin();
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
plugin.enable(testPackage, tracer, logger);
|
plugin.enable(testPackage, registry, logger);
|
||||||
});
|
});
|
||||||
|
|
||||||
// @TODO: https://github.com/open-telemetry/opentelemetry-js/issues/285
|
// @TODO: https://github.com/open-telemetry/opentelemetry-js/issues/285
|
||||||
|
@ -61,6 +62,10 @@ class TestPlugin extends BasePlugin<{ [key: string]: Function }> {
|
||||||
readonly version = '0.1.0';
|
readonly version = '0.1.0';
|
||||||
readonly _basedir = basedir;
|
readonly _basedir = basedir;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super('test-package.opentelemetry');
|
||||||
|
}
|
||||||
|
|
||||||
protected readonly _internalFilesList = {
|
protected readonly _internalFilesList = {
|
||||||
'0.1.0': {
|
'0.1.0': {
|
||||||
internal: 'foo/bar/internal.js',
|
internal: 'foo/bar/internal.js',
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
/*!
|
|
||||||
* Copyright 2019, OpenTelemetry Authors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as assert from 'assert';
|
|
||||||
import * as types from '@opentelemetry/types';
|
|
||||||
import { TracerDelegate } from '../../src/trace/TracerDelegate';
|
|
||||||
import { NoopTracer, NoopSpan } from '../../src';
|
|
||||||
import { TraceFlags } from '@opentelemetry/types';
|
|
||||||
|
|
||||||
describe('TracerDelegate', () => {
|
|
||||||
const functions = [
|
|
||||||
'getCurrentSpan',
|
|
||||||
'startSpan',
|
|
||||||
'withSpan',
|
|
||||||
'bind',
|
|
||||||
'getBinaryFormat',
|
|
||||||
'getHttpTextFormat',
|
|
||||||
];
|
|
||||||
const spanContext = {
|
|
||||||
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
|
|
||||||
spanId: '6e0c63257de34c92',
|
|
||||||
traceFlags: TraceFlags.UNSAMPLED,
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('constructor', () => {
|
|
||||||
it('should not crash with default constructor', () => {
|
|
||||||
functions.forEach(fn => {
|
|
||||||
const tracer = new TracerDelegate();
|
|
||||||
try {
|
|
||||||
((tracer as unknown) as { [fn: string]: Function })[fn](); // Try to run the function
|
|
||||||
assert.ok(true, fn);
|
|
||||||
} catch (err) {
|
|
||||||
if (err.message !== 'Method not implemented.') {
|
|
||||||
assert.ok(true, fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow fallback tracer to be set', () => {
|
|
||||||
const dummyTracer = new DummyTracer();
|
|
||||||
const tracerDelegate = new TracerDelegate(dummyTracer);
|
|
||||||
|
|
||||||
tracerDelegate.startSpan('foo');
|
|
||||||
assert.deepStrictEqual(dummyTracer.spyCounter, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use user provided tracer if provided', () => {
|
|
||||||
const dummyTracer = new DummyTracer();
|
|
||||||
const tracerDelegate = new TracerDelegate(dummyTracer);
|
|
||||||
|
|
||||||
tracerDelegate.startSpan('foo');
|
|
||||||
assert.deepStrictEqual(dummyTracer.spyCounter, 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.start/.stop()', () => {
|
|
||||||
it('should use the fallback tracer when stop is called', () => {
|
|
||||||
const dummyTracerUser = new DummyTracer();
|
|
||||||
const dummyTracerFallback = new DummyTracer();
|
|
||||||
const tracerDelegate = new TracerDelegate(
|
|
||||||
dummyTracerUser,
|
|
||||||
dummyTracerFallback
|
|
||||||
);
|
|
||||||
|
|
||||||
tracerDelegate.stop();
|
|
||||||
tracerDelegate.startSpan('fallback');
|
|
||||||
assert.deepStrictEqual(dummyTracerUser.spyCounter, 0);
|
|
||||||
assert.deepStrictEqual(dummyTracerFallback.spyCounter, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use the user tracer when start is called', () => {
|
|
||||||
const dummyTracerUser = new DummyTracer();
|
|
||||||
const dummyTracerFallback = new DummyTracer();
|
|
||||||
const tracerDelegate = new TracerDelegate(
|
|
||||||
dummyTracerUser,
|
|
||||||
dummyTracerFallback
|
|
||||||
);
|
|
||||||
|
|
||||||
tracerDelegate.stop();
|
|
||||||
tracerDelegate.startSpan('fallback');
|
|
||||||
assert.deepStrictEqual(dummyTracerUser.spyCounter, 0);
|
|
||||||
assert.deepStrictEqual(dummyTracerFallback.spyCounter, 1);
|
|
||||||
|
|
||||||
tracerDelegate.start();
|
|
||||||
tracerDelegate.startSpan('user');
|
|
||||||
assert.deepStrictEqual(dummyTracerUser.spyCounter, 1);
|
|
||||||
assert.deepStrictEqual(
|
|
||||||
dummyTracerFallback.spyCounter,
|
|
||||||
1,
|
|
||||||
'Only user tracer counter is incremented'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
class DummyTracer extends NoopTracer {
|
|
||||||
spyCounter = 0;
|
|
||||||
|
|
||||||
startSpan(name: string, options?: types.SpanOptions | undefined) {
|
|
||||||
this.spyCounter = this.spyCounter + 1;
|
|
||||||
return new NoopSpan(spanContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -17,11 +17,12 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as types from '@opentelemetry/types';
|
import * as types from '@opentelemetry/types';
|
||||||
import {
|
import {
|
||||||
getTracer,
|
getTracerRegistry,
|
||||||
initGlobalTracer,
|
initGlobalTracerRegistry,
|
||||||
} from '../../src/trace/globaltracer-utils';
|
} from '../../src/trace/globaltracer-utils';
|
||||||
import { NoopTracer, NoopSpan } from '../../src';
|
import { NoopTracer, NoopSpan } from '../../src';
|
||||||
import { TraceFlags } from '@opentelemetry/types';
|
import { TraceFlags } from '@opentelemetry/types';
|
||||||
|
import { NoopTracerRegistry } from '../../src/trace/NoopTracerRegistry';
|
||||||
|
|
||||||
describe('globaltracer-utils', () => {
|
describe('globaltracer-utils', () => {
|
||||||
const functions = [
|
const functions = [
|
||||||
|
@ -32,13 +33,13 @@ describe('globaltracer-utils', () => {
|
||||||
'getHttpTextFormat',
|
'getHttpTextFormat',
|
||||||
];
|
];
|
||||||
|
|
||||||
it('should expose a tracer via getTracer', () => {
|
it('should expose a tracer registry via getTracerRegistry', () => {
|
||||||
const tracer = getTracer();
|
const tracer = getTracerRegistry();
|
||||||
assert.ok(tracer);
|
assert.ok(tracer);
|
||||||
assert.strictEqual(typeof tracer, 'object');
|
assert.strictEqual(typeof tracer, 'object');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GlobalTracer', () => {
|
describe('GlobalTracerRegistry', () => {
|
||||||
const spanContext = {
|
const spanContext = {
|
||||||
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
|
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
|
||||||
spanId: '6e0c63257de34c92',
|
spanId: '6e0c63257de34c92',
|
||||||
|
@ -47,12 +48,12 @@ describe('globaltracer-utils', () => {
|
||||||
const dummySpan = new NoopSpan(spanContext);
|
const dummySpan = new NoopSpan(spanContext);
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
initGlobalTracer(new NoopTracer());
|
initGlobalTracerRegistry(new NoopTracerRegistry());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not crash', () => {
|
it('should not crash', () => {
|
||||||
functions.forEach(fn => {
|
functions.forEach(fn => {
|
||||||
const tracer = getTracer();
|
const tracer = getTracerRegistry();
|
||||||
try {
|
try {
|
||||||
((tracer as unknown) as { [fn: string]: Function })[fn](); // Try to run the function
|
((tracer as unknown) as { [fn: string]: Function })[fn](); // Try to run the function
|
||||||
assert.ok(true, fn);
|
assert.ok(true, fn);
|
||||||
|
@ -64,8 +65,9 @@ describe('globaltracer-utils', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use the global tracer', () => {
|
it('should use the global tracer registry', () => {
|
||||||
const tracer = initGlobalTracer(new TestTracer());
|
initGlobalTracerRegistry(new TestTracerRegistry());
|
||||||
|
const tracer = getTracerRegistry().getTracer('name');
|
||||||
const span = tracer.startSpan('test');
|
const span = tracer.startSpan('test');
|
||||||
assert.deepStrictEqual(span, dummySpan);
|
assert.deepStrictEqual(span, dummySpan);
|
||||||
});
|
});
|
||||||
|
@ -78,5 +80,11 @@ describe('globaltracer-utils', () => {
|
||||||
return dummySpan;
|
return dummySpan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestTracerRegistry extends NoopTracerRegistry {
|
||||||
|
getTracer(_name: string, version?: string) {
|
||||||
|
return new TestTracer();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,18 +35,18 @@ opentelemetry.initGlobalTracer(tracer);
|
||||||
## Usage in Node
|
## Usage in Node
|
||||||
```js
|
```js
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { BasicTracer, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
const { BasicTracerRegistry, SimpleSpanProcessor } = require('@opentelemetry/tracing');
|
||||||
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
|
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
|
||||||
|
|
||||||
const collectorOptions = {
|
const collectorOptions = {
|
||||||
url: '<opentelemetry-collector-url>' // url is optional and can be omitted - default is http://localhost:55678/v1/trace
|
url: '<opentelemetry-collector-url>' // url is optional and can be omitted - default is http://localhost:55678/v1/trace
|
||||||
};
|
};
|
||||||
|
|
||||||
const tracer = new BasicTracer();
|
const registry = new BasicTracerRegistry();
|
||||||
const exporter = new CollectorExporter(collectorOptions);
|
const exporter = new CollectorExporter(collectorOptions);
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
||||||
|
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as types from '@opentelemetry/types';
|
import * as types from '@opentelemetry/types';
|
||||||
import { Span, BasicTracer } from '@opentelemetry/tracing';
|
import { Span, BasicTracerRegistry } from '@opentelemetry/tracing';
|
||||||
import {
|
import {
|
||||||
NoopLogger,
|
NoopLogger,
|
||||||
hrTimeToMicroseconds,
|
hrTimeToMicroseconds,
|
||||||
|
@ -32,9 +32,9 @@ import {
|
||||||
import * as zipkinTypes from '../src/types';
|
import * as zipkinTypes from '../src/types';
|
||||||
|
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
});
|
}).getTracer('default');
|
||||||
const parentId = '5c1c63257de34c67';
|
const parentId = '5c1c63257de34c67';
|
||||||
const spanContext: types.SpanContext = {
|
const spanContext: types.SpanContext = {
|
||||||
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
|
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
|
||||||
|
|
|
@ -11,14 +11,14 @@ For manual instrumentation see the
|
||||||
[@opentelemetry/tracing](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing) package.
|
[@opentelemetry/tracing](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing) package.
|
||||||
|
|
||||||
## How does automated instrumentation work?
|
## How does automated instrumentation work?
|
||||||
This package exposes a `NodeTracer` that will automatically hook into the module loader of Node.js.
|
This package exposes a `NodeTracerRegistry` that will automatically hook into the module loader of Node.js.
|
||||||
|
|
||||||
For this to work, please make sure that `NodeTracer` is initialized before any other module of your application, (like `http` or `express`) is loaded.
|
For this to work, please make sure that `NodeTracerRegistry` is initialized before any other module of your application, (like `http` or `express`) is loaded.
|
||||||
|
|
||||||
OpenTelemetry comes with a growing number of instrumentation plugins for well know modules (see [supported modules](https://github.com/open-telemetry/opentelemetry-js#plugins)) and an API to create custom plugins (see [the plugin developer guide](https://github.com/open-telemetry/opentelemetry-js/blob/master/doc/plugin-guide.md)).
|
OpenTelemetry comes with a growing number of instrumentation plugins for well know modules (see [supported modules](https://github.com/open-telemetry/opentelemetry-js#plugins)) and an API to create custom plugins (see [the plugin developer guide](https://github.com/open-telemetry/opentelemetry-js/blob/master/doc/plugin-guide.md)).
|
||||||
|
|
||||||
|
|
||||||
Whenever a module is loaded `NodeTracer` will check if a matching instrumentation plugin has been installed.
|
Whenever a module is loaded `NodeTracerRegistry` will check if a matching instrumentation plugin has been installed.
|
||||||
|
|
||||||
> **Please note:** This module does *not* bundle any plugins. They need to be installed separately.
|
> **Please note:** This module does *not* bundle any plugins. They need to be installed separately.
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ This instrumentation code will automatically
|
||||||
In short, this means that this module will use provided plugins to automatically instrument your application to produce spans and provide end-to-end tracing by just adding a few lines of code.
|
In short, this means that this module will use provided plugins to automatically instrument your application to produce spans and provide end-to-end tracing by just adding a few lines of code.
|
||||||
|
|
||||||
## Creating custom spans on top of auto-instrumentation
|
## Creating custom spans on top of auto-instrumentation
|
||||||
Additionally to automated instrumentation, `NodeTracer` exposes the same API as [@opentelemetry/tracing](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing), allowing creating custom spans if needed.
|
Additionally to automated instrumentation, `NodeTracerRegistry` exposes the same API as [@opentelemetry/tracing](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing), allowing creating custom spans if needed.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -50,14 +50,14 @@ npm install --save @opentelemetry/plugin-https
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The following code will configure the `NodeTracer` to instrument `http` using `@opentelemetry/plugin-http`.
|
The following code will configure the `NodeTracerRegistry` to instrument `http` using `@opentelemetry/plugin-http`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
// Create and configure NodeTracer
|
// Create and configure NodeTracerRegistry
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
http: {
|
http: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -68,25 +68,25 @@ const tracer = new NodeTracer({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize the tracer
|
// Initialize the registry
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
|
|
||||||
// Your application code - http will automatically be instrumented if
|
// Your application code - http will automatically be instrumented if
|
||||||
// @opentelemetry/plugin-http is present
|
// @opentelemetry/plugin-http is present
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
```
|
```
|
||||||
|
|
||||||
To enable instrumentation for all [supported modules](https://github.com/open-telemetry/opentelemetry-js#plugins), create an instance of `NodeTracer` without providing any plugin configuration to the constructor.
|
To enable instrumentation for all [supported modules](https://github.com/open-telemetry/opentelemetry-js#plugins), create an instance of `NodeTracerRegistry` without providing any plugin configuration to the constructor.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
// Create and initialize NodeTracer
|
// Create and initialize NodeTracerRegistry
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
|
|
||||||
// Initialize the tracer
|
// Initialize the registry
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
opentelemetry.initGlobalTracerRegistry(registry);
|
||||||
|
|
||||||
// Your application code
|
// Your application code
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BasicTracer } from '@opentelemetry/tracing';
|
import { BasicTracerRegistry } from '@opentelemetry/tracing';
|
||||||
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
|
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
|
||||||
import { PluginLoader } from './instrumentation/PluginLoader';
|
import { PluginLoader } from './instrumentation/PluginLoader';
|
||||||
import { NodeTracerConfig, DEFAULT_INSTRUMENTATION_PLUGINS } from './config';
|
import { NodeTracerConfig, DEFAULT_INSTRUMENTATION_PLUGINS } from './config';
|
||||||
|
@ -22,7 +22,7 @@ import { NodeTracerConfig, DEFAULT_INSTRUMENTATION_PLUGINS } from './config';
|
||||||
/**
|
/**
|
||||||
* This class represents a node tracer with `async_hooks` module.
|
* This class represents a node tracer with `async_hooks` module.
|
||||||
*/
|
*/
|
||||||
export class NodeTracer extends BasicTracer {
|
export class NodeTracerRegistry extends BasicTracerRegistry {
|
||||||
private readonly _pluginLoader: PluginLoader;
|
private readonly _pluginLoader: PluginLoader;
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -15,12 +15,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Plugins } from './instrumentation/PluginLoader';
|
import { Plugins } from './instrumentation/PluginLoader';
|
||||||
import { BasicTracerConfig } from '@opentelemetry/tracing';
|
import { TracerConfig } from '@opentelemetry/tracing';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeTracerConfig provides an interface for configuring a Node Tracer.
|
* NodeTracerConfig provides an interface for configuring a Node Tracer.
|
||||||
*/
|
*/
|
||||||
export interface NodeTracerConfig extends BasicTracerConfig {
|
export interface NodeTracerConfig extends TracerConfig {
|
||||||
/** Plugins options. */
|
/** Plugins options. */
|
||||||
plugins?: Plugins;
|
plugins?: Plugins;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,4 +14,4 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './NodeTracer';
|
export * from './NodeTracerRegistry';
|
||||||
|
|
|
@ -14,7 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Logger, Plugin, Tracer, PluginConfig } from '@opentelemetry/types';
|
import {
|
||||||
|
Logger,
|
||||||
|
Plugin,
|
||||||
|
PluginConfig,
|
||||||
|
TracerRegistry,
|
||||||
|
} from '@opentelemetry/types';
|
||||||
import * as hook from 'require-in-the-middle';
|
import * as hook from 'require-in-the-middle';
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
|
|
||||||
|
@ -55,7 +60,7 @@ export class PluginLoader {
|
||||||
private _hookState = HookState.UNINITIALIZED;
|
private _hookState = HookState.UNINITIALIZED;
|
||||||
|
|
||||||
/** Constructs a new PluginLoader instance. */
|
/** Constructs a new PluginLoader instance. */
|
||||||
constructor(readonly tracer: Tracer, readonly logger: Logger) {}
|
constructor(readonly registry: TracerRegistry, readonly logger: Logger) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a list of plugins. Each plugin module should implement the core
|
* Loads a list of plugins. Each plugin module should implement the core
|
||||||
|
@ -115,7 +120,7 @@ export class PluginLoader {
|
||||||
|
|
||||||
this._plugins.push(plugin);
|
this._plugins.push(plugin);
|
||||||
// Enable each supported plugin.
|
// Enable each supported plugin.
|
||||||
return plugin.enable(exports, this.tracer, this.logger, config);
|
return plugin.enable(exports, this.registry, this.logger, config);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`PluginLoader#load: could not load plugin ${modulePath} of module ${name}. Error: ${e.message}`
|
`PluginLoader#load: could not load plugin ${modulePath} of module ${name}. Error: ${e.message}`
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {
|
||||||
NoopLogger,
|
NoopLogger,
|
||||||
NoRecordingSpan,
|
NoRecordingSpan,
|
||||||
} from '@opentelemetry/core';
|
} from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '../src/NodeTracer';
|
import { NodeTracerRegistry } from '../src/NodeTracerRegistry';
|
||||||
import { TraceFlags } from '@opentelemetry/types';
|
import { TraceFlags } from '@opentelemetry/types';
|
||||||
import { Span } from '@opentelemetry/tracing';
|
import { Span } from '@opentelemetry/tracing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
@ -39,8 +39,8 @@ const INSTALLED_PLUGINS_PATH = path.join(
|
||||||
'node_modules'
|
'node_modules'
|
||||||
);
|
);
|
||||||
|
|
||||||
describe('NodeTracer', () => {
|
describe('NodeTracerRegistry', () => {
|
||||||
let tracer: NodeTracer;
|
let registry: NodeTracerRegistry;
|
||||||
before(() => {
|
before(() => {
|
||||||
module.paths.push(INSTALLED_PLUGINS_PATH);
|
module.paths.push(INSTALLED_PLUGINS_PATH);
|
||||||
});
|
});
|
||||||
|
@ -48,45 +48,45 @@ describe('NodeTracer', () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
// clear require cache
|
// clear require cache
|
||||||
Object.keys(require.cache).forEach(key => delete require.cache[key]);
|
Object.keys(require.cache).forEach(key => delete require.cache[key]);
|
||||||
tracer.stop();
|
registry.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
it('should construct an instance with required only options', () => {
|
it('should construct an instance with required only options', () => {
|
||||||
tracer = new NodeTracer();
|
registry = new NodeTracerRegistry();
|
||||||
assert.ok(tracer instanceof NodeTracer);
|
assert.ok(registry instanceof NodeTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with binary format', () => {
|
it('should construct an instance with binary format', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
binaryFormat: new BinaryTraceContext(),
|
binaryFormat: new BinaryTraceContext(),
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof NodeTracer);
|
assert.ok(registry instanceof NodeTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with http text format', () => {
|
it('should construct an instance with http text format', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
httpTextFormat: new HttpTraceContext(),
|
httpTextFormat: new HttpTraceContext(),
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof NodeTracer);
|
assert.ok(registry instanceof NodeTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with logger', () => {
|
it('should construct an instance with logger', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof NodeTracer);
|
assert.ok(registry instanceof NodeTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with sampler', () => {
|
it('should construct an instance with sampler', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
sampler: ALWAYS_SAMPLER,
|
sampler: ALWAYS_SAMPLER,
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof NodeTracer);
|
assert.ok(registry instanceof NodeTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load user configured plugins', () => {
|
it('should load user configured plugins', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
plugins: {
|
plugins: {
|
||||||
'simple-module': {
|
'simple-module': {
|
||||||
|
@ -102,7 +102,7 @@ describe('NodeTracer', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const pluginLoader = tracer['_pluginLoader'];
|
const pluginLoader = registry['_pluginLoader'];
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
require('simple-module');
|
require('simple-module');
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 1);
|
assert.strictEqual(pluginLoader['_plugins'].length, 1);
|
||||||
|
@ -111,39 +111,39 @@ describe('NodeTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with default attributes', () => {
|
it('should construct an instance with default attributes', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
defaultAttributes: {
|
defaultAttributes: {
|
||||||
region: 'eu-west',
|
region: 'eu-west',
|
||||||
asg: 'my-asg',
|
asg: 'my-asg',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof NodeTracer);
|
assert.ok(registry instanceof NodeTracerRegistry);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.startSpan()', () => {
|
describe('.startSpan()', () => {
|
||||||
it('should start a span with name only', () => {
|
it('should start a span with name only', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
});
|
||||||
const span = tracer.startSpan('my-span');
|
const span = registry.getTracer('default').startSpan('my-span');
|
||||||
assert.ok(span);
|
assert.ok(span);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with name and options', () => {
|
it('should start a span with name and options', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
});
|
||||||
const span = tracer.startSpan('my-span', {});
|
const span = registry.getTracer('default').startSpan('my-span', {});
|
||||||
assert.ok(span);
|
assert.ok(span);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a default span with no sampling', () => {
|
it('should return a default span with no sampling', () => {
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
sampler: NEVER_SAMPLER,
|
sampler: NEVER_SAMPLER,
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
});
|
||||||
const span = tracer.startSpan('my-span');
|
const span = registry.getTracer('default').startSpan('my-span');
|
||||||
assert.ok(span instanceof NoRecordingSpan);
|
assert.ok(span instanceof NoRecordingSpan);
|
||||||
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
||||||
assert.strictEqual(span.isRecording(), false);
|
assert.strictEqual(span.isRecording(), false);
|
||||||
|
@ -156,11 +156,11 @@ describe('NodeTracer', () => {
|
||||||
const defaultAttributes = {
|
const defaultAttributes = {
|
||||||
foo: 'bar',
|
foo: 'bar',
|
||||||
};
|
};
|
||||||
tracer = new NodeTracer({
|
registry = new NodeTracerRegistry({
|
||||||
defaultAttributes,
|
defaultAttributes,
|
||||||
});
|
});
|
||||||
|
|
||||||
const span = tracer.startSpan('my-span') as Span;
|
const span = registry.getTracer('default').startSpan('my-span') as Span;
|
||||||
assert.ok(span instanceof Span);
|
assert.ok(span instanceof Span);
|
||||||
assert.deepStrictEqual(span.attributes, defaultAttributes);
|
assert.deepStrictEqual(span.attributes, defaultAttributes);
|
||||||
});
|
});
|
||||||
|
@ -168,32 +168,48 @@ describe('NodeTracer', () => {
|
||||||
|
|
||||||
describe('.getCurrentSpan()', () => {
|
describe('.getCurrentSpan()', () => {
|
||||||
it('should return undefined with AsyncHooksScopeManager when no span started', () => {
|
it('should return undefined with AsyncHooksScopeManager when no span started', () => {
|
||||||
tracer = new NodeTracer({});
|
registry = new NodeTracerRegistry({});
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
undefined
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.withSpan()', () => {
|
describe('.withSpan()', () => {
|
||||||
it('should run scope with AsyncHooksScopeManager scope manager', done => {
|
it('should run scope with AsyncHooksScopeManager scope manager', done => {
|
||||||
tracer = new NodeTracer({});
|
registry = new NodeTracerRegistry({});
|
||||||
const span = tracer.startSpan('my-span');
|
const span = registry.getTracer('default').startSpan('my-span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
span
|
||||||
|
);
|
||||||
return done();
|
return done();
|
||||||
});
|
});
|
||||||
// @todo: below check is not running.
|
assert.deepStrictEqual(
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
undefined
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run scope with AsyncHooksScopeManager scope manager with multiple spans', done => {
|
it('should run scope with AsyncHooksScopeManager scope manager with multiple spans', done => {
|
||||||
tracer = new NodeTracer({});
|
registry = new NodeTracerRegistry({});
|
||||||
const span = tracer.startSpan('my-span');
|
const span = registry.getTracer('default').startSpan('my-span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
span
|
||||||
|
);
|
||||||
|
|
||||||
const span1 = tracer.startSpan('my-span1', { parent: span });
|
const span1 = registry
|
||||||
tracer.withSpan(span1, () => {
|
.getTracer('default')
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), span1);
|
.startSpan('my-span1', { parent: span });
|
||||||
|
registry.getTracer('default').withSpan(span1, () => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
span1
|
||||||
|
);
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
span1.context().traceId,
|
span1.context().traceId,
|
||||||
span.context().traceId
|
span.context().traceId
|
||||||
|
@ -203,48 +219,66 @@ describe('NodeTracer', () => {
|
||||||
});
|
});
|
||||||
// when span ended.
|
// when span ended.
|
||||||
// @todo: below check is not running.
|
// @todo: below check is not running.
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
undefined
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find correct scope with promises', done => {
|
it('should find correct scope with promises', done => {
|
||||||
tracer = new NodeTracer({});
|
registry = new NodeTracerRegistry({});
|
||||||
const span = tracer.startSpan('my-span');
|
const span = registry.getTracer('default').startSpan('my-span');
|
||||||
tracer.withSpan(span, async () => {
|
registry.getTracer('default').withSpan(span, async () => {
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
await sleep(5).then(() => {
|
await sleep(5).then(() => {
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
span
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return done();
|
return done();
|
||||||
});
|
});
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
undefined
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.bind()', () => {
|
describe('.bind()', () => {
|
||||||
it('should bind scope with AsyncHooksScopeManager scope manager', done => {
|
it('should bind scope with AsyncHooksScopeManager scope manager', done => {
|
||||||
const tracer = new NodeTracer({});
|
const registry = new NodeTracerRegistry({});
|
||||||
const span = tracer.startSpan('my-span');
|
const span = registry.getTracer('default').startSpan('my-span');
|
||||||
const fn = () => {
|
const fn = () => {
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
|
assert.deepStrictEqual(
|
||||||
|
registry.getTracer('default').getCurrentSpan(),
|
||||||
|
span
|
||||||
|
);
|
||||||
return done();
|
return done();
|
||||||
};
|
};
|
||||||
const patchedFn = tracer.bind(fn, span);
|
const patchedFn = registry.getTracer('default').bind(fn, span);
|
||||||
return patchedFn();
|
return patchedFn();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.getBinaryFormat()', () => {
|
describe('.getBinaryFormat()', () => {
|
||||||
it('should get default binary formatter', () => {
|
it('should get default binary formatter', () => {
|
||||||
tracer = new NodeTracer({});
|
registry = new NodeTracerRegistry({});
|
||||||
assert.ok(tracer.getBinaryFormat() instanceof BinaryTraceContext);
|
assert.ok(
|
||||||
|
registry.getTracer('default').getBinaryFormat() instanceof
|
||||||
|
BinaryTraceContext
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.getHttpTextFormat()', () => {
|
describe('.getHttpTextFormat()', () => {
|
||||||
it('should get default HTTP text formatter', () => {
|
it('should get default HTTP text formatter', () => {
|
||||||
tracer = new NodeTracer({});
|
registry = new NodeTracerRegistry({});
|
||||||
assert.ok(tracer.getHttpTextFormat() instanceof HttpTraceContext);
|
assert.ok(
|
||||||
|
registry.getTracer('default').getHttpTextFormat() instanceof
|
||||||
|
HttpTraceContext
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NoopLogger, NoopTracer } from '@opentelemetry/core';
|
import { NoopLogger, NoopTracerRegistry } from '@opentelemetry/core';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {
|
import {
|
||||||
HookState,
|
HookState,
|
||||||
PluginLoader,
|
PluginLoader,
|
||||||
searchPathForTest,
|
|
||||||
Plugins,
|
Plugins,
|
||||||
|
searchPathForTest,
|
||||||
} from '../../src/instrumentation/PluginLoader';
|
} from '../../src/instrumentation/PluginLoader';
|
||||||
|
|
||||||
const INSTALLED_PLUGINS_PATH = path.join(__dirname, 'node_modules');
|
const INSTALLED_PLUGINS_PATH = path.join(__dirname, 'node_modules');
|
||||||
|
@ -86,7 +86,7 @@ const notSupportedVersionPlugins: Plugins = {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('PluginLoader', () => {
|
describe('PluginLoader', () => {
|
||||||
const tracer = new NoopTracer();
|
const registry = new NoopTracerRegistry();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
|
@ -101,19 +101,19 @@ describe('PluginLoader', () => {
|
||||||
|
|
||||||
describe('.state()', () => {
|
describe('.state()', () => {
|
||||||
it('returns UNINITIALIZED when first called', () => {
|
it('returns UNINITIALIZED when first called', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_hookState'], HookState.UNINITIALIZED);
|
assert.strictEqual(pluginLoader['_hookState'], HookState.UNINITIALIZED);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('transitions from UNINITIALIZED to ENABLED', () => {
|
it('transitions from UNINITIALIZED to ENABLED', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
pluginLoader.load(simplePlugins);
|
pluginLoader.load(simplePlugins);
|
||||||
assert.strictEqual(pluginLoader['_hookState'], HookState.ENABLED);
|
assert.strictEqual(pluginLoader['_hookState'], HookState.ENABLED);
|
||||||
pluginLoader.unload();
|
pluginLoader.unload();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('transitions from ENABLED to DISABLED', () => {
|
it('transitions from ENABLED to DISABLED', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
pluginLoader.load(simplePlugins).unload();
|
pluginLoader.load(simplePlugins).unload();
|
||||||
assert.strictEqual(pluginLoader['_hookState'], HookState.DISABLED);
|
assert.strictEqual(pluginLoader['_hookState'], HookState.DISABLED);
|
||||||
});
|
});
|
||||||
|
@ -138,7 +138,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load a plugin and patch the target modules', () => {
|
it('should load a plugin and patch the target modules', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(simplePlugins);
|
pluginLoader.load(simplePlugins);
|
||||||
// The hook is only called the first time the module is loaded.
|
// The hook is only called the first time the module is loaded.
|
||||||
|
@ -150,7 +150,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load a plugin and patch the core module', () => {
|
it('should load a plugin and patch the core module', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(httpPlugins);
|
pluginLoader.load(httpPlugins);
|
||||||
// The hook is only called the first time the module is loaded.
|
// The hook is only called the first time the module is loaded.
|
||||||
|
@ -161,7 +161,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
// @TODO: simplify this test once we can load module with custom path
|
// @TODO: simplify this test once we can load module with custom path
|
||||||
it('should not load the plugin when supported versions does not match', () => {
|
it('should not load the plugin when supported versions does not match', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(notSupportedVersionPlugins);
|
pluginLoader.load(notSupportedVersionPlugins);
|
||||||
// The hook is only called the first time the module is loaded.
|
// The hook is only called the first time the module is loaded.
|
||||||
|
@ -171,7 +171,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
// @TODO: simplify this test once we can load module with custom path
|
// @TODO: simplify this test once we can load module with custom path
|
||||||
it('should load a plugin and patch the target modules when supported versions match', () => {
|
it('should load a plugin and patch the target modules when supported versions match', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(supportedVersionPlugins);
|
pluginLoader.load(supportedVersionPlugins);
|
||||||
// The hook is only called the first time the module is loaded.
|
// The hook is only called the first time the module is loaded.
|
||||||
|
@ -183,7 +183,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not load a plugin when value is false', () => {
|
it('should not load a plugin when value is false', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(disablePlugins);
|
pluginLoader.load(disablePlugins);
|
||||||
const simpleModule = require('simple-module');
|
const simpleModule = require('simple-module');
|
||||||
|
@ -194,7 +194,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not load a plugin when value is true but path is missing', () => {
|
it('should not load a plugin when value is true but path is missing', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(missingPathPlugins);
|
pluginLoader.load(missingPathPlugins);
|
||||||
const simpleModule = require('simple-module');
|
const simpleModule = require('simple-module');
|
||||||
|
@ -205,7 +205,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not load a non existing plugin', () => {
|
it('should not load a non existing plugin', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(nonexistentPlugins);
|
pluginLoader.load(nonexistentPlugins);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
|
@ -213,7 +213,7 @@ describe('PluginLoader', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`doesn't patch modules for which plugins aren't specified`, () => {
|
it(`doesn't patch modules for which plugins aren't specified`, () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
pluginLoader.load({});
|
pluginLoader.load({});
|
||||||
assert.strictEqual(require('simple-module').value(), 0);
|
assert.strictEqual(require('simple-module').value(), 0);
|
||||||
pluginLoader.unload();
|
pluginLoader.unload();
|
||||||
|
@ -222,7 +222,7 @@ describe('PluginLoader', () => {
|
||||||
|
|
||||||
describe('.unload()', () => {
|
describe('.unload()', () => {
|
||||||
it('should unload the plugins and unpatch the target module when unloads', () => {
|
it('should unload the plugins and unpatch the target module when unloads', () => {
|
||||||
const pluginLoader = new PluginLoader(tracer, logger);
|
const pluginLoader = new PluginLoader(registry, logger);
|
||||||
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
assert.strictEqual(pluginLoader['_plugins'].length, 0);
|
||||||
pluginLoader.load(simplePlugins);
|
pluginLoader.load(simplePlugins);
|
||||||
// The hook is only called the first time the module is loaded.
|
// The hook is only called the first time the module is loaded.
|
||||||
|
|
|
@ -18,9 +18,9 @@ npm install --save @opentelemetry/plugin-dns
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
dns: {
|
dns: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -37,7 +37,7 @@ const tracer = new NodeTracer({
|
||||||
If you use Zipkin, you must use `ignoreHostnames` in order to not trace those calls. If the server is local. You can set :
|
If you use Zipkin, you must use `ignoreHostnames` in order to not trace those calls. If the server is local. You can set :
|
||||||
|
|
||||||
```
|
```
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
dns: {
|
dns: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
|
@ -14,22 +14,23 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as shimmer from 'shimmer';
|
|
||||||
import * as semver from 'semver';
|
|
||||||
import * as utils from './utils';
|
|
||||||
import { BasePlugin } from '@opentelemetry/core';
|
import { BasePlugin } from '@opentelemetry/core';
|
||||||
import { SpanOptions, SpanKind, Span } from '@opentelemetry/types';
|
import { Span, SpanKind, SpanOptions } from '@opentelemetry/types';
|
||||||
|
import { LookupAddress } from 'dns';
|
||||||
|
import * as semver from 'semver';
|
||||||
|
import * as shimmer from 'shimmer';
|
||||||
|
import { AddressFamily } from './enums/AddressFamily';
|
||||||
|
import { AttributeNames } from './enums/AttributeNames';
|
||||||
import {
|
import {
|
||||||
Dns,
|
Dns,
|
||||||
LookupPromiseSignature,
|
DnsPluginConfig,
|
||||||
|
LookupCallbackSignature,
|
||||||
LookupFunction,
|
LookupFunction,
|
||||||
LookupFunctionSignature,
|
LookupFunctionSignature,
|
||||||
LookupCallbackSignature,
|
LookupPromiseSignature,
|
||||||
DnsPluginConfig,
|
|
||||||
} from './types';
|
} from './types';
|
||||||
import { AttributeNames } from './enums/AttributeNames';
|
import * as utils from './utils';
|
||||||
import { AddressFamily } from './enums/AddressFamily';
|
import { VERSION } from './version';
|
||||||
import { LookupAddress } from 'dns';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dns instrumentation plugin for Opentelemetry
|
* Dns instrumentation plugin for Opentelemetry
|
||||||
|
@ -39,7 +40,7 @@ export class DnsPlugin extends BasePlugin<Dns> {
|
||||||
protected _config!: DnsPluginConfig;
|
protected _config!: DnsPluginConfig;
|
||||||
|
|
||||||
constructor(readonly moduleName: string, readonly version: string) {
|
constructor(readonly moduleName: string, readonly version: string) {
|
||||||
super();
|
super('@opentelemetry/plugin-dns', VERSION);
|
||||||
// For now component is equal to moduleName but it can change in the future.
|
// For now component is equal to moduleName but it can change in the future.
|
||||||
this.component = this.moduleName;
|
this.component = this.moduleName;
|
||||||
this._config = {};
|
this._config = {};
|
||||||
|
|
|
@ -20,19 +20,20 @@ import {
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { plugin } from '../../src/dns';
|
import { plugin } from '../../src/dns';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
import * as dns from 'dns';
|
import * as dns from 'dns';
|
||||||
|
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({ logger });
|
const registry = new NodeTracerRegistry({ logger });
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
const tracer = registry.getTracer('default');
|
||||||
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
|
|
||||||
describe('DnsPlugin', () => {
|
describe('DnsPlugin', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
plugin.enable(dns, tracer, tracer.logger);
|
plugin.enable(dns, registry, tracer.logger);
|
||||||
assert.strictEqual(dns.lookup.__wrapped, true);
|
assert.strictEqual(dns.lookup.__wrapped, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,18 @@ import {
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { plugin, DnsPlugin } from '../../src/dns';
|
import { plugin, DnsPlugin } from '../../src/dns';
|
||||||
import * as dns from 'dns';
|
import * as dns from 'dns';
|
||||||
|
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({ logger });
|
const registry = new NodeTracerRegistry({ logger });
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
|
|
||||||
describe('DnsPlugin', () => {
|
describe('DnsPlugin', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
plugin.enable(dns, tracer, tracer.logger);
|
plugin.enable(dns, registry, registry.logger);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
|
import { BasicTracerRegistry, Span } from '@opentelemetry/tracing';
|
||||||
|
import { CanonicalCode, SpanKind } from '@opentelemetry/types';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
import { CanonicalCode, SpanKind } from '@opentelemetry/types';
|
import { AttributeNames } from '../../src/enums/AttributeNames';
|
||||||
import { IgnoreMatcher } from '../../src/types';
|
import { IgnoreMatcher } from '../../src/types';
|
||||||
import * as utils from '../../src/utils';
|
import * as utils from '../../src/utils';
|
||||||
import { Span, BasicTracer } from '@opentelemetry/tracing';
|
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
|
||||||
import { AttributeNames } from '../../src/enums/AttributeNames';
|
|
||||||
|
|
||||||
describe('Utility', () => {
|
describe('Utility', () => {
|
||||||
describe('parseResponseStatus()', () => {
|
describe('parseResponseStatus()', () => {
|
||||||
|
@ -162,7 +162,7 @@ describe('Utility', () => {
|
||||||
it('should have error attributes', () => {
|
it('should have error attributes', () => {
|
||||||
const errorMessage = 'test error';
|
const errorMessage = 'test error';
|
||||||
const span = new Span(
|
const span = new Span(
|
||||||
new BasicTracer(),
|
new BasicTracerRegistry().getTracer('default'),
|
||||||
'test',
|
'test',
|
||||||
{ spanId: '', traceId: '' },
|
{ spanId: '', traceId: '' },
|
||||||
SpanKind.INTERNAL
|
SpanKind.INTERNAL
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { plugin } from '../../src/dns';
|
import { plugin } from '../../src/dns';
|
||||||
import * as dns from 'dns';
|
import * as dns from 'dns';
|
||||||
import * as utils from '../utils/utils';
|
import * as utils from '../utils/utils';
|
||||||
|
@ -29,14 +29,14 @@ import { CanonicalCode } from '@opentelemetry/types';
|
||||||
|
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({ logger });
|
const registry = new NodeTracerRegistry({ logger });
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
|
|
||||||
describe('dns.lookup()', () => {
|
describe('dns.lookup()', () => {
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
// mandatory
|
// mandatory
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
plugin.enable(dns, tracer, tracer.logger);
|
plugin.enable(dns, registry, registry.logger);
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ describe('dns.lookup()', () => {
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
plugin.enable(dns, tracer, tracer.logger);
|
plugin.enable(dns, registry, registry.logger);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { plugin } from '../../src/dns';
|
import { plugin } from '../../src/dns';
|
||||||
import * as dns from 'dns';
|
import * as dns from 'dns';
|
||||||
import * as utils from '../utils/utils';
|
import * as utils from '../utils/utils';
|
||||||
|
@ -30,8 +30,8 @@ import { CanonicalCode } from '@opentelemetry/types';
|
||||||
|
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({ logger });
|
const registry = new NodeTracerRegistry({ logger });
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
|
|
||||||
describe('dns.promises.lookup()', () => {
|
describe('dns.promises.lookup()', () => {
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
|
@ -42,7 +42,7 @@ describe('dns.promises.lookup()', () => {
|
||||||
|
|
||||||
// if node version is supported, it's mandatory for CI
|
// if node version is supported, it's mandatory for CI
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
plugin.enable(dns, tracer, tracer.logger);
|
plugin.enable(dns, registry, registry.logger);
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ describe('dns.promises.lookup()', () => {
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
plugin.enable(dns, tracer, tracer.logger);
|
plugin.enable(dns, registry, registry.logger);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
|
@ -21,7 +21,6 @@ import {
|
||||||
TRACE_PARENT_HEADER,
|
TRACE_PARENT_HEADER,
|
||||||
} from '@opentelemetry/core';
|
} from '@opentelemetry/core';
|
||||||
import { PluginConfig, Span, SpanOptions } from '@opentelemetry/types';
|
import { PluginConfig, Span, SpanOptions } from '@opentelemetry/types';
|
||||||
import { AttributeNames } from './enums/AttributeNames';
|
|
||||||
import {
|
import {
|
||||||
addSpanNetworkEvent,
|
addSpanNetworkEvent,
|
||||||
hasKey,
|
hasKey,
|
||||||
|
@ -29,6 +28,8 @@ import {
|
||||||
PerformanceLegacy,
|
PerformanceLegacy,
|
||||||
PerformanceTimingNames as PTN,
|
PerformanceTimingNames as PTN,
|
||||||
} from '@opentelemetry/web';
|
} from '@opentelemetry/web';
|
||||||
|
import { AttributeNames } from './enums/AttributeNames';
|
||||||
|
import { VERSION } from './version';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a document load plugin
|
* This class represents a document load plugin
|
||||||
|
@ -44,7 +45,7 @@ export class DocumentLoad extends BasePlugin<unknown> {
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
constructor(config: PluginConfig = {}) {
|
constructor(config: PluginConfig = {}) {
|
||||||
super();
|
super('@opentelemetry/plugin-document-load', VERSION);
|
||||||
this._onDocumentLoaded = this._onDocumentLoaded.bind(this);
|
this._onDocumentLoaded = this._onDocumentLoaded.bind(this);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,16 @@
|
||||||
* Can't use Sinon Fake Time here as then cannot stub the performance getEntriesByType with desired metrics
|
* Can't use Sinon Fake Time here as then cannot stub the performance getEntriesByType with desired metrics
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as assert from 'assert';
|
|
||||||
import * as sinon from 'sinon';
|
|
||||||
|
|
||||||
import { ConsoleLogger, TRACE_PARENT_HEADER } from '@opentelemetry/core';
|
import { ConsoleLogger, TRACE_PARENT_HEADER } from '@opentelemetry/core';
|
||||||
import {
|
import {
|
||||||
BasicTracer,
|
BasicTracerRegistry,
|
||||||
ReadableSpan,
|
ReadableSpan,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
SpanExporter,
|
SpanExporter,
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import { Logger, PluginConfig, TimedEvent } from '@opentelemetry/types';
|
import { Logger, PluginConfig, TimedEvent } from '@opentelemetry/types';
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import * as sinon from 'sinon';
|
||||||
import { ExportResult } from '../../opentelemetry-base/build/src';
|
import { ExportResult } from '../../opentelemetry-base/build/src';
|
||||||
import { DocumentLoad } from '../src';
|
import { DocumentLoad } from '../src';
|
||||||
import { PerformanceTimingNames as PTN } from '@opentelemetry/web';
|
import { PerformanceTimingNames as PTN } from '@opentelemetry/web';
|
||||||
|
@ -193,7 +191,7 @@ function ensureNetworkEventsExists(events: TimedEvent[]) {
|
||||||
describe('DocumentLoad Plugin', () => {
|
describe('DocumentLoad Plugin', () => {
|
||||||
let plugin: DocumentLoad;
|
let plugin: DocumentLoad;
|
||||||
let moduleExports: any;
|
let moduleExports: any;
|
||||||
let tracer: BasicTracer;
|
let registry: BasicTracerRegistry;
|
||||||
let logger: Logger;
|
let logger: Logger;
|
||||||
let config: PluginConfig;
|
let config: PluginConfig;
|
||||||
let spanProcessor: SimpleSpanProcessor;
|
let spanProcessor: SimpleSpanProcessor;
|
||||||
|
@ -205,13 +203,13 @@ describe('DocumentLoad Plugin', () => {
|
||||||
value: 'complete',
|
value: 'complete',
|
||||||
});
|
});
|
||||||
moduleExports = {};
|
moduleExports = {};
|
||||||
tracer = new BasicTracer();
|
registry = new BasicTracerRegistry();
|
||||||
logger = new ConsoleLogger();
|
logger = new ConsoleLogger();
|
||||||
config = {};
|
config = {};
|
||||||
plugin = new DocumentLoad();
|
plugin = new DocumentLoad();
|
||||||
dummyExporter = new DummyExporter();
|
dummyExporter = new DummyExporter();
|
||||||
spanProcessor = new SimpleSpanProcessor(dummyExporter);
|
spanProcessor = new SimpleSpanProcessor(dummyExporter);
|
||||||
tracer.addSpanProcessor(spanProcessor);
|
registry.addSpanProcessor(spanProcessor);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -239,7 +237,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
spyEntries.restore();
|
spyEntries.restore();
|
||||||
});
|
});
|
||||||
it('should start collecting the performance immediately', done => {
|
it('should start collecting the performance immediately', done => {
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
assert.strictEqual(window.document.readyState, 'complete');
|
assert.strictEqual(window.document.readyState, 'complete');
|
||||||
assert.strictEqual(spyEntries.callCount, 2);
|
assert.strictEqual(spyEntries.callCount, 2);
|
||||||
|
@ -266,7 +264,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
it('should collect performance after document load event', done => {
|
it('should collect performance after document load event', done => {
|
||||||
const spy = sinon.spy(window, 'addEventListener');
|
const spy = sinon.spy(window, 'addEventListener');
|
||||||
|
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
const args = spy.args[0];
|
const args = spy.args[0];
|
||||||
const name = args[0];
|
const name = args[0];
|
||||||
assert.strictEqual(name, 'load');
|
assert.strictEqual(name, 'load');
|
||||||
|
@ -301,7 +299,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
|
|
||||||
it('should export correct span with events', done => {
|
it('should export correct span with events', done => {
|
||||||
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
||||||
|
@ -358,7 +356,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
|
|
||||||
it('should create a root span with server context traceId', done => {
|
it('should create a root span with server context traceId', done => {
|
||||||
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
||||||
const fetchSpan = spyOnEnd.args[1][0][0] as ReadableSpan;
|
const fetchSpan = spyOnEnd.args[1][0][0] as ReadableSpan;
|
||||||
|
@ -394,7 +392,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
|
|
||||||
it('should create span for each of the resource', done => {
|
it('should create span for each of the resource', done => {
|
||||||
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const spanResource1 = spyOnEnd.args[1][0][0] as ReadableSpan;
|
const spanResource1 = spyOnEnd.args[1][0][0] as ReadableSpan;
|
||||||
const spanResource2 = spyOnEnd.args[2][0][0] as ReadableSpan;
|
const spanResource2 = spyOnEnd.args[2][0][0] as ReadableSpan;
|
||||||
|
@ -432,7 +430,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
|
|
||||||
it('should create span for each of the resource', done => {
|
it('should create span for each of the resource', done => {
|
||||||
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const spanResource1 = spyOnEnd.args[1][0][0] as ReadableSpan;
|
const spanResource1 = spyOnEnd.args[1][0][0] as ReadableSpan;
|
||||||
|
|
||||||
|
@ -473,7 +471,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
|
|
||||||
it('should still export rootSpan and fetchSpan', done => {
|
it('should still export rootSpan and fetchSpan', done => {
|
||||||
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
||||||
|
@ -505,7 +503,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
|
|
||||||
it('should export correct span with events', done => {
|
it('should export correct span with events', done => {
|
||||||
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
|
||||||
const fetchSpan = spyOnEnd.args[1][0][0] as ReadableSpan;
|
const fetchSpan = spyOnEnd.args[1][0][0] as ReadableSpan;
|
||||||
|
@ -553,7 +551,7 @@ describe('DocumentLoad Plugin', () => {
|
||||||
|
|
||||||
it('should not create any span', done => {
|
it('should not create any span', done => {
|
||||||
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
const spyOnEnd = sinon.spy(dummyExporter, 'export');
|
||||||
plugin.enable(moduleExports, tracer, logger, config);
|
plugin.enable(moduleExports, registry, logger, config);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
assert.ok(spyOnEnd.callCount === 0);
|
assert.ok(spyOnEnd.callCount === 0);
|
||||||
done();
|
done();
|
||||||
|
|
|
@ -22,9 +22,9 @@ OpenTelemetry gRPC Instrumentation allows the user to automatically collect trac
|
||||||
|
|
||||||
To load a specific plugin (**gRPC** in this case), specify it in the Node Tracer's configuration.
|
To load a specific plugin (**gRPC** in this case), specify it in the Node Tracer's configuration.
|
||||||
```javascript
|
```javascript
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
grpc: {
|
grpc: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -37,9 +37,9 @@ const tracer = new NodeTracer({
|
||||||
|
|
||||||
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
||||||
```javascript
|
```javascript
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
```
|
```
|
||||||
|
|
||||||
See [examples/grpc](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/grpc) for a short example.
|
See [examples/grpc](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/grpc) for a short example.
|
||||||
|
|
|
@ -16,33 +16,33 @@
|
||||||
|
|
||||||
import { BasePlugin } from '@opentelemetry/core';
|
import { BasePlugin } from '@opentelemetry/core';
|
||||||
import {
|
import {
|
||||||
|
CanonicalCode,
|
||||||
|
Span,
|
||||||
|
SpanContext,
|
||||||
SpanKind,
|
SpanKind,
|
||||||
SpanOptions,
|
SpanOptions,
|
||||||
Span,
|
|
||||||
Status,
|
Status,
|
||||||
CanonicalCode,
|
|
||||||
SpanContext,
|
|
||||||
} from '@opentelemetry/types';
|
} from '@opentelemetry/types';
|
||||||
|
import * as events from 'events';
|
||||||
|
import * as grpcTypes from 'grpc';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as shimmer from 'shimmer';
|
||||||
import { AttributeNames } from './enums/AttributeNames';
|
import { AttributeNames } from './enums/AttributeNames';
|
||||||
import {
|
import {
|
||||||
grpc,
|
grpc,
|
||||||
ModuleExportsMapping,
|
|
||||||
GrpcPluginOptions,
|
|
||||||
ServerCallWithMeta,
|
|
||||||
SendUnaryDataCallback,
|
|
||||||
GrpcClientFunc,
|
GrpcClientFunc,
|
||||||
GrpcInternalClientTypes,
|
GrpcInternalClientTypes,
|
||||||
|
GrpcPluginOptions,
|
||||||
|
ModuleExportsMapping,
|
||||||
|
SendUnaryDataCallback,
|
||||||
|
ServerCallWithMeta,
|
||||||
} from './types';
|
} from './types';
|
||||||
import {
|
import {
|
||||||
findIndex,
|
findIndex,
|
||||||
_grpcStatusCodeToCanonicalCode,
|
_grpcStatusCodeToCanonicalCode,
|
||||||
_grpcStatusCodeToSpanStatus,
|
_grpcStatusCodeToSpanStatus,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
import { VERSION } from './version';
|
||||||
import * as events from 'events';
|
|
||||||
import * as grpcTypes from 'grpc';
|
|
||||||
import * as shimmer from 'shimmer';
|
|
||||||
import * as path from 'path';
|
|
||||||
|
|
||||||
/** The metadata key under which span context is stored as a binary value. */
|
/** The metadata key under which span context is stored as a binary value. */
|
||||||
export const GRPC_TRACE_KEY = 'grpc-trace-bin';
|
export const GRPC_TRACE_KEY = 'grpc-trace-bin';
|
||||||
|
@ -56,7 +56,7 @@ export class GrpcPlugin extends BasePlugin<grpc> {
|
||||||
protected _config!: GrpcPluginOptions;
|
protected _config!: GrpcPluginOptions;
|
||||||
|
|
||||||
constructor(readonly moduleName: string, readonly version: string) {
|
constructor(readonly moduleName: string, readonly version: string) {
|
||||||
super();
|
super('@opentelemetry/plugin-grpc', VERSION);
|
||||||
this._config = {};
|
this._config = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,22 +14,20 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NoopLogger, NoopTracer } from '@opentelemetry/core';
|
import { NoopLogger, NoopTracerRegistry } from '@opentelemetry/core';
|
||||||
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import { SpanKind, Tracer } from '@opentelemetry/types';
|
import { SpanKind } from '@opentelemetry/types';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import * as assert from 'assert';
|
||||||
|
import * as grpc from 'grpc';
|
||||||
import { assertSpan, assertPropagation } from './utils/assertionUtils';
|
import * as semver from 'semver';
|
||||||
|
import * as sinon from 'sinon';
|
||||||
import { GrpcPlugin, plugin } from '../src';
|
import { GrpcPlugin, plugin } from '../src';
|
||||||
import { SendUnaryDataCallback } from '../src/types';
|
import { SendUnaryDataCallback } from '../src/types';
|
||||||
|
import { assertPropagation, assertSpan } from './utils/assertionUtils';
|
||||||
import * as assert from 'assert';
|
|
||||||
import * as semver from 'semver';
|
|
||||||
import * as grpc from 'grpc';
|
|
||||||
import * as sinon from 'sinon';
|
|
||||||
|
|
||||||
const PROTO_PATH = __dirname + '/fixtures/grpc-test.proto';
|
const PROTO_PATH = __dirname + '/fixtures/grpc-test.proto';
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
|
@ -318,7 +316,7 @@ describe('GrpcPlugin', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should patch client constructor makeClientConstructor() and makeGenericClientConstructor()', () => {
|
it('should patch client constructor makeClientConstructor() and makeGenericClientConstructor()', () => {
|
||||||
plugin.enable(grpc, new NoopTracer(), new NoopLogger());
|
plugin.enable(grpc, new NoopTracerRegistry(), new NoopLogger());
|
||||||
(plugin['_moduleExports'] as any).makeGenericClientConstructor({});
|
(plugin['_moduleExports'] as any).makeGenericClientConstructor({});
|
||||||
assert.strictEqual(clientPatchStub.callCount, 1);
|
assert.strictEqual(clientPatchStub.callCount, 1);
|
||||||
});
|
});
|
||||||
|
@ -370,7 +368,7 @@ describe('GrpcPlugin', () => {
|
||||||
|
|
||||||
const runTest = (
|
const runTest = (
|
||||||
method: typeof methodList[0],
|
method: typeof methodList[0],
|
||||||
tracer: Tracer,
|
registry: NodeTracerRegistry,
|
||||||
checkSpans = true
|
checkSpans = true
|
||||||
) => {
|
) => {
|
||||||
it(`should ${
|
it(`should ${
|
||||||
|
@ -410,9 +408,11 @@ describe('GrpcPlugin', () => {
|
||||||
const expectEmpty = memoryExporter.getFinishedSpans();
|
const expectEmpty = memoryExporter.getFinishedSpans();
|
||||||
assert.strictEqual(expectEmpty.length, 0);
|
assert.strictEqual(expectEmpty.length, 0);
|
||||||
|
|
||||||
const span = tracer.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
|
const span = registry
|
||||||
return tracer.withSpan(span, async () => {
|
.getTracer('default')
|
||||||
const rootSpan = tracer.getCurrentSpan();
|
.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
|
||||||
|
return registry.getTracer('default').withSpan(span, async () => {
|
||||||
|
const rootSpan = registry.getTracer('default').getCurrentSpan();
|
||||||
if (!rootSpan) {
|
if (!rootSpan) {
|
||||||
assert.ok(false);
|
assert.ok(false);
|
||||||
return; // return so typechecking passes for rootSpan.end()
|
return; // return so typechecking passes for rootSpan.end()
|
||||||
|
@ -465,7 +465,7 @@ describe('GrpcPlugin', () => {
|
||||||
method: typeof methodList[0],
|
method: typeof methodList[0],
|
||||||
key: string,
|
key: string,
|
||||||
errorCode: number,
|
errorCode: number,
|
||||||
tracer: Tracer
|
registry: NodeTracerRegistry
|
||||||
) => {
|
) => {
|
||||||
it(`should raise an error for client/server rootSpans: method=${method.methodName}, status=${key}`, async () => {
|
it(`should raise an error for client/server rootSpans: method=${method.methodName}, status=${key}`, async () => {
|
||||||
const expectEmpty = memoryExporter.getFinishedSpans();
|
const expectEmpty = memoryExporter.getFinishedSpans();
|
||||||
|
@ -503,9 +503,11 @@ describe('GrpcPlugin', () => {
|
||||||
const expectEmpty = memoryExporter.getFinishedSpans();
|
const expectEmpty = memoryExporter.getFinishedSpans();
|
||||||
assert.strictEqual(expectEmpty.length, 0);
|
assert.strictEqual(expectEmpty.length, 0);
|
||||||
|
|
||||||
const span = tracer.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
|
const span = registry
|
||||||
return tracer.withSpan(span, async () => {
|
.getTracer('default')
|
||||||
const rootSpan = tracer.getCurrentSpan();
|
.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
|
||||||
|
return registry.getTracer('default').withSpan(span, async () => {
|
||||||
|
const rootSpan = registry.getTracer('default').getCurrentSpan();
|
||||||
if (!rootSpan) {
|
if (!rootSpan) {
|
||||||
assert.ok(false);
|
assert.ok(false);
|
||||||
return; // return so typechecking passes for rootSpan.end()
|
return; // return so typechecking passes for rootSpan.end()
|
||||||
|
@ -552,8 +554,8 @@ describe('GrpcPlugin', () => {
|
||||||
|
|
||||||
describe('enable()', () => {
|
describe('enable()', () => {
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({ logger });
|
const registry = new NodeTracerRegistry({ logger });
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memoryExporter.reset();
|
memoryExporter.reset();
|
||||||
});
|
});
|
||||||
|
@ -562,7 +564,7 @@ describe('GrpcPlugin', () => {
|
||||||
const config = {
|
const config = {
|
||||||
// TODO: add plugin options here once supported
|
// TODO: add plugin options here once supported
|
||||||
};
|
};
|
||||||
plugin.enable(grpc, tracer, logger, config);
|
plugin.enable(grpc, registry, logger, config);
|
||||||
|
|
||||||
const proto = grpc.load(PROTO_PATH).pkg_test;
|
const proto = grpc.load(PROTO_PATH).pkg_test;
|
||||||
server = startServer(grpc, proto);
|
server = startServer(grpc, proto);
|
||||||
|
@ -579,7 +581,7 @@ describe('GrpcPlugin', () => {
|
||||||
|
|
||||||
methodList.forEach(method => {
|
methodList.forEach(method => {
|
||||||
describe(`Test automatic tracing for grpc remote method ${method.description}`, () => {
|
describe(`Test automatic tracing for grpc remote method ${method.description}`, () => {
|
||||||
runTest(method, tracer);
|
runTest(method, registry);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -589,7 +591,7 @@ describe('GrpcPlugin', () => {
|
||||||
// tslint:disable-next-line:no-any
|
// tslint:disable-next-line:no-any
|
||||||
const errorCode = Number(grpc.status[statusKey as any]);
|
const errorCode = Number(grpc.status[statusKey as any]);
|
||||||
if (errorCode > grpc.status.OK) {
|
if (errorCode > grpc.status.OK) {
|
||||||
runErrorTest(method, statusKey, errorCode, tracer);
|
runErrorTest(method, statusKey, errorCode, registry);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -598,14 +600,14 @@ describe('GrpcPlugin', () => {
|
||||||
|
|
||||||
describe('disable()', () => {
|
describe('disable()', () => {
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({ logger });
|
const registry = new NodeTracerRegistry({ logger });
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memoryExporter.reset();
|
memoryExporter.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
plugin.enable(grpc, tracer, logger);
|
plugin.enable(grpc, registry, logger);
|
||||||
plugin.disable();
|
plugin.disable();
|
||||||
|
|
||||||
const proto = grpc.load(PROTO_PATH).pkg_test;
|
const proto = grpc.load(PROTO_PATH).pkg_test;
|
||||||
|
@ -622,7 +624,7 @@ describe('GrpcPlugin', () => {
|
||||||
|
|
||||||
methodList.map(method => {
|
methodList.map(method => {
|
||||||
describe(`Test automatic tracing for grpc remote method ${method.description}`, () => {
|
describe(`Test automatic tracing for grpc remote method ${method.description}`, () => {
|
||||||
runTest(method, tracer, false);
|
runTest(method, registry, false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,9 +22,9 @@ OpenTelemetry HTTP Instrumentation allows the user to automatically collect trac
|
||||||
|
|
||||||
To load a specific plugin (HTTP in this case), specify it in the Node Tracer's configuration.
|
To load a specific plugin (HTTP in this case), specify it in the Node Tracer's configuration.
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
http: {
|
http: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -38,9 +38,9 @@ const tracer = new NodeTracer({
|
||||||
|
|
||||||
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
```
|
```
|
||||||
|
|
||||||
See [examples/http](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/http) for a short example.
|
See [examples/http](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/http) for a short example.
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
|
|
||||||
import { BasePlugin, isValid } from '@opentelemetry/core';
|
import { BasePlugin, isValid } from '@opentelemetry/core';
|
||||||
import {
|
import {
|
||||||
|
CanonicalCode,
|
||||||
Span,
|
Span,
|
||||||
SpanKind,
|
SpanKind,
|
||||||
SpanOptions,
|
SpanOptions,
|
||||||
CanonicalCode,
|
|
||||||
Status,
|
Status,
|
||||||
} from '@opentelemetry/types';
|
} from '@opentelemetry/types';
|
||||||
import {
|
import {
|
||||||
|
@ -29,22 +29,23 @@ import {
|
||||||
RequestOptions,
|
RequestOptions,
|
||||||
ServerResponse,
|
ServerResponse,
|
||||||
} from 'http';
|
} from 'http';
|
||||||
|
import { Socket } from 'net';
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
import * as shimmer from 'shimmer';
|
import * as shimmer from 'shimmer';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import {
|
|
||||||
HttpPluginConfig,
|
|
||||||
Http,
|
|
||||||
Func,
|
|
||||||
ResponseEndArgs,
|
|
||||||
ParsedRequestOptions,
|
|
||||||
HttpRequestArgs,
|
|
||||||
Err,
|
|
||||||
} from './types';
|
|
||||||
import { Format } from './enums/Format';
|
|
||||||
import { AttributeNames } from './enums/AttributeNames';
|
import { AttributeNames } from './enums/AttributeNames';
|
||||||
|
import { Format } from './enums/Format';
|
||||||
|
import {
|
||||||
|
Err,
|
||||||
|
Func,
|
||||||
|
Http,
|
||||||
|
HttpPluginConfig,
|
||||||
|
HttpRequestArgs,
|
||||||
|
ParsedRequestOptions,
|
||||||
|
ResponseEndArgs,
|
||||||
|
} from './types';
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
import { Socket } from 'net';
|
import { VERSION } from './version';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Http instrumentation plugin for Opentelemetry
|
* Http instrumentation plugin for Opentelemetry
|
||||||
|
@ -56,7 +57,7 @@ export class HttpPlugin extends BasePlugin<Http> {
|
||||||
private readonly _spanNotEnded: WeakSet<Span>;
|
private readonly _spanNotEnded: WeakSet<Span>;
|
||||||
|
|
||||||
constructor(readonly moduleName: string, readonly version: string) {
|
constructor(readonly moduleName: string, readonly version: string) {
|
||||||
super();
|
super(`@opentelemetry/plugin-${moduleName}`, VERSION);
|
||||||
// For now component is equal to moduleName but it can change in the future.
|
// For now component is equal to moduleName but it can change in the future.
|
||||||
this.component = this.moduleName;
|
this.component = this.moduleName;
|
||||||
this._spanNotEnded = new WeakSet<Span>();
|
this._spanNotEnded = new WeakSet<Span>();
|
||||||
|
|
|
@ -20,10 +20,12 @@ import * as nock from 'nock';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
|
|
||||||
import { plugin } from '../../src/http';
|
import { plugin } from '../../src/http';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import {
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
NoopLogger,
|
||||||
|
NoopTracerRegistry,
|
||||||
|
noopTracer,
|
||||||
|
} from '@opentelemetry/core';
|
||||||
import { AddressInfo } from 'net';
|
import { AddressInfo } from 'net';
|
||||||
import { DummyPropagation } from '../utils/DummyPropagation';
|
|
||||||
import { httpRequest } from '../utils/httpRequest';
|
import { httpRequest } from '../utils/httpRequest';
|
||||||
|
|
||||||
describe('HttpPlugin', () => {
|
describe('HttpPlugin', () => {
|
||||||
|
@ -31,17 +33,13 @@ describe('HttpPlugin', () => {
|
||||||
let serverPort = 0;
|
let serverPort = 0;
|
||||||
|
|
||||||
describe('disable()', () => {
|
describe('disable()', () => {
|
||||||
const httpTextFormat = new DummyPropagation();
|
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({
|
const registry = new NoopTracerRegistry();
|
||||||
logger,
|
|
||||||
httpTextFormat,
|
|
||||||
});
|
|
||||||
before(() => {
|
before(() => {
|
||||||
nock.cleanAll();
|
nock.cleanAll();
|
||||||
nock.enableNetConnect();
|
nock.enableNetConnect();
|
||||||
|
|
||||||
plugin.enable(http, tracer, tracer.logger);
|
plugin.enable(http, registry, logger);
|
||||||
// Ensure that http module is patched.
|
// Ensure that http module is patched.
|
||||||
assert.strictEqual(http.Server.prototype.emit.__wrapped, true);
|
assert.strictEqual(http.Server.prototype.emit.__wrapped, true);
|
||||||
server = http.createServer((request, response) => {
|
server = http.createServer((request, response) => {
|
||||||
|
@ -55,8 +53,8 @@ describe('HttpPlugin', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tracer.startSpan = sinon.spy();
|
noopTracer.startSpan = sinon.spy();
|
||||||
tracer.withSpan = sinon.spy();
|
noopTracer.withSpan = sinon.spy();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -67,7 +65,7 @@ describe('HttpPlugin', () => {
|
||||||
server.close();
|
server.close();
|
||||||
});
|
});
|
||||||
describe('unpatch()', () => {
|
describe('unpatch()', () => {
|
||||||
it('should not call tracer methods for creating span', async () => {
|
it('should not call registry methods for creating span', async () => {
|
||||||
plugin.disable();
|
plugin.disable();
|
||||||
const testPath = '/incoming/unpatch/';
|
const testPath = '/incoming/unpatch/';
|
||||||
|
|
||||||
|
@ -75,12 +73,15 @@ describe('HttpPlugin', () => {
|
||||||
|
|
||||||
await httpRequest.get(options).then(result => {
|
await httpRequest.get(options).then(result => {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
(tracer.startSpan as sinon.SinonSpy).called,
|
(noopTracer.startSpan as sinon.SinonSpy).called,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.strictEqual(http.Server.prototype.emit.__wrapped, undefined);
|
assert.strictEqual(http.Server.prototype.emit.__wrapped, undefined);
|
||||||
assert.strictEqual((tracer.withSpan as sinon.SinonSpy).called, false);
|
assert.strictEqual(
|
||||||
|
(noopTracer.withSpan as sinon.SinonSpy).called,
|
||||||
|
false
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { CanonicalCode, Span as ISpan, SpanKind } from '@opentelemetry/types';
|
import { CanonicalCode, Span as ISpan, SpanKind } from '@opentelemetry/types';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
|
@ -45,11 +45,11 @@ const serverName = 'my.server.name';
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const httpTextFormat = new DummyPropagation();
|
const httpTextFormat = new DummyPropagation();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
httpTextFormat,
|
httpTextFormat,
|
||||||
});
|
});
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
|
|
||||||
function doNock(
|
function doNock(
|
||||||
hostname: string,
|
hostname: string,
|
||||||
|
@ -109,7 +109,7 @@ describe('HttpPlugin', () => {
|
||||||
plugin.component,
|
plugin.component,
|
||||||
process.versions.node
|
process.versions.node
|
||||||
);
|
);
|
||||||
pluginWithBadOptions.enable(http, tracer, tracer.logger, config);
|
pluginWithBadOptions.enable(http, registry, registry.logger, config);
|
||||||
server = http.createServer((request, response) => {
|
server = http.createServer((request, response) => {
|
||||||
response.end('Test Server Response');
|
response.end('Test Server Response');
|
||||||
});
|
});
|
||||||
|
@ -187,7 +187,7 @@ describe('HttpPlugin', () => {
|
||||||
applyCustomAttributesOnSpan: customAttributeFunction,
|
applyCustomAttributesOnSpan: customAttributeFunction,
|
||||||
serverName,
|
serverName,
|
||||||
};
|
};
|
||||||
plugin.enable(http, tracer, tracer.logger, config);
|
plugin.enable(http, registry, registry.logger, config);
|
||||||
server = http.createServer((request, response) => {
|
server = http.createServer((request, response) => {
|
||||||
response.end('Test Server Response');
|
response.end('Test Server Response');
|
||||||
});
|
});
|
||||||
|
@ -208,7 +208,7 @@ describe('HttpPlugin', () => {
|
||||||
const httpNotPatched = new HttpPlugin(
|
const httpNotPatched = new HttpPlugin(
|
||||||
plugin.component,
|
plugin.component,
|
||||||
process.versions.node
|
process.versions.node
|
||||||
).enable({} as Http, tracer, tracer.logger, {});
|
).enable({} as Http, registry, registry.logger, {});
|
||||||
assert.strictEqual(Object.keys(httpNotPatched).length, 0);
|
assert.strictEqual(Object.keys(httpNotPatched).length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -323,8 +323,8 @@ describe('HttpPlugin', () => {
|
||||||
const testPath = '/outgoing/rootSpan/childs/1';
|
const testPath = '/outgoing/rootSpan/childs/1';
|
||||||
doNock(hostname, testPath, 200, 'Ok');
|
doNock(hostname, testPath, 200, 'Ok');
|
||||||
const name = 'TestRootSpan';
|
const name = 'TestRootSpan';
|
||||||
const span = tracer.startSpan(name);
|
const span = registry.getTracer('default').startSpan(name);
|
||||||
return tracer.withSpan(span, async () => {
|
return registry.getTracer('default').withSpan(span, async () => {
|
||||||
const result = await httpRequest.get(
|
const result = await httpRequest.get(
|
||||||
`${protocol}://${hostname}${testPath}`
|
`${protocol}://${hostname}${testPath}`
|
||||||
);
|
);
|
||||||
|
@ -366,8 +366,8 @@ describe('HttpPlugin', () => {
|
||||||
httpErrorCodes[i].toString()
|
httpErrorCodes[i].toString()
|
||||||
);
|
);
|
||||||
const name = 'TestRootSpan';
|
const name = 'TestRootSpan';
|
||||||
const span = tracer.startSpan(name);
|
const span = registry.getTracer('default').startSpan(name);
|
||||||
return tracer.withSpan(span, async () => {
|
return registry.getTracer('default').withSpan(span, async () => {
|
||||||
const result = await httpRequest.get(
|
const result = await httpRequest.get(
|
||||||
`${protocol}://${hostname}${testPath}`
|
`${protocol}://${hostname}${testPath}`
|
||||||
);
|
);
|
||||||
|
@ -405,8 +405,8 @@ describe('HttpPlugin', () => {
|
||||||
const num = 5;
|
const num = 5;
|
||||||
doNock(hostname, testPath, 200, 'Ok', num);
|
doNock(hostname, testPath, 200, 'Ok', num);
|
||||||
const name = 'TestRootSpan';
|
const name = 'TestRootSpan';
|
||||||
const span = tracer.startSpan(name);
|
const span = registry.getTracer('default').startSpan(name);
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('default').withSpan(span, async () => {
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < num; i++) {
|
||||||
await httpRequest.get(`${protocol}://${hostname}${testPath}`);
|
await httpRequest.get(`${protocol}://${hostname}${testPath}`);
|
||||||
const spans = memoryExporter.getFinishedSpans();
|
const spans = memoryExporter.getFinishedSpans();
|
||||||
|
|
|
@ -28,7 +28,7 @@ import * as superagent from 'superagent';
|
||||||
import * as got from 'got';
|
import * as got from 'got';
|
||||||
import * as request from 'request-promise-native';
|
import * as request from 'request-promise-native';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
|
@ -45,11 +45,11 @@ describe('Packages', () => {
|
||||||
const httpTextFormat = new DummyPropagation();
|
const httpTextFormat = new DummyPropagation();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
httpTextFormat,
|
httpTextFormat,
|
||||||
});
|
});
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memoryExporter.reset();
|
memoryExporter.reset();
|
||||||
});
|
});
|
||||||
|
@ -58,7 +58,7 @@ describe('Packages', () => {
|
||||||
const config: HttpPluginConfig = {
|
const config: HttpPluginConfig = {
|
||||||
applyCustomAttributesOnSpan: customAttributeFunction,
|
applyCustomAttributesOnSpan: customAttributeFunction,
|
||||||
};
|
};
|
||||||
plugin.enable(http, tracer, tracer.logger, config);
|
plugin.enable(http, registry, registry.logger, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { NoopScopeManager } from '@opentelemetry/scope-base';
|
||||||
import { IgnoreMatcher } from '../../src/types';
|
import { IgnoreMatcher } from '../../src/types';
|
||||||
import * as utils from '../../src/utils';
|
import * as utils from '../../src/utils';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import { Span, BasicTracer } from '@opentelemetry/tracing';
|
import { Span, BasicTracerRegistry } from '@opentelemetry/tracing';
|
||||||
import { AttributeNames } from '../../src';
|
import { AttributeNames } from '../../src';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
|
|
||||||
|
@ -248,9 +248,9 @@ describe('Utility', () => {
|
||||||
const errorMessage = 'test error';
|
const errorMessage = 'test error';
|
||||||
for (const obj of [undefined, { statusCode: 400 }]) {
|
for (const obj of [undefined, { statusCode: 400 }]) {
|
||||||
const span = new Span(
|
const span = new Span(
|
||||||
new BasicTracer({
|
new BasicTracerRegistry({
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
}),
|
}).getTracer('default'),
|
||||||
'test',
|
'test',
|
||||||
{ spanId: '', traceId: '' },
|
{ spanId: '', traceId: '' },
|
||||||
SpanKind.INTERNAL
|
SpanKind.INTERNAL
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { DummyPropagation } from '../utils/DummyPropagation';
|
||||||
import { httpRequest } from '../utils/httpRequest';
|
import { httpRequest } from '../utils/httpRequest';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import * as utils from '../utils/utils';
|
import * as utils from '../utils/utils';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
|
@ -60,11 +60,11 @@ describe('HttpPlugin Integration tests', () => {
|
||||||
|
|
||||||
const httpTextFormat = new DummyPropagation();
|
const httpTextFormat = new DummyPropagation();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
httpTextFormat,
|
httpTextFormat,
|
||||||
});
|
});
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memoryExporter.reset();
|
memoryExporter.reset();
|
||||||
});
|
});
|
||||||
|
@ -83,7 +83,7 @@ describe('HttpPlugin Integration tests', () => {
|
||||||
try {
|
try {
|
||||||
plugin.disable();
|
plugin.disable();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
plugin.enable(http, tracer, tracer.logger, config);
|
plugin.enable(http, registry, registry.logger, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
|
|
@ -22,9 +22,9 @@ OpenTelemetry HTTPS Instrumentation allows the user to automatically collect tra
|
||||||
|
|
||||||
To load a specific plugin (HTTPS in this case), specify it in the Node Tracer's configuration.
|
To load a specific plugin (HTTPS in this case), specify it in the Node Tracer's configuration.
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
https: {
|
https: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -38,9 +38,9 @@ const tracer = new NodeTracer({
|
||||||
|
|
||||||
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
```
|
```
|
||||||
|
|
||||||
See [examples/https](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/https) for a short example.
|
See [examples/https](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/https) for a short example.
|
||||||
|
|
|
@ -14,19 +14,19 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
|
import { Http } from '@opentelemetry/plugin-http';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
|
import { AddressInfo } from 'net';
|
||||||
import * as nock from 'nock';
|
import * as nock from 'nock';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
|
|
||||||
import { plugin } from '../../src/https';
|
import { plugin } from '../../src/https';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
|
||||||
import { Http } from '@opentelemetry/plugin-http';
|
|
||||||
import { AddressInfo } from 'net';
|
|
||||||
import { DummyPropagation } from '../utils/DummyPropagation';
|
import { DummyPropagation } from '../utils/DummyPropagation';
|
||||||
import { httpsRequest } from '../utils/httpsRequest';
|
import { httpsRequest } from '../utils/httpsRequest';
|
||||||
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
|
import * as types from '@opentelemetry/types';
|
||||||
|
|
||||||
describe('HttpsPlugin', () => {
|
describe('HttpsPlugin', () => {
|
||||||
let server: https.Server;
|
let server: https.Server;
|
||||||
|
@ -35,15 +35,18 @@ describe('HttpsPlugin', () => {
|
||||||
describe('disable()', () => {
|
describe('disable()', () => {
|
||||||
const httpTextFormat = new DummyPropagation();
|
const httpTextFormat = new DummyPropagation();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
httpTextFormat,
|
httpTextFormat,
|
||||||
});
|
});
|
||||||
|
// const tracer = registry.getTracer('test-https')
|
||||||
|
let tracer: types.Tracer;
|
||||||
before(() => {
|
before(() => {
|
||||||
nock.cleanAll();
|
nock.cleanAll();
|
||||||
nock.enableNetConnect();
|
nock.enableNetConnect();
|
||||||
|
|
||||||
plugin.enable((https as unknown) as Http, tracer, tracer.logger);
|
plugin.enable((https as unknown) as Http, registry, registry.logger);
|
||||||
|
tracer = plugin['_tracer'];
|
||||||
// Ensure that https module is patched.
|
// Ensure that https module is patched.
|
||||||
assert.strictEqual(https.Server.prototype.emit.__wrapped, true);
|
assert.strictEqual(https.Server.prototype.emit.__wrapped, true);
|
||||||
server = https.createServer(
|
server = https.createServer(
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
Http,
|
Http,
|
||||||
HttpPluginConfig,
|
HttpPluginConfig,
|
||||||
|
@ -50,11 +50,12 @@ const pathname = '/test';
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const httpTextFormat = new DummyPropagation();
|
const httpTextFormat = new DummyPropagation();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
httpTextFormat,
|
httpTextFormat,
|
||||||
});
|
});
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
const tracer = registry.getTracer('test-https');
|
||||||
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
|
|
||||||
function doNock(
|
function doNock(
|
||||||
hostname: string,
|
hostname: string,
|
||||||
|
@ -113,7 +114,7 @@ describe('HttpsPlugin', () => {
|
||||||
pluginWithBadOptions = new HttpsPlugin(process.versions.node);
|
pluginWithBadOptions = new HttpsPlugin(process.versions.node);
|
||||||
pluginWithBadOptions.enable(
|
pluginWithBadOptions.enable(
|
||||||
(https as unknown) as Http,
|
(https as unknown) as Http,
|
||||||
tracer,
|
registry,
|
||||||
tracer.logger,
|
tracer.logger,
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
|
@ -202,7 +203,7 @@ describe('HttpsPlugin', () => {
|
||||||
};
|
};
|
||||||
plugin.enable(
|
plugin.enable(
|
||||||
(https as unknown) as Http,
|
(https as unknown) as Http,
|
||||||
tracer,
|
registry,
|
||||||
tracer.logger,
|
tracer.logger,
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
|
@ -231,7 +232,7 @@ describe('HttpsPlugin', () => {
|
||||||
it(`should not patch if it's not a ${protocol} module`, () => {
|
it(`should not patch if it's not a ${protocol} module`, () => {
|
||||||
const httpsNotPatched = new HttpsPlugin(process.versions.node).enable(
|
const httpsNotPatched = new HttpsPlugin(process.versions.node).enable(
|
||||||
{} as Http,
|
{} as Http,
|
||||||
tracer,
|
registry,
|
||||||
tracer.logger,
|
tracer.logger,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { SpanKind } from '@opentelemetry/types';
|
import { SpanKind, Span } from '@opentelemetry/types';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
|
@ -29,37 +29,35 @@ import * as superagent from 'superagent';
|
||||||
import * as got from 'got';
|
import * as got from 'got';
|
||||||
import * as request from 'request-promise-native';
|
import * as request from 'request-promise-native';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
|
import { Http } from '@opentelemetry/plugin-http';
|
||||||
import { Http, HttpPluginConfig } from '@opentelemetry/plugin-http';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { customAttributeFunction } from './https-enable.test';
|
|
||||||
|
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const protocol = 'https';
|
|
||||||
|
export const customAttributeFunction = (span: Span): void => {
|
||||||
|
span.setAttribute('span kind', SpanKind.CLIENT);
|
||||||
|
};
|
||||||
|
|
||||||
describe('Packages', () => {
|
describe('Packages', () => {
|
||||||
describe('get', () => {
|
describe('get', () => {
|
||||||
const httpTextFormat = new DummyPropagation();
|
const httpTextFormat = new DummyPropagation();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
httpTextFormat,
|
httpTextFormat,
|
||||||
});
|
});
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memoryExporter.reset();
|
memoryExporter.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
const config: HttpPluginConfig = {
|
plugin.enable((https as unknown) as Http, registry, registry.logger);
|
||||||
applyCustomAttributesOnSpan: customAttributeFunction,
|
|
||||||
};
|
|
||||||
plugin.enable((https as unknown) as Http, tracer, tracer.logger, config);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
@ -95,8 +93,8 @@ describe('Packages', () => {
|
||||||
// https://github.com/nock/nock/pull/1551
|
// https://github.com/nock/nock/pull/1551
|
||||||
// https://github.com/sindresorhus/got/commit/bf1aa5492ae2bc78cbbec6b7d764906fb156e6c2#diff-707a4781d57c42085155dcb27edb9ccbR258
|
// https://github.com/sindresorhus/got/commit/bf1aa5492ae2bc78cbbec6b7d764906fb156e6c2#diff-707a4781d57c42085155dcb27edb9ccbR258
|
||||||
// TODO: check if this is still the case when new version
|
// TODO: check if this is still the case when new version
|
||||||
`${protocol}://www.google.com`
|
'https://www.google.com'
|
||||||
: `${protocol}://www.google.com/search?q=axios&oq=axios&aqs=chrome.0.69i59l2j0l3j69i60.811j0j7&sourceid=chrome&ie=UTF-8`
|
: `https://www.google.com/search?q=axios&oq=axios&aqs=chrome.0.69i59l2j0l3j69i60.811j0j7&sourceid=chrome&ie=UTF-8`
|
||||||
);
|
);
|
||||||
const result = await httpPackage.get(urlparsed.href!);
|
const result = await httpPackage.get(urlparsed.href!);
|
||||||
if (!resHeaders) {
|
if (!resHeaders) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import { DummyPropagation } from '../utils/DummyPropagation';
|
||||||
import { httpsRequest } from '../utils/httpsRequest';
|
import { httpsRequest } from '../utils/httpsRequest';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import * as utils from '../utils/utils';
|
import * as utils from '../utils/utils';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
|
@ -65,11 +65,11 @@ describe('HttpsPlugin Integration tests', () => {
|
||||||
|
|
||||||
const httpTextFormat = new DummyPropagation();
|
const httpTextFormat = new DummyPropagation();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
logger,
|
logger,
|
||||||
httpTextFormat,
|
httpTextFormat,
|
||||||
});
|
});
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memoryExporter.reset();
|
memoryExporter.reset();
|
||||||
});
|
});
|
||||||
|
@ -88,7 +88,12 @@ describe('HttpsPlugin Integration tests', () => {
|
||||||
try {
|
try {
|
||||||
plugin.disable();
|
plugin.disable();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
plugin.enable((https as unknown) as Http, tracer, tracer.logger, config);
|
plugin.enable(
|
||||||
|
(https as unknown) as Http,
|
||||||
|
registry,
|
||||||
|
registry.logger,
|
||||||
|
config
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SpanKind, Status } from '@opentelemetry/types';
|
import { SpanKind } from '@opentelemetry/types';
|
||||||
import { hrTimeToNanoseconds } from '@opentelemetry/core';
|
import { hrTimeToNanoseconds } from '@opentelemetry/core';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
|
@ -36,7 +36,6 @@ export const assertSpan = (
|
||||||
pathname: string;
|
pathname: string;
|
||||||
reqHeaders?: http.OutgoingHttpHeaders;
|
reqHeaders?: http.OutgoingHttpHeaders;
|
||||||
path?: string | null;
|
path?: string | null;
|
||||||
forceStatus?: Status;
|
|
||||||
serverName?: string;
|
serverName?: string;
|
||||||
component: string;
|
component: string;
|
||||||
}
|
}
|
||||||
|
@ -68,13 +67,12 @@ export const assertSpan = (
|
||||||
span.attributes[AttributeNames.HTTP_STATUS_CODE],
|
span.attributes[AttributeNames.HTTP_STATUS_CODE],
|
||||||
validations.httpStatusCode
|
validations.httpStatusCode
|
||||||
);
|
);
|
||||||
|
assert.ok(span.endTime);
|
||||||
assert.strictEqual(span.links.length, 0);
|
assert.strictEqual(span.links.length, 0);
|
||||||
assert.strictEqual(span.events.length, 0);
|
assert.strictEqual(span.events.length, 0);
|
||||||
|
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
span.status,
|
span.status,
|
||||||
validations.forceStatus || parseResponseStatus(validations.httpStatusCode)
|
parseResponseStatus(validations.httpStatusCode)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.ok(span.endTime, 'must be finished');
|
assert.ok(span.endTime, 'must be finished');
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { BasePlugin } from '@opentelemetry/core';
|
||||||
import * as ioredisTypes from 'ioredis';
|
import * as ioredisTypes from 'ioredis';
|
||||||
import * as shimmer from 'shimmer';
|
import * as shimmer from 'shimmer';
|
||||||
import { traceConnection, traceSendCommand } from './utils';
|
import { traceConnection, traceSendCommand } from './utils';
|
||||||
|
import { VERSION } from './version';
|
||||||
|
|
||||||
export class IORedisPlugin extends BasePlugin<typeof ioredisTypes> {
|
export class IORedisPlugin extends BasePlugin<typeof ioredisTypes> {
|
||||||
static readonly COMPONENT = 'ioredis';
|
static readonly COMPONENT = 'ioredis';
|
||||||
|
@ -25,7 +26,7 @@ export class IORedisPlugin extends BasePlugin<typeof ioredisTypes> {
|
||||||
readonly supportedVersions = ['^2.0.0'];
|
readonly supportedVersions = ['^2.0.0'];
|
||||||
|
|
||||||
constructor(readonly moduleName: string) {
|
constructor(readonly moduleName: string) {
|
||||||
super();
|
super('@opentelemetry/plugin-ioredis', VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected patch(): typeof ioredisTypes {
|
protected patch(): typeof ioredisTypes {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { plugin, IORedisPlugin } from '../src';
|
import { plugin, IORedisPlugin } from '../src';
|
||||||
import * as ioredisTypes from 'ioredis';
|
import * as ioredisTypes from 'ioredis';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
|
@ -49,7 +49,7 @@ const okStatus: Status = {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('ioredis', () => {
|
describe('ioredis', () => {
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
let ioredis: typeof ioredisTypes;
|
let ioredis: typeof ioredisTypes;
|
||||||
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
|
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
|
||||||
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
|
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
|
||||||
|
@ -68,8 +68,8 @@ describe('ioredis', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
ioredis = require('ioredis');
|
ioredis = require('ioredis');
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
plugin.enable(ioredis, tracer, new NoopLogger());
|
plugin.enable(ioredis, registry, new NoopLogger());
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
@ -84,7 +84,7 @@ describe('ioredis', () => {
|
||||||
|
|
||||||
describe('#createClient()', () => {
|
describe('#createClient()', () => {
|
||||||
it('should propagate the current span to event handlers', done => {
|
it('should propagate the current span to event handlers', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
let client: ioredisTypes.Redis;
|
let client: ioredisTypes.Redis;
|
||||||
const attributes = {
|
const attributes = {
|
||||||
...DEFAULT_ATTRIBUTES,
|
...DEFAULT_ATTRIBUTES,
|
||||||
|
@ -93,7 +93,10 @@ describe('ioredis', () => {
|
||||||
const readyHandler = () => {
|
const readyHandler = () => {
|
||||||
const endedSpans = memoryExporter.getFinishedSpans();
|
const endedSpans = memoryExporter.getFinishedSpans();
|
||||||
|
|
||||||
assert.strictEqual(tracer.getCurrentSpan(), span);
|
assert.strictEqual(
|
||||||
|
registry.getTracer('ioredis-test').getCurrentSpan(),
|
||||||
|
span
|
||||||
|
);
|
||||||
assert.strictEqual(endedSpans.length, 2);
|
assert.strictEqual(endedSpans.length, 2);
|
||||||
assert.strictEqual(endedSpans[0].name, `connect`);
|
assert.strictEqual(endedSpans[0].name, `connect`);
|
||||||
assert.strictEqual(endedSpans[1].name, `info`);
|
assert.strictEqual(endedSpans[1].name, `info`);
|
||||||
|
@ -119,7 +122,7 @@ describe('ioredis', () => {
|
||||||
client.quit(done);
|
client.quit(done);
|
||||||
};
|
};
|
||||||
|
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('ioredis-test').withSpan(span, () => {
|
||||||
client = new ioredis(URL);
|
client = new ioredis(URL);
|
||||||
client.on('ready', readyHandler);
|
client.on('ready', readyHandler);
|
||||||
client.on('error', errorHandler);
|
client.on('error', errorHandler);
|
||||||
|
@ -183,8 +186,10 @@ describe('ioredis', () => {
|
||||||
' '
|
' '
|
||||||
)}`,
|
)}`,
|
||||||
};
|
};
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry
|
||||||
tracer.withSpan(span, () => {
|
.getTracer('ioredis-test')
|
||||||
|
.startSpan('test span');
|
||||||
|
registry.getTracer('ioredis-test').withSpan(span, () => {
|
||||||
command.method((err, _result) => {
|
command.method((err, _result) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 1);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 1);
|
||||||
|
@ -211,8 +216,8 @@ describe('ioredis', () => {
|
||||||
...DEFAULT_ATTRIBUTES,
|
...DEFAULT_ATTRIBUTES,
|
||||||
[AttributeNames.DB_STATEMENT]: 'hset hash random random',
|
[AttributeNames.DB_STATEMENT]: 'hset hash random random',
|
||||||
};
|
};
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('ioredis-test').withSpan(span, async () => {
|
||||||
try {
|
try {
|
||||||
await client.hset('hash', 'random', 'random');
|
await client.hset('hash', 'random', 'random');
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 1);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 1);
|
||||||
|
@ -239,8 +244,8 @@ describe('ioredis', () => {
|
||||||
...DEFAULT_ATTRIBUTES,
|
...DEFAULT_ATTRIBUTES,
|
||||||
[AttributeNames.DB_STATEMENT]: 'scan 0',
|
[AttributeNames.DB_STATEMENT]: 'scan 0',
|
||||||
};
|
};
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('ioredis-test').withSpan(span, () => {
|
||||||
const stream = client.scanStream();
|
const stream = client.scanStream();
|
||||||
stream
|
stream
|
||||||
.on('data', resultKeys => {
|
.on('data', resultKeys => {
|
||||||
|
@ -275,8 +280,8 @@ describe('ioredis', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a child span for pubsub', async () => {
|
it('should create a child span for pubsub', async () => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('ioredis-test').withSpan(span, async () => {
|
||||||
try {
|
try {
|
||||||
const pub = new ioredis(URL);
|
const pub = new ioredis(URL);
|
||||||
const sub = new ioredis(URL);
|
const sub = new ioredis(URL);
|
||||||
|
@ -334,8 +339,8 @@ describe('ioredis', () => {
|
||||||
[AttributeNames.DB_STATEMENT]: 'eval return {KEYS[1],ARGV[1]} 1 test',
|
[AttributeNames.DB_STATEMENT]: 'eval return {KEYS[1],ARGV[1]} 1 test',
|
||||||
};
|
};
|
||||||
|
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('ioredis-test').withSpan(span, () => {
|
||||||
// This will define a command echo:
|
// This will define a command echo:
|
||||||
client.defineCommand('echo', {
|
client.defineCommand('echo', {
|
||||||
numberOfKeys: 1,
|
numberOfKeys: 1,
|
||||||
|
@ -372,8 +377,8 @@ describe('ioredis', () => {
|
||||||
[AttributeNames.DB_STATEMENT]: 'multi',
|
[AttributeNames.DB_STATEMENT]: 'multi',
|
||||||
};
|
};
|
||||||
|
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('ioredis-test').withSpan(span, () => {
|
||||||
client
|
client
|
||||||
.multi()
|
.multi()
|
||||||
.set('foo', 'bar')
|
.set('foo', 'bar')
|
||||||
|
@ -408,8 +413,8 @@ describe('ioredis', () => {
|
||||||
[AttributeNames.DB_STATEMENT]: 'set foo bar',
|
[AttributeNames.DB_STATEMENT]: 'set foo bar',
|
||||||
};
|
};
|
||||||
|
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('ioredis-test').withSpan(span, () => {
|
||||||
const pipeline = client.pipeline();
|
const pipeline = client.pipeline();
|
||||||
pipeline.set('foo', 'bar');
|
pipeline.set('foo', 'bar');
|
||||||
pipeline.del('cc');
|
pipeline.del('cc');
|
||||||
|
@ -441,8 +446,8 @@ describe('ioredis', () => {
|
||||||
...DEFAULT_ATTRIBUTES,
|
...DEFAULT_ATTRIBUTES,
|
||||||
[AttributeNames.DB_STATEMENT]: 'get test',
|
[AttributeNames.DB_STATEMENT]: 'get test',
|
||||||
};
|
};
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('ioredis-test').withSpan(span, async () => {
|
||||||
try {
|
try {
|
||||||
const value = await client.get('test');
|
const value = await client.get('test');
|
||||||
assert.strictEqual(value, 'data');
|
assert.strictEqual(value, 'data');
|
||||||
|
@ -470,8 +475,8 @@ describe('ioredis', () => {
|
||||||
...DEFAULT_ATTRIBUTES,
|
...DEFAULT_ATTRIBUTES,
|
||||||
[AttributeNames.DB_STATEMENT]: 'del test',
|
[AttributeNames.DB_STATEMENT]: 'del test',
|
||||||
};
|
};
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('ioredis-test').withSpan(span, async () => {
|
||||||
try {
|
try {
|
||||||
const result = await client.del('test');
|
const result = await client.del('test');
|
||||||
assert.strictEqual(result, 1);
|
assert.strictEqual(result, 1);
|
||||||
|
@ -502,8 +507,10 @@ describe('ioredis', () => {
|
||||||
|
|
||||||
IOREDIS_CALLBACK_OPERATIONS.forEach(operation => {
|
IOREDIS_CALLBACK_OPERATIONS.forEach(operation => {
|
||||||
it(`should not create a child span for cb style ${operation.description}`, done => {
|
it(`should not create a child span for cb style ${operation.description}`, done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry
|
||||||
tracer.withSpan(span, () => {
|
.getTracer('ioredis-test')
|
||||||
|
.startSpan('test span');
|
||||||
|
registry.getTracer('ioredis-test').withSpan(span, () => {
|
||||||
operation.method((err, _) => {
|
operation.method((err, _) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
||||||
|
@ -518,8 +525,8 @@ describe('ioredis', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create a child span for hset promise upon error', async () => {
|
it('should not create a child span for hset promise upon error', async () => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('ioredis-test').startSpan('test span');
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('ioredis-test').withSpan(span, async () => {
|
||||||
try {
|
try {
|
||||||
await client.hset('hash', 'random', 'random');
|
await client.hset('hash', 'random', 'random');
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
||||||
|
|
|
@ -23,9 +23,9 @@ OpenTelemetry Mongodb Instrumentation allows the user to automatically collect t
|
||||||
|
|
||||||
To load a specific plugin (mongodb in this case), specify it in the Node Tracer's configuration.
|
To load a specific plugin (mongodb in this case), specify it in the Node Tracer's configuration.
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
mongodb: {
|
mongodb: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -38,9 +38,9 @@ const tracer = new NodeTracer({
|
||||||
|
|
||||||
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
```
|
```
|
||||||
|
|
||||||
See [examples/mongodb](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/mongodb) for a short example.
|
See [examples/mongodb](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/mongodb) for a short example.
|
||||||
|
|
|
@ -18,16 +18,17 @@
|
||||||
/* tslint:disable:deprecation */
|
/* tslint:disable:deprecation */
|
||||||
|
|
||||||
import { BasePlugin } from '@opentelemetry/core';
|
import { BasePlugin } from '@opentelemetry/core';
|
||||||
import { Span, SpanKind, CanonicalCode } from '@opentelemetry/types';
|
import { CanonicalCode, Span, SpanKind } from '@opentelemetry/types';
|
||||||
import {
|
|
||||||
Func,
|
|
||||||
MongoInternalCommand,
|
|
||||||
MongoInternalTopology,
|
|
||||||
AttributeNames,
|
|
||||||
MongodbCommandType,
|
|
||||||
} from './types';
|
|
||||||
import * as mongodb from 'mongodb';
|
import * as mongodb from 'mongodb';
|
||||||
import * as shimmer from 'shimmer';
|
import * as shimmer from 'shimmer';
|
||||||
|
import {
|
||||||
|
AttributeNames,
|
||||||
|
Func,
|
||||||
|
MongodbCommandType,
|
||||||
|
MongoInternalCommand,
|
||||||
|
MongoInternalTopology,
|
||||||
|
} from './types';
|
||||||
|
import { VERSION } from './version';
|
||||||
|
|
||||||
/** MongoDBCore instrumentation plugin for OpenTelemetry */
|
/** MongoDBCore instrumentation plugin for OpenTelemetry */
|
||||||
export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
|
export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
|
||||||
|
@ -40,7 +41,7 @@ export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
|
||||||
readonly supportedVersions = ['>=2 <4'];
|
readonly supportedVersions = ['>=2 <4'];
|
||||||
|
|
||||||
constructor(readonly moduleName: string) {
|
constructor(readonly moduleName: string) {
|
||||||
super();
|
super('@opentelemetry/plugin-mongodb-core', VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,7 +107,7 @@ export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
|
||||||
const resultHandler =
|
const resultHandler =
|
||||||
typeof options === 'function' ? options : callback;
|
typeof options === 'function' ? options : callback;
|
||||||
if (
|
if (
|
||||||
currentSpan === undefined ||
|
!currentSpan ||
|
||||||
typeof resultHandler !== 'function' ||
|
typeof resultHandler !== 'function' ||
|
||||||
typeof commands !== 'object'
|
typeof commands !== 'object'
|
||||||
) {
|
) {
|
||||||
|
@ -210,7 +211,7 @@ export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
|
||||||
): mongodb.Cursor {
|
): mongodb.Cursor {
|
||||||
const currentSpan = plugin._tracer.getCurrentSpan();
|
const currentSpan = plugin._tracer.getCurrentSpan();
|
||||||
const resultHandler = args[0];
|
const resultHandler = args[0];
|
||||||
if (currentSpan === undefined || typeof resultHandler !== 'function') {
|
if (!currentSpan || typeof resultHandler !== 'function') {
|
||||||
return original.apply(this, args);
|
return original.apply(this, args);
|
||||||
}
|
}
|
||||||
const span = plugin._tracer.startSpan(`mongodb.query`, {
|
const span = plugin._tracer.startSpan(`mongodb.query`, {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as mongodb from 'mongodb';
|
import * as mongodb from 'mongodb';
|
||||||
import { plugin } from '../src';
|
import { plugin } from '../src';
|
||||||
|
@ -65,8 +65,12 @@ function accessCollection(
|
||||||
function assertSpans(
|
function assertSpans(
|
||||||
spans: ReadableSpan[],
|
spans: ReadableSpan[],
|
||||||
expectedName: string,
|
expectedName: string,
|
||||||
expectedKind: SpanKind
|
expectedKind: SpanKind,
|
||||||
|
log = false
|
||||||
) {
|
) {
|
||||||
|
if (log) {
|
||||||
|
console.log(spans);
|
||||||
|
}
|
||||||
assert.strictEqual(spans.length, 2);
|
assert.strictEqual(spans.length, 2);
|
||||||
spans.forEach(span => {
|
spans.forEach(span => {
|
||||||
assert(span.endTime instanceof Array);
|
assert(span.endTime instanceof Array);
|
||||||
|
@ -75,10 +79,7 @@ function assertSpans(
|
||||||
const [mongoSpan] = spans;
|
const [mongoSpan] = spans;
|
||||||
assert.strictEqual(mongoSpan.name, expectedName);
|
assert.strictEqual(mongoSpan.name, expectedName);
|
||||||
assert.strictEqual(mongoSpan.kind, expectedKind);
|
assert.strictEqual(mongoSpan.kind, expectedKind);
|
||||||
assert.strictEqual(
|
assert.strictEqual(mongoSpan.attributes[AttributeNames.COMPONENT], 'mongodb');
|
||||||
mongoSpan.attributes[AttributeNames.COMPONENT],
|
|
||||||
'mongodb'
|
|
||||||
);
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
mongoSpan.attributes[AttributeNames.PEER_HOSTNAME],
|
mongoSpan.attributes[AttributeNames.PEER_HOSTNAME],
|
||||||
process.env.MONGODB_HOST || 'localhost'
|
process.env.MONGODB_HOST || 'localhost'
|
||||||
|
@ -104,12 +105,13 @@ describe('MongoDBPlugin', () => {
|
||||||
let client: mongodb.MongoClient;
|
let client: mongodb.MongoClient;
|
||||||
let collection: mongodb.Collection;
|
let collection: mongodb.Collection;
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
const spanProcessor = new SimpleSpanProcessor(memoryExporter);
|
||||||
|
registry.addSpanProcessor(spanProcessor);
|
||||||
|
|
||||||
before(done => {
|
before(done => {
|
||||||
plugin.enable(mongodb, tracer, logger);
|
plugin.enable(mongodb, registry, logger);
|
||||||
accessCollection(URL, DB_NAME, COLLECTION_NAME)
|
accessCollection(URL, DB_NAME, COLLECTION_NAME)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
client = result.client;
|
client = result.client;
|
||||||
|
@ -155,8 +157,8 @@ describe('MongoDBPlugin', () => {
|
||||||
it('should create a child span for insert', done => {
|
it('should create a child span for insert', done => {
|
||||||
const insertData = [{ a: 1 }, { a: 2 }, { a: 3 }];
|
const insertData = [{ a: 1 }, { a: 2 }, { a: 3 }];
|
||||||
|
|
||||||
const span = tracer.startSpan(`insertRootSpan`);
|
const span = registry.getTracer('default').startSpan(`insertRootSpan`);
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
collection.insertMany(insertData, (err, result) => {
|
collection.insertMany(insertData, (err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -171,8 +173,8 @@ describe('MongoDBPlugin', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a child span for update', done => {
|
it('should create a child span for update', done => {
|
||||||
const span = tracer.startSpan('updateRootSpan');
|
const span = registry.getTracer('default').startSpan('updateRootSpan');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
collection.updateOne({ a: 2 }, { $set: { b: 1 } }, (err, result) => {
|
collection.updateOne({ a: 2 }, { $set: { b: 1 } }, (err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -187,8 +189,8 @@ describe('MongoDBPlugin', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a child span for remove', done => {
|
it('should create a child span for remove', done => {
|
||||||
const span = tracer.startSpan('removeRootSpan');
|
const span = registry.getTracer('default').startSpan('removeRootSpan');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
collection.deleteOne({ a: 3 }, (err, result) => {
|
collection.deleteOne({ a: 3 }, (err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -206,8 +208,8 @@ describe('MongoDBPlugin', () => {
|
||||||
/** Should intercept cursor */
|
/** Should intercept cursor */
|
||||||
describe('Instrumenting cursor operations', () => {
|
describe('Instrumenting cursor operations', () => {
|
||||||
it('should create a child span for find', done => {
|
it('should create a child span for find', done => {
|
||||||
const span = tracer.startSpan('findRootSpan');
|
const span = registry.getTracer('default').startSpan('findRootSpan');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
collection.find({}).toArray((err, result) => {
|
collection.find({}).toArray((err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -225,8 +227,8 @@ describe('MongoDBPlugin', () => {
|
||||||
/** Should intercept command */
|
/** Should intercept command */
|
||||||
describe('Instrumenting command operations', () => {
|
describe('Instrumenting command operations', () => {
|
||||||
it('should create a child span for create index', done => {
|
it('should create a child span for create index', done => {
|
||||||
const span = tracer.startSpan('indexRootSpan');
|
const span = registry.getTracer('default').startSpan('indexRootSpan');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
collection.createIndex({ a: 1 }, (err, result) => {
|
collection.createIndex({ a: 1 }, (err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -252,7 +254,7 @@ describe('MongoDBPlugin', () => {
|
||||||
it('should not create a child span for query', done => {
|
it('should not create a child span for query', done => {
|
||||||
const insertData = [{ a: 1 }, { a: 2 }, { a: 3 }];
|
const insertData = [{ a: 1 }, { a: 2 }, { a: 3 }];
|
||||||
|
|
||||||
const span = tracer.startSpan('insertRootSpan');
|
const span = registry.getTracer('default').startSpan('insertRootSpan');
|
||||||
collection.insertMany(insertData, (err, result) => {
|
collection.insertMany(insertData, (err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -262,7 +264,7 @@ describe('MongoDBPlugin', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create a child span for cursor', done => {
|
it('should not create a child span for cursor', done => {
|
||||||
const span = tracer.startSpan('findRootSpan');
|
const span = registry.getTracer('default').startSpan('findRootSpan');
|
||||||
collection.find({}).toArray((err, result) => {
|
collection.find({}).toArray((err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -272,7 +274,7 @@ describe('MongoDBPlugin', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create a child span for command', done => {
|
it('should not create a child span for command', done => {
|
||||||
const span = tracer.startSpan('indexRootSpan');
|
const span = registry.getTracer('default').startSpan('indexRootSpan');
|
||||||
collection.createIndex({ a: 1 }, (err, result) => {
|
collection.createIndex({ a: 1 }, (err, result) => {
|
||||||
span.end();
|
span.end();
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"outDir": "build"
|
"outDir": "build"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts"
|
"src/**/*.ts",
|
||||||
|
"test/**/*.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import * as mysqlTypes from 'mysql';
|
||||||
import * as shimmer from 'shimmer';
|
import * as shimmer from 'shimmer';
|
||||||
import { AttributeNames } from './enums';
|
import { AttributeNames } from './enums';
|
||||||
import { getConnectionAttributes, getSpanName } from './utils';
|
import { getConnectionAttributes, getSpanName } from './utils';
|
||||||
|
import { VERSION } from './version';
|
||||||
|
|
||||||
export class MysqlPlugin extends BasePlugin<typeof mysqlTypes> {
|
export class MysqlPlugin extends BasePlugin<typeof mysqlTypes> {
|
||||||
readonly moduleName = 'mysql';
|
|
||||||
readonly supportedVersions = ['2.*'];
|
readonly supportedVersions = ['2.*'];
|
||||||
|
|
||||||
static readonly COMPONENT = 'mysql';
|
static readonly COMPONENT = 'mysql';
|
||||||
|
@ -36,6 +36,10 @@ export class MysqlPlugin extends BasePlugin<typeof mysqlTypes> {
|
||||||
|
|
||||||
private _enabled = false;
|
private _enabled = false;
|
||||||
|
|
||||||
|
constructor(readonly moduleName: string) {
|
||||||
|
super('@opentelemetry/plugin-mysql', VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
protected patch(): typeof mysqlTypes {
|
protected patch(): typeof mysqlTypes {
|
||||||
this._enabled = true;
|
this._enabled = true;
|
||||||
shimmer.wrap(
|
shimmer.wrap(
|
||||||
|
@ -283,4 +287,4 @@ export class MysqlPlugin extends BasePlugin<typeof mysqlTypes> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const plugin = new MysqlPlugin();
|
export const plugin = new MysqlPlugin(MysqlPlugin.COMPONENT);
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
|
@ -38,7 +38,7 @@ describe('mysql@2.x', () => {
|
||||||
let connection: mysql.Connection;
|
let connection: mysql.Connection;
|
||||||
let pool: mysql.Pool;
|
let pool: mysql.Pool;
|
||||||
let poolCluster: mysql.PoolCluster;
|
let poolCluster: mysql.PoolCluster;
|
||||||
const tracer = new NodeTracer({ plugins: {} });
|
const registry = new NodeTracerRegistry({ plugins: {} });
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const testMysql = process.env.RUN_MYSQL_TESTS; // For CI: assumes local mysql db is already available
|
const testMysql = process.env.RUN_MYSQL_TESTS; // For CI: assumes local mysql db is already available
|
||||||
const testMysqlLocally = process.env.RUN_MYSQL_TESTS_LOCAL; // For local: spins up local mysql db via docker
|
const testMysqlLocally = process.env.RUN_MYSQL_TESTS_LOCAL; // For local: spins up local mysql db via docker
|
||||||
|
@ -52,7 +52,7 @@ describe('mysql@2.x', () => {
|
||||||
this.test!.parent!.pending = true;
|
this.test!.parent!.pending = true;
|
||||||
this.skip();
|
this.skip();
|
||||||
}
|
}
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
if (testMysqlLocally) {
|
if (testMysqlLocally) {
|
||||||
testUtils.startDocker('mysql');
|
testUtils.startDocker('mysql');
|
||||||
// wait 15 seconds for docker container to start
|
// wait 15 seconds for docker container to start
|
||||||
|
@ -71,7 +71,7 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
plugin.enable(mysql, tracer, logger);
|
plugin.enable(mysql, registry, logger);
|
||||||
connection = mysql.createConnection({
|
connection = mysql.createConnection({
|
||||||
port,
|
port,
|
||||||
user,
|
user,
|
||||||
|
@ -118,8 +118,8 @@ describe('mysql@2.x', () => {
|
||||||
|
|
||||||
describe('#Connection', () => {
|
describe('#Connection', () => {
|
||||||
it('should intercept connection.query(text: string)', done => {
|
it('should intercept connection.query(text: string)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
const query = connection.query(statement);
|
const query = connection.query(statement);
|
||||||
let rows = 0;
|
let rows = 0;
|
||||||
|
@ -140,8 +140,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept connection.query(text: string, callback)', done => {
|
it('should intercept connection.query(text: string, callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
connection.query(statement, (err, res) => {
|
connection.query(statement, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -156,8 +156,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept connection.query(text: options, callback)', done => {
|
it('should intercept connection.query(text: options, callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+? as solution';
|
const statement = 'SELECT 1+? as solution';
|
||||||
connection.query({ sql: statement, values: [1] }, (err, res) => {
|
connection.query({ sql: statement, values: [1] }, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -172,8 +172,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept connection.query(text: options, values: [], callback)', done => {
|
it('should intercept connection.query(text: options, values: [], callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+? as solution';
|
const statement = 'SELECT 1+? as solution';
|
||||||
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
|
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
|
||||||
// but does not match the typings
|
// but does not match the typings
|
||||||
|
@ -190,8 +190,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept connection.query(text: string, values: [], callback)', done => {
|
it('should intercept connection.query(text: string, values: [], callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
connection.query(statement, [1], (err, res) => {
|
connection.query(statement, [1], (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -206,8 +206,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept connection.query(text: string, value: any, callback)', done => {
|
it('should intercept connection.query(text: string, value: any, callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
connection.query(statement, 1, (err, res) => {
|
connection.query(statement, 1, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -222,8 +222,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should attach error messages to spans', done => {
|
it('should attach error messages to spans', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
connection.query(statement, (err, res) => {
|
connection.query(statement, (err, res) => {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
|
@ -238,8 +238,8 @@ describe('mysql@2.x', () => {
|
||||||
|
|
||||||
describe('#Pool', () => {
|
describe('#Pool', () => {
|
||||||
it('should intercept pool.query(text: string)', done => {
|
it('should intercept pool.query(text: string)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
const query = pool.query(statement);
|
const query = pool.query(statement);
|
||||||
let rows = 0;
|
let rows = 0;
|
||||||
|
@ -260,8 +260,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept pool.getConnection().query(text: string)', done => {
|
it('should intercept pool.getConnection().query(text: string)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
pool.getConnection((err, conn) => {
|
pool.getConnection((err, conn) => {
|
||||||
const query = conn.query(statement);
|
const query = conn.query(statement);
|
||||||
|
@ -284,8 +284,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept pool.query(text: string, callback)', done => {
|
it('should intercept pool.query(text: string, callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
pool.query(statement, (err, res) => {
|
pool.query(statement, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -300,8 +300,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept pool.getConnection().query(text: string, callback)', done => {
|
it('should intercept pool.getConnection().query(text: string, callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
pool.getConnection((err, conn) => {
|
pool.getConnection((err, conn) => {
|
||||||
conn.query(statement, (err, res) => {
|
conn.query(statement, (err, res) => {
|
||||||
|
@ -318,8 +318,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept pool.query(text: options, callback)', done => {
|
it('should intercept pool.query(text: options, callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+? as solution';
|
const statement = 'SELECT 1+? as solution';
|
||||||
pool.query({ sql: statement, values: [1] }, (err, res) => {
|
pool.query({ sql: statement, values: [1] }, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -334,8 +334,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept pool.query(text: options, values: [], callback)', done => {
|
it('should intercept pool.query(text: options, values: [], callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+? as solution';
|
const statement = 'SELECT 1+? as solution';
|
||||||
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
|
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
|
||||||
// but does not match the typings
|
// but does not match the typings
|
||||||
|
@ -352,8 +352,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept pool.query(text: string, values: [], callback)', done => {
|
it('should intercept pool.query(text: string, values: [], callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
pool.query(statement, [1], (err, res) => {
|
pool.query(statement, [1], (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -368,8 +368,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should intercept pool.query(text: string, value: any, callback)', done => {
|
it('should intercept pool.query(text: string, value: any, callback)', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
pool.query(statement, 1, (err, res) => {
|
pool.query(statement, 1, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -384,8 +384,8 @@ describe('mysql@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should attach error messages to spans', done => {
|
it('should attach error messages to spans', done => {
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
pool.query(statement, (err, res) => {
|
pool.query(statement, (err, res) => {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
|
@ -402,8 +402,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should intercept poolClusterConnection.query(text: string)', done => {
|
it('should intercept poolClusterConnection.query(text: string)', done => {
|
||||||
poolCluster.getConnection((err, poolClusterConnection) => {
|
poolCluster.getConnection((err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
const query = poolClusterConnection.query(statement);
|
const query = poolClusterConnection.query(statement);
|
||||||
let rows = 0;
|
let rows = 0;
|
||||||
|
@ -427,8 +427,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should intercept poolClusterConnection.query(text: string, callback)', done => {
|
it('should intercept poolClusterConnection.query(text: string, callback)', done => {
|
||||||
poolCluster.getConnection((err, poolClusterConnection) => {
|
poolCluster.getConnection((err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+1 as solution';
|
const statement = 'SELECT 1+1 as solution';
|
||||||
poolClusterConnection.query(statement, (err, res) => {
|
poolClusterConnection.query(statement, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -446,8 +446,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should intercept poolClusterConnection.query(text: options, callback)', done => {
|
it('should intercept poolClusterConnection.query(text: options, callback)', done => {
|
||||||
poolCluster.getConnection((err, poolClusterConnection) => {
|
poolCluster.getConnection((err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+? as solution';
|
const statement = 'SELECT 1+? as solution';
|
||||||
poolClusterConnection.query(
|
poolClusterConnection.query(
|
||||||
{ sql: statement, values: [1] },
|
{ sql: statement, values: [1] },
|
||||||
|
@ -468,8 +468,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should intercept poolClusterConnection.query(text: options, values: [], callback)', done => {
|
it('should intercept poolClusterConnection.query(text: options, values: [], callback)', done => {
|
||||||
poolCluster.getConnection((err, poolClusterConnection) => {
|
poolCluster.getConnection((err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1+? as solution';
|
const statement = 'SELECT 1+? as solution';
|
||||||
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
|
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
|
||||||
// but does not match the typings
|
// but does not match the typings
|
||||||
|
@ -489,8 +489,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should intercept poolClusterConnection.query(text: string, values: [], callback)', done => {
|
it('should intercept poolClusterConnection.query(text: string, values: [], callback)', done => {
|
||||||
poolCluster.getConnection((err, poolClusterConnection) => {
|
poolCluster.getConnection((err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
poolClusterConnection.query(statement, [1], (err, res) => {
|
poolClusterConnection.query(statement, [1], (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -508,8 +508,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should intercept poolClusterConnection.query(text: string, value: any, callback)', done => {
|
it('should intercept poolClusterConnection.query(text: string, value: any, callback)', done => {
|
||||||
poolCluster.getConnection((err, poolClusterConnection) => {
|
poolCluster.getConnection((err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
poolClusterConnection.query(statement, 1, (err, res) => {
|
poolClusterConnection.query(statement, 1, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
@ -527,8 +527,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should attach error messages to spans', done => {
|
it('should attach error messages to spans', done => {
|
||||||
poolCluster.getConnection((err, poolClusterConnection) => {
|
poolCluster.getConnection((err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT ? as solution';
|
const statement = 'SELECT ? as solution';
|
||||||
poolClusterConnection.query(statement, (err, res) => {
|
poolClusterConnection.query(statement, (err, res) => {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
|
@ -544,8 +544,8 @@ describe('mysql@2.x', () => {
|
||||||
it('should get connection by name', done => {
|
it('should get connection by name', done => {
|
||||||
poolCluster.getConnection('name', (err, poolClusterConnection) => {
|
poolCluster.getConnection('name', (err, poolClusterConnection) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('default').startSpan('test span');
|
||||||
tracer.withSpan(span, () => {
|
registry.getTracer('default').withSpan(span, () => {
|
||||||
const statement = 'SELECT 1 as solution';
|
const statement = 'SELECT 1 as solution';
|
||||||
poolClusterConnection.query(statement, (err, res) => {
|
poolClusterConnection.query(statement, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
PgPoolExtended,
|
PgPoolExtended,
|
||||||
} from './types';
|
} from './types';
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
|
import { VERSION } from './version';
|
||||||
|
|
||||||
export class PostgresPoolPlugin extends BasePlugin<typeof pgPoolTypes> {
|
export class PostgresPoolPlugin extends BasePlugin<typeof pgPoolTypes> {
|
||||||
protected _config: PostgresPoolPluginOptions;
|
protected _config: PostgresPoolPluginOptions;
|
||||||
|
@ -35,7 +36,7 @@ export class PostgresPoolPlugin extends BasePlugin<typeof pgPoolTypes> {
|
||||||
readonly supportedVersions = ['2.*'];
|
readonly supportedVersions = ['2.*'];
|
||||||
|
|
||||||
constructor(readonly moduleName: string) {
|
constructor(readonly moduleName: string) {
|
||||||
super();
|
super('@opentelemetry/plugin-pg-pool', VERSION);
|
||||||
this._config = {};
|
this._config = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
|
@ -92,7 +92,7 @@ const runCallbackTest = (
|
||||||
|
|
||||||
describe('pg-pool@2.x', () => {
|
describe('pg-pool@2.x', () => {
|
||||||
let pool: pgPool<pg.Client>;
|
let pool: pgPool<pg.Client>;
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const testPostgres = process.env.TEST_POSTGRES; // For CI: assumes local postgres db is already available
|
const testPostgres = process.env.TEST_POSTGRES; // For CI: assumes local postgres db is already available
|
||||||
const testPostgresLocally = process.env.TEST_POSTGRES_LOCAL; // For local: spins up local postgres db via docker
|
const testPostgresLocally = process.env.TEST_POSTGRES_LOCAL; // For local: spins up local postgres db via docker
|
||||||
|
@ -106,7 +106,7 @@ describe('pg-pool@2.x', () => {
|
||||||
this.skip();
|
this.skip();
|
||||||
}
|
}
|
||||||
pool = new pgPool(CONFIG);
|
pool = new pgPool(CONFIG);
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
if (testPostgresLocally) {
|
if (testPostgresLocally) {
|
||||||
testUtils.startDocker('postgres');
|
testUtils.startDocker('postgres');
|
||||||
}
|
}
|
||||||
|
@ -123,8 +123,8 @@ describe('pg-pool@2.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
plugin.enable(pgPool, tracer, logger);
|
plugin.enable(pgPool, registry, logger);
|
||||||
pgPlugin.enable(pg, tracer, logger);
|
pgPlugin.enable(pg, registry, logger);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -152,8 +152,8 @@ describe('pg-pool@2.x', () => {
|
||||||
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
||||||
};
|
};
|
||||||
const events: TimedEvent[] = [];
|
const events: TimedEvent[] = [];
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('test-pg-pool').startSpan('test span');
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('test-pg-pool').withSpan(span, async () => {
|
||||||
const client = await pool.connect();
|
const client = await pool.connect();
|
||||||
runCallbackTest(span, pgPoolattributes, events, okStatus, 1, 0);
|
runCallbackTest(span, pgPoolattributes, events, okStatus, 1, 0);
|
||||||
assert.ok(client, 'pool.connect() returns a promise');
|
assert.ok(client, 'pool.connect() returns a promise');
|
||||||
|
@ -178,8 +178,10 @@ describe('pg-pool@2.x', () => {
|
||||||
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
||||||
};
|
};
|
||||||
const events: TimedEvent[] = [];
|
const events: TimedEvent[] = [];
|
||||||
const parentSpan = tracer.startSpan('test span');
|
const parentSpan = registry
|
||||||
tracer.withSpan(parentSpan, () => {
|
.getTracer('test-pg-pool')
|
||||||
|
.startSpan('test span');
|
||||||
|
registry.getTracer('test-pg-pool').withSpan(parentSpan, () => {
|
||||||
const resNoPromise = pool.connect((err, client, release) => {
|
const resNoPromise = pool.connect((err, client, release) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
|
@ -212,8 +214,8 @@ describe('pg-pool@2.x', () => {
|
||||||
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
||||||
};
|
};
|
||||||
const events: TimedEvent[] = [];
|
const events: TimedEvent[] = [];
|
||||||
const span = tracer.startSpan('test span');
|
const span = registry.getTracer('test-pg-pool').startSpan('test span');
|
||||||
await tracer.withSpan(span, async () => {
|
await registry.getTracer('test-pg-pool').withSpan(span, async () => {
|
||||||
try {
|
try {
|
||||||
const result = await pool.query('SELECT NOW()');
|
const result = await pool.query('SELECT NOW()');
|
||||||
runCallbackTest(span, pgPoolattributes, events, okStatus, 2, 0);
|
runCallbackTest(span, pgPoolattributes, events, okStatus, 2, 0);
|
||||||
|
@ -235,8 +237,10 @@ describe('pg-pool@2.x', () => {
|
||||||
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
|
||||||
};
|
};
|
||||||
const events: TimedEvent[] = [];
|
const events: TimedEvent[] = [];
|
||||||
const parentSpan = tracer.startSpan('test span');
|
const parentSpan = registry
|
||||||
tracer.withSpan(parentSpan, () => {
|
.getTracer('test-pg-pool')
|
||||||
|
.startSpan('test span');
|
||||||
|
registry.getTracer('test-pg-pool').withSpan(parentSpan, () => {
|
||||||
const resNoPromise = pool.query('SELECT NOW()', (err, result) => {
|
const resNoPromise = pool.query('SELECT NOW()', (err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
|
|
|
@ -16,15 +16,16 @@
|
||||||
|
|
||||||
import { BasePlugin } from '@opentelemetry/core';
|
import { BasePlugin } from '@opentelemetry/core';
|
||||||
import { CanonicalCode, Span } from '@opentelemetry/types';
|
import { CanonicalCode, Span } from '@opentelemetry/types';
|
||||||
|
import * as pgTypes from 'pg';
|
||||||
|
import * as shimmer from 'shimmer';
|
||||||
import {
|
import {
|
||||||
PostgresPluginOptions,
|
|
||||||
PgClientExtended,
|
PgClientExtended,
|
||||||
PgPluginQueryConfig,
|
PgPluginQueryConfig,
|
||||||
PostgresCallback,
|
PostgresCallback,
|
||||||
|
PostgresPluginOptions,
|
||||||
} from './types';
|
} from './types';
|
||||||
import * as pgTypes from 'pg';
|
|
||||||
import * as shimmer from 'shimmer';
|
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
|
import { VERSION } from './version';
|
||||||
|
|
||||||
export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
|
export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
|
||||||
protected _config: PostgresPluginOptions;
|
protected _config: PostgresPluginOptions;
|
||||||
|
@ -37,7 +38,7 @@ export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
|
||||||
readonly supportedVersions = ['7.*'];
|
readonly supportedVersions = ['7.*'];
|
||||||
|
|
||||||
constructor(readonly moduleName: string) {
|
constructor(readonly moduleName: string) {
|
||||||
super();
|
super('@opentelemetry/plugin-pg', VERSION);
|
||||||
this._config = {};
|
this._config = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
|
@ -81,7 +81,8 @@ const runCallbackTest = (
|
||||||
|
|
||||||
describe('pg@7.x', () => {
|
describe('pg@7.x', () => {
|
||||||
let client: pg.Client;
|
let client: pg.Client;
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
|
const tracer = registry.getTracer('external');
|
||||||
const logger = new NoopLogger();
|
const logger = new NoopLogger();
|
||||||
const testPostgres = process.env.RUN_POSTGRES_TESTS; // For CI: assumes local postgres db is already available
|
const testPostgres = process.env.RUN_POSTGRES_TESTS; // For CI: assumes local postgres db is already available
|
||||||
const testPostgresLocally = process.env.RUN_POSTGRES_TESTS_LOCAL; // For local: spins up local postgres db via docker
|
const testPostgresLocally = process.env.RUN_POSTGRES_TESTS_LOCAL; // For local: spins up local postgres db via docker
|
||||||
|
@ -94,7 +95,7 @@ describe('pg@7.x', () => {
|
||||||
this.test!.parent!.pending = true;
|
this.test!.parent!.pending = true;
|
||||||
this.skip();
|
this.skip();
|
||||||
}
|
}
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
if (testPostgresLocally) {
|
if (testPostgresLocally) {
|
||||||
testUtils.startDocker('postgres');
|
testUtils.startDocker('postgres');
|
||||||
}
|
}
|
||||||
|
@ -115,7 +116,7 @@ describe('pg@7.x', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
plugin.enable(pg, tracer, logger);
|
plugin.enable(pg, registry, logger);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
|
@ -24,9 +24,9 @@ OpenTelemetry Redis Instrumentation allows the user to automatically collect tra
|
||||||
|
|
||||||
To load a specific plugin (**redis** in this case), specify it in the Node Tracer's configuration
|
To load a specific plugin (**redis** in this case), specify it in the Node Tracer's configuration
|
||||||
```js
|
```js
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer({
|
const registry = new NodeTracerRegistry({
|
||||||
plugins: {
|
plugins: {
|
||||||
redis: {
|
redis: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -39,9 +39,9 @@ const tracer = new NodeTracer({
|
||||||
|
|
||||||
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
To load all the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.
|
||||||
```javascript
|
```javascript
|
||||||
const { NodeTracer } = require('@opentelemetry/node');
|
const { NodeTracerRegistry } = require('@opentelemetry/node');
|
||||||
|
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
```
|
```
|
||||||
|
|
||||||
See [examples/redis](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/redis) for a short example.
|
See [examples/redis](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/redis) for a short example.
|
||||||
|
|
|
@ -22,13 +22,14 @@ import {
|
||||||
getTracedCreateStreamTrace,
|
getTracedCreateStreamTrace,
|
||||||
getTracedInternalSendCommand,
|
getTracedInternalSendCommand,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
import { VERSION } from './version';
|
||||||
|
|
||||||
export class RedisPlugin extends BasePlugin<typeof redisTypes> {
|
export class RedisPlugin extends BasePlugin<typeof redisTypes> {
|
||||||
static readonly COMPONENT = 'redis';
|
static readonly COMPONENT = 'redis';
|
||||||
readonly supportedVersions = ['^2.6.0']; // equivalent to >= 2.6.0 <3
|
readonly supportedVersions = ['^2.6.0']; // equivalent to >= 2.6.0 <3
|
||||||
|
|
||||||
constructor(readonly moduleName: string) {
|
constructor(readonly moduleName: string) {
|
||||||
super();
|
super('@opentelemetry/plugin-redis', VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected patch() {
|
protected patch() {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
} from '@opentelemetry/tracing';
|
} from '@opentelemetry/tracing';
|
||||||
import { NodeTracer } from '@opentelemetry/node';
|
import { NodeTracerRegistry } from '@opentelemetry/node';
|
||||||
import { plugin, RedisPlugin } from '../src';
|
import { plugin, RedisPlugin } from '../src';
|
||||||
import * as redisTypes from 'redis';
|
import * as redisTypes from 'redis';
|
||||||
import { NoopLogger } from '@opentelemetry/core';
|
import { NoopLogger } from '@opentelemetry/core';
|
||||||
|
@ -48,7 +48,8 @@ const okStatus: Status = {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('redis@2.x', () => {
|
describe('redis@2.x', () => {
|
||||||
const tracer = new NodeTracer();
|
const registry = new NodeTracerRegistry();
|
||||||
|
const tracer = registry.getTracer('external');
|
||||||
let redis: typeof redisTypes;
|
let redis: typeof redisTypes;
|
||||||
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
|
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
|
||||||
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
|
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
|
||||||
|
@ -67,8 +68,8 @@ describe('redis@2.x', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
redis = require('redis');
|
redis = require('redis');
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
plugin.enable(redis, tracer, new NoopLogger());
|
plugin.enable(redis, registry, new NoopLogger());
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
|
|
@ -69,15 +69,12 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
|
||||||
readonly version: string = VERSION;
|
readonly version: string = VERSION;
|
||||||
moduleName = this.component;
|
moduleName = this.component;
|
||||||
|
|
||||||
protected _config!: XMLHttpRequestPluginConfig;
|
|
||||||
|
|
||||||
private _tasksCount = 0;
|
private _tasksCount = 0;
|
||||||
private _xhrMem = new WeakMap<XMLHttpRequest, XhrMem>();
|
private _xhrMem = new WeakMap<XMLHttpRequest, XhrMem>();
|
||||||
private _usedResources = new WeakSet<PerformanceResourceTiming>();
|
private _usedResources = new WeakSet<PerformanceResourceTiming>();
|
||||||
|
|
||||||
constructor(config: XMLHttpRequestPluginConfig = {}) {
|
constructor(protected _config: XMLHttpRequestPluginConfig = {}) {
|
||||||
super();
|
super('@opentelemetry/plugin-xml-http-request', VERSION);
|
||||||
this._config = config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,10 +27,14 @@ import {
|
||||||
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
|
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
|
||||||
import * as tracing from '@opentelemetry/tracing';
|
import * as tracing from '@opentelemetry/tracing';
|
||||||
import * as types from '@opentelemetry/types';
|
import * as types from '@opentelemetry/types';
|
||||||
import { PerformanceTimingNames as PTN, WebTracer } from '@opentelemetry/web';
|
import {
|
||||||
|
PerformanceTimingNames as PTN,
|
||||||
|
WebTracerRegistry,
|
||||||
|
} from '@opentelemetry/web';
|
||||||
import { AttributeNames } from '../src/enums/AttributeNames';
|
import { AttributeNames } from '../src/enums/AttributeNames';
|
||||||
import { EventNames } from '../src/enums/EventNames';
|
import { EventNames } from '../src/enums/EventNames';
|
||||||
import { XMLHttpRequestPlugin } from '../src/xhr';
|
import { XMLHttpRequestPlugin } from '../src/xhr';
|
||||||
|
import { Tracer } from '@opentelemetry/types';
|
||||||
|
|
||||||
class DummySpanExporter implements tracing.SpanExporter {
|
class DummySpanExporter implements tracing.SpanExporter {
|
||||||
export(spans: any) {}
|
export(spans: any) {}
|
||||||
|
@ -97,7 +101,8 @@ describe('xhr', () => {
|
||||||
let clearData: any;
|
let clearData: any;
|
||||||
|
|
||||||
describe('when request is successful', () => {
|
describe('when request is successful', () => {
|
||||||
let webTracerWithZone: WebTracer;
|
let webTracerWithZone: Tracer;
|
||||||
|
let webTracerRegistryWithZone: WebTracerRegistry;
|
||||||
let dummySpanExporter: DummySpanExporter;
|
let dummySpanExporter: DummySpanExporter;
|
||||||
let exportSpy: any;
|
let exportSpy: any;
|
||||||
let rootSpan: types.Span;
|
let rootSpan: types.Span;
|
||||||
|
@ -136,7 +141,7 @@ describe('xhr', () => {
|
||||||
spyEntries = sandbox.stub(performance, 'getEntriesByType');
|
spyEntries = sandbox.stub(performance, 'getEntriesByType');
|
||||||
spyEntries.withArgs('resource').returns(resources);
|
spyEntries.withArgs('resource').returns(resources);
|
||||||
|
|
||||||
webTracerWithZone = new WebTracer({
|
webTracerRegistryWithZone = new WebTracerRegistry({
|
||||||
logLevel: LogLevel.ERROR,
|
logLevel: LogLevel.ERROR,
|
||||||
httpTextFormat: new B3Format(),
|
httpTextFormat: new B3Format(),
|
||||||
scopeManager: new ZoneScopeManager(),
|
scopeManager: new ZoneScopeManager(),
|
||||||
|
@ -146,9 +151,10 @@ describe('xhr', () => {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
webTracerWithZone = webTracerRegistryWithZone.getTracer('xhr-test');
|
||||||
dummySpanExporter = new DummySpanExporter();
|
dummySpanExporter = new DummySpanExporter();
|
||||||
exportSpy = sinon.stub(dummySpanExporter, 'export');
|
exportSpy = sinon.stub(dummySpanExporter, 'export');
|
||||||
webTracerWithZone.addSpanProcessor(
|
webTracerRegistryWithZone.addSpanProcessor(
|
||||||
new tracing.SimpleSpanProcessor(dummySpanExporter)
|
new tracing.SimpleSpanProcessor(dummySpanExporter)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -403,7 +409,8 @@ describe('xhr', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when request is NOT successful', () => {
|
describe('when request is NOT successful', () => {
|
||||||
let webTracerWithZone: WebTracer;
|
let webTracerWithZoneRegistry: WebTracerRegistry;
|
||||||
|
let webTracerWithZone: Tracer;
|
||||||
let dummySpanExporter: DummySpanExporter;
|
let dummySpanExporter: DummySpanExporter;
|
||||||
let exportSpy: any;
|
let exportSpy: any;
|
||||||
let rootSpan: types.Span;
|
let rootSpan: types.Span;
|
||||||
|
@ -434,16 +441,17 @@ describe('xhr', () => {
|
||||||
spyEntries = sandbox.stub(performance, 'getEntriesByType');
|
spyEntries = sandbox.stub(performance, 'getEntriesByType');
|
||||||
spyEntries.withArgs('resource').returns(resources);
|
spyEntries.withArgs('resource').returns(resources);
|
||||||
|
|
||||||
webTracerWithZone = new WebTracer({
|
webTracerWithZoneRegistry = new WebTracerRegistry({
|
||||||
logLevel: LogLevel.ERROR,
|
logLevel: LogLevel.ERROR,
|
||||||
scopeManager: new ZoneScopeManager(),
|
scopeManager: new ZoneScopeManager(),
|
||||||
plugins: [new XMLHttpRequestPlugin()],
|
plugins: [new XMLHttpRequestPlugin()],
|
||||||
});
|
});
|
||||||
dummySpanExporter = new DummySpanExporter();
|
dummySpanExporter = new DummySpanExporter();
|
||||||
exportSpy = sinon.stub(dummySpanExporter, 'export');
|
exportSpy = sinon.stub(dummySpanExporter, 'export');
|
||||||
webTracerWithZone.addSpanProcessor(
|
webTracerWithZoneRegistry.addSpanProcessor(
|
||||||
new tracing.SimpleSpanProcessor(dummySpanExporter)
|
new tracing.SimpleSpanProcessor(dummySpanExporter)
|
||||||
);
|
);
|
||||||
|
webTracerWithZone = webTracerWithZoneRegistry.getTracer('xhr-test');
|
||||||
|
|
||||||
rootSpan = webTracerWithZone.startSpan('root');
|
rootSpan = webTracerWithZone.startSpan('root');
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,16 @@
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as opentracing from 'opentracing';
|
import * as opentracing from 'opentracing';
|
||||||
import { BasicTracer, Span } from '@opentelemetry/tracing';
|
import { BasicTracerRegistry, Span } from '@opentelemetry/tracing';
|
||||||
import { TracerShim, SpanShim, SpanContextShim } from '../src/shim';
|
import { TracerShim, SpanShim, SpanContextShim } from '../src/shim';
|
||||||
import { INVALID_SPAN_CONTEXT, timeInputToHrTime } from '@opentelemetry/core';
|
import { INVALID_SPAN_CONTEXT, timeInputToHrTime } from '@opentelemetry/core';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
|
|
||||||
describe('OpenTracing Shim', () => {
|
describe('OpenTracing Shim', () => {
|
||||||
const tracer = new BasicTracer();
|
const registry = new BasicTracerRegistry();
|
||||||
const shimTracer: opentracing.Tracer = new TracerShim(tracer);
|
const shimTracer: opentracing.Tracer = new TracerShim(
|
||||||
|
registry.getTracer('default')
|
||||||
|
);
|
||||||
opentracing.initGlobalTracer(shimTracer);
|
opentracing.initGlobalTracer(shimTracer);
|
||||||
|
|
||||||
describe('TracerShim', () => {
|
describe('TracerShim', () => {
|
||||||
|
|
|
@ -25,22 +25,19 @@ npm install --save @opentelemetry/tracing
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const opentelemetry = require('@opentelemetry/core');
|
const opentelemetry = require('@opentelemetry/core');
|
||||||
const { BasicTracer } = require('@opentelemetry/tracing');
|
const { BasicTracerRegistry } = require('@opentelemetry/tracing');
|
||||||
|
|
||||||
// To start a trace, you first need to initialize the Tracer.
|
// To start a trace, you first need to initialize the Tracer registry.
|
||||||
// NOTE: the default OpenTelemetry tracer does not record any tracing information.
|
// NOTE: the default OpenTelemetry tracer registry does not record any tracing information.
|
||||||
const tracer = new BasicTracer();
|
opentelemetry.initGlobalTracer(new BasicTracerRegistry());
|
||||||
|
|
||||||
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
|
|
||||||
opentelemetry.initGlobalTracer(tracer);
|
|
||||||
|
|
||||||
// To create a span in a trace, we used the global singleton tracer to start a new span.
|
// To create a span in a trace, we used the global singleton tracer to start a new span.
|
||||||
const span = opentelemetry.getTracer().startSpan('foo');
|
const span = opentelemetry.getTracer('default').startSpan('foo');
|
||||||
|
|
||||||
// Create an Attributes
|
// Set a span attribute
|
||||||
span.setAttribute('key', 'value');
|
span.setAttribute('key', 'value');
|
||||||
|
|
||||||
// We must end the spans so they becomes available for exporting.
|
// We must end the spans so they become available for exporting.
|
||||||
span.end();
|
span.end();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*!
|
||||||
|
* Copyright 2019, OpenTelemetry Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ConsoleLogger } from '@opentelemetry/core';
|
||||||
|
import * as types from '@opentelemetry/types';
|
||||||
|
import { Logger } from '@opentelemetry/types';
|
||||||
|
import { SpanProcessor, Tracer } from '.';
|
||||||
|
import { DEFAULT_CONFIG } from './config';
|
||||||
|
import { MultiSpanProcessor } from './MultiSpanProcessor';
|
||||||
|
import { NoopSpanProcessor } from './NoopSpanProcessor';
|
||||||
|
import { TracerConfig } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a basic tracer registry which platform libraries can extend
|
||||||
|
*/
|
||||||
|
export class BasicTracerRegistry implements types.TracerRegistry {
|
||||||
|
private readonly _registeredSpanProcessors: SpanProcessor[] = [];
|
||||||
|
private readonly _tracers: Map<string, Tracer> = new Map();
|
||||||
|
|
||||||
|
activeSpanProcessor = new NoopSpanProcessor();
|
||||||
|
readonly logger: Logger;
|
||||||
|
|
||||||
|
constructor(private _config: TracerConfig = DEFAULT_CONFIG) {
|
||||||
|
this.logger = _config.logger || new ConsoleLogger(_config.logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTracer(name: string, version = '*', config?: TracerConfig): Tracer {
|
||||||
|
const key = `${name}@${version}`;
|
||||||
|
if (!this._tracers.has(key)) {
|
||||||
|
this._tracers.set(key, new Tracer(config || this._config, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._tracers.get(key)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new {@link SpanProcessor} to this tracer.
|
||||||
|
* @param spanProcessor the new SpanProcessor to be added.
|
||||||
|
*/
|
||||||
|
addSpanProcessor(spanProcessor: SpanProcessor): void {
|
||||||
|
this._registeredSpanProcessors.push(spanProcessor);
|
||||||
|
this.activeSpanProcessor = new MultiSpanProcessor(
|
||||||
|
this._registeredSpanProcessors
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getActiveSpanProcessor(): SpanProcessor {
|
||||||
|
return this.activeSpanProcessor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ import {
|
||||||
timeInputToHrTime,
|
timeInputToHrTime,
|
||||||
} from '@opentelemetry/core';
|
} from '@opentelemetry/core';
|
||||||
import { ReadableSpan } from './export/ReadableSpan';
|
import { ReadableSpan } from './export/ReadableSpan';
|
||||||
import { BasicTracer } from './BasicTracer';
|
import { Tracer } from './Tracer';
|
||||||
import { SpanProcessor } from './SpanProcessor';
|
import { SpanProcessor } from './SpanProcessor';
|
||||||
import { TraceParams } from './types';
|
import { TraceParams } from './types';
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ export class Span implements types.Span, ReadableSpan {
|
||||||
|
|
||||||
/** Constructs a new Span instance. */
|
/** Constructs a new Span instance. */
|
||||||
constructor(
|
constructor(
|
||||||
parentTracer: BasicTracer,
|
parentTracer: Tracer,
|
||||||
spanName: string,
|
spanName: string,
|
||||||
spanContext: types.SpanContext,
|
spanContext: types.SpanContext,
|
||||||
kind: types.SpanKind,
|
kind: types.SpanKind,
|
||||||
|
@ -68,7 +68,7 @@ export class Span implements types.Span, ReadableSpan {
|
||||||
this.startTime = timeInputToHrTime(startTime);
|
this.startTime = timeInputToHrTime(startTime);
|
||||||
this._logger = parentTracer.logger;
|
this._logger = parentTracer.logger;
|
||||||
this._traceParams = parentTracer.getActiveTraceParams();
|
this._traceParams = parentTracer.getActiveTraceParams();
|
||||||
this._spanProcessor = parentTracer.activeSpanProcessor;
|
this._spanProcessor = parentTracer.getActiveSpanProcessor();
|
||||||
this._spanProcessor.onStart(this);
|
this._spanProcessor.onStart(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,19 +28,17 @@ import {
|
||||||
TraceFlags,
|
TraceFlags,
|
||||||
Logger,
|
Logger,
|
||||||
} from '@opentelemetry/types';
|
} from '@opentelemetry/types';
|
||||||
import { BasicTracerConfig, TraceParams } from './types';
|
import { TracerConfig, TraceParams } from './types';
|
||||||
import { ScopeManager } from '@opentelemetry/scope-base';
|
import { ScopeManager } from '@opentelemetry/scope-base';
|
||||||
import { Span } from './Span';
|
import { Span } from './Span';
|
||||||
import { mergeConfig } from './utility';
|
import { mergeConfig } from './utility';
|
||||||
import { SpanProcessor } from './SpanProcessor';
|
|
||||||
import { NoopSpanProcessor } from './NoopSpanProcessor';
|
|
||||||
import { MultiSpanProcessor } from './MultiSpanProcessor';
|
|
||||||
import { DEFAULT_CONFIG } from './config';
|
import { DEFAULT_CONFIG } from './config';
|
||||||
|
import { BasicTracerRegistry } from './BasicTracerRegistry';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a basic tracer.
|
* This class represents a basic tracer.
|
||||||
*/
|
*/
|
||||||
export class BasicTracer implements types.Tracer {
|
export class Tracer implements types.Tracer {
|
||||||
private readonly _defaultAttributes: types.Attributes;
|
private readonly _defaultAttributes: types.Attributes;
|
||||||
private readonly _binaryFormat: types.BinaryFormat;
|
private readonly _binaryFormat: types.BinaryFormat;
|
||||||
private readonly _httpTextFormat: types.HttpTextFormat;
|
private readonly _httpTextFormat: types.HttpTextFormat;
|
||||||
|
@ -48,13 +46,14 @@ export class BasicTracer implements types.Tracer {
|
||||||
private readonly _scopeManager: ScopeManager;
|
private readonly _scopeManager: ScopeManager;
|
||||||
private readonly _traceParams: TraceParams;
|
private readonly _traceParams: TraceParams;
|
||||||
readonly logger: Logger;
|
readonly logger: Logger;
|
||||||
private readonly _registeredSpanProcessor: SpanProcessor[] = [];
|
|
||||||
activeSpanProcessor = new NoopSpanProcessor();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Tracer instance.
|
* Constructs a new Tracer instance.
|
||||||
*/
|
*/
|
||||||
constructor(config: BasicTracerConfig = DEFAULT_CONFIG) {
|
constructor(
|
||||||
|
config: TracerConfig = DEFAULT_CONFIG,
|
||||||
|
private _tracerRegistry: BasicTracerRegistry
|
||||||
|
) {
|
||||||
const localConfig = mergeConfig(config);
|
const localConfig = mergeConfig(config);
|
||||||
this._binaryFormat = localConfig.binaryFormat;
|
this._binaryFormat = localConfig.binaryFormat;
|
||||||
this._defaultAttributes = localConfig.defaultAttributes;
|
this._defaultAttributes = localConfig.defaultAttributes;
|
||||||
|
@ -162,15 +161,8 @@ export class BasicTracer implements types.Tracer {
|
||||||
return this._traceParams;
|
return this._traceParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getActiveSpanProcessor() {
|
||||||
* Adds a new {@link SpanProcessor} to this tracer.
|
return this._tracerRegistry.getActiveSpanProcessor();
|
||||||
* @param spanProcessor the new SpanProcessor to be added.
|
|
||||||
*/
|
|
||||||
addSpanProcessor(spanProcessor: SpanProcessor): void {
|
|
||||||
this._registeredSpanProcessor.push(spanProcessor);
|
|
||||||
this.activeSpanProcessor = new MultiSpanProcessor(
|
|
||||||
this._registeredSpanProcessor
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getParentSpanContext(
|
private _getParentSpanContext(
|
|
@ -14,7 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './BasicTracer';
|
export * from './Tracer';
|
||||||
|
export * from './BasicTracerRegistry';
|
||||||
export * from './export/ConsoleSpanExporter';
|
export * from './export/ConsoleSpanExporter';
|
||||||
export * from './export/BatchSpanProcessor';
|
export * from './export/BatchSpanProcessor';
|
||||||
export * from './export/InMemorySpanExporter';
|
export * from './export/InMemorySpanExporter';
|
||||||
|
|
|
@ -25,9 +25,9 @@ import {
|
||||||
import { LogLevel } from '@opentelemetry/core';
|
import { LogLevel } from '@opentelemetry/core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BasicTracerConfig provides an interface for configuring a Basic Tracer.
|
* TracerConfig provides an interface for configuring a Basic Tracer.
|
||||||
*/
|
*/
|
||||||
export interface BasicTracerConfig {
|
export interface TracerConfig {
|
||||||
/**
|
/**
|
||||||
* Binary formatter which can serialize/deserialize Spans.
|
* Binary formatter which can serialize/deserialize Spans.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,19 +14,19 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BasicTracerConfig } from './types';
|
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_CONFIG,
|
||||||
DEFAULT_MAX_ATTRIBUTES_PER_SPAN,
|
DEFAULT_MAX_ATTRIBUTES_PER_SPAN,
|
||||||
DEFAULT_MAX_EVENTS_PER_SPAN,
|
DEFAULT_MAX_EVENTS_PER_SPAN,
|
||||||
DEFAULT_MAX_LINKS_PER_SPAN,
|
DEFAULT_MAX_LINKS_PER_SPAN,
|
||||||
} from './config';
|
} from './config';
|
||||||
import { DEFAULT_CONFIG } from './config';
|
import { TracerConfig } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to merge Default configuration (as specified in './config') with
|
* Function to merge Default configuration (as specified in './config') with
|
||||||
* user provided configurations.
|
* user provided configurations.
|
||||||
*/
|
*/
|
||||||
export function mergeConfig(userConfig: BasicTracerConfig) {
|
export function mergeConfig(userConfig: TracerConfig) {
|
||||||
const traceParams = userConfig.traceParams;
|
const traceParams = userConfig.traceParams;
|
||||||
const target = Object.assign({}, DEFAULT_CONFIG, userConfig);
|
const target = Object.assign({}, DEFAULT_CONFIG, userConfig);
|
||||||
|
|
||||||
|
|
|
@ -14,62 +14,62 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as assert from 'assert';
|
|
||||||
import {
|
import {
|
||||||
ALWAYS_SAMPLER,
|
ALWAYS_SAMPLER,
|
||||||
BinaryTraceContext,
|
BinaryTraceContext,
|
||||||
HttpTraceContext,
|
HttpTraceContext,
|
||||||
NEVER_SAMPLER,
|
NEVER_SAMPLER,
|
||||||
NoopLogger,
|
NoopLogger,
|
||||||
TraceState,
|
|
||||||
NoRecordingSpan,
|
NoRecordingSpan,
|
||||||
|
TraceState,
|
||||||
} from '@opentelemetry/core';
|
} from '@opentelemetry/core';
|
||||||
import { TraceFlags } from '@opentelemetry/types';
|
|
||||||
import { BasicTracer, Span } from '../src';
|
|
||||||
import { NoopScopeManager, ScopeManager } from '@opentelemetry/scope-base';
|
import { NoopScopeManager, ScopeManager } from '@opentelemetry/scope-base';
|
||||||
|
import { TraceFlags } from '@opentelemetry/types';
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import { BasicTracerRegistry, Span } from '../src';
|
||||||
|
|
||||||
describe('BasicTracer', () => {
|
describe('BasicTracerRegistry', () => {
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
it('should construct an instance without any options', () => {
|
it('should construct an instance without any options', () => {
|
||||||
const tracer = new BasicTracer();
|
const registry = new BasicTracerRegistry();
|
||||||
assert.ok(tracer instanceof BasicTracer);
|
assert.ok(registry instanceof BasicTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with binary format', () => {
|
it('should construct an instance with binary format', () => {
|
||||||
const tracer = new BasicTracer({
|
const registry = new BasicTracerRegistry({
|
||||||
binaryFormat: new BinaryTraceContext(),
|
binaryFormat: new BinaryTraceContext(),
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof BasicTracer);
|
assert.ok(registry instanceof BasicTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with http text format', () => {
|
it('should construct an instance with http text format', () => {
|
||||||
const tracer = new BasicTracer({
|
const registry = new BasicTracerRegistry({
|
||||||
httpTextFormat: new HttpTraceContext(),
|
httpTextFormat: new HttpTraceContext(),
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof BasicTracer);
|
assert.ok(registry instanceof BasicTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with logger', () => {
|
it('should construct an instance with logger', () => {
|
||||||
const tracer = new BasicTracer({
|
const registry = new BasicTracerRegistry({
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof BasicTracer);
|
assert.ok(registry instanceof BasicTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with sampler', () => {
|
it('should construct an instance with sampler', () => {
|
||||||
const tracer = new BasicTracer({
|
const registry = new BasicTracerRegistry({
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
sampler: ALWAYS_SAMPLER,
|
sampler: ALWAYS_SAMPLER,
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof BasicTracer);
|
assert.ok(registry instanceof BasicTracerRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with default trace params', () => {
|
it('should construct an instance with default trace params', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
});
|
}).getTracer('default');
|
||||||
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
||||||
numberOfAttributesPerSpan: 32,
|
numberOfAttributesPerSpan: 32,
|
||||||
numberOfEventsPerSpan: 128,
|
numberOfEventsPerSpan: 128,
|
||||||
|
@ -78,12 +78,12 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with customized numberOfAttributesPerSpan trace params', () => {
|
it('should construct an instance with customized numberOfAttributesPerSpan trace params', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
traceParams: {
|
traceParams: {
|
||||||
numberOfAttributesPerSpan: 100,
|
numberOfAttributesPerSpan: 100,
|
||||||
},
|
},
|
||||||
});
|
}).getTracer('default');
|
||||||
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
||||||
numberOfAttributesPerSpan: 100,
|
numberOfAttributesPerSpan: 100,
|
||||||
numberOfEventsPerSpan: 128,
|
numberOfEventsPerSpan: 128,
|
||||||
|
@ -92,12 +92,12 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with customized numberOfEventsPerSpan trace params', () => {
|
it('should construct an instance with customized numberOfEventsPerSpan trace params', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
traceParams: {
|
traceParams: {
|
||||||
numberOfEventsPerSpan: 300,
|
numberOfEventsPerSpan: 300,
|
||||||
},
|
},
|
||||||
});
|
}).getTracer('default');
|
||||||
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
||||||
numberOfAttributesPerSpan: 32,
|
numberOfAttributesPerSpan: 32,
|
||||||
numberOfEventsPerSpan: 300,
|
numberOfEventsPerSpan: 300,
|
||||||
|
@ -106,12 +106,12 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with customized numberOfLinksPerSpan trace params', () => {
|
it('should construct an instance with customized numberOfLinksPerSpan trace params', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
traceParams: {
|
traceParams: {
|
||||||
numberOfLinksPerSpan: 10,
|
numberOfLinksPerSpan: 10,
|
||||||
},
|
},
|
||||||
});
|
}).getTracer('default');
|
||||||
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
|
||||||
numberOfAttributesPerSpan: 32,
|
numberOfAttributesPerSpan: 32,
|
||||||
numberOfEventsPerSpan: 128,
|
numberOfEventsPerSpan: 128,
|
||||||
|
@ -120,26 +120,26 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should construct an instance with default attributes', () => {
|
it('should construct an instance with default attributes', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
defaultAttributes: {
|
defaultAttributes: {
|
||||||
region: 'eu-west',
|
region: 'eu-west',
|
||||||
asg: 'my-asg',
|
asg: 'my-asg',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
assert.ok(tracer instanceof BasicTracer);
|
assert.ok(tracer instanceof BasicTracerRegistry);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.startSpan()', () => {
|
describe('.startSpan()', () => {
|
||||||
it('should start a span with name only', () => {
|
it('should start a span with name only', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span');
|
const span = tracer.startSpan('my-span');
|
||||||
assert.ok(span);
|
assert.ok(span);
|
||||||
assert.ok(span instanceof Span);
|
assert.ok(span instanceof Span);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with name and options', () => {
|
it('should start a span with name and options', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', {});
|
const span = tracer.startSpan('my-span', {});
|
||||||
assert.ok(span);
|
assert.ok(span);
|
||||||
assert.ok(span instanceof Span);
|
assert.ok(span instanceof Span);
|
||||||
|
@ -152,9 +152,9 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with defaultAttributes and spanoptions->attributes', () => {
|
it('should start a span with defaultAttributes and spanoptions->attributes', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
defaultAttributes: { foo: 'bar' },
|
defaultAttributes: { foo: 'bar' },
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', {
|
const span = tracer.startSpan('my-span', {
|
||||||
attributes: { foo: 'foo', bar: 'bar' },
|
attributes: { foo: 'foo', bar: 'bar' },
|
||||||
}) as Span;
|
}) as Span;
|
||||||
|
@ -163,16 +163,16 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with defaultAttributes and undefined spanoptions->attributes', () => {
|
it('should start a span with defaultAttributes and undefined spanoptions->attributes', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
defaultAttributes: { foo: 'bar' },
|
defaultAttributes: { foo: 'bar' },
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', {}) as Span;
|
const span = tracer.startSpan('my-span', {}) as Span;
|
||||||
assert.deepStrictEqual(span.attributes, { foo: 'bar' });
|
assert.deepStrictEqual(span.attributes, { foo: 'bar' });
|
||||||
span.end();
|
span.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with spanoptions->attributes', () => {
|
it('should start a span with spanoptions->attributes', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', {
|
const span = tracer.startSpan('my-span', {
|
||||||
attributes: { foo: 'foo', bar: 'bar' },
|
attributes: { foo: 'foo', bar: 'bar' },
|
||||||
}) as Span;
|
}) as Span;
|
||||||
|
@ -181,7 +181,7 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with name and parent spancontext', () => {
|
it('should start a span with name and parent spancontext', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const state = new TraceState('a=1,b=2');
|
const state = new TraceState('a=1,b=2');
|
||||||
const span = tracer.startSpan('my-span', {
|
const span = tracer.startSpan('my-span', {
|
||||||
parent: {
|
parent: {
|
||||||
|
@ -199,7 +199,7 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with name and parent span', () => {
|
it('should start a span with name and parent span', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span');
|
const span = tracer.startSpan('my-span');
|
||||||
const childSpan = tracer.startSpan('child-span', {
|
const childSpan = tracer.startSpan('child-span', {
|
||||||
parent: span,
|
parent: span,
|
||||||
|
@ -212,7 +212,7 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with name and with invalid parent span', () => {
|
it('should start a span with name and with invalid parent span', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', {
|
const span = tracer.startSpan('my-span', {
|
||||||
parent: ('invalid-parent' as unknown) as undefined,
|
parent: ('invalid-parent' as unknown) as undefined,
|
||||||
}) as Span;
|
}) as Span;
|
||||||
|
@ -220,7 +220,7 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should start a span with name and with invalid spancontext', () => {
|
it('should start a span with name and with invalid spancontext', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', {
|
const span = tracer.startSpan('my-span', {
|
||||||
parent: { traceId: '0', spanId: '0' },
|
parent: { traceId: '0', spanId: '0' },
|
||||||
});
|
});
|
||||||
|
@ -233,10 +233,10 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a no recording span when never sampling', () => {
|
it('should return a no recording span when never sampling', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
sampler: NEVER_SAMPLER,
|
sampler: NEVER_SAMPLER,
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan('my-span');
|
const span = tracer.startSpan('my-span');
|
||||||
assert.ok(span instanceof NoRecordingSpan);
|
assert.ok(span instanceof NoRecordingSpan);
|
||||||
const context = span.context();
|
const context = span.context();
|
||||||
|
@ -248,9 +248,9 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create real span when not sampled but recording events true', () => {
|
it('should create real span when not sampled but recording events true', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
sampler: NEVER_SAMPLER,
|
sampler: NEVER_SAMPLER,
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', { isRecording: true });
|
const span = tracer.startSpan('my-span', { isRecording: true });
|
||||||
assert.ok(span instanceof Span);
|
assert.ok(span instanceof Span);
|
||||||
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
||||||
|
@ -258,10 +258,10 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create real span when not sampled and recording events false', () => {
|
it('should not create real span when not sampled and recording events false', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
sampler: NEVER_SAMPLER,
|
sampler: NEVER_SAMPLER,
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', { isRecording: false });
|
const span = tracer.startSpan('my-span', { isRecording: false });
|
||||||
assert.ok(span instanceof NoRecordingSpan);
|
assert.ok(span instanceof NoRecordingSpan);
|
||||||
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
||||||
|
@ -269,10 +269,10 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create real span when not sampled and no recording events configured', () => {
|
it('should not create real span when not sampled and no recording events configured', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
sampler: NEVER_SAMPLER,
|
sampler: NEVER_SAMPLER,
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan('my-span');
|
const span = tracer.startSpan('my-span');
|
||||||
assert.ok(span instanceof NoRecordingSpan);
|
assert.ok(span instanceof NoRecordingSpan);
|
||||||
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
|
||||||
|
@ -280,10 +280,10 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create real span when sampled and recording events true', () => {
|
it('should create real span when sampled and recording events true', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
sampler: ALWAYS_SAMPLER,
|
sampler: ALWAYS_SAMPLER,
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan('my-span', { isRecording: true });
|
const span = tracer.startSpan('my-span', { isRecording: true });
|
||||||
assert.ok(span instanceof Span);
|
assert.ok(span instanceof Span);
|
||||||
assert.strictEqual(span.context().traceFlags, TraceFlags.SAMPLED);
|
assert.strictEqual(span.context().traceFlags, TraceFlags.SAMPLED);
|
||||||
|
@ -294,10 +294,10 @@ describe('BasicTracer', () => {
|
||||||
const defaultAttributes = {
|
const defaultAttributes = {
|
||||||
foo: 'bar',
|
foo: 'bar',
|
||||||
};
|
};
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
scopeManager: new NoopScopeManager(),
|
scopeManager: new NoopScopeManager(),
|
||||||
defaultAttributes,
|
defaultAttributes,
|
||||||
});
|
}).getTracer('default');
|
||||||
|
|
||||||
const span = tracer.startSpan('my-span') as Span;
|
const span = tracer.startSpan('my-span') as Span;
|
||||||
assert.ok(span instanceof Span);
|
assert.ok(span instanceof Span);
|
||||||
|
@ -306,25 +306,25 @@ describe('BasicTracer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.getCurrentSpan()', () => {
|
describe('.getCurrentSpan()', () => {
|
||||||
it('should return undefined with NoopScopeManager', () => {
|
it('should return null with NoopScopeManager', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const currentSpan = tracer.getCurrentSpan();
|
const currentSpan = tracer.getCurrentSpan();
|
||||||
assert.deepStrictEqual(currentSpan, undefined);
|
assert.deepStrictEqual(currentSpan, undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return current span when it exists', () => {
|
it('should return current span when it exists', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
scopeManager: {
|
scopeManager: {
|
||||||
active: () => 'foo',
|
active: () => 'foo',
|
||||||
} as ScopeManager,
|
} as ScopeManager,
|
||||||
});
|
}).getTracer('default');
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), 'foo');
|
assert.deepStrictEqual(tracer.getCurrentSpan(), 'foo');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.withSpan()', () => {
|
describe('.withSpan()', () => {
|
||||||
it('should run scope with NoopScopeManager scope manager', done => {
|
it('should run scope with NoopScopeManager scope manager', done => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span');
|
const span = tracer.startSpan('my-span');
|
||||||
tracer.withSpan(span, () => {
|
tracer.withSpan(span, () => {
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
||||||
|
@ -335,7 +335,7 @@ describe('BasicTracer', () => {
|
||||||
|
|
||||||
describe('.bind()', () => {
|
describe('.bind()', () => {
|
||||||
it('should bind scope with NoopScopeManager scope manager', done => {
|
it('should bind scope with NoopScopeManager scope manager', done => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('my-span');
|
const span = tracer.startSpan('my-span');
|
||||||
const fn = () => {
|
const fn = () => {
|
||||||
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
|
||||||
|
@ -348,14 +348,14 @@ describe('BasicTracer', () => {
|
||||||
|
|
||||||
describe('.getBinaryFormat()', () => {
|
describe('.getBinaryFormat()', () => {
|
||||||
it('should get default binary formatter', () => {
|
it('should get default binary formatter', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
assert.ok(tracer.getBinaryFormat() instanceof BinaryTraceContext);
|
assert.ok(tracer.getBinaryFormat() instanceof BinaryTraceContext);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.getHttpTextFormat()', () => {
|
describe('.getHttpTextFormat()', () => {
|
||||||
it('should get default HTTP text formatter', () => {
|
it('should get default HTTP text formatter', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
assert.ok(tracer.getHttpTextFormat() instanceof HttpTraceContext);
|
assert.ok(tracer.getHttpTextFormat() instanceof HttpTraceContext);
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { MultiSpanProcessor } from '../src/MultiSpanProcessor';
|
import { MultiSpanProcessor } from '../src/MultiSpanProcessor';
|
||||||
import { SpanProcessor, Span, BasicTracer } from '../src';
|
import { SpanProcessor, Span, BasicTracerRegistry } from '../src';
|
||||||
|
|
||||||
class TestProcessor implements SpanProcessor {
|
class TestProcessor implements SpanProcessor {
|
||||||
spans: Span[] = [];
|
spans: Span[] = [];
|
||||||
|
@ -30,7 +30,7 @@ class TestProcessor implements SpanProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('MultiSpanProcessor', () => {
|
describe('MultiSpanProcessor', () => {
|
||||||
const tracer = new BasicTracer();
|
const tracer = new BasicTracerRegistry().getTracer('default');
|
||||||
const span = tracer.startSpan('one');
|
const span = tracer.startSpan('one');
|
||||||
|
|
||||||
it('should handle empty span processor', () => {
|
it('should handle empty span processor', () => {
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
TraceFlags,
|
TraceFlags,
|
||||||
SpanContext,
|
SpanContext,
|
||||||
} from '@opentelemetry/types';
|
} from '@opentelemetry/types';
|
||||||
import { BasicTracer, Span } from '../src';
|
import { BasicTracerRegistry, Span } from '../src';
|
||||||
import {
|
import {
|
||||||
hrTime,
|
hrTime,
|
||||||
hrTimeToNanoseconds,
|
hrTimeToNanoseconds,
|
||||||
|
@ -33,9 +33,9 @@ import {
|
||||||
const performanceTimeOrigin = hrTime();
|
const performanceTimeOrigin = hrTime();
|
||||||
|
|
||||||
describe('Span', () => {
|
describe('Span', () => {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
}).getTracer('default');
|
||||||
const name = 'span1';
|
const name = 'span1';
|
||||||
const spanContext: SpanContext = {
|
const spanContext: SpanContext = {
|
||||||
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
|
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
|
||||||
|
|
|
@ -18,26 +18,26 @@ import * as assert from 'assert';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
import {
|
import {
|
||||||
Span,
|
Span,
|
||||||
BasicTracer,
|
BasicTracerRegistry,
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
BatchSpanProcessor,
|
BatchSpanProcessor,
|
||||||
} from '../../src';
|
} from '../../src';
|
||||||
import { NEVER_SAMPLER, ALWAYS_SAMPLER, NoopLogger } from '@opentelemetry/core';
|
import { NEVER_SAMPLER, ALWAYS_SAMPLER, NoopLogger } from '@opentelemetry/core';
|
||||||
|
|
||||||
function createSampledSpan(spanName: string): Span {
|
function createSampledSpan(spanName: string): Span {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
sampler: ALWAYS_SAMPLER,
|
sampler: ALWAYS_SAMPLER,
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan(spanName);
|
const span = tracer.startSpan(spanName);
|
||||||
span.end();
|
span.end();
|
||||||
return span as Span;
|
return span as Span;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createUnSampledSpan(spanName: string): Span {
|
function createUnSampledSpan(spanName: string): Span {
|
||||||
const tracer = new BasicTracer({
|
const tracer = new BasicTracerRegistry({
|
||||||
sampler: NEVER_SAMPLER,
|
sampler: NEVER_SAMPLER,
|
||||||
logger: new NoopLogger(),
|
logger: new NoopLogger(),
|
||||||
});
|
}).getTracer('default');
|
||||||
const span = tracer.startSpan(spanName, { isRecording: false });
|
const span = tracer.startSpan(spanName, { isRecording: false });
|
||||||
span.end();
|
span.end();
|
||||||
return span as Span;
|
return span as Span;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
import {
|
import {
|
||||||
BasicTracer,
|
BasicTracerRegistry,
|
||||||
ConsoleSpanExporter,
|
ConsoleSpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
} from '../../src';
|
} from '../../src';
|
||||||
|
@ -39,15 +39,17 @@ describe('ConsoleSpanExporter', () => {
|
||||||
describe('.export()', () => {
|
describe('.export()', () => {
|
||||||
it('should export information about span', () => {
|
it('should export information about span', () => {
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
const basicTracer = new BasicTracer();
|
const basicTracerRegistry = new BasicTracerRegistry();
|
||||||
consoleExporter = new ConsoleSpanExporter();
|
consoleExporter = new ConsoleSpanExporter();
|
||||||
|
|
||||||
const spyConsole = sinon.spy(console, 'log');
|
const spyConsole = sinon.spy(console, 'log');
|
||||||
const spyExport = sinon.spy(consoleExporter, 'export');
|
const spyExport = sinon.spy(consoleExporter, 'export');
|
||||||
|
|
||||||
basicTracer.addSpanProcessor(new SimpleSpanProcessor(consoleExporter));
|
basicTracerRegistry.addSpanProcessor(
|
||||||
|
new SimpleSpanProcessor(consoleExporter)
|
||||||
|
);
|
||||||
|
|
||||||
const span = basicTracer.startSpan('foo');
|
const span = basicTracerRegistry.getTracer('default').startSpan('foo');
|
||||||
span.addEvent('foobar');
|
span.addEvent('foobar');
|
||||||
span.end();
|
span.end();
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,14 @@ import * as assert from 'assert';
|
||||||
import {
|
import {
|
||||||
InMemorySpanExporter,
|
InMemorySpanExporter,
|
||||||
SimpleSpanProcessor,
|
SimpleSpanProcessor,
|
||||||
BasicTracer,
|
BasicTracerRegistry,
|
||||||
} from '../../src';
|
} from '../../src';
|
||||||
import { ExportResult } from '@opentelemetry/base';
|
import { ExportResult } from '@opentelemetry/base';
|
||||||
|
|
||||||
describe('InMemorySpanExporter', () => {
|
describe('InMemorySpanExporter', () => {
|
||||||
const memoryExporter = new InMemorySpanExporter();
|
const memoryExporter = new InMemorySpanExporter();
|
||||||
const tracer = new BasicTracer();
|
const registry = new BasicTracerRegistry();
|
||||||
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
// reset spans in memory.
|
// reset spans in memory.
|
||||||
|
@ -33,9 +33,13 @@ describe('InMemorySpanExporter', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get finished spans', () => {
|
it('should get finished spans', () => {
|
||||||
const root = tracer.startSpan('root');
|
const root = registry.getTracer('default').startSpan('root');
|
||||||
const child = tracer.startSpan('child', { parent: root });
|
const child = registry
|
||||||
const grandChild = tracer.startSpan('grand-child', { parent: child });
|
.getTracer('default')
|
||||||
|
.startSpan('child', { parent: root });
|
||||||
|
const grandChild = registry
|
||||||
|
.getTracer('default')
|
||||||
|
.startSpan('grand-child', { parent: child });
|
||||||
|
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
||||||
grandChild.end();
|
grandChild.end();
|
||||||
|
@ -56,15 +60,21 @@ describe('InMemorySpanExporter', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should shutdown the exorter', () => {
|
it('should shutdown the exorter', () => {
|
||||||
const root = tracer.startSpan('root');
|
const root = registry.getTracer('default').startSpan('root');
|
||||||
tracer.startSpan('child', { parent: root }).end();
|
registry
|
||||||
|
.getTracer('default')
|
||||||
|
.startSpan('child', { parent: root })
|
||||||
|
.end();
|
||||||
root.end();
|
root.end();
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 2);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 2);
|
||||||
memoryExporter.shutdown();
|
memoryExporter.shutdown();
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
||||||
|
|
||||||
// after shutdown no new spans are accepted
|
// after shutdown no new spans are accepted
|
||||||
tracer.startSpan('child1', { parent: root }).end();
|
registry
|
||||||
|
.getTracer('default')
|
||||||
|
.startSpan('child1', { parent: root })
|
||||||
|
.end();
|
||||||
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue