UNPKG

@kangc/skywalking-backend-js

Version:

The NodeJS agent for Apache SkyWalking

191 lines 7.48 kB
"use strict"; /*! * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 }); var tslib_1 = require("tslib"); var AgentConfig_1 = tslib_1.__importDefault(require("../../config/AgentConfig")); var SpanContext_1 = tslib_1.__importDefault(require("../../trace/context/SpanContext")); var DummyContext_1 = tslib_1.__importDefault(require("../../trace/context/DummyContext")); var async_hooks_1 = tslib_1.__importDefault(require("async_hooks")); var store; if (async_hooks_1.default.AsyncLocalStorage) { store = new async_hooks_1.default.AsyncLocalStorage(); } else { // Node 10 doesn't have AsyncLocalStore, so recreate it var executionAsyncId_1 = async_hooks_1.default.executionAsyncId; var asyncLocalStore_1 = {}; store = { getStore: function () { return asyncLocalStore_1[executionAsyncId_1()]; }, enterWith: function (s) { asyncLocalStore_1[executionAsyncId_1()] = s; }, }; async_hooks_1.default .createHook({ init: function (asyncId, type, triggerId) { asyncLocalStore_1[asyncId] = asyncLocalStore_1[triggerId]; }, destroy: function (asyncId) { delete asyncLocalStore_1[asyncId]; }, }) .enable(); } var ContextManager = /** @class */ (function () { function ContextManager() { this.isCold = true; } ContextManager.prototype.checkCold = function () { var isCold = this.isCold; this.isCold = false; return isCold; }; Object.defineProperty(ContextManager.prototype, "asyncState", { get: function () { var asyncState = store.getStore(); if (!asyncState) { asyncState = { spans: [] }; store.enterWith(asyncState); } return asyncState; }, enumerable: false, configurable: true }); Object.defineProperty(ContextManager.prototype, "currentSpan", { get: function () { var _a; var spans = (_a = store.getStore()) === null || _a === void 0 ? void 0 : _a.spans; return spans === null || spans === void 0 ? void 0 : spans[spans.length - 1]; }, enumerable: false, configurable: true }); Object.defineProperty(ContextManager.prototype, "hasContext", { get: function () { var _a; return Boolean((_a = store.getStore()) === null || _a === void 0 ? void 0 : _a.spans.length); }, enumerable: false, configurable: true }); Object.defineProperty(ContextManager.prototype, "current", { get: function () { var asyncState = this.asyncState; if (asyncState.spans.length) return asyncState.spans[asyncState.spans.length - 1].context; if (SpanContext_1.default.nActiveSegments < AgentConfig_1.default.maxBufferSize) return new SpanContext_1.default(); return new DummyContext_1.default(); }, enumerable: false, configurable: true }); Object.defineProperty(ContextManager.prototype, "spans", { get: function () { return this.asyncState.spans; }, enumerable: false, configurable: true }); ContextManager.prototype.spansDup = function () { var asyncState = store.getStore(); if (!asyncState) { asyncState = { spans: [] }; } else { asyncState = { spans: tslib_1.__spreadArrays(asyncState.spans) }; } store.enterWith(asyncState); return asyncState.spans; }; ContextManager.prototype.clear = function (span) { var spans = this.spansDup(); // this needed to make sure async tasks created before this call will still have this span at the top of their span list var idx = spans.indexOf(span); if (idx !== -1) spans.splice(idx, 1); }; ContextManager.prototype.restore = function (span) { var spans = this.spansDup(); if (spans.indexOf(span) === -1) spans.push(span); }; ContextManager.prototype.removeTailFinishedContexts = function () { // XXX: Normally, SpanContexts that finish and send their segments can remain in the span lists of async contexts. // This is so that if an async child that was spawned by the original span code and is executed after the parent // finishes and creates its own span can be linked to the parent segment and span correctly. But in some situations // where successive independent operations are chained linearly instead of hierarchically (AWS Lambda functions), // this can cause a false reference by a subsequent operation as if it were a child of the finished previous span. for (var spans = this.asyncState.spans; spans.length && spans[spans.length - 1].context.finished; spans.pop()) ; }; ContextManager.prototype.withSpan = function (span, callback) { var args = []; for (var _i = 2; _i < arguments.length; _i++) { args[_i - 2] = arguments[_i]; } if (!span.startTime) span.start(); try { return callback.apply(void 0, args); } catch (e) { span.error(e); throw e; } finally { span.stop(); } }; ContextManager.prototype.withSpanAwait = function (span, callback) { var args = []; for (var _i = 2; _i < arguments.length; _i++) { args[_i - 2] = arguments[_i]; } return tslib_1.__awaiter(this, void 0, void 0, function () { var e_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!span.startTime) span.start(); _a.label = 1; case 1: _a.trys.push([1, 3, 4, 5]); return [4 /*yield*/, callback.apply(void 0, args)]; case 2: return [2 /*return*/, _a.sent()]; case 3: e_1 = _a.sent(); span.error(e_1); throw e_1; case 4: span.stop(); return [7 /*endfinally*/]; case 5: return [2 /*return*/]; } }); }); }; return ContextManager; }()); exports.default = new ContextManager(); //# sourceMappingURL=ContextManager.js.map