Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

zipkin

Package Overview
Dependencies
Maintainers
1
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zipkin - npm Package Compare versions

Comparing version 0.10.1 to 0.11.0

lib/gen-nodejs/zipkinCore_types.js

142

index.d.ts

@@ -17,7 +17,23 @@ // TypeScript type definitions

namespace sampler {
class Sampler {
constructor(evaluator: (traceId: TraceId) => boolean);
shouldSample(traceId: TraceId): option.IOption<boolean>
}
class CountingSampler implements Sampler {
constructor(sampleRate?: number);
shouldSample(traceId: TraceId): option.IOption<boolean>
}
const neverSample: (traceId: TraceId) => boolean;
const alwaysSample: (traceId: TraceId) => boolean;
}
class Tracer {
constructor(args: { ctxImpl: Context<TraceId>, recorder: Recorder, sampler?: any, traceId128Bit?: boolean });
constructor(args: { ctxImpl: Context<TraceId>, recorder: Recorder, sampler?: sampler.Sampler, traceId128Bit?: boolean, localServiceName?: string, localEndpoint?: model.Endpoint });
id: TraceId;
scoped<V>(callback: () => V): V;
local<V>(name: string, callback: () => V): V;
createRootId(): TraceId;

@@ -39,2 +55,16 @@ createChildId(): TraceId;

class TraceId {
_traceId: option.IOption<string>;
_parentId: option.IOption<string>;
_spanId: string;
_sampled: option.IOption<boolean>;
_flags: number;
readonly traceId: string;
readonly parentId: string;
readonly spanId: string;
readonly sampled: option.IOption<boolean>;
readonly flags: number;
isDebug(): boolean;
constructor(args?: {

@@ -47,2 +77,4 @@ traceId?: option.IOption<string>,

});
isDebug(): boolean;
toString(): string;
}

@@ -91,5 +123,50 @@

namespace model {
class Endpoint {
constructor(args: { serviceName?: string, ipv4?: InetAddress, port?: number });
setServiceName(serviceName: string): void;
setIpv4(ipv4: string): void;
setPort(port: number): void;
isEmpty(): void;
}
interface Annotation {
timestamp: number;
value: string;
}
class Span {
readonly traceId: string;
readonly parentId?: string;
readonly id: string;
readonly name?: string;
readonly kind?: string;
readonly timestamp?: number;
readonly duration?: number;
readonly localEndpoint?: Endpoint;
readonly remoteEndpoint?: Endpoint;
readonly annotations: Annotation[];
readonly tags: { [ key: string ]: string };
readonly debug: boolean;
readonly shared: boolean;
constructor(traceId: TraceId)
setName(name: string): void;
setKind(kind: string): void;
setTimestamp(timestamp: number): void;
setDuration(duration: number): void;
setLocalEndpoint(endpoint: Endpoint): void;
setRemoteEndpoint(endpoint: Endpoint): void;
addAnnotation(timestamp: number, value: string): void;
putTag(key: string, value: string): void;
setDebug(debug: boolean): void;
setShared(shared: boolean): void;
}
}
/** Used by the HttpLogger transport to convert spans to JSON */
interface JsonEncoder {
// TODO: make a typesafe def for model.Endpoint,Span using Span here
encode: (span: any) => string;
encode: (span: model.Span) => string;
}

@@ -103,12 +180,22 @@

interface IAnnotation {
readonly annotationType: string
}
namespace Annotation {
class ClientSend implements IAnnotation { }
class ClientRecv implements IAnnotation { }
class ServerSend implements IAnnotation { }
class ServerRecv implements IAnnotation { }
class ClientSend implements IAnnotation {
readonly annotationType: string;
}
class ClientRecv implements IAnnotation {
readonly annotationType: string;
}
class ServerSend implements IAnnotation {
readonly annotationType: string;
}
class ServerRecv implements IAnnotation {
readonly annotationType: string;
}
class Message implements IAnnotation {
constructor(message: string);
readonly annotationType: string;
}

@@ -118,2 +205,3 @@

constructor(serviceName: string);
readonly annotationType: string;
}

@@ -123,2 +211,3 @@

constructor(name: string);
readonly annotationType: string;
}

