UNPKG

skywalking-backend-js-netease

Version:

The NodeJS agent for Apache SkyWalking

151 lines 5.42 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 }); const tslib_1 = require("tslib"); const AgentConfig_1 = tslib_1.__importDefault(require("../../config/AgentConfig")); const SpanContext_1 = tslib_1.__importDefault(require("../../trace/context/SpanContext")); const DummyContext_1 = tslib_1.__importDefault(require("../../trace/context/DummyContext")); const async_hooks_1 = tslib_1.__importDefault(require("async_hooks")); let store; if (async_hooks_1.default.AsyncLocalStorage) { store = new async_hooks_1.default.AsyncLocalStorage(); } else { // Node 10 doesn't have AsyncLocalStore, so recreate it const executionAsyncId = async_hooks_1.default.executionAsyncId; const asyncLocalStore = {}; store = { getStore() { return asyncLocalStore[executionAsyncId()]; }, enterWith(s) { asyncLocalStore[executionAsyncId()] = s; }, }; async_hooks_1.default .createHook({ init(asyncId, type, triggerId) { asyncLocalStore[asyncId] = asyncLocalStore[triggerId]; }, destroy(asyncId) { delete asyncLocalStore[asyncId]; }, }) .enable(); } class ContextManager { constructor() { this.isCold = true; } checkCold() { const isCold = this.isCold; this.isCold = false; return isCold; } get asyncState() { let asyncState = store.getStore(); if (!asyncState) { asyncState = { spans: [] }; store.enterWith(asyncState); } return asyncState; } get currentSpan() { var _a; const spans = (_a = store.getStore()) === null || _a === void 0 ? void 0 : _a.spans; return spans === null || spans === void 0 ? void 0 : spans[spans.length - 1]; } get hasContext() { var _a; return Boolean((_a = store.getStore()) === null || _a === void 0 ? void 0 : _a.spans.length); } get current() { const 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(); } get spans() { return this.asyncState.spans; } spansDup() { let asyncState = store.getStore(); if (!asyncState) { asyncState = { spans: [] }; } else { asyncState = { spans: [...asyncState.spans] }; } store.enterWith(asyncState); return asyncState.spans; } clear(span) { const 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 const idx = spans.indexOf(span); if (idx !== -1) spans.splice(idx, 1); } restore(span) { const spans = this.spansDup(); if (spans.indexOf(span) === -1) spans.push(span); } removeTailFinishedContexts() { // 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 (const spans = this.asyncState.spans; spans.length && spans[spans.length - 1].context.finished; spans.pop()) ; } withSpan(span, callback, ...args) { if (!span.startTime) span.start(); try { return callback(...args); } catch (e) { span.error(e); throw e; } finally { span.stop(); } } async withSpanAwait(span, callback, ...args) { if (!span.startTime) span.start(); try { return await callback(...args); } catch (e) { span.error(e); throw e; } finally { span.stop(); } } } exports.default = new ContextManager(); //# sourceMappingURL=ContextManager.js.map