openzipkin / zipkin-js Goto Github PK
View Code? Open in Web Editor NEWZipkin instrumentation for Node.js and browsers
License: Apache License 2.0
Zipkin instrumentation for Node.js and browsers
License: Apache License 2.0
It should be possible for applications to handle errors in the loggers, by adding e.g.
kafkaLogger.on('error', err => console.error('oops', err));
to the code. That means we need to forward the error events from the underlying implementations.
Another alternative is to let users provide their own scribe client or kafka client etc., and let them add error handling directly on their underlying client.
function makeCountingEvaluator(sampleRate) {
if (sampleRate <= 0) {
return neverSample;
} else if (sampleRate >= 1) {
return alwaysSample;
} else {
let counter = 0;
const limit = parseInt(1 / sampleRate);
const counting = function counting(traceId) { // eslint-disable-line no-unused-vars
counter = counter % limit;
const shouldSample = counter === 0;
counter++;
return shouldSample;
};
counting.toString = () => countingSampler: sampleRate=${sampleRate}
;
return counting;
}
}
In your code, if the sampleRate > 0.5, then the limit is 1, so sample rate 0.9 will not sample 90 % of all incoming requests, otherwise it will sample 100%.
am i right?
looking forward your answer!
I've successfully integrated zipkin on some of our services. In most of them we are using Bluebird to promisify the redis.RedisClient
and we are using request-promise
for external service request, which also uses Bluebird internally.
What is the best approach to wrapping a promisified redisClient
and request-promise
? Should we use the zipkin-instrumentation-redis
and zipkin-instrumentation-request
packages and then promisify them? Or should we create our own instrumentation packages that support Promises?
Hi,
I just dived into Zipkin and it's really cool so far. But I couldn't get it running perfectly.
To test the interaction I set up two express Server in docker and one is calling the other.
However, both servers emit the same Span information SpanID, ParentID and TraceID. Is that an intended behaviour, a bug or did I screw something up?
Is the Service that creates the root span (in this case watch_1
) supposed to have a ParentID?
(watch_1
calls, fetchme_1
responds )
If the environment variable FETCH_URL is set it will act as the caller otherwise it will just respond to queries.
import * as express from "express";
var fetch = require('node-fetch');
const {trace, BatchRecorder, Tracer, ExplicitContext, ConsoleRecorder} = require('zipkin');
const zipkinMiddleware = require('zipkin-instrumentation-express').expressMiddleware;
const {HttpLogger} = require('zipkin-transport-http');
const CLSContext = require('zipkin-context-cls');
var ctxImpl = new ExplicitContext();
var recorder = new ConsoleRecorder();
const tracer = new Tracer({
recorder: recorder,
ctxImpl: new CLSContext('zipkin')
});
//CALLER
const wrapFetch = require('zipkin-instrumentation-fetch');
const zipkinFetch = wrapFetch(fetch, {
tracer,
serviceName: process.env.SERVICE_NAME + '-fetch-' + process.env.APPLICATION_PORT,
port: process.env.APPLICATION_PORT
});
if (process.env.FETCH_URL != undefined) {
setTimeout(function () {
zipkinFetch(process.env.FETCH_URL).then(function (res) {
return res.text();
}).then(function (body) {
console.log(body)
});
}, 1000)
}
var app = express();
//RECEIVER
app.use(function (request:express.Request, response:express.Response, next) {
console.log(request.headers);
next()
});
app.use(zipkinMiddleware({
tracer,
serviceName: process.env.SERVICE_NAME + '-middleware-' + process.env.APPLICATION_PORT,
port: process.env.APPLICATION_PORT
}));
app.use('/', function (request:express.Request, response:express.Response, next) {
response.send('Hi');
});
app.listen(process.env.APPLICATION_PORT, function () {
console.log('The PetStore sample is now running at http://localhost:' + process.env.APPLICATION_PORT);
});
Thanks in advance :)
Hi - you're using thrift
and thrift
is using ws
. thrift
has not patched an old security vulnerability in ws
.
https://nodesecurity.io/advisories/120 and https://nodesecurity.io/advisories/67
Thrift has an issue here: https://issues.apache.org/jira/browse/THRIFT-4064
Any chance you can urge thrift to patch?
The current implementation in time.js has a bug:
const d = new Date();
return d.getTime() * 1000
+ d.getMilliseconds(); // <-- This should be microseconds, not milliseconds
We want to get the number of microseconds since 1970, not the number of milliseconds. That's why we take d.getTime(), which returns number of milliseconds from 1970, and multiply by 1000, to get number of microseconds since 1970.
In order to solve this, we need to find a timer with microsecond precision, that preferably works both in the browser and in node.js.
from @rektide
Node.js can now see the V8 tracing info. Some bridge of those internal traces into [zipkin] could be dandy.
I have a cloud slueth zipkin application A1 in spring boot. I also have a zipkin server application A2 in spring boot.When I run the zipkin server A2 at localhost at default port 9411, then A1 trace ids are sent to zipkin server A2. When the port of the zipkin server is changed and is successfully started at the new port 9455, the application A1 fails to send logs to zipkin-server. URLConnectionSender{encoding=THRIFT, messageMaxBytes=5242880, encoder=THRIFT, endpoint=http://localhost:9411/api/v1/spans, connectTimeout=10000, readTimeout=60000, compressionEnabled=false, mediaType=application/x-thrift})] WARN z.r.AsyncReporter$BoundedAsyncReporter - Dropped 1 spans due to ConnectException(Connection refused: connect). The cloud slueth zipkin server end point is not changing even when following properties are set in aplication.yml
spring.zipkin.baseUrl = corrrect host and port and
sample:
zipkin:
enabled: true
The current implementation of the HTTP transporter does not send open records in it's queue when the node process finished executing (no events left in the queue).
if (timer.unref) { // unref might not be available in browsers
timer.unref(); // Allows Node to terminate instead of blocking on timer
}
Why shouldn't the transporter send all open records before exiting?
There are a number of zipkin libraries supporting local tracing (operations that spawn in-process and are not RPCs).
We've recently had a request by @wirehead for how to do this.
// Is this how I'm supposed to instrument a long-running function?
function ExampleTraceFunction() {
tracer.setId(tracer.createRootId());
tracer.recordMessage('start');
// do stuff here
tracer.recordMessage('end');
}
I suggested a workaround, which is to use Client annotations while we figure out how we want to address this here.
function ExampleTraceFunction() {
tracer.scoped(() => {
tracer.setId(tracer.createRootId());
tracer.recordAnnotation(new Annotation.ClientSend());
// do work
tracer.recordAnnotation(new Annotation.ClientRecv());
});
}
There's a background issue in finagle which might steer implementation. twitter/finagle#541
cc @fedj
We're currently working on a refactor of zipkin-js, where you, instead of using continuation-local-storage, can provide your own context API. This is handy for people who either don't want to use continuation-local-storage for whatever reasons, and/or people who already have a context object they pass around explicitly in their application code.
Another use case would be to run zipkin-js in the browser, where we can inject zone.js as a context api.
The work is going on in a feature branch.
Best way to get the generated traceId?
Currently is generated inside the wrapFetch:
...
tracer.scoped(() => { tracer.setId(tracer.createChildId()); const traceId = tracer.id;
And added as request header: x-b3-traceid
const zipkinOpts = Request.addZipkinHeaders(opts, traceId);
But what happens if we want to use that traceId later to access the Zipkin API? for example using /traces/{traceId}
I tried with the recorder, without success.
The other way is to rewrite the wrapFetch function and include the traceId when resolving the fetch promise.
resolve({response: res, traceId: traceId.traceId});
Any other options?
Thanks!
I am making proof of concept client - server app with tracing via zipkin. The problem is spans are not being sent to Zipkin running on localhost when im using Cujojs/REST instrumentation. I can make request to my server (running on http://localhost:9999
) and I can properly read Zipkin headers on the server. This is my Js client code:
const {Tracer, BatchRecorder, ExplicitContext} = require('zipkin');
const {HttpLogger} = require('zipkin-transport-http');
const {restInterceptor} = require('zipkin-instrumentation-cujojs-rest');
const rest = require('rest');
const ctxImpl = new ExplicitContext();
const recorder = new BatchRecorder({
logger: new HttpLogger({
endpoint: 'http://localhost:9411/api/v1/spans'
})
});
const tracer = new Tracer({ctxImpl, recorder});
const nameOfRemoteService = 'Client';
const client = rest.wrap(restInterceptor, {tracer, serviceName: nameOfRemoteService});
client({
method: 'GET',
path: 'http://localhost:9999/request'
}).then(function(response) {
console.log('response: ', response);
});
record
method of BatchRecorder has a piece of code, that tries to cast the host
field of the annotation to integer, using rec.annotation.host.toInt()
of your InetAddress
class.
It seems ServerAddr
annotation constructor doesn't have any opinion about host
parameter, so this behaviour mightn't be expected.
For example, the zipkin-instrumentation-redis
provides an example, which uses host as a raw string both for connection options and for remote server annotation:
const redisConnectionOptions = {
host: 'localhost',
port: '6379'
};
const redis = zipkinClient(tracer, Redis, redisConnectionOptions);
Shouldn't BatchRecorder
cast host field of ServerAddr
annotation to integer (ipv4/ipv6 address) during the recording process?
We currently support logging of only IPv4 addresses. Starting with Zipkin 1.4 endpoints can omit IPv4 (by setting Endpoint.ipv4 to 0), and optionally log Endpoint.ipv6 as the raw 16byte address.
https://github.com/openzipkin/zipkin-api/blob/master/thrift/zipkinCore.thrift#L276
In json, both are the string formatting http://zipkin.io/zipkin-api
ipv4:
string
The text representation of a IPv4 address associated with this endpoint. Ex. 192.168.99.100
ipv6:
string
The text representation of a IPv6 address associated with this endpoint. Ex. 2001:db8::c001
Lengthy requests exceeding several seconds are being reported as 1-2ms.
Wrote a failing test here: https://github.com/zackangelo/zipkin-js/blob/fix_hapi_span_duration/packages/zipkin-instrumentation-hapi/test/integrationTest.js#L157
Has anyone else noticed this? If so, or seems entirely possible, will open a PR to fix.
We should make zipkin-js' public API fool-proof, by validating every input argument to every public function.
This transitively pulls in vulnerable minimatch (https://nodesecurity.io/advisories/118). Any chance you could upgrade?
https://github.com/openzipkin/zipkin-js/tree/master/packages/zipkin-transport-kafka
Doesn't seem like there's any breaking changes, should be straight forward: https://github.com/SOHU-Co/kafka-node/blob/master/CHANGELOG.md
(if they don't already exist)
I noticed in fetch and cujo examples like this:
const nameOfRemoteService = 'youtube';
const zipkinFetch = wrapFetch(fetch, {tracer, serviceName: nameOfRemoteService});
In code, we aren't actually using the name as mentioned, as it is being used for the local service. In most libraries, we set the local service name (and address), as a part of initializing the tracer.
When calling an uninstrumented server, like mysql or redis, we allow you to control the ServerAddr, which helps especially in the case of the dependency graph.
We should move declaring the local service to tracer initialization (at least a default one) and add support for ServerAddr, which examples like above could use.
Hello,
Not sure if I missed something but I think there is no possibility to customize the span name in zipkin-js.
For example, in the previous screenshot, I would like to show something else than "get" for the first calls (js), rest of the app is polyglot but I managed to put what I wanted to name the spans.
Did I miss something ?
Thanks in advance
Are there any plans of adding support for hapi.js? It'd be great to have this.
Hey there,
First of all thanks for this great project, it really helps us tracing performance issues in our stack. For the last part of the stack, the react native mobile app, we ran into an issue:
Zipkin requires the package network-address
to determine the current IP automatically in getLocalAddress
.
We don't need this functionality, but as the require is on top level we still run into issues, because network-address
uses the os
package. This is native to node and not available in the V8 / Safari engine we use.
If we could move the require into the function or migrate to a fallback for non-node environments it would be a lot easier for us. If you agree I would be glad to contribute a PR.
zipkin-java has a JsonCodec class that is used by things like ElasticsearchSpanConsumer or spring-cloud-sleuth HttpZipkinSpanReporter. Can support for JsonCodec be added?
I am looking to leverage the "Spring Cloud Zipkin UI" (not sure of the proper name, but screenshots at https://spring.io/blog/2016/02/15/distributed-tracing-with-spring-cloud-sleuth-and-spring-cloud-zipkin) and this seems like a required prerequisite.
Looks like the prepublish script (for babel) doesn't work on Windows... we need to have a look at porting it so that it works on all platforms. (I think it should be possible to release zipkin-js from a Windows machine if needed)
It would be nice to have interceptors similar to the grpc ones from openzipkin/brave
The constructor for expressMiddleware takes a default value for port
of 0
module.exports = function expressMiddleware({tracer, serviceName = 'unknown', port = 0}) {
Using ConsoleRecorder
I see log records like this, where the port is known to be 3000 as part of the HOST header but port=0
when constructing the InetAddress.
Record at (spanId=b1d6a95787bb7f9d, parentId=b1d6a95787bb7f9d, traceId=b1d6a95787bb7f9d): BinaryAnnotation(http.url="http://localhost:3000/")
Record at (spanId=b1d6a95787bb7f9d, parentId=b1d6a95787bb7f9d, traceId=b1d6a95787bb7f9d): ServerRecv()
Record at (spanId=b1d6a95787bb7f9d, parentId=b1d6a95787bb7f9d, traceId=b1d6a95787bb7f9d): LocalAddr(host="InetAddress(10.211.55.2)", port=0)
It seems like the port
should be derived from the HOST header when left as its default value.
tracer.recordBinary('http.url', url.format({
protocol: req.protocol,
host: req.get('host'),
pathname: req.originalUrl
}));
tracer.recordAnnotation(new Annotation.ServerRecv());
tracer.recordAnnotation(new Annotation.LocalAddr({port}));
it would be nice if there is a es5 equivalent of this project. I have converted this entire project to es5 using babel. but not tested completely.
https://github.com/byteshiva/zipkin-js-es5
It would be helpful, to run this project on version below node 4.1.0 or something above 0.10.35
In my Spring Cloud Sleuth library I can set a sample resolution for zipkin integration (e.g. 10% of spans are published per instance). Can this library be configured in a similar way?
https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/README.adoc
Right now, only the server-side code add the annotation LocalAddr, usually when they have a port
tracer.recordAnnotation(new Annotation.LocalAddr({port}));
https://github.com/openzipkin/zipkin-js/blob/master/packages/zipkin-instrumentation-express/src/expressMiddleware.js#L85
ย
The client side doesn't, but it should as otherwise annotations are allocated to IP "unknown"
One way is to go through all the client libraries and do the following when they don't know the client-side of the socket.
tracer.recordAnnotation(new Annotation.LocalAddr());
Another way is to default LocalAddr somehow in tracer
Thanks to @bojand for reporting
If I (or someone) can work out a way to do it would you be open to accepting a PR that has a prepublish step that transpiles the ES6 code to ES5 so that ES5 restrained consumers can also use this module?
E.g. prepublish uses babel to generate output to /lib/es5/ before publish and that's the entry point for ES5 consumers. This would not impact the ES6 consumers and the current ES6 being used in the module. i.e. ES6 by default. ES5 needs to be explicitly required
by the consumer by path.
Might also help with #1 which might need ES5 for browsers.
There are a couple places where we use console logging for errors where it would be good if you could pass in a logger to use instead of console.error
. We can still default to console logging if that's desired, but in a lot of cases I think users will already have a logger they want to use. Should be fairly easy to implement. Examples would be in HttpLogger
or ScribeLogger
.
Hi,
Recently I needed to integrate a koa based microservice with zipkin. I didn't find any existing integrations and had to write my custom middleware. Now I'm thinking about contributing it to open source. Would it be reasonable to add corresponding module to zipkin-js/packages?
Recent versions of the zipkin thrift have the fields Span.timestamp and duration. Particularly in the case of client spans, we can set an authoritative start, with duration accurate to microseconds. This would start by updating the model to the latest thrift.
https://github.com/openzipkin/zipkin-api/blob/master/thrift/zipkinCore.thrift
Hi, I can not run zipkin because missing strict modes.
Node: 4.6.0
E:\Repositorys\test\node_modules\zipkin\src\option.js:31
class Some {
^^^^^
SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
at exports.runInThisContext (vm.js:53:16)
I keep receiving the error "ScribeLogger is not a constructor" when I instrument a brand new express application using the sample code provided for the Scribe implementation. Any help on this would be appreciated. Relevant code below...
//New for Zipkin
const {Tracer, ExplicitContext, BatchRecorder} = require('zipkin');
var zipkinMiddleware = require('zipkin-instrumentation-express').expressMiddleware;
const ScribeLogger = require('zipkin-transport-scribe');
const scribeRecorder = new BatchRecorder({
logger: new ScribeLogger({
scribeHost: '127.0.0.1',
scribePort: 2411,
scribeInterval: 1
})
});
var ctxImpl = new ExplicitContext();
//var recorder = new ConsoleRecorder();
var tracer = new Tracer({ctxImpl, scribeRecorder});
//
var app = express();
//Add the Zipkin Middleware
app.use(zipkinMiddleware({
tracer,
serviceName: 'zipkinTesting'
}));
The README.md uses this sample code:
zipkinFetch('http://www.youtube.com/').then(res => res.json()).then(data => ...);
But with only a url
parameter, this error appears:
TypeError: Cannot read property 'method' of undefined
This appears to be because wrapFetch.js
assumes the opts
object exists:
const method = opts.method || 'GET';
Assuming the behavior should matchnode-fetch
, the documentation is correct and the code implementation should be fixed.
I'll post up a quick sample as soon as I have a second, but I wanted to record it here so I don't forget.
I was using both body-parser and zipkinMiddleware, with body-parser being the last item in the middleware chain.
Using getContext() + letContext() would give me a new spanid/traceid every time, rather than using the ID generated in the middleware.
(Once I can show you as an example) - is this intended behavior that we want documented, or something we can enhance?
i focked this repo at https://github.com/hafeyang/zipkin-js/tree/master/packages/zipkin-instrumentation-mongodb
ctxImpl.letContext(ctx, () => {
const url = 'mongodb://localhost:27017/zipkin_test';
MongoClient.connect(url, function(err, db) {
const col = db.collection('somecollection');
ctxImpl.letContext(ctx, () => {
col.deleteMany({}, {}, function() {
ctxImpl.letContext(ctx, () => {
col.insertMany([{a: 1}, {a: 2}, {a: 3}], function() {
db.close();
const annotations = record.args.map(args => args[0]);
annotations.forEach(a => console.log(a.traceId.traceId+" "+a.traceId.spanId+" "+a.traceId.parentId));
console.log(annotations);
done();
});
});
});
});
});
});
here is my test code , annotations logged and i found traceId changed,and i got 2 traceId.
may caused by context losing
detailed err description and code pls check https://github.com/hafeyang/zipkin-js/tree/master/packages/zipkin-instrumentation-mongodb
Thanks!
The README focuses on node, but we do actually work on browsers. Maybe we could revise some things and suggest browserify (if that's a decent recommendation).
From @virusdave
I want to get a whole-system tracing tree that is rooted in a client's action on a web page. While there is a zipkin-js project, this appears to be a server-side node.js library. Is there a canonical client-side JS library that one would use to do things like 'start a new trace', 'annotate trace with browser info', 'send trace data to a specific collector', etc?
OpenTracing website proclaims that Zipkin is one of the supported implementations. However, the interface of the tracer provided by zipkin
does not seem to be any close to the official Javascript OpenTracing API and it fails with the TypeError: Uncaught error: tracer.startSpan is not a function
.
Am I missing something fundamental (quite possible), or is openzipkin/zipkin-js
indeed incompatible with OpenTracing API? In the latter case, is there either a plan to provide compatibility with OpenTracing API (and/or willingness to accept pull requests which would provide it), or some other zipkin tracer implementation that would be compatible wityh OpenTracing API?
I have done a lot of research lately, and I just can't find any implementation of Zipkin with socket based app (SPA).
hi team,I have a doubt that the zipkin-js agent how to know current callstack has finished and then send the traced data to collector?
I use restify
and redis
to test zipkin-js
, script as follow
const restify = require('restify');
const {Tracer, ExplicitContext, ConsoleRecorder, BatchRecorder} = require('zipkin');
const zipkinMiddleware = require('zipkin-instrumentation-restify').restifyMiddleware;
const zipkinClient = require('zipkin-instrumentation-redis');
const Redis = require('redis');
const redisConnectionOptions = {
host: '192.168.4.114',
port: 6379
};
const ctxImpl = new ExplicitContext();
const recorder = new ConsoleRecorder();
const tracer = new Tracer({ctxImpl, recorder});
const redis = zipkinClient(tracer, Redis, redisConnectionOptions, "redis");
const app = restify.createServer();
app.use(zipkinMiddleware({
tracer,
serviceName: 'service-a'
}));
app.get('/echo/:name', function (req, res, next) {
const name = req.params.name
redis.set(name, name, (err, data) => {
redis.get(name, (err, data) => {
res.send(req.params)
return next()
})
});
});
app.listen(9999, function () {
console.log('%s listening at %s', app.name, app.url);
});
I think result is not right
I'm trying to get zipkin-js working in the browser, by browserify'ing the following
It eventually dies on timer.unref();
from BatchRecorder. I'm not sure if there are tricks to make it not die.
Here's my example code:
const {Tracer, BatchRecorder, ExplicitContext} = require('zipkin');
const {HttpLogger} = require('zipkin-transport-http');
const recorder = new BatchRecorder({
logger: new HttpLogger({
endpoint: 'http://localhost:9411/api/v1/spans'
})
});
const ctxImpl = new ExplicitContext();
const tracer = new Tracer({ctxImpl, recorder});
const wrapFetch = require('zipkin-instrumentation-fetch');
const zipkinFetch = wrapFetch(fetch, {tracer, serviceName: 'browser'});
var result = fetch('/api')
result.then(function(response) {
console.log('response', response)
console.log('header', response.headers.get('Content-Type'))
return response.text()
}).then(function(text) {
console.log('got text', text)
}).catch(function(ex) {
console.log('failed', ex)
})
By applying this patch to the test in zipkin-transport-scribe
diff --git a/packages/zipkin-transport-scribe/test/integrationTest.js b/packages/zipkin-transport-scribe/test/integrationTest.js
index 6a0179c..2c269fa 100644
--- a/packages/zipkin-transport-scribe/test/integrationTest.js
+++ b/packages/zipkin-transport-scribe/test/integrationTest.js
@@ -46,6 +46,7 @@ describe('Scribe transport - integration test', () => {
flags: 0
});
tracer.setId(id);
+ tracer.recordAnnotation(new Annotation.ServerAddr({serviceName: 'test'}));
tracer.recordAnnotation(new Annotation.ClientSend());
tracer.recordAnnotation(new Annotation.ClientRecv());
setTimeout(() => {
I get this error:
Scribe transport - integration test
1) should send trace data to Scribe
1) Scribe transport - integration test should send trace data to Scribe:
Uncaught TypeError: buf.copy is not a function
at /dev/zipkin-js/node_modules/thrift/lib/nodejs/lib/thrift/buffered_transport.js:164:9
at Array.forEach (native)
at TBufferedTransport.flush (/dev/zipkin-js/node_modules/thrift/lib/nodejs/lib/thrift/buffered_transport.js:163:19)
at TBinaryProtocol.flush (/dev/zipkin-js/node_modules/thrift/lib/nodejs/lib/thrift/binary_protocol.js:43:21)
at serializeSpan (/dev/zipkin-js/packages/zipkin/lib/serializeSpan.js:21:12)
at queue.forEach.span (src/ScribeLogger.js:19:43)
at Array.forEach (native)
at scribeClient.open.err (src/ScribeLogger.js:18:24)
at .<anonymous> (/dev/zipkin-js/node_modules/scribe/lib/scribe.js:110:7)
at Socket.<anonymous> (/dev/zipkin-js/node_modules/scribe/node_modules/thrift/lib/thrift/connection.js:52:10)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1077:10)
The error occurs on the latest package version on latest node v7 and v6.
Update:
I did more debugging on this and found a UInt8Array in the span that the thrift library expects to be a Buffer with the copy method.
I changed the offending line and it no longer fails.
diff --git a/packages/zipkin/src/internalRepresentations.js b/packages/zipkin/src/internalRepresentations.js
index 1d3ee71..379abfa 100644
--- a/packages/zipkin/src/internalRepresentations.js
+++ b/packages/zipkin/src/internalRepresentations.js
@@ -91,8 +91,7 @@ function Address({key, endpoint}) {
this.endpoint = endpoint;
}
Address.prototype.toThrift = function toThrift() {
- const value = new Uint8Array(1);
- value[0] = 1;
+ const value = Buffer.from([1]);
const res = new thriftTypes.BinaryAnnotation({
key: this.key,
value,
Pull Request inbound!
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.