skywalking-backend-js-netease
Version:
The NodeJS agent for Apache SkyWalking
192 lines • 8.05 kB
JavaScript
"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