opentracing
Advanced tools
Comparing version 0.9.1 to 0.9.2
{ | ||
"name": "opentracing", | ||
"version": "0.9.1", | ||
"version": "0.9.2", | ||
"main": "dist/opentracing-node-debug.js", | ||
@@ -5,0 +5,0 @@ "scripts": { |
# OpenTracing API for JavaScript | ||
This library is a JavaScript implementation of Open Tracing API intended for use both on the server and in the browser. | ||
This library is a JavaScript implementation of Open Tracing API. It is intended for use both on the server and in the browser. | ||
**STATUS**: this library is still in development but should be ready shortly. | ||
## Required Reading | ||
## Objectives | ||
In order to fully understand this platform API, one must must first be familiar with the [OpenTracing project](http://opentracing.io) and | ||
[terminology](http://opentracing.io/spec/) more generally. | ||
Distributed tracing and context propagation have become important analysis tools for today's multi-layer distributed systems comprised of numerous micro-services implemented in different languages. The success of these tools is dependent on pervasive instrumentation of applications and libraries with trace context propagation support. | ||
The OpenTracing project (http://opentracing.github.io) provides a multi-lingual standard for application-level instrumentation that's loosely coupled to any particular downstream tracing or monitoring system. In this way, adding or switching tracing implementations becomes a single-step code change. | ||
## Quick Start | ||
@@ -27,3 +24,3 @@ | ||
var span = Tracer.startTrace('http_request'); | ||
var span = Tracer.startSpan('http_request'); | ||
var opts = { | ||
@@ -38,10 +35,10 @@ host : 'example.com', | ||
res.on('error', function (err) { | ||
span.info('Request error', err); | ||
span.logEvent('request_error', err); | ||
span.finish(); | ||
}); | ||
res.on('data', function (chunk) { | ||
span.info('Data chunk received', chunk); | ||
span.logEvent('data_received', chunk); | ||
}); | ||
res.on('end', function(err) { | ||
span.info('Request finished', err); | ||
span.logEvent('request_end', err); | ||
span.finish(); | ||
@@ -52,4 +49,6 @@ }); | ||
To capture and make the tracing data actionable, simply update the `initialize` call to specify a backend of your choosing to pipe the data to. Note: the underlying implementation object is shared with between all inclusions of the `opentracing` package, so only the initialization code needs to concern itself with the implementation package. | ||
The default behavior of the `opentracing` package is to act as a "no-op" implementation. | ||
To capture and make the tracing data actionable, the `Tracer` object should be initialized with the OpenTracing implementation of your choice as in the pseudo-code below: | ||
```js | ||
@@ -62,6 +61,4 @@ var Tracer = require('opentracing'); | ||
## Concepts | ||
*Note: the underlying implementation object is shared between all inclusions of the `opentracing` package, so `initGlobalTracer` needs to only be called once during initialization.* | ||
The main OpenTracing project (http://opentracing.github.io) provides the most up to date documentation on concepts, semantics, and best practices around effectively using OpenTracing. | ||
## API | ||
@@ -75,12 +72,28 @@ | ||
## Development | ||
## JavaScript OpenTracing Implementations | ||
#### Unit tests | ||
*I.e. information for developers wanting to create an OpenTracing-compatible JavaScript implementation.* | ||
To run the unit tests: | ||
The API layer uses a [bridge pattern](https://en.wikipedia.org/wiki/Bridge_pattern) to pass work to the specific tracing implementation. The indirection allows the API layer to enforce greater API conformance and standardization across implementations (especially in debug builds), which helps keep instrumented code more portable across OpenTracing implementations. | ||
The "implementation API" - i.e. the interface the API layer expects to be able to call on the implementation - is a proper subset of the API layer itself. The surface area of the implementation API has been reduced in the case where the an API layer method (usually a convenience method of some form) can be expressed in terms of another more general method. For example, `logEvent` can be expressed as a `log` call, therefore the implementation only needs to implement `log`. | ||
For truly implementation-dependent methods, the JavaScript API layer does expose `imp()` methods on each major type to allow the implementations to be accessed directly. Use of implementation-dependent methods is discouraged as it immediately makes instrumented code no longer portable. However, the `imp()` call does at least call attention to deviations from the standard API without making implementation-dependent calls impossible. | ||
## Development Information | ||
*I.e. information for developers working on this package.* | ||
#### Building the library | ||
``` | ||
npm run webpack | ||
``` | ||
This builds both a production and debug version of the library. The production version is intended to introduce minimal overhead, whereas the debug version does more aggressive checks for correct API usage. | ||
#### Unit tests | ||
``` | ||
npm test | ||
``` | ||
*See [DEV.md](DEV.md) for additional detail.* |
@@ -5,2 +5,8 @@ 'use strict'; | ||
module.exports = new Singleton(); | ||
let singleton = new Singleton(); | ||
// Add in constants to the singleton object | ||
singleton.FORMAT_SPLIT_BINARY = 'split_binary'; | ||
singleton.FORMAT_SPLIT_TEXT = 'split_text'; | ||
module.exports = singleton; |
@@ -6,13 +6,11 @@ 'use strict'; | ||
/** | ||
* | ||
* The Singleton object extends the standard Tracer object so that the default | ||
* exported object of the package can be conveniently be used both as the | ||
* default tracer and an interface to the library. | ||
*/ | ||
export default class Singleton extends Tracer { | ||
/** | ||
* Creates the Singleton with no underlying implementation (i.e. defaults | ||
* to no-op behavior for all functions). | ||
*/ | ||
constructor() { | ||
super(); | ||
} | ||
// ---------------------------------------------------------------------- // | ||
// OpenTracing API methods | ||
// ---------------------------------------------------------------------- // | ||
@@ -34,7 +32,18 @@ /** | ||
initNewTracer(tracingImp) { | ||
if (!this._imp) { | ||
return null; | ||
} | ||
return new Tracer(tracingImp); | ||
} | ||
// ---------------------------------------------------------------------- // | ||
// Private and non-standard methods | ||
// ---------------------------------------------------------------------- // | ||
/** | ||
* Creates the Singleton with no underlying implementation (i.e. defaults | ||
* to no-op behavior for all functions). | ||
* | ||
* Note: this should never be called directly by consumers of the library. | ||
*/ | ||
constructor() { | ||
super(); | ||
} | ||
} |
275
src/span.js
'use strict'; | ||
import * as Constants from './constants'; | ||
import TraceContext from './trace_context'; | ||
const kKeyRegExp = new RegExp(/^[a-z0-9][-a-z0-9]*/); | ||
/** | ||
* | ||
* Span represents a logical unit of work as part of a broader Trace. Examples | ||
* of span might include remote procedure calls or a in-process function calls | ||
* to sub-components. A Trace has a single, top-level "root" Span that in turn | ||
* may have zero or more child Spans, which in turn may have children. | ||
*/ | ||
export default class Span { | ||
/** | ||
* [constructor description] | ||
* @return {[type]} [description] | ||
*/ | ||
constructor(imp) { | ||
this._imp = imp; | ||
} | ||
// ---------------------------------------------------------------------- // | ||
// OpenTracing API methods | ||
// ---------------------------------------------------------------------- // | ||
/** | ||
* Adds a single tag to the span. See `AddTags()` for details. | ||
* | ||
* @param {string} key | ||
* @param {any} value | ||
*/ | ||
imp() { | ||
return this._imp; | ||
} | ||
// ---------------------------------------------------------------------- // | ||
// | ||
// ---------------------------------------------------------------------- // | ||
traceContext() { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 0) { | ||
throw new Error('Invalid arguments'); | ||
setTag(key, value) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 2) { | ||
throw new Error('Invalid number of arguments'); | ||
} | ||
if (typeof key !== 'string') { | ||
throw new Error('Tag key must be a string'); | ||
} | ||
} | ||
let contextImp = null; | ||
if (this._imp) { | ||
contextImp = this._imp.traceContext(); | ||
} | ||
return new TraceContext(contextImp); | ||
this.addTags({ [key] : value }); | ||
} | ||
/** | ||
* [tags description] | ||
* Adds the given key value pairs to the set of span tags. | ||
* | ||
* Multiple calls to addTags() results in the tags being the superset of | ||
* all calls. | ||
* | ||
* The behavior of setting the same key multiple times on the same span | ||
* is undefined. | ||
* | ||
* The supported type of the values is implementation-dependent. | ||
* Implementations are expected to safely handle all types of values but | ||
* may choose to ignore unrecognized / unhandle-able values (e.g. objects | ||
* with cyclic references, function objects). | ||
* | ||
* @return {[type]} [description] | ||
*/ | ||
setTag(key, value) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 2) { | ||
addTags(keyValuePairs) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid number of arguments'); | ||
} | ||
if (typeof key !== 'string') { | ||
throw new Error('Tag key must be a string'); | ||
if (typeof keyValuePairs !== 'object') { | ||
throw new Error('Invalid argument type'); | ||
} | ||
@@ -61,59 +65,99 @@ } | ||
} | ||
this._imp.setTag(key, value); | ||
this._imp.addTags(keyValuePairs); | ||
} | ||
/** | ||
* Creates an informational log record with the given message and optional | ||
* payload. | ||
* Set an arbitrary key-value string pair that will be carried along the | ||
* full path of a trace. | ||
* | ||
* @param {string} message Text of the log record | ||
* @param {object} payload [description] | ||
* @return {[type]} [description] | ||
* All spans created as children of this span will inherit the set of trace | ||
* attributes of this span. | ||
* | ||
* Trace attributes are copied between all spans, both in-process and across | ||
* distributed requets, therefore this feature should be used with care to | ||
* ensure undue overhead is not incurred. | ||
* | ||
* Trace keys are case insensitive, must match the regular expresssion | ||
* `[a-z0-9][-a-z0-9]*`. | ||
* | ||
* @param {string} key | ||
* @param {string} value | ||
*/ | ||
info(message, payload) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length < 1 || arguments.length > 2) { | ||
throw new Error('Invalid arguments.'); | ||
setTraceAttribute(key, value) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 2) { | ||
throw new Error('Expected 2 arguments'); | ||
} | ||
if (typeof message !== 'string') { | ||
throw new Error('Expected message to be a string'); | ||
if (typeof key !== 'string' || key.length === 0) { | ||
throw new Error('Key must be a string'); | ||
} | ||
if (!kKeyRegExp.match(key)) { | ||
throw new Error('Invalid trace key'); | ||
} | ||
let valueType = typeof value; | ||
if (value !== null && | ||
valueType !== 'boolean' && | ||
valueType !== 'number' && | ||
valueType !== 'string') { | ||
throw new Error('Trace attribute values can only be basic types'); | ||
} | ||
} | ||
if (!this._imp) { | ||
return; | ||
if (this._imp) { | ||
this._imp.setTraceAttribute(key, value); | ||
} | ||
this._imp.info(message, payload); | ||
return; | ||
} | ||
/** | ||
* [error description] | ||
* @param {[type]} message [description] | ||
* @param {[type]} payload [description] | ||
* @return {[type]} [description] | ||
* Returns the value for the given trace attribute key. | ||
* | ||
* @param {string} key | ||
* The key for the given trace attribute. | ||
* @return {string} | ||
* String value for the given key, or undefined if the key does not | ||
* correspond to a set trace attribute. | ||
*/ | ||
error(message, payload) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length < 1 || arguments.length > 2) { | ||
throw new Error('Invalid arguments.'); | ||
getTraceAttribute(key) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Expected 1 arguments'); | ||
} | ||
if (typeof message !== 'string') { | ||
throw new Error('Expected message to be a string'); | ||
if (typeof key !== 'string' || key.length === 0) { | ||
throw new Error('Key must be a string'); | ||
} | ||
if (!kKeyRegExp.match(key)) { | ||
throw new Error('Invalid trace key'); | ||
} | ||
} | ||
if (!this._imp) { | ||
return; | ||
return undefined; | ||
} | ||
this._imp.error(message, payload); | ||
return this._imp.getTraceAttribute(key); | ||
} | ||
startChild(operationName) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
/** | ||
* Starts a child span with the given operation name. | ||
* | ||
* Child spans automatically inherit all the trace attributes of the | ||
* parent span. Child span do not inherit any of the parent span tags. | ||
* | ||
* @param {string} operationName | ||
* Operation name to use for the child span. | ||
* @param {Object} fields | ||
* Optional associative array of key-value pairs. The set of valid | ||
* fields is the same as `Tracer.startSpan` with the exception that | ||
* `parent` is not valid in this context. | ||
* @return {Span} | ||
* The newly created span. | ||
*/ | ||
startChildSpan(operationNameOrFields) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid arguments'); | ||
} | ||
if (typeof operationName !== 'string') { | ||
if (typeof operationNameOrFields !== 'string' && typeof operationNameOrFields !== 'object') { | ||
throw new Error('Invalid arguments'); | ||
@@ -125,3 +169,8 @@ } | ||
if (this._imp) { | ||
spanImp = this._imp.startChild(operationName); | ||
if (typeof operationNameOrFields === 'string') { | ||
operationNameOrFields = { | ||
operationName: operationNameOrFields, | ||
}; | ||
} | ||
spanImp = this._imp.startChildSpan(operationNameOrFields); | ||
} | ||
@@ -132,9 +181,72 @@ return new Span(spanImp); | ||
/** | ||
* [finish description] | ||
* Explicitly create a log record associated with the span. | ||
* | ||
* @param {[type]} fields [description] | ||
* @param {object} fields | ||
* Optional associative array of fields. | ||
* - `timestamp` {Number} Optional field specifying the timestamp | ||
* in milliseconds as a Unix timestamp. Fractional values are | ||
* allowed so that timestamps with sub-millisecond accuracy | ||
* can be represented. If not specified, the implementation | ||
* is expected to use it's notion of the current time of the | ||
* call. | ||
* - `event` {string} | ||
* The event name. | ||
* - `payload` {object} | ||
* An arbitrary structured payload. It is implementation-dependent | ||
* how this will be processed. | ||
*/ | ||
finish() { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 0) { | ||
log(fields) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid number of arguments'); | ||
} | ||
if (typeof fields !== 'object') { | ||
throw new Error('Expected fields to be an object'); | ||
} | ||
} | ||
if (!this._imp) { | ||
return; | ||
} | ||
this._imp.log(fields); | ||
} | ||
/** | ||
* Logs a event with an optional payload. | ||
* | ||
* @param {string} eventName [description] | ||
* @param {} payload [description] | ||
* @return {[type]} [description] | ||
*/ | ||
logEvent(eventName, payload) { | ||
return this.log({ | ||
'event' : eventName, | ||
'payload' : payload, | ||
}); | ||
} | ||
/** | ||
* Indicates that the unit of work represented by the span is complete or | ||
* has otherwise been terminated. | ||
* | ||
* All Span objects must have finish() called on them before they are | ||
* reported to the backend implementation. | ||
* | ||
* Once `finish()` is called on a Span object, the behavior of all methods | ||
* on the object is considered undefined. | ||
* | ||
* @param {Number} finishTime | ||
* Optional finish time in milliseconds as a Unix timestamp. Decimal | ||
* values are supported for timestamps with sub-millisecond accuracy. | ||
* If not specified, the current time (as defined by the | ||
* implementation) will be used. | ||
*/ | ||
finish(finishTime) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length > 1) { | ||
throw new Error('Invalid arguments'); | ||
} | ||
if (arguments.length === 1 && typeof finishTime !== 'number') { | ||
throw new Error('Unexpected argument type'); | ||
} | ||
} | ||
@@ -145,4 +257,23 @@ | ||
} | ||
this._imp.finish(); | ||
this._imp.finish(finishTime); | ||
} | ||
// ---------------------------------------------------------------------- // | ||
// Private and non-standard methods | ||
// ---------------------------------------------------------------------- // | ||
/** | ||
* Constructs a new Span object. This method should not be called directly. | ||
*/ | ||
constructor(imp) { | ||
this._imp = imp; | ||
} | ||
/** | ||
* Returns the Span implementation object. The returned object is by its | ||
* nature entirely implementation-dependent. | ||
*/ | ||
imp() { | ||
return this._imp; | ||
} | ||
} |
'use strict'; | ||
import * as Constants from './constants'; | ||
import Span from './span'; | ||
/** | ||
* Tracer is the entry-point between the instrumentation API and the tracing | ||
* implementation. | ||
* | ||
* The default object acts as a no-op implementation. | ||
*/ | ||
export default class Tracer { | ||
/** | ||
* [constructor description] | ||
* @return {[type]} [description] | ||
*/ | ||
constructor(imp) { | ||
this._imp = imp || null; | ||
} | ||
// ---------------------------------------------------------------------- // | ||
// OpenTracing API methods | ||
// ---------------------------------------------------------------------- // | ||
/** | ||
* Handle to implementation object. | ||
*/ | ||
imp() { | ||
return this._imp; | ||
} | ||
/** | ||
* TODO: Unclear what the OpenTracing specification wants here. This | ||
* implementation is a best-guess approximation that's likely not right. | ||
* The spec refers to text and binary representations, but what does | ||
* "binary" mean in JavaScript without making assumptions about protocols, | ||
* transports, and platforms? | ||
* Starts and returns a new Span representing a logical unit of work. | ||
* | ||
* @param {[type]} traceContext [description] | ||
* @return {[type]} [description] | ||
*/ | ||
encodeTraceContext(traceContext) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid arguments.'); | ||
} | ||
} | ||
if (!this._imp) { | ||
return null; | ||
} | ||
// TODO: this does not get wrapped as it's unclear what the type of | ||
// return value is / should be. | ||
return this._imp.encodeTraceContext(traceContext); | ||
} | ||
/** | ||
* TODO: see concerns in encodeTraceContext. | ||
* @param {string|object} nameOrFields | ||
* If the given argument is a `string`, it is the name of the | ||
* the operation from the perpsective of the current service. | ||
* | ||
* @param {[type]} json [description] | ||
* @return {[type]} [description] | ||
* If the given argument is a object, it is treated as a set of | ||
* fields to set on the newly created span. | ||
* | ||
* - `operationName` {string} Required. This is the name to use for | ||
* the newly created span. | ||
* - `parent` {Span} Optional. The newly created Span will be created | ||
* as a child of `parent`. | ||
* - `tags` {object} Optional set of key-value pairs which will be set as | ||
* tags on the newly created Span. Ownership of the object is | ||
* passed to the created span and the caller for efficiency | ||
* reasons. | ||
* - `startTime` {Number} Optional manually specified start time for the | ||
* created Span object. The time should be specified in | ||
* milliseconds as Unix timestamp. Decimal value are supported | ||
* to represent time values with sub-millisecond accuracy. | ||
* | ||
* @return {Span} | ||
* A new Span object. | ||
*/ | ||
decodeTraceContext(obj) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid arguments.'); | ||
startSpan(nameOrFields) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid number of arguments.'); | ||
} | ||
if (typeof nameOrFields !== 'string' && typeof nameOrFields !== 'object') { | ||
throw new Error('argument expected to be a string or object'); | ||
} | ||
if (typeof nameOrFields === 'string' && nameOrFields.length === 0) { | ||
throw new Error('operation name cannot be length zero'); | ||
} | ||
if (typeof nameOrFields === 'object') { | ||
if (nameOrFields === null) { | ||
throw new Error('fields should not be null'); | ||
} | ||
if (!nameOrFields.operationName) { | ||
throw new Error('operationName is a required parameter') | ||
} | ||
} | ||
} | ||
let traceContextImp = null; | ||
let spanImp = null; | ||
if (this._imp) { | ||
traceContextImp = this._imp.decodeTraceContext(); | ||
// Normalize the argument so the implementation is always provided | ||
// the same argument type. | ||
if (typeof nameOrFields === 'string') { | ||
nameOrFields = { | ||
operationName : nameOrFields, | ||
} | ||
} | ||
spanImp = this._imp.startSpan(nameOrFields); | ||
} | ||
return TraceContext(traceContextImp); | ||
return new Span(spanImp); | ||
} | ||
/** | ||
* [newRootTraceContext description] | ||
* @return {[type]} [description] | ||
* Returns an Injector object that handles the given `format`. | ||
* | ||
* @param {string} format | ||
* See the Injector documentation for valid formats. | ||
* @return {Injector} | ||
*/ | ||
newRootTraceContext() { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 0) { | ||
throw new Error('Invalid arguments.'); | ||
injector(format) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid number of arguments.'); | ||
} | ||
if (typeof format !== 'string') { | ||
throw new Error('format expected to be a string'); | ||
} | ||
} | ||
let traceContextImp = null; | ||
let imp = null; | ||
if (this._imp) { | ||
traceContextImp = this._imp.newRootTraceContext(); | ||
imp = this._imp.injector(format); | ||
} | ||
return TraceContext(traceContextImp); | ||
return new Injector(imp); | ||
} | ||
/** | ||
* [newChildTraceContext description] | ||
* @return {[type]} [description] | ||
* Returns an Extractor object that handles the given `format`. | ||
* | ||
* @param {string} format | ||
* See the Extractor documentation for valid formats. | ||
* @return {Injector} | ||
*/ | ||
newChildTraceContext(parentContext) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid arguments.'); | ||
extractor(format) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid number of arguments.'); | ||
} | ||
if (typeof format !== 'string') { | ||
throw new Error('format expected to be a string'); | ||
} | ||
} | ||
let traceContextImp = null; | ||
let tags = {}; | ||
let imp = null; | ||
if (this._imp) { | ||
let pair = this._imp.newChildTraceContext(parentContext.imp()); | ||
traceContextImp = pair[0]; | ||
tags = pair[1]; | ||
imp = this._imp.extractor(format); | ||
} | ||
return [ TraceContext(traceContextImp), tags ]; | ||
return new Extractor(imp); | ||
} | ||
/** | ||
* [startTrace description] | ||
* @param {[type]} operation [description] | ||
* @return {[type]} [description] | ||
* Request that any buffered or in-memory data is flushed out of the process. | ||
* | ||
* @param {function} done | ||
* Optional callback function with the signature `function(err)` that | ||
* will be called as soon as the flush completes. `err` should be | ||
* null or undefined if the flush was successful. | ||
*/ | ||
startTrace(operationName) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 1) { | ||
throw new Error('Invalid arguments.'); | ||
flush(done) { | ||
if (API_CONFORMANCE_CHECKS) { | ||
if (arguments.length > 1) { | ||
throw new Error('Invalid number of arguments'); | ||
} | ||
if (typeof operationName !== 'string') { | ||
throw new Error('operationName expected to be a string'); | ||
if (done !== undefined && typeof done !== 'function') { | ||
throw new Error('callback expected to be a function'); | ||
} | ||
if (operationName.length === 0) { | ||
throw new Error('operationName cannot be length zero'); | ||
} | ||
} | ||
let spanImp = null; | ||
if (this._imp) { | ||
spanImp = this._imp.startTrace(operationName); | ||
if (!this._imp) { | ||
done(null); | ||
return; | ||
} | ||
return new Span(spanImp); | ||
this._imp.flush(done); | ||
} | ||
// ---------------------------------------------------------------------- // | ||
// Private and non-standard methods | ||
// ---------------------------------------------------------------------- // | ||
/** | ||
* [joinTrace description] | ||
* @param {[type]} operationName [description] | ||
* @param {[type]} parent [description] | ||
* @return {[type]} [description] | ||
* Note: this constructor should not be called directly by consumers of this | ||
* code. The singleton's initNewTracer() method should be invoked instead. | ||
*/ | ||
joinTrace(operationName, parentContext) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 2) { | ||
throw new Error('Invalid arguments.'); | ||
} | ||
if (typeof operationName !== 'string') { | ||
throw new Error('operationName expected to be a string'); | ||
} | ||
if (typeof parentContext !== 'object') { | ||
throw new Error('parentContext expected to be an object'); | ||
} | ||
} | ||
let spanImp = null; | ||
if (this._imp) { | ||
spanImp = this._imp.joinTrace(operationName, parentContext.imp()); | ||
} | ||
return new Span(spanImp); | ||
constructor(imp) { | ||
this._imp = imp || null; | ||
} | ||
/** | ||
* [startSpanWithContext description] | ||
* @param {[type]} operationName [description] | ||
* @param {[type]} traceContext [description] | ||
* @return {[type]} [description] | ||
* Handle to implementation object. | ||
* | ||
* Use of this method is discouraged as it greatly reduces the portability of | ||
* the calling code. Use only when implementation-specific functionality must | ||
* be used and cannot accessed otherwise. | ||
* | ||
* @return {object} | ||
* An implementation-dependent object. | ||
*/ | ||
startSpanWithContext(operationName, traceContext) { | ||
if (Constants.API_CONFORMANCE_CHECKS) { | ||
if (arguments.length !== 2) { | ||
throw new Error('Invalid arguments.'); | ||
} | ||
} | ||
let spanImp = null; | ||
if (this._imp) { | ||
spanImp = this._imp.startSpanWithContext(operationName, parent); | ||
} | ||
return new Span(spanImp); | ||
imp() { | ||
return this._imp; | ||
} | ||
} |
@@ -24,74 +24,22 @@ // For the convenience of unit testing, add these to the global namespace | ||
it('should have the required Tracer functions', function() { | ||
expect(Tracer.encodeTraceContext).to.be.a('function'); | ||
expect(Tracer.decodeTraceContext).to.be.a('function'); | ||
expect(Tracer.newRootTraceContext).to.be.a('function'); | ||
expect(Tracer.newChildTraceContext).to.be.a('function'); | ||
expect(Tracer.startTrace).to.be.a('function'); | ||
expect(Tracer.joinTrace).to.be.a('function'); | ||
expect(Tracer.startSpanWithContext).to.be.a('function'); | ||
expect(Tracer.startSpan).to.be.a('function'); | ||
expect(Tracer.injector).to.be.a('function'); | ||
expect(Tracer.extractor).to.be.a('function'); | ||
expect(Tracer.flush).to.be.a('function'); | ||
}); | ||
it('should have the required Span functions', function() { | ||
var span = Tracer.startTrace('test_operation'); | ||
var span = Tracer.startSpan('test_operation'); | ||
expect(span.traceContext).to.be.a('function'); | ||
expect(span.setTag).to.be.a('function'); | ||
expect(span.addTags).to.be.a('function'); | ||
expect(span.setTraceAttribute).to.be.a('function'); | ||
expect(span.getTraceAttribute).to.be.a('function'); | ||
expect(span.startChildSpan).to.be.a('function'); | ||
expect(span.log).to.be.a('function'); | ||
expect(span.logEvent).to.be.a('function'); | ||
expect(span.finish).to.be.a('function'); | ||
expect(span.info).to.be.a('function'); | ||
expect(span.error).to.be.a('function'); | ||
}); | ||
}); | ||
describe('Tracer API conformance', function() { | ||
describe("encodeTraceContext", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("decodeTraceContext", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("newRootTraceContext", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("newChildTraceContext", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("startTrace", function() { | ||
it("should except only a single string argument", function() { | ||
expect(Tracer.startTrace("test")).to.be.an('object'); | ||
expect(function() { Tracer.startTrace(); }).to.throw(); | ||
expect(function() { Tracer.startTrace(null); }).to.throw(); | ||
expect(function() { Tracer.startTrace(123); }).to.throw(); | ||
expect(function() { Tracer.startTrace(''); }).to.throw(); | ||
expect(function() { Tracer.startTrace([]); }).to.throw(); | ||
expect(function() { Tracer.startTrace({}); }).to.throw(); | ||
}); | ||
}); | ||
describe("joinTrace", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("startSpanWithContext", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
}); | ||
describe('Span API conformance', function() { | ||
describe("traceContext", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("setTag", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("finish", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("info", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
describe("error", function() { | ||
it("should have basic API conformance tests"); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -13,2 +13,3 @@ var webpack = require("webpack"); | ||
PLATFORM_BROWSER : false, | ||
API_CONFORMANCE_CHECKS : false, | ||
}; | ||
@@ -25,2 +26,3 @@ | ||
defines.DEBUG = true; | ||
defines.API_CONFORMANCE_CHECKS = true; | ||
bundleSuffix = "-debug"; | ||
@@ -27,0 +29,0 @@ devtool = "source-map"; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
95
29353
12
641
1