rittenhop-ghost/versions/5.94.2/node_modules/@opentelemetry/sdk-trace-base/build/esnext/Span.js

285 lines
10 KiB
JavaScript

/*
* Copyright The OpenTelemetry Authors
*
* Licensed 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
*
* https://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.
*/
import { diag, SpanStatusCode, } from '@opentelemetry/api';
import { addHrTimes, millisToHrTime, getTimeOrigin, hrTime, hrTimeDuration, isAttributeValue, isTimeInput, isTimeInputHrTime, otperformance, sanitizeAttributes, } from '@opentelemetry/core';
import { SEMATTRS_EXCEPTION_MESSAGE, SEMATTRS_EXCEPTION_STACKTRACE, SEMATTRS_EXCEPTION_TYPE, } from '@opentelemetry/semantic-conventions';
import { ExceptionEventName } from './enums';
/**
* This class represents a span.
*/
export class Span {
/**
* Constructs a new Span instance.
*
* @deprecated calling Span constructor directly is not supported. Please use tracer.startSpan.
* */
constructor(parentTracer, context, spanName, spanContext, kind, parentSpanId, links = [], startTime, _deprecatedClock, // keeping this argument even though it is unused to ensure backwards compatibility
attributes) {
this.attributes = {};
this.links = [];
this.events = [];
this._droppedAttributesCount = 0;
this._droppedEventsCount = 0;
this._droppedLinksCount = 0;
this.status = {
code: SpanStatusCode.UNSET,
};
this.endTime = [0, 0];
this._ended = false;
this._duration = [-1, -1];
this.name = spanName;
this._spanContext = spanContext;
this.parentSpanId = parentSpanId;
this.kind = kind;
this.links = links;
const now = Date.now();
this._performanceStartTime = otperformance.now();
this._performanceOffset =
now - (this._performanceStartTime + getTimeOrigin());
this._startTimeProvided = startTime != null;
this.startTime = this._getTime(startTime !== null && startTime !== void 0 ? startTime : now);
this.resource = parentTracer.resource;
this.instrumentationLibrary = parentTracer.instrumentationLibrary;
this._spanLimits = parentTracer.getSpanLimits();
this._attributeValueLengthLimit =
this._spanLimits.attributeValueLengthLimit || 0;
if (attributes != null) {
this.setAttributes(attributes);
}
this._spanProcessor = parentTracer.getActiveSpanProcessor();
this._spanProcessor.onStart(this, context);
}
spanContext() {
return this._spanContext;
}
setAttribute(key, value) {
if (value == null || this._isSpanEnded())
return this;
if (key.length === 0) {
diag.warn(`Invalid attribute key: ${key}`);
return this;
}
if (!isAttributeValue(value)) {
diag.warn(`Invalid attribute value set for key: ${key}`);
return this;
}
if (Object.keys(this.attributes).length >=
this._spanLimits.attributeCountLimit &&
!Object.prototype.hasOwnProperty.call(this.attributes, key)) {
this._droppedAttributesCount++;
return this;
}
this.attributes[key] = this._truncateToSize(value);
return this;
}
setAttributes(attributes) {
for (const [k, v] of Object.entries(attributes)) {
this.setAttribute(k, v);
}
return this;
}
/**
*
* @param name Span Name
* @param [attributesOrStartTime] Span attributes or start time
* if type is {@type TimeInput} and 3rd param is undefined
* @param [timeStamp] Specified time stamp for the event
*/
addEvent(name, attributesOrStartTime, timeStamp) {
if (this._isSpanEnded())
return this;
if (this._spanLimits.eventCountLimit === 0) {
diag.warn('No events allowed.');
this._droppedEventsCount++;
return this;
}
if (this.events.length >= this._spanLimits.eventCountLimit) {
if (this._droppedEventsCount === 0) {
diag.debug('Dropping extra events.');
}
this.events.shift();
this._droppedEventsCount++;
}
if (isTimeInput(attributesOrStartTime)) {
if (!isTimeInput(timeStamp)) {
timeStamp = attributesOrStartTime;
}
attributesOrStartTime = undefined;
}
const attributes = sanitizeAttributes(attributesOrStartTime);
this.events.push({
name,
attributes,
time: this._getTime(timeStamp),
droppedAttributesCount: 0,
});
return this;
}
addLink(link) {
this.links.push(link);
return this;
}
addLinks(links) {
this.links.push(...links);
return this;
}
setStatus(status) {
if (this._isSpanEnded())
return this;
this.status = status;
return this;
}
updateName(name) {
if (this._isSpanEnded())
return this;
this.name = name;
return this;
}
end(endTime) {
if (this._isSpanEnded()) {
diag.error(`${this.name} ${this._spanContext.traceId}-${this._spanContext.spanId} - You can only call end() on a span once.`);
return;
}
this._ended = true;
this.endTime = this._getTime(endTime);
this._duration = hrTimeDuration(this.startTime, this.endTime);
if (this._duration[0] < 0) {
diag.warn('Inconsistent start and end time, startTime > endTime. Setting span duration to 0ms.', this.startTime, this.endTime);
this.endTime = this.startTime.slice();
this._duration = [0, 0];
}
if (this._droppedEventsCount > 0) {
diag.warn(`Dropped ${this._droppedEventsCount} events because eventCountLimit reached`);
}
this._spanProcessor.onEnd(this);
}
_getTime(inp) {
if (typeof inp === 'number' && inp < otperformance.now()) {
// must be a performance timestamp
// apply correction and convert to hrtime
return hrTime(inp + this._performanceOffset);
}
if (typeof inp === 'number') {
return millisToHrTime(inp);
}
if (inp instanceof Date) {
return millisToHrTime(inp.getTime());
}
if (isTimeInputHrTime(inp)) {
return inp;
}
if (this._startTimeProvided) {
// if user provided a time for the start manually
// we can't use duration to calculate event/end times
return millisToHrTime(Date.now());
}
const msDuration = otperformance.now() - this._performanceStartTime;
return addHrTimes(this.startTime, millisToHrTime(msDuration));
}
isRecording() {
return this._ended === false;
}
recordException(exception, time) {
const attributes = {};
if (typeof exception === 'string') {
attributes[SEMATTRS_EXCEPTION_MESSAGE] = exception;
}
else if (exception) {
if (exception.code) {
attributes[SEMATTRS_EXCEPTION_TYPE] = exception.code.toString();
}
else if (exception.name) {
attributes[SEMATTRS_EXCEPTION_TYPE] = exception.name;
}
if (exception.message) {
attributes[SEMATTRS_EXCEPTION_MESSAGE] = exception.message;
}
if (exception.stack) {
attributes[SEMATTRS_EXCEPTION_STACKTRACE] = exception.stack;
}
}
// these are minimum requirements from spec
if (attributes[SEMATTRS_EXCEPTION_TYPE] ||
attributes[SEMATTRS_EXCEPTION_MESSAGE]) {
this.addEvent(ExceptionEventName, attributes, time);
}
else {
diag.warn(`Failed to record an exception ${exception}`);
}
}
get duration() {
return this._duration;
}
get ended() {
return this._ended;
}
get droppedAttributesCount() {
return this._droppedAttributesCount;
}
get droppedEventsCount() {
return this._droppedEventsCount;
}
get droppedLinksCount() {
return this._droppedLinksCount;
}
_isSpanEnded() {
if (this._ended) {
diag.warn(`Can not execute the operation on ended Span {traceId: ${this._spanContext.traceId}, spanId: ${this._spanContext.spanId}}`);
}
return this._ended;
}
// Utility function to truncate given value within size
// for value type of string, will truncate to given limit
// for type of non-string, will return same value
_truncateToLimitUtil(value, limit) {
if (value.length <= limit) {
return value;
}
return value.substr(0, limit);
}
/**
* If the given attribute value is of type string and has more characters than given {@code attributeValueLengthLimit} then
* return string with truncated to {@code attributeValueLengthLimit} characters
*
* If the given attribute value is array of strings then
* return new array of strings with each element truncated to {@code attributeValueLengthLimit} characters
*
* Otherwise return same Attribute {@code value}
*
* @param value Attribute value
* @returns truncated attribute value if required, otherwise same value
*/
_truncateToSize(value) {
const limit = this._attributeValueLengthLimit;
// Check limit
if (limit <= 0) {
// Negative values are invalid, so do not truncate
diag.warn(`Attribute value limit must be positive, got ${limit}`);
return value;
}
// String
if (typeof value === 'string') {
return this._truncateToLimitUtil(value, limit);
}
// Array of strings
if (Array.isArray(value)) {
return value.map(val => typeof val === 'string' ? this._truncateToLimitUtil(val, limit) : val);
}
// Other types, no need to apply value length limit
return value;
}
}
//# sourceMappingURL=Span.js.map