UNPKG

@grafana/faro-transport-otlp-http

Version:

Faro transport which converts the Faro data model to the Otlp data model.

165 lines 8.27 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OtlpHttpTransport = void 0; var faro_core_1 = require("@grafana/faro-core"); var payload_1 = require("./payload"); var DEFAULT_BUFFER_SIZE = 30; var DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17 var DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000; var BEACON_BODY_SIZE_LIMIT = 60000; var TOO_MANY_REQUESTS = 429; var OtlpHttpTransport = /** @class */ (function (_super) { __extends(OtlpHttpTransport, _super); function OtlpHttpTransport(options) { var _a, _b, _c; var _this = _super.call(this) || this; _this.options = options; _this.name = '@grafana/faro-web-sdk:transport-otlp-http'; _this.version = faro_core_1.VERSION; _this.sendingTracesDisabledUntil = new Date(); _this.sendingLogsDisabledUntil = new Date(); _this.rateLimitBackoffMs = (_a = options.defaultRateLimitBackoffMs) !== null && _a !== void 0 ? _a : DEFAULT_RATE_LIMIT_BACKOFF_MS; _this.promiseBuffer = (0, faro_core_1.createPromiseBuffer)({ size: (_b = options === null || options === void 0 ? void 0 : options.bufferSize) !== null && _b !== void 0 ? _b : DEFAULT_BUFFER_SIZE, concurrency: (_c = options === null || options === void 0 ? void 0 : options.concurrency) !== null && _c !== void 0 ? _c : DEFAULT_CONCURRENCY, }); return _this; } OtlpHttpTransport.prototype.getIgnoreUrls = function () { var _a; var _b = this.options, _c = _b.tracesURL, tracesURL = _c === void 0 ? '' : _c, _d = _b.logsURL, logsURL = _d === void 0 ? '' : _d; return [tracesURL, logsURL].filter(Boolean).concat((_a = this.config.ignoreUrls) !== null && _a !== void 0 ? _a : []); }; OtlpHttpTransport.prototype.isBatched = function () { return true; }; OtlpHttpTransport.prototype.send = function (items) { var otelPayload = new payload_1.OtelPayload({ internalLogger: this.internalLogger, customOtlpTransform: this.options.otlpTransform, }); items.forEach(function (item) { return otelPayload.addResourceItem(item); }); this.sendPayload(otelPayload.getPayload()); }; OtlpHttpTransport.prototype.sendPayload = function (payload) { var _this = this; try { var _a = this.options, _b = _a.tracesURL, tracesURL = _b === void 0 ? '' : _b, _c = _a.logsURL, logsURL = _c === void 0 ? '' : _c; var _loop_1 = function (key, value) { var _f; if (!((0, faro_core_1.isArray)(value) && value.length > 0)) { return "continue"; } var disabledUntil; var updateDisabledUntil = function (_) { }; var url = ''; switch (key) { case 'resourceSpans': url = tracesURL; disabledUntil = this_1.sendingTracesDisabledUntil; updateDisabledUntil = function (retryAfterDate) { _this.sendingTracesDisabledUntil = retryAfterDate; }; break; case 'resourceLogs': url = logsURL; disabledUntil = this_1.sendingLogsDisabledUntil; updateDisabledUntil = function (retryAfterDate) { _this.sendingLogsDisabledUntil = retryAfterDate; }; break; } if (disabledUntil && disabledUntil > new Date(Date.now())) { this_1.logWarn("Dropping transport item due to too many requests. Backoff until ".concat(disabledUntil)); return { value: undefined }; } var body = JSON.stringify((_f = {}, _f[key] = value, _f)); var _g = this_1.options, requestOptions = _g.requestOptions, apiKey = _g.apiKey; var _h = requestOptions !== null && requestOptions !== void 0 ? requestOptions : {}, headers = _h.headers, restOfRequestOptions = __rest(_h, ["headers"]); if (!url) { return "continue"; } this_1.promiseBuffer.add(function () { return fetch(url, __assign({ method: 'POST', headers: __assign(__assign({ 'Content-Type': 'application/json' }, (headers !== null && headers !== void 0 ? headers : {})), (apiKey ? { 'x-api-key': apiKey } : {})), body: body, keepalive: body.length <= BEACON_BODY_SIZE_LIMIT }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {}))) .then(function (response) { if (response.status === TOO_MANY_REQUESTS) { updateDisabledUntil(_this.getRetryAfterDate(response)); _this.logWarn("Too many requests, backing off until ".concat(disabledUntil)); } // read the body so the connection can be closed response.text().catch(faro_core_1.noop); return response; }) .catch(function (error) { _this.logError('Failed sending payload to the receiver\n', JSON.parse(body), error); }); }); }; var this_1 = this; for (var _i = 0, _d = Object.entries(payload); _i < _d.length; _i++) { var _e = _d[_i], key = _e[0], value = _e[1]; var state_1 = _loop_1(key, value); if (typeof state_1 === "object") return state_1.value; } } catch (error) { this.logError(error); } }; OtlpHttpTransport.prototype.getRetryAfterDate = function (response) { var now = Date.now(); var retryAfterHeader = response.headers.get('Retry-After'); if (retryAfterHeader) { var delay = Number(retryAfterHeader); if (!isNaN(delay)) { return new Date(delay * 1000 + now); } var date = Date.parse(retryAfterHeader); if (!isNaN(date)) { return new Date(date); } } return new Date(now + this.rateLimitBackoffMs); }; return OtlpHttpTransport; }(faro_core_1.BaseTransport)); exports.OtlpHttpTransport = OtlpHttpTransport; //# sourceMappingURL=transport.js.map