diff --git a/lib/http-instrumentation-tempo/v1.0.0/index.js b/lib/http-instrumentation-tempo/v1.0.0/index.js index e31849a..e2a29a3 100644 --- a/lib/http-instrumentation-tempo/v1.0.0/index.js +++ b/lib/http-instrumentation-tempo/v1.0.0/index.js @@ -9,191 +9,191 @@ const request = http.request; const asyncRequest = http.asyncRequest; const propagatorMap = { - "w3c": (sampler, traceID) => { - return { - "traceparent": `00-${traceID}-${randHexString(16)}-${sampler() ? "01" : "00"}` - } - }, - "jaeger": (sampler, traceID) => { - return { - "uber-trace-id": `${traceID}:${randHexString(8)}:0:${sampler() ? "1" : "0"}`, - } - }, + "w3c": (sampler, traceID) => { + return { + "traceparent": `00-${traceID}-${randHexString(16)}-${sampler() ? "01" : "00"}` + } + }, + "jaeger": (sampler, traceID) => { + return { + "uber-trace-id": `${traceID}:${randHexString(8)}:0:${sampler() ? "1" : "0"}`, + } + }, } class Client { - #propagator; - #sampler; - - constructor(opts) { - this.configure(opts) - } - - configure(opts) { - this.#sampler = newProbalisticSampler(opts.sampling); - this.#propagator = propagatorMap[opts.propagator]; - if (this.#propagator == null) { - throw "unknown propagator: " + opts.propagator - } - } - - // request instruments the http module's request function with tracing headers, - // and ensures the trace_id is emitted as part of the output's data points metadata. - request(method, url, ...args) { - const traceID = newTraceID() - const traceContextHeader = this.#propagator(this.#sampler, traceID) - args = instrumentArguments(traceContextHeader, ...args) - - try { - execution.vu.metrics.metadata["trace_id"] = traceID - return request(method, url, ...args) - } finally { - delete execution.vu.metrics.metadata["trace_id"] - - } - } - - // asyncRequest instruments the http module's asyncRequest function with tracing headers, - // and ensures the trace_id is emitted as part of the output's data points metadata. - async asyncRequest(method, url, ...args) { - const traceID = newTraceID() - const traceContextHeader = this.#propagator(this.#sampler, traceID) - args = instrumentArguments(traceContextHeader, ...args) - - let promise; - try { - execution.vu.metrics.metadata["trace_id"] = traceID - promise = asyncRequest(method, url, ...args) - } finally { - delete execution.vu.metrics.metadata["trace_id"] - } - - return await promise; - } - - del(url, ...args) { return this.request("DELETE", url, ...args) } - get(url, ...args) { return this.request("GET", url, null, ...args) } - head(url, ...args) { return this.request("HEAD", url, null, ...args) } - options(url, ...args) { return this.request("OPTIONS", url, ...args) } - patch(url, ...args) { return this.request("PATCH", url, ...args) } - post(url, ...args) { return this.request("POST", url, ...args) } - put(url, ...args) { return this.request("PUT", url, ...args) } + #propagator; + #sampler; + + constructor(opts) { + this.configure(opts) + } + + configure(opts) { + this.#sampler = newProbalisticSampler(opts.sampling); + this.#propagator = propagatorMap[opts.propagator]; + if (this.#propagator == null) { + throw "unknown propagator: " + opts.propagator + } + } + + // request instruments the http module's request function with tracing headers, + // and ensures the trace_id is emitted as part of the output's data points metadata. + request(method, url, ...args) { + const traceID = newTraceID() + const traceContextHeader = this.#propagator(this.#sampler, traceID) + args = instrumentArguments(traceContextHeader, ...args) + + try { + execution.vu.metrics.metadata["trace_id"] = traceID + return request(method, url, ...args) + } finally { + delete execution.vu.metrics.metadata["trace_id"] + + } + } + + // asyncRequest instruments the http module's asyncRequest function with tracing headers, + // and ensures the trace_id is emitted as part of the output's data points metadata. + async asyncRequest(method, url, ...args) { + const traceID = newTraceID() + const traceContextHeader = this.#propagator(this.#sampler, traceID) + args = instrumentArguments(traceContextHeader, ...args) + + let promise; + try { + execution.vu.metrics.metadata["trace_id"] = traceID + promise = asyncRequest(method, url, ...args) + } finally { + delete execution.vu.metrics.metadata["trace_id"] + } + + return await promise; + } + + del(url, ...args) { return this.request("DELETE", url, ...args) } + get(url, ...args) { return this.request("GET", url, null, ...args) } + head(url, ...args) { return this.request("HEAD", url, null, ...args) } + options(url, ...args) { return this.request("OPTIONS", url, ...args) } + patch(url, ...args) { return this.request("PATCH", url, ...args) } + post(url, ...args) { return this.request("POST", url, ...args) } + put(url, ...args) { return this.request("PUT", url, ...args) } } function longToByteArray(long) { - var byteArray = new Uint8Array(8) - - for (var index = byteArray.byteLength; index >= 0; index--) { - const byte = long % 256 - byteArray[index] = byte - long = (long-byte)/256; - if (long < 1) { - break - } - } - - return byteArray; + var byteArray = new Uint8Array(8) + + for (var index = byteArray.byteLength; index >= 0; index--) { + const byte = long % 256 + byteArray[index] = byte + long = (long-byte)/256; + if (long < 1) { + break + } + } + + return byteArray; } function instrumentArguments(traceContext, ...args) { - switch (args.length) { - case 0: - args.push(null) - // fallthrough to add the header - case 1: - // We only received a body argument - args.push({ headers: traceContext }) - break; - default: // this handles 2 and more just in case someone provided more arguments - // We received both a body and a params argument. In the - // event params would be nullish, we'll instantiate - // a new object. - if (args[1] == null) args[1] = {} - - let params = args[1] - if (params.headers == null) { - params.headers = {} - } - Object.assign(params.headers, traceContext) - break; - } - - return args + switch (args.length) { + case 0: + args.push(null) + // fallthrough to add the header + case 1: + // We only received a body argument + args.push({ headers: traceContext }) + break; + default: // this handles 2 and more just in case someone provided more arguments + // We received both a body and a params argument. In the + // event params would be nullish, we'll instantiate + // a new object. + if (args[1] == null) args[1] = {} + + let params = args[1] + if (params.headers == null) { + params.headers = {} + } + Object.assign(params.headers, traceContext) + break; + } + + return args } function newTraceID() { - let result = "dc0718" // prefix for k6 - - // add nanoseconds - let now = Date.now() - const ns = longToByteArray(now * 1e6) // this is very likely ... loosy - let n = 3 - let i = 0 - for (; i < ns.byteLength; i++) { // skip leading zeros - if (ns[i] == 0) continue; - break; - } - for (; i < ns.byteLength; i++) { - result += ns[i].toString(16).padStart(2, "0") - n++; - } - - // pad with random - let random = new Uint8Array(crypto.randomBytes(16 - n)); - for (i=0; i < random.byteLength; i++) { - result += random[i].toString(16).padStart(2, "0") - n++; - } - - return result + let result = "dc0718" // prefix for k6 + + // add nanoseconds + let now = Date.now() + const ns = longToByteArray(now * 1e6) // this is very likely ... loosy + let n = 3 + let i = 0 + for (; i < ns.byteLength; i++) { // skip leading zeros + if (ns[i] == 0) continue; + break; + } + for (; i < ns.byteLength; i++) { + result += ns[i].toString(16).padStart(2, "0") + n++; + } + + // pad with random + let random = new Uint8Array(crypto.randomBytes(16 - n)); + for (i=0; i < random.byteLength; i++) { + result += random[i].toString(16).padStart(2, "0") + n++; + } + + return result } function newProbalisticSampler(samplingRate) { - if (samplingRate < 0 || samplingRate > 1) { - throw "sampling rate must be between 0.0 and 1.0" - } - if (typeof samplingRate == 'undefined') { - samplingRate = 1 - - } - switch (samplingRate) { - case 0: - return () => false - case 1: - return () => true - default: - return () => Math.random() < samplingRate - } + if (samplingRate < 0 || samplingRate > 1) { + throw "sampling rate must be between 0.0 and 1.0" + } + if (typeof samplingRate == 'undefined') { + samplingRate = 1 + + } + switch (samplingRate) { + case 0: + return () => false + case 1: + return () => true + default: + return () => Math.random() < samplingRate + } } const digits = "0123456789abcdef"; function randHexString(n) { - let result = ''; - for (let i = 0; i < n; ++i) { - result += digits[Math.floor(16 * Math.random())]; - } - return result; + let result = ''; + for (let i = 0; i < n; ++i) { + result += digits[Math.floor(16 * Math.random())]; + } + return result; } function instrumentHTTP(opts) { - const client = new Client(opts) - - http.del = client.del.bind(client); - http.get = client.get.bind(client); - http.head = client.head.bind(client); - http.options = client.options.bind(client); - http.patch = client.patch.bind(client); - http.post = client.post.bind(client); - http.put = client.put.bind(client); - http.request = client.request.bind(client) - http.asyncRequest = client.asyncRequest.bind(client) + const client = new Client(opts) + + http.del = client.del.bind(client); + http.get = client.get.bind(client); + http.head = client.head.bind(client); + http.options = client.options.bind(client); + http.patch = client.patch.bind(client); + http.post = client.post.bind(client); + http.put = client.put.bind(client); + http.request = client.request.bind(client) + http.asyncRequest = client.asyncRequest.bind(client) } const exp = { Client: Client, instrumentHTTP: instrumentHTTP }; module.exports = { - default: exp, - __esModule: true, - ...exp + default: exp, + __esModule: true, + ...exp }