UNPKG

skywalking-backend-js-netease

Version:

The NodeJS agent for Apache SkyWalking

192 lines 8.05 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 DummySpan_1 = tslib_1.__importDefault(require("../../trace/span/DummySpan")); const Segment_1 = tslib_1.__importDefault(require("../../trace/context/Segment")); const EntrySpan_1 = tslib_1.__importDefault(require("../../trace/span/EntrySpan")); const ExitSpan_1 = tslib_1.__importDefault(require("../../trace/span/ExitSpan")); const LocalSpan_1 = tslib_1.__importDefault(require("../../trace/span/LocalSpan")); const SegmentRef_1 = tslib_1.__importDefault(require("./SegmentRef")); const ContextManager_1 = tslib_1.__importDefault(require("./ContextManager")); const Tag_1 = tslib_1.__importDefault(require("../../Tag")); const Component_1 = require("../Component"); const logging_1 = require("../../logging"); const ContextCarrier_1 = require("./ContextCarrier"); const Tracing_pb_1 = require("../../proto/language-agent/Tracing_pb"); const EventEmitter_1 = require("../../lib/EventEmitter"); const logger = logging_1.createLogger(__filename); EventEmitter_1.emitter.on('segments-sent', () => { SpanContext.nActiveSegments = 0; // reset limiter }); class SpanContext { constructor() { this.spanId = 0; this.nSpans = 0; this.finished = false; this.segment = new Segment_1.default(); } ignoreCheck(operation, type, carrier) { if (operation.match(AgentConfig_1.default.reIgnoreOperation) || (carrier && !carrier.isValid())) return DummySpan_1.default.create(); return undefined; } spanCheck(spanType, operation, carrier) { const span = this.ignoreCheck(operation, Tracing_pb_1.SpanType.ENTRY, carrier); if (span) return [span]; const spans = ContextManager_1.default.spans; const parent = spans[spans.length - 1]; if (parent instanceof DummySpan_1.default) return [parent]; return [null, parent]; } newSpan(spanClass, parent, operation, force) { var _a; const context = !this.finished ? this : new SpanContext(); const span = new spanClass({ id: context.spanId++, parentId: (this.finished || force) ? -1 : (_a = parent === null || parent === void 0 ? void 0 : parent.id) !== null && _a !== void 0 ? _a : -1, context, operation, }); if ((this.finished || force) && parent) { // segment has already been closed and sent to server, if there is a parent span then need new segment to reference const carrier = new ContextCarrier_1.ContextCarrier(parent.context.segment.relatedTraces[0], parent.context.segment.segmentId, parent.id, AgentConfig_1.default.serviceName, AgentConfig_1.default.serviceInstance, parent.operation, parent.peer, []); const ref = SegmentRef_1.default.fromCarrier(carrier); context.segment.relate(carrier.traceId); span.refer(ref); } return span; } newEntrySpan(operation, carrier, inherit) { // tslint:disable-next-line:prefer-const let [span, parent] = this.spanCheck(Tracing_pb_1.SpanType.ENTRY, operation, carrier); if (span) return span; if (logger._isDebugEnabled) { logger.debug('Creating entry span', { parent, }); } if (!this.finished && (parent === null || parent === void 0 ? void 0 : parent.type) === Tracing_pb_1.SpanType.ENTRY && inherit && (inherit instanceof Component_1.Component ? inherit === parent.component : inherit.indexOf(parent.component) != -1)) { span = parent; parent.operation = operation; } else { span = this.newSpan(EntrySpan_1.default, parent, operation); if (carrier && carrier.isValid()) span.extract(carrier); } return span; } newExitSpan(operation, component, inherit) { // tslint:disable-next-line:prefer-const let [span, parent] = this.spanCheck(Tracing_pb_1.SpanType.EXIT, operation); if (span) return span; if (logger._isDebugEnabled) { logger.debug('Creating exit span', { operation, parent, }); } if (!this.finished && (parent === null || parent === void 0 ? void 0 : parent.type) === Tracing_pb_1.SpanType.EXIT && component === parent.inherit) span = parent; else span = this.newSpan(ExitSpan_1.default, parent, operation); if (inherit) span.inherit = inherit; return span; } newLocalSpan(operation, manParent) { var _a; let [span, parent] = this.spanCheck(Tracing_pb_1.SpanType.LOCAL, operation); if (span) return span; if (logger._isDebugEnabled) { logger.debug('Creating local span', { parentId: (_a = parent === null || parent === void 0 ? void 0 : parent.id) !== null && _a !== void 0 ? _a : -1, }); } return this.newSpan(LocalSpan_1.default, (parent !== null && parent !== void 0 ? parent : manParent), operation, !!manParent && !parent); } start(span) { const spans = ContextManager_1.default.spansDup(); logger.debug(`Starting span ${span.operation}`, { span, spans, nSpans: this.nSpans, }); if (!this.nSpans++) { SpanContext.nActiveSegments += 1; span.isCold = ContextManager_1.default.checkCold(); if (span.isCold) span.tag(Tag_1.default.coldStart(), true); } if (spans.indexOf(span) === -1) spans.push(span); return this; } stop(span) { logger.debug(`Stopping span ${span.operation}`, { span, spans: ContextManager_1.default.spans, nSpans: this.nSpans, }); span.finish(this.segment); ContextManager_1.default.clear(span); if (--this.nSpans === 0) { this.finished = true; EventEmitter_1.emitter.emit('segment-finished', this.segment); return true; } return false; } async(span) { logger.debug(`Async span ${span.operation}`, { span, spans: ContextManager_1.default.spans, nSpans: this.nSpans, }); ContextManager_1.default.clear(span); } resync(span) { logger.debug(`Resync span ${span.operation}`, { span, spans: ContextManager_1.default.spans, nSpans: this.nSpans, }); ContextManager_1.default.restore(span); } traceId() { if (!this.segment.relatedTraces) { return 'N/A'; } return this.segment.relatedTraces[0].toString(); } } exports.default = SpanContext; SpanContext.nActiveSegments = 0; // counter to allow only config.maxBufferSize active (non-dummy) segments per reporting frame //# sourceMappingURL=SpanContext.js.map