@@ -128,2 +217,3 @@

constructor(args: { host: InetAddress, port: number });
readonly annotationType: string;
}

@@ -133,2 +223,3 @@

constructor(args: { serviceName: string, host?: InetAddress, port?: number });
readonly annotationType: string;
}

@@ -138,2 +229,3 @@

constructor(args?: { host?: InetAddress, port?: number });
readonly annotationType: string;
}

@@ -143,2 +235,3 @@

constructor(key: string, value: boolean | string | number);
readonly annotationType: string;
}

@@ -150,2 +243,5 @@ }

static getLocalAddress(): InetAddress;
ipv4(): string;
toInt(): number;
}

@@ -161,4 +257,11 @@

interface Record {
traceId: TraceId;
timestamp: number;
annotation: IAnnotation
}
/** The Tracer sends each annotation to a Recorder implementation */
interface Recorder {
record: (rec: any) => void;
record: (rec: Record) => void;
}

@@ -168,3 +271,3 @@

constructor(args: { logger: Logger, timeout?: number });
record: (rec: any) => void;
record: (rec: Record) => void;
}

@@ -174,14 +277,21 @@

constructor(args?: { logger?: Logger });
record: (rec: any) => void;
record: (rec: Record) => void;
}
class ExplicitContext {
class ExplicitContext implements Context<TraceId> {
setContext(ctx: TraceId): void;
getContext(): TraceId;
scoped<V>(callback: () => V): V;
letContext<V>(ctx: TraceId, callback: () => V): V;
}
const sampler: () => void;
class Request {
namespace Request {
function addZipkinHeaders(req: {headers: any}, traceId: TraceId): void;
}
/** The Logger (or transport) is what the Recorder uses to send spans to Zipkin.
* @see https://github.com/openzipkin/zipkin-js/#transports Official transport implementations
*/
interface Logger {
logSpan(span: model.Span): void;
}

@@ -191,3 +301,3 @@

class HttpServer {
constructor(args: { tracer: Tracer, serviceName: string, port: string | number });
constructor(args: { tracer: Tracer, port: number });

@@ -203,3 +313,3 @@ recordRequest(

class HttpClient {
constructor(args: { tracer: Tracer, serviceName: string, remoteServiceName?: string });
constructor(args: { tracer: Tracer, remoteServiceName?: string });

@@ -206,0 +316,0 @@ recordRequest<T>(

@@ -76,2 +76,21 @@ 'use strict';

function LocalOperationStart(name) {
this.name = name;
}
LocalOperationStart.prototype.toString = function () {
return 'LocalOperationStart("' + this.name + '")';
};
var LocalOperationStop = function (_SimpleAnnotation5) {
_inherits(LocalOperationStop, _SimpleAnnotation5);
function LocalOperationStop() {
_classCallCheck(this, LocalOperationStop);
return _possibleConstructorReturn(this, (LocalOperationStop.__proto__ || Object.getPrototypeOf(LocalOperationStop)).apply(this, arguments));
}
return LocalOperationStop;
}(SimpleAnnotation);
function Message(message) {

@@ -152,3 +171,5 @@ this.message = message;

LocalAddr: LocalAddr,
BinaryAnnotation: BinaryAnnotation
BinaryAnnotation: BinaryAnnotation,
LocalOperationStart: LocalOperationStart,
LocalOperationStop: LocalOperationStop
};

@@ -155,0 +176,0 @@

@@ -117,2 +117,8 @@ 'use strict';

break;
case 'LocalOperationStart':
span.delegate.setName(rec.annotation.name);
break;
case 'LocalOperationStop':
span.finish();
break;
case 'Message':

@@ -119,0 +125,0 @@ span.delegate.addAnnotation(rec.timestamp, rec.annotation.message);

2

lib/instrumentation/httpClient.js

@@ -19,3 +19,3 @@ 'use strict';

_ref$serviceName = _ref.serviceName,
serviceName = _ref$serviceName === undefined ? requiredArg('serviceName') : _ref$serviceName,
serviceName = _ref$serviceName === undefined ? tracer.localEndpoint.serviceName : _ref$serviceName,
remoteServiceName = _ref.remoteServiceName;

@@ -22,0 +22,0 @@

@@ -41,3 +41,3 @@ 'use strict';

_ref$serviceName = _ref.serviceName,
serviceName = _ref$serviceName === undefined ? requiredArg('serviceName') : _ref$serviceName,
serviceName = _ref$serviceName === undefined ? tracer.localEndpoint.serviceName : _ref$serviceName,
_ref$port = _ref.port,

@@ -44,0 +44,0 @@ port = _ref$port === undefined ? requiredArg('port') : _ref$port;

@@ -25,2 +25,7 @@ 'use strict';

var _require4 = require('../model'),
Endpoint = _require4.Endpoint;
var isPromise = require('is-promise');
function requiredArg(name) {

@@ -39,3 +44,5 @@ throw new Error('Tracer: Missing required argument ' + name + '.');

_ref$traceId128Bit = _ref.traceId128Bit,
traceId128Bit = _ref$traceId128Bit === undefined ? false : _ref$traceId128Bit;
traceId128Bit = _ref$traceId128Bit === undefined ? false : _ref$traceId128Bit,
localServiceName = _ref.localServiceName,
localEndpoint = _ref.localEndpoint;

@@ -47,2 +54,9 @@ _classCallCheck(this, Tracer);

this.traceId128Bit = traceId128Bit;
if (localEndpoint) {
this._localEndpoint = localEndpoint;
} else {
this._localEndpoint = new Endpoint({
serviceName: localServiceName || 'unknown'
});
}
this._ctxImpl = ctxImpl;

@@ -99,10 +113,54 @@ this._defaultTraceId = this.createRootId();

}
// creates a span, timing the given callable, adding any error as a tag
// if the callable returns a promise, a span stops after the promise resolves
}, {
key: 'letChildId',
value: function letChildId(callable) {
key: 'local',
value: function local(operationName, callable) {
var _this = this;
if (typeof callable !== 'function') {
throw new Error('you must pass a function');
}
return this.scoped(function () {
var traceId = _this.createChildId();
_this.setId(traceId);
_this.recordServiceName(_this._localEndpoint.serviceName);
_this.recordAnnotation(new Annotation.LocalOperationStart(operationName));
var result = void 0;
try {
result = callable();
} catch (err) {
_this.recordBinary('error', err.message ? err.message : err.toString());
_this.recordAnnotation(new Annotation.LocalOperationStop());
throw err;
}
// Finish the span on a synchronous success
if (!isPromise(result)) {
_this.recordAnnotation(new Annotation.LocalOperationStop());
return result;
}
// Ensure the span representing the promise completes
return result.then(function (output) {
_this.recordAnnotation(new Annotation.LocalOperationStop());
return output;
}).catch(function (err) {
_this.recordBinary('error', err.message ? err.message : err.toString());
_this.recordAnnotation(new Annotation.LocalOperationStop());
throw err;
});
});
}
}, {
key: 'letChildId',
value: function letChildId(callable) {
var _this2 = this;
return this.scoped(function () {
var traceId = _this2.createChildId();
_this2.setId(traceId);
return callable(traceId);

@@ -119,7 +177,13 @@ });

value: function recordAnnotation(annotation) {
this.recorder.record(new Record({
traceId: this.id,
timestamp: now(this._startTimestamp, this._startTick),
annotation: annotation
}));
var _this3 = this;
this.id.sampled.ifPresent(function (sampled) {
// sampled present is different than sampled == true
if (!sampled) return;
_this3.recorder.record(new Record({
traceId: _this3.id,
timestamp: now(_this3._startTimestamp, _this3._startTick),
annotation: annotation
}));
});
}

@@ -172,2 +236,7 @@ }, {

}
}, {
key: 'localEndpoint',
get: function get() {
return this._localEndpoint;
}
}]);

@@ -174,0 +243,0 @@

{
"name": "zipkin",
"version": "0.10.1",
"version": "0.11.0",
"description": "The core tracer for zipkin.js",

@@ -17,2 +17,3 @@ "main": "lib/index.js",

"base64-js": "^1.1.2",
"is-promise": "^2.1.0",
"network-address": "^1.1.0"

@@ -22,2 +23,3 @@ },

"babel-cli": "^6.23.0",
"bluebird": "^3.5.1",
"mocha": "^3.2.0",

@@ -24,0 +26,0 @@ "typescript": "^2.4.2"

@@ -26,4 +26,27 @@ # zipkin

sampler: new zipkin.sampler.CountingSampler(0.01), // sample rate 0.01 will sample 1 % of all incoming requests
traceId128Bit: true // to generate 128-bit trace IDs. 64-bit (false) is default
traceId128Bit: true, // to generate 128-bit trace IDs. 64-bit (false) is default
localServiceName: 'my-service' // indicates this node in your service graph
});
```
### Local tracing
Sometimes you have activity that precedes a remote request that you want to
capture in a trace. `tracer.local` can time an operation, placing a
corresponding span ID in scope so that any downstream commands end up in the
same trace.
Here's an example tracing a synchronous function:
```javascript
// A span representing checkout completes before result is returned
const result = tracer.local('checkout', () => {
return someComputation();
});
```
Here's an example tracing a function that returns a promise:
```javascript
// A span is in progress and completes when the promise is resolved.
const result = tracer.local('checkout', () => {
return createAPromise();
});
```

@@ -13,2 +13,11 @@ const InetAddress = require('./InetAddress');

function LocalOperationStart(name) {
this.name = name;
}
LocalOperationStart.prototype.toString = function() {
return `LocalOperationStart("${this.name}")`;
};
class LocalOperationStop extends SimpleAnnotation {}
function Message(message) {

@@ -79,3 +88,5 @@ this.message = message;

LocalAddr,
BinaryAnnotation
BinaryAnnotation,
LocalOperationStart,
LocalOperationStop
};

@@ -82,0 +93,0 @@

@@ -95,2 +95,8 @@ const {now, hrtime} = require('./time');

break;
case 'LocalOperationStart':
span.delegate.setName(rec.annotation.name);
break;
case 'LocalOperationStop':
span.finish();
break;
case 'Message':

@@ -97,0 +103,0 @@ span.delegate.addAnnotation(rec.timestamp, rec.annotation.message);

@@ -11,3 +11,3 @@ const Annotation = require('../annotation');

tracer = requiredArg('tracer'),
serviceName = requiredArg('serviceName'),
serviceName = tracer.localEndpoint.serviceName,
remoteServiceName

@@ -14,0 +14,0 @@ }) {

@@ -29,3 +29,3 @@ const Header = require('../httpHeaders');

tracer = requiredArg('tracer'),
serviceName = requiredArg('serviceName'),
serviceName = tracer.localEndpoint.serviceName,
port = requiredArg('port')

@@ -32,0 +32,0 @@ }) {

@@ -9,3 +9,6 @@ const {None, Some, fromNullable} = require('../option');

const {now, hrtime} = require('../time');
const {Endpoint} = require('../model');
const isPromise = require('is-promise');
function requiredArg(name) {

@@ -24,3 +27,5 @@ throw new Error(`Tracer: Missing required argument ${name}.`);

// 64 and 128 bit incoming traces from upstream sources.
traceId128Bit = false
traceId128Bit = false,
localServiceName,
localEndpoint
}) {

@@ -30,2 +35,9 @@ this.recorder = recorder;

this.traceId128Bit = traceId128Bit;
if (localEndpoint) {
this._localEndpoint = localEndpoint;
} else {
this._localEndpoint = new Endpoint({
serviceName: localServiceName || 'unknown'
});
}
this._ctxImpl = ctxImpl;

@@ -75,2 +87,43 @@ this._defaultTraceId = this.createRootId();

// creates a span, timing the given callable, adding any error as a tag
// if the callable returns a promise, a span stops after the promise resolves
local(operationName, callable) {
if (typeof callable !== 'function') {
throw new Error('you must pass a function');
}
return this.scoped(() => {
const traceId = this.createChildId();
this.setId(traceId);
this.recordServiceName(this._localEndpoint.serviceName);
this.recordAnnotation(new Annotation.LocalOperationStart(operationName));
let result;
try {
result = callable();
} catch (err) {
this.recordBinary('error', err.message ? err.message : err.toString());
this.recordAnnotation(new Annotation.LocalOperationStop());
throw err;
}
// Finish the span on a synchronous success
if (!isPromise(result)) {
this.recordAnnotation(new Annotation.LocalOperationStop());
return result;
}
// Ensure the span representing the promise completes
return result
.then((output) => {
this.recordAnnotation(new Annotation.LocalOperationStop());
return output;
})
.catch((err) => {
this.recordBinary('error', err.message ? err.message : err.toString());
this.recordAnnotation(new Annotation.LocalOperationStop());
throw err;
});
});
}
letChildId(callable) {

@@ -92,8 +145,16 @@ return this.scoped(() => {

get localEndpoint() {
return this._localEndpoint;
}
recordAnnotation(annotation) {
this.recorder.record(new Record({
traceId: this.id,
timestamp: now(this._startTimestamp, this._startTick),
annotation
}));
this.id.sampled.ifPresent(sampled => {
// sampled present is different than sampled == true
if (!sampled) return;
this.recorder.record(new Record({
traceId: this.id,
timestamp: now(this._startTimestamp, this._startTick),
annotation
}));
});
}

@@ -100,0 +161,0 @@

const sinon = require('sinon');
const lolex = require('lolex');
const Promise = require('bluebird');
const isPromise = require('is-promise');
const Tracer = require('../src/tracer');
const Annotation = require('../src/annotation');
const {Sampler} = require('../src/tracer/sampler');
const {Sampler, neverSample} = require('../src/tracer/sampler');
const ExplicitContext = require('../src/explicit-context');
const {Some} = require('../src/option');
const {Endpoint} = require('../src/model');

@@ -41,2 +43,150 @@ describe('Tracer', () => {

it('should make a local span', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const localServiceName = 'smoothie-store';
const trace = new Tracer({ctxImpl, recorder, localServiceName});
ctxImpl.scoped(() => {
const result = trace.local('buy-smoothie', () => {
trace.recordBinary('taste', 'banana');
return 'smoothie';
});
expect(result).to.eql('smoothie');
expect(record.getCall(0).args[0].annotation).to.eql(
new Annotation.ServiceName('smoothie-store')
);
expect(record.getCall(1).args[0].annotation).to.eql(
new Annotation.LocalOperationStart('buy-smoothie')
);
expect(record.getCall(2).args[0].annotation).to.eql(
new Annotation.BinaryAnnotation('taste', 'banana')
);
expect(record.getCall(3).args[0].annotation).to.eql(
new Annotation.LocalOperationStop()
);
});
});
it('should complete a local span on error type', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const localServiceName = 'smoothie-store';
const trace = new Tracer({ctxImpl, recorder, localServiceName});
ctxImpl.scoped(() => {
let error;
try {
trace.local('buy-smoothie', () => {
throw new Error('no smoothies. try our cake');
});
} catch (err) {
error = err; // error wasn't swallowed
}
// sanity check
expect(error).to.eql(new Error('no smoothies. try our cake'));
expect(record.getCall(0).args[0].annotation).to.eql(
new Annotation.ServiceName('smoothie-store')
);
expect(record.getCall(1).args[0].annotation).to.eql(
new Annotation.LocalOperationStart('buy-smoothie')
);
expect(record.getCall(2).args[0].annotation).to.eql(
new Annotation.BinaryAnnotation('error', 'no smoothies. try our cake')
);
expect(record.getCall(3).args[0].annotation).to.eql(
new Annotation.LocalOperationStop() // stopped on error
);
});
});
it('should make a local span for a promise', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const localServiceName = 'smoothie-store';
const trace = new Tracer({ctxImpl, recorder, localServiceName});
ctxImpl.scoped(() => {
const promise = trace.local('buy-smoothie', () =>
Promise.delay(10)
.then(() => {
throw new Error('no smoothies. try our cake');
})
);
expect(isPromise(promise)).to.eql(true);
// but the start event's timestamp is still correct
expect(record.getCall(0).args[0].annotation).to.eql(
new Annotation.ServiceName('smoothie-store')
);
expect(record.getCall(1).args[0].annotation).to.eql(
new Annotation.LocalOperationStart('buy-smoothie')
);
// hasn't finished yet, due to the delay
expect(record.getCall(2)).to.eql(null);
return promise.catch((error) => {
expect(error).to.eql(new Error('no smoothies. try our cake'));
expect(record.getCall(2).args[0].annotation).to.eql(
new Annotation.BinaryAnnotation('error', 'no smoothies. try our cake')
);
expect(record.getCall(3).args[0].annotation).to.eql(
new Annotation.LocalOperationStop()
);
});
});
});
it('should make a local span for a promise that produces an error', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const localServiceName = 'smoothie-store';
const trace = new Tracer({ctxImpl, recorder, localServiceName});
ctxImpl.scoped(() => {
const promise = trace.local('buy-smoothie', () =>
Promise.delay(10)
.then(() => {
trace.recordBinary('taste', 'banana');
return 'smoothie';
})
);
expect(isPromise(promise)).to.eql(true);
// but the start event's timestamp is still correct
expect(record.getCall(0).args[0].annotation).to.eql(
new Annotation.ServiceName('smoothie-store')
);
expect(record.getCall(1).args[0].annotation).to.eql(
new Annotation.LocalOperationStart('buy-smoothie')
);
// hasn't finished yet, due to the delay
expect(record.getCall(2)).to.eql(null);
return promise.then((result) => {
expect(result).to.eql('smoothie');
expect(record.getCall(2).args[0].annotation).to.eql(
new Annotation.BinaryAnnotation('taste', 'banana')
);
expect(record.getCall(3).args[0].annotation).to.eql(
new Annotation.LocalOperationStop()
);
});
});
});
function runTest(bool, done) {

@@ -68,2 +218,49 @@ const recorder = {

it('should not record unsampled spans', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const sampler = new Sampler(neverSample);
const trace = new Tracer({ctxImpl, recorder, sampler});
ctxImpl.scoped(() => {
trace.recordAnnotation(new Annotation.ServerSend());
trace.recordMessage('error');
expect(record.getCall(0)).to.equal(null);
});
});
it('should default to unknown endpoint', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const trace = new Tracer({ctxImpl, recorder});
expect(trace.localEndpoint).to.eql(new Endpoint({serviceName: 'unknown'}));
});
it('should accept localServiceName parameter', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const trace = new Tracer({ctxImpl, recorder, localServiceName: 'robot'});
expect(trace.localEndpoint).to.eql(new Endpoint({serviceName: 'robot'}));
});
it('should accept localEndpoint parameter', () => {
const record = sinon.spy();
const recorder = {record};
const ctxImpl = new ExplicitContext();
const localEndpoint = new Endpoint({
serviceName: 'portal-service',
ipv4: '10.57.50.83',
port: 8080
});
const trace = new Tracer({ctxImpl, recorder, localEndpoint});
expect(trace.localEndpoint).to.eql(localEndpoint);
});
it('should log timestamps in microseconds', () => {

@@ -70,0 +267,0 @@ const clock = lolex.install(12345678);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc