Coder Social home page Coder Social logo

jaegertracing / jaeger-client-node Goto Github PK

View Code? Open in Web Editor NEW
552.0 408.0 133.0 1.66 MB

๐Ÿ›‘ This library is DEPRECATED!

Home Page: https://jaegertracing.io/

License: Apache License 2.0

JavaScript 98.52% Shell 0.60% Makefile 0.50% Thrift 0.28% Dockerfile 0.10%
distributed-tracing opentracing node-js javascript-opentracing-api

jaeger-client-node's Introduction

Build Status Coverage Status NPM Published Version OpenTracing 1.0 Enabled

๐Ÿ›‘ This library is DEPRECATED!

There will be no new releases of this library.

We urge all users to migrate to OpenTelemetry. Please refer to the notice in the documentation for details.

Jaeger Bindings for OpenTracing API for Node.js

This is Jaeger's client side instrumentation library for Node.js that implements Javascript OpenTracing API 1.0.

Note that this library is not designed to run in the browser, only in the Node.js-backend servers. For browser-only version, see https://github.com/jaegertracing/jaeger-client-javascript.

See the OpenTracing tutorial for the introduction on using the OpenTracing API and the Jaeger SDK.

Contributing and Developing

Please see CONTRIBUTING.md.

Installation

npm install --save jaeger-client

Initialization

The Tracer defaults to sending spans over UDP to the jaeger-agent running on localhost; the jaeger-agent handles forwarding the spans to the jaeger-collector. When you are instantiating your client instance you can specify the sampler of your choice. The library support the following samplers:

SAMPLER KEY
Constant const
Probabilistic probabilistic
Rate Limiting ratelimiting
Remote remote

More information about sampling can be found here

var initTracer = require('jaeger-client').initTracer;

// See schema https://github.com/jaegertracing/jaeger-client-node/blob/master/src/configuration.js#L37
var config = {
  serviceName: 'my-awesome-service',
};
var options = {
  tags: {
    'my-awesome-service.version': '1.1.2',
  },
  metrics: metrics,
  logger: logger,
};
var tracer = initTracer(config, options);

Environment variables

The tracer can be initialized with values coming from environment variables:

var tracer = initTracerFromEnv(config, options);

None of the env vars are required and all of them can be overridden via properties on the config object.

Property Description
JAEGER_SERVICE_NAME The service name
JAEGER_AGENT_HOST The hostname for communicating with agent via UDP
JAEGER_AGENT_PORT The port for communicating with agent via UDP
JAEGER_AGENT_SOCKET_TYPE The family of socket. Must be either 'udp4' or 'udp6' ('udp4' by default).
JAEGER_ENDPOINT The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces
JAEGER_USER Username to send as part of "Basic" authentication to the collector endpoint
JAEGER_PASSWORD Password to send as part of "Basic" authentication to the collector endpoint
JAEGER_REPORTER_LOG_SPANS Whether the reporter should also log the spans
JAEGER_REPORTER_FLUSH_INTERVAL The reporter's flush interval (ms)
JAEGER_REPORTER_TIMEOUT The reporter's http timeout (ms)
JAEGER_SAMPLER_TYPE The sampler type
JAEGER_SAMPLER_PARAM The sampler parameter (number)
JAEGER_SAMPLER_MANAGER_HOST_PORT The HTTP endpoint when using the remote sampler, i.e. http://jaeger-agent:5778/sampling
JAEGER_SAMPLER_REFRESH_INTERVAL How often the remotely controlled sampler will poll jaeger-agent for the appropriate sampling strategy
JAEGER_TAGS A comma separated list of name = value tracer level tags, which get added to all reported spans. The value can also refer to an environment variable using the format ${envVarName:default}, where the :default is optional, and identifies a value to be used if the environment variable cannot be found
JAEGER_DISABLED Whether the tracer is disabled or not. If true, the default opentracing.NoopTracer is used.

By default, the client sends traces via UDP to the agent at localhost:6832. Use JAEGER_AGENT_HOST and JAEGER_AGENT_PORT to send UDP traces to a different host:port. If JAEGER_ENDPOINT is set, the client sends traces to the endpoint via HTTP, making the JAEGER_AGENT_HOST and JAEGER_AGENT_PORT unused. If JAEGER_ENDPOINT is secured, HTTP basic authentication can be performed by setting the JAEGER_USER and JAEGER_PASSWORD environment variables.

Reporting spans via HTTP

UDP has a hard size limit of 65,507 bytes; if the span is larger than this limit, the tracer will drop the span. To circumvent this, you can configure the tracer to directly send spans to the jaeger-collector over HTTP (skipping the jaeger-agent altogether).

var initTracer = require('jaeger-client').initTracer;

// See schema https://github.com/jaegertracing/jaeger-client-node/blob/master/src/configuration.js#L37
var config = {
  serviceName: 'my-awesome-service',
  reporter: {
    // Provide the traces endpoint; this forces the client to connect directly to the Collector and send
    // spans over HTTP
    collectorEndpoint: 'http://jaeger-collector:14268/api/traces',
    // Provide username and password if authentication is enabled in the Collector
    // username: '',
    // password: '',
  },
};
var options = {
  tags: {
    'my-awesome-service.version': '1.1.2',
  },
  metrics: metrics,
  logger: logger,
};
var tracer = initTracer(config, options);

Metrics and Logging

The metrics and logger objects shown in the above example must satisfy the MetricsFactory and Logger APIs respectively.

Prometheus metrics

This module brings a Prometheus(prom-client) integration to the internal Jaeger metrics. The way to initialize the tracer with Prometheus metrics:

var PrometheusMetricsFactory = require('jaeger-client').PrometheusMetricsFactory;
var promClient = require('prom-client');

var config = {
  serviceName: 'my-awesome-service',
};
var namespace = config.serviceName;
var metrics = new PrometheusMetricsFactory(promClient, namespace);
var options = {
  metrics: metrics,
};
var tracer = initTracer(config, options);

Usage

The Tracer instance created by initTracer is OpenTracing-1.0 compliant. See opentracing-javascript for usage examples. Ensure that tracer.close() is called on application exit to flush buffered traces.

TChannel Span Bridging

Because tchannel-node does not have instrumentation for OpenTracing, Jaeger-Client exposes methods wrapping tchannel handlers, and encoded channels. An encoded channel is a channel wrapped in either a thrift encoder TChannelAsThrift, or json encoder TChannelAsJson. To wrap a server handler for thrift one can initialize a tchannel bridge, and wrap the encoded handler function with a tracedHandler decorator. The tchannel bridge takes an OpenTracing tracer, and a context factory. The context factory must be a function that returns a context with the methods 'getSpan', and 'setSpan' which retrieve and assign the span to the context respectively.

import { TChannelBridge } from 'jaeger-client';
import Context from 'some-conformant-context';

function contextFactory() {
  return new Context();
}

let bridge = new TChannelBridge(tracer, { contextFactory: contextFactory });
let server = new TChannel({ serviceName: 'server' });
server.listen(4040, '127.0.0.1');
let serverThriftChannel = TChannelAsThrift({
  channel: server,
  entryPoint: path.join(__dirname, 'thrift', 'echo.thrift'), // file path to a thrift file
});

let perProcessOptions = {};
serverThriftChannel.register(
  server,
  'Echo::echo',
  perProcessOptions,
  bridge.tracedHandler((perProcessOptions, req, head, body, callback) => {
    /* Your handler code goes here. */
  })
);

Outbound calls can be made in two ways, shown below.

Using encoded channel to create a request and calling request.send()

import { TChannelBridge } from 'jaeger-client';

let bridge = new TChannelBridge(tracer);
// Create the toplevel client channel.
let client = new TChannel();

// Create the client subchannel that makes requests.
let clientSubChannel = client.makeSubChannel({
  serviceName: 'server',
  peers: ['127.0.0.1:4040'],
});

let encodedThriftChannel = TChannelAsThrift({
  channel: clientSubChannel,
  entryPoint: path.join(__dirname, 'thrift', 'echo.thrift'), // file path to a thrift file
});

// wrap encodedThriftChannel in a tracing decorator
let tracedChannel = bridge.tracedChannel(encodedThriftChannel);

// The encodedThriftChannel's (also true for json encoded channels) request object can call 'send' directly.
let req = tracedChannel.request({
  serviceName: 'server',
  context: context, // must be passed through from the service handler shown above
  headers: { cn: 'echo' },
});

// headers should contain your outgoing tchannel headers if any.
// In this instance 'send' is being called on the request object, and not the channel.
req.send('Echo::echo', headers, { value: 'some-string' });

Using top level channel to create a request and calling encodedChannel.send(request)

let tracedChannel = bridge.tracedChannel(encodedThriftChannel);

// tracedChannel.channel refers to encodedThriftChannel's inner channel which
// is clientSubChannel in this instance.
let req = tracedChannel.channel.request({
  serviceName: 'server',
  headers: { cn: 'echo' },
  context: context, // must be passed through from the service handler shown above
  timeout: someTimeout,
});
// send() can be called directly on the tracing decorator
tracedChannel.send(req, 'Echo::echo', o.headers, { value: 'some-string' }, clientCallback);

Debug Traces (Forced Sampling)

Programmatically

The OpenTracing API defines a sampling.priority standard tag that can be used to affect the sampling of a span and its children:

span.setTag(opentracing_tags.SAMPLING_PRIORITY, 1);

Via HTTP Headers

Jaeger Tracer also understands a special HTTP Header jaeger-debug-id, which can be set in the incoming request, e.g.

curl -H "jaeger-debug-id: some-correlation-id" http://myhost.com

When Jaeger sees this header in the request that otherwise has no tracing context, it ensures that the new trace started for this request will be sampled in the "debug" mode (meaning it should survive all downsampling that might happen in the collection pipeline), and the root span will have a tag as if this statement was executed:

span.setTag('jaeger-debug-id', 'some-correlation-id');

This allows using Jaeger UI to find the trace by this tag.

Trace Buffer

Specify the reporter's flush interval (ms) with config.reporter.flushIntervalMs or JAEGER_REPORTER_FLUSH_INTERVAL. The default is 1000 ms.

Calling .close() on the tracer will properly flush and close composed objects, including the reporter and sampler. This prevents dropped traces in the event of an error or unexpected early termination prior to normal periodic flushing.

tracer.close(cb?)

Zipkin Compatibility

Support for Zipkin's B3 Propagation HTTP headers is provided by the ZipkinB3TextMapCodec, which can be configured instead of the default TextMapCodec.

The new codec can be used by registering it with a tracer instance as both an injector and an extractor:

let codec = new ZipkinB3TextMapCodec({ urlEncoding: true });

tracer.registerInjector(opentracing.FORMAT_HTTP_HEADERS, codec);
tracer.registerExtractor(opentracing.FORMAT_HTTP_HEADERS, codec);

This can prove useful when compatibility with existing Zipkin tracing/instrumentation is desired.

Webpack Compatibility

In order to bundle the library using webpack, e.g. for uploading code to an AWS Lambda function, it is required to copy the Jaeger thrift definition file into the output directory of the bundle:

{
  plugins: [
    new CopyPlugin([
      {
        from: require.resolve('jaeger-client/dist/src/jaeger-idl/thrift/jaeger.thrift'),
        to: 'jaeger-idl/thrift/jaeger.thrift',
      },
      {
        from: require.resolve('jaeger-client/dist/src/thriftrw-idl/agent.thrift'),
        to: 'thriftrw-idl/agent.thrift',
      },
    ]),
  ];
}

License

Apache 2.0 License.

jaeger-client-node's People

Contributors

a1300 avatar albertteoh avatar aledbf avatar baldmaster avatar black-adder avatar dcarney avatar dependabot[bot] avatar doochik avatar eundoosong avatar kanolato avatar keitwb avatar ledor473 avatar marckk avatar mmorel-35 avatar objectiser avatar oibe avatar oliversalzburg avatar paulmiami avatar pavolloffay avatar pikbot avatar samarara avatar sebnow avatar thomwright avatar tiffon avatar tladd avatar tylerauerbeck avatar verma-varsha avatar vprithvi avatar yepninja avatar yurishkuro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jaeger-client-node's Issues

Travis build shows Flow errors but does not fail

The build should fail on Flow errors.

Ex: https://travis-ci.org/uber/jaeger-client-node/jobs/175170799

flow is still initializing; this can take some time. [processing] -# linter passed
./node_modules/.bin/mocha --compilers js:babel-core/register test
Launching Flow server for /home/travis/build/uber/jaeger-client-node
Spawned flow server (pid=4755)
Logs will go to /tmp/flow/zShomezStraviszSbuildzSuberzSjaeger-client-node.log
crossdock/src/helpers.js:37
 37:     _tracer: Tracer;
                  ^^^^^^ identifier `Tracer`. Could not resolve name
