UNPKG

@platformos/pos-cli

Version:

Manage your platformOS application

283 lines 9.8 kB
// tslint:disable:max-classes-per-file import * as tslib_1 from "tslib"; import { getCurrentHub, Hub } from '@sentry/hub'; import { SpanStatus } from '@sentry/types'; import { dropUndefinedKeys, isInstanceOf, logger, timestampWithMs, uuid4 } from '@sentry/utils'; // TODO: Should this be exported? export var TRACEPARENT_REGEXP = new RegExp('^[ \\t]*' + // whitespace '([0-9a-f]{32})?' + // trace_id '-?([0-9a-f]{16})?' + // span_id '-?([01])?' + // sampled '[ \\t]*$'); /** * Keeps track of finished spans for a given transaction */ var SpanRecorder = /** @class */ (function () { function SpanRecorder(maxlen) { this._openSpanCount = 0; this.finishedSpans = []; this._maxlen = maxlen; } /** * This is just so that we don't run out of memory while recording a lot * of spans. At some point we just stop and flush out the start of the * trace tree (i.e.the first n spans with the smallest * start_timestamp). */ SpanRecorder.prototype.startSpan = function (span) { this._openSpanCount += 1; if (this._openSpanCount > this._maxlen) { span.spanRecorder = undefined; } }; /** * Appends a span to finished spans table * @param span Span to be added */ SpanRecorder.prototype.finishSpan = function (span) { this.finishedSpans.push(span); }; return SpanRecorder; }()); /** * Span contains all data about a span */ var Span = /** @class */ (function () { function Span(spanContext, hub) { /** * The reference to the current hub. */ this._hub = getCurrentHub(); /** * @inheritDoc */ this._traceId = uuid4(); /** * @inheritDoc */ this._spanId = uuid4().substring(16); /** * Timestamp in seconds when the span was created. */ this.startTimestamp = timestampWithMs(); /** * @inheritDoc */ this.tags = {}; /** * @inheritDoc */ this.data = {}; if (isInstanceOf(hub, Hub)) { this._hub = hub; } if (!spanContext) { return this; } if (spanContext.traceId) { this._traceId = spanContext.traceId; } if (spanContext.spanId) { this._spanId = spanContext.spanId; } if (spanContext.parentSpanId) { this._parentSpanId = spanContext.parentSpanId; } // We want to include booleans as well here if ('sampled' in spanContext) { this.sampled = spanContext.sampled; } if (spanContext.transaction) { this.transaction = spanContext.transaction; } if (spanContext.op) { this.op = spanContext.op; } if (spanContext.description) { this.description = spanContext.description; } if (spanContext.data) { this.data = spanContext.data; } if (spanContext.tags) { this.tags = spanContext.tags; } } /** * Attaches SpanRecorder to the span itself * @param maxlen maximum number of spans that can be recorded */ Span.prototype.initFinishedSpans = function (maxlen) { if (maxlen === void 0) { maxlen = 1000; } if (!this.spanRecorder) { this.spanRecorder = new SpanRecorder(maxlen); } this.spanRecorder.startSpan(this); }; /** * Creates a new `Span` while setting the current `Span.id` as `parentSpanId`. * Also the `sampled` decision will be inherited. */ Span.prototype.child = function (spanContext) { var span = new Span(tslib_1.__assign({}, spanContext, { parentSpanId: this._spanId, sampled: this.sampled, traceId: this._traceId })); span.spanRecorder = this.spanRecorder; return span; }; /** * Continues a trace from a string (usually the header). * @param traceparent Traceparent string */ Span.fromTraceparent = function (traceparent, spanContext) { var matches = traceparent.match(TRACEPARENT_REGEXP); if (matches) { var sampled = void 0; if (matches[3] === '1') { sampled = true; } else if (matches[3] === '0') { sampled = false; } return new Span(tslib_1.__assign({}, spanContext, { parentSpanId: matches[2], sampled: sampled, traceId: matches[1] })); } return undefined; }; /** * @inheritDoc */ Span.prototype.setTag = function (key, value) { var _a; this.tags = tslib_1.__assign({}, this.tags, (_a = {}, _a[key] = value, _a)); return this; }; /** * @inheritDoc */ Span.prototype.setData = function (key, value) { var _a; this.data = tslib_1.__assign({}, this.data, (_a = {}, _a[key] = value, _a)); return this; }; /** * @inheritDoc */ Span.prototype.setStatus = function (value) { this.setTag('status', value); return this; }; /** * @inheritDoc */ Span.prototype.setHttpStatus = function (httpStatus) { this.setTag('http.status_code', String(httpStatus)); var spanStatus = SpanStatus.fromHttpCode(httpStatus); if (spanStatus !== SpanStatus.UnknownError) { this.setStatus(spanStatus); } return this; }; /** * @inheritDoc */ Span.prototype.isSuccess = function () { return this.tags.status === SpanStatus.Ok; }; /** * Sets the finish timestamp on the current span. * @param trimEnd If true, sets the end timestamp of the transaction to the highest timestamp of child spans, trimming * the duration of the transaction span. This is useful to discard extra time in the transaction span that is not * accounted for in child spans, like what happens in the idle transaction Tracing integration, where we finish the * transaction after a given "idle time" and we don't want this "idle time" to be part of the transaction. */ Span.prototype.finish = function (trimEnd) { var _this = this; if (trimEnd === void 0) { trimEnd = false; } // This transaction is already finished, so we should not flush it again. if (this.timestamp !== undefined) { return undefined; } this.timestamp = timestampWithMs(); if (this.spanRecorder === undefined) { return undefined; } this.spanRecorder.finishSpan(this); if (this.transaction === undefined) { // If this has no transaction set we assume there's a parent // transaction for this span that would be flushed out eventually. return undefined; } if (this.sampled === undefined) { // At this point a `sampled === undefined` should have already been // resolved to a concrete decision. If `sampled` is `undefined`, it's // likely that somebody used `Sentry.startSpan(...)` on a // non-transaction span and later decided to make it a transaction. logger.warn('Discarding transaction Span without sampling decision'); return undefined; } var finishedSpans = this.spanRecorder ? this.spanRecorder.finishedSpans.filter(function (s) { return s !== _this; }) : []; if (trimEnd && finishedSpans.length > 0) { this.timestamp = finishedSpans.reduce(function (prev, current) { if (prev.timestamp && current.timestamp) { return prev.timestamp > current.timestamp ? prev : current; } return prev; }).timestamp; } return this._hub.captureEvent({ contexts: { trace: this.getTraceContext(), }, spans: finishedSpans, start_timestamp: this.startTimestamp, tags: this.tags, timestamp: this.timestamp, transaction: this.transaction, type: 'transaction', }); }; /** * @inheritDoc */ Span.prototype.toTraceparent = function () { var sampledString = ''; if (this.sampled !== undefined) { sampledString = this.sampled ? '-1' : '-0'; } return this._traceId + "-" + this._spanId + sampledString; }; /** * @inheritDoc */ Span.prototype.getTraceContext = function () { return dropUndefinedKeys({ data: Object.keys(this.data).length > 0 ? this.data : undefined, description: this.description, op: this.op, parent_span_id: this._parentSpanId, span_id: this._spanId, status: this.tags.status, tags: Object.keys(this.tags).length > 0 ? this.tags : undefined, trace_id: this._traceId, }); }; /** * @inheritDoc */ Span.prototype.toJSON = function () { return dropUndefinedKeys({ data: Object.keys(this.data).length > 0 ? this.data : undefined, description: this.description, op: this.op, parent_span_id: this._parentSpanId, sampled: this.sampled, span_id: this._spanId, start_timestamp: this.startTimestamp, tags: Object.keys(this.tags).length > 0 ? this.tags : undefined, timestamp: this.timestamp, trace_id: this._traceId, transaction: this.transaction, }); }; return Span; }()); export { Span }; //# sourceMappingURL=span.js.map