UNPKG

6.48 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright The OpenTelemetry Authors
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.Span = void 0;
19const api = require("@opentelemetry/api");
20const core_1 = require("@opentelemetry/core");
21const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
22const enums_1 = require("./enums");
23/**
24 * This class represents a span.
25 */
26class Span {
27 /** Constructs a new Span instance. */
28 constructor(parentTracer, context, spanName, spanContext, kind, parentSpanId, links = [], startTime = core_1.hrTime()) {
29 this.attributes = {};
30 this.links = [];
31 this.events = [];
32 this.status = {
33 code: api.SpanStatusCode.UNSET,
34 };
35 this.endTime = [0, 0];
36 this._ended = false;
37 this._duration = [-1, -1];
38 this.name = spanName;
39 this._spanContext = spanContext;
40 this.parentSpanId = parentSpanId;
41 this.kind = kind;
42 this.links = links;
43 this.startTime = core_1.timeInputToHrTime(startTime);
44 this.resource = parentTracer.resource;
45 this.instrumentationLibrary = parentTracer.instrumentationLibrary;
46 this._spanLimits = parentTracer.getSpanLimits();
47 this._spanProcessor = parentTracer.getActiveSpanProcessor();
48 this._spanProcessor.onStart(this, context);
49 }
50 spanContext() {
51 return this._spanContext;
52 }
53 setAttribute(key, value) {
54 if (value == null || this._isSpanEnded())
55 return this;
56 if (key.length === 0) {
57 api.diag.warn(`Invalid attribute key: ${key}`);
58 return this;
59 }
60 if (!core_1.isAttributeValue(value)) {
61 api.diag.warn(`Invalid attribute value set for key: ${key}`);
62 return this;
63 }
64 if (Object.keys(this.attributes).length >=
65 this._spanLimits.attributeCountLimit &&
66 !Object.prototype.hasOwnProperty.call(this.attributes, key)) {
67 return this;
68 }
69 this.attributes[key] = value;
70 return this;
71 }
72 setAttributes(attributes) {
73 for (const [k, v] of Object.entries(attributes)) {
74 this.setAttribute(k, v);
75 }
76 return this;
77 }
78 /**
79 *
80 * @param name Span Name
81 * @param [attributesOrStartTime] Span attributes or start time
82 * if type is {@type TimeInput} and 3rd param is undefined
83 * @param [startTime] Specified start time for the event
84 */
85 addEvent(name, attributesOrStartTime, startTime) {
86 if (this._isSpanEnded())
87 return this;
88 if (this.events.length >= this._spanLimits.eventCountLimit) {
89 api.diag.warn('Dropping extra events.');
90 this.events.shift();
91 }
92 if (core_1.isTimeInput(attributesOrStartTime)) {
93 if (typeof startTime === 'undefined') {
94 startTime = attributesOrStartTime;
95 }
96 attributesOrStartTime = undefined;
97 }
98 if (typeof startTime === 'undefined') {
99 startTime = core_1.hrTime();
100 }
101 this.events.push({
102 name,
103 attributes: attributesOrStartTime,
104 time: core_1.timeInputToHrTime(startTime),
105 });
106 return this;
107 }
108 setStatus(status) {
109 if (this._isSpanEnded())
110 return this;
111 this.status = status;
112 return this;
113 }
114 updateName(name) {
115 if (this._isSpanEnded())
116 return this;
117 this.name = name;
118 return this;
119 }
120 end(endTime = core_1.hrTime()) {
121 if (this._isSpanEnded()) {
122 api.diag.error('You can only call end() on a span once.');
123 return;
124 }
125 this._ended = true;
126 this.endTime = core_1.timeInputToHrTime(endTime);
127 this._duration = core_1.hrTimeDuration(this.startTime, this.endTime);
128 if (this._duration[0] < 0) {
129 api.diag.warn('Inconsistent start and end time, startTime > endTime', this.startTime, this.endTime);
130 }
131 this._spanProcessor.onEnd(this);
132 }
133 isRecording() {
134 return this._ended === false;
135 }
136 recordException(exception, time = core_1.hrTime()) {
137 const attributes = {};
138 if (typeof exception === 'string') {
139 attributes[semantic_conventions_1.SemanticAttributes.EXCEPTION_MESSAGE] = exception;
140 }
141 else if (exception) {
142 if (exception.code) {
143 attributes[semantic_conventions_1.SemanticAttributes.EXCEPTION_TYPE] = exception.code.toString();
144 }
145 else if (exception.name) {
146 attributes[semantic_conventions_1.SemanticAttributes.EXCEPTION_TYPE] = exception.name;
147 }
148 if (exception.message) {
149 attributes[semantic_conventions_1.SemanticAttributes.EXCEPTION_MESSAGE] = exception.message;
150 }
151 if (exception.stack) {
152 attributes[semantic_conventions_1.SemanticAttributes.EXCEPTION_STACKTRACE] = exception.stack;
153 }
154 }
155 // these are minimum requirements from spec
156 if (attributes[semantic_conventions_1.SemanticAttributes.EXCEPTION_TYPE] ||
157 attributes[semantic_conventions_1.SemanticAttributes.EXCEPTION_MESSAGE]) {
158 this.addEvent(enums_1.ExceptionEventName, attributes, time);
159 }
160 else {
161 api.diag.warn(`Failed to record an exception ${exception}`);
162 }
163 }
164 get duration() {
165 return this._duration;
166 }
167 get ended() {
168 return this._ended;
169 }
170 _isSpanEnded() {
171 if (this._ended) {
172 api.diag.warn('Can not execute the operation on ended Span {traceId: %s, spanId: %s}', this._spanContext.traceId, this._spanContext.spanId);
173 }
174 return this._ended;
175 }
176}
177exports.Span = Span;
178//# sourceMappingURL=Span.js.map
\No newline at end of file