crossdock/src/helpers.js:39
 39:     _thriftChannel: Channel;
                         ^^^^^^^ identifier `Channel`. Could not resolve name
crossdock/src/helpers.js:46
 46:             peers: [Utils.myIp() + ':8082']
                         ^^^^^^^^^^^^ null. This type cannot be added to
 46:             peers: [Utils.myIp() + ':8082']
                         ^^^^^^^^^^^^^^^^^^^^^^ string

Make tracing headers configurable

Currently, TextMapCodec allows dynamic configuration of contextKey and baggagePrefix. However, there seems to be no way for a user to configure these values as TextMapCodec is instantiated as follows:

let textCodec = new TextMapCodec({
    urlEncoding: false,
    metrics: this._metrics
});

This is also an open issue with the go client here.

Any hosted solutions available for Jaeger?

Are there any hosted solutions out there available for Jaeger or opentracing in general?

My company is looking into using Jeager but they don't want to incur the costs of hosting/maintaining the solution themselves.

Getting flow errors

$ npm test
Launching Flow server for ...
crossdock/src/healthcheck_server.js:39
 39: if (require.main === module) {
                 ^^^^ property `main`. Property not found in
 39: if (require.main === module) {
         ^^^^^^^ statics of function type

crossdock/src/http_server.js:195
195: if (require.main === module) {
                 ^^^^ property `main`. Property not found in
195: if (require.main === module) {
         ^^^^^^^ statics of function type

crossdock/src/tchannel_server.js:63
 63: if (require.main === module) {
                 ^^^^ property `main`. Property not found in
 63: if (require.main === module) {
         ^^^^^^^ statics of function type

tags/logs not retained when nesting spans

I either don't know how to use this SDK or this is a bug. When I nest spans, by using childOf, tags and logs are NOT retained in either span. What am I doing wrong?

import jaeger from 'jaeger-client';

const serviceName = 'test';
const tracer = jaeger.initTracer({ serviceName });

const printArgs = (span) => {
  const ctx = span.context();
  console.log('-'.repeat(45));
  console.log(span._operationName);
  console.log('| traceId | spanId | parentId | flags |');
  console.log(ctx.toString());
  console.log(`debugId: ${ctx.debugId}`);
  console.log(JSON.stringify(span._logs));
  console.log(JSON.stringify(span._tags));
};

const printHeader = (message) => console.log(`\n${'-'.repeat(45)}\n${message}`);

printHeader('tags/logs are NOT retained when nesting');
const outerSpan = tracer.startSpan('outer');
const innerSpan = tracer.startSpan('inner', { childOf: outerSpan });
innerSpan.log({ message: 'im hiding in an inner span' });
innerSpan.addTags({ event: 'inner' });
innerSpan.finish();
outerSpan.log({ message: 'im out in the open' });
outerSpan.addTags({ event: 'outer' });
outerSpan.finish();
printArgs(innerSpan);
printArgs(outerSpan);

printHeader('tags/logs are retained without nesting');
const isolatedSpan = tracer.startSpan('isolatedSpan');
isolatedSpan.addTags({ event: 'isolatedSpan' });
isolatedSpan.log({ message: 'isolation is the key to avoiding the alien invasion' });
printArgs(isolatedSpan);
isolatedSpan.finish();

process.exit(0);

output:

---------------------------------------------
tags/logs are NOT retained when chaining
---------------------------------------------
inner
| traceId | spanId | parentId | flags |
876b91547e1bacc6:969afb74890d5da3:876b91547e1bacc6:0
debugId: 
[] // <- why?
[] // <- why?
---------------------------------------------
outer
| traceId | spanId | parentId | flags |
876b91547e1bacc6:876b91547e1bacc6:0:0
debugId: 
[] // <- why?
[] // <- why?

---------------------------------------------
tags/logs are retained without chaining
---------------------------------------------
isolatedSpan
| traceId | spanId | parentId | flags |
57f6576f28558146:57f6576f28558146:0:0
debugId: 
[{"timestamp":1495411873799,"fields":[{"key":"message","value":"isolation is the key to avoiding the alien invasion"}]}]
[{"key":"event","value":"isolatedSpan"}]

Enabling logSpans flag causes exception

The logging reporter writes the span with JSON.stringify, which fails because of some recursive links in the span.

Instead, it should log the span in the same format as other clients, as trace context + operation name.

Define release process

  • Write a RELEASE.md file
  • I am not clear on when the ES5 code is supposed to be committed to git. Perhaps this should be part of the release process, something like "make release" which will generate the files and commit them to git along with release version tag and changelog.

Frequent EMSGSIZE with UDPSender

I run frequently into EMSGSIZE error with UDPSender sender.
I tried to configure a huge maxPacketSize without any luck.

Do you experience similar issue?

unable to get anything to log

I need some help. I created the basic example below but the data is not making it to the collector in the docker image. I pulled and ran the image like so docker run -d -p5775:5775/udp -p16686:16686 jaegertracing/all-in-one:latest and then executed the code below. Nothing ever shows up in the Jaeger UI. (http://localhost:16686/search)

Anything look out of place in my setup?
Is there a way to view logs in the docker image and confirm its receiving traffic or getting an error?

// @flow
/* eslint-disable import/no-extraneous-dependencies, no-underscore-dangle */
import jaeger from 'jaeger-client';

const host = 'localhost';
// The agent exposes the following ports: 5775/udp 6831/udp 6832/udp 5778.
const port = 5775;
const flushInterval = 500;

const config = {
  serviceName: 'test-service',
  sampler: {
    type: 'const',
    param: 1,
    host,
    port,
    refreshIntervalMs: flushInterval,
  },
  reporter: {
    flushIntervalMs: flushInterval,
    // agentHost: host,
    // agentPort: port,
  },
};

const options = {};

const tracer = jaeger.initTracer(config, options);

const getRandomInt = (min, max) => {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min;
};

const getRandomArgs = () => ({
  page: getRandomInt(1, 50),
  pageSize: getRandomInt(10, 150),
});

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const users = [
  { name: 'Jiblets McGee' },
  { name: 'Smokey McCoy' },
];

const printSpanDetails = (span) => {
  console.log(span.context().toString());
  console.log(JSON.stringify(span._logs));
  console.log(span._tags);
};

const getUsersAsync = async (args) => {
  const randomWaitTime = getRandomInt(100, 4000);
  args.span.addTags({ page: args.page, pageSize: args.pageSize });
  args.span.log({ message: `the date is: ${new Date(Date.now()).toLocaleString()}` });
  await sleep(randomWaitTime);
  args.span.finish();
  printSpanDetails(args.span);
  return new Promise(resolve => resolve(users));
};

(async () => {
  // parent -> child example
  const parentSpan = tracer.startSpan('test');
  parentSpan.addTags({ level: 0 });
  await sleep(getRandomInt(200, 1000));
  const childSpan = tracer.startSpan('child-test', { childOf: parentSpan });
  childSpan.addTags({ level: 1 });
  await sleep(getRandomInt(200, 1000));
  childSpan.finish();
  parentSpan.finish();
  printSpanDetails(parentSpan);
  printSpanDetails(childSpan);

  // add bunch of async calls with random wait times
  const iterations = [];
  for (let i = 0; i < 20; i += 1) {
    const args = {
      ...getRandomArgs(),
      span: tracer.startSpan('getUsersAsync'),
    };
    iterations.push(getUsersAsync(args));
  }
  const results = await Promise.all(iterations);
  results.forEach((result) => {
    console.log(result);
  });

  tracer.close();
})();


Support Zipkin HTTP B3 propagation format

Support for Zipkin-style X-B3-* headers has already been added to the go client and the java client. It appears to be straightforward to add such support to the node client as well.

Per the contribution guidelines, I'm opening an issue before submitting a PR to add this functionality.

The bulk of the new "propagator" implementation for Zipkin-style headers would be similar to the current TextMapCodec. I've got a working prototype (I called it a ZipkinB3TextMapCodec, after the go implementation of the same name) that I could clean up and submit in a PR.

Migrate to jaegertracing org

Per jaegertracing/jaeger#409

  • Move the repo
  • Re-register the repo with Travis
  • Re-register the repo with Coveralls/CodeCov
  • Re-encrypt credentials
  • Update the links to badges in the README
  • Add DCO file
  • Add sign-off checker bot
  • Update CONTRIBUTING instructions to require sign-off
  • Update to Apache license
    • Replace LICENSE file
    • Update CONTRIBUTING instructions and references to license in the README
    • Update the existing license headers (keep Uber copyright)
    • Update the check-license script (new files get The Jaeger Authors copyright)

Reduce the use of url encoding

URL encoding of the tracing headers showed up as a large part of the flame graph. We need to minimize its use

  • we do not need to invoke url encoding for encoding trace IDs, because x:y:z:w format is safe for http headers
  • when decoding trace IDs, we should first try split(":"), and only if that didn't work we can try urlDecode
  • for baggage values we should always use url encoding, in each direction

Is it possible to send spans themselves with http?

I have a case where some parts of the code are executed in an isolated 1-way traffic environment. Meaning there is no jaeger stack available, other than the client libraries. So the spans created there don't end up in the jaeger collector where the first call was made.

Is it possible to send span data, together with context? Then in the initial service which made the external call, we can send spans to remote reporter.

Support callback in udpSender.flush

Right now there is no way to use Jaeger client in script-like apps (like the OpenTracing tutorial for Node.js) because when the app exists the reporter may still have span buffered and they don't get flushed, even if the app calls tracer.close().

The RemoteReporter and UDPSender are written in non-idiomatic style for JS/Node where UDPSender returns values from its append/flush method instead of using callbacks. It would be best to re-implement their interfaces to use callbacks for reporting the results. Then the reporter's own close() method make make sure that the UDP packet is actually flushed before returning.

Remove dependency on yaml and jsonschema

As we discussed, we can leave the schema definition as a public constant in this project, should someone wants to use it, but we should not force these extra dependencies on users who may not need them.

Error when requiring (on master)

const require('jaeger-client')

Fails with

ENOENT, no such file or directory '[redacted...]/node_modules/jaeger-client/dist/src/thriftrw-idl/agent.thrift'

Spans may be lost under heavy load

this code is from https://github.com/uber/jaeger-client-node/blob/master/src/reporters/udp_sender.js
when high concurrency, spans may be dropped frequently:

    append(span: any): SenderResponse {
        let spanSize: number = this._calcSpanSize(span); 
        if (spanSize > this._maxSpanBytes) {
            return { err: true, numSpans: 1 };
        }

        this._byteBufferSize += spanSize;          // comment 1
        if (this._byteBufferSize <= this._maxSpanBytes) {
            this._batch.spans.push(span);
            if (this._byteBufferSize < this._maxSpanBytes) {
                return {err: false, numSpans: 0};
            }
            return this.flush();
        }

        let flushResponse: SenderResponse = this.flush();  // comment 2
        this._batch.spans.push(span);                                  //comment 3
        this._byteBufferSize = spanSize;
        return flushResponse;
    }

here is a example:

this._maxSpanBytes: 64696
a span lenth: 639
current _byteBufferSize: 64671
now run append(span)

at comment 1: this._byteBufferSize will be 64671+639=65310, it's bigger than this._maxSpanBytes
so it will run comment 2: this.flush()

but in this.flush():

flush(): SenderResponse {
        let numSpans: number = this._batch.spans.length;
        if (numSpans == 0) {
            return {err: false, numSpans: 0}
        }

        let bufferLen = this._byteBufferSize + this._emitSpanBatchOverhead;  //comment 4
        let thriftBuffer = new Buffer(bufferLen);   

comment 4 use this._byteBufferSize, which now is 65310, which will cause "EMSGSIZE" error, if you add a send callback:

this._client.send(thriftBuffer, 0, thriftBuffer.length, this._port, this._host, function(e, sent) {
  console.log(e)
});

and the 64671 byte span is dropped!

fix :

add this._byteBufferSize -= spanSize; before comment 2.
or maybe reconstruct it

this._byteBufferSize += spanSize; and this._batch.spans.push(span); should be atomic, but the code separated them.

Compiler warning about [email protected]

happens during npm install

npm WARN deprecated [email protected]: We're super ๐Ÿ˜ธ  excited that you're trying to
use ES2015 syntax, but instead of continuing yearly presets ๐Ÿ˜ญ , we recommend using 
babel-preset-env: npm install babel-preset-env. preset-env without options will compile ES2015+
down to ES5. And by targeting specific browsers, Babel can do less work and you can ship native 
ES2015+ to users ๐Ÿ˜Ž ! Also, we are in the process of releasing v7, so give 
http://babeljs.io/blog/2017/09/12/planning-for-7.0 a read and test it! Thanks so much for using 
Babel ๐Ÿ™ , please give us a follow @babeljs for updates, join slack.babeljs.io for discussion and help 
support at opencollective.com/babel

Support for HTTP sender

Because Java and Go clients already support HTTP senders to emit span requests directly to the collector, it would be a nice addition if Node.js client could be capable to transport spans over HTTP too.

Double reporting process tags?

We set the process tags for the tracer once on startup here: https://github.com/uber/jaeger-client-node/blob/master/src/tracer.js#L88

These tags include the hostname, ip, etc.

However, in https://github.com/uber/jaeger-client-node/blob/master/src/tracer.js#L138, for the first span in the process, we add the same tags that we've already added in the process.

Does this logic make sense for the jaeger model? Given all the tags that we need are already in the process, is this double tagging necessary?

@badiib you know the converters better than anyone, would this cause an issue if we removed the tags from the first span in the process?
@yurishkuro for philosophical reasons

Consider using Long instead of buffers for IDs

According to @Raynos:

Keeping i64 in buffer is expensive for numerous reasons, prefer Long format.

  • buffers should have a "short life time", keeping them around will bloat memory ( they are internally slab allocated )
  • allocating a buffer slice is more expensive then an object with two integer fields

I see that Long has to/from hex string, so we should be using it instead of buffers:

Long#toString(radix=)
Long.fromString(str, unsigned=, radix=)

https://www.npmjs.com/package/long#longtostringradix

README is wrong

Instructions in the readme are broken.

  • submodule does not init
  • tests don't work
  • I believe we need specific versions of Node and npm
$ cd jaeger-client-node
$ git submodule init update
error: pathspec 'update' did not match any file(s) known to git.

so fix it by

$ git submodule init
$ git submodule update

# now try running tests
$ npm test
...
sh: flow: command not found
sh: eslint: command not found
...
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

Redo per-operation sampling if span.operationName is modified

Sometimes the span is started by instrumentation in a place were we do not have access to the route, and the concrete operation name is assigned later. In case of per-operation sampling we need to redo the sampling decision when operation name is changed.

  • It probably only needs to apply to root span
  • It means we should not be ignoring tags created during span construction when the span is not initially sampled

Unable to get trace to Jaeger tracing

I am new to opentracing and would like to use it, to get tracing around various microservices which we built (mostly using node).

To start with I tried to build a hello-world service using jaeger-client-node (code snippet) attached.

Below are the steps done:

  1. Docker around Jaeger Tracing
    sudo docker run -d -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp -p5778:5778 -p16686:16686 -p14268:14268 jaegertracing/all-in-one:latest

  2. Here is the below code which I am trying to run to get opentracing work

var restify = require('restify');
var initTracer = require('jaeger-client').initTracer;
var bunyan = require('bunyan');
var logger = bunyan.createLogger({
  name: 'hello-world'
});

// See schema https://github.com/uber/jaeger-client-node/blob/master/src/configuration.js#L37
var config = {
  'serviceName': 'hello-world'
};
var options = {
  'tags': {
    'hello-world.version': '1.1.2'
  },
  'logger': logger
};

var tracer = initTracer(config, options);

function respond(req, res, next) {

  var span = tracer.startSpan('GET-hello');
  span.log({'name': req.params.name});
  span.finish();

  res.send('hello: ' + req.params.name);

  next();
}

var server = restify.createServer();
server.get('/hello/:name', respond);

server.listen(8080, function() {
  console.log('%s listening at %s', server.name, server.url);
});

3. >>node index.js
I Get a log from Jaeger saying

{"name":"hello-world","hostname":"P10-LAP-031","pid":2405,"level":30,"msg":"Initializing Jaeger Tracer with RemoteReporter and RemoteSampler","time":"2017-07-28T07:05:00.264Z","v":0}
restify listening at http://[::]:8080

Every 1 minute I get error in my log

**{"name":"hello-world","hostname":"P10-LAP-031","pid":2405,"level":50,"msg":"Error in parsing sampling strategy: SyntaxError: Unexpected token c in JSON at position 1.","time":"2017-07-28T07:06:04.790Z","v":0}**

And I dont get any Traces in Jaeger UI http://localhost:16686/search

Do let me know if I am missing anything

Thanks

Error parsing sampling strategy

This is probably problem of (configuration of) all-in-one docker image, so it is more request for help than an issue.

TL;DR

Error: Error in parsing sampling strategy: SyntaxError: Unexpected token c in JSON at position 1.

Question1: Can someone please point me to the solution of this problem? According to my current understanding, it would probably be some documentation explaining how to configure the remote sampler, which I missed.

Question2: I tried with const sampler (sampler: { type: 'const', param: 1 }), but that would result no traces at all appearing in Jaeger UI. Could someone please point me to some more detailed documentation for samplers and their configuration?

Long Story

I start the all-in-one docker container with the command from the official documentation:

$ docker run --rm -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp -p5778:5778 -p16686:16686 -p14268:14268 jaegertracing/all-in-one:latest
{"level":"info","ts":1500067556.8956976,"caller":"tchannel/bulider.go:95","msg":"Enabling service discovery","service":"jaeger-collector"}
{"level":"info","ts":1500067556.895823,"caller":"peerlistmgr/peer_list_mgr.go:117","msg":"Registering active peer","peer":"127.0.0.1:14267"}
{"level":"info","ts":1500067556.8969154,"caller":"standalone/main.go:82","msg":"Starting agent"}
{"level":"info","ts":1500067556.8984168,"caller":"standalone/main.go:117","msg":"Starting jaeger-collector TChannel server","port":14267}
{"level":"info","ts":1500067556.898527,"caller":"standalone/main.go:124","msg":"Starting jaeger-collector HTTP server","http-port":14268}
{"level":"info","ts":1500067556.9013727,"caller":"standalone/main.go:174","msg":"Starting jaeger-query HTTP server","port":16686}
{"level":"info","ts":1500067557.896384,"caller":"peerlistmgr/peer_list_mgr.go:165","msg":"Not enough connected peers","connected":0,"required":1}
{"level":"info","ts":1500067557.896504,"caller":"peerlistmgr/peer_list_mgr.go:172","msg":"Trying to connect to peer","host:port":"127.0.0.1:14267"}
{"level":"info","ts":1500067557.8978744,"caller":"peerlistmgr/peer_list_mgr.go:177","msg":"Connected to peer","host:port":"[::]:14267"}

Then I start the sample service with almost default configuration passed to the tracer:

const config = {
  'serviceName': 'foo'
};
const options = {
  'logger': console
};
const tracer = initTracer(config, options);

After sending some requests, it looks it is working (I see some traces in the Jaeger UI), but I keep getting the JSON parsing error while the tracer attempts to retrieve sampling strategy:

$ npm run start
Initializing Jaeger Tracer with RemoteReporter and RemoteSampler
API initialized
Error in parsing sampling strategy: SyntaxError: Unexpected token c in JSON at position 1.

This is due to the following problem:

$ curl -sS -i -H'Content-Type: application/json' --connect-timeout 10 --max-time 60 -X GET 'http://localhost:5778/sampling?service=foo'
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Mon, 17 Jul 2017 14:33:40 GMT
Content-Length: 37

tcollector error: no peers available

Simplify how the client is imported

Instead of var SpanContext = require('jaeger-client/dist/src/span_context.js').default; there should be a simpler way, e.g. require('jaeger-client').SpanContext

Add flag to the tracer to enable/disable deferred sampling behavior

From #113

Can we instead add a boolean param to the tracer that will enable the deferred sampling behavior? The code seems to be fairly isolated, so we can just exit from processDeferredSampling if the flag is not set, then there will be no impact, yet all the code will remain in place and we'll just need to take out the config param in the future (or make it default to enabled).

Uncaught exception from finish()

Moved from opentracing/opentracing-javascript#83

@frankgreco is getting an uncaught exception

{ Error: getaddrinfo ENOTFOUND jaeger-agent.kube-system.svc.cluster.local
    at errnoException (dns.js:28:10)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)
  code: 'ENOTFOUND',
  errno: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: 'jaeger-agent.kube-system.svc.cluster.local' }

We need to wrap the sender in a try/catch and log the error if the logger is provider.

Reference Errror

Hi I am new to jaeger, When i run below given initialization code, I am getting "Reference Error metrics is not defined " . How to define metrics, logger variables.

My initialization sample code below.

var initTracer = require('jaeger-client').initTracer;
var config = {
'serviceName': 'my-awesome-service'
};
var options = {
'tags': {
'my-awesome-service.version': '1.1.2'
},
'metrics': metrics,
'logger': logger
};
var tracer = initTracer(config, options);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.