UNPKG

lightstep-tracer

Version:

> ❗ **This instrumentation is no longer recommended**. Please review [documentation on setting up and configuring the OpenTelemetry Node.js Launcher](https://github.com/lightstep/otel-launcher-node) or [OpenTelemetry JS (Browser)](https://github.com/open-

236 lines (197 loc) 7.1 kB
import * as opentracing from 'opentracing'; import * as coerce from './coerce'; import * as constants from '../constants'; import _each from '../_each'; import { crouton_thrift } from '../platform_abstraction_layer'; // eslint-disable-line camelcase import LogRecordImp from './log_record_imp'; // eslint-disable-line camelcase import util from './util/util'; export default class SpanImp extends opentracing.Span { // ---------------------------------------------------------------------- // // opentracing.Span SPI // ---------------------------------------------------------------------- // _tracer() { return this._tracerImp; } _context() { return this._ctx; } _setOperationName(name) { this._operationName = `${name}`; } _setBaggageItem(key, value) { this._ctx.setBaggageItem(key, value); } _getBaggageItem(key) { return this._ctx.getBaggageItem(key); } _addTags(keyValuePairs) { let self = this; _each(keyValuePairs, (value, key) => { self._tags[key] = value; }); } _log(keyValuePairs, timestamp) { let self = this; const argumentType = typeof keyValuePairs; if (argumentType !== 'object') { self._tracerImp._error('Span.log() expects an object as its first argument'); return; } let tsMicros = timestamp ? (timestamp * 1000) : self._tracerImp._platform.nowMicros(); let record = new LogRecordImp( self._tracerImp.getLogFieldKeyHardLimit(), self._tracerImp.getLogFieldValueHardLimit(), tsMicros, keyValuePairs, ); self._log_records = self._log_records || []; self._log_records.push(record); self._tracerImp.emit('log_added', record); } _finish(finishTime) { return this.end(finishTime); } // ---------------------------------------------------------------------- // // Private methods // ---------------------------------------------------------------------- // constructor(tracer, name, spanContext) { super(); console.assert(typeof tracer === 'object', 'Invalid runtime'); // eslint-disable-line no-console this._tracerImp = tracer; this._ctx = spanContext; this._ended = false; this._operationName = name; this._tags = {}; this._beginMicros = tracer._platform.nowMicros(); this._endMicros = 0; this._errorFlag = false; this._log_records = null; } // ---------------------------------------------------------------------- // // LightStep Extensions // ---------------------------------------------------------------------- // getOperationName() { return this._operationName; } // Getter only. The GUID is immutable once set internally. guid() { return this._ctx._guid; } traceGUID() { return this._ctx._traceGUID; } parentGUID() { return this._tags.parent_span_guid; } setParentGUID(guid) { this._tags.parent_span_guid = coerce.toString(guid); return this; } beginMicros() { return this._beginMicros; } setBeginMicros(micros) { this._beginMicros = micros; return this; } endMicros() { return this._endMicros; } setEndMicros(micros) { this._endMicros = micros; return this; } isSampled() { return this._ctx._sampled; } /** * Returns a URL to the trace containing this span. * * Unlike most methods, it *is* safe to call this method after `finish()`. * * @return {string} the absolute URL for the span */ generateTraceURL() { let micros; if (this._beginMicros > 0 && this._endMicros > 0) { micros = Math.floor((this._beginMicros + this._endMicros) / 2); } else { micros = this._tracerImp._platform.nowMicros(); } let urlPrefix = constants.LIGHTSTEP_APP_URL_PREFIX; let accessToken = encodeURIComponent(this._tracerImp.options().access_token); let guid = encodeURIComponent(this.guid()); return `${urlPrefix}/${accessToken}/trace?span_guid=${guid}&at_micros=${micros}`; } getTags() { return this._tags; } /** * Finishes the span. * * @param {Number} finishTime * Optional Unix timestamp in milliseconds setting an explicit * finish time for the span. */ end(finishTime) { // Ensure a single span is not recorded multiple times if (this._ended) { return; } this._ended = true; if (finishTime !== undefined) { this.setEndMicros(Math.floor(finishTime * 1000)); } // Do not set endMicros if it has already been set. This accounts for // the case of a span that has had it's times set manually (i.e. allows // for retroactively created spans that might not be possible to create // in real-time). if (this._endMicros === 0) { this.setEndMicros(this._tracerImp._platform.nowMicros()); } if (util.shouldSendMetaSpan(this._tracer().options(), this.getTags())) { this._tracerImp.startSpan(constants.LS_META_SP_FINISH, { tags : { [constants.LS_META_EVENT_KEY] : true, [constants.LS_META_TRACE_KEY] : this.traceGUID(), [constants.LS_META_SPAN_KEY] : this.guid(), }, }).finish(); } // Only record span if sampled if (this.isSampled()) { this._tracerImp._addSpanRecord(this); } } _toThrift() { let attributes = []; _each(this._tags, (value, key) => { // eslint-disable-next-line camelcase attributes.push(new crouton_thrift.KeyValue({ Key : coerce.toString(key), Value : coerce.toString(value), })); }); let logs = []; _each(this._log_records, (logRecord) => { let logThrift = logRecord.toThrift(); this._tracerImp._counters['logs.keys.over_limit'] += logRecord.getNumKeysOverLimit(); this._tracerImp._counters['logs.values.over_limit'] += logRecord.getNumValuesOverLimit(); logs.push(logThrift); }); // eslint-disable-next-line camelcase return new crouton_thrift.SpanRecord({ span_guid : this.guid(), trace_guid : this.traceGUID(), runtime_guid : this._tracerImp.guid(), span_name : this._operationName, oldest_micros : this._beginMicros, youngest_micros : this._endMicros, attributes : attributes, error_flag : this._errorFlag, log_records : logs, }); } }