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:
Daniel Dyla 2020-01-09 11:29:38 -05:00 committed by Mayur Kale
parent 059595a215
commit 18c6aa4f19
107 changed files with 981 additions and 942 deletions

1
.gitignore vendored
View File

@ -71,6 +71,7 @@ docs
#lerna
.changelog
package.json.lerna_backup
# OS generated files
.DS_Store

View File

@ -2,26 +2,26 @@
const benchmark = require('./benchmark');
const opentelemetry = require('@opentelemetry/core');
const { BasicTracer, BatchSpanProcessor, InMemorySpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { NodeTracer } = require('@opentelemetry/node');
const { BasicTracerRegistry, BatchSpanProcessor, InMemorySpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const exporter = new InMemorySpanExporter();
const logger = new opentelemetry.NoopLogger();
const setups = [
{
name: 'BasicTracer',
tracer: new BasicTracer({ logger })
name: 'BasicTracerRegistry',
registry: new BasicTracerRegistry({ logger })
},
{
name: 'NodeTracer',
tracer: new NodeTracer({ logger })
name: 'NodeTracerRegistry',
registry: new NodeTracerRegistry({ logger })
}
];
for (const setup of setups) {
console.log(`Beginning ${setup.name} Benchmark...`);
const tracer = setup.tracer;
const tracer = setup.registry.getTracer("benchmark");
const suite = benchmark()
.add('#startSpan', function () {
const span = tracer.startSpan('op');
@ -55,7 +55,7 @@ for (const setup of setups) {
.add('#startSpan with SimpleSpanProcessor', function () {
const simpleSpanProcessor = new SimpleSpanProcessor(exporter);
tracer.addSpanProcessor(simpleSpanProcessor);
registry.addSpanProcessor(simpleSpanProcessor);
const span = tracer.startSpan('op');
span.end();
@ -64,7 +64,7 @@ for (const setup of setups) {
.add('#startSpan with BatchSpanProcessor', function () {
const batchSpanProcessor = new BatchSpanProcessor(exporter);
tracer.addSpanProcessor(batchSpanProcessor);
registry.addSpanProcessor(batchSpanProcessor);
const span = tracer.startSpan('op');
span.end();
batchSpanProcessor.shutdown();

View File

@ -1,5 +1,5 @@
const opentelemetry = require('@opentelemetry/core');
const { BasicTracer, SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { BasicTracerRegistry, SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
@ -20,16 +20,17 @@ if (EXPORTER.toLowerCase().startsWith('z')) {
exporter = new CollectorExporter(options);
}
const tracer = new BasicTracer();
const registry = new BasicTracerRegistry();
// 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
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
const tracer = opentelemetry.getTracer('example-basic-tracer-node')
// 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++) {
doWork(span);
}
@ -42,7 +43,7 @@ exporter.shutdown();
function doWork(parent) {
// 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.
const span = opentelemetry.getTracer().startSpan('doWork', {
const span = tracer.startSpan('doWork', {
parent: parent
});

View File

@ -1,10 +1,10 @@
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 { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
const tracer = new BasicTracer();
const registry = new BasicTracerRegistry();
const zipkinExporter = new ZipkinExporter({serviceName: 'basic-service'});
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
// 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.
}));
// It is recommended to use SimpleSpanProcessor in case of Jaeger exporter as
// 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
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
const tracer = opentelemetry.getTracer('default');
// 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++) {
doWork(span);
}
@ -43,7 +44,7 @@ collectorExporter.shutdown();
function doWork(parent) {
// 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.
const span = opentelemetry.getTracer().startSpan('doWork', {
const span = tracer.startSpan('doWork', {
parent: parent
});

View File

@ -10,7 +10,7 @@ const config = require('./setup');
config.setupTracerAndExporters('dns-client-service');
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. */
function makeLookup() {

View File

@ -1,14 +1,14 @@
'use strict';
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const EXPORTER = process.env.EXPORTER || '';
function setupTracerAndExporters(service) {
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
      plugins: {
          dns: {
            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
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
}
exports.setupTracerAndExporters = setupTracerAndExporters;

View File

@ -14,7 +14,7 @@ const grpc = require('grpc');
const messages = require('./helloworld_pb');
const services = require('./helloworld_grpc_pb');
const PORT = 50051;
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-grpc-client');
/** A function which makes requests and handles response. */
function main() {

View File

@ -10,7 +10,7 @@ const config = require('./setup');
config.setupTracerAndExporters('grpc-server-service');
const grpc = require('grpc');
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-grpc-server');
const messages = require('./helloworld_pb');
const services = require('./helloworld_grpc_pb');

View File

@ -1,14 +1,14 @@
'use strict';
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const EXPORTER = process.env.EXPORTER || '';
function setupTracerAndExporters(service) {
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
grpc: {
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
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
}
exports.setupTracerAndExporters = setupTracerAndExporters;

View File

@ -13,7 +13,7 @@ const path = require('path');
const grpc = require('grpc');
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_OPTIONS = { keepCase: true, enums: String, defaults: true, oneofs: true };

View File

@ -19,7 +19,7 @@ const PROTO_OPTIONS = { keepCase: true, enums: String, defaults: true, oneofs: t
const definition = protoLoader.loadSync(PROTO_PATH, PROTO_OPTIONS);
const rpcProto = grpc.loadPackageDefinition(definition).rpc;
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-grpc-capitalize-server');
/** Implements the Capitalize RPC method. */
function capitalize(call, callback) {

View File

@ -1,14 +1,14 @@
'use strict';
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const EXPORTER = process.env.EXPORTER || '';
function setupTracerAndExporters(service) {
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
grpc: {
enabled: true,
@ -31,10 +31,10 @@ function setupTracerAndExporters(service) {
// It is recommended to use this `BatchSpanProcessor` for better performance
// and optimization, especially in production.
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
}
exports.setupTracerAndExporters = setupTracerAndExporters;

View File

@ -10,7 +10,7 @@ const config = require('./setup');
config.setupTracerAndExporters('http-client-service');
const http = require('http');
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-http-client');
/** A function which makes requests and handles response. */
function makeRequest() {

View File

@ -9,7 +9,7 @@ const config = require('./setup');
config.setupTracerAndExporters('http-server-service');
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. */
function startServer (port) {

View File

@ -1,14 +1,14 @@
'use strict';
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const EXPORTER = process.env.EXPORTER || '';
function setupTracerAndExporters(service) {
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
let exporter;
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
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
}
exports.setupTracerAndExporters = setupTracerAndExporters;

View File

@ -9,7 +9,7 @@ const config = require('./setup');
config.setupTracerAndExporters('https-client-service');
const https = require('https');
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-https-client');
/** A function which makes requests and handles response. */
function makeRequest() {
@ -31,7 +31,7 @@ function makeRequest() {
});
});
});
// The process must live for at least the interval past any traces that
// must be exported, or some risk being lost if they are recorded after the
// last export.

View File

@ -10,7 +10,7 @@ const config = require('./setup');
config.setupTracerAndExporters('https-server-service');
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. */
function startServer (port) {

View File

@ -1,7 +1,7 @@
'use strict';
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
@ -9,7 +9,7 @@ const EXPORTER = process.env.EXPORTER || '';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
function setupTracerAndExporters(service) {
let exporter;
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
if (EXPORTER.toLowerCase().startsWith('z')) {
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
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
}
exports.setupTracerAndExporters = setupTracerAndExporters;

View File

@ -10,7 +10,7 @@ const config = require('./setup');
config.setupTracerAndExporters('http-client-service');
const http = require('http');
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-mysql-http-client');
/** A function which makes requests and handles response. */
function makeRequest() {

View File

@ -11,7 +11,7 @@ config.setupTracerAndExporters('http-mysql-server-service');
const mysql = require('mysql');
const http = require('http');
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-mysql-http-server');
const pool = mysql.createPool({
host : 'localhost',

View File

@ -1,13 +1,13 @@
'use strict';
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
function setupTracerAndExporters(service) {
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
mysql: {
enabled: true,
@ -20,15 +20,15 @@ function setupTracerAndExporters(service) {
}
});
tracer.addSpanProcessor(new SimpleSpanProcessor(new ZipkinExporter({
registry.addSpanProcessor(new SimpleSpanProcessor(new ZipkinExporter({
serviceName: service,
})));
tracer.addSpanProcessor(new SimpleSpanProcessor(new JaegerExporter({
registry.addSpanProcessor(new SimpleSpanProcessor(new JaegerExporter({
serviceName: service,
})));
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
}
exports.setupTracerAndExporters = setupTracerAndExporters;

View File

@ -1,17 +1,17 @@
"use strict";
const { NodeTracer } = require("@opentelemetry/node");
const { NodeTracerRegistry } = require("@opentelemetry/node");
const { SimpleSpanProcessor } = require("@opentelemetry/tracing");
const { JaegerExporter } = require("@opentelemetry/exporter-jaeger");
const { ZipkinExporter } = require("@opentelemetry/exporter-zipkin");
const { TracerShim } = require("@opentelemetry/shim-opentracing");
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) {

View File

@ -4,7 +4,7 @@ const opentelemetry = require('@opentelemetry/core');
const types = require('@opentelemetry/types');
const config = require('./setup');
config.setupTracerAndExporters('redis-client-service');
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-redis-client');
const axios = require('axios').default;
function makeRequest() {

View File

@ -4,7 +4,7 @@
const opentelemetry = require('@opentelemetry/core');
const config = require('./setup');
config.setupTracerAndExporters('redis-server-service');
const tracer = opentelemetry.getTracer();
const tracer = opentelemetry.getTracer('example-redis-server');
// Require in rest of modules
const express = require('express');

View File

@ -1,14 +1,14 @@
'use strict';
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const EXPORTER = process.env.EXPORTER || '';
function setupTracerAndExporters(service) {
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
let exporter;
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
opentelemetry.initGlobalTracer(tracer);
// Initialize the OpenTelemetry APIs to use the BasicTracerRegistry bindings
opentelemetry.initGlobalTracerRegistry(registry);
}
exports.setupTracerAndExporters = setupTracerAndExporters;

View File

@ -1,26 +1,27 @@
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracer } from '@opentelemetry/web';
import { WebTracerRegistry } from '@opentelemetry/web';
import { DocumentLoad } from '@opentelemetry/plugin-document-load';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { CollectorExporter } from '@opentelemetry/exporter-collector'
const webTracer = new WebTracer({
const registry = new WebTracerRegistry({
plugins: [
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(),
plugins: [
new DocumentLoad()
]
});
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorExporter()));
registryWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
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
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 element = document.getElementById('button1');
let mainSpan = webTracerWithZone.startSpan('main-span');
webTracerWithZone.bind(element, mainSpan);
let mainSpan = tracerWithZone.startSpan('main-span');
tracerWithZone.bind(element, mainSpan);
const onClick = () => {
const span1 = webTracerWithZone.startSpan(`files-series-info-1`, {
parent: webTracerWithZone.getCurrentSpan()
const span1 = tracerWithZone.startSpan(`files-series-info-1`, {
parent: tracerWithZone.getCurrentSpan()
});
const span2 = webTracerWithZone.startSpan(`files-series-info-2`, {
parent: webTracerWithZone.getCurrentSpan()
const span2 = tracerWithZone.startSpan(`files-series-info-2`, {
parent: tracerWithZone.getCurrentSpan()
});
webTracerWithZone.withSpan(span1, () => {
tracerWithZone.withSpan(span1, () => {
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);
webTracerWithZone.getCurrentSpan().addEvent('fetching-span1-completed');
tracerWithZone.getCurrentSpan().addEvent('fetching-span1-completed');
span1.end();
});
});
webTracerWithZone.withSpan(span2, () => {
tracerWithZone.withSpan(span2, () => {
getData(url2).then((data) => {
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);
webTracerWithZone.getCurrentSpan().addEvent('fetching-span2-completed');
tracerWithZone.getCurrentSpan().addEvent('fetching-span2-completed');
span2.end();
}, 100);
});

View File

@ -27,10 +27,10 @@ export * from './trace/globaltracer-utils';
export * from './trace/instrumentation/BasePlugin';
export * from './trace/NoopSpan';
export * from './trace/NoopTracer';
export * from './trace/NoopTracerRegistry';
export * from './trace/NoRecordingSpan';
export * from './trace/sampler/ProbabilitySampler';
export * from './trace/spancontext-utils';
export * from './trace/TracerDelegate';
export * from './trace/TraceState';
export * from './metrics/NoopMeter';
export * from './utils/url';

View File

@ -59,3 +59,5 @@ export class NoopTracer implements Tracer {
return NOOP_HTTP_TEXT_FORMAT;
}
}
export const noopTracer = new NoopTracer();

View File

@ -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;
}
}

View File

@ -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
);
}
}

View File

@ -15,21 +15,31 @@
*/
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
*/
export function initGlobalTracer(tracer: types.Tracer): types.Tracer {
return (globalTracerDelegate = new TracerDelegate(tracer));
export function initGlobalTracerRegistry(
tracerRegistry: types.TracerRegistry
): types.TracerRegistry {
return (globalTracerRegistry = tracerRegistry);
}
/**
* Returns the global tracer
* Returns the global tracer registry.
*/
export function getTracer(): types.Tracer {
// Return the global tracer delegate
return globalTracerDelegate;
export function getTracerRegistry(): types.TracerRegistry {
// Return the global tracer registry
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);
}

View File

@ -21,6 +21,7 @@ import {
PluginConfig,
PluginInternalFiles,
PluginInternalFilesVersion,
TracerRegistry,
} from '@opentelemetry/types';
import * as semver from 'semver';
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 _config!: PluginConfig;
constructor(
protected readonly _tracerName: string,
protected readonly _tracerVersion?: string
) {}
enable(
moduleExports: T,
tracer: Tracer,
tracerRegistry: TracerRegistry,
logger: Logger,
config?: PluginConfig
): T {
this._moduleExports = moduleExports;
this._tracer = tracer;
this._tracer = tracerRegistry.getTracer(
this._tracerName,
this._tracerVersion
);
this._logger = logger;
this._internalFilesExports = this._loadInternalFilesExports();
if (config) this._config = config;

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
import { BasePlugin, NoopTracer, NoopLogger } from '../../src';
import * as assert from 'assert';
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';
const tracer = new NoopTracer();
const registry = new NoopTracerRegistry();
const logger = new NoopLogger();
describe('BasePlugin', () => {
@ -28,7 +29,7 @@ describe('BasePlugin', () => {
const testPackage = require('./fixtures/test-package');
const plugin = new TestPlugin();
assert.doesNotThrow(() => {
plugin.enable(testPackage, tracer, logger);
plugin.enable(testPackage, registry, logger);
});
// @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 _basedir = basedir;
constructor() {
super('test-package.opentelemetry');
}
protected readonly _internalFilesList = {
'0.1.0': {
internal: 'foo/bar/internal.js',

View File

@ -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);
}
}
});

View File

@ -17,11 +17,12 @@
import * as assert from 'assert';
import * as types from '@opentelemetry/types';
import {
getTracer,
initGlobalTracer,
getTracerRegistry,
initGlobalTracerRegistry,
} from '../../src/trace/globaltracer-utils';
import { NoopTracer, NoopSpan } from '../../src';
import { TraceFlags } from '@opentelemetry/types';
import { NoopTracerRegistry } from '../../src/trace/NoopTracerRegistry';
describe('globaltracer-utils', () => {
const functions = [
@ -32,13 +33,13 @@ describe('globaltracer-utils', () => {
'getHttpTextFormat',
];
it('should expose a tracer via getTracer', () => {
const tracer = getTracer();
it('should expose a tracer registry via getTracerRegistry', () => {
const tracer = getTracerRegistry();
assert.ok(tracer);
assert.strictEqual(typeof tracer, 'object');
});
describe('GlobalTracer', () => {
describe('GlobalTracerRegistry', () => {
const spanContext = {
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
spanId: '6e0c63257de34c92',
@ -47,12 +48,12 @@ describe('globaltracer-utils', () => {
const dummySpan = new NoopSpan(spanContext);
afterEach(() => {
initGlobalTracer(new NoopTracer());
initGlobalTracerRegistry(new NoopTracerRegistry());
});
it('should not crash', () => {
functions.forEach(fn => {
const tracer = getTracer();
const tracer = getTracerRegistry();
try {
((tracer as unknown) as { [fn: string]: Function })[fn](); // Try to run the function
assert.ok(true, fn);
@ -64,8 +65,9 @@ describe('globaltracer-utils', () => {
});
});
it('should use the global tracer', () => {
const tracer = initGlobalTracer(new TestTracer());
it('should use the global tracer registry', () => {
initGlobalTracerRegistry(new TestTracerRegistry());
const tracer = getTracerRegistry().getTracer('name');
const span = tracer.startSpan('test');
assert.deepStrictEqual(span, dummySpan);
});
@ -78,5 +80,11 @@ describe('globaltracer-utils', () => {
return dummySpan;
}
}
class TestTracerRegistry extends NoopTracerRegistry {
getTracer(_name: string, version?: string) {
return new TestTracer();
}
}
});
});

View File

@ -35,18 +35,18 @@ opentelemetry.initGlobalTracer(tracer);
## Usage in Node
```js
const opentelemetry = require('@opentelemetry/core');
const { BasicTracer, SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { BasicTracerRegistry, SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { CollectorExporter } = require('@opentelemetry/exporter-collector');
const collectorOptions = {
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);
tracer.addSpanProcessor(new SimpleSpanProcessor(exporter));
registry.addSpanProcessor(new SimpleSpanProcessor(exporter));
opentelemetry.initGlobalTracer(tracer);
opentelemetry.initGlobalTracerRegistry(registry);
```

View File

@ -16,7 +16,7 @@
import * as assert from 'assert';
import * as types from '@opentelemetry/types';
import { Span, BasicTracer } from '@opentelemetry/tracing';
import { Span, BasicTracerRegistry } from '@opentelemetry/tracing';
import {
NoopLogger,
hrTimeToMicroseconds,
@ -32,9 +32,9 @@ import {
import * as zipkinTypes from '../src/types';
const logger = new NoopLogger();
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
logger,
});
}).getTracer('default');
const parentId = '5c1c63257de34c67';
const spanContext: types.SpanContext = {
traceId: 'd4cda95b652f4a1592b449d5929fda1b',

View File

@ -11,14 +11,14 @@ For manual instrumentation see the
[@opentelemetry/tracing](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing) package.
## 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)).
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.
@ -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.
## 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
@ -50,14 +50,14 @@ npm install --save @opentelemetry/plugin-https
## 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
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
// Create and configure NodeTracer
const tracer = new NodeTracer({
// Create and configure NodeTracerRegistry
const registry = new NodeTracerRegistry({
plugins: {
http: {
enabled: true,
@ -68,25 +68,25 @@ const tracer = new NodeTracer({
}
});
// Initialize the tracer
opentelemetry.initGlobalTracer(tracer);
// Initialize the registry
opentelemetry.initGlobalTracerRegistry(registry);
// Your application code - http will automatically be instrumented if
// @opentelemetry/plugin-http is present
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
const opentelemetry = require('@opentelemetry/core');
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
// Create and initialize NodeTracer
const tracer = new NodeTracer();
// Create and initialize NodeTracerRegistry
const registry = new NodeTracerRegistry();
// Initialize the tracer
opentelemetry.initGlobalTracer(tracer);
// Initialize the registry
opentelemetry.initGlobalTracerRegistry(registry);
// Your application code
// ...

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { BasicTracer } from '@opentelemetry/tracing';
import { BasicTracerRegistry } from '@opentelemetry/tracing';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { PluginLoader } from './instrumentation/PluginLoader';
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.
*/
export class NodeTracer extends BasicTracer {
export class NodeTracerRegistry extends BasicTracerRegistry {
private readonly _pluginLoader: PluginLoader;
/**

View File

@ -15,12 +15,12 @@
*/
import { Plugins } from './instrumentation/PluginLoader';
import { BasicTracerConfig } from '@opentelemetry/tracing';
import { TracerConfig } from '@opentelemetry/tracing';
/**
* NodeTracerConfig provides an interface for configuring a Node Tracer.
*/
export interface NodeTracerConfig extends BasicTracerConfig {
export interface NodeTracerConfig extends TracerConfig {
/** Plugins options. */
plugins?: Plugins;
}

View File

@ -14,4 +14,4 @@
* limitations under the License.
*/
export * from './NodeTracer';
export * from './NodeTracerRegistry';

View File

@ -14,7 +14,12 @@
* 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 utils from './utils';
@ -55,7 +60,7 @@ export class PluginLoader {
private _hookState = HookState.UNINITIALIZED;
/** 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
@ -115,7 +120,7 @@ export class PluginLoader {
this._plugins.push(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) {
this.logger.error(
`PluginLoader#load: could not load plugin ${modulePath} of module ${name}. Error: ${e.message}`

View File

@ -23,7 +23,7 @@ import {
NoopLogger,
NoRecordingSpan,
} from '@opentelemetry/core';
import { NodeTracer } from '../src/NodeTracer';
import { NodeTracerRegistry } from '../src/NodeTracerRegistry';
import { TraceFlags } from '@opentelemetry/types';
import { Span } from '@opentelemetry/tracing';
import * as path from 'path';
@ -39,8 +39,8 @@ const INSTALLED_PLUGINS_PATH = path.join(
'node_modules'
);
describe('NodeTracer', () => {
let tracer: NodeTracer;
describe('NodeTracerRegistry', () => {
let registry: NodeTracerRegistry;
before(() => {
module.paths.push(INSTALLED_PLUGINS_PATH);
});
@ -48,45 +48,45 @@ describe('NodeTracer', () => {
afterEach(() => {
// clear require cache
Object.keys(require.cache).forEach(key => delete require.cache[key]);
tracer.stop();
registry.stop();
});
describe('constructor', () => {
it('should construct an instance with required only options', () => {
tracer = new NodeTracer();
assert.ok(tracer instanceof NodeTracer);
registry = new NodeTracerRegistry();
assert.ok(registry instanceof NodeTracerRegistry);
});
it('should construct an instance with binary format', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
binaryFormat: new BinaryTraceContext(),
});
assert.ok(tracer instanceof NodeTracer);
assert.ok(registry instanceof NodeTracerRegistry);
});
it('should construct an instance with http text format', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
httpTextFormat: new HttpTraceContext(),
});
assert.ok(tracer instanceof NodeTracer);
assert.ok(registry instanceof NodeTracerRegistry);
});
it('should construct an instance with logger', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
logger: new NoopLogger(),
});
assert.ok(tracer instanceof NodeTracer);
assert.ok(registry instanceof NodeTracerRegistry);
});
it('should construct an instance with sampler', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
sampler: ALWAYS_SAMPLER,
});
assert.ok(tracer instanceof NodeTracer);
assert.ok(registry instanceof NodeTracerRegistry);
});
it('should load user configured plugins', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
logger: new NoopLogger(),
plugins: {
'simple-module': {
@ -102,7 +102,7 @@ describe('NodeTracer', () => {
},
},
});
const pluginLoader = tracer['_pluginLoader'];
const pluginLoader = registry['_pluginLoader'];
assert.strictEqual(pluginLoader['_plugins'].length, 0);
require('simple-module');
assert.strictEqual(pluginLoader['_plugins'].length, 1);
@ -111,39 +111,39 @@ describe('NodeTracer', () => {
});
it('should construct an instance with default attributes', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
defaultAttributes: {
region: 'eu-west',
asg: 'my-asg',
},
});
assert.ok(tracer instanceof NodeTracer);
assert.ok(registry instanceof NodeTracerRegistry);
});
});
describe('.startSpan()', () => {
it('should start a span with name only', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
logger: new NoopLogger(),
});
const span = tracer.startSpan('my-span');
const span = registry.getTracer('default').startSpan('my-span');
assert.ok(span);
});
it('should start a span with name and options', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
logger: new NoopLogger(),
});
const span = tracer.startSpan('my-span', {});
const span = registry.getTracer('default').startSpan('my-span', {});
assert.ok(span);
});
it('should return a default span with no sampling', () => {
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
sampler: NEVER_SAMPLER,
logger: new NoopLogger(),
});
const span = tracer.startSpan('my-span');
const span = registry.getTracer('default').startSpan('my-span');
assert.ok(span instanceof NoRecordingSpan);
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
assert.strictEqual(span.isRecording(), false);
@ -156,11 +156,11 @@ describe('NodeTracer', () => {
const defaultAttributes = {
foo: 'bar',
};
tracer = new NodeTracer({
registry = new NodeTracerRegistry({
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.deepStrictEqual(span.attributes, defaultAttributes);
});
@ -168,32 +168,48 @@ describe('NodeTracer', () => {
describe('.getCurrentSpan()', () => {
it('should return undefined with AsyncHooksScopeManager when no span started', () => {
tracer = new NodeTracer({});
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
registry = new NodeTracerRegistry({});
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
undefined
);
});
});
describe('.withSpan()', () => {
it('should run scope with AsyncHooksScopeManager scope manager', done => {
tracer = new NodeTracer({});
const span = tracer.startSpan('my-span');
tracer.withSpan(span, () => {
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
registry = new NodeTracerRegistry({});
const span = registry.getTracer('default').startSpan('my-span');
registry.getTracer('default').withSpan(span, () => {
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
span
);
return done();
});
// @todo: below check is not running.
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
undefined
);
});
it('should run scope with AsyncHooksScopeManager scope manager with multiple spans', done => {
tracer = new NodeTracer({});
const span = tracer.startSpan('my-span');
tracer.withSpan(span, () => {
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
registry = new NodeTracerRegistry({});
const span = registry.getTracer('default').startSpan('my-span');
registry.getTracer('default').withSpan(span, () => {
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
span
);
const span1 = tracer.startSpan('my-span1', { parent: span });
tracer.withSpan(span1, () => {
assert.deepStrictEqual(tracer.getCurrentSpan(), span1);
const span1 = registry
.getTracer('default')
.startSpan('my-span1', { parent: span });
registry.getTracer('default').withSpan(span1, () => {
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
span1
);
assert.deepStrictEqual(
span1.context().traceId,
span.context().traceId
@ -203,48 +219,66 @@ describe('NodeTracer', () => {
});
// when span ended.
// @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 => {
tracer = new NodeTracer({});
const span = tracer.startSpan('my-span');
tracer.withSpan(span, async () => {
registry = new NodeTracerRegistry({});
const span = registry.getTracer('default').startSpan('my-span');
registry.getTracer('default').withSpan(span, async () => {
for (let i = 0; i < 3; i++) {
await sleep(5).then(() => {
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
span
);
});
}
return done();
});
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
undefined
);
});
});
describe('.bind()', () => {
it('should bind scope with AsyncHooksScopeManager scope manager', done => {
const tracer = new NodeTracer({});
const span = tracer.startSpan('my-span');
const registry = new NodeTracerRegistry({});
const span = registry.getTracer('default').startSpan('my-span');
const fn = () => {
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
assert.deepStrictEqual(
registry.getTracer('default').getCurrentSpan(),
span
);
return done();
};
const patchedFn = tracer.bind(fn, span);
const patchedFn = registry.getTracer('default').bind(fn, span);
return patchedFn();
});
});
describe('.getBinaryFormat()', () => {
it('should get default binary formatter', () => {
tracer = new NodeTracer({});
assert.ok(tracer.getBinaryFormat() instanceof BinaryTraceContext);
registry = new NodeTracerRegistry({});
assert.ok(
registry.getTracer('default').getBinaryFormat() instanceof
BinaryTraceContext
);
});
});
describe('.getHttpTextFormat()', () => {
it('should get default HTTP text formatter', () => {
tracer = new NodeTracer({});
assert.ok(tracer.getHttpTextFormat() instanceof HttpTraceContext);
registry = new NodeTracerRegistry({});
assert.ok(
registry.getTracer('default').getHttpTextFormat() instanceof
HttpTraceContext
);
});
});
});

View File

@ -14,14 +14,14 @@
* limitations under the License.
*/
import { NoopLogger, NoopTracer } from '@opentelemetry/core';
import { NoopLogger, NoopTracerRegistry } from '@opentelemetry/core';
import * as assert from 'assert';
import * as path from 'path';
import {
HookState,
PluginLoader,
searchPathForTest,
Plugins,
searchPathForTest,
} from '../../src/instrumentation/PluginLoader';
const INSTALLED_PLUGINS_PATH = path.join(__dirname, 'node_modules');
@ -86,7 +86,7 @@ const notSupportedVersionPlugins: Plugins = {
};
describe('PluginLoader', () => {
const tracer = new NoopTracer();
const registry = new NoopTracerRegistry();
const logger = new NoopLogger();
before(() => {
@ -101,19 +101,19 @@ describe('PluginLoader', () => {
describe('.state()', () => {
it('returns UNINITIALIZED when first called', () => {
const pluginLoader = new PluginLoader(tracer, logger);
const pluginLoader = new PluginLoader(registry, logger);
assert.strictEqual(pluginLoader['_hookState'], HookState.UNINITIALIZED);
});
it('transitions from UNINITIALIZED to ENABLED', () => {
const pluginLoader = new PluginLoader(tracer, logger);
const pluginLoader = new PluginLoader(registry, logger);
pluginLoader.load(simplePlugins);
assert.strictEqual(pluginLoader['_hookState'], HookState.ENABLED);
pluginLoader.unload();
});
it('transitions from ENABLED to DISABLED', () => {
const pluginLoader = new PluginLoader(tracer, logger);
const pluginLoader = new PluginLoader(registry, logger);
pluginLoader.load(simplePlugins).unload();
assert.strictEqual(pluginLoader['_hookState'], HookState.DISABLED);
});
@ -138,7 +138,7 @@ describe('PluginLoader', () => {
});
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);
pluginLoader.load(simplePlugins);
// 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', () => {
const pluginLoader = new PluginLoader(tracer, logger);
const pluginLoader = new PluginLoader(registry, logger);
assert.strictEqual(pluginLoader['_plugins'].length, 0);
pluginLoader.load(httpPlugins);
// 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
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);
pluginLoader.load(notSupportedVersionPlugins);
// 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
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);
pluginLoader.load(supportedVersionPlugins);
// 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', () => {
const pluginLoader = new PluginLoader(tracer, logger);
const pluginLoader = new PluginLoader(registry, logger);
assert.strictEqual(pluginLoader['_plugins'].length, 0);
pluginLoader.load(disablePlugins);
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', () => {
const pluginLoader = new PluginLoader(tracer, logger);
const pluginLoader = new PluginLoader(registry, logger);
assert.strictEqual(pluginLoader['_plugins'].length, 0);
pluginLoader.load(missingPathPlugins);
const simpleModule = require('simple-module');
@ -205,7 +205,7 @@ describe('PluginLoader', () => {
});
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);
pluginLoader.load(nonexistentPlugins);
assert.strictEqual(pluginLoader['_plugins'].length, 0);
@ -213,7 +213,7 @@ describe('PluginLoader', () => {
});
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({});
assert.strictEqual(require('simple-module').value(), 0);
pluginLoader.unload();
@ -222,7 +222,7 @@ describe('PluginLoader', () => {
describe('.unload()', () => {
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);
pluginLoader.load(simplePlugins);
// The hook is only called the first time the module is loaded.

View File

@ -18,9 +18,9 @@ npm install --save @opentelemetry/plugin-dns
## Usage
```js
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
dns: {
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 :
```
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
dns: {
enabled: true,

View File

@ -14,22 +14,23 @@
* 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 { 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 {
Dns,
LookupPromiseSignature,
DnsPluginConfig,
LookupCallbackSignature,
LookupFunction,
LookupFunctionSignature,
LookupCallbackSignature,
DnsPluginConfig,
LookupPromiseSignature,
} from './types';
import { AttributeNames } from './enums/AttributeNames';
import { AddressFamily } from './enums/AddressFamily';
import { LookupAddress } from 'dns';
import * as utils from './utils';
import { VERSION } from './version';
/**
* Dns instrumentation plugin for Opentelemetry
@ -39,7 +40,7 @@ export class DnsPlugin extends BasePlugin<Dns> {
protected _config!: DnsPluginConfig;
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.
this.component = this.moduleName;
this._config = {};

View File

@ -20,19 +20,20 @@ import {
} from '@opentelemetry/tracing';
import * as assert from 'assert';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import { plugin } from '../../src/dns';
import * as sinon from 'sinon';
import * as dns from 'dns';
const memoryExporter = new InMemorySpanExporter();
const logger = new NoopLogger();
const tracer = new NodeTracer({ logger });
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const registry = new NodeTracerRegistry({ logger });
const tracer = registry.getTracer('default');
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
describe('DnsPlugin', () => {
before(() => {
plugin.enable(dns, tracer, tracer.logger);
plugin.enable(dns, registry, tracer.logger);
assert.strictEqual(dns.lookup.__wrapped, true);
});

View File

@ -20,18 +20,18 @@ import {
} from '@opentelemetry/tracing';
import * as assert from 'assert';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import { plugin, DnsPlugin } from '../../src/dns';
import * as dns from 'dns';
const memoryExporter = new InMemorySpanExporter();
const logger = new NoopLogger();
const tracer = new NodeTracer({ logger });
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const registry = new NodeTracerRegistry({ logger });
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
describe('DnsPlugin', () => {
before(() => {
plugin.enable(dns, tracer, tracer.logger);
plugin.enable(dns, registry, registry.logger);
});
after(() => {

View File

@ -14,14 +14,14 @@
* 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 sinon from 'sinon';
import { CanonicalCode, SpanKind } from '@opentelemetry/types';
import { AttributeNames } from '../../src/enums/AttributeNames';
import { IgnoreMatcher } from '../../src/types';
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('parseResponseStatus()', () => {
@ -162,7 +162,7 @@ describe('Utility', () => {
it('should have error attributes', () => {
const errorMessage = 'test error';
const span = new Span(
new BasicTracer(),
new BasicTracerRegistry().getTracer('default'),
'test',
{ spanId: '', traceId: '' },
SpanKind.INTERNAL

View File

@ -20,7 +20,7 @@ import {
} from '@opentelemetry/tracing';
import * as assert from 'assert';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import { plugin } from '../../src/dns';
import * as dns from 'dns';
import * as utils from '../utils/utils';
@ -29,14 +29,14 @@ import { CanonicalCode } from '@opentelemetry/types';
const memoryExporter = new InMemorySpanExporter();
const logger = new NoopLogger();
const tracer = new NodeTracer({ logger });
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const registry = new NodeTracerRegistry({ logger });
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
describe('dns.lookup()', () => {
before(function(done) {
// mandatory
if (process.env.CI) {
plugin.enable(dns, tracer, tracer.logger);
plugin.enable(dns, registry, registry.logger);
done();
return;
}
@ -48,7 +48,7 @@ describe('dns.lookup()', () => {
}
done();
});
plugin.enable(dns, tracer, tracer.logger);
plugin.enable(dns, registry, registry.logger);
});
afterEach(() => {

View File

@ -20,7 +20,7 @@ import {
} from '@opentelemetry/tracing';
import * as assert from 'assert';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import { plugin } from '../../src/dns';
import * as dns from 'dns';
import * as utils from '../utils/utils';
@ -30,8 +30,8 @@ import { CanonicalCode } from '@opentelemetry/types';
const memoryExporter = new InMemorySpanExporter();
const logger = new NoopLogger();
const tracer = new NodeTracer({ logger });
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const registry = new NodeTracerRegistry({ logger });
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
describe('dns.promises.lookup()', () => {
before(function(done) {
@ -42,7 +42,7 @@ describe('dns.promises.lookup()', () => {
// if node version is supported, it's mandatory for CI
if (process.env.CI) {
plugin.enable(dns, tracer, tracer.logger);
plugin.enable(dns, registry, registry.logger);
done();
return;
}
@ -54,7 +54,7 @@ describe('dns.promises.lookup()', () => {
}
done();
});
plugin.enable(dns, tracer, tracer.logger);
plugin.enable(dns, registry, registry.logger);
});
afterEach(() => {

View File

@ -21,7 +21,6 @@ import {
TRACE_PARENT_HEADER,
} from '@opentelemetry/core';
import { PluginConfig, Span, SpanOptions } from '@opentelemetry/types';
import { AttributeNames } from './enums/AttributeNames';
import {
addSpanNetworkEvent,
hasKey,
@ -29,6 +28,8 @@ import {
PerformanceLegacy,
PerformanceTimingNames as PTN,
} from '@opentelemetry/web';
import { AttributeNames } from './enums/AttributeNames';
import { VERSION } from './version';
/**
* This class represents a document load plugin
@ -44,7 +45,7 @@ export class DocumentLoad extends BasePlugin<unknown> {
* @param config
*/
constructor(config: PluginConfig = {}) {
super();
super('@opentelemetry/plugin-document-load', VERSION);
this._onDocumentLoaded = this._onDocumentLoaded.bind(this);
this._config = config;
}

View File

@ -18,18 +18,16 @@
* 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 {
BasicTracer,
BasicTracerRegistry,
ReadableSpan,
SimpleSpanProcessor,
SpanExporter,
} from '@opentelemetry/tracing';
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 { DocumentLoad } from '../src';
import { PerformanceTimingNames as PTN } from '@opentelemetry/web';
@ -193,7 +191,7 @@ function ensureNetworkEventsExists(events: TimedEvent[]) {
describe('DocumentLoad Plugin', () => {
let plugin: DocumentLoad;
let moduleExports: any;
let tracer: BasicTracer;
let registry: BasicTracerRegistry;
let logger: Logger;
let config: PluginConfig;
let spanProcessor: SimpleSpanProcessor;
@ -205,13 +203,13 @@ describe('DocumentLoad Plugin', () => {
value: 'complete',
});
moduleExports = {};
tracer = new BasicTracer();
registry = new BasicTracerRegistry();
logger = new ConsoleLogger();
config = {};
plugin = new DocumentLoad();
dummyExporter = new DummyExporter();
spanProcessor = new SimpleSpanProcessor(dummyExporter);
tracer.addSpanProcessor(spanProcessor);
registry.addSpanProcessor(spanProcessor);
});
afterEach(() => {
@ -239,7 +237,7 @@ describe('DocumentLoad Plugin', () => {
spyEntries.restore();
});
it('should start collecting the performance immediately', done => {
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
assert.strictEqual(window.document.readyState, 'complete');
assert.strictEqual(spyEntries.callCount, 2);
@ -266,7 +264,7 @@ describe('DocumentLoad Plugin', () => {
it('should collect performance after document load event', done => {
const spy = sinon.spy(window, 'addEventListener');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
const args = spy.args[0];
const name = args[0];
assert.strictEqual(name, 'load');
@ -301,7 +299,7 @@ describe('DocumentLoad Plugin', () => {
it('should export correct span with events', done => {
const spyOnEnd = sinon.spy(dummyExporter, 'export');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
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 => {
const spyOnEnd = sinon.spy(dummyExporter, 'export');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
const rootSpan = spyOnEnd.args[0][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 => {
const spyOnEnd = sinon.spy(dummyExporter, 'export');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
const spanResource1 = spyOnEnd.args[1][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 => {
const spyOnEnd = sinon.spy(dummyExporter, 'export');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
const spanResource1 = spyOnEnd.args[1][0][0] as ReadableSpan;
@ -473,7 +471,7 @@ describe('DocumentLoad Plugin', () => {
it('should still export rootSpan and fetchSpan', done => {
const spyOnEnd = sinon.spy(dummyExporter, 'export');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
const rootSpan = spyOnEnd.args[0][0][0] as ReadableSpan;
@ -505,7 +503,7 @@ describe('DocumentLoad Plugin', () => {
it('should export correct span with events', done => {
const spyOnEnd = sinon.spy(dummyExporter, 'export');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
const rootSpan = spyOnEnd.args[0][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 => {
const spyOnEnd = sinon.spy(dummyExporter, 'export');
plugin.enable(moduleExports, tracer, logger, config);
plugin.enable(moduleExports, registry, logger, config);
setTimeout(() => {
assert.ok(spyOnEnd.callCount === 0);
done();

View File

@ -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.
```javascript
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
grpc: {
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.
```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.

View File

@ -16,33 +16,33 @@
import { BasePlugin } from '@opentelemetry/core';
import {
CanonicalCode,
Span,
SpanContext,
SpanKind,
SpanOptions,
Span,
Status,
CanonicalCode,
SpanContext,
} 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 {
grpc,
ModuleExportsMapping,
GrpcPluginOptions,
ServerCallWithMeta,
SendUnaryDataCallback,
GrpcClientFunc,
GrpcInternalClientTypes,
GrpcPluginOptions,
ModuleExportsMapping,
SendUnaryDataCallback,
ServerCallWithMeta,
} from './types';
import {
findIndex,
_grpcStatusCodeToCanonicalCode,
_grpcStatusCodeToSpanStatus,
} from './utils';
import * as events from 'events';
import * as grpcTypes from 'grpc';
import * as shimmer from 'shimmer';
import * as path from 'path';
import { VERSION } from './version';
/** The metadata key under which span context is stored as a binary value. */
export const GRPC_TRACE_KEY = 'grpc-trace-bin';
@ -56,7 +56,7 @@ export class GrpcPlugin extends BasePlugin<grpc> {
protected _config!: GrpcPluginOptions;
constructor(readonly moduleName: string, readonly version: string) {
super();
super('@opentelemetry/plugin-grpc', VERSION);
this._config = {};
}

View File

@ -14,22 +14,20 @@
* limitations under the License.
*/
import { NoopLogger, NoopTracer } from '@opentelemetry/core';
import { NoopLogger, NoopTracerRegistry } from '@opentelemetry/core';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import { SpanKind, Tracer } from '@opentelemetry/types';
import { NodeTracer } from '@opentelemetry/node';
import { assertSpan, assertPropagation } from './utils/assertionUtils';
import { SpanKind } from '@opentelemetry/types';
import * as assert from 'assert';
import * as grpc from 'grpc';
import * as semver from 'semver';
import * as sinon from 'sinon';
import { GrpcPlugin, plugin } from '../src';
import { SendUnaryDataCallback } from '../src/types';
import * as assert from 'assert';
import * as semver from 'semver';
import * as grpc from 'grpc';
import * as sinon from 'sinon';
import { assertPropagation, assertSpan } from './utils/assertionUtils';
const PROTO_PATH = __dirname + '/fixtures/grpc-test.proto';
const memoryExporter = new InMemorySpanExporter();
@ -318,7 +316,7 @@ describe('GrpcPlugin', () => {
});
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({});
assert.strictEqual(clientPatchStub.callCount, 1);
});
@ -370,7 +368,7 @@ describe('GrpcPlugin', () => {
const runTest = (
method: typeof methodList[0],
tracer: Tracer,
registry: NodeTracerRegistry,
checkSpans = true
) => {
it(`should ${
@ -410,9 +408,11 @@ describe('GrpcPlugin', () => {
const expectEmpty = memoryExporter.getFinishedSpans();
assert.strictEqual(expectEmpty.length, 0);
const span = tracer.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
return tracer.withSpan(span, async () => {
const rootSpan = tracer.getCurrentSpan();
const span = registry
.getTracer('default')
.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
return registry.getTracer('default').withSpan(span, async () => {
const rootSpan = registry.getTracer('default').getCurrentSpan();
if (!rootSpan) {
assert.ok(false);
return; // return so typechecking passes for rootSpan.end()
@ -465,7 +465,7 @@ describe('GrpcPlugin', () => {
method: typeof methodList[0],
key: string,
errorCode: number,
tracer: Tracer
registry: NodeTracerRegistry
) => {
it(`should raise an error for client/server rootSpans: method=${method.methodName}, status=${key}`, async () => {
const expectEmpty = memoryExporter.getFinishedSpans();
@ -503,9 +503,11 @@ describe('GrpcPlugin', () => {
const expectEmpty = memoryExporter.getFinishedSpans();
assert.strictEqual(expectEmpty.length, 0);
const span = tracer.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
return tracer.withSpan(span, async () => {
const rootSpan = tracer.getCurrentSpan();
const span = registry
.getTracer('default')
.startSpan('TestSpan', { kind: SpanKind.PRODUCER });
return registry.getTracer('default').withSpan(span, async () => {
const rootSpan = registry.getTracer('default').getCurrentSpan();
if (!rootSpan) {
assert.ok(false);
return; // return so typechecking passes for rootSpan.end()
@ -552,8 +554,8 @@ describe('GrpcPlugin', () => {
describe('enable()', () => {
const logger = new NoopLogger();
const tracer = new NodeTracer({ logger });
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const registry = new NodeTracerRegistry({ logger });
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
beforeEach(() => {
memoryExporter.reset();
});
@ -562,7 +564,7 @@ describe('GrpcPlugin', () => {
const config = {
// 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;
server = startServer(grpc, proto);
@ -579,7 +581,7 @@ describe('GrpcPlugin', () => {
methodList.forEach(method => {
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
const errorCode = Number(grpc.status[statusKey as any]);
if (errorCode > grpc.status.OK) {
runErrorTest(method, statusKey, errorCode, tracer);
runErrorTest(method, statusKey, errorCode, registry);
}
});
});
@ -598,14 +600,14 @@ describe('GrpcPlugin', () => {
describe('disable()', () => {
const logger = new NoopLogger();
const tracer = new NodeTracer({ logger });
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const registry = new NodeTracerRegistry({ logger });
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
beforeEach(() => {
memoryExporter.reset();
});
before(() => {
plugin.enable(grpc, tracer, logger);
plugin.enable(grpc, registry, logger);
plugin.disable();
const proto = grpc.load(PROTO_PATH).pkg_test;
@ -622,7 +624,7 @@ describe('GrpcPlugin', () => {
methodList.map(method => {
describe(`Test automatic tracing for grpc remote method ${method.description}`, () => {
runTest(method, tracer, false);
runTest(method, registry, false);
});
});
});

View File

@ -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.
```js
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
http: {
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.
```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.

View File

@ -16,10 +16,10 @@
import { BasePlugin, isValid } from '@opentelemetry/core';
import {
CanonicalCode,
Span,
SpanKind,
SpanOptions,
CanonicalCode,
Status,
} from '@opentelemetry/types';
import {
@ -29,22 +29,23 @@ import {
RequestOptions,
ServerResponse,
} from 'http';
import { Socket } from 'net';
import * as semver from 'semver';
import * as shimmer from 'shimmer';
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 { Format } from './enums/Format';
import {
Err,
Func,
Http,
HttpPluginConfig,
HttpRequestArgs,
ParsedRequestOptions,
ResponseEndArgs,
} from './types';
import * as utils from './utils';
import { Socket } from 'net';
import { VERSION } from './version';
/**
* Http instrumentation plugin for Opentelemetry
@ -56,7 +57,7 @@ export class HttpPlugin extends BasePlugin<Http> {
private readonly _spanNotEnded: WeakSet<Span>;
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.
this.component = this.moduleName;
this._spanNotEnded = new WeakSet<Span>();

View File

@ -20,10 +20,12 @@ import * as nock from 'nock';
import * as sinon from 'sinon';
import { plugin } from '../../src/http';
import { NodeTracer } from '@opentelemetry/node';
import { NoopLogger } from '@opentelemetry/core';
import {
NoopLogger,
NoopTracerRegistry,
noopTracer,
} from '@opentelemetry/core';
import { AddressInfo } from 'net';
import { DummyPropagation } from '../utils/DummyPropagation';
import { httpRequest } from '../utils/httpRequest';
describe('HttpPlugin', () => {
@ -31,17 +33,13 @@ describe('HttpPlugin', () => {
let serverPort = 0;
describe('disable()', () => {
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
logger,
httpTextFormat,
});
const registry = new NoopTracerRegistry();
before(() => {
nock.cleanAll();
nock.enableNetConnect();
plugin.enable(http, tracer, tracer.logger);
plugin.enable(http, registry, logger);
// Ensure that http module is patched.
assert.strictEqual(http.Server.prototype.emit.__wrapped, true);
server = http.createServer((request, response) => {
@ -55,8 +53,8 @@ describe('HttpPlugin', () => {
});
beforeEach(() => {
tracer.startSpan = sinon.spy();
tracer.withSpan = sinon.spy();
noopTracer.startSpan = sinon.spy();
noopTracer.withSpan = sinon.spy();
});
afterEach(() => {
@ -67,7 +65,7 @@ describe('HttpPlugin', () => {
server.close();
});
describe('unpatch()', () => {
it('should not call tracer methods for creating span', async () => {
it('should not call registry methods for creating span', async () => {
plugin.disable();
const testPath = '/incoming/unpatch/';
@ -75,12 +73,15 @@ describe('HttpPlugin', () => {
await httpRequest.get(options).then(result => {
assert.strictEqual(
(tracer.startSpan as sinon.SinonSpy).called,
(noopTracer.startSpan as sinon.SinonSpy).called,
false
);
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
);
});
});
});

View File

@ -19,7 +19,7 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
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 * as assert from 'assert';
import * as http from 'http';
@ -45,11 +45,11 @@ const serverName = 'my.server.name';
const memoryExporter = new InMemorySpanExporter();
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
logger,
httpTextFormat,
});
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
function doNock(
hostname: string,
@ -109,7 +109,7 @@ describe('HttpPlugin', () => {
plugin.component,
process.versions.node
);
pluginWithBadOptions.enable(http, tracer, tracer.logger, config);
pluginWithBadOptions.enable(http, registry, registry.logger, config);
server = http.createServer((request, response) => {
response.end('Test Server Response');
});
@ -187,7 +187,7 @@ describe('HttpPlugin', () => {
applyCustomAttributesOnSpan: customAttributeFunction,
serverName,
};
plugin.enable(http, tracer, tracer.logger, config);
plugin.enable(http, registry, registry.logger, config);
server = http.createServer((request, response) => {
response.end('Test Server Response');
});
@ -208,7 +208,7 @@ describe('HttpPlugin', () => {
const httpNotPatched = new HttpPlugin(
plugin.component,
process.versions.node
).enable({} as Http, tracer, tracer.logger, {});
).enable({} as Http, registry, registry.logger, {});
assert.strictEqual(Object.keys(httpNotPatched).length, 0);
});
@ -323,8 +323,8 @@ describe('HttpPlugin', () => {
const testPath = '/outgoing/rootSpan/childs/1';
doNock(hostname, testPath, 200, 'Ok');
const name = 'TestRootSpan';
const span = tracer.startSpan(name);
return tracer.withSpan(span, async () => {
const span = registry.getTracer('default').startSpan(name);
return registry.getTracer('default').withSpan(span, async () => {
const result = await httpRequest.get(
`${protocol}://${hostname}${testPath}`
);
@ -366,8 +366,8 @@ describe('HttpPlugin', () => {
httpErrorCodes[i].toString()
);
const name = 'TestRootSpan';
const span = tracer.startSpan(name);
return tracer.withSpan(span, async () => {
const span = registry.getTracer('default').startSpan(name);
return registry.getTracer('default').withSpan(span, async () => {
const result = await httpRequest.get(
`${protocol}://${hostname}${testPath}`
);
@ -405,8 +405,8 @@ describe('HttpPlugin', () => {
const num = 5;
doNock(hostname, testPath, 200, 'Ok', num);
const name = 'TestRootSpan';
const span = tracer.startSpan(name);
await tracer.withSpan(span, async () => {
const span = registry.getTracer('default').startSpan(name);
await registry.getTracer('default').withSpan(span, async () => {
for (let i = 0; i < num; i++) {
await httpRequest.get(`${protocol}://${hostname}${testPath}`);
const spans = memoryExporter.getFinishedSpans();

View File

@ -28,7 +28,7 @@ import * as superagent from 'superagent';
import * as got from 'got';
import * as request from 'request-promise-native';
import * as path from 'path';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -45,11 +45,11 @@ describe('Packages', () => {
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
logger,
httpTextFormat,
});
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
beforeEach(() => {
memoryExporter.reset();
});
@ -58,7 +58,7 @@ describe('Packages', () => {
const config: HttpPluginConfig = {
applyCustomAttributesOnSpan: customAttributeFunction,
};
plugin.enable(http, tracer, tracer.logger, config);
plugin.enable(http, registry, registry.logger, config);
});
after(() => {

View File

@ -22,7 +22,7 @@ import { NoopScopeManager } from '@opentelemetry/scope-base';
import { IgnoreMatcher } from '../../src/types';
import * as utils from '../../src/utils';
import * as http from 'http';
import { Span, BasicTracer } from '@opentelemetry/tracing';
import { Span, BasicTracerRegistry } from '@opentelemetry/tracing';
import { AttributeNames } from '../../src';
import { NoopLogger } from '@opentelemetry/core';
@ -248,9 +248,9 @@ describe('Utility', () => {
const errorMessage = 'test error';
for (const obj of [undefined, { statusCode: 400 }]) {
const span = new Span(
new BasicTracer({
new BasicTracerRegistry({
scopeManager: new NoopScopeManager(),
}),
}).getTracer('default'),
'test',
{ spanId: '', traceId: '' },
SpanKind.INTERNAL

View File

@ -24,7 +24,7 @@ import { DummyPropagation } from '../utils/DummyPropagation';
import { httpRequest } from '../utils/httpRequest';
import * as url from 'url';
import * as utils from '../utils/utils';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -60,11 +60,11 @@ describe('HttpPlugin Integration tests', () => {
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
logger,
httpTextFormat,
});
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
beforeEach(() => {
memoryExporter.reset();
});
@ -83,7 +83,7 @@ describe('HttpPlugin Integration tests', () => {
try {
plugin.disable();
} catch (e) {}
plugin.enable(http, tracer, tracer.logger, config);
plugin.enable(http, registry, registry.logger, config);
});
after(() => {

View File

@ -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.
```js
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
https: {
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.
```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.

View File

@ -14,19 +14,19 @@
* limitations under the License.
*/
import { NoopLogger } from '@opentelemetry/core';
import { Http } from '@opentelemetry/plugin-http';
import * as assert from 'assert';
import * as fs from 'fs';
import * as https from 'https';
import { AddressInfo } from 'net';
import * as nock from 'nock';
import * as sinon from 'sinon';
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 { httpsRequest } from '../utils/httpsRequest';
import { NodeTracerRegistry } from '@opentelemetry/node';
import * as types from '@opentelemetry/types';
describe('HttpsPlugin', () => {
let server: https.Server;
@ -35,15 +35,18 @@ describe('HttpsPlugin', () => {
describe('disable()', () => {
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
logger,
httpTextFormat,
});
// const tracer = registry.getTracer('test-https')
let tracer: types.Tracer;
before(() => {
nock.cleanAll();
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.
assert.strictEqual(https.Server.prototype.emit.__wrapped, true);
server = https.createServer(

View File

@ -19,7 +19,7 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
Http,
HttpPluginConfig,
@ -50,11 +50,12 @@ const pathname = '/test';
const memoryExporter = new InMemorySpanExporter();
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
logger,
httpTextFormat,
});
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const tracer = registry.getTracer('test-https');
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
function doNock(
hostname: string,
@ -113,7 +114,7 @@ describe('HttpsPlugin', () => {
pluginWithBadOptions = new HttpsPlugin(process.versions.node);
pluginWithBadOptions.enable(
(https as unknown) as Http,
tracer,
registry,
tracer.logger,
config
);
@ -202,7 +203,7 @@ describe('HttpsPlugin', () => {
};
plugin.enable(
(https as unknown) as Http,
tracer,
registry,
tracer.logger,
config
);
@ -231,7 +232,7 @@ describe('HttpsPlugin', () => {
it(`should not patch if it's not a ${protocol} module`, () => {
const httpsNotPatched = new HttpsPlugin(process.versions.node).enable(
{} as Http,
tracer,
registry,
tracer.logger,
{}
);

View File

@ -15,7 +15,7 @@
*/
import { NoopLogger } from '@opentelemetry/core';
import { SpanKind } from '@opentelemetry/types';
import { SpanKind, Span } from '@opentelemetry/types';
import * as assert from 'assert';
import * as https from 'https';
import * as http from 'http';
@ -29,37 +29,35 @@ import * as superagent from 'superagent';
import * as got from 'got';
import * as request from 'request-promise-native';
import * as path from 'path';
import { NodeTracer } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import { Http, HttpPluginConfig } from '@opentelemetry/plugin-http';
import { customAttributeFunction } from './https-enable.test';
import { Http } from '@opentelemetry/plugin-http';
import { NodeTracerRegistry } from '@opentelemetry/node';
const memoryExporter = new InMemorySpanExporter();
const protocol = 'https';
export const customAttributeFunction = (span: Span): void => {
span.setAttribute('span kind', SpanKind.CLIENT);
};
describe('Packages', () => {
describe('get', () => {
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
logger,
httpTextFormat,
});
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
beforeEach(() => {
memoryExporter.reset();
});
before(() => {
const config: HttpPluginConfig = {
applyCustomAttributesOnSpan: customAttributeFunction,
};
plugin.enable((https as unknown) as Http, tracer, tracer.logger, config);
plugin.enable((https as unknown) as Http, registry, registry.logger);
});
after(() => {
@ -95,8 +93,8 @@ describe('Packages', () => {
// https://github.com/nock/nock/pull/1551
// https://github.com/sindresorhus/got/commit/bf1aa5492ae2bc78cbbec6b7d764906fb156e6c2#diff-707a4781d57c42085155dcb27edb9ccbR258
// TODO: check if this is still the case when new version
`${protocol}://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'
: `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!);
if (!resHeaders) {

View File

@ -30,7 +30,7 @@ import { DummyPropagation } from '../utils/DummyPropagation';
import { httpsRequest } from '../utils/httpsRequest';
import * as url from 'url';
import * as utils from '../utils/utils';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -65,11 +65,11 @@ describe('HttpsPlugin Integration tests', () => {
const httpTextFormat = new DummyPropagation();
const logger = new NoopLogger();
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
logger,
httpTextFormat,
});
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
beforeEach(() => {
memoryExporter.reset();
});
@ -88,7 +88,12 @@ describe('HttpsPlugin Integration tests', () => {
try {
plugin.disable();
} 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(() => {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { SpanKind, Status } from '@opentelemetry/types';
import { SpanKind } from '@opentelemetry/types';
import { hrTimeToNanoseconds } from '@opentelemetry/core';
import * as assert from 'assert';
import * as http from 'http';
@ -36,7 +36,6 @@ export const assertSpan = (
pathname: string;
reqHeaders?: http.OutgoingHttpHeaders;
path?: string | null;
forceStatus?: Status;
serverName?: string;
component: string;
}
@ -68,13 +67,12 @@ export const assertSpan = (
span.attributes[AttributeNames.HTTP_STATUS_CODE],
validations.httpStatusCode
);
assert.ok(span.endTime);
assert.strictEqual(span.links.length, 0);
assert.strictEqual(span.events.length, 0);
assert.deepStrictEqual(
span.status,
validations.forceStatus || parseResponseStatus(validations.httpStatusCode)
parseResponseStatus(validations.httpStatusCode)
);
assert.ok(span.endTime, 'must be finished');

View File

@ -18,6 +18,7 @@ import { BasePlugin } from '@opentelemetry/core';
import * as ioredisTypes from 'ioredis';
import * as shimmer from 'shimmer';
import { traceConnection, traceSendCommand } from './utils';
import { VERSION } from './version';
export class IORedisPlugin extends BasePlugin<typeof ioredisTypes> {
static readonly COMPONENT = 'ioredis';
@ -25,7 +26,7 @@ export class IORedisPlugin extends BasePlugin<typeof ioredisTypes> {
readonly supportedVersions = ['^2.0.0'];
constructor(readonly moduleName: string) {
super();
super('@opentelemetry/plugin-ioredis', VERSION);
}
protected patch(): typeof ioredisTypes {

View File

@ -19,7 +19,7 @@ import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import { plugin, IORedisPlugin } from '../src';
import * as ioredisTypes from 'ioredis';
import { NoopLogger } from '@opentelemetry/core';
@ -49,7 +49,7 @@ const okStatus: Status = {
};
describe('ioredis', () => {
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
let ioredis: typeof ioredisTypes;
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
@ -68,8 +68,8 @@ describe('ioredis', () => {
}
ioredis = require('ioredis');
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
plugin.enable(ioredis, tracer, new NoopLogger());
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
plugin.enable(ioredis, registry, new NoopLogger());
});
after(() => {
@ -84,7 +84,7 @@ describe('ioredis', () => {
describe('#createClient()', () => {
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;
const attributes = {
...DEFAULT_ATTRIBUTES,
@ -93,7 +93,10 @@ describe('ioredis', () => {
const readyHandler = () => {
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[0].name, `connect`);
assert.strictEqual(endedSpans[1].name, `info`);
@ -119,7 +122,7 @@ describe('ioredis', () => {
client.quit(done);
};
tracer.withSpan(span, () => {
registry.getTracer('ioredis-test').withSpan(span, () => {
client = new ioredis(URL);
client.on('ready', readyHandler);
client.on('error', errorHandler);
@ -183,8 +186,10 @@ describe('ioredis', () => {
' '
)}`,
};
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry
.getTracer('ioredis-test')
.startSpan('test span');
registry.getTracer('ioredis-test').withSpan(span, () => {
command.method((err, _result) => {
assert.ifError(err);
assert.strictEqual(memoryExporter.getFinishedSpans().length, 1);
@ -211,8 +216,8 @@ describe('ioredis', () => {
...DEFAULT_ATTRIBUTES,
[AttributeNames.DB_STATEMENT]: 'hset hash random random',
};
const span = tracer.startSpan('test span');
await tracer.withSpan(span, async () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
await registry.getTracer('ioredis-test').withSpan(span, async () => {
try {
await client.hset('hash', 'random', 'random');
assert.strictEqual(memoryExporter.getFinishedSpans().length, 1);
@ -239,8 +244,8 @@ describe('ioredis', () => {
...DEFAULT_ATTRIBUTES,
[AttributeNames.DB_STATEMENT]: 'scan 0',
};
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
registry.getTracer('ioredis-test').withSpan(span, () => {
const stream = client.scanStream();
stream
.on('data', resultKeys => {
@ -275,8 +280,8 @@ describe('ioredis', () => {
});
it('should create a child span for pubsub', async () => {
const span = tracer.startSpan('test span');
await tracer.withSpan(span, async () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
await registry.getTracer('ioredis-test').withSpan(span, async () => {
try {
const pub = 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',
};
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
registry.getTracer('ioredis-test').withSpan(span, () => {
// This will define a command echo:
client.defineCommand('echo', {
numberOfKeys: 1,
@ -372,8 +377,8 @@ describe('ioredis', () => {
[AttributeNames.DB_STATEMENT]: 'multi',
};
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
registry.getTracer('ioredis-test').withSpan(span, () => {
client
.multi()
.set('foo', 'bar')
@ -408,8 +413,8 @@ describe('ioredis', () => {
[AttributeNames.DB_STATEMENT]: 'set foo bar',
};
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
registry.getTracer('ioredis-test').withSpan(span, () => {
const pipeline = client.pipeline();
pipeline.set('foo', 'bar');
pipeline.del('cc');
@ -441,8 +446,8 @@ describe('ioredis', () => {
...DEFAULT_ATTRIBUTES,
[AttributeNames.DB_STATEMENT]: 'get test',
};
const span = tracer.startSpan('test span');
await tracer.withSpan(span, async () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
await registry.getTracer('ioredis-test').withSpan(span, async () => {
try {
const value = await client.get('test');
assert.strictEqual(value, 'data');
@ -470,8 +475,8 @@ describe('ioredis', () => {
...DEFAULT_ATTRIBUTES,
[AttributeNames.DB_STATEMENT]: 'del test',
};
const span = tracer.startSpan('test span');
await tracer.withSpan(span, async () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
await registry.getTracer('ioredis-test').withSpan(span, async () => {
try {
const result = await client.del('test');
assert.strictEqual(result, 1);
@ -502,8 +507,10 @@ describe('ioredis', () => {
IOREDIS_CALLBACK_OPERATIONS.forEach(operation => {
it(`should not create a child span for cb style ${operation.description}`, done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry
.getTracer('ioredis-test')
.startSpan('test span');
registry.getTracer('ioredis-test').withSpan(span, () => {
operation.method((err, _) => {
assert.ifError(err);
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 () => {
const span = tracer.startSpan('test span');
await tracer.withSpan(span, async () => {
const span = registry.getTracer('ioredis-test').startSpan('test span');
await registry.getTracer('ioredis-test').withSpan(span, async () => {
try {
await client.hset('hash', 'random', 'random');
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);

View File

@ -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.
```js
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
mongodb: {
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.
```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.

View File

@ -18,16 +18,17 @@
/* tslint:disable:deprecation */
import { BasePlugin } from '@opentelemetry/core';
import { Span, SpanKind, CanonicalCode } from '@opentelemetry/types';
import {
Func,
MongoInternalCommand,
MongoInternalTopology,
AttributeNames,
MongodbCommandType,
} from './types';
import { CanonicalCode, Span, SpanKind } from '@opentelemetry/types';
import * as mongodb from 'mongodb';
import * as shimmer from 'shimmer';
import {
AttributeNames,
Func,
MongodbCommandType,
MongoInternalCommand,
MongoInternalTopology,
} from './types';
import { VERSION } from './version';
/** MongoDBCore instrumentation plugin for OpenTelemetry */
export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
@ -40,7 +41,7 @@ export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
readonly supportedVersions = ['>=2 <4'];
constructor(readonly moduleName: string) {
super();
super('@opentelemetry/plugin-mongodb-core', VERSION);
}
/**
@ -106,7 +107,7 @@ export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
const resultHandler =
typeof options === 'function' ? options : callback;
if (
currentSpan === undefined ||
!currentSpan ||
typeof resultHandler !== 'function' ||
typeof commands !== 'object'
) {
@ -210,7 +211,7 @@ export class MongoDBPlugin extends BasePlugin<typeof mongodb> {
): mongodb.Cursor {
const currentSpan = plugin._tracer.getCurrentSpan();
const resultHandler = args[0];
if (currentSpan === undefined || typeof resultHandler !== 'function') {
if (!currentSpan || typeof resultHandler !== 'function') {
return original.apply(this, args);
}
const span = plugin._tracer.startSpan(`mongodb.query`, {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import * as assert from 'assert';
import * as mongodb from 'mongodb';
import { plugin } from '../src';
@ -65,8 +65,12 @@ function accessCollection(
function assertSpans(
spans: ReadableSpan[],
expectedName: string,
expectedKind: SpanKind
expectedKind: SpanKind,
log = false
) {
if (log) {
console.log(spans);
}
assert.strictEqual(spans.length, 2);
spans.forEach(span => {
assert(span.endTime instanceof Array);
@ -75,10 +79,7 @@ function assertSpans(
const [mongoSpan] = spans;
assert.strictEqual(mongoSpan.name, expectedName);
assert.strictEqual(mongoSpan.kind, expectedKind);
assert.strictEqual(
mongoSpan.attributes[AttributeNames.COMPONENT],
'mongodb'
);
assert.strictEqual(mongoSpan.attributes[AttributeNames.COMPONENT], 'mongodb');
assert.strictEqual(
mongoSpan.attributes[AttributeNames.PEER_HOSTNAME],
process.env.MONGODB_HOST || 'localhost'
@ -104,12 +105,13 @@ describe('MongoDBPlugin', () => {
let client: mongodb.MongoClient;
let collection: mongodb.Collection;
const logger = new NoopLogger();
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
const memoryExporter = new InMemorySpanExporter();
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const spanProcessor = new SimpleSpanProcessor(memoryExporter);
registry.addSpanProcessor(spanProcessor);
before(done => {
plugin.enable(mongodb, tracer, logger);
plugin.enable(mongodb, registry, logger);
accessCollection(URL, DB_NAME, COLLECTION_NAME)
.then(result => {
client = result.client;
@ -155,8 +157,8 @@ describe('MongoDBPlugin', () => {
it('should create a child span for insert', done => {
const insertData = [{ a: 1 }, { a: 2 }, { a: 3 }];
const span = tracer.startSpan(`insertRootSpan`);
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan(`insertRootSpan`);
registry.getTracer('default').withSpan(span, () => {
collection.insertMany(insertData, (err, result) => {
span.end();
assert.ifError(err);
@ -171,8 +173,8 @@ describe('MongoDBPlugin', () => {
});
it('should create a child span for update', done => {
const span = tracer.startSpan('updateRootSpan');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('updateRootSpan');
registry.getTracer('default').withSpan(span, () => {
collection.updateOne({ a: 2 }, { $set: { b: 1 } }, (err, result) => {
span.end();
assert.ifError(err);
@ -187,8 +189,8 @@ describe('MongoDBPlugin', () => {
});
it('should create a child span for remove', done => {
const span = tracer.startSpan('removeRootSpan');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('removeRootSpan');
registry.getTracer('default').withSpan(span, () => {
collection.deleteOne({ a: 3 }, (err, result) => {
span.end();
assert.ifError(err);
@ -206,8 +208,8 @@ describe('MongoDBPlugin', () => {
/** Should intercept cursor */
describe('Instrumenting cursor operations', () => {
it('should create a child span for find', done => {
const span = tracer.startSpan('findRootSpan');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('findRootSpan');
registry.getTracer('default').withSpan(span, () => {
collection.find({}).toArray((err, result) => {
span.end();
assert.ifError(err);
@ -225,8 +227,8 @@ describe('MongoDBPlugin', () => {
/** Should intercept command */
describe('Instrumenting command operations', () => {
it('should create a child span for create index', done => {
const span = tracer.startSpan('indexRootSpan');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('indexRootSpan');
registry.getTracer('default').withSpan(span, () => {
collection.createIndex({ a: 1 }, (err, result) => {
span.end();
assert.ifError(err);
@ -252,7 +254,7 @@ describe('MongoDBPlugin', () => {
it('should not create a child span for query', done => {
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) => {
span.end();
assert.ifError(err);
@ -262,7 +264,7 @@ describe('MongoDBPlugin', () => {
});
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) => {
span.end();
assert.ifError(err);
@ -272,7 +274,7 @@ describe('MongoDBPlugin', () => {
});
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) => {
span.end();
assert.ifError(err);

View File

@ -5,6 +5,7 @@
"outDir": "build"
},
"include": [
"src/**/*.ts"
"src/**/*.ts",
"test/**/*.ts"
]
}

View File

@ -20,9 +20,9 @@ import * as mysqlTypes from 'mysql';
import * as shimmer from 'shimmer';
import { AttributeNames } from './enums';
import { getConnectionAttributes, getSpanName } from './utils';
import { VERSION } from './version';
export class MysqlPlugin extends BasePlugin<typeof mysqlTypes> {
readonly moduleName = 'mysql';
readonly supportedVersions = ['2.*'];
static readonly COMPONENT = 'mysql';
@ -36,6 +36,10 @@ export class MysqlPlugin extends BasePlugin<typeof mysqlTypes> {
private _enabled = false;
constructor(readonly moduleName: string) {
super('@opentelemetry/plugin-mysql', VERSION);
}
protected patch(): typeof mysqlTypes {
this._enabled = true;
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);

View File

@ -15,7 +15,7 @@
*/
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -38,7 +38,7 @@ describe('mysql@2.x', () => {
let connection: mysql.Connection;
let pool: mysql.Pool;
let poolCluster: mysql.PoolCluster;
const tracer = new NodeTracer({ plugins: {} });
const registry = new NodeTracerRegistry({ plugins: {} });
const logger = new NoopLogger();
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
@ -52,7 +52,7 @@ describe('mysql@2.x', () => {
this.test!.parent!.pending = true;
this.skip();
}
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
if (testMysqlLocally) {
testUtils.startDocker('mysql');
// wait 15 seconds for docker container to start
@ -71,7 +71,7 @@ describe('mysql@2.x', () => {
});
beforeEach(function() {
plugin.enable(mysql, tracer, logger);
plugin.enable(mysql, registry, logger);
connection = mysql.createConnection({
port,
user,
@ -118,8 +118,8 @@ describe('mysql@2.x', () => {
describe('#Connection', () => {
it('should intercept connection.query(text: string)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
const query = connection.query(statement);
let rows = 0;
@ -140,8 +140,8 @@ describe('mysql@2.x', () => {
});
it('should intercept connection.query(text: string, callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
connection.query(statement, (err, res) => {
assert.ifError(err);
@ -156,8 +156,8 @@ describe('mysql@2.x', () => {
});
it('should intercept connection.query(text: options, callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+? as solution';
connection.query({ sql: statement, values: [1] }, (err, res) => {
assert.ifError(err);
@ -172,8 +172,8 @@ describe('mysql@2.x', () => {
});
it('should intercept connection.query(text: options, values: [], callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+? as solution';
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
// but does not match the typings
@ -190,8 +190,8 @@ describe('mysql@2.x', () => {
});
it('should intercept connection.query(text: string, values: [], callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
connection.query(statement, [1], (err, res) => {
assert.ifError(err);
@ -206,8 +206,8 @@ describe('mysql@2.x', () => {
});
it('should intercept connection.query(text: string, value: any, callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
connection.query(statement, 1, (err, res) => {
assert.ifError(err);
@ -222,8 +222,8 @@ describe('mysql@2.x', () => {
});
it('should attach error messages to spans', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
connection.query(statement, (err, res) => {
assert.ok(err);
@ -238,8 +238,8 @@ describe('mysql@2.x', () => {
describe('#Pool', () => {
it('should intercept pool.query(text: string)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
const query = pool.query(statement);
let rows = 0;
@ -260,8 +260,8 @@ describe('mysql@2.x', () => {
});
it('should intercept pool.getConnection().query(text: string)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
pool.getConnection((err, conn) => {
const query = conn.query(statement);
@ -284,8 +284,8 @@ describe('mysql@2.x', () => {
});
it('should intercept pool.query(text: string, callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
pool.query(statement, (err, res) => {
assert.ifError(err);
@ -300,8 +300,8 @@ describe('mysql@2.x', () => {
});
it('should intercept pool.getConnection().query(text: string, callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
pool.getConnection((err, conn) => {
conn.query(statement, (err, res) => {
@ -318,8 +318,8 @@ describe('mysql@2.x', () => {
});
it('should intercept pool.query(text: options, callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+? as solution';
pool.query({ sql: statement, values: [1] }, (err, res) => {
assert.ifError(err);
@ -334,8 +334,8 @@ describe('mysql@2.x', () => {
});
it('should intercept pool.query(text: options, values: [], callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+? as solution';
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
// but does not match the typings
@ -352,8 +352,8 @@ describe('mysql@2.x', () => {
});
it('should intercept pool.query(text: string, values: [], callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
pool.query(statement, [1], (err, res) => {
assert.ifError(err);
@ -368,8 +368,8 @@ describe('mysql@2.x', () => {
});
it('should intercept pool.query(text: string, value: any, callback)', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
pool.query(statement, 1, (err, res) => {
assert.ifError(err);
@ -384,8 +384,8 @@ describe('mysql@2.x', () => {
});
it('should attach error messages to spans', done => {
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
pool.query(statement, (err, res) => {
assert.ok(err);
@ -402,8 +402,8 @@ describe('mysql@2.x', () => {
it('should intercept poolClusterConnection.query(text: string)', done => {
poolCluster.getConnection((err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
const query = poolClusterConnection.query(statement);
let rows = 0;
@ -427,8 +427,8 @@ describe('mysql@2.x', () => {
it('should intercept poolClusterConnection.query(text: string, callback)', done => {
poolCluster.getConnection((err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+1 as solution';
poolClusterConnection.query(statement, (err, res) => {
assert.ifError(err);
@ -446,8 +446,8 @@ describe('mysql@2.x', () => {
it('should intercept poolClusterConnection.query(text: options, callback)', done => {
poolCluster.getConnection((err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+? as solution';
poolClusterConnection.query(
{ sql: statement, values: [1] },
@ -468,8 +468,8 @@ describe('mysql@2.x', () => {
it('should intercept poolClusterConnection.query(text: options, values: [], callback)', done => {
poolCluster.getConnection((err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1+? as solution';
// @ts-ignore this is documented https://github.com/mysqljs/mysql#performing-queries
// but does not match the typings
@ -489,8 +489,8 @@ describe('mysql@2.x', () => {
it('should intercept poolClusterConnection.query(text: string, values: [], callback)', done => {
poolCluster.getConnection((err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
poolClusterConnection.query(statement, [1], (err, res) => {
assert.ifError(err);
@ -508,8 +508,8 @@ describe('mysql@2.x', () => {
it('should intercept poolClusterConnection.query(text: string, value: any, callback)', done => {
poolCluster.getConnection((err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
poolClusterConnection.query(statement, 1, (err, res) => {
assert.ifError(err);
@ -527,8 +527,8 @@ describe('mysql@2.x', () => {
it('should attach error messages to spans', done => {
poolCluster.getConnection((err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT ? as solution';
poolClusterConnection.query(statement, (err, res) => {
assert.ok(err);
@ -544,8 +544,8 @@ describe('mysql@2.x', () => {
it('should get connection by name', done => {
poolCluster.getConnection('name', (err, poolClusterConnection) => {
assert.ifError(err);
const span = tracer.startSpan('test span');
tracer.withSpan(span, () => {
const span = registry.getTracer('default').startSpan('test span');
registry.getTracer('default').withSpan(span, () => {
const statement = 'SELECT 1 as solution';
poolClusterConnection.query(statement, (err, res) => {
assert.ifError(err);

View File

@ -25,6 +25,7 @@ import {
PgPoolExtended,
} from './types';
import * as utils from './utils';
import { VERSION } from './version';
export class PostgresPoolPlugin extends BasePlugin<typeof pgPoolTypes> {
protected _config: PostgresPoolPluginOptions;
@ -35,7 +36,7 @@ export class PostgresPoolPlugin extends BasePlugin<typeof pgPoolTypes> {
readonly supportedVersions = ['2.*'];
constructor(readonly moduleName: string) {
super();
super('@opentelemetry/plugin-pg-pool', VERSION);
this._config = {};
}

View File

@ -15,7 +15,7 @@
*/
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -92,7 +92,7 @@ const runCallbackTest = (
describe('pg-pool@2.x', () => {
let pool: pgPool<pg.Client>;
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
const logger = new NoopLogger();
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
@ -106,7 +106,7 @@ describe('pg-pool@2.x', () => {
this.skip();
}
pool = new pgPool(CONFIG);
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
if (testPostgresLocally) {
testUtils.startDocker('postgres');
}
@ -123,8 +123,8 @@ describe('pg-pool@2.x', () => {
});
beforeEach(function() {
plugin.enable(pgPool, tracer, logger);
pgPlugin.enable(pg, tracer, logger);
plugin.enable(pgPool, registry, logger);
pgPlugin.enable(pg, registry, logger);
});
afterEach(() => {
@ -152,8 +152,8 @@ describe('pg-pool@2.x', () => {
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
};
const events: TimedEvent[] = [];
const span = tracer.startSpan('test span');
await tracer.withSpan(span, async () => {
const span = registry.getTracer('test-pg-pool').startSpan('test span');
await registry.getTracer('test-pg-pool').withSpan(span, async () => {
const client = await pool.connect();
runCallbackTest(span, pgPoolattributes, events, okStatus, 1, 0);
assert.ok(client, 'pool.connect() returns a promise');
@ -178,8 +178,10 @@ describe('pg-pool@2.x', () => {
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
};
const events: TimedEvent[] = [];
const parentSpan = tracer.startSpan('test span');
tracer.withSpan(parentSpan, () => {
const parentSpan = registry
.getTracer('test-pg-pool')
.startSpan('test span');
registry.getTracer('test-pg-pool').withSpan(parentSpan, () => {
const resNoPromise = pool.connect((err, client, release) => {
if (err) {
return done(err);
@ -212,8 +214,8 @@ describe('pg-pool@2.x', () => {
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
};
const events: TimedEvent[] = [];
const span = tracer.startSpan('test span');
await tracer.withSpan(span, async () => {
const span = registry.getTracer('test-pg-pool').startSpan('test span');
await registry.getTracer('test-pg-pool').withSpan(span, async () => {
try {
const result = await pool.query('SELECT NOW()');
runCallbackTest(span, pgPoolattributes, events, okStatus, 2, 0);
@ -235,8 +237,10 @@ describe('pg-pool@2.x', () => {
[AttributeNames.DB_STATEMENT]: 'SELECT NOW()',
};
const events: TimedEvent[] = [];
const parentSpan = tracer.startSpan('test span');
tracer.withSpan(parentSpan, () => {
const parentSpan = registry
.getTracer('test-pg-pool')
.startSpan('test span');
registry.getTracer('test-pg-pool').withSpan(parentSpan, () => {
const resNoPromise = pool.query('SELECT NOW()', (err, result) => {
if (err) {
return done(err);

View File

@ -16,15 +16,16 @@
import { BasePlugin } from '@opentelemetry/core';
import { CanonicalCode, Span } from '@opentelemetry/types';
import * as pgTypes from 'pg';
import * as shimmer from 'shimmer';
import {
PostgresPluginOptions,
PgClientExtended,
PgPluginQueryConfig,
PostgresCallback,
PostgresPluginOptions,
} from './types';
import * as pgTypes from 'pg';
import * as shimmer from 'shimmer';
import * as utils from './utils';
import { VERSION } from './version';
export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
protected _config: PostgresPluginOptions;
@ -37,7 +38,7 @@ export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
readonly supportedVersions = ['7.*'];
constructor(readonly moduleName: string) {
super();
super('@opentelemetry/plugin-pg', VERSION);
this._config = {};
}

View File

@ -15,7 +15,7 @@
*/
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -81,7 +81,8 @@ const runCallbackTest = (
describe('pg@7.x', () => {
let client: pg.Client;
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
const tracer = registry.getTracer('external');
const logger = new NoopLogger();
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
@ -94,7 +95,7 @@ describe('pg@7.x', () => {
this.test!.parent!.pending = true;
this.skip();
}
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
if (testPostgresLocally) {
testUtils.startDocker('postgres');
}
@ -115,7 +116,7 @@ describe('pg@7.x', () => {
});
beforeEach(function() {
plugin.enable(pg, tracer, logger);
plugin.enable(pg, registry, logger);
});
afterEach(() => {

View File

@ -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
```js
const { NodeTracer } = require('@opentelemetry/node');
const { NodeTracerRegistry } = require('@opentelemetry/node');
const tracer = new NodeTracer({
const registry = new NodeTracerRegistry({
plugins: {
redis: {
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.
```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.

View File

@ -22,13 +22,14 @@ import {
getTracedCreateStreamTrace,
getTracedInternalSendCommand,
} from './utils';
import { VERSION } from './version';
export class RedisPlugin extends BasePlugin<typeof redisTypes> {
static readonly COMPONENT = 'redis';
readonly supportedVersions = ['^2.6.0']; // equivalent to >= 2.6.0 <3
constructor(readonly moduleName: string) {
super();
super('@opentelemetry/plugin-redis', VERSION);
}
protected patch() {

View File

@ -19,7 +19,7 @@ import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import { NodeTracer } from '@opentelemetry/node';
import { NodeTracerRegistry } from '@opentelemetry/node';
import { plugin, RedisPlugin } from '../src';
import * as redisTypes from 'redis';
import { NoopLogger } from '@opentelemetry/core';
@ -48,7 +48,8 @@ const okStatus: Status = {
};
describe('redis@2.x', () => {
const tracer = new NodeTracer();
const registry = new NodeTracerRegistry();
const tracer = registry.getTracer('external');
let redis: typeof redisTypes;
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
@ -67,8 +68,8 @@ describe('redis@2.x', () => {
}
redis = require('redis');
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
plugin.enable(redis, tracer, new NoopLogger());
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
plugin.enable(redis, registry, new NoopLogger());
});
after(() => {

View File

@ -69,15 +69,12 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
readonly version: string = VERSION;
moduleName = this.component;
protected _config!: XMLHttpRequestPluginConfig;
private _tasksCount = 0;
private _xhrMem = new WeakMap<XMLHttpRequest, XhrMem>();
private _usedResources = new WeakSet<PerformanceResourceTiming>();
constructor(config: XMLHttpRequestPluginConfig = {}) {
super();
this._config = config;
constructor(protected _config: XMLHttpRequestPluginConfig = {}) {
super('@opentelemetry/plugin-xml-http-request', VERSION);
}
/**

View File

@ -27,10 +27,14 @@ import {
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import * as tracing from '@opentelemetry/tracing';
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 { EventNames } from '../src/enums/EventNames';
import { XMLHttpRequestPlugin } from '../src/xhr';
import { Tracer } from '@opentelemetry/types';
class DummySpanExporter implements tracing.SpanExporter {
export(spans: any) {}
@ -97,7 +101,8 @@ describe('xhr', () => {
let clearData: any;
describe('when request is successful', () => {
let webTracerWithZone: WebTracer;
let webTracerWithZone: Tracer;
let webTracerRegistryWithZone: WebTracerRegistry;
let dummySpanExporter: DummySpanExporter;
let exportSpy: any;
let rootSpan: types.Span;
@ -136,7 +141,7 @@ describe('xhr', () => {
spyEntries = sandbox.stub(performance, 'getEntriesByType');
spyEntries.withArgs('resource').returns(resources);
webTracerWithZone = new WebTracer({
webTracerRegistryWithZone = new WebTracerRegistry({
logLevel: LogLevel.ERROR,
httpTextFormat: new B3Format(),
scopeManager: new ZoneScopeManager(),
@ -146,9 +151,10 @@ describe('xhr', () => {
}),
],
});
webTracerWithZone = webTracerRegistryWithZone.getTracer('xhr-test');
dummySpanExporter = new DummySpanExporter();
exportSpy = sinon.stub(dummySpanExporter, 'export');
webTracerWithZone.addSpanProcessor(
webTracerRegistryWithZone.addSpanProcessor(
new tracing.SimpleSpanProcessor(dummySpanExporter)
);
@ -403,7 +409,8 @@ describe('xhr', () => {
});
describe('when request is NOT successful', () => {
let webTracerWithZone: WebTracer;
let webTracerWithZoneRegistry: WebTracerRegistry;
let webTracerWithZone: Tracer;
let dummySpanExporter: DummySpanExporter;
let exportSpy: any;
let rootSpan: types.Span;
@ -434,16 +441,17 @@ describe('xhr', () => {
spyEntries = sandbox.stub(performance, 'getEntriesByType');
spyEntries.withArgs('resource').returns(resources);
webTracerWithZone = new WebTracer({
webTracerWithZoneRegistry = new WebTracerRegistry({
logLevel: LogLevel.ERROR,
scopeManager: new ZoneScopeManager(),
plugins: [new XMLHttpRequestPlugin()],
});
dummySpanExporter = new DummySpanExporter();
exportSpy = sinon.stub(dummySpanExporter, 'export');
webTracerWithZone.addSpanProcessor(
webTracerWithZoneRegistry.addSpanProcessor(
new tracing.SimpleSpanProcessor(dummySpanExporter)
);
webTracerWithZone = webTracerWithZoneRegistry.getTracer('xhr-test');
rootSpan = webTracerWithZone.startSpan('root');

View File

@ -16,14 +16,16 @@
import * as assert from 'assert';
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 { INVALID_SPAN_CONTEXT, timeInputToHrTime } from '@opentelemetry/core';
import { performance } from 'perf_hooks';
describe('OpenTracing Shim', () => {
const tracer = new BasicTracer();
const shimTracer: opentracing.Tracer = new TracerShim(tracer);
const registry = new BasicTracerRegistry();
const shimTracer: opentracing.Tracer = new TracerShim(
registry.getTracer('default')
);
opentracing.initGlobalTracer(shimTracer);
describe('TracerShim', () => {

View File

@ -25,22 +25,19 @@ npm install --save @opentelemetry/tracing
```js
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.
// NOTE: the default OpenTelemetry tracer does not record any tracing information.
const tracer = new BasicTracer();
// Initialize the OpenTelemetry APIs to use the BasicTracer bindings
opentelemetry.initGlobalTracer(tracer);
// To start a trace, you first need to initialize the Tracer registry.
// NOTE: the default OpenTelemetry tracer registry does not record any tracing information.
opentelemetry.initGlobalTracer(new BasicTracerRegistry());
// 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');
// We must end the spans so they becomes available for exporting.
// We must end the spans so they become available for exporting.
span.end();
```

View File

@ -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;
}
}

View File

@ -22,7 +22,7 @@ import {
timeInputToHrTime,
} from '@opentelemetry/core';
import { ReadableSpan } from './export/ReadableSpan';
import { BasicTracer } from './BasicTracer';
import { Tracer } from './Tracer';
import { SpanProcessor } from './SpanProcessor';
import { TraceParams } from './types';
@ -52,7 +52,7 @@ export class Span implements types.Span, ReadableSpan {
/** Constructs a new Span instance. */
constructor(
parentTracer: BasicTracer,
parentTracer: Tracer,
spanName: string,
spanContext: types.SpanContext,
kind: types.SpanKind,
@ -68,7 +68,7 @@ export class Span implements types.Span, ReadableSpan {
this.startTime = timeInputToHrTime(startTime);
this._logger = parentTracer.logger;
this._traceParams = parentTracer.getActiveTraceParams();
this._spanProcessor = parentTracer.activeSpanProcessor;
this._spanProcessor = parentTracer.getActiveSpanProcessor();
this._spanProcessor.onStart(this);
}

View File

@ -28,19 +28,17 @@ import {
TraceFlags,
Logger,
} from '@opentelemetry/types';
import { BasicTracerConfig, TraceParams } from './types';
import { TracerConfig, TraceParams } from './types';
import { ScopeManager } from '@opentelemetry/scope-base';
import { Span } from './Span';
import { mergeConfig } from './utility';
import { SpanProcessor } from './SpanProcessor';
import { NoopSpanProcessor } from './NoopSpanProcessor';
import { MultiSpanProcessor } from './MultiSpanProcessor';
import { DEFAULT_CONFIG } from './config';
import { BasicTracerRegistry } from './BasicTracerRegistry';
/**
* 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 _binaryFormat: types.BinaryFormat;
private readonly _httpTextFormat: types.HttpTextFormat;
@ -48,13 +46,14 @@ export class BasicTracer implements types.Tracer {
private readonly _scopeManager: ScopeManager;
private readonly _traceParams: TraceParams;
readonly logger: Logger;
private readonly _registeredSpanProcessor: SpanProcessor[] = [];
activeSpanProcessor = new NoopSpanProcessor();
/**
* Constructs a new Tracer instance.
*/
constructor(config: BasicTracerConfig = DEFAULT_CONFIG) {
constructor(
config: TracerConfig = DEFAULT_CONFIG,
private _tracerRegistry: BasicTracerRegistry
) {
const localConfig = mergeConfig(config);
this._binaryFormat = localConfig.binaryFormat;
this._defaultAttributes = localConfig.defaultAttributes;
@ -162,15 +161,8 @@ export class BasicTracer implements types.Tracer {
return this._traceParams;
}
/**
* Adds a new {@link SpanProcessor} to this tracer.
* @param spanProcessor the new SpanProcessor to be added.
*/
addSpanProcessor(spanProcessor: SpanProcessor): void {
this._registeredSpanProcessor.push(spanProcessor);
this.activeSpanProcessor = new MultiSpanProcessor(
this._registeredSpanProcessor
);
getActiveSpanProcessor() {
return this._tracerRegistry.getActiveSpanProcessor();
}
private _getParentSpanContext(

View File

@ -14,7 +14,8 @@
* limitations under the License.
*/
export * from './BasicTracer';
export * from './Tracer';
export * from './BasicTracerRegistry';
export * from './export/ConsoleSpanExporter';
export * from './export/BatchSpanProcessor';
export * from './export/InMemorySpanExporter';

View File

@ -25,9 +25,9 @@ import {
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.
*/

View File

@ -14,19 +14,19 @@
* limitations under the License.
*/
import { BasicTracerConfig } from './types';
import {
DEFAULT_CONFIG,
DEFAULT_MAX_ATTRIBUTES_PER_SPAN,
DEFAULT_MAX_EVENTS_PER_SPAN,
DEFAULT_MAX_LINKS_PER_SPAN,
} from './config';
import { DEFAULT_CONFIG } from './config';
import { TracerConfig } from './types';
/**
* Function to merge Default configuration (as specified in './config') with
* user provided configurations.
*/
export function mergeConfig(userConfig: BasicTracerConfig) {
export function mergeConfig(userConfig: TracerConfig) {
const traceParams = userConfig.traceParams;
const target = Object.assign({}, DEFAULT_CONFIG, userConfig);

View File

@ -14,62 +14,62 @@
* limitations under the License.
*/
import * as assert from 'assert';
import {
ALWAYS_SAMPLER,
BinaryTraceContext,
HttpTraceContext,
NEVER_SAMPLER,
NoopLogger,
TraceState,
NoRecordingSpan,
TraceState,
} from '@opentelemetry/core';
import { TraceFlags } from '@opentelemetry/types';
import { BasicTracer, Span } from '../src';
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', () => {
it('should construct an instance without any options', () => {
const tracer = new BasicTracer();
assert.ok(tracer instanceof BasicTracer);
const registry = new BasicTracerRegistry();
assert.ok(registry instanceof BasicTracerRegistry);
});
it('should construct an instance with binary format', () => {
const tracer = new BasicTracer({
const registry = new BasicTracerRegistry({
binaryFormat: new BinaryTraceContext(),
});
assert.ok(tracer instanceof BasicTracer);
assert.ok(registry instanceof BasicTracerRegistry);
});
it('should construct an instance with http text format', () => {
const tracer = new BasicTracer({
const registry = new BasicTracerRegistry({
httpTextFormat: new HttpTraceContext(),
scopeManager: new NoopScopeManager(),
});
assert.ok(tracer instanceof BasicTracer);
assert.ok(registry instanceof BasicTracerRegistry);
});
it('should construct an instance with logger', () => {
const tracer = new BasicTracer({
const registry = new BasicTracerRegistry({
logger: new NoopLogger(),
scopeManager: new NoopScopeManager(),
});
assert.ok(tracer instanceof BasicTracer);
assert.ok(registry instanceof BasicTracerRegistry);
});
it('should construct an instance with sampler', () => {
const tracer = new BasicTracer({
const registry = new BasicTracerRegistry({
scopeManager: new NoopScopeManager(),
sampler: ALWAYS_SAMPLER,
});
assert.ok(tracer instanceof BasicTracer);
assert.ok(registry instanceof BasicTracerRegistry);
});
it('should construct an instance with default trace params', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
scopeManager: new NoopScopeManager(),
});
}).getTracer('default');
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
numberOfAttributesPerSpan: 32,
numberOfEventsPerSpan: 128,
@ -78,12 +78,12 @@ describe('BasicTracer', () => {
});
it('should construct an instance with customized numberOfAttributesPerSpan trace params', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
scopeManager: new NoopScopeManager(),
traceParams: {
numberOfAttributesPerSpan: 100,
},
});
}).getTracer('default');
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
numberOfAttributesPerSpan: 100,
numberOfEventsPerSpan: 128,
@ -92,12 +92,12 @@ describe('BasicTracer', () => {
});
it('should construct an instance with customized numberOfEventsPerSpan trace params', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
scopeManager: new NoopScopeManager(),
traceParams: {
numberOfEventsPerSpan: 300,
},
});
}).getTracer('default');
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
numberOfAttributesPerSpan: 32,
numberOfEventsPerSpan: 300,
@ -106,12 +106,12 @@ describe('BasicTracer', () => {
});
it('should construct an instance with customized numberOfLinksPerSpan trace params', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
scopeManager: new NoopScopeManager(),
traceParams: {
numberOfLinksPerSpan: 10,
},
});
}).getTracer('default');
assert.deepStrictEqual(tracer.getActiveTraceParams(), {
numberOfAttributesPerSpan: 32,
numberOfEventsPerSpan: 128,
@ -120,26 +120,26 @@ describe('BasicTracer', () => {
});
it('should construct an instance with default attributes', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
defaultAttributes: {
region: 'eu-west',
asg: 'my-asg',
},
});
assert.ok(tracer instanceof BasicTracer);
assert.ok(tracer instanceof BasicTracerRegistry);
});
});
describe('.startSpan()', () => {
it('should start a span with name only', () => {
const tracer = new BasicTracer();
const tracer = new BasicTracerRegistry().getTracer('default');
const span = tracer.startSpan('my-span');
assert.ok(span);
assert.ok(span instanceof Span);
});
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', {});
assert.ok(span);
assert.ok(span instanceof Span);
@ -152,9 +152,9 @@ describe('BasicTracer', () => {
});
it('should start a span with defaultAttributes and spanoptions->attributes', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
defaultAttributes: { foo: 'bar' },
});
}).getTracer('default');
const span = tracer.startSpan('my-span', {
attributes: { foo: 'foo', bar: 'bar' },
}) as Span;
@ -163,16 +163,16 @@ describe('BasicTracer', () => {
});
it('should start a span with defaultAttributes and undefined spanoptions->attributes', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
defaultAttributes: { foo: 'bar' },
});
}).getTracer('default');
const span = tracer.startSpan('my-span', {}) as Span;
assert.deepStrictEqual(span.attributes, { foo: 'bar' });
span.end();
});
it('should start a span with spanoptions->attributes', () => {
const tracer = new BasicTracer();
const tracer = new BasicTracerRegistry().getTracer('default');
const span = tracer.startSpan('my-span', {
attributes: { foo: 'foo', bar: 'bar' },
}) as Span;
@ -181,7 +181,7 @@ describe('BasicTracer', () => {
});
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 span = tracer.startSpan('my-span', {
parent: {
@ -199,7 +199,7 @@ describe('BasicTracer', () => {
});
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 childSpan = tracer.startSpan('child-span', {
parent: span,
@ -212,7 +212,7 @@ describe('BasicTracer', () => {
});
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', {
parent: ('invalid-parent' as unknown) as undefined,
}) as Span;
@ -220,7 +220,7 @@ describe('BasicTracer', () => {
});
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', {
parent: { traceId: '0', spanId: '0' },
});
@ -233,10 +233,10 @@ describe('BasicTracer', () => {
});
it('should return a no recording span when never sampling', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
sampler: NEVER_SAMPLER,
logger: new NoopLogger(),
});
}).getTracer('default');
const span = tracer.startSpan('my-span');
assert.ok(span instanceof NoRecordingSpan);
const context = span.context();
@ -248,9 +248,9 @@ describe('BasicTracer', () => {
});
it('should create real span when not sampled but recording events true', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
sampler: NEVER_SAMPLER,
});
}).getTracer('default');
const span = tracer.startSpan('my-span', { isRecording: true });
assert.ok(span instanceof Span);
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', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
sampler: NEVER_SAMPLER,
logger: new NoopLogger(),
});
}).getTracer('default');
const span = tracer.startSpan('my-span', { isRecording: false });
assert.ok(span instanceof NoRecordingSpan);
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', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
sampler: NEVER_SAMPLER,
logger: new NoopLogger(),
});
}).getTracer('default');
const span = tracer.startSpan('my-span');
assert.ok(span instanceof NoRecordingSpan);
assert.strictEqual(span.context().traceFlags, TraceFlags.UNSAMPLED);
@ -280,10 +280,10 @@ describe('BasicTracer', () => {
});
it('should create real span when sampled and recording events true', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
sampler: ALWAYS_SAMPLER,
scopeManager: new NoopScopeManager(),
});
}).getTracer('default');
const span = tracer.startSpan('my-span', { isRecording: true });
assert.ok(span instanceof Span);
assert.strictEqual(span.context().traceFlags, TraceFlags.SAMPLED);
@ -294,10 +294,10 @@ describe('BasicTracer', () => {
const defaultAttributes = {
foo: 'bar',
};
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
scopeManager: new NoopScopeManager(),
defaultAttributes,
});
}).getTracer('default');
const span = tracer.startSpan('my-span') as Span;
assert.ok(span instanceof Span);
@ -306,25 +306,25 @@ describe('BasicTracer', () => {
});
describe('.getCurrentSpan()', () => {
it('should return undefined with NoopScopeManager', () => {
const tracer = new BasicTracer();
it('should return null with NoopScopeManager', () => {
const tracer = new BasicTracerRegistry().getTracer('default');
const currentSpan = tracer.getCurrentSpan();
assert.deepStrictEqual(currentSpan, undefined);
});
it('should return current span when it exists', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
scopeManager: {
active: () => 'foo',
} as ScopeManager,
});
}).getTracer('default');
assert.deepStrictEqual(tracer.getCurrentSpan(), 'foo');
});
});
describe('.withSpan()', () => {
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');
tracer.withSpan(span, () => {
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
@ -335,7 +335,7 @@ describe('BasicTracer', () => {
describe('.bind()', () => {
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 fn = () => {
assert.deepStrictEqual(tracer.getCurrentSpan(), undefined);
@ -348,14 +348,14 @@ describe('BasicTracer', () => {
describe('.getBinaryFormat()', () => {
it('should get default binary formatter', () => {
const tracer = new BasicTracer();
const tracer = new BasicTracerRegistry().getTracer('default');
assert.ok(tracer.getBinaryFormat() instanceof BinaryTraceContext);
});
});
describe('.getHttpTextFormat()', () => {
it('should get default HTTP text formatter', () => {
const tracer = new BasicTracer();
const tracer = new BasicTracerRegistry().getTracer('default');
assert.ok(tracer.getHttpTextFormat() instanceof HttpTraceContext);
});
});

View File

@ -16,7 +16,7 @@
import * as assert from 'assert';
import { MultiSpanProcessor } from '../src/MultiSpanProcessor';
import { SpanProcessor, Span, BasicTracer } from '../src';
import { SpanProcessor, Span, BasicTracerRegistry } from '../src';
class TestProcessor implements SpanProcessor {
spans: Span[] = [];
@ -30,7 +30,7 @@ class TestProcessor implements SpanProcessor {
}
describe('MultiSpanProcessor', () => {
const tracer = new BasicTracer();
const tracer = new BasicTracerRegistry().getTracer('default');
const span = tracer.startSpan('one');
it('should handle empty span processor', () => {

View File

@ -21,7 +21,7 @@ import {
TraceFlags,
SpanContext,
} from '@opentelemetry/types';
import { BasicTracer, Span } from '../src';
import { BasicTracerRegistry, Span } from '../src';
import {
hrTime,
hrTimeToNanoseconds,
@ -33,9 +33,9 @@ import {
const performanceTimeOrigin = hrTime();
describe('Span', () => {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
logger: new NoopLogger(),
});
}).getTracer('default');
const name = 'span1';
const spanContext: SpanContext = {
traceId: 'd4cda95b652f4a1592b449d5929fda1b',

View File

@ -18,26 +18,26 @@ import * as assert from 'assert';
import * as sinon from 'sinon';
import {
Span,
BasicTracer,
BasicTracerRegistry,
InMemorySpanExporter,
BatchSpanProcessor,
} from '../../src';
import { NEVER_SAMPLER, ALWAYS_SAMPLER, NoopLogger } from '@opentelemetry/core';
function createSampledSpan(spanName: string): Span {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
sampler: ALWAYS_SAMPLER,
});
}).getTracer('default');
const span = tracer.startSpan(spanName);
span.end();
return span as Span;
}
function createUnSampledSpan(spanName: string): Span {
const tracer = new BasicTracer({
const tracer = new BasicTracerRegistry({
sampler: NEVER_SAMPLER,
logger: new NoopLogger(),
});
}).getTracer('default');
const span = tracer.startSpan(spanName, { isRecording: false });
span.end();
return span as Span;

View File

@ -17,7 +17,7 @@
import * as assert from 'assert';
import * as sinon from 'sinon';
import {
BasicTracer,
BasicTracerRegistry,
ConsoleSpanExporter,
SimpleSpanProcessor,
} from '../../src';
@ -39,15 +39,17 @@ describe('ConsoleSpanExporter', () => {
describe('.export()', () => {
it('should export information about span', () => {
assert.doesNotThrow(() => {
const basicTracer = new BasicTracer();
const basicTracerRegistry = new BasicTracerRegistry();
consoleExporter = new ConsoleSpanExporter();
const spyConsole = sinon.spy(console, 'log');
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.end();

View File

@ -18,14 +18,14 @@ import * as assert from 'assert';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
BasicTracer,
BasicTracerRegistry,
} from '../../src';
import { ExportResult } from '@opentelemetry/base';
describe('InMemorySpanExporter', () => {
const memoryExporter = new InMemorySpanExporter();
const tracer = new BasicTracer();
tracer.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
const registry = new BasicTracerRegistry();
registry.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
afterEach(() => {
// reset spans in memory.
@ -33,9 +33,13 @@ describe('InMemorySpanExporter', () => {
});
it('should get finished spans', () => {
const root = tracer.startSpan('root');
const child = tracer.startSpan('child', { parent: root });
const grandChild = tracer.startSpan('grand-child', { parent: child });
const root = registry.getTracer('default').startSpan('root');
const child = registry
.getTracer('default')
.startSpan('child', { parent: root });
const grandChild = registry
.getTracer('default')
.startSpan('grand-child', { parent: child });
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
grandChild.end();
@ -56,15 +60,21 @@ describe('InMemorySpanExporter', () => {
});
it('should shutdown the exorter', () => {
const root = tracer.startSpan('root');
tracer.startSpan('child', { parent: root }).end();
const root = registry.getTracer('default').startSpan('root');
registry
.getTracer('default')
.startSpan('child', { parent: root })
.end();
root.end();
assert.strictEqual(memoryExporter.getFinishedSpans().length, 2);
memoryExporter.shutdown();
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
// 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);
});

Some files were not shown because too many files have changed in this diff Show More