jaegertracing / jaeger-client-node Goto Github PK
View Code? Open in Web Editor NEW๐ This library is DEPRECATED!
Home Page: https://jaegertracing.io/
License: Apache License 2.0
๐ This library is DEPRECATED!
Home Page: https://jaegertracing.io/
License: Apache License 2.0
@oibe said
long is used only because its a type recognized by thriftrw (we should remove that...).
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.
URL encoding of the tracing headers showed up as a large part of the flame graph. We need to minimize its use
split(":")
, and only if that didn't work we can try urlDecodeHi 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.
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);
We're using this to log, so it's better to log the actual underlying failure.
For the sake of consistency, it would be useful if tags could be aggregated via JAEGER_TAGS
environment variable like in the Java client.
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.
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:
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
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
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
const require('jaeger-client')
Fails with
ENOENT, no such file or directory '[redacted...]/node_modules/jaeger-client/dist/src/thriftrw-idl/agent.thrift'
I run frequently into EMSGSIZE
error with UDPSender
sender.
I tried to configure a huge maxPacketSize
without any luck.
Do you experience similar issue?
The current ESLint configuration is broken, and doesn't seem to be enforced during builds.
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=)
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.
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
Can't we have make publish
build all the required artifacts before submitting to npm repository instead of having those checked into git repository?
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.
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
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.
It would be nice to have typescript definition files (see Writing Definition Files)
Make agent host:port and sampling server URL configurable via ENV vars.
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.
Hello,
I have a question, can this library be used in a web browser?
-- update Jan 24 2020 --
jaegertracing/jaeger-client-javascript#1
https://github.com/uber/jaeger-client-node/blob/master/src/samplers/remote_sampler.js#L127
To return a more comprehensible log: #141 (comment)
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.
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.
Instructions in the readme are broken.
$ 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?
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"}]
There's a lot of locations in the codebase where we use an object where a map is more appropriate.
This is probably problem of (configuration of) all-in-one docker image, so it is more request for help than an issue.
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?
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
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();
})();
Golang is using scratch so the crossdock image is only 3MB. Do something similar for xdock-node
According to the specs Tracer.extract
should return null
when no trace context is found.
However, for HTTP requests with no span context, not null
but a SpanContext
with many undefined properties is returned. I believe the problem is in text_map_codec which doesn't check if a trace or span id exists.
Use https://github.com/graphql/graphql-js for reference
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.
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).
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.
$ npm run report-cover
> [email protected] report-cover ...
> nyc report --reporter html --reporter text
sh: nyc: command not found
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
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.
$ 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
The badge in the main repo shows coverage unknown
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.