@google-cloud/trace-agent
Advanced tools
Comparing version 2.3.1 to 2.3.2
@@ -53,3 +53,3 @@ /** Available configuration options. */ | ||
*/ | ||
ignoreUrls?: (string | RegExp)[]; | ||
ignoreUrls?: Array<string | RegExp>; | ||
/** | ||
@@ -143,2 +143,3 @@ * An upper bound on the number of traces to gather each second. If set to 0, | ||
'http': string; | ||
'https': string; | ||
'knex': string; | ||
@@ -145,0 +146,0 @@ 'koa': string; |
@@ -38,2 +38,3 @@ "use strict"; | ||
'http': path.join(__dirname, 'src/plugins/plugin-http.js'), | ||
'https': path.join(__dirname, 'src/plugins/plugin-https.js'), | ||
'knex': path.join(__dirname, 'src/plugins/plugin-knex.js'), | ||
@@ -40,0 +41,0 @@ 'koa': path.join(__dirname, 'src/plugins/plugin-koa.js'), |
@@ -55,2 +55,3 @@ "use strict"; | ||
// When it's landed and released, we can remove these `any` casts. | ||
// tslint:disable-next-line:no-any | ||
if (cb[wrappedSymbol] || !current) { | ||
@@ -67,2 +68,3 @@ return cb; | ||
}; | ||
// tslint:disable-next-line:no-any | ||
contextWrapper[wrappedSymbol] = true; | ||
@@ -84,4 +86,5 @@ Object.defineProperty(contextWrapper, 'length', { | ||
const ns = this; | ||
EVENT_EMITTER_METHODS.forEach(function (method) { | ||
EVENT_EMITTER_METHODS.forEach((method) => { | ||
// TODO(kjin): Presumably also dependent on MS/TS-#15473. | ||
// tslint:disable:no-any | ||
const oldMethod = ee[method]; | ||
@@ -91,2 +94,3 @@ ee[method] = function (event, cb) { | ||
}; | ||
// tslint:enable:no-any | ||
}); | ||
@@ -93,0 +97,0 @@ } |
/// <reference types="node" /> | ||
/** | ||
* Copyright 2017 Google Inc. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
import { Constants } from './constants'; | ||
@@ -3,0 +18,0 @@ import { TraceLabels } from './trace-labels'; |
"use strict"; | ||
/** | ||
* Copyright 2017 Google Inc. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=plugin-types.js.map |
@@ -44,11 +44,83 @@ /** | ||
} | ||
function unpatchHttp(http) { | ||
shimmer.unwrap(http, 'request'); | ||
if (semver.satisfies(process.version, '>=8.0.0')) { | ||
shimmer.unwrap(http, 'get'); | ||
} | ||
function isTraceAgentRequest(options, api) { | ||
return options && options.headers && | ||
!!options.headers[api.constants.TRACE_AGENT_REQUEST_HEADER]; | ||
} | ||
function makeRequestTrace(request, api) { | ||
// On Node 8+ we use the following function to patch both request and get. | ||
// Here `request` may also happen to be `get`. | ||
return function request_trace(options, callback) { | ||
if (!options) { | ||
return request.apply(this, arguments); | ||
} | ||
// Don't trace ourselves lest we get into infinite loops | ||
// Note: this would not be a problem if we guarantee buffering | ||
// of trace api calls. If there is no buffering then each trace is | ||
// an http call which will get a trace which will be an http call | ||
if (isTraceAgentRequest(options, api)) { | ||
return request.apply(this, arguments); | ||
} | ||
options = isString(options) ? url.parse(options) : merge({}, options); | ||
options.headers = options.headers || {}; | ||
var uri = extractUrl(options); | ||
var requestLifecycleSpan = api.createChildSpan({ name: getSpanName(options) }); | ||
if (!requestLifecycleSpan) { | ||
return request.apply(this, arguments); | ||
} | ||
requestLifecycleSpan.addLabel(api.labels.HTTP_METHOD_LABEL_KEY, options.method); | ||
requestLifecycleSpan.addLabel(api.labels.HTTP_URL_LABEL_KEY, uri); | ||
options.headers[api.constants.TRACE_CONTEXT_HEADER_NAME] = | ||
requestLifecycleSpan.getTraceContext(); | ||
var req = request.call(this, options, function (res) { | ||
api.wrapEmitter(res); | ||
var numBytes = 0; | ||
var listenerAttached = false; | ||
// Responses returned by http#request are yielded in paused mode. Attaching | ||
// a 'data' listener to the request will switch the stream to flowing mode | ||
// which could cause the request to drain before the calling framework has | ||
// a chance to attach their own listeners. To avoid this, we attach our listener | ||
// lazily. | ||
// This approach to tracking data size will not observe data read by | ||
// explicitly calling `read` on the request. We expect this to be very | ||
// uncommon as it is not mentioned in any of the official documentation. | ||
shimmer.wrap(res, 'on', function onWrap(on) { | ||
return function on_trace(eventName, cb) { | ||
if (eventName === 'data' && !listenerAttached) { | ||
on.call(this, 'data', function (chunk) { | ||
numBytes += chunk.length; | ||
}); | ||
} | ||
return on.apply(this, arguments); | ||
}; | ||
}); | ||
res.on('end', function () { | ||
requestLifecycleSpan | ||
.addLabel(api.labels.HTTP_RESPONSE_SIZE_LABEL_KEY, numBytes); | ||
requestLifecycleSpan | ||
.addLabel(api.labels.HTTP_RESPONSE_CODE_LABEL_KEY, res.statusCode); | ||
requestLifecycleSpan.endSpan(); | ||
}); | ||
if (callback) { | ||
return callback(res); | ||
} | ||
}); | ||
api.wrapEmitter(req); | ||
req.on('error', function (e) { | ||
if (e) { | ||
requestLifecycleSpan.addLabel(api.labels.ERROR_DETAILS_NAME, e.name); | ||
requestLifecycleSpan | ||
.addLabel(api.labels.ERROR_DETAILS_MESSAGE, e.message); | ||
} | ||
else { | ||
// What's the new logger target? | ||
// console.error('HTTP request error was null or undefined', e); | ||
} | ||
requestLifecycleSpan.endSpan(); | ||
}); | ||
return req; | ||
}; | ||
} | ||
function patchHttp(http, api) { | ||
shimmer.wrap(http, 'request', function requestWrap(request) { | ||
return makeRequestTrace(request); | ||
return makeRequestTrace(request, api); | ||
}); | ||
@@ -60,84 +132,24 @@ if (semver.satisfies(process.version, '>=8.0.0')) { | ||
shimmer.wrap(http, 'get', function getWrap(get) { | ||
return makeRequestTrace(get); | ||
return makeRequestTrace(get, api); | ||
}); | ||
} | ||
function isTraceAgentRequest(options) { | ||
return options && options.headers && | ||
!!options.headers[api.constants.TRACE_AGENT_REQUEST_HEADER]; | ||
} | ||
function patchHttps(https, api) { | ||
shimmer.wrap(https, 'request', function requestWrap(request) { | ||
return makeRequestTrace(request, api); | ||
}); | ||
shimmer.wrap(https, 'get', function getWrap(get) { | ||
return makeRequestTrace(get, api); | ||
}); | ||
} | ||
function unpatchHttp(http) { | ||
shimmer.unwrap(http, 'request'); | ||
if (semver.satisfies(process.version, '>=8.0.0')) { | ||
shimmer.unwrap(http, 'get'); | ||
} | ||
function makeRequestTrace(request) { | ||
// On Node 8+ we use the following function to patch both request and get. | ||
// Here `request` may also happen to be `get`. | ||
return function request_trace(options, callback) { | ||
if (!options) { | ||
return request.apply(this, arguments); | ||
} | ||
// Don't trace ourselves lest we get into infinite loops | ||
// Note: this would not be a problem if we guarantee buffering | ||
// of trace api calls. If there is no buffering then each trace is | ||
// an http call which will get a trace which will be an http call | ||
if (isTraceAgentRequest(options)) { | ||
return request.apply(this, arguments); | ||
} | ||
options = isString(options) ? url.parse(options) : merge({}, options); | ||
options.headers = options.headers || {}; | ||
var uri = extractUrl(options); | ||
var requestLifecycleSpan = api.createChildSpan({ name: getSpanName(options) }); | ||
if (!requestLifecycleSpan) { | ||
return request.apply(this, arguments); | ||
} | ||
requestLifecycleSpan.addLabel(api.labels.HTTP_METHOD_LABEL_KEY, options.method); | ||
requestLifecycleSpan.addLabel(api.labels.HTTP_URL_LABEL_KEY, uri); | ||
options.headers[api.constants.TRACE_CONTEXT_HEADER_NAME] = | ||
requestLifecycleSpan.getTraceContext(); | ||
var req = request.call(this, options, function (res) { | ||
api.wrapEmitter(res); | ||
var numBytes = 0; | ||
var listenerAttached = false; | ||
// Responses returned by http#request are yielded in paused mode. Attaching | ||
// a 'data' listener to the request will switch the stream to flowing mode | ||
// which could cause the request to drain before the calling framework has | ||
// a chance to attach their own listeners. To avoid this, we attach our listener | ||
// lazily. | ||
// This approach to tracking data size will not observe data read by | ||
// explicitly calling `read` on the request. We expect this to be very | ||
// uncommon as it is not mentioned in any of the official documentation. | ||
shimmer.wrap(res, 'on', function onWrap(on) { | ||
return function on_trace(eventName, cb) { | ||
if (eventName === 'data' && !listenerAttached) { | ||
on.call(this, 'data', function (chunk) { | ||
numBytes += chunk.length; | ||
}); | ||
} | ||
return on.apply(this, arguments); | ||
}; | ||
}); | ||
res.on('end', function () { | ||
requestLifecycleSpan | ||
.addLabel(api.labels.HTTP_RESPONSE_SIZE_LABEL_KEY, numBytes); | ||
requestLifecycleSpan | ||
.addLabel(api.labels.HTTP_RESPONSE_CODE_LABEL_KEY, res.statusCode); | ||
requestLifecycleSpan.endSpan(); | ||
}); | ||
if (callback) { | ||
return callback(res); | ||
} | ||
}); | ||
api.wrapEmitter(req); | ||
req.on('error', function (e) { | ||
if (e) { | ||
requestLifecycleSpan.addLabel(api.labels.ERROR_DETAILS_NAME, e.name); | ||
requestLifecycleSpan | ||
.addLabel(api.labels.ERROR_DETAILS_MESSAGE, e.message); | ||
} | ||
else { | ||
// What's the new logger target? | ||
// console.error('HTTP request error was null or undefined', e); | ||
} | ||
requestLifecycleSpan.endSpan(); | ||
}); | ||
return req; | ||
}; | ||
} | ||
} | ||
function unpatchHttps(https) { | ||
shimmer.unwrap(https, 'request'); | ||
shimmer.unwrap(https, 'get'); | ||
} | ||
module.exports = [ | ||
@@ -148,2 +160,8 @@ { | ||
unpatch: unpatchHttp | ||
}, | ||
{ | ||
file: 'https', | ||
versions: '=8.9.0 || >=9.0.0', | ||
patch: patchHttps, | ||
unpatch: unpatchHttps | ||
} | ||
@@ -150,0 +168,0 @@ ]; |
@@ -19,6 +19,6 @@ /** | ||
const shimmer = require('shimmer'); | ||
var urlParse = require('url').parse; | ||
const urlParse = require('url').parse; | ||
function startSpanForRequest(api, req, res, next) { | ||
var originalEnd = res.end; | ||
var options = { | ||
const originalEnd = res.end; | ||
const options = { | ||
name: urlParse(req.url).pathname, | ||
@@ -29,5 +29,5 @@ url: req.url, | ||
}; | ||
api.runInRootSpan(options, function (root) { | ||
return api.runInRootSpan(options, function (root) { | ||
// Set response trace context. | ||
var responseTraceContext = api.getResponseTraceContext(options.traceContext, !!root); | ||
const responseTraceContext = api.getResponseTraceContext(options.traceContext, !!root); | ||
if (responseTraceContext) { | ||
@@ -37,3 +37,3 @@ res.setHeader(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext); | ||
if (!root) { | ||
return; | ||
return next; | ||
} | ||
@@ -67,3 +67,11 @@ api.wrapEmitter(req); | ||
}); | ||
api.wrap(next); | ||
// In Koa 1, next is a Generator object. | ||
// We wrap Generator#next here. | ||
if (!next.apply && next.next) { | ||
next.next = api.wrap(next.next); | ||
return next; | ||
} | ||
else { | ||
return api.wrap(next); | ||
} | ||
}); | ||
@@ -76,3 +84,3 @@ } | ||
const res = this.res; | ||
startSpanForRequest(api, req, res, next); | ||
next = startSpanForRequest(api, req, res, next); | ||
yield next; | ||
@@ -85,3 +93,3 @@ }; | ||
const res = ctx.res; | ||
startSpanForRequest(api, req, res, next); | ||
next = startSpanForRequest(api, req, res, next); | ||
return next(); | ||
@@ -88,0 +96,0 @@ }; |
@@ -56,5 +56,6 @@ "use strict"; | ||
const origPrepare = Error.prepareStackTrace; | ||
Error.prepareStackTrace = function (error, structured) { | ||
return structured; | ||
}; | ||
Error.prepareStackTrace = | ||
(error, structured) => { | ||
return structured; | ||
}; | ||
const e = {}; | ||
@@ -64,3 +65,3 @@ Error.captureStackTrace(e, SpanData); | ||
if (e.stack) { | ||
e.stack.forEach(function (callSite, i) { | ||
e.stack.forEach((callSite, i) => { | ||
if (i < skipFrames) { | ||
@@ -67,0 +68,0 @@ return; |
@@ -31,2 +31,3 @@ "use strict"; | ||
*/ | ||
// tslint:disable-next-line:no-any | ||
function isString(obj) { | ||
@@ -33,0 +34,0 @@ return is.string(obj); |
@@ -38,2 +38,3 @@ "use strict"; | ||
let plugins = Object.create(null); | ||
// tslint:disable-next-line:no-any | ||
let intercepts = Object.create(null); | ||
@@ -96,7 +97,3 @@ let activated = false; | ||
agent.enable(logger, config); | ||
plugins[moduleName] = { | ||
file: pluginConfig[moduleName], | ||
patches: {}, | ||
agent: agent | ||
}; | ||
plugins[moduleName] = { file: pluginConfig[moduleName], patches: {}, agent }; | ||
} | ||
@@ -106,3 +103,5 @@ checkLoadedModules(); | ||
shimmer.wrap(Module, '_load', (originalModuleLoad) => { | ||
// tslint:disable:no-any | ||
function loadAndPatch(instrumentation, moduleRoot, version) { | ||
// tslint:enable:no-any | ||
let patchSet = instrumentation.patches[moduleRoot]; | ||
@@ -127,3 +126,3 @@ if (!patchSet) { | ||
patchSet[file] = { | ||
file: file, | ||
file, | ||
patch: patch.patch, | ||
@@ -134,3 +133,3 @@ unpatch: patch.unpatch | ||
if (isIntercept(patch)) { | ||
patchSet[file] = { file: file, intercept: patch.intercept }; | ||
patchSet[file] = { file, intercept: patch.intercept }; | ||
} | ||
@@ -176,3 +175,5 @@ // The conditionals exhaustively cover types for the patch | ||
// Future requires get patched as they get loaded. | ||
// tslint:disable:no-any | ||
return function Module_load(request, parent, isMain) { | ||
// tslint:enable:no-any | ||
const instrumentation = plugins[request]; | ||
@@ -179,0 +180,0 @@ if (instrumentation) { |
@@ -62,3 +62,3 @@ "use strict"; | ||
if (onUncaughtException === 'flushAndExit') { | ||
setTimeout(function () { | ||
setTimeout(() => { | ||
process.exit(1); | ||
@@ -130,3 +130,3 @@ }, 2000); | ||
getHostname(cb) { | ||
gcpMetadata.instance({ property: 'hostname', headers: headers }, (err, response, hostname) => { | ||
gcpMetadata.instance({ property: 'hostname', headers }, (err, response, hostname) => { | ||
if (err && err.code !== 'ENOTFOUND') { | ||
@@ -140,3 +140,3 @@ // We are running on GCP. | ||
getInstanceId(cb) { | ||
gcpMetadata.instance({ property: 'id', headers: headers }, (err, response, instanceId) => { | ||
gcpMetadata.instance({ property: 'id', headers }, (err, response, instanceId) => { | ||
if (err && err.code !== 'ENOTFOUND') { | ||
@@ -158,3 +158,3 @@ // We are running on GCP. | ||
} | ||
gcpMetadata.project({ property: 'project-id', headers: headers }, (err, response, projectId) => { | ||
gcpMetadata.project({ property: 'project-id', headers }, (err, response, projectId) => { | ||
if (response && response.statusCode !== 200) { | ||
@@ -265,3 +265,3 @@ if (response.statusCode === 503) { | ||
const uri = `https://cloudtrace.googleapis.com/v1/projects/${this.config.projectId}/traces`; | ||
const options = { method: 'PATCH', uri: uri, body: json, headers: headers }; | ||
const options = { method: 'PATCH', uri, body: json, headers }; | ||
this.logger.debug('TraceWriter: publishing to ' + uri); | ||
@@ -268,0 +268,0 @@ this.request(options, (err, body, response) => { |
@@ -1,3 +0,18 @@ | ||
# Node.js Agent for Google Cloud Trace ChangeLog | ||
# Node.js Agent for Google Cloud Trace Changelog | ||
## 2017-11-13, Version 2.3.2 (Beta), @kjin | ||
**bug fixes** | ||
* Fixed HTTPS tracing in Node 8.9.0 and 9.0.0+ (#589) | ||
* Fixed trace context not being propagated for Koa (#593) | ||
### Commits | ||
* [[`b9e6a3bc24`](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/commit/b9e6a3bc24)] - **fix**: propagate context in koa tracing (#594) (Kelvin Jin) [#594](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/pull/594) | ||
* [[`4170f8967a`](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/commit/4170f8967a)] - **src**: patch https in Node 8.9 and 9.0 (#591) (Kelvin Jin) [#591](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/pull/591) | ||
* [[`58925af30e`](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/commit/58925af30e)] - **chore**: update dependencies to enable greenkeeper (#584) (greenkeeper[bot]) [#584](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/pull/584) | ||
* [[`84a5f7d94c`](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/commit/84a5f7d94c)] - **style**: upgrade to gts@0.5 (#592) (Kelvin Jin) [#592](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/pull/592) | ||
* [[`523ab22d74`](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/commit/523ab22d74)] - **chore**: upgrade gcp-metadata to 0.4 (#590) (Kelvin Jin) [#590](https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/pull/590) | ||
## 2017-10-31, Version 2.3.1 (Beta), @kjin | ||
@@ -4,0 +19,0 @@ |
{ | ||
"name": "@google-cloud/trace-agent", | ||
"version": "2.3.1", | ||
"version": "2.3.2", | ||
"description": "Node.js Support for StackDriver Trace", | ||
@@ -57,3 +57,3 @@ "main": "build/index.js", | ||
"@types/once": "^1.4.0", | ||
"@types/pify": "0.0.28", | ||
"@types/pify": "^3.0.0", | ||
"@types/proxyquire": "^1.3.28", | ||
@@ -65,3 +65,3 @@ "@types/request": "^2.0.3", | ||
"changelog-maker": "^2.2.2", | ||
"coveralls": "^2.11.8", | ||
"coveralls": "^3.0.0", | ||
"express": "^4.15.2", | ||
@@ -71,6 +71,6 @@ "glob": "^7.0.3", | ||
"got": "^7.1.0", | ||
"gts": "latest", | ||
"gts": "^0.5.0", | ||
"istanbul": "^0.4.2", | ||
"jshint": "^2.9.1", | ||
"mocha": "^3.0.0", | ||
"mocha": "^4.0.1", | ||
"ncp": "^2.0.0", | ||
@@ -82,3 +82,3 @@ "nock": "^9.0.0", | ||
"request": "^2.81.0", | ||
"source-map-support": "^0.4.16", | ||
"source-map-support": "^0.5.0", | ||
"standard-version": "^4.2.0", | ||
@@ -94,3 +94,3 @@ "timekeeper": "^2.0.0", | ||
"extend": "^3.0.0", | ||
"gcp-metadata": "^0.2.0", | ||
"gcp-metadata": "^0.4.1", | ||
"is": "^3.2.0", | ||
@@ -97,0 +97,0 @@ "lodash.findindex": "^4.4.0", |
# Stackdriver Trace for Node.js | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/GoogleCloudPlatform/cloud-trace-nodejs.svg)](https://greenkeeper.io/) | ||
[![NPM Version][npm-image]][npm-url] | ||
@@ -4,0 +6,0 @@ [![Build Status][travis-image]][travis-url] |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
878269
43
3777
257
1
+ Addedgcp-metadata@0.4.1(transitive)
- Removedgcp-metadata@0.2.0(transitive)
- Removedretry-request@2.0.5(transitive)
Updatedgcp-metadata@^0.4.1