Socket
Socket
Sign inDemoInstall

@google-cloud/trace-agent

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@google-cloud/trace-agent - npm Package Compare versions

Comparing version 3.6.1 to 4.0.0

4

build/src/cls.d.ts

@@ -30,3 +30,3 @@ /**

export interface PhantomRootContext {
readonly type: SpanType.UNCORRELATED | SpanType.UNTRACED;
readonly type: SpanType.UNCORRELATED | SpanType.UNSAMPLED | SpanType.DISABLED;
}

@@ -88,3 +88,3 @@ /**

static UNCORRELATED: RootContext;
static UNTRACED: RootContext;
static DISABLED: RootContext;
/**

@@ -91,0 +91,0 @@ * Stack traces are captured when a root span is started. Because the stack

@@ -87,3 +87,3 @@ "use strict";

this.logger.info(`TraceCLS#constructor: Created [${config.mechanism}] CLS instance.`);
this.currentCLS = new null_1.NullCLS(TraceCLS.UNTRACED);
this.currentCLS = new null_1.NullCLS(TraceCLS.DISABLED);
this.currentCLS.enable();

@@ -95,5 +95,3 @@ }

enable() {
// if this.CLSClass = NullCLS, the user specifically asked not to use
// any context propagation mechanism. So nothing should change.
if (!this.enabled && this.CLSClass !== null_1.NullCLS) {
if (!this.enabled) {
this.logger.info('TraceCLS#enable: Enabling CLS.');

@@ -110,3 +108,3 @@ this.currentCLS.disable();

this.currentCLS.disable();
this.currentCLS = new null_1.NullCLS(TraceCLS.UNTRACED);
this.currentCLS = new null_1.NullCLS(TraceCLS.DISABLED);
this.currentCLS.enable();

@@ -130,5 +128,5 @@ }

TraceCLS.UNCORRELATED = span_data_1.UNCORRELATED_ROOT_SPAN;
TraceCLS.UNTRACED = span_data_1.UNTRACED_ROOT_SPAN;
TraceCLS.DISABLED = span_data_1.DISABLED_ROOT_SPAN;
exports.TraceCLS = TraceCLS;
exports.cls = new util_1.Singleton(TraceCLS);
//# sourceMappingURL=cls.js.map

@@ -20,3 +20,9 @@ "use strict";

// A list of well-known EventEmitter methods that add event listeners.
const EVENT_EMITTER_METHODS = ['addListener', 'on', 'once', 'prependListener', 'prependOnceListener'];
const EVENT_EMITTER_METHODS = [
'addListener',
'on',
'once',
'prependListener',
'prependOnceListener',
];
// A symbol used to check if a method has been wrapped for context.

@@ -91,3 +97,3 @@ const WRAPPED = Symbol('@google-cloud/trace-agent:AsyncHooksCLS:WRAPPED');

delete this.contexts[id];
}
},
});

@@ -155,3 +161,3 @@ }

writable: false,
value: fn.length
value: fn.length,
});

@@ -162,5 +168,5 @@ return contextWrapper;

const that = this;
EVENT_EMITTER_METHODS.forEach((method) => {
EVENT_EMITTER_METHODS.forEach(method => {
if (ee[method]) {
shimmer.wrap(ee, method, (oldMethod) => {
shimmer.wrap(ee, method, oldMethod => {
return function (event, cb) {

@@ -167,0 +173,0 @@ return oldMethod.call(this, event, that.bindWithCurrentContext(cb));

@@ -18,2 +18,50 @@ /**

export declare type ContextHeaderBehavior = 'default' | 'ignore' | 'require';
export interface RequestDetails {
/**
* The request timestamp.
*/
timestamp: number;
/**
* The request URL.
*/
url: string;
/**
* The request method.
*/
method: string;
/**
* The parsed trace context, if it exists.
*/
traceContext: {
traceId: string;
spanId: string;
options: number;
} | null;
/**
* The original options object used to create the root span that corresponds
* to this request.
*/
options: {};
}
export interface TracePolicy {
shouldTrace: (requestDetails: RequestDetails) => boolean;
}
export interface GetHeaderFunction {
getHeader: (key: string) => string[] | string | undefined;
}
export interface SetHeaderFunction {
setHeader: (key: string, value: string) => void;
}
export interface OpenCensusPropagation {
extract: (getHeader: GetHeaderFunction) => {
traceId: string;
spanId: string;
options?: number;
} | null;
inject: (setHeader: SetHeaderFunction, traceContext: {
traceId: string;
spanId: string;
options?: number;
}) => void;
}
/**

@@ -128,21 +176,30 @@ * Available configuration options. All fields are optional. See the

/**
* Specifies how to use incoming trace context headers. The following options
* are available:
* 'default' -- Trace context will be propagated for incoming requests that
* contain the context header. A new trace will be created for requests
* without trace context headers. All traces are still subject to local
* sampling and url filter policies.
* 'require' -- Same as default, but traces won't be created for requests
* without trace context headers. This should not be set for end user-facing
* services, as this header is usually set by other traced services rather
* than by users.
* 'ignore' -- Trace context headers will always be ignored, so a new trace
* with a unique ID will be created for every request. This means that a
* sampling decision specified on an incoming request will be ignored.
* Specifies whether to trace based on the 'traced' bit specified on incoming
* trace context headers. The following options are available:
* 'default' -- Don't trace incoming requests that have a trace context
* header with its 'traced' bit set to 0.
* 'require' -- Don't trace incoming requests that have a trace context
* header with its 'traced' bit set to 0, or incoming requests without a
* trace context header.
* 'ignore' -- The 'traced' bit will be ignored. In other words, the context
* header isn't used to determine whether a request will be traced at all.
* This might be useful for aggregating traces generated by different cloud
* platform projects.
* All traces are still subject to local tracing policy.
*/
contextHeaderBehavior?: ContextHeaderBehavior;
/**
* For advanced usage only.
* If specified, overrides the built-in trace policy object.
* Note that if any of ignoreUrls, ignoreMethods, samplingRate, or
* contextHeaderBehavior is specified, an error will be thrown when start()
* is called.
*/
tracePolicy?: TracePolicy;
/**
* If specified, the Trace Agent will use this context header propagation
* implementation instead of @opencensus/propagation-stackdriver, the default
* trace context header format.
*/
propagation?: OpenCensusPropagation;
/**
* Buffer the captured traces for `flushDelaySeconds` seconds before

@@ -181,9 +238,2 @@ * publishing to the Stackdriver Trace API, unless the buffer fills up first.

/**
* Setting this to true or false is the same as setting contextHeaderBehavior
* to 'ignore' or 'default' respectively. If both are explicitly set,
* contextHeaderBehavior will be prioritized over this value.
* Deprecated: This option will be removed in a future release.
*/
ignoreContextHeader?: boolean;
/**
* The ID of the Google Cloud Platform project with which traces should

@@ -238,18 +288,18 @@ * be associated. The value of GCLOUD_PROJECT takes precedence over this

plugins: {
'bluebird': string;
'connect': string;
'express': string;
bluebird: string;
connect: string;
express: string;
'generic-pool': string;
'grpc': string;
'hapi': string;
'http': string;
'http2': string;
'koa': string;
grpc: string;
hapi: string;
http: string;
http2: string;
koa: string;
'mongodb-core': string;
'mongoose': string;
'mysql': string;
'mysql2': string;
'pg': string;
'redis': string;
'restify': string;
mongoose: string;
mysql: string;
mysql2: string;
pg: string;
redis: string;
restify: string;
};

@@ -256,0 +306,0 @@ stackTraceLimit: number;

@@ -37,18 +37,18 @@ "use strict";

// enable all by default
'bluebird': path.join(pluginDirectory, 'plugin-bluebird.js'),
'connect': path.join(pluginDirectory, 'plugin-connect.js'),
'express': path.join(pluginDirectory, 'plugin-express.js'),
bluebird: path.join(pluginDirectory, 'plugin-bluebird.js'),
connect: path.join(pluginDirectory, 'plugin-connect.js'),
express: path.join(pluginDirectory, 'plugin-express.js'),
'generic-pool': path.join(pluginDirectory, 'plugin-generic-pool.js'),
'grpc': path.join(pluginDirectory, 'plugin-grpc.js'),
'hapi': path.join(pluginDirectory, 'plugin-hapi.js'),
'http': path.join(pluginDirectory, 'plugin-http.js'),
'http2': path.join(pluginDirectory, 'plugin-http2.js'),
'koa': path.join(pluginDirectory, 'plugin-koa.js'),
grpc: path.join(pluginDirectory, 'plugin-grpc.js'),
hapi: path.join(pluginDirectory, 'plugin-hapi.js'),
http: path.join(pluginDirectory, 'plugin-http.js'),
http2: path.join(pluginDirectory, 'plugin-http2.js'),
koa: path.join(pluginDirectory, 'plugin-koa.js'),
'mongodb-core': path.join(pluginDirectory, 'plugin-mongodb-core.js'),
'mongoose': path.join(pluginDirectory, 'plugin-mongoose.js'),
'mysql': path.join(pluginDirectory, 'plugin-mysql.js'),
'mysql2': path.join(pluginDirectory, 'plugin-mysql2.js'),
'pg': path.join(pluginDirectory, 'plugin-pg.js'),
'redis': path.join(pluginDirectory, 'plugin-redis.js'),
'restify': path.join(pluginDirectory, 'plugin-restify.js')
mongoose: path.join(pluginDirectory, 'plugin-mongoose.js'),
mysql: path.join(pluginDirectory, 'plugin-mysql.js'),
mysql2: path.join(pluginDirectory, 'plugin-mysql2.js'),
pg: path.join(pluginDirectory, 'plugin-pg.js'),
redis: path.join(pluginDirectory, 'plugin-redis.js'),
restify: path.join(pluginDirectory, 'plugin-restify.js'),
},

@@ -63,4 +63,4 @@ stackTraceLimit: 10,

onUncaughtException: 'ignore',
serviceContext: {}
serviceContext: {},
};
//# sourceMappingURL=config.js.map

@@ -48,13 +48,12 @@ /**

/**
* This span object was created in circumstances where a trace span could not
* be created for one of the following reasons:
* (1) The Trace Agent is disabled, either explicitly or because a project ID
* couldn't be determined.
* (2) The configured tracing policy disallows tracing for this request
* (due to sampling restrictions, ignored URLs, etc.)
* (3) The current incoming request contains trace context headers that
* explicitly disable local tracing for the request.
* This span object was created by a disabled Trace Agent, either explicitly
* or because a project ID couldn't be determined.
*/
DISABLED = "DISABLED",
/**
* This span object represents an unsampled request, and will not be
* published.
* Getting a span object of this type should not be considered an error.
*/
UNTRACED = "UNTRACED",
UNSAMPLED = "UNSAMPLED",
/**

@@ -61,0 +60,0 @@ * This span object was created by StackdriverTracer#runInRootSpan, and

@@ -40,3 +40,3 @@ "use strict";

/** Maximum size of a label value in bytes. */
TRACE_SERVICE_LABEL_VALUE_LIMIT: 16 * 1024 - 1
TRACE_SERVICE_LABEL_VALUE_LIMIT: 16 * 1024 - 1,
};

@@ -55,13 +55,12 @@ /**

/**
* This span object was created in circumstances where a trace span could not
* be created for one of the following reasons:
* (1) The Trace Agent is disabled, either explicitly or because a project ID
* couldn't be determined.
* (2) The configured tracing policy disallows tracing for this request
* (due to sampling restrictions, ignored URLs, etc.)
* (3) The current incoming request contains trace context headers that
* explicitly disable local tracing for the request.
* This span object was created by a disabled Trace Agent, either explicitly
* or because a project ID couldn't be determined.
*/
SpanType["DISABLED"] = "DISABLED";
/**
* This span object represents an unsampled request, and will not be
* published.
* Getting a span object of this type should not be considered an error.
*/
SpanType["UNTRACED"] = "UNTRACED";
SpanType["UNSAMPLED"] = "UNSAMPLED";
/**

@@ -68,0 +67,0 @@ * This span object was created by StackdriverTracer#runInRootSpan, and

@@ -29,2 +29,3 @@ "use strict";

const constants_1 = require("./constants");
const cls_1 = require("./cls");
let traceAgent;

@@ -34,31 +35,11 @@ /**

* and overriding with env variables when they are provided.
* @param projectConfig The user-provided configuration object. It will not
* @param userConfig The user-provided configuration object. It will not
* be modified.
* @return A normalized configuration object.
*/
function initConfig(projectConfig) {
// `|| undefined` prevents environmental variables that are empty strings
// from overriding values provided in the config object passed to start().
const envConfig = {
logLevel: Number(process.env.GCLOUD_TRACE_LOGLEVEL) || undefined,
projectId: process.env.GCLOUD_PROJECT || undefined,
serviceContext: {
service: process.env.GAE_SERVICE || process.env.GAE_MODULE_NAME || undefined,
version: process.env.GAE_VERSION || process.env.GAE_MODULE_VERSION ||
undefined,
minorVersion: process.env.GAE_MINOR_VERSION || undefined
}
};
function initConfig(userConfig) {
let envSetConfig = {};
if (!!process.env.GCLOUD_TRACE_CONFIG) {
envSetConfig =
require(path.resolve(process.env.GCLOUD_TRACE_CONFIG));
envSetConfig = require(path.resolve(process.env.GCLOUD_TRACE_CONFIG));
}
// Internally, ignoreContextHeader is no longer being used, so convert the
// user's value into a value for contextHeaderBehavior. But let this value
// be overridden by the user's explicitly set value for contextHeaderBehavior.
const contextHeaderBehaviorUnderride = {
contextHeaderBehavior: projectConfig.ignoreContextHeader ? 'ignore' :
'default'
};
// Configuration order of precedence:

@@ -69,25 +50,89 @@ // 1. Environment Variables

// 4. Default Config (as specified in './config')
const config = extend(true, { [util_1.FORCE_NEW]: projectConfig[util_1.FORCE_NEW] }, config_1.defaultConfig, envSetConfig, contextHeaderBehaviorUnderride, projectConfig, envConfig, { plugins: {} });
// The empty plugins object guarantees that plugins is a plain object,
// even if it's explicitly specified in the config to be a non-object.
// Enforce the upper limit for the label value size.
if (config.maximumLabelValueSize >
constants_1.Constants.TRACE_SERVICE_LABEL_VALUE_LIMIT) {
config.maximumLabelValueSize = constants_1.Constants.TRACE_SERVICE_LABEL_VALUE_LIMIT;
const mergedConfig = extend(true, {}, config_1.defaultConfig, envSetConfig, userConfig);
const forceNew = userConfig[util_1.FORCE_NEW];
// Throw for improper configurations.
const userSetKeys = new Set([
...Object.keys(envSetConfig),
...Object.keys(userConfig),
]);
if (userSetKeys.has('tracePolicy')) {
// If the user specified tracePolicy, they should not have also set these
// other fields.
const forbiddenKeys = [
'ignoreUrls',
'ignoreMethods',
'samplingRate',
'contextHeaderBehavior',
]
.filter(key => userSetKeys.has(key))
.map(key => `config.${key}`);
if (forbiddenKeys.length > 0) {
throw new Error(`config.tracePolicy and any of [${forbiddenKeys.join(', ')}] can't be specified at the same time.`);
}
}
// Make rootSpanNameOverride a function if not already.
if (typeof config.rootSpanNameOverride === 'string') {
const spanName = config.rootSpanNameOverride;
config.rootSpanNameOverride = () => spanName;
}
else if (typeof config.rootSpanNameOverride !== 'function') {
config.rootSpanNameOverride = (name) => name;
}
// If the CLS mechanism is set to auto-determined, decide now what it should
// be.
const ahAvailable = semver.satisfies(process.version, '>=8');
if (config.clsMechanism === 'auto') {
config.clsMechanism = ahAvailable ? 'async-hooks' : 'async-listener';
}
return config;
const getInternalClsMechanism = (clsMechanism) => {
// If the CLS mechanism is set to auto-determined, decide now
// what it should be.
const ahAvailable = semver.satisfies(process.version, '>=8');
if (clsMechanism === 'auto') {
return ahAvailable
? cls_1.TraceCLSMechanism.ASYNC_HOOKS
: cls_1.TraceCLSMechanism.ASYNC_LISTENER;
}
return clsMechanism;
};
const getInternalRootSpanNameOverride = (rootSpanNameOverride) => {
// Make rootSpanNameOverride a function if not already.
switch (typeof rootSpanNameOverride) {
case 'string':
return () => rootSpanNameOverride;
case 'function':
return rootSpanNameOverride;
default:
return (name) => name;
}
};
return {
[util_1.FORCE_NEW]: forceNew,
enabled: mergedConfig.enabled,
logLevel: util_1.lastOf(mergedConfig.logLevel, Number(process.env.GCLOUD_TRACE_LOGLEVEL)),
clsConfig: {
[util_1.FORCE_NEW]: forceNew,
mechanism: getInternalClsMechanism(mergedConfig.clsMechanism),
},
writerConfig: {
[util_1.FORCE_NEW]: forceNew,
projectId: util_1.lastOf(mergedConfig.projectId, process.env.GCLOUD_PROJECT),
onUncaughtException: mergedConfig.onUncaughtException,
bufferSize: mergedConfig.bufferSize,
flushDelaySeconds: mergedConfig.flushDelaySeconds,
stackTraceLimit: mergedConfig.stackTraceLimit,
maximumLabelValueSize: Math.min(mergedConfig.maximumLabelValueSize, constants_1.Constants.TRACE_SERVICE_LABEL_VALUE_LIMIT),
serviceContext: {
service: util_1.lastOf(mergedConfig.serviceContext.service, process.env.GAE_MODULE_NAME, process.env.GAE_SERVICE),
version: util_1.lastOf(mergedConfig.serviceContext.version, process.env.GAE_MODULE_VERSION, process.env.GAE_VERSION),
minorVersion: util_1.lastOf(mergedConfig.serviceContext.minorVersion, process.env.GAE_MINOR_VERSION),
},
},
pluginLoaderConfig: {
[util_1.FORCE_NEW]: forceNew,
plugins: Object.assign({}, mergedConfig.plugins),
tracerConfig: {
enhancedDatabaseReporting: mergedConfig.enhancedDatabaseReporting,
rootSpanNameOverride: getInternalRootSpanNameOverride(mergedConfig.rootSpanNameOverride),
spansPerTraceHardLimit: mergedConfig.spansPerTraceHardLimit,
spansPerTraceSoftLimit: mergedConfig.spansPerTraceSoftLimit,
},
},
tracePolicyConfig: {
samplingRate: mergedConfig.samplingRate,
ignoreMethods: mergedConfig.ignoreMethods,
ignoreUrls: mergedConfig.ignoreUrls,
contextHeaderBehavior: mergedConfig.contextHeaderBehavior,
},
overrides: {
tracePolicy: mergedConfig.tracePolicy,
propagation: mergedConfig.propagation,
},
};
}

@@ -112,3 +157,3 @@ /**

if (normalizedConfig.enabled &&
normalizedConfig.clsMechanism === 'async-listener') {
normalizedConfig.clsConfig.mechanism === cls_1.TraceCLSMechanism.ASYNC_LISTENER) {
// This is the earliest we can load continuation-local-storage.

@@ -118,3 +163,3 @@ require('continuation-local-storage');

if (!traceAgent) {
traceAgent = new (require('./trace-api').StackdriverTracer)();
traceAgent = new (require('./trace-api')).StackdriverTracer();
}

@@ -124,4 +169,3 @@ try {

try {
tracing =
require('./tracing').tracing.create(normalizedConfig, traceAgent);
tracing = require('./tracing').tracing.create(normalizedConfig, traceAgent);
}

@@ -150,3 +194,3 @@ catch (e) {

if (!traceAgent) {
traceAgent = new (require('./trace-api').StackdriverTracer)();
traceAgent = new (require('./trace-api')).StackdriverTracer();
}

@@ -153,0 +197,0 @@ return traceAgent;

@@ -23,3 +23,9 @@ "use strict";

*/
exports.LEVELS = ['silent', 'error', 'warn', 'info', 'debug'];
exports.LEVELS = [
'silent',
'error',
'warn',
'info',
'debug',
];
function logLevelToName(level) {

@@ -40,5 +46,5 @@ if (typeof level === 'string') {

constructor(opts) {
const levelName = opts && opts.level !== undefined ?
opts.level :
logLevelToName(config_1.defaultConfig.logLevel);
const levelName = opts && opts.level !== undefined
? opts.level
: logLevelToName(config_1.defaultConfig.logLevel);
if (levelName === false || levelName === 'silent') {

@@ -51,3 +57,3 @@ this.logger = null;

prefix: `${opts && opts.tag ? opts.tag : 'unknown'} ${levelName.toUpperCase()}`,
level: levelName
level: levelName,
});

@@ -54,0 +60,0 @@ }

@@ -32,7 +32,6 @@ /**

/**
* Gets the current trace context serialized as a string, or an empty string
* if it can't be generated.
* @return The stringified trace context.
* Gets the current trace context, or null if it can't be retrieved.
* @return The trace context.
*/
getTraceContext(): string;
getTraceContext(): TraceContext | null;
/**

@@ -92,6 +91,5 @@ * Adds a key-value pair as a label to the trace span. The value will be

/**
* The serialized form of an object that contains information about an
* existing trace context, if it exists.
* An existing trace context, if it exists.
*/
traceContext?: string | null;
traceContext?: TraceContext | null;
}

@@ -168,3 +166,3 @@ export interface Tracer {

/**
* Generates a stringified trace context that should be set as the trace
* Generates a trace context object that should be set as the trace
* context header in a response to an incoming web request. This value is

@@ -176,9 +174,9 @@ * based on the trace context header value in the corresponding incoming

* the incoming web request, or null if the incoming request didn't have one.
* @param isTraced Whether the incoming was traced. This is determined
* @param isTraced Whether the incoming request was traced. This is determined
* by the local tracing policy.
* @returns If the response should contain the trace context within its
* header, the string to be set as this header's value. Otherwise, an empty
* string.
* header, the context object to be serialized as this header's value.
* Otherwise, null.
*/
getResponseTraceContext(incomingTraceContext: string | null, isTraced: boolean): string;
getResponseTraceContext(incomingTraceContext: TraceContext | null, isTraced: boolean): TraceContext | null;
/**

@@ -208,8 +206,16 @@ * Binds the trace context to the given function.

readonly traceContextUtils: {
encodeAsString: (ctx: TraceContext) => string;
decodeFromString: (str: string) => TraceContext | null;
encodeAsByteArray: (ctx: TraceContext) => Buffer;
decodeFromByteArray: (buf: Buffer) => TraceContext | null;
};
/**
* A collection of functions for dealing with trace context in HTTP headers.
*/
readonly propagation: Propagation;
}
export declare type GetHeaderFunction = (key: string) => string[] | string | null | undefined;
export declare type SetHeaderFunction = (key: string, value: string) => void;
export interface Propagation {
extract: (getHeader: GetHeaderFunction) => TraceContext | null;
inject: (setHeader: SetHeaderFunction, traceContext: TraceContext | null) => void;
}
export interface Monkeypatch<T> {

@@ -216,0 +222,0 @@ file?: string;

@@ -18,3 +18,4 @@ "use strict";

const shimmer = require("shimmer");
const plugin = [{
const plugin = [
{
// Bluebird is a class.

@@ -31,3 +32,5 @@ // tslint:disable-next-line:variable-name

return thenFn.apply(this, [
wrapIfFunction(args[0]), wrapIfFunction(args[1]), ...args.slice(2)
wrapIfFunction(args[0]),
wrapIfFunction(args[1]),
...args.slice(2),
]);

@@ -37,5 +40,6 @@ };

// tslint:enable:no-any
}
}];
},
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-bluebird.js.map

@@ -19,23 +19,16 @@ "use strict";

const SUPPORTED_VERSIONS = '3.x';
function getFirstHeader(req, key) {
let headerValue = req.headers[key] || null;
if (headerValue && typeof headerValue !== 'string') {
headerValue = headerValue[0];
}
return headerValue;
}
function createMiddleware(api) {
return function middleware(req, res, next) {
const options = {
name: req.originalUrl ? (url_1.parse(req.originalUrl).pathname || '') : '',
name: req.originalUrl ? url_1.parse(req.originalUrl).pathname || '' : '',
url: req.originalUrl,
method: req.method,
traceContext: getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME),
skipFrames: 1
traceContext: api.propagation.extract(key => req.headers[key]),
skipFrames: 1,
};
api.runInRootSpan(options, (root) => {
api.runInRootSpan(options, root => {
// Set response trace context.
const responseTraceContext = api.getResponseTraceContext(options.traceContext || null, api.isRealSpan(root));
const responseTraceContext = api.getResponseTraceContext(options.traceContext, api.isRealSpan(root));
if (responseTraceContext) {
res.setHeader(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext);
api.propagation.inject((k, v) => res.setHeader(k, v), responseTraceContext);
}

@@ -67,3 +60,4 @@ if (!api.isRealSpan(root)) {

}
const plugin = [{
const plugin = [
{
file: '',

@@ -77,5 +71,6 @@ versions: SUPPORTED_VERSIONS,

};
}
}];
},
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-connect.js.map

@@ -19,4 +19,3 @@ "use strict";

const shimmer = require("shimmer");
const methods = httpMethods
.concat('use', 'route', 'param', 'all');
const methods = httpMethods.concat('use', 'route', 'param', 'all');
const SUPPORTED_VERSIONS = '4.x';

@@ -28,12 +27,12 @@ function patchModuleRoot(express, api) {

name: req.path,
traceContext: req.get(api.constants.TRACE_CONTEXT_HEADER_NAME),
traceContext: api.propagation.extract(key => req.get(key)),
url: req.originalUrl,
method: req.method,
skipFrames: 1
skipFrames: 1,
};
api.runInRootSpan(options, (rootSpan) => {
api.runInRootSpan(options, rootSpan => {
// Set response trace context.
const responseTraceContext = api.getResponseTraceContext(options.traceContext || null, api.isRealSpan(rootSpan));
const responseTraceContext = api.getResponseTraceContext(options.traceContext, api.isRealSpan(rootSpan));
if (responseTraceContext) {
res.set(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext);
api.propagation.inject((k, v) => res.setHeader(k, v), responseTraceContext);
}

@@ -74,3 +73,3 @@ if (!api.isRealSpan(rootSpan)) {

}
methods.forEach((method) => {
methods.forEach(method => {
shimmer.wrap(express.application, method, applicationActionWrap);

@@ -80,12 +79,14 @@ });

function unpatchModuleRoot(express) {
methods.forEach((method) => {
methods.forEach(method => {
shimmer.unwrap(express.application, method);
});
}
const plugin = [{
const plugin = [
{
versions: SUPPORTED_VERSIONS,
patch: patchModuleRoot,
unpatch: unpatchModuleRoot
}];
unpatch: unpatchModuleRoot,
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-express.js.map

@@ -43,4 +43,3 @@ "use strict";

*/
function setTraceContextFromString(metadata, stringifiedTraceContext) {
const traceContext = api.traceContextUtils.decodeFromString(stringifiedTraceContext);
function setTraceContextFromString(metadata, traceContext) {
if (traceContext) {

@@ -96,3 +95,3 @@ const metadataValue = api.traceContextUtils.encodeAsByteArray(traceContext);

// gRPC.
const cbIndex = args.findIndex((arg) => {
const cbIndex = args.findIndex(arg => {
return typeof arg === 'function';

@@ -108,5 +107,7 @@ });

// but this is an extremely rare case.
let metaIndex = args.findIndex((arg) => {
return !!arg && typeof arg === 'object' && arg._internal_repr &&
typeof arg.getMap === 'function';
let metaIndex = args.findIndex(arg => {
return (!!arg &&
typeof arg === 'object' &&
arg._internal_repr &&
typeof arg.getMap === 'function');
});

@@ -190,4 +191,3 @@ if (metaIndex === -1) {

.map(methodName => methods[methodName].originalName)
.filter(originalName => !!originalName &&
Client.prototype.hasOwnProperty(originalName))
.filter(originalName => !!originalName && Client.prototype.hasOwnProperty(originalName)),
];

@@ -209,7 +209,7 @@ shimmer.massWrap([Client.prototype], methodsToWrap, makeClientMethod);

* Returns a trace context on a Metadata object if it exists and is
* well-formed, or null otherwise. The result will be encoded as a string.
* well-formed, or null otherwise.
* @param metadata The Metadata object from which trace context should be
* retrieved.
*/
function getStringifiedTraceContext(metadata) {
function getTraceContext(metadata) {
const metadataValue = metadata.getMap()[api.constants.TRACE_CONTEXT_GRPC_METADATA_NAME];

@@ -220,8 +220,3 @@ // Entry doesn't exist.

}
const traceContext = api.traceContextUtils.decodeFromByteArray(metadataValue);
// Value is malformed.
if (!traceContext) {
return null;
}
return api.traceContextUtils.encodeAsString(traceContext);
return api.traceContextUtils.decodeFromByteArray(metadataValue);
}

@@ -263,6 +258,6 @@ /**

url: requestName,
traceContext: getStringifiedTraceContext(call.metadata),
skipFrames: SKIP_FRAMES
traceContext: getTraceContext(call.metadata),
skipFrames: SKIP_FRAMES,
};
return api.runInRootSpan(rootSpanOptions, (rootSpan) => {
return api.runInRootSpan(rootSpanOptions, rootSpan => {
if (!api.isRealSpan(rootSpan)) {

@@ -313,6 +308,6 @@ return serverMethod.call(this, call, callback);

url: requestName,
traceContext: getStringifiedTraceContext(stream.metadata),
skipFrames: SKIP_FRAMES
traceContext: getTraceContext(stream.metadata),
skipFrames: SKIP_FRAMES,
};
return api.runInRootSpan(rootSpanOptions, (rootSpan) => {
return api.runInRootSpan(rootSpanOptions, rootSpan => {
if (!api.isRealSpan(rootSpan)) {

@@ -346,3 +341,3 @@ return serverMethod.call(this, stream);

});
stream.on('error', (err) => {
stream.on('error', err => {
if (api.enhancedDatabaseReportingEnabled()) {

@@ -372,6 +367,6 @@ rootSpan.addLabel('error', err);

url: requestName,
traceContext: getStringifiedTraceContext(stream.metadata),
skipFrames: SKIP_FRAMES
traceContext: getTraceContext(stream.metadata),
skipFrames: SKIP_FRAMES,
};
return api.runInRootSpan(rootSpanOptions, (rootSpan) => {
return api.runInRootSpan(rootSpanOptions, rootSpan => {
if (!api.isRealSpan(rootSpan)) {

@@ -427,6 +422,6 @@ return serverMethod.call(this, stream, callback);

url: requestName,
traceContext: getStringifiedTraceContext(stream.metadata),
skipFrames: SKIP_FRAMES
traceContext: getTraceContext(stream.metadata),
skipFrames: SKIP_FRAMES,
};
return api.runInRootSpan(rootSpanOptions, (rootSpan) => {
return api.runInRootSpan(rootSpanOptions, rootSpan => {
if (!api.isRealSpan(rootSpan)) {

@@ -522,3 +517,3 @@ return serverMethod.call(this, stream);

patch: patchClient,
unpatch: unpatchClient
unpatch: unpatchClient,
},

@@ -529,3 +524,3 @@ {

patch: patchMetadata,
unpatch: unpatchMetadata
unpatch: unpatchMetadata,
},

@@ -536,3 +531,3 @@ {

patch: patchServer,
unpatch: unpatchServer
unpatch: unpatchServer,
},

@@ -543,3 +538,3 @@ {

patch: patchClient,
unpatch: unpatchClient
unpatch: unpatchClient,
},

@@ -550,3 +545,3 @@ {

patch: patchMetadata,
unpatch: unpatchMetadata
unpatch: unpatchMetadata,
},

@@ -557,6 +552,6 @@ {

patch: patchServer,
unpatch: unpatchServer
}
unpatch: unpatchServer,
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-grpc.js.map

@@ -21,9 +21,2 @@ "use strict";

const ORIGINAL = Symbol();
function getFirstHeader(req, key) {
let headerValue = req.headers[key] || null;
if (headerValue && typeof headerValue !== 'string') {
headerValue = headerValue[0];
}
return headerValue;
}
function instrument(api, request, continueCb) {

@@ -34,13 +27,13 @@ const req = request.raw.req;

const options = {
name: req.url ? (url_1.parse(req.url).pathname || '') : '',
name: req.url ? url_1.parse(req.url).pathname || '' : '',
url: req.url,
method: req.method,
traceContext: getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME),
skipFrames: 2
traceContext: api.propagation.extract(key => req.headers[key]),
skipFrames: 2,
};
return api.runInRootSpan(options, (root) => {
return api.runInRootSpan(options, root => {
// Set response trace context.
const responseTraceContext = api.getResponseTraceContext(options.traceContext || null, api.isRealSpan(root));
const responseTraceContext = api.getResponseTraceContext(options.traceContext, api.isRealSpan(root));
if (responseTraceContext) {
res.setHeader(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext);
api.propagation.inject((k, v) => res.setHeader(k, v), responseTraceContext);
}

@@ -84,3 +77,3 @@ if (!api.isRealSpan(root)) {

patch: (hapi, api) => {
shimmer.wrap(hapi.Server.prototype, 'connection', (connection) => {
shimmer.wrap(hapi.Server.prototype, 'connection', connection => {
return function connectionTrace() {

@@ -95,5 +88,5 @@ const server = connection.apply(this, arguments);

},
unpatch: (hapi) => {
unpatch: hapi => {
shimmer.unwrap(hapi.Server.prototype, 'connection');
}
},
},

@@ -114,19 +107,18 @@ /**

const origExecute = Request.prototype._execute;
Request.prototype._execute =
Object.assign(function _executeWrap() {
return instrument(api, this, () => {
return origExecute.apply(this, arguments);
});
}, { [ORIGINAL]: origExecute });
Request.prototype._execute = Object.assign(function _executeWrap() {
return instrument(api, this, () => {
return origExecute.apply(this, arguments);
});
}, { [ORIGINAL]: origExecute });
},
// Request is a class name.
// tslint:disable-next-line:variable-name
unpatch: (Request) => {
unpatch: Request => {
if (Request.prototype._execute[ORIGINAL]) {
Request.prototype._execute = Request.prototype._execute[ORIGINAL];
}
}
}
},
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-hapi.js.map

@@ -22,3 +22,3 @@ "use strict";

const ERR_HTTP_HEADERS_SENT = 'ERR_HTTP_HEADERS_SENT';
const ERR_HTTP_HEADERS_SENT_MSG = 'Can\'t set headers after they are sent.';
const ERR_HTTP_HEADERS_SENT_MSG = "Can't set headers after they are sent.";
// tslint:disable:no-any

@@ -28,5 +28,5 @@ const isString = is.string;

// This function works around that.
const isURL = semver.satisfies(process.version, '>=7') ?
((value) => value instanceof url.URL) :
((value) => false);
const isURL = semver.satisfies(process.version, '>=7')
? (value) => value instanceof url.URL
: (value) => false;
// tslint:enable:no-any

@@ -65,3 +65,3 @@ function getSpanName(options) {

const host = options.hostname || options.host || 'localhost';
const portString = options.port ? (':' + options.port) : '';
const portString = options.port ? ':' + options.port : '';
// In theory we should use url.format here. However, that is

@@ -75,4 +75,5 @@ // broken. See: https://github.com/joyent/node/issues/9117 and

function isTraceAgentRequest(options, api) {
return options && options.headers &&
!!options.headers[api.constants.TRACE_AGENT_REQUEST_HEADER];
return (options &&
options.headers &&
!!options.headers[api.constants.TRACE_AGENT_REQUEST_HEADER]);
}

@@ -124,7 +125,9 @@ function makeRequestTrace(protocol, request, api) {

options.headers = Object.assign({}, options.headers);
const headers = options.headers;
// Inject the trace context header.
options.headers[api.constants.TRACE_CONTEXT_HEADER_NAME] =
span.getTraceContext();
api.propagation.inject((key, value) => {
headers[key] = value;
}, span.getTraceContext());
}
const req = request(options, (res) => {
const req = request(options, res => {
api.wrapEmitter(res);

@@ -141,3 +144,3 @@ let numBytes = 0;

// official documentation.
shimmer.wrap(res, 'on', (on) => {
shimmer.wrap(res, 'on', on => {
return function on_trace(eventName) {

@@ -171,16 +174,18 @@ if (eventName === 'data' && !listenerAttached) {

if (!traceHeaderPreinjected) {
try {
req.setHeader(api.constants.TRACE_CONTEXT_HEADER_NAME, span.getTraceContext());
}
catch (e) {
if (e.code === ERR_HTTP_HEADERS_SENT ||
e.message === ERR_HTTP_HEADERS_SENT_MSG) {
// Swallow the error.
// This would happen in the pathological case where the Expect header
// exists but is not detected by hasExpectHeader.
api.propagation.inject((key, value) => {
try {
req.setHeader(key, value);
}
else {
throw e;
catch (e) {
if (e.code === ERR_HTTP_HEADERS_SENT ||
e.message === ERR_HTTP_HEADERS_SENT_MSG) {
// Swallow the error.
// This would happen in the pathological case where the Expect
// header exists but is not detected by hasExpectHeader.
}
else {
throw e;
}
}
}
}, span.getTraceContext());
}

@@ -191,3 +196,3 @@ return req;

function patchHttp(http, api) {
shimmer.wrap(http, 'request', (request) => {
shimmer.wrap(http, 'request', request => {
return makeRequestTrace('http:', request, api);

@@ -220,3 +225,3 @@ });

function patchHttps(https, api) {
shimmer.wrap(https, 'request', (request) => {
shimmer.wrap(https, 'request', request => {
return makeRequestTrace('https:', request, api);

@@ -253,3 +258,3 @@ });

// the public 'http' module.
patch: () => require('http')
patch: () => require('http'),
},

@@ -261,5 +266,5 @@ {

unpatch: unpatchHttps,
}
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-http.js.map

@@ -63,3 +63,5 @@ "use strict";

}
const requestLifecycleSpan = api.createChildSpan({ name: getSpanName(authority) });
const requestLifecycleSpan = api.createChildSpan({
name: getSpanName(authority),
});
if (!api.isRealSpan(requestLifecycleSpan)) {

@@ -71,4 +73,3 @@ return request.apply(this, arguments);

requestLifecycleSpan.addLabel(api.labels.HTTP_URL_LABEL_KEY, extractUrl(authority, newHeaders));
newHeaders[api.constants.TRACE_CONTEXT_HEADER_NAME] =
requestLifecycleSpan.getTraceContext();
api.propagation.inject((k, v) => (newHeaders[k] = v), requestLifecycleSpan.getTraceContext());
const stream = request.call(this, newHeaders, ...Array.prototype.slice.call(arguments, 1));

@@ -79,3 +80,3 @@ api.wrapEmitter(stream);

stream
.on('response', (headers) => {
.on('response', headers => {
requestLifecycleSpan.addLabel(api.labels.HTTP_RESPONSE_CODE_LABEL_KEY, headers[':status']);

@@ -102,3 +103,3 @@ })

// any of the official documentation.
shimmer.wrap(stream, 'on', (on) => {
shimmer.wrap(stream, 'on', on => {
return function (eventName, cb) {

@@ -119,6 +120,6 @@ if (eventName === 'data' && !listenerAttached) {

api.wrapEmitter(session);
shimmer.wrap(session, 'request', (request) => makeRequestTrace(request, authority, api));
shimmer.wrap(session, 'request', request => makeRequestTrace(request, authority, api));
}
function patchHttp2(h2, api) {
shimmer.wrap(h2, 'connect', (connect) => function (authority) {
shimmer.wrap(h2, 'connect', connect => function (authority) {
const session = connect.apply(this, arguments);

@@ -125,0 +126,0 @@ patchHttp2Session(session, authority, api);

@@ -19,9 +19,2 @@ "use strict";

const url_1 = require("url");
function getFirstHeader(req, key) {
let headerValue = req.headers[key] || null;
if (headerValue && typeof headerValue !== 'string') {
headerValue = headerValue[0];
}
return headerValue;
}
function startSpanForRequest(api, ctx, getNext) {

@@ -32,13 +25,13 @@ const req = ctx.req;

const options = {
name: req.url ? (url_1.parse(req.url).pathname || '') : '',
name: req.url ? url_1.parse(req.url).pathname || '' : '',
url: req.url,
method: req.method,
traceContext: getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME),
skipFrames: 2
traceContext: api.propagation.extract(key => req.headers[key]),
skipFrames: 2,
};
return api.runInRootSpan(options, root => {
// Set response trace context.
const responseTraceContext = api.getResponseTraceContext(options.traceContext || null, api.isRealSpan(root));
const responseTraceContext = api.getResponseTraceContext(options.traceContext, api.isRealSpan(root));
if (responseTraceContext) {
res.setHeader(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext);
api.propagation.inject((k, v) => res.setHeader(k, v), responseTraceContext);
}

@@ -96,3 +89,3 @@ if (!api.isRealSpan(root)) {

function patchUse(koa, api, createMiddlewareFunction) {
shimmer.wrap(koa.prototype, 'use', (use) => {
shimmer.wrap(koa.prototype, 'use', use => {
return function useTrace() {

@@ -114,5 +107,5 @@ if (!this._google_trace_patched) {

},
unpatch: (koa) => {
unpatch: koa => {
shimmer.unwrap(koa.prototype, 'use');
}
},
},

@@ -125,8 +118,8 @@ {

},
unpatch: (koa) => {
unpatch: koa => {
shimmer.unwrap(koa.prototype, 'use');
}
}
},
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-koa.js.map

@@ -54,8 +54,8 @@ "use strict";

this.tracer = tracer;
this.maybePopulateLabelsFromInputs =
tracer.enhancedDatabaseReportingEnabled() ? populateLabelsFromInputs :
noOp;
this.maybePopulateLabelsFromOutputs =
tracer.enhancedDatabaseReportingEnabled() ? populateLabelsFromOutputs :
noOp;
this.maybePopulateLabelsFromInputs = tracer.enhancedDatabaseReportingEnabled()
? populateLabelsFromInputs
: noOp;
this.maybePopulateLabelsFromOutputs = tracer.enhancedDatabaseReportingEnabled()
? populateLabelsFromOutputs
: noOp;
}

@@ -66,3 +66,3 @@ patchSubmittable(pgQuery, span) {

if (pgQuery.handleError) {
shimmer.wrap(pgQuery, 'handleError', (origCallback) => {
shimmer.wrap(pgQuery, 'handleError', origCallback => {
// Elements of args are not individually accessed.

@@ -85,3 +85,3 @@ // tslint:disable:no-any

if (pgQuery.handleReadyForQuery) {
shimmer.wrap(pgQuery, 'handleReadyForQuery', (origCallback) => {
shimmer.wrap(pgQuery, 'handleReadyForQuery', origCallback => {
// Elements of args are not individually accessed.

@@ -112,11 +112,11 @@ // tslint:disable:no-any

patchPromise(promise, span) {
return promise = promise.then((res) => {
return (promise = promise.then(res => {
this.maybePopulateLabelsFromOutputs(span, null, res);
span.endSpan();
return res;
}, (err) => {
}, err => {
this.maybePopulateLabelsFromOutputs(span, err);
span.endSpan();
throw err;
});
}));
}

@@ -132,3 +132,3 @@ }

const pgPatch = new PostgresPatchUtility(api);
shimmer.wrap(Client.prototype, 'query', (query) => {
shimmer.wrap(Client.prototype, 'query', query => {
// Every call to Client#query will have a Submittable object associated

@@ -174,3 +174,3 @@ // with it. We need to patch two handlers (handleReadyForQuery and

shimmer.unwrap(Client.prototype, 'query');
}
},
},

@@ -184,3 +184,3 @@ {

const pgPatch = new PostgresPatchUtility(api);
shimmer.wrap(Client.prototype, 'query', (query) => {
shimmer.wrap(Client.prototype, 'query', query => {
return function query_trace() {

@@ -240,6 +240,6 @@ const span = api.createChildSpan({ name: 'pg-query' });

shimmer.unwrap(Client.prototype, 'query');
}
}
},
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-pg.js.map

@@ -38,4 +38,4 @@ "use strict";

method: req.method,
traceContext: req.header(api.constants.TRACE_CONTEXT_HEADER_NAME),
skipFrames: 1
traceContext: api.propagation.extract(key => req.header(key)),
skipFrames: 1,
};

@@ -46,3 +46,3 @@ api.runInRootSpan(options, rootSpan => {

if (responseTraceContext) {
res.header(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext);
api.propagation.inject((k, v) => res.setHeader(k, v), responseTraceContext);
}

@@ -73,8 +73,10 @@ if (!api.isRealSpan(rootSpan)) {

}
const plugin = [{
const plugin = [
{
versions: SUPPORTED_VERSIONS,
patch: patchRestify,
unpatch: unpatchRestify
}];
unpatch: unpatchRestify,
},
];
module.exports = plugin;
//# sourceMappingURL=plugin-restify.js.map

@@ -17,4 +17,5 @@ /**

import { SpanType } from './constants';
import { RootSpan, Span, SpanOptions } from './plugin-types';
import { RootSpan, Span, SpanOptions, TraceContext } from './plugin-types';
import { Trace, TraceSpan } from './trace';
import * as traceUtil from './util';
/**

@@ -37,3 +38,7 @@ * Represents a real trace span.

constructor(trace: Trace, spanName: string, parentSpanId: string, skipFrames: number);
getTraceContext(): string;
getTraceContext(): {
traceId: string;
spanId: string;
options: number;
};
addLabel(key: string, value: any): void;

@@ -62,2 +67,22 @@ endSpan(timestamp?: Date): void;

/**
* Helper (and base) class for UntracedRootSpanData. Represents an untraced
* child span.
*/
declare class UntracedSpanData implements Span {
readonly type = SpanType.UNSAMPLED;
protected readonly traceContext: TraceContext;
constructor(traceId: string);
getTraceContext(): traceUtil.TraceContext | null;
addLabel(): void;
endSpan(): void;
}
/**
* Represents an "untraced" root span (aka not published).
* For distributed trace context propagation purposes.
*/
export declare class UntracedRootSpanData extends UntracedSpanData implements RootSpan {
private child;
createChildSpan(): Span;
}
/**
* A virtual trace span that indicates that a real child span couldn't be

@@ -71,7 +96,6 @@ * created because the correct root span couldn't be determined.

* A virtual trace span that indicates that a real child span couldn't be
* created because the corresponding root span was disallowed by user
* configuration.
* created because the Trace Agent was disabled.
*/
export declare const UNTRACED_CHILD_SPAN: Span & {
readonly type: SpanType.UNTRACED;
export declare const DISABLED_CHILD_SPAN: Span & {
readonly type: SpanType.DISABLED;
};

@@ -93,8 +117,9 @@ /**

*/
export declare const UNTRACED_ROOT_SPAN: Readonly<{
export declare const DISABLED_ROOT_SPAN: Readonly<{
createChildSpan(): Span & {
readonly type: SpanType.UNTRACED;
readonly type: SpanType.DISABLED;
};
} & Span & {
readonly type: SpanType.UNTRACED;
readonly type: SpanType.DISABLED;
}>;
export {};

@@ -32,5 +32,5 @@ "use strict";

const randomBytes = crypto.randomBytes;
const spanRandomBuffer = randomFillSync ?
() => randomFillSync(spanIdBuffer) :
() => randomBytes(SPAN_ID_RANDOM_BYTES);
const spanRandomBuffer = randomFillSync
? () => randomFillSync(spanIdBuffer)
: () => randomBytes(SPAN_ID_RANDOM_BYTES);
function randomSpanId() {

@@ -57,3 +57,3 @@ // tslint:disable-next-line:ban Needed to parse hexadecimal.

name: traceUtil.truncate(spanName, constants_1.Constants.TRACE_SERVICE_SPAN_NAME_LIMIT),
startTime: (new Date()).toISOString(),
startTime: new Date().toISOString(),
endTime: '',

@@ -63,3 +63,3 @@ spanId: randomSpanId(),

parentSpanId,
labels: {}
labels: {},
};

@@ -71,12 +71,11 @@ this.trace.spans.push(this.span);

// stack trace label has its own size constraints.
this.span.labels[trace_labels_1.TraceLabels.STACK_TRACE_DETAILS_KEY] =
traceUtil.truncate(JSON.stringify({ stack_frame: stackFrames }), constants_1.Constants.TRACE_SERVICE_LABEL_VALUE_LIMIT);
this.span.labels[trace_labels_1.TraceLabels.STACK_TRACE_DETAILS_KEY] = traceUtil.truncate(JSON.stringify({ stack_frame: stackFrames }), constants_1.Constants.TRACE_SERVICE_LABEL_VALUE_LIMIT);
}
}
getTraceContext() {
return traceUtil.generateTraceContext({
return {
traceId: this.trace.traceId.toString(),
spanId: this.span.spanId.toString(),
options: 1 // always traced
});
options: 1,
};
}

@@ -114,3 +113,3 @@ // tslint:disable-next-line:no-any

const skipFrames = options.skipFrames ? options.skipFrames + 1 : 1;
const child = new ChildSpanData(this.trace, /* Trace object */ options.name, /* Span name */ this.span.spanId, /* Parent's span ID */ skipFrames); /* # of frames to skip in stack trace */
const child = new ChildSpanData(this.trace /* Trace object */, options.name /* Span name */, this.span.spanId /* Parent's span ID */, skipFrames); /* # of frames to skip in stack trace */
this.children.push(child);

@@ -159,3 +158,3 @@ return child;

traceId: this.trace.traceId,
spans: [this.span]
spans: [this.span],
});

@@ -170,10 +169,48 @@ }

getTraceContext() {
return '';
return null;
},
// tslint:disable-next-line:no-any
addLabel(key, value) { },
endSpan() { }
endSpan() { },
}, { type: spanType }));
}
/**
* Helper (and base) class for UntracedRootSpanData. Represents an untraced
* child span.
*/
class UntracedSpanData {
constructor(traceId) {
this.type = constants_1.SpanType.UNSAMPLED;
this.traceContext = {
traceId,
spanId: randomSpanId(),
options: 0,
};
}
getTraceContext() {
return this.traceContext;
}
// No-op.
addLabel() { }
// No-op.
endSpan() { }
}
/**
* Represents an "untraced" root span (aka not published).
* For distributed trace context propagation purposes.
*/
class UntracedRootSpanData extends UntracedSpanData {
constructor() {
super(...arguments);
this.child = null;
}
createChildSpan() {
if (!this.child) {
this.child = new UntracedSpanData(this.traceContext.traceId);
}
return this.child;
}
}
exports.UntracedRootSpanData = UntracedRootSpanData;
/**
* A virtual trace span that indicates that a real child span couldn't be

@@ -185,6 +222,5 @@ * created because the correct root span couldn't be determined.

* A virtual trace span that indicates that a real child span couldn't be
* created because the corresponding root span was disallowed by user
* configuration.
* created because the Trace Agent was disabled.
*/
exports.UNTRACED_CHILD_SPAN = createPhantomSpanData(constants_1.SpanType.UNTRACED);
exports.DISABLED_CHILD_SPAN = createPhantomSpanData(constants_1.SpanType.DISABLED);
/**

@@ -197,3 +233,3 @@ * A virtual trace span that indicates that a real root span couldn't be

return exports.UNCORRELATED_CHILD_SPAN;
}
},
}, exports.UNCORRELATED_CHILD_SPAN));

@@ -204,7 +240,7 @@ /**

*/
exports.UNTRACED_ROOT_SPAN = Object.freeze(Object.assign({
exports.DISABLED_ROOT_SPAN = Object.freeze(Object.assign({
createChildSpan() {
return exports.UNTRACED_CHILD_SPAN;
}
}, exports.UNTRACED_CHILD_SPAN));
return exports.DISABLED_CHILD_SPAN;
},
}, exports.DISABLED_CHILD_SPAN));
//# sourceMappingURL=span-data.js.map

@@ -18,34 +18,13 @@ /**

import { EventEmitter } from 'events';
import { OpenCensusPropagation, TracePolicy } from './config';
import { SpanType } from './constants';
import { Logger } from './logger';
import { Func, RootSpan, RootSpanOptions, Span, SpanOptions, Tracer } from './plugin-types';
import { TracePolicyConfig } from './tracing-policy';
import { Func, Propagation, RootSpan, RootSpanOptions, Span, SpanOptions, Tracer } from './plugin-types';
import * as util from './util';
/**
* An enumeration of the different possible types of behavior when dealing with
* incoming trace context. Requests are still subject to local tracing policy.
*/
export declare enum TraceContextHeaderBehavior {
/**
* Respect the trace context header if it exists; otherwise, trace the
* request as a new trace.
*/
DEFAULT = "default",
/**
* Respect the trace context header if it exists; otherwise, treat the
* request as unsampled and don't trace it.
*/
REQUIRE = "require",
/**
* Trace every request as a new trace, even if trace context exists.
*/
IGNORE = "ignore"
}
/**
* An interface describing configuration fields read by the StackdriverTracer
* object. This includes fields read by the trace policy.
*/
export interface StackdriverTracerConfig extends TracePolicyConfig {
export interface StackdriverTracerConfig {
enhancedDatabaseReporting: boolean;
contextHeaderBehavior: TraceContextHeaderBehavior;
rootSpanNameOverride: (path: string) => string;

@@ -56,2 +35,10 @@ spansPerTraceSoftLimit: number;

/**
* A collection of externally-instantiated objects used by StackdriverTracer.
*/
export interface StackdriverTracerComponents {
logger: Logger;
tracePolicy: TracePolicy;
propagation: OpenCensusPropagation;
}
/**
* StackdriverTracer exposes a number of methods to create trace spans and

@@ -88,7 +75,6 @@ * propagate trace context across asynchronous boundaries.

readonly traceContextUtils: {
encodeAsString: typeof util.generateTraceContext;
decodeFromString: typeof util.parseContextFromHeader;
encodeAsByteArray: typeof util.serializeTraceContext;
decodeFromByteArray: typeof util.deserializeTraceContext;
};
readonly propagation: Propagation;
private enabled;

@@ -100,2 +86,3 @@ private pluginName;

private policy;
private headerPropagation;
/**

@@ -112,6 +99,7 @@ * Constructs a new StackdriverTracer instance.

* be configured.
* @param logger A logger object.
* @param components An collection of externally-instantiated objects used
* by this instance.
* @private
*/
enable(config: StackdriverTracerConfig, logger: Logger): void;
enable(config: StackdriverTracerConfig, components: StackdriverTracerComponents): void;
/**

@@ -139,5 +127,9 @@ * Disable this instance. This function is only for internal use and

isRealSpan(span: Span): boolean;
getResponseTraceContext(incomingTraceContext: string | null, isTraced: boolean): string;
getResponseTraceContext(incomingTraceContext: util.TraceContext | null, isTraced: boolean): {
traceId: string;
spanId: string;
options: number;
} | null;
wrap<T>(fn: Func<T>): Func<T>;
wrapEmitter(emitter: EventEmitter): void;
}

@@ -18,3 +18,2 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const is = require("is");
const uuid = require("uuid");

@@ -29,30 +28,2 @@ const cls_1 = require("./cls");

/**
* An enumeration of the different possible types of behavior when dealing with
* incoming trace context. Requests are still subject to local tracing policy.
*/
var TraceContextHeaderBehavior;
(function (TraceContextHeaderBehavior) {
/**
* Respect the trace context header if it exists; otherwise, trace the
* request as a new trace.
*/
TraceContextHeaderBehavior["DEFAULT"] = "default";
/**
* Respect the trace context header if it exists; otherwise, treat the
* request as unsampled and don't trace it.
*/
TraceContextHeaderBehavior["REQUIRE"] = "require";
/**
* Trace every request as a new trace, even if trace context exists.
*/
TraceContextHeaderBehavior["IGNORE"] = "ignore";
})(TraceContextHeaderBehavior = exports.TraceContextHeaderBehavior || (exports.TraceContextHeaderBehavior = {}));
/**
* Type guard that returns whether an object is a string or not.
*/
// tslint:disable-next-line:no-any
function isString(obj) {
return is.string(obj);
}
/**
* StackdriverTracer exposes a number of methods to create trace spans and

@@ -71,7 +42,42 @@ * propagate trace context across asynchronous boundaries.

this.traceContextUtils = {
encodeAsString: util.generateTraceContext,
decodeFromString: util.parseContextFromHeader,
encodeAsByteArray: util.serializeTraceContext,
decodeFromByteArray: util.deserializeTraceContext
decodeFromByteArray: util.deserializeTraceContext,
};
this.propagation = {
extract: getHeader => {
// If enabled, this.propagationMechanism is non-null.
if (!this.enabled) {
return null;
}
// OpenCensus propagation libraries expect span IDs to be size-16 hex
// strings. In the future it might be worthwhile to change how span IDs
// are stored in this library to avoid excessive base 10<->16 conversions.
const result = this.headerPropagation.extract({
getHeader: (...args) => {
const result = getHeader(...args);
if (result === null) {
return; // undefined
}
return result;
},
});
if (result) {
result.spanId = util.hexToDec(result.spanId);
}
return result;
},
inject: (setHeader, value) => {
// If enabled, this.propagationMechanism is non-null.
// Also, don't inject a falsey value.
if (!this.enabled || !value) {
return;
}
// Convert back to base-10 span IDs. See the wrapper for `extract`
// for more details.
value = Object.assign({}, value, {
spanId: `0000000000000000${util.decToHex(value.spanId).slice(2)}`.slice(-16),
});
this.headerPropagation.inject({ setHeader }, value);
},
};
this.enabled = false;

@@ -81,2 +87,4 @@ this.logger = null;

this.policy = null;
// The underlying propagation mechanism used by this.propagation.
this.headerPropagation = null;
this.pluginName = name;

@@ -92,9 +100,11 @@ this.pluginNameToLog = this.pluginName ? this.pluginName : 'no-plugin-name';

* be configured.
* @param logger A logger object.
* @param components An collection of externally-instantiated objects used
* by this instance.
* @private
*/
enable(config, logger) {
this.logger = logger;
enable(config, components) {
this.config = config;
this.policy = new tracing_policy_1.TracePolicy(config);
this.logger = components.logger;
this.policy = components.tracePolicy;
this.headerPropagation = components.propagation;
this.enabled = true;

@@ -112,3 +122,3 @@ }

// short-circuit out of trace generation logic.
this.policy = tracing_policy_1.TracePolicy.never();
this.policy = tracing_policy_1.neverTrace();
this.enabled = false;

@@ -136,3 +146,3 @@ }

if (!this.isActive()) {
return fn(span_data_1.UNTRACED_ROOT_SPAN);
return fn(span_data_1.DISABLED_ROOT_SPAN);
}

@@ -146,39 +156,52 @@ options = options || { name: '' };

}
// Attempt to read incoming trace context.
const incomingTraceContext = { options: 1 };
let parsedContext = null;
if (isString(options.traceContext) &&
this.config.contextHeaderBehavior !==
TraceContextHeaderBehavior.IGNORE) {
parsedContext = util.parseContextFromHeader(options.traceContext);
}
if (parsedContext) {
if (parsedContext.options === undefined) {
// If there are no incoming option flags, default to 0x1.
parsedContext.options = 1;
// Ensure that the trace context, if it exists, has an options field.
const canonicalizeTraceContext = (traceContext) => {
if (!traceContext) {
return null;
}
Object.assign(incomingTraceContext, parsedContext);
}
else if (this.config.contextHeaderBehavior ===
TraceContextHeaderBehavior.REQUIRE) {
incomingTraceContext.options = 0;
}
if (traceContext.options !== undefined) {
return traceContext;
}
return {
traceId: traceContext.traceId,
spanId: traceContext.spanId,
options: 1,
};
};
const traceContext = canonicalizeTraceContext(options.traceContext);
// Consult the trace policy.
const locallyAllowed = this.policy.shouldTrace({
const shouldTrace = this.policy.shouldTrace({
timestamp: Date.now(),
url: options.url || '',
method: options.method || ''
method: options.method || '',
traceContext,
options,
});
const remotelyAllowed = !!(incomingTraceContext.options & constants_1.Constants.TRACE_OPTIONS_TRACE_ENABLED);
const traceId = traceContext
? traceContext.traceId
: uuid
.v4()
.split('-')
.join('');
let rootContext;
// Don't create a root span if the trace policy disallows it.
if (!locallyAllowed || !remotelyAllowed) {
rootContext = span_data_1.UNTRACED_ROOT_SPAN;
// Create an "untraced" root span (one that won't be published) if the
// trace policy disallows it.
if (!shouldTrace) {
rootContext = new span_data_1.UntracedRootSpanData(traceId);
}
else {
// Create a new root span, and invoke fn with it.
const traceId = incomingTraceContext.traceId || (uuid.v4().split('-').join(''));
const parentId = incomingTraceContext.spanId || '0';
const name = this.config.rootSpanNameOverride(options.name);
rootContext = new span_data_1.RootSpanData({ projectId: '', traceId, spans: [] }, /* Trace object */ name, /* Span name */ parentId, /* Parent's span ID */ options.skipFrames || 0);
rootContext = new span_data_1.RootSpanData(
// Trace object
{
projectId: '',
traceId,
spans: [],
},
// Span name
this.config.rootSpanNameOverride(options.name),
// Parent span ID
traceContext ? traceContext.spanId : '0',
// Number of stack frames to skip
options.skipFrames || 0);
}

@@ -191,3 +214,3 @@ return cls_1.cls.get().runWithContext(() => {

if (!this.isActive()) {
return span_data_1.UNTRACED_ROOT_SPAN;
return span_data_1.DISABLED_ROOT_SPAN;
}

@@ -199,4 +222,3 @@ return cls_1.cls.get().getContext();

const traceContext = this.getCurrentRootSpan().getTraceContext();
const parsedTraceContext = util.parseContextFromHeader(traceContext);
return parsedTraceContext ? parsedTraceContext.traceId : null;
return traceContext ? traceContext.traceId : null;
}

@@ -222,3 +244,3 @@ getProjectId() {

if (!this.isActive()) {
return span_data_1.UNTRACED_CHILD_SPAN;
return span_data_1.DISABLED_CHILD_SPAN;
}

@@ -243,8 +265,7 @@ options = options || { name: '' };

// is likely due to userspace task queues or Promise implementations.
this.logger.error(`TraceApi#createChildSpan: [${this.pluginNameToLog}] Creating phantom child span [${options.name}] because the trace with root span [${rootSpan.span.name}] has reached a limit of ${this.config
.spansPerTraceHardLimit} spans. This is likely a memory leak.`);
this.logger.error(`TraceApi#createChildSpan: [${this.pluginNameToLog}] Creating phantom child span [${options.name}] because the trace with root span [${rootSpan.span.name}] has reached a limit of ${this.config.spansPerTraceHardLimit} spans. This is likely a memory leak.`);
this.logger.error([
'TraceApi#createChildSpan: Please see',
'https://github.com/googleapis/cloud-trace-nodejs/wiki',
'for details and suggested actions.'
'for details and suggested actions.',
].join(' '));

@@ -261,8 +282,7 @@ return span_data_1.UNCORRELATED_CHILD_SPAN;

// uses the RootSpanData API directly.
this.logger.error(`TraceApi#createChildSpan: [${this.pluginNameToLog}] Adding child span [${options.name}] will cause the trace with root span [${rootSpan.span.name}] to contain more than ${this.config
.spansPerTraceSoftLimit} spans. This is likely a memory leak.`);
this.logger.error(`TraceApi#createChildSpan: [${this.pluginNameToLog}] Adding child span [${options.name}] will cause the trace with root span [${rootSpan.span.name}] to contain more than ${this.config.spansPerTraceSoftLimit} spans. This is likely a memory leak.`);
this.logger.error([
'TraceApi#createChildSpan: Please see',
'https://github.com/googleapis/cloud-trace-nodejs/wiki',
'for details and suggested actions.'
'for details and suggested actions.',
].join(' '));

@@ -273,3 +293,3 @@ }

name: options.name,
skipFrames: options.skipFrames ? options.skipFrames + 1 : 1
skipFrames: options.skipFrames ? options.skipFrames + 1 : 1,
});

@@ -279,7 +299,9 @@ this.logger.info(`TraceApi#createChildSpan: [${this.pluginNameToLog}] Created child span [${options.name}]`);

}
else if (rootSpan.type === constants_1.SpanType.UNTRACED) {
// Context wasn't lost, but there's no root span, indicating that this
// request should not be traced.
return span_data_1.UNTRACED_CHILD_SPAN;
else if (rootSpan.type === constants_1.SpanType.UNSAMPLED) {
// "Untraced" child spans don't incur a memory penalty.
return rootSpan.createChildSpan();
}
else if (rootSpan.type === constants_1.SpanType.DISABLED) {
return span_data_1.DISABLED_CHILD_SPAN;
}
else {

@@ -296,10 +318,9 @@ // Context was lost.

if (!this.isActive() || !incomingTraceContext) {
return '';
return null;
}
const traceContext = util.parseContextFromHeader(incomingTraceContext);
if (!traceContext) {
return '';
}
traceContext.options = (traceContext.options || 0) & (isTraced ? 1 : 0);
return util.generateTraceContext(traceContext);
return {
traceId: incomingTraceContext.traceId,
spanId: incomingTraceContext.spanId,
options: (incomingTraceContext.options || 0) & (isTraced ? 1 : 0),
};
}

@@ -306,0 +327,0 @@ wrap(fn) {

@@ -84,4 +84,4 @@ "use strict";

*/
AGENT_DATA: '/agent'
AGENT_DATA: '/agent',
};
//# sourceMappingURL=trace-labels.js.map

@@ -16,5 +16,4 @@ /**

*/
import { Logger } from './logger';
import { Plugin } from './plugin-types';
import { StackdriverTracerConfig } from './trace-api';
import { StackdriverTracerComponents, StackdriverTracerConfig } from './trace-api';
import { Singleton } from './util';

@@ -31,6 +30,7 @@ /**

*/
export interface PluginLoaderConfig extends StackdriverTracerConfig {
export interface PluginLoaderConfig {
plugins: {
[pluginName: string]: string;
};
tracerConfig: StackdriverTracerConfig;
}

@@ -72,6 +72,7 @@ export interface ModulePluginWrapperOptions {

export declare class ModulePluginWrapper implements PluginWrapper {
private readonly traceConfig;
private static readonly NOT_LOADED;
private readonly unpatchFns;
private readonly logger;
private readonly traceConfig;
private readonly components;
private readonly name;

@@ -85,5 +86,7 @@ private readonly path;

* @param traceConfig Configuration for a StackdriverTracer instance.
* @param tracePolicy The trace policy to apply to a StackdriverTracer
* instance.
* @param logger The logger to use.
*/
constructor(options: ModulePluginWrapperOptions, traceConfig: StackdriverTracerConfig, logger: Logger);
constructor(options: ModulePluginWrapperOptions, traceConfig: StackdriverTracerConfig, components: StackdriverTracerComponents);
isSupported(version: string): boolean;

@@ -104,3 +107,3 @@ unapplyAll(): void;

private readonly children;
constructor(config: CorePluginWrapperOptions, traceConfig: StackdriverTracerConfig, logger: Logger);
constructor(config: CorePluginWrapperOptions, traceConfig: StackdriverTracerConfig, components: StackdriverTracerComponents);
/**

@@ -135,4 +138,4 @@ * Returns whether the given version of the module is supported by this

export declare class PluginLoader {
static readonly CORE_MODULE = "[core]";
private readonly logger;
static readonly CORE_MODULE = "[core]";
private enableRequireHook;

@@ -147,3 +150,3 @@ private readonly pluginMap;

*/
constructor(config: PluginLoaderConfig, logger: Logger);
constructor(config: PluginLoaderConfig, components: StackdriverTracerComponents);
readonly state: PluginLoaderState;

@@ -177,2 +180,2 @@ /**

}
export declare const pluginLoader: Singleton<PluginLoader, PluginLoaderConfig, Logger>;
export declare const pluginLoader: Singleton<PluginLoader, PluginLoaderConfig, StackdriverTracerComponents>;

@@ -33,5 +33,8 @@ "use strict";

* @param traceConfig Configuration for a StackdriverTracer instance.
* @param tracePolicy The trace policy to apply to a StackdriverTracer
* instance.
* @param logger The logger to use.
*/
constructor(options, traceConfig, logger) {
constructor(options, traceConfig, components) {
this.traceConfig = traceConfig;
this.unpatchFns = [];

@@ -42,6 +45,6 @@ // The exported value of the plugin, or NOT_LOADED if it hasn't been

this.traceApiInstances = [];
this.logger = logger;
this.logger = components.logger;
this.components = components;
this.name = options.name;
this.path = options.path;
this.traceConfig = traceConfig;
}

@@ -108,4 +111,3 @@ isSupported(version) {

else if (patch.intercept) {
exportedValue =
patch.intercept(exportedValue, this.createTraceAgentInstance(file));
exportedValue = patch.intercept(exportedValue, this.createTraceAgentInstance(file));
}

@@ -124,3 +126,3 @@ return exportedValue;

const traceApi = new trace_api_1.StackdriverTracer(file);
traceApi.enable(this.traceConfig, this.logger);
traceApi.enable(this.traceConfig, this.components);
this.traceApiInstances.push(traceApi);

@@ -141,5 +143,5 @@ return traceApi;

class CorePluginWrapper {
constructor(config, traceConfig, logger) {
this.logger = logger;
this.children = config.children.map(config => new ModulePluginWrapper(config, traceConfig, logger));
constructor(config, traceConfig, components) {
this.logger = components.logger;
this.children = config.children.map(config => new ModulePluginWrapper(config, traceConfig, components));
// Eagerly load core plugins into memory.

@@ -192,4 +194,3 @@ // This prevents issues related to circular dependencies.

*/
constructor(config, logger) {
this.logger = logger;
constructor(config, components) {
// A map mapping module names to their respective plugins.

@@ -201,2 +202,3 @@ this.pluginMap = new Map();

this.internalState = PluginLoaderState.NO_HOOK;
this.logger = components.logger;
const nonCoreModules = [];

@@ -210,4 +212,3 @@ // Initialize ALL of the PluginWrapper objects here.

// Core module plugins share a common key.
const coreModule = key === PluginLoader.CORE_MODULE ||
builtinModules.indexOf(key) !== -1;
const coreModule = key === PluginLoader.CORE_MODULE || builtinModules.indexOf(key) !== -1;
if (value) {

@@ -220,3 +221,3 @@ // Convert the given string value to a PluginConfigEntry

else {
this.pluginMap.set(key, new ModulePluginWrapper({ name: key, path: value }, config, logger));
this.pluginMap.set(key, new ModulePluginWrapper({ name: key, path: value }, config.tracerConfig, components));
}

@@ -227,3 +228,3 @@ nonCoreModules.push(key);

if (coreWrapperConfig.children.length > 0) {
this.pluginMap.set(PluginLoader.CORE_MODULE, new CorePluginWrapper(coreWrapperConfig, config, logger));
this.pluginMap.set(PluginLoader.CORE_MODULE, new CorePluginWrapper(coreWrapperConfig, config.tracerConfig, components));
}

@@ -236,4 +237,6 @@ // Define the function that will attach a require hook upon activate.

// TODO(kjin): This should be encapsulated in a class.
this.enableRequireHook = (onRequire) => {
const builtins = this.pluginMap.has(PluginLoader.CORE_MODULE) ? builtinModules : [];
this.enableRequireHook = onRequire => {
const builtins = this.pluginMap.has(PluginLoader.CORE_MODULE)
? builtinModules
: [];
hook(builtins.concat(nonCoreModules), { internals: true }, onRequire);

@@ -287,4 +290,3 @@ };

if (plugin.isSupported(version)) {
exportedValue =
plugin.applyPlugin(exportedValue, file, version);
exportedValue = plugin.applyPlugin(exportedValue, file, version);
}

@@ -352,3 +354,3 @@ else {

name: parts.slice(0, indexOfFile).join('/'),
file: parts.slice(indexOfFile).join('/')
file: parts.slice(indexOfFile).join('/'),
};

@@ -387,3 +389,4 @@ }

}
else { // core module
else {
// core module
return process.version.slice(1); // starts with v

@@ -390,0 +393,0 @@ }

@@ -41,2 +41,4 @@ "use strict";

const SCOPES = ['https://www.googleapis.com/auth/trace.append'];
/* The API endpoint of the Stackdriver Trace service */
const TRACE_API_ENDPOINT = 'cloudtrace.googleapis.com';
class TraceBuffer {

@@ -94,4 +96,5 @@ constructor() {

projectIdRequired: false,
baseUrl: 'https://cloudtrace.googleapis.com/v1',
scopes: SCOPES
apiEndpoint: TRACE_API_ENDPOINT,
baseUrl: `https://${TRACE_API_ENDPOINT}/v1`,
scopes: SCOPES,
}, config);

@@ -145,3 +148,5 @@ this.config = config;

const [hostname, instanceId] = yield Promise.all([
this.getHostname(), this.getInstanceId(), getProjectIdAndScheduleFlush()
this.getHostname(),
this.getInstanceId(),
getProjectIdAndScheduleFlush(),
]);

@@ -228,3 +233,3 @@ const addDefaultLabel = (key, value) => {

projectId: trace.projectId,
spans: publishableSpans
spans: publishableSpans,
});

@@ -265,3 +270,3 @@ this.logger.info(`TraceWriter#writeTrace: number of buffered spans = ${this.buffer.getNumSpans()}`);

const afterProjectId = (projectId) => {
flushedTraces.forEach(trace => trace.projectId = projectId);
flushedTraces.forEach(trace => (trace.projectId = projectId));
this.logger.debug('TraceWriter#flushBuffer: Flushing traces', flushedTraces);

@@ -299,4 +304,3 @@ this.publish(JSON.stringify({ traces: flushedTraces }));

if (err) {
this.logger.error(`TraceWriter#publish: Received error ${statusCode ? `with status code ${statusCode}` :
''} while publishing traces to ${hostname}: ${err}`);
this.logger.error(`TraceWriter#publish: Received error ${statusCode ? `with status code ${statusCode}` : ''} while publishing traces to ${hostname}: ${err}`);
}

@@ -303,0 +307,0 @@ else {

@@ -0,1 +1,2 @@

import { RequestDetails, TracePolicy } from './config';
/**

@@ -17,2 +18,22 @@ * Copyright 2015 Google Inc. All Rights Reserved.

/**
* An enumeration of the different possible types of behavior when dealing with
* incoming trace context. Requests are still subject to local tracing policy.
*/
export declare enum TraceContextHeaderBehavior {
/**
* Respect the trace context header if it exists; otherwise, trace the
* request as a new trace.
*/
DEFAULT = "default",
/**
* Respect the trace context header if it exists; otherwise, treat the
* request as unsampled and don't trace it.
*/
REQUIRE = "require",
/**
* Trace every request as a new trace, even if trace context exists.
*/
IGNORE = "ignore"
}
/**
* Options for constructing a TracePolicy instance.

@@ -33,2 +54,6 @@ */

ignoreMethods: string[];
/**
* A field that controls filtering based on incoming trace context.
*/
contextHeaderBehavior: TraceContextHeaderBehavior;
}

@@ -38,6 +63,7 @@ /**

*/
export declare class TracePolicy {
export declare class BuiltinTracePolicy implements TracePolicy {
private readonly sampler;
private readonly urlFilter;
private readonly methodsFilter;
private readonly contextHeaderFilter;
/**

@@ -53,9 +79,5 @@ * Constructs a new TracePolicy instance.

*/
shouldTrace(options: {
timestamp: number;
url: string;
method: string;
}): boolean;
static always(): TracePolicy;
static never(): TracePolicy;
shouldTrace(options: RequestDetails): boolean;
}
export declare function alwaysTrace(): BuiltinTracePolicy;
export declare function neverTrace(): BuiltinTracePolicy;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("./constants");
/**

@@ -17,3 +19,23 @@ * Copyright 2015 Google Inc. All Rights Reserved.

*/
Object.defineProperty(exports, "__esModule", { value: true });
/**
* An enumeration of the different possible types of behavior when dealing with
* incoming trace context. Requests are still subject to local tracing policy.
*/
var TraceContextHeaderBehavior;
(function (TraceContextHeaderBehavior) {
/**
* Respect the trace context header if it exists; otherwise, trace the
* request as a new trace.
*/
TraceContextHeaderBehavior["DEFAULT"] = "default";
/**
* Respect the trace context header if it exists; otherwise, treat the
* request as unsampled and don't trace it.
*/
TraceContextHeaderBehavior["REQUIRE"] = "require";
/**
* Trace every request as a new trace, even if trace context exists.
*/
TraceContextHeaderBehavior["IGNORE"] = "ignore";
})(TraceContextHeaderBehavior = exports.TraceContextHeaderBehavior || (exports.TraceContextHeaderBehavior = {}));
class Sampler {

@@ -40,5 +62,5 @@ constructor(samplesPerSecond) {

shouldTrace(url) {
return !this.filterUrls.some((candidate) => {
return (typeof candidate === 'string' && candidate === url) ||
!!url.match(candidate);
return !this.filterUrls.some(candidate => {
return ((typeof candidate === 'string' && candidate === url) ||
!!url.match(candidate));
});

@@ -52,11 +74,33 @@ }

shouldTrace(method) {
return !this.filterMethods.some((candidate) => {
return (candidate.toLowerCase() === method.toLowerCase());
return !this.filterMethods.some(candidate => {
return candidate.toLowerCase() === method.toLowerCase();
});
}
}
class ContextHeaderFilter {
constructor(contextHeaderBehavior) {
this.contextHeaderBehavior = contextHeaderBehavior;
}
shouldTrace(header) {
switch (this.contextHeaderBehavior) {
case TraceContextHeaderBehavior.IGNORE: {
return true;
}
case TraceContextHeaderBehavior.REQUIRE: {
// There must be an incoming header, and its LSB must be 1.
return !!(header && header.options & constants_1.Constants.TRACE_OPTIONS_TRACE_ENABLED);
}
default: {
// TraceContextHeaderBehavior.DEFAULT
// If there is a header, its LSB must be 1. Otherwise, we assume that
// it would be 1.
return !!(!header || header.options & constants_1.Constants.TRACE_OPTIONS_TRACE_ENABLED);
}
}
}
}
/**
* A class that makes decisions about whether a trace should be created.
*/
class TracePolicy {
class BuiltinTracePolicy {
/**

@@ -88,2 +132,8 @@ * Constructs a new TracePolicy instance.

}
if (config.contextHeaderBehavior === TraceContextHeaderBehavior.IGNORE) {
this.contextHeaderFilter = { shouldTrace: () => true };
}
else {
this.contextHeaderFilter = new ContextHeaderFilter(config.contextHeaderBehavior);
}
}

@@ -96,14 +146,27 @@ /**

shouldTrace(options) {
return this.sampler.shouldTrace(options.timestamp) &&
this.urlFilter.shouldTrace(options.url) &&
this.methodsFilter.shouldTrace(options.method);
return (this.urlFilter.shouldTrace(options.url) &&
this.methodsFilter.shouldTrace(options.method) &&
this.contextHeaderFilter.shouldTrace(options.traceContext) &&
this.sampler.shouldTrace(options.timestamp));
}
static always() {
return new TracePolicy({ samplingRate: 0, ignoreUrls: [], ignoreMethods: [] });
}
static never() {
return new TracePolicy({ samplingRate: -1, ignoreUrls: [], ignoreMethods: [] });
}
}
exports.TracePolicy = TracePolicy;
exports.BuiltinTracePolicy = BuiltinTracePolicy;
function alwaysTrace() {
return new BuiltinTracePolicy({
samplingRate: 0,
ignoreUrls: [],
ignoreMethods: [],
contextHeaderBehavior: TraceContextHeaderBehavior.DEFAULT,
});
}
exports.alwaysTrace = alwaysTrace;
function neverTrace() {
return new BuiltinTracePolicy({
samplingRate: -1,
ignoreUrls: [],
ignoreMethods: [],
contextHeaderBehavior: TraceContextHeaderBehavior.DEFAULT,
});
}
exports.neverTrace = neverTrace;
//# sourceMappingURL=tracing-policy.js.map

@@ -16,15 +16,23 @@ /**

*/
import { CLSMechanism } from './config';
import { TraceCLSConfig } from './cls';
import { OpenCensusPropagation, TracePolicy } from './config';
import { StackdriverTracer } from './trace-api';
import { PluginLoaderConfig } from './trace-plugin-loader';
import { TraceWriterConfig } from './trace-writer';
import { Component, Singleton } from './util';
export interface TopLevelConfig {
import { TracePolicyConfig } from './tracing-policy';
import { Component, Forceable, Singleton } from './util';
export declare type TopLevelConfig = Forceable<{
enabled: boolean;
logLevel: number;
clsMechanism: CLSMechanism;
}
export declare type NormalizedConfig = ((TraceWriterConfig & PluginLoaderConfig & TopLevelConfig) | {
clsConfig: Forceable<TraceCLSConfig>;
writerConfig: Forceable<TraceWriterConfig>;
pluginLoaderConfig: Forceable<PluginLoaderConfig>;
tracePolicyConfig: TracePolicyConfig;
overrides: {
tracePolicy?: TracePolicy;
propagation?: OpenCensusPropagation;
};
}> | {
enabled: false;
});
};
/**

@@ -44,3 +52,3 @@ * A class that represents automatic tracing.

*/
constructor(config: NormalizedConfig, traceAgent: StackdriverTracer);
constructor(config: TopLevelConfig, traceAgent: StackdriverTracer);
/**

@@ -65,4 +73,2 @@ * Logs an error message detailing the list of modules that were loaded before

}
export declare const tracing: Singleton<Tracing, {
enabled: false;
} | (TraceWriterConfig & PluginLoaderConfig & TopLevelConfig), StackdriverTracer>;
export declare const tracing: Singleton<Tracing, TopLevelConfig, StackdriverTracer>;

@@ -18,2 +18,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const propagation_stackdriver_1 = require("@opencensus/propagation-stackdriver");
const path = require("path");

@@ -24,2 +25,3 @@ const cls_1 = require("./cls");

const trace_writer_1 = require("./trace-writer");
const tracing_policy_1 = require("./tracing-policy");
const util_1 = require("./util");

@@ -47,3 +49,6 @@ /**

}
this.logger = new logger_1.Logger({ level: defaultLevels[logLevel], tag: '@google-cloud/trace-agent' });
this.logger = new logger_1.Logger({
level: defaultLevels[logLevel],
tag: '@google-cloud/trace-agent',
});
}

@@ -62,3 +67,4 @@ /**

const moduleName = util_1.packageNameFromPath(filesLoadedBeforeTrace[i]);
if (moduleName && moduleName !== traceModuleName &&
if (moduleName &&
moduleName !== traceModuleName &&
modulesLoadedBeforeTrace.indexOf(moduleName) === -1) {

@@ -80,9 +86,5 @@ modulesLoadedBeforeTrace.push(moduleName);

// Initialize context propagation mechanism configuration.
const clsConfig = {
mechanism: this.config.clsMechanism,
[util_1.FORCE_NEW]: this.config[util_1.FORCE_NEW]
};
try {
trace_writer_1.traceWriter.create(this.config, this.logger);
cls_1.cls.create(clsConfig, this.logger);
trace_writer_1.traceWriter.create(this.config.writerConfig, this.logger);
cls_1.cls.create(this.config.clsConfig, this.logger);
}

@@ -94,3 +96,6 @@ catch (e) {

}
trace_writer_1.traceWriter.get().initialize().catch((err) => {
trace_writer_1.traceWriter
.get()
.initialize()
.catch(err => {
this.logger.error('StackdriverTracer#start: Disabling the Trace Agent for the', `following reason: ${err.message}`);

@@ -100,6 +105,12 @@ this.disable();

cls_1.cls.get().enable();
this.traceAgent.enable(this.config, this.logger);
trace_plugin_loader_1.pluginLoader.create(this.config, this.logger).activate();
if (typeof this.config.projectId !== 'string' &&
typeof this.config.projectId !== 'undefined') {
const tracePolicy = this.config.overrides.tracePolicy ||
new tracing_policy_1.BuiltinTracePolicy(this.config.tracePolicyConfig);
const propagation = this.config.overrides.propagation || new propagation_stackdriver_1.StackdriverFormat();
const tracerComponents = { logger: this.logger, tracePolicy, propagation };
this.traceAgent.enable(this.config.pluginLoaderConfig.tracerConfig, tracerComponents);
trace_plugin_loader_1.pluginLoader
.create(this.config.pluginLoaderConfig, tracerComponents)
.activate();
if (typeof this.config.writerConfig.projectId !== 'string' &&
typeof this.config.writerConfig.projectId !== 'undefined') {
this.logger.error('StackdriverTracer#start: config.projectId, if provided, must be a string.', 'Disabling trace agent.');

@@ -106,0 +117,0 @@ this.disable();

@@ -1,17 +0,4 @@

/**
* Copyright 2015 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.
*/
/// <reference types="node" />
declare const hexToDec: (input: string) => string, decToHex: (input: string) => string;
export { hexToDec, decToHex };
export declare const kSingleton: unique symbol;

@@ -44,6 +31,6 @@ /**

};
export declare type Component = {
export interface Component {
enable(): void;
disable(): void;
};
}
/**

@@ -64,2 +51,8 @@ * A class that provides access to a singleton.

/**
* Returns the last parameter that is not null, undefined, or NaN.
* @param defaultValue The first parameter. This must not be null/undefined/NaN.
* @param otherValues Other parameters, which may be null/undefined/NaN.
*/
export declare function lastOf<T>(defaultValue: T, ...otherValues: Array<T | null | undefined>): T;
/**
* Truncates the provided `string` to be at most `length` bytes

@@ -66,0 +59,0 @@ * after utf8 encoding and the appending of '...'.

"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
"use strict";
/**

@@ -17,7 +20,7 @@ * Copyright 2015 Google Inc. All Rights Reserved.

*/
Object.defineProperty(exports, "__esModule", { value: true });
var _a;
"use strict";
const path = require("path");
const { hexToDec, decToHex } = require('hex2dec');
const sourceMapSupport = require("source-map-support");
const { hexToDec, decToHex, } = require('hex2dec');
exports.hexToDec = hexToDec;
exports.decToHex = decToHex;
// This symbol must be exported (for now).

@@ -65,2 +68,20 @@ // See: https://github.com/Microsoft/TypeScript/issues/20080

/**
* Returns the last parameter that is not null, undefined, or NaN.
* @param defaultValue The first parameter. This must not be null/undefined/NaN.
* @param otherValues Other parameters, which may be null/undefined/NaN.
*/
function lastOf(defaultValue, ...otherValues) {
for (let i = otherValues.length - 1; i >= 0; i--) {
// tslint:disable:no-any
if (otherValues[i] !== null &&
otherValues[i] !== undefined &&
(typeof otherValues[i] !== 'number' || !isNaN(otherValues[i]))) {
return otherValues[i];
}
// tslint:enable:no-any
}
return defaultValue;
}
exports.lastOf = lastOf;
/**
* Truncates the provided `string` to be at most `length` bytes

@@ -87,4 +108,8 @@ * after utf8 encoding and the appending of '...'.

const moduleRegex = new RegExp([
'.*?node_modules(?!.*node_modules)\\', '(@[^\\', ']*\\', '[^\\', ']*|[^\\',
']*).*'
'.*?node_modules(?!.*node_modules)\\',
'(@[^\\',
']*\\',
'[^\\',
']*|[^\\',
']*).*',
].join(path.sep));

@@ -106,3 +131,5 @@ /**

const matches = str.match(/^([0-9a-fA-F]+)(?:\/([0-9]+))(?:;o=(.*))?/);
if (!matches || matches.length !== 4 || matches[0] !== str ||
if (!matches ||
matches.length !== 4 ||
matches[0] !== str ||
(matches[2] && isNaN(Number(matches[2])))) {

@@ -114,3 +141,3 @@ return null;

spanId: matches[2],
options: isNaN(Number(matches[3])) ? undefined : Number(matches[3])
options: isNaN(Number(matches[3])) ? undefined : Number(matches[3]),
};

@@ -170,6 +197,5 @@ }

const origPrepare = Error.prepareStackTrace;
Error.prepareStackTrace =
(error, structured) => {
return structured;
};
Error.prepareStackTrace = (error, structured) => {
return structured.map(sourceMapSupport.wrapCallSite);
};
const e = {};

@@ -187,5 +213,5 @@ Error.captureStackTrace(e, constructorOpt);

const methodName = callSite.getMethodName();
const name = (methodName && functionName) ?
functionName + ' [as ' + methodName + ']' :
functionName || methodName || '<anonymous function>';
const name = methodName && functionName
? functionName + ' [as ' + methodName + ']'
: functionName || methodName || '<anonymous function>';
const stackFrame = {

@@ -195,3 +221,3 @@ method_name: name,

line_number: callSite.getLineNumber() || undefined,
column_number: callSite.getColumnNumber() || undefined
column_number: callSite.getColumnNumber() || undefined,
};

@@ -250,4 +276,6 @@ stackFrames.push(stackFrame);

// Check version and field numbers.
if (buffer.readUInt8(0) !== 0 || buffer.readUInt8(1) !== 0 ||
buffer.readUInt8(18) !== 1 || buffer.readUInt8(27) !== 2) {
if (buffer.readUInt8(0) !== 0 ||
buffer.readUInt8(1) !== 0 ||
buffer.readUInt8(18) !== 1 ||
buffer.readUInt8(27) !== 2) {
return null;

@@ -254,0 +282,0 @@ }

{
"name": "@google-cloud/trace-agent",
"version": "3.6.1",
"version": "4.0.0",
"description": "Node.js Support for StackDriver Trace",

@@ -14,7 +14,5 @@ "main": "build/src/index.js",

"system-test": "npm run script decrypt-service-account-credentials run-system-tests",
"changelog": "./bin/run-changelog.sh",
"check-install": "npm run script check-install",
"get-plugin-types": "npm run script get-plugin-types",
"coverage": "npm run script run-unit-tests-with-coverage report-coverage",
"bump": "./bin/run-bump.sh",
"check": "gts check",

@@ -51,3 +49,3 @@ "clean": "rimraf build/src",

"engines": {
"node": ">=6"
"node": ">=8.10.0"
},

@@ -66,7 +64,5 @@ "devDependencies": {

"@types/mongoose": "^5.3.26",
"@types/ncp": "^2.0.1",
"@types/nock": "^10.0.0",
"@types/node": "~10.7.2",
"@types/once": "^1.4.0",
"@types/pify": "^3.0.0",
"@types/proxyquire": "^1.3.28",

@@ -76,33 +72,31 @@ "@types/request": "^2.48.1",

"@types/shimmer": "^1.0.1",
"@types/source-map-support": "^0.5.0",
"@types/tmp": "0.1.0",
"@types/uuid": "^3.4.3",
"axios": "^0.18.0",
"changelog-maker": "^2.2.2",
"axios": "^0.19.0",
"codecov": "^3.0.0",
"cpy": "^7.2.0",
"express": "^4.15.2",
"glob": "^7.0.3",
"grpc": "1.20.2",
"gts": "^0.9.0",
"grpc": "1.21.1",
"gts": "^1.0.0",
"intelli-espower-loader": "^1.0.1",
"js-green-licenses": "^0.5.0",
"jshint": "^2.9.1",
"js-green-licenses": "^1.0.0",
"linkinator": "^1.1.2",
"mocha": "^6.0.0",
"ncp": "^2.0.0",
"nock": "^10.0.0",
"nyc": "^14.0.0",
"once": "^1.4.0",
"pify": "^4.0.0",
"retry-axios": "^0.5.0",
"retry-axios": "^1.0.0",
"rimraf": "^2.6.2",
"source-map-support": "^0.5.6",
"standard-version": "^5.0.0",
"teeny-request": "^3.11.1",
"standard-version": "^6.0.0",
"teeny-request": "^4.0.0",
"timekeeper": "^2.0.0",
"tmp": "0.1.0",
"ts-node": "^8.0.0",
"typescript": "~3.4.0"
"typescript": "~3.5.1"
},
"dependencies": {
"@google-cloud/common": "^0.32.1",
"@google-cloud/common": "^2.0.0",
"@opencensus/propagation-stackdriver": "0.0.13",
"builtin-modules": "^3.0.0",

@@ -112,3 +106,3 @@ "console-log-level": "^1.4.0",

"extend": "^3.0.0",
"gcp-metadata": "^1.0.0",
"gcp-metadata": "^2.0.0",
"hex2dec": "^1.0.1",

@@ -119,2 +113,3 @@ "is": "^3.2.0",

"semver": "^6.0.0",
"source-map-support": "^0.5.12",
"shimmer": "^1.2.0",

@@ -121,0 +116,0 @@ "uuid": "^3.0.1"

@@ -163,3 +163,3 @@ # Stackdriver Trace Agent for Node.js

The way we trace modules we does not support bundled server code. Bundlers like webpack or @zeit/ncc will not work.
The way we trace modules does not support bundled server code. Bundlers like webpack or @zeit/ncc will not work.

@@ -166,0 +166,0 @@ ## Contributing changes

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc