UNPKG

@opencensus/core

Version:

OpenCensus is a toolkit for collecting application performance and behavior data.

150 lines 5.02 kB
"use strict"; /** * Copyright 2018 Google LLC * * 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 }); exports.reset = exports.getNamespace = exports.destroyNamespace = exports.createNamespace = void 0; // Original file from Stackdriver Trace Agent for Node.js // https://github.com/GoogleCloudPlatform/cloud-trace-nodejs const asyncHook = require("async_hooks"); const shimmer = require("shimmer"); const WRAPPED = Symbol('context_wrapped'); /** A map of AsyncResource IDs to Context objects. */ let contexts = new Map(); let current = {}; // Create the hook. asyncHook.createHook({ init, before, destroy }).enable(); // A list of well-known EventEmitter methods that add event listeners. const EVENT_EMITTER_METHODS = [ 'addListener', 'on', 'once', 'prependListener', 'prependOnceListener', ]; class AsyncHooksNamespace { get name() { throw new Error('Not implemented'); } get active() { return current; } createContext() { throw new Error('Not implemented'); } get(k) { return current[k]; } set(k, v) { current[k] = v; return v; } run(fn) { this.runAndReturn(fn); return current; } runAndReturn(fn) { const oldContext = current; current = {}; if (oldContext['current_tag_map']) { current['current_tag_map'] = oldContext['current_tag_map']; } const res = fn(); current = oldContext; return res; } bind(cb) { // TODO(kjin): Monitor https://github.com/Microsoft/TypeScript/pull/15473. // When it's landed and released, we can remove these `any` casts. // tslint:disable-next-line:no-any if (cb[WRAPPED] || !current) { return cb; } const boundContext = current; const contextWrapper = function () { const oldContext = current; current = boundContext; // @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'IArguments' is not assignable to... Remove this comment to see the full error message const res = cb.apply(this, arguments); current = oldContext; return res; }; // tslint:disable-next-line:no-any contextWrapper[WRAPPED] = true; Object.defineProperty(contextWrapper, 'length', { enumerable: false, configurable: true, writable: false, value: cb.length, }); return contextWrapper; } // This function is not technically needed and all tests currently pass // without it (after removing call sites). While it is not a complete // solution, restoring correct context before running every request/response // event handler reduces the number of situations in which userspace queuing // will cause us to lose context. bindEmitter(ee) { const ns = this; EVENT_EMITTER_METHODS.forEach(method => { if (ee[method]) { shimmer.wrap(ee, method, oldMethod => { return function (event, cb) { // @ts-expect-error ts-migrate(2684) FIXME: The 'this' context of type '((event: string | symb... Remove this comment to see the full error message return oldMethod.call(this, event, ns.bind(cb)); }; }); } }); } } const namespace = new AsyncHooksNamespace(); // AsyncWrap Hooks /** init is called during object construction. */ function init(uid, provider, parentUid, parentHandle) { contexts.set(uid, current); } /** before is called just before the resource's callback is called. */ function before(uid) { const maybeCurrent = contexts.get(uid); if (maybeCurrent !== undefined) { current = maybeCurrent; } } /** * destroy is called when the object is no longer used, so also delete * its entry in the map. */ function destroy(uid) { contexts.delete(uid); } function createNamespace() { return namespace; } exports.createNamespace = createNamespace; function destroyNamespace() { current = {}; contexts = new Map(); } exports.destroyNamespace = destroyNamespace; function getNamespace() { return namespace; } exports.getNamespace = getNamespace; function reset() { throw new Error('Not implemented'); } exports.reset = reset; //# sourceMappingURL=cls-ah.js.map