@coralogix/browser
Version:
Official Coralogix SDK for browsers
1,193 lines (1,148 loc) • 214 kB
JavaScript
import { __assign, __extends, __awaiter, __generator, __read as __read$1, __spreadArray, __rest, __values as __values$1 } from 'tslib';
import { SamplingDecision, AlwaysOnSampler, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { getElementXPath, WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { InstrumentationBase, registerInstrumentations } from '@opentelemetry/instrumentation';
import ErrorStackParser from 'error-stack-parser';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
import { onFID, onCLS, onLCP, onFCP, onINP, onTTFB } from 'web-vitals/attribution';
import { createContextKey, baggageEntryMetadataFromString, propagation, diag, trace, isSpanContextValid, TraceFlags, context } from '@opentelemetry/api';
import { B3Propagator, B3InjectEncoding } from '@opentelemetry/propagator-b3';
import { AWSXRayPropagator } from '@opentelemetry/propagator-aws-xray';
function isString(value) {
return typeof value === 'string';
}
function isRegExp(value) {
return value instanceof RegExp;
}
function isMatchingPattern(value, pattern, requireExactStringMatch) {
if (requireExactStringMatch === undefined) { requireExactStringMatch = false; }
if (!isString(value)) {
return false;
}
if (isRegExp(pattern)) {
return pattern.test(value);
}
if (isString(pattern)) {
return requireExactStringMatch
? value === pattern
: value.includes(pattern);
}
return false;
}
function stringMatchesSomePattern(testString, patterns, requireExactStringMatch) {
if (patterns === undefined) { patterns = []; }
if (requireExactStringMatch === undefined) { requireExactStringMatch = false; }
return patterns.some(function (pattern) {
return isMatchingPattern(testString, pattern, requireExactStringMatch);
});
}
/**
* UUID v4
* https://gist.github.com/jed/982883
*/
function generateUUID(placeholder) {
return placeholder
? (+placeholder ^ ((Math.random() * 16) >> (+placeholder / 4))).toString(16)
: "".concat(1e7, "-").concat(1e3, "-").concat(4e3, "-").concat(8e3, "-").concat(1e11).replace(/[018]/g, generateUUID);
}
function isFunction (funktion) {
return typeof funktion === 'function'
}
// Default to complaining loudly when things don't go according to plan.
var logger = console.error.bind(console);
// Sets a property on an object, preserving its enumerability.
// This function assumes that the property is already writable.
function defineProperty (obj, name, value) {
var enumerable = !!obj[name] && obj.propertyIsEnumerable(name);
Object.defineProperty(obj, name, {
configurable: true,
enumerable: enumerable,
writable: true,
value: value
});
}
// Keep initialization idempotent.
function shimmer (options) {
if (options && options.logger) {
if (!isFunction(options.logger)) logger("new logger isn't a function, not replacing");
else logger = options.logger;
}
}
function wrap (nodule, name, wrapper) {
if (!nodule || !nodule[name]) {
logger('no original function ' + name + ' to wrap');
return
}
if (!wrapper) {
logger('no wrapper function');
logger((new Error()).stack);
return
}
if (!isFunction(nodule[name]) || !isFunction(wrapper)) {
logger('original object and wrapper must be functions');
return
}
var original = nodule[name];
var wrapped = wrapper(original, name);
defineProperty(wrapped, '__original', original);
defineProperty(wrapped, '__unwrap', function () {
if (nodule[name] === wrapped) defineProperty(nodule, name, original);
});
defineProperty(wrapped, '__wrapped', true);
defineProperty(nodule, name, wrapped);
return wrapped
}
function massWrap (nodules, names, wrapper) {
if (!nodules) {
logger('must provide one or more modules to patch');
logger((new Error()).stack);
return
} else if (!Array.isArray(nodules)) {
nodules = [nodules];
}
if (!(names && Array.isArray(names))) {
logger('must provide one or more functions to wrap on modules');
return
}
nodules.forEach(function (nodule) {
names.forEach(function (name) {
wrap(nodule, name, wrapper);
});
});
}
function unwrap (nodule, name) {
if (!nodule || !nodule[name]) {
logger('no function to unwrap.');
logger((new Error()).stack);
return
}
if (!nodule[name].__unwrap) {
logger('no original to unwrap to -- has ' + name + ' already been unwrapped?');
} else {
return nodule[name].__unwrap()
}
}
function massUnwrap (nodules, names) {
if (!nodules) {
logger('must provide one or more modules to patch');
logger((new Error()).stack);
return
} else if (!Array.isArray(nodules)) {
nodules = [nodules];
}
if (!(names && Array.isArray(names))) {
logger('must provide one or more functions to unwrap on modules');
return
}
nodules.forEach(function (nodule) {
names.forEach(function (name) {
unwrap(nodule, name);
});
});
}
shimmer.wrap = wrap;
shimmer.massWrap = massWrap;
shimmer.unwrap = unwrap;
shimmer.massUnwrap = massUnwrap;
var shimmer_1 = shimmer;
var CoralogixEventType;
(function (CoralogixEventType) {
CoralogixEventType["ERROR"] = "error";
CoralogixEventType["NETWORK_REQUEST"] = "network-request";
CoralogixEventType["LOG"] = "log";
CoralogixEventType["USER_INTERACTION"] = "user-interaction";
CoralogixEventType["WEB_VITALS"] = "web-vitals";
CoralogixEventType["LONG_TASK"] = "longtask";
CoralogixEventType["RESOURCES"] = "resources";
CoralogixEventType["INTERNAL"] = "internal";
CoralogixEventType["DOM"] = "dom";
CoralogixEventType["CUSTOM_MEASUREMENT"] = "custom-measurement";
CoralogixEventType["MEMORY_USAGE"] = "memory-usage";
CoralogixEventType["SCREENSHOT"] = "screenshot";
CoralogixEventType["CUSTOM_SPAN"] = "custom-span";
})(CoralogixEventType || (CoralogixEventType = {}));
var PerformanceTypes;
(function (PerformanceTypes) {
PerformanceTypes["Resource"] = "resource";
PerformanceTypes["LongTask"] = "longtask";
PerformanceTypes["Navigation"] = "navigation";
PerformanceTypes["SoftNavigation"] = "soft-navigation";
})(PerformanceTypes || (PerformanceTypes = {}));
var OtelNetworkAttrs;
(function (OtelNetworkAttrs) {
OtelNetworkAttrs["METHOD"] = "http.method";
OtelNetworkAttrs["URL"] = "http.url";
OtelNetworkAttrs["STATUS_CODE"] = "http.status_code";
OtelNetworkAttrs["HOST"] = "http.host";
OtelNetworkAttrs["SCHEME"] = "http.scheme";
OtelNetworkAttrs["STATUS_TEXT"] = "http.status_text";
OtelNetworkAttrs["RESPONSE_CONTENT_LENGTH"] = "http.response_content_length";
})(OtelNetworkAttrs || (OtelNetworkAttrs = {}));
var UrlType;
(function (UrlType) {
UrlType["PAGE"] = "page";
UrlType["NETWORK_REQUEST"] = "network_request";
})(UrlType || (UrlType = {}));
var CoralogixLogSeverity;
(function (CoralogixLogSeverity) {
CoralogixLogSeverity[CoralogixLogSeverity["Debug"] = 1] = "Debug";
CoralogixLogSeverity[CoralogixLogSeverity["Verbose"] = 2] = "Verbose";
CoralogixLogSeverity[CoralogixLogSeverity["Info"] = 3] = "Info";
CoralogixLogSeverity[CoralogixLogSeverity["Warn"] = 4] = "Warn";
CoralogixLogSeverity[CoralogixLogSeverity["Error"] = 5] = "Error";
CoralogixLogSeverity[CoralogixLogSeverity["Critical"] = 6] = "Critical";
})(CoralogixLogSeverity || (CoralogixLogSeverity = {}));
var millisecondsPerSecond = 1000;
var millisecondsPerMinute = millisecondsPerSecond * 60;
var MILLISECONDS_PER_HOUR = millisecondsPerMinute * 60;
function getNowTime() {
return new Date().getTime();
}
var MAX_BATCH_TIME_MS = 10000; //10s
var SESSION_RECORDING_DEFAULT_HEADERS = {
'Content-Encoding': 'gzip',
};
var SESSION_RECORDING_DEFAULT_ERROR_MESSAGE = 'Coralogix Browser SDK - Recording is not supported on this platform';
var SESSION_RECORDING_NETWORK_ERR0R_MESSAGE = 'Coralogix Browser SDK - Error while sending record';
var BATCH_TIME_DELAY = 1000;
var SESSION_RECORDING_POSTFIX_URL = '/browser/alpha/sessionrecording';
var SESSION_KEY = 'rum_session';
var PREV_SESSION_KEY = 'rum_prev_session';
var MAX_MUTATIONS_FOR_SESSION_RECORDING = 5000;
var DEFAULT_SESSION_CONFIG = {
sessionSampleRate: 100,
onlyWithErrorConfig: {
enable: false,
},
};
var SESSION_IDLE_TIME = 15 * millisecondsPerMinute;
var SESSION_EXPIRATION_TIME = MILLISECONDS_PER_HOUR;
var SESSION_MANAGER_KEY = 'rumSessionManager';
var SESSION_RECORDER_KEY = 'rumSessionRecorder';
var SESSION_RECORDER_SEGMENTS_MAP = 'rumSessionRecorderSegmentsMap';
var SNAPSHOT_MANAGER_KEY = 'rumSnapshotManager';
var INITIAL_SNAPSHOT_CONTEXT = {
errorCount: 0,
viewCount: 0,
actionCount: 0,
hasRecording: false,
hasScreenshot: false,
};
function getCxGlobal() {
if (typeof globalThis === 'object') {
return globalThis;
}
Object.defineProperty(Object.prototype, '__cx_global__', {
get: function () {
return this;
},
configurable: true,
});
var globalObject = __cx_global__;
delete Object.prototype.__cx_global__;
if (typeof globalObject !== 'object') {
if (typeof self === 'object') {
globalObject = self;
}
else if (typeof window === 'object') {
globalObject = window;
}
else {
globalObject = {};
}
}
return globalObject;
}
var CxGlobal = getCxGlobal();
function getSnapshotManager() {
return CxGlobal[SNAPSHOT_MANAGER_KEY];
}
function getSessionManager() {
return CxGlobal[SESSION_MANAGER_KEY];
}
function getSessionRecorder() {
return CxGlobal[SESSION_RECORDER_KEY];
}
function getSdkConfig() {
return CxGlobal[SDK_CONFIG_KEY];
}
var GLOBAL_SPAN_KEY = '__globalSpan__';
var CUSTOM_TRACER_KEY = '__customTracer__';
var CUSTOM_TRACER_IGNORED_INSTRUMENTS = '__customTracerIgnoredInstruments__';
function setGlobalSpan(globalSpan) {
CxGlobal[GLOBAL_SPAN_KEY] = globalSpan;
}
function getGlobalSpan() {
return CxGlobal[GLOBAL_SPAN_KEY];
}
function clearGlobalSpan() {
delete CxGlobal[GLOBAL_SPAN_KEY];
}
function setCustomTracer(customTracer) {
CxGlobal[CUSTOM_TRACER_KEY] = customTracer;
}
function getCustomTracer() {
return CxGlobal[CUSTOM_TRACER_KEY];
}
function setCustomTracerIgnoredInstruments(ignoredInstruments) {
CxGlobal[CUSTOM_TRACER_IGNORED_INSTRUMENTS] = ignoredInstruments;
}
function getCustomTracerIgnoredInstruments() {
return CxGlobal[CUSTOM_TRACER_IGNORED_INSTRUMENTS];
}
function shouldAttachSpanToGlobalSpan(instrumentationType) {
var _a;
return (getGlobalSpan() &&
!((_a = getCustomTracerIgnoredInstruments()) === null || _a === undefined ? undefined : _a.includes(instrumentationType)));
}
function attachChildSpanToGlobalSpan(name) {
var span;
var globalSpan = getGlobalSpan();
globalSpan.withContext(function () {
var childSpan = globalSpan.startCustomSpan(name);
span = childSpan.span;
});
return span;
}
var IS_OTEL_READY = 'otelReady';
var MAIN_TRACER_KEY = '@';
var ATTR_PROCESSOR_KEY = 'attrProcessor';
var SpanStatusCode;
(function (SpanStatusCode) {
/**
* The default status.
*/
SpanStatusCode[SpanStatusCode["UNSET"] = 0] = "UNSET";
/**
* The operation has been validated by an Application developer or
* Operator to have completed successfully.
*/
SpanStatusCode[SpanStatusCode["OK"] = 1] = "OK";
/**
* The operation contains an error.
*/
SpanStatusCode[SpanStatusCode["ERROR"] = 2] = "ERROR";
})(SpanStatusCode || (SpanStatusCode = {}));
function markSpanAsOtelToSend(span) {
span[IS_OTEL_READY] = true;
}
function shouldAddOtelAttr(span) {
return !!span[IS_OTEL_READY];
}
function setAttrProcessor(processor) {
CxGlobal[ATTR_PROCESSOR_KEY] = processor;
}
function getAttrProcessor() {
return CxGlobal[ATTR_PROCESSOR_KEY];
}
function setCustomLabelsForSpan(span, labels) {
if (labels === undefined) { labels = {}; }
span.setAttribute(CoralogixAttributes.CUSTOM_LABELS, JSON.stringify(getCustomMergedLabels(labels)));
}
function getCustomMergedLabels(labels) {
var _a;
if (labels === undefined) { labels = {}; }
var globalLabels = ((_a = getAttrProcessor()) === null || _a === undefined ? undefined : _a.getCustomLabels()) || {};
return __assign(__assign({}, globalLabels), labels);
}
var CACHED_METADATA_KEY = '__cx_metadata__';
var ERROR_INSTRUMENTATION_VERSION = '1';
var STACK_LIMIT = 4096;
var MESSAGE_LIMIT = 1024;
var ERROR_INSTRUMENTATION_NAME = 'errors';
var ErrorAttributes = {
TYPE: 'error_type',
STACK: 'error_stack',
MESSAGE: 'error_message',
DATA: 'error_custom_data',
};
var ErrorSource;
(function (ErrorSource) {
ErrorSource["CONSOLE"] = "console";
ErrorSource["WINDOW"] = "window";
ErrorSource["UNHANDLED_REJECTION"] = "unhandledrejection";
ErrorSource["DOCUMENT"] = "document";
ErrorSource["CAPTURED"] = "captured";
})(ErrorSource || (ErrorSource = {}));
function buildStacktrace(span, err) {
return __awaiter(this, undefined, undefined, function () {
var stack, message, name, hasStack, supportMfe, stackFrames;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
stack = err.stack, message = err.message, name = err.name;
hasStack = !!(stack === null || stack === undefined ? undefined : stack.includes('at '));
if (!(err && hasStack)) return [3 /*break*/, 3];
supportMfe = getSdkConfig().supportMfe;
stackFrames = ErrorStackParser.parse({
stack: stack.substring(0, STACK_LIMIT),
message: message,
name: name,
}).map(function (_a) {
var fileName = _a.fileName, columnNumber = _a.columnNumber, lineNumber = _a.lineNumber, functionName = _a.functionName;
return ({
fileName: fileName,
columnNumber: columnNumber,
lineNumber: lineNumber,
functionName: functionName,
});
});
if (!supportMfe) return [3 /*break*/, 2];
return [4 /*yield*/, handleMFE(stackFrames, span)];
case 1:
_a.sent();
_a.label = 2;
case 2:
span[ErrorAttributes.STACK] = stackFrames;
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
}
function handleMFE(stackFrames, span) {
return __awaiter(this, undefined, undefined, function () {
var i, metadata, _a, lastFrame;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
i = 0;
_b.label = 1;
case 1:
if (!(i < stackFrames.length)) return [3 /*break*/, 4];
return [4 /*yield*/, extractMetadataFromMfeStacktrace(stackFrames[i].fileName)];
case 2:
metadata = _b.sent();
stackFrames[i] = __assign(__assign({}, stackFrames[i]), (metadata || { isShell: true }));
_b.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4:
_a = __read$1(stackFrames, 1), lastFrame = _a[0];
addLabelForMFE(span, lastFrame);
return [2 /*return*/];
}
});
});
}
function addLabelForMFE(span, lastFrame) {
var app = lastFrame.app, version = lastFrame.version, isShell = lastFrame.isShell;
// Do not add label if its shell
if (!isShell) {
setCustomLabelsForSpan(span, { mfeApp: app, mfeVersion: version });
}
}
function extractMetadataFromMfeStacktrace() {
return __awaiter(this, arguments, undefined, function (fileName) {
var metadata, cachedMetadata, MFE_METADATA_KEY, _a, mfePath, response, _b, e_1;
if (fileName === undefined) { fileName = ''; }
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
cachedMetadata = CxGlobal[CACHED_METADATA_KEY];
MFE_METADATA_KEY = 'cx-metadata.json';
_a = __read$1(fileName.match(/https?:\/\/.*\//), 1), mfePath = _a[0];
if (!mfePath) return [3 /*break*/, 7];
response = undefined;
if (!!(cachedMetadata === null || cachedMetadata === undefined ? undefined : cachedMetadata.has(mfePath))) return [3 /*break*/, 6];
_c.label = 1;
case 1:
_c.trys.push([1, 4, , 5]);
return [4 /*yield*/, fetch("".concat(mfePath).concat(MFE_METADATA_KEY), {
//this is a browser cache control
cache: 'no-cache',
})];
case 2:
response = _c.sent();
_b = [{}];
return [4 /*yield*/, response.json()];
case 3:
metadata = __assign.apply(undefined, [__assign.apply(undefined, _b.concat([(_c.sent())])), { mfePath: mfePath }]);
return [3 /*break*/, 5];
case 4:
e_1 = _c.sent();
if (getSdkConfig().debug) {
console.warn('Coralogix Browser SDK - Error fetching metadata', e_1);
}
return [3 /*break*/, 5];
case 5:
CxGlobal[CACHED_METADATA_KEY] = cachedMetadata.set(mfePath, metadata);
return [3 /*break*/, 7];
case 6:
metadata = cachedMetadata === null || cachedMetadata === undefined ? undefined : cachedMetadata.get(mfePath);
_c.label = 7;
case 7: return [2 /*return*/, metadata];
}
});
});
}
var _consoleErrorHandler = function (that) {
return function (original) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
that.report(ErrorSource.CONSOLE, args);
return original.apply(that, args);
};
};
};
var _errorListener = function (that) {
return function (event) {
that.report(ErrorSource.WINDOW, event);
};
};
var _unhandledRejectionListener = function (that) {
return function (event) {
that.report(ErrorSource.UNHANDLED_REJECTION, event.reason);
};
};
var _documentErrorListener = function (that) {
return function (event) {
that.report(ErrorSource.DOCUMENT, event);
};
};
function addErrorDefaultAttributes(span) {
span.setAttribute(CoralogixAttributes.EVENT_TYPE, CoralogixEventType.ERROR);
span.setAttribute(CoralogixAttributes.SEVERITY, CoralogixLogSeverity.Error);
}
var CoralogixErrorInstrumentation = /** @class */ (function (_super) {
__extends(CoralogixErrorInstrumentation, _super);
function CoralogixErrorInstrumentation(config) {
var _this = _super.call(this, ERROR_INSTRUMENTATION_NAME, ERROR_INSTRUMENTATION_VERSION, config) || this;
_this.parseErrorObject = function (obj) {
var _a;
return (_a = obj === null || obj === undefined ? undefined : obj.message) !== null && _a !== undefined ? _a : JSON.stringify(obj, getCircularReplacer());
};
if (getSdkConfig().supportMfe) {
CxGlobal[CACHED_METADATA_KEY] = new Map();
}
return _this;
}
CoralogixErrorInstrumentation.prototype.init = function () { };
CoralogixErrorInstrumentation.prototype.enable = function () {
shimmer_1.wrap(console, 'error', _consoleErrorHandler(this));
CxGlobal.addEventListener('error', _errorListener(this));
CxGlobal.addEventListener('unhandledrejection', _unhandledRejectionListener(this));
document.documentElement.addEventListener('error', _documentErrorListener(this), {
capture: true,
});
};
CoralogixErrorInstrumentation.prototype.disable = function () {
shimmer_1.unwrap(console, 'error');
CxGlobal.removeEventListener('error', _errorListener(this));
CxGlobal.removeEventListener('unhandledrejection', _unhandledRejectionListener(this));
document.documentElement.removeEventListener('error', _documentErrorListener(this), { capture: true });
};
CoralogixErrorInstrumentation.prototype.report = function (source, arg) {
var _this = this;
if (arg instanceof Array) {
if (arg.length === 0) {
return;
}
}
switch (true) {
case arg instanceof Error:
this.reportError(source, arg);
break;
case arg instanceof ErrorEvent:
this.reportErrorEvent(source, arg);
break;
case arg instanceof Event:
this.reportEvent(source, arg);
break;
case typeof arg === 'string':
this.reportString(source, arg);
break;
case arg instanceof Array: {
// if any arguments are Errors then add the stack trace even though the message is handled differently
var firstError = arg.find(function (x) { return x instanceof Error; });
var message = arg
.map(function (msg) {
return typeof msg === 'string' ? msg : _this.parseErrorObject(msg);
})
.join(' ');
this.reportString(source, message, firstError);
break;
}
default:
this.reportString(source, typeof arg === 'string' ? arg : this.getPossibleEventMessage(arg));
}
};
CoralogixErrorInstrumentation.prototype.reportError = function (source, err, customData, labels) {
return __awaiter(this, undefined, undefined, function () {
var message, name, span, cleanMessage;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
message = err.message, name = err.name;
span = this.createSpan('error');
cleanMessage = message.split('\n')[0];
addErrorDefaultAttributes(span);
span.setAttribute(CoralogixAttributes.SOURCE, source);
span.setAttribute(ErrorAttributes.TYPE, name);
span.setAttribute(ErrorAttributes.MESSAGE, cleanMessage);
if (customData) {
span[ErrorAttributes.DATA] = JSON.stringify(customData, getCircularReplacer());
}
if (labels) {
setCustomLabelsForSpan(span, labels);
}
return [4 /*yield*/, buildStacktrace(span, err)];
case 1:
_a.sent();
span.end();
return [2 /*return*/];
}
});
});
};
CoralogixErrorInstrumentation.prototype.reportString = function (source, message, firstError) {
return __awaiter(this, undefined, undefined, function () {
var span;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
span = this.createSpan(source);
addErrorDefaultAttributes(span);
span.setAttribute(CoralogixAttributes.SOURCE, source);
span.setAttribute(ErrorAttributes.MESSAGE, message === null || message === undefined ? undefined : message.substring(0, MESSAGE_LIMIT));
if (!firstError) return [3 /*break*/, 2];
return [4 /*yield*/, buildStacktrace(span, firstError)];
case 1:
_a.sent();
_a.label = 2;
case 2:
span.end();
return [2 /*return*/];
}
});
});
};
CoralogixErrorInstrumentation.prototype.reportErrorEvent = function (source, _a) {
var error = _a.error, message = _a.message;
var event = error !== null && error !== undefined ? error : message;
this.report(source, event);
};
CoralogixErrorInstrumentation.prototype.reportEvent = function (source, ev) {
if (!ev.target) {
return;
}
var span = this.createSpan(source);
addErrorDefaultAttributes(span);
span.setAttribute(CoralogixAttributes.SOURCE, source);
if (ev.target) {
span.setAttribute('target_element', ev.target.tagName);
span.setAttribute('target_xpath', getElementXPath(ev.target, true));
span.setAttribute('target_src', ev.target.src);
}
span.end();
};
CoralogixErrorInstrumentation.prototype.createSpan = function (name) {
var span;
if (shouldAttachSpanToGlobalSpan(CoralogixEventType.ERROR)) {
span = attachChildSpanToGlobalSpan(name);
}
else {
span = this.tracer.startSpan(name);
}
return span;
};
CoralogixErrorInstrumentation.prototype.getPossibleEventMessage = function (event) {
var _a = event || {}, message = _a.message, statusMessage = _a.statusMessage;
if (message && typeof message === 'string') {
return message;
}
// GrpcStatusEvent
if (statusMessage && typeof statusMessage === 'string') {
return statusMessage;
}
return JSON.stringify(event);
};
return CoralogixErrorInstrumentation;
}(InstrumentationBase));
var propagateTraceHeaderCorsUrls = function (config) {
var _a;
var traceParentInHeader = config.traceParentInHeader;
var propagateCorsUrls = (_a = traceParentInHeader === null || traceParentInHeader === undefined ? undefined : traceParentInHeader.options) === null || _a === undefined ? undefined : _a.propagateTraceHeaderCorsUrls;
if ((traceParentInHeader === null || traceParentInHeader === undefined ? undefined : traceParentInHeader.enabled) && propagateCorsUrls) {
config.propagateTraceHeaderCorsUrls = propagateCorsUrls;
}
};
var NetworkDataManager = /** @class */ (function () {
function NetworkDataManager() {
var _this = this;
this.responseBodyParsers = new Map([
[MimeType.Json, function (body) { return __awaiter(_this, undefined, undefined, function () { var _a, _b; return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b = (_a = JSON).stringify;
return [4 /*yield*/, body.json()];
case 1: return [2 /*return*/, _b.apply(_a, [_c.sent()])];
}
}); }); }],
[MimeType.TextPlain, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, body.text()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }],
[MimeType.TextHtml, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, body.text()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }],
[MimeType.TextCss, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, body.text()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }],
[MimeType.TextJavascript, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, body.text()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }],
[MimeType.Xml, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, body.text()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }],
[MimeType.FormData, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, body.text()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }],
]);
this.requestBodySerializers = new Map([
[BodyType.String, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
return [2 /*return*/, body];
}); }); }],
[BodyType.Blob, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
return [2 /*return*/, body.text()];
}); }); }],
[
BodyType.FormData,
function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
return [2 /*return*/, this.serializeFormData(body)];
}); }); },
],
[
BodyType.URLSearchParams,
function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
return [2 /*return*/, body.toString()];
}); }); },
],
[BodyType.JsonObject, function (body) { return __awaiter(_this, undefined, undefined, function () { return __generator(this, function (_a) {
return [2 /*return*/, JSON.stringify(body)];
}); }); }],
]);
}
NetworkDataManager.prototype.resolveConfigForUrl = function (url, configs) {
if (configs === undefined) { configs = []; }
return configs.find(function (_a) {
var configUrl = _a.url;
return configUrl === url ||
(configUrl instanceof RegExp && configUrl.test(url));
});
};
NetworkDataManager.prototype.stringifyRequestBody = function (request) {
return __awaiter(this, undefined, undefined, function () {
var bodyContent;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(request === null || request === undefined ? undefined : request.body))
return [2 /*return*/, ''];
return [4 /*yield*/, this.serializeRequestBody(request.body)];
case 1:
bodyContent = _a.sent();
return [2 /*return*/, this.truncateIfExceedsLimit(bodyContent)];
}
});
});
};
NetworkDataManager.prototype.stringifyResponseBody = function (response) {
return __awaiter(this, undefined, undefined, function () {
var contentType, mimeType, parser, parsedContent;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
contentType = response.headers.get('content-type') || '';
mimeType = contentType.split(';')[0].trim();
parser = this.responseBodyParsers.get(mimeType);
if (!parser)
return [2 /*return*/, ''];
return [4 /*yield*/, parser(response)];
case 1:
parsedContent = _a.sent();
return [2 /*return*/, this.truncateIfExceedsLimit(parsedContent)];
}
});
});
};
NetworkDataManager.prototype.truncateIfExceedsLimit = function (content) {
return content.length > MAX_CHARACTERS ? undefined : content;
};
NetworkDataManager.prototype.serializeRequestBody = function (body) {
return __awaiter(this, undefined, undefined, function () {
var handler, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
handler = this.requestBodySerializers.get(body.constructor.name);
if (!handler) return [3 /*break*/, 2];
return [4 /*yield*/, handler(body)];
case 1:
_a = _b.sent();
return [3 /*break*/, 3];
case 2:
_a = '';
_b.label = 3;
case 3: return [2 /*return*/, _a];
}
});
});
};
NetworkDataManager.prototype.serializeFormData = function (formData) {
var result = '';
formData.forEach(function (value, key) {
result += "".concat(key, ": ").concat(value, "\n");
});
return result.trim();
};
return NetworkDataManager;
}());
var MimeType;
(function (MimeType) {
MimeType["Json"] = "application/json";
MimeType["TextPlain"] = "text/plain";
MimeType["TextHtml"] = "text/html";
MimeType["TextCss"] = "text/css";
MimeType["TextJavascript"] = "application/javascript";
MimeType["Xml"] = "application/xml";
MimeType["FormData"] = "multipart/form-data";
})(MimeType || (MimeType = {}));
var BodyType;
(function (BodyType) {
BodyType["String"] = "String";
BodyType["Blob"] = "Blob";
BodyType["FormData"] = "FormData";
BodyType["URLSearchParams"] = "URLSearchParams";
BodyType["JsonObject"] = "JsonObject";
BodyType["Unknown"] = "Unknown";
})(BodyType || (BodyType = {}));
var HeadersManager = /** @class */ (function () {
function HeadersManager() {
}
HeadersManager.prototype.filterHeaders = function (headersInit, allowedKeys) {
if (allowedKeys === undefined) { allowedKeys = []; }
if (!headersInit) {
return new Map();
}
var normalized = this.normalizeHeaders(headersInit);
var filteredHeaders = new Map();
allowedKeys.forEach(function (headerKey) {
var normalizedKey = headerKey.toLowerCase();
if (normalized.has(normalizedKey)) {
filteredHeaders.set(headerKey, normalized.get(normalizedKey));
}
});
return filteredHeaders;
};
HeadersManager.prototype.normalizeHeaders = function (headersInit) {
if (typeof headersInit === 'string') {
return this.normalizeHeadersFromString(headersInit);
}
var headers = new Headers(headersInit);
var headersMap = new Map();
headers.forEach(function (value, key) {
headersMap.set(key.toLowerCase(), value);
});
return headersMap;
};
HeadersManager.prototype.normalizeHeadersFromString = function (headersString) {
var headerMap = new Map();
if (!headersString) {
return headerMap;
}
var lines = headersString.trim().split(/\r\n/);
lines.forEach(function (line) {
var _a = __read$1(line.split(': ', 2), 2), key = _a[0], value = _a[1];
if (key && value) {
headerMap.set(key.trim().toLowerCase(), value.trim());
}
});
return headerMap;
};
return HeadersManager;
}());
var NetworkInstrumentationAttributes = {
REQUEST_HEADERS: 'request_headers',
RESPONSE_HEADERS: 'response_headers',
RESPONSE_PAYLOAD: 'response_payload',
REQUEST_PAYLOAD: 'request_payload',
};
function checkAttachingNetworkSpanToGlobalSpan(span) {
if (shouldAttachSpanToGlobalSpan(CoralogixEventType.NETWORK_REQUEST)) {
var globalSpan = getGlobalSpan();
var _a = globalSpan.span.spanContext(), traceId = _a.traceId, globalSpanId = _a.spanId;
span['_spanContext'].traceId = traceId;
span['parentSpanId'] = globalSpanId;
}
}
var FetchSource;
(function (FetchSource) {
FetchSource["FETCH"] = "fetch";
})(FetchSource || (FetchSource = {}));
var CoralogixFetchInstrumentation = /** @class */ (function (_super) {
__extends(CoralogixFetchInstrumentation, _super);
function CoralogixFetchInstrumentation(config) {
var _this = this;
propagateTraceHeaderCorsUrls(config);
config.applyCustomAttributesOnSpan = function (span, request, result) {
markSpanAsOtelToSend(span);
checkAttachingNetworkSpanToGlobalSpan(span);
_this.setNetworkSpanAttributes(span, request, result);
};
_this = _super.call(this, config) || this;
_this.networkDataManager = new NetworkDataManager();
_this.headersManager = new HeadersManager();
return _this;
}
CoralogixFetchInstrumentation.prototype.setNetworkSpanAttributes = function (span, request, response) {
return __awaiter(this, undefined, undefined, function () {
var status, networkExtraConfig, url, resolvedConfig;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
status = response.status;
networkExtraConfig = getSdkConfig().networkExtraConfig;
url = span.attributes['http.url'] ||
'';
resolvedConfig = this.networkDataManager.resolveConfigForUrl(url, networkExtraConfig);
if (!resolvedConfig) return [3 /*break*/, 3];
return [4 /*yield*/, this.setRequestAttributes(span, request, resolvedConfig)];
case 1:
_b.sent();
return [4 /*yield*/, this.setResponseAttributes(span, response, resolvedConfig)];
case 2:
_b.sent();
_b.label = 3;
case 3:
span.setAttributes((_a = {},
_a[CoralogixAttributes.SEVERITY] = isNetworkError(status)
? CoralogixLogSeverity.Error
: CoralogixLogSeverity.Info,
_a[CoralogixAttributes.EVENT_TYPE] = CoralogixEventType.NETWORK_REQUEST,
_a[CoralogixAttributes.SOURCE] = FetchSource.FETCH,
_a));
return [2 /*return*/];
}
});
});
};
CoralogixFetchInstrumentation.prototype.setRequestAttributes = function (span, request, networkExtraConfig) {
return __awaiter(this, undefined, undefined, function () {
var reqHeaders, collectReqPayload, requestPayload, _a, sanitizedHeaders, error_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
reqHeaders = networkExtraConfig.reqHeaders, collectReqPayload = networkExtraConfig.collectReqPayload;
_b.label = 1;
case 1:
_b.trys.push([1, 5, , 6]);
if (!collectReqPayload) return [3 /*break*/, 3];
return [4 /*yield*/, this.networkDataManager.stringifyRequestBody(request)];
case 2:
_a = _b.sent();
return [3 /*break*/, 4];
case 3:
_a = undefined;
_b.label = 4;
case 4:
requestPayload = _a;
sanitizedHeaders = (reqHeaders === null || reqHeaders === undefined ? undefined : reqHeaders.length)
? this.headersManager.filterHeaders(request.headers, reqHeaders)
: undefined;
if (requestPayload)
span[NetworkInstrumentationAttributes.REQUEST_PAYLOAD] = requestPayload;
if (sanitizedHeaders === null || sanitizedHeaders === undefined ? undefined : sanitizedHeaders.size) {
span[NetworkInstrumentationAttributes.REQUEST_HEADERS] =
Object.fromEntries(sanitizedHeaders);
}
return [3 /*break*/, 6];
case 5:
error_1 = _b.sent();
if (getSdkConfig().debug) {
console.debug('Error setting request attributes on span:', error_1);
}
return [3 /*break*/, 6];
case 6: return [2 /*return*/];
}
});
});
};
CoralogixFetchInstrumentation.prototype.setResponseAttributes = function (span, result, networkExtraConfig) {
return __awaiter(this, undefined, undefined, function () {
var resHeaders, collectResPayload, responsePayload, _a, sanitizedHeaders, error_2;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
resHeaders = networkExtraConfig.resHeaders, collectResPayload = networkExtraConfig.collectResPayload;
if (!(result instanceof Response)) return [3 /*break*/, 6];
_b.label = 1;
case 1:
_b.trys.push([1, 5, , 6]);
if (!collectResPayload) return [3 /*break*/, 3];
return [4 /*yield*/, this.networkDataManager.stringifyResponseBody(result)];
case 2:
_a = _b.sent();
return [3 /*break*/, 4];
case 3:
_a = undefined;
_b.label = 4;
case 4:
responsePayload = _a;
sanitizedHeaders = (resHeaders === null || resHeaders === undefined ? undefined : resHeaders.length)
? this.headersManager.filterHeaders(result.headers, resHeaders)
: undefined;
if (responsePayload) {
span[NetworkInstrumentationAttributes.RESPONSE_PAYLOAD] =
responsePayload;
}
if (sanitizedHeaders === null || sanitizedHeaders === undefined ? undefined : sanitizedHeaders.size) {
span[NetworkInstrumentationAttributes.RESPONSE_HEADERS] =
Object.fromEntries(sanitizedHeaders);
}
return [3 /*break*/, 6];
case 5:
error_2 = _b.sent();
if (getSdkConfig().debug) {
console.debug('Error setting request attributes on span:', error_2);
}
return [3 /*break*/, 6];
case 6: return [2 /*return*/];
}
});
});
};
return CoralogixFetchInstrumentation;
}(FetchInstrumentation));
var XHRSource;
(function (XHRSource) {
XHRSource["XHR"] = "xhr";
})(XHRSource || (XHRSource = {}));
var CoralogixXhrInstrumentation = /** @class */ (function (_super) {
__extends(CoralogixXhrInstrumentation, _super);
function CoralogixXhrInstrumentation(config) {
var _this = this;
propagateTraceHeaderCorsUrls(config);
config.applyCustomAttributesOnSpan = function (span, xhr) {
markSpanAsOtelToSend(span);
checkAttachingNetworkSpanToGlobalSpan(span);
_this.setNetworkSpanAttributes(span, xhr);
};
_this = _super.call(this, config) || this;
_this.networkDataManager = new NetworkDataManager();
_this.headersManager = new HeadersManager();
return _this;
}
CoralogixXhrInstrumentation.prototype.setNetworkSpanAttributes = function (span, xhr) {
var _a;
var status = xhr.status;
var networkExtraConfig = getSdkConfig().networkExtraConfig;
var resolvedConfig = this.networkDataManager.resolveConfigForUrl(xhr.responseURL, networkExtraConfig);
span.setAttributes((_a = {},
_a[CoralogixAttributes.SEVERITY] = isNetworkError(status)
? CoralogixLogSeverity.Error
: CoralogixLogSeverity.Info,
_a[CoralogixAttributes.EVENT_TYPE] = CoralogixEventType.NETWORK_REQUEST,
_a[CoralogixAttributes.SOURCE] = XHRSource.XHR,
_a));
if (resolvedConfig) {
this.setResponseAttributes(span, xhr, resolvedConfig);
}
};
CoralogixXhrInstrumentation.prototype.setResponseAttributes = function (span, xhr, resolvedConfig) {
var resHeaders = resolvedConfig.resHeaders, collectResPayload = resolvedConfig.collectResPayload;
var responsePayload = collectResPayload
? this.networkDataManager.truncateIfExceedsLimit(xhr.responseText)
: undefined;
var sanitizedHeaders = (resHeaders === null || resHeaders === undefined ? undefined : resHeaders.length)
? this.headersManager.filterHeaders(xhr.getAllResponseHeaders(), resHeaders)
: undefined;
if (responsePayload) {
span[NetworkInstrumentationAttributes.RESPONSE_PAYLOAD] = responsePayload;
}
if (sanitizedHeaders === null || sanitizedHeaders === undefined ? undefined : sanitizedHeaders.size) {
span[NetworkInstrumentationAttributes.RESPONSE_HEADERS] =
Object.fromEntries(sanitizedHeaders);
}
};
return CoralogixXhrInstrumentation;
}(XMLHttpRequestInstrumentation));
var CUSTOM_INSTRUMENTATION_VERSION = '1';
var LogSource;
(function (LogSource) {
LogSource["CODE"] = "code";
})(LogSource || (LogSource = {}));
var CoralogixCustomLogInstrumentation = /** @class */ (function (_super) {
__extends(CoralogixCustomLogInstrumentation, _super);
function CoralogixCustomLogInstrumentation(config) {
var _a;
var _this = _super.call(this, CoralogixEventType.LOG, CUSTOM_INSTRUMENTATION_VERSION, config) || this;
_this.stringifyCustomLogData = (_a = getSdkConfig()) === null || _a === undefined ? undefined : _a.stringifyCustomLogData;
return _this;
}
CoralogixCustomLogInstrumentation.prototype.init = function () { };
CoralogixCustomLogInstrumentation.prototype.disable = function () { };
CoralogixCustomLogInstrumentation.prototype.enable = function () { };
CoralogixCustomLogInstrumentation.prototype.log = function (_a) {
var severity = _a.severity, message = _a.message, data = _a.data, labels = _a.labels;
var span = this.tracer.startSpan(CoralogixEventType.LOG);
span.setAttribute(CoralogixAttributes.EVENT_TYPE, CoralogixEventType.LOG);
span.setAttribute(CoralogixAttributes.SOURCE, LogSource.CODE);
span.setAttribute(CoralogixAttributes.SEVERITY, severity);
span.setAttribute(CoralogixAttributes.LOG, JSON.stringify({
severity: severity,
message: message,
data: this.stringifyCustomLogData
? JSON.stringify(data, getCircularReplacer())
: data,
}));
if (labels) {
setCustomLabelsForSpan(span, labels);
}
span.end();
};
return CoralogixCustomLogInstrumentation;
}(InstrumentationBase));
/**
* Checks if value is null or undefined.
*
* @param value The value to check.
* @returns Returns true if value is null or undefined, else false.
*/
function isNil(value) {
return value == null;
}
/**
* Ensures a given value is converted into an array of elements.
*
* @template T - The type of the input value and the elements in the resulting array.
*
* @param value - The input value, which can be a single instance of type `T`, an array of instances of type `T`, or a Set of instances of type `T`.
*
* @returns An array of elements of type `T`. If the input is `null` or `undefined`, returns an empty array.
*/
function coerceArray(value) {
if (isNil(value))