splunk-events
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -10,2 +10,8 @@ # Changelog | ||
## [1.6.0] - 2021-04-07 | ||
### Added | ||
- Configuration `useExponentialBackoff`, `maxNumberOfRetries`, | ||
`exponentialBackoffLimit` to add an exponential backoff strategy | ||
to request retry. | ||
## [1.5.0] - 2021-03-26 | ||
@@ -12,0 +18,0 @@ ### Added |
/*! | ||
* splunk-events v1.5.0 | ||
* splunk-events v1.6.0 | ||
* Copyright (c) VTEX | ||
@@ -32,6 +32,49 @@ * Released under the MIT License. | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function debounce(func, wait) { | ||
if (wait === void 0) { wait = 100; } | ||
var timeout = null; | ||
var cancel = null; | ||
var debounced = function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
if (timeout) { | ||
@@ -41,3 +84,11 @@ clearTimeout(timeout); | ||
} | ||
timeout = setTimeout(func, wait); | ||
return new Promise(function (res, rej) { | ||
cancel = rej; | ||
timeout = setTimeout(function () { | ||
var maybePromise = func.apply(void 0, args); | ||
if (maybePromise != null) { | ||
maybePromise.then(res)["catch"](rej); | ||
} | ||
}, wait); | ||
}); | ||
}; | ||
@@ -49,2 +100,3 @@ debounced.clear = function () { | ||
clearTimeout(timeout); | ||
cancel === null || cancel === void 0 ? void 0 : cancel(); | ||
timeout = null; | ||
@@ -70,8 +122,26 @@ }; | ||
var DEFAULT_EXPONENTIAL_BACKOFF_LIMIT = 60000; | ||
var DEFAULT_DEBOUNCE_TIME = 2000; | ||
var SplunkEvents = /** @class */ (function () { | ||
function SplunkEvents() { | ||
function SplunkEvents(config) { | ||
var _this = this; | ||
this._requestImpl = fetchRequest; | ||
this.autoFlush = true; | ||
this.autoRetryFlush = true; | ||
this.debounceTime = DEFAULT_DEBOUNCE_TIME; | ||
this.debug = false; | ||
this.events = []; | ||
this.host = '-'; | ||
this.injectAdditionalInfo = false; | ||
this.injectTimestamp = false; | ||
this.isSendingEvents = false; | ||
this.path = '/services/collector/event'; | ||
this.pendingEvents = []; | ||
this.shouldParseEventData = true; | ||
this.source = 'log'; | ||
this.flushPending = false; | ||
this.useExponentialBackoff = false; | ||
this.exponentialBackoffLimit = DEFAULT_EXPONENTIAL_BACKOFF_LIMIT; | ||
this.isBackoffInProgress = false; | ||
this.maxNumberOfRetries = Infinity; | ||
/** | ||
@@ -101,3 +171,2 @@ * Logs an event to Splunk. | ||
this.logEvent = function (level, type, workflowType, workflowInstance, eventData, account) { | ||
var _a; | ||
if (account === void 0) { account = ''; } | ||
@@ -116,6 +185,18 @@ _this.validateEvent(eventData); | ||
if (_this.autoFlush) { | ||
(_a = _this.debouncedFlush) === null || _a === void 0 ? void 0 : _a.call(_this); | ||
_this.flushEvents(); | ||
} | ||
}; | ||
/** | ||
* Internal flush that contains the logic for debouncing or | ||
* backing off exponentially. | ||
*/ | ||
this.flushEvents = function () { | ||
if (_this.useExponentialBackoff) { | ||
_this._backoffFlush(); | ||
} | ||
else { | ||
_this.debouncedFlush(); | ||
} | ||
}; | ||
/** | ||
* Flushes pending events into one single request. | ||
@@ -126,4 +207,67 @@ * | ||
*/ | ||
this.flush = function () { | ||
var _a; | ||
this.flush = function (events) { | ||
if (events === void 0) { events = _this.events; } | ||
return __awaiter(_this, void 0, void 0, function () { | ||
var splunkBatchedFormattedEvents; | ||
var _this = this; | ||
var _a; | ||
return __generator(this, function (_b) { | ||
this.validateConfig(); | ||
if (events.length === 0) { | ||
return [2 /*return*/]; | ||
} | ||
if (this.debug) { | ||
console.log("sending " + events.length + " events to splunk"); | ||
} | ||
splunkBatchedFormattedEvents = this.formatEventsForSplunkBatch(events); | ||
return [2 /*return*/, this.request({ | ||
url: "" + this.endpoint + this.path, | ||
method: 'POST', | ||
data: splunkBatchedFormattedEvents, | ||
headers: (_a = this.headers) !== null && _a !== void 0 ? _a : {}, | ||
responseType: 'json', | ||
}) | ||
.then(function () { | ||
if (_this.debug) { | ||
console.log(events.length + " events successfuly sent to splunk"); | ||
} | ||
})["catch"](function (e) { | ||
if (_this.debug) { | ||
console.warn('Error sending events to splunk.', e); | ||
} | ||
throw e; | ||
})]; | ||
}); | ||
}); | ||
}; | ||
this._backoffFlush = function () { | ||
if (_this.isBackoffInProgress) { | ||
return; | ||
} | ||
_this.isBackoffInProgress = true; | ||
var backoffMultiplier = 2; | ||
var executeFlush = function (depth) { | ||
if (depth === void 0) { depth = 0; } | ||
return _this.flush() | ||
.then(function () { | ||
_this.events = []; | ||
_this.isBackoffInProgress = false; | ||
})["catch"](function () { | ||
var waitTime = Math.pow(backoffMultiplier, depth) * 1000; | ||
if (depth > _this.maxNumberOfRetries) { | ||
_this.events = []; | ||
_this.isBackoffInProgress = false; | ||
return; | ||
} | ||
return new Promise(function (resolve, reject) { | ||
setTimeout(function () { | ||
executeFlush(depth + 1) | ||
.then(resolve, reject)["catch"](reject); | ||
}, Math.min(waitTime, _this.exponentialBackoffLimit)); | ||
}); | ||
}); | ||
}; | ||
return executeFlush(); | ||
}; | ||
this._debouncedFlush = function () { | ||
if (_this.isSendingEvents) { | ||
@@ -133,32 +277,15 @@ _this.flushPending = true; | ||
} | ||
_this.validateConfig(); | ||
_this.pendingEvents = Array.from(_this.events); | ||
_this.events = []; | ||
_this.isSendingEvents = true; | ||
if (_this.debug) { | ||
console.log("sending " + _this.pendingEvents.length + " events to splunk"); | ||
} | ||
if (_this.pendingEvents.length === 0) { | ||
return; | ||
} | ||
var splunkBatchedFormattedEvents = _this.formatEventsForSplunkBatch(_this.pendingEvents); | ||
_this.request({ | ||
url: "" + _this.endpoint + _this.path, | ||
method: 'POST', | ||
data: splunkBatchedFormattedEvents, | ||
headers: (_a = _this.headers) !== null && _a !== void 0 ? _a : {}, | ||
responseType: 'json', | ||
}) | ||
_this.flush(_this.pendingEvents) | ||
.then(function () { | ||
if (_this.debug) { | ||
console.log(_this.pendingEvents.length + " events successfuly sent to splunk"); | ||
} | ||
_this.pendingEvents = []; | ||
_this.isSendingEvents = false; | ||
if (_this.flushPending) { | ||
_this.flushPending = false; | ||
return _this.flush(); | ||
if (!_this.flushPending) { | ||
return; | ||
} | ||
})["catch"](function (e) { | ||
var _a; | ||
_this.flushPending = false; | ||
return _this._debouncedFlush(); | ||
})["catch"](function () { | ||
_this.events = _this.events.concat(_this.pendingEvents); | ||
@@ -168,12 +295,10 @@ _this.pendingEvents = []; | ||
if (_this.autoRetryFlush) { | ||
if (_this.debug) { | ||
console.warn('Error sending events to splunk. Retrying in 5 seconds.', e); | ||
} | ||
(_a = _this.debouncedFlush) === null || _a === void 0 ? void 0 : _a.call(_this); | ||
_this.flushEvents(); | ||
} | ||
else if (_this.debug) { | ||
console.warn('Error sending events to splunk.', e); | ||
} | ||
}); | ||
}; | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime); | ||
if (config) { | ||
this.config(config); | ||
} | ||
} | ||
@@ -184,23 +309,33 @@ /** | ||
SplunkEvents.prototype.config = function (config) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; | ||
this.events = this.events || []; | ||
this.pendingEvents = this.pendingEvents || []; | ||
this.isSendingEvents = (_a = this.isSendingEvents) !== null && _a !== void 0 ? _a : false; | ||
this.endpoint = config.endpoint; // required | ||
this.token = config.token; // required | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; | ||
this.endpoint = (_a = config === null || config === void 0 ? void 0 : config.endpoint) !== null && _a !== void 0 ? _a : this.endpoint; // required | ||
this.token = (_b = config === null || config === void 0 ? void 0 : config.token) !== null && _b !== void 0 ? _b : this.endpoint; // required | ||
this.injectAdditionalInfo = | ||
(_c = (_b = config.injectAditionalInfo) !== null && _b !== void 0 ? _b : config.injectAdditionalInfo) !== null && _c !== void 0 ? _c : false; | ||
this.autoFlush = (_d = config.autoFlush) !== null && _d !== void 0 ? _d : true; | ||
this.autoRetryFlush = (_e = config.autoRetryFlush) !== null && _e !== void 0 ? _e : true; | ||
this.source = (_f = config.source) !== null && _f !== void 0 ? _f : 'log'; | ||
this.path = (_g = config.path) !== null && _g !== void 0 ? _g : '/services/collector/event'; | ||
this.host = (_h = config.host) !== null && _h !== void 0 ? _h : '-'; | ||
this.debug = (_j = config.debug) !== null && _j !== void 0 ? _j : false; | ||
this.debounceTime = (_l = (_k = config.debounceTime) !== null && _k !== void 0 ? _k : this.debounceTime) !== null && _l !== void 0 ? _l : 2000; | ||
this.debouncedFlush = | ||
(_m = this.debouncedFlush) !== null && _m !== void 0 ? _m : debounce(this.flush, this.debounceTime); | ||
this._requestImpl = (_p = (_o = config.request) !== null && _o !== void 0 ? _o : this._requestImpl) !== null && _p !== void 0 ? _p : fetchRequest; | ||
this.injectTimestamp = (_q = config.injectTimestamp) !== null && _q !== void 0 ? _q : false; | ||
this.shouldParseEventData = (_r = config.shouldParseEventData) !== null && _r !== void 0 ? _r : true; | ||
this.headers = __assign({ Authorization: "Splunk " + this.token, 'Content-Type': 'application/json' }, config.headers); | ||
(_d = (_c = config === null || config === void 0 ? void 0 : config.injectAditionalInfo) !== null && _c !== void 0 ? _c : config === null || config === void 0 ? void 0 : config.injectAdditionalInfo) !== null && _d !== void 0 ? _d : this.injectAdditionalInfo; | ||
this.useExponentialBackoff = | ||
(_e = config === null || config === void 0 ? void 0 : config.useExponentialBackoff) !== null && _e !== void 0 ? _e : this.useExponentialBackoff; | ||
this.exponentialBackoffLimit = | ||
(_f = config === null || config === void 0 ? void 0 : config.exponentialBackoffLimit) !== null && _f !== void 0 ? _f : this.exponentialBackoffLimit; | ||
this.autoFlush = this.useExponentialBackoff | ||
? // should always be true when using exponential backoff strategy | ||
true | ||
: (_g = config === null || config === void 0 ? void 0 : config.autoFlush) !== null && _g !== void 0 ? _g : this.autoFlush; | ||
this.autoRetryFlush = (_h = config === null || config === void 0 ? void 0 : config.autoRetryFlush) !== null && _h !== void 0 ? _h : this.autoRetryFlush; | ||
this.source = (_j = config === null || config === void 0 ? void 0 : config.source) !== null && _j !== void 0 ? _j : this.source; | ||
this.path = (_k = config === null || config === void 0 ? void 0 : config.path) !== null && _k !== void 0 ? _k : this.path; | ||
this.host = (_l = config === null || config === void 0 ? void 0 : config.host) !== null && _l !== void 0 ? _l : this.host; | ||
this.debug = (_m = config === null || config === void 0 ? void 0 : config.debug) !== null && _m !== void 0 ? _m : this.debug; | ||
var prevDebounceTime = this.debounceTime; | ||
this.debounceTime = (_o = config === null || config === void 0 ? void 0 : config.debounceTime) !== null && _o !== void 0 ? _o : this.debounceTime; | ||
if (this.debounceTime !== prevDebounceTime) { | ||
this.debouncedFlush.clear(); | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime); | ||
} | ||
this._requestImpl = (_p = config === null || config === void 0 ? void 0 : config.request) !== null && _p !== void 0 ? _p : this._requestImpl; | ||
this.injectTimestamp = (_q = config === null || config === void 0 ? void 0 : config.injectTimestamp) !== null && _q !== void 0 ? _q : this.injectTimestamp; | ||
this.shouldParseEventData = | ||
(_r = config === null || config === void 0 ? void 0 : config.shouldParseEventData) !== null && _r !== void 0 ? _r : this.shouldParseEventData; | ||
this.maxNumberOfRetries = | ||
(_s = config === null || config === void 0 ? void 0 : config.maxNumberOfRetries) !== null && _s !== void 0 ? _s : this.maxNumberOfRetries; | ||
this.headers = __assign({ Authorization: "Splunk " + this.token, 'Content-Type': 'application/json' }, ((_t = config === null || config === void 0 ? void 0 : config.headers) !== null && _t !== void 0 ? _t : {})); | ||
}; | ||
@@ -225,2 +360,3 @@ /** | ||
case 'boolean': | ||
// eslint-disable-next-line no-fallthrough | ||
case 'number': | ||
@@ -261,21 +397,11 @@ parsedEvent += key + "=" + value + " "; | ||
SplunkEvents.prototype.formatEventsForSplunkBatch = function (events) { | ||
var splunkBatchedFormattedEvents = ''; | ||
for (var i = 0; i < events.length; i++) { | ||
splunkBatchedFormattedEvents += "\n" + JSON.stringify(events[i]) + "\n"; | ||
} | ||
return splunkBatchedFormattedEvents; | ||
return events.map(function (event) { return JSON.stringify(event); }).join('\n'); | ||
}; | ||
SplunkEvents.prototype.validateConfig = function () { | ||
if (this.token === null) { | ||
throw new Error('Token must not be null'); | ||
if (this.token == null) { | ||
throw new Error('Token must not be null nor undefined'); | ||
} | ||
if (this.token === undefined) { | ||
throw new Error('Token must not be undefined'); | ||
if (this.endpoint == null) { | ||
throw new Error('Endpoint must not be null nor undefined'); | ||
} | ||
if (this.endpoint === null) { | ||
throw new Error('endpoint must not be null'); | ||
} | ||
if (this.endpoint === undefined) { | ||
throw new Error('endpoint must not be undefined'); | ||
} | ||
}; | ||
@@ -282,0 +408,0 @@ return SplunkEvents; |
/*! | ||
* splunk-events v1.5.0 | ||
* splunk-events v1.6.0 | ||
* Copyright (c) VTEX | ||
@@ -20,3 +20,3 @@ * Released under the MIT License. | ||
***************************************************************************** */ | ||
var n=function(){return(n=Object.assign||function(n){for(var e,t=1,o=arguments.length;t<o;t++)for(var i in e=arguments[t])Object.prototype.hasOwnProperty.call(e,i)&&(n[i]=e[i]);return n}).apply(this,arguments)};function e(e){return"undefined"!=typeof window&&"function"!=typeof window.fetch||"undefined"!=typeof global&&"function"!=typeof global.fetch?(console.log("Error, using fetchRequest without fetch object"),Promise.resolve(null)):fetch(e.url,n(n({},e),{body:e.data})).then((function(n){return"json"===e.responseType?n.json():n}))}var t=function(){function t(){var e=this;this.events=[],this.pendingEvents=[],this.flushPending=!1,this.logEvent=function(t,o,i,s,r,l){var u;void 0===l&&(l=""),e.validateEvent(r);var a=n(n({level:t,type:o,workflowType:i,workflowInstance:s,account:l},r),e.injectAdditionalInfo?e.getAdditionalInfo():{}),d=e.shouldParseEventData?e.parseEventData(a):a,h=n(n({sourcetype:e.source,host:e.host},e.injectTimestamp&&{time:+new Date}),{event:d});e.events.push(h),e.autoFlush&&(null===(u=e.debouncedFlush)||void 0===u||u.call(e))},this.flush=function(){var n;if(e.isSendingEvents)e.flushPending=!0;else if(e.validateConfig(),e.pendingEvents=Array.from(e.events),e.events=[],e.isSendingEvents=!0,e.debug&&console.log("sending "+e.pendingEvents.length+" events to splunk"),0!==e.pendingEvents.length){var t=e.formatEventsForSplunkBatch(e.pendingEvents);e.request({url:""+e.endpoint+e.path,method:"POST",data:t,headers:null!==(n=e.headers)&&void 0!==n?n:{},responseType:"json"}).then((function(){if(e.debug&&console.log(e.pendingEvents.length+" events successfuly sent to splunk"),e.pendingEvents=[],e.isSendingEvents=!1,e.flushPending)return e.flushPending=!1,e.flush()})).catch((function(n){var t;e.events=e.events.concat(e.pendingEvents),e.pendingEvents=[],e.isSendingEvents=!1,e.autoRetryFlush?(e.debug&&console.warn("Error sending events to splunk. Retrying in 5 seconds.",n),null===(t=e.debouncedFlush)||void 0===t||t.call(e)):e.debug&&console.warn("Error sending events to splunk.",n)}))}}}return t.prototype.config=function(t){var o,i,s,r,l,u,a,d,h,v,c,p,f,g,E,b;this.events=this.events||[],this.pendingEvents=this.pendingEvents||[],this.isSendingEvents=null!==(o=this.isSendingEvents)&&void 0!==o&&o,this.endpoint=t.endpoint,this.token=t.token,this.injectAdditionalInfo=null!==(s=null!==(i=t.injectAditionalInfo)&&void 0!==i?i:t.injectAdditionalInfo)&&void 0!==s&&s,this.autoFlush=null===(r=t.autoFlush)||void 0===r||r,this.autoRetryFlush=null===(l=t.autoRetryFlush)||void 0===l||l,this.source=null!==(u=t.source)&&void 0!==u?u:"log",this.path=null!==(a=t.path)&&void 0!==a?a:"/services/collector/event",this.host=null!==(d=t.host)&&void 0!==d?d:"-",this.debug=null!==(h=t.debug)&&void 0!==h&&h,this.debounceTime=null!==(c=null!==(v=t.debounceTime)&&void 0!==v?v:this.debounceTime)&&void 0!==c?c:2e3,this.debouncedFlush=null!==(p=this.debouncedFlush)&&void 0!==p?p:function(n,e){void 0===e&&(e=100);var t=null,o=function(){t&&(clearTimeout(t),t=null),t=setTimeout(n,e)};return o.clear=function(){t&&(clearTimeout(t),t=null)},o}(this.flush,this.debounceTime),this._requestImpl=null!==(g=null!==(f=t.request)&&void 0!==f?f:this._requestImpl)&&void 0!==g?g:e,this.injectTimestamp=null!==(E=t.injectTimestamp)&&void 0!==E&&E,this.shouldParseEventData=null===(b=t.shouldParseEventData)||void 0===b||b,this.headers=n({Authorization:"Splunk "+this.token,"Content-Type":"application/json"},t.headers)},t.prototype.request=function(n){return this._requestImpl(n)},t.prototype.parseEventData=function(n){var e="";for(var t in n)if(Object.prototype.hasOwnProperty.call(n,t)&&null!=n[t]){var o=n[t];switch(typeof o){case"string":e+=t+'="'+o.replace(/"/g,"")+'" ';break;case"boolean":case"number":e+=t+"="+o+" ";break;default:throw new Error("Event property must be string, number or boolean")}}return e},t.prototype.validateEvent=function(n){if(null===n)throw new Error("Event must not be null");if(void 0===n)throw new Error("Event must not be undefined");if("object"!=typeof n)throw new Error("Event must be an object")},t.prototype.getAdditionalInfo=function(){if("undefined"==typeof navigator||"undefined"==typeof window)return"";var n=window.screen,e=window.location;return{additional_info:navigator.userAgent.replace(/,/g,";")+","+(navigator.browserLanguage||navigator.language)+","+navigator.platform+","+(n.availWidth||"-")+","+(n.availHeight||"-")+","+e.hostname+","+e.pathname+","+e.protocol.replace(":","")+","+(e.hash||"-")}},t.prototype.formatEventsForSplunkBatch=function(n){for(var e="",t=0;t<n.length;t++)e+="\n"+JSON.stringify(n[t])+"\n";return e},t.prototype.validateConfig=function(){if(null===this.token)throw new Error("Token must not be null");if(void 0===this.token)throw new Error("Token must not be undefined");if(null===this.endpoint)throw new Error("endpoint must not be null");if(void 0===this.endpoint)throw new Error("endpoint must not be undefined")},t}();export default t; | ||
var n=function(){return(n=Object.assign||function(n){for(var t,e=1,o=arguments.length;e<o;e++)for(var i in t=arguments[e])Object.prototype.hasOwnProperty.call(t,i)&&(n[i]=t[i]);return n}).apply(this,arguments)};function t(n,t,e,o){return new(e||(e=Promise))((function(i,s){function u(n){try{l(o.next(n))}catch(n){s(n)}}function r(n){try{l(o.throw(n))}catch(n){s(n)}}function l(n){var t;n.done?i(n.value):(t=n.value,t instanceof e?t:new e((function(n){n(t)}))).then(u,r)}l((o=o.apply(n,t||[])).next())}))}function e(n,t){var e,o,i,s,u={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return s={next:r(0),throw:r(1),return:r(2)},"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function r(s){return function(r){return function(s){if(e)throw new TypeError("Generator is already executing.");for(;u;)try{if(e=1,o&&(i=2&s[0]?o.return:s[0]?o.throw||((i=o.return)&&i.call(o),0):o.next)&&!(i=i.call(o,s[1])).done)return i;switch(o=0,i&&(s=[2&s[0],i.value]),s[0]){case 0:case 1:i=s;break;case 4:return u.label++,{value:s[1],done:!1};case 5:u.label++,o=s[1],s=[0];continue;case 7:s=u.ops.pop(),u.trys.pop();continue;default:if(!(i=u.trys,(i=i.length>0&&i[i.length-1])||6!==s[0]&&2!==s[0])){u=0;continue}if(3===s[0]&&(!i||s[1]>i[0]&&s[1]<i[3])){u.label=s[1];break}if(6===s[0]&&u.label<i[1]){u.label=i[1],i=s;break}if(i&&u.label<i[2]){u.label=i[2],u.ops.push(s);break}i[2]&&u.ops.pop(),u.trys.pop();continue}s=t.call(n,u)}catch(n){s=[6,n],o=0}finally{e=i=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,r])}}}function o(n,t){void 0===t&&(t=100);var e=null,o=null,i=function(){for(var i=[],s=0;s<arguments.length;s++)i[s]=arguments[s];return e&&(clearTimeout(e),e=null),new Promise((function(s,u){o=u,e=setTimeout((function(){var t=n.apply(void 0,i);null!=t&&t.then(s).catch(u)}),t)}))};return i.clear=function(){e&&(clearTimeout(e),null==o||o(),e=null)},i}function i(t){return"undefined"!=typeof window&&"function"!=typeof window.fetch||"undefined"!=typeof global&&"function"!=typeof global.fetch?(console.log("Error, using fetchRequest without fetch object"),Promise.resolve(null)):fetch(t.url,n(n({},t),{body:t.data})).then((function(n){return"json"===t.responseType?n.json():n}))}var s=function(){function s(s){var u=this;this._requestImpl=i,this.autoFlush=!0,this.autoRetryFlush=!0,this.debounceTime=2e3,this.debug=!1,this.events=[],this.host="-",this.injectAdditionalInfo=!1,this.injectTimestamp=!1,this.isSendingEvents=!1,this.path="/services/collector/event",this.pendingEvents=[],this.shouldParseEventData=!0,this.source="log",this.flushPending=!1,this.useExponentialBackoff=!1,this.exponentialBackoffLimit=6e4,this.isBackoffInProgress=!1,this.maxNumberOfRetries=1/0,this.logEvent=function(t,e,o,i,s,r){void 0===r&&(r=""),u.validateEvent(s);var l=n(n({level:t,type:e,workflowType:o,workflowInstance:i,account:r},s),u.injectAdditionalInfo?u.getAdditionalInfo():{}),a=u.shouldParseEventData?u.parseEventData(l):l,h=n(n({sourcetype:u.source,host:u.host},u.injectTimestamp&&{time:+new Date}),{event:a});u.events.push(h),u.autoFlush&&u.flushEvents()},this.flushEvents=function(){u.useExponentialBackoff?u._backoffFlush():u.debouncedFlush()},this.flush=function(n){return void 0===n&&(n=u.events),t(u,void 0,void 0,(function(){var t,o,i=this;return e(this,(function(e){return this.validateConfig(),0===n.length?[2]:(this.debug&&console.log("sending "+n.length+" events to splunk"),t=this.formatEventsForSplunkBatch(n),[2,this.request({url:""+this.endpoint+this.path,method:"POST",data:t,headers:null!==(o=this.headers)&&void 0!==o?o:{},responseType:"json"}).then((function(){i.debug&&console.log(n.length+" events successfuly sent to splunk")})).catch((function(n){throw i.debug&&console.warn("Error sending events to splunk.",n),n}))])}))}))},this._backoffFlush=function(){if(!u.isBackoffInProgress){u.isBackoffInProgress=!0;var n=function(t){return void 0===t&&(t=0),u.flush().then((function(){u.events=[],u.isBackoffInProgress=!1})).catch((function(){var e=1e3*Math.pow(2,t);return t>u.maxNumberOfRetries?(u.events=[],void(u.isBackoffInProgress=!1)):new Promise((function(o,i){setTimeout((function(){n(t+1).then(o,i).catch(i)}),Math.min(e,u.exponentialBackoffLimit))}))}))};return n()}},this._debouncedFlush=function(){u.isSendingEvents?u.flushPending=!0:(u.pendingEvents=Array.from(u.events),u.events=[],u.isSendingEvents=!0,u.flush(u.pendingEvents).then((function(){if(u.pendingEvents=[],u.isSendingEvents=!1,u.flushPending)return u.flushPending=!1,u._debouncedFlush()})).catch((function(){u.events=u.events.concat(u.pendingEvents),u.pendingEvents=[],u.isSendingEvents=!1,u.autoRetryFlush&&u.flushEvents()})))},this.debouncedFlush=o(this._debouncedFlush,this.debounceTime),s&&this.config(s)}return s.prototype.config=function(t){var e,i,s,u,r,l,a,h,c,f,d,v,p,g,b,m,y,w;this.endpoint=null!==(e=null==t?void 0:t.endpoint)&&void 0!==e?e:this.endpoint,this.token=null!==(i=null==t?void 0:t.token)&&void 0!==i?i:this.endpoint,this.injectAdditionalInfo=null!==(u=null!==(s=null==t?void 0:t.injectAditionalInfo)&&void 0!==s?s:null==t?void 0:t.injectAdditionalInfo)&&void 0!==u?u:this.injectAdditionalInfo,this.useExponentialBackoff=null!==(r=null==t?void 0:t.useExponentialBackoff)&&void 0!==r?r:this.useExponentialBackoff,this.exponentialBackoffLimit=null!==(l=null==t?void 0:t.exponentialBackoffLimit)&&void 0!==l?l:this.exponentialBackoffLimit,this.autoFlush=!!this.useExponentialBackoff||(null!==(a=null==t?void 0:t.autoFlush)&&void 0!==a?a:this.autoFlush),this.autoRetryFlush=null!==(h=null==t?void 0:t.autoRetryFlush)&&void 0!==h?h:this.autoRetryFlush,this.source=null!==(c=null==t?void 0:t.source)&&void 0!==c?c:this.source,this.path=null!==(f=null==t?void 0:t.path)&&void 0!==f?f:this.path,this.host=null!==(d=null==t?void 0:t.host)&&void 0!==d?d:this.host,this.debug=null!==(v=null==t?void 0:t.debug)&&void 0!==v?v:this.debug;var E=this.debounceTime;this.debounceTime=null!==(p=null==t?void 0:t.debounceTime)&&void 0!==p?p:this.debounceTime,this.debounceTime!==E&&(this.debouncedFlush.clear(),this.debouncedFlush=o(this._debouncedFlush,this.debounceTime)),this._requestImpl=null!==(g=null==t?void 0:t.request)&&void 0!==g?g:this._requestImpl,this.injectTimestamp=null!==(b=null==t?void 0:t.injectTimestamp)&&void 0!==b?b:this.injectTimestamp,this.shouldParseEventData=null!==(m=null==t?void 0:t.shouldParseEventData)&&void 0!==m?m:this.shouldParseEventData,this.maxNumberOfRetries=null!==(y=null==t?void 0:t.maxNumberOfRetries)&&void 0!==y?y:this.maxNumberOfRetries,this.headers=n({Authorization:"Splunk "+this.token,"Content-Type":"application/json"},null!==(w=null==t?void 0:t.headers)&&void 0!==w?w:{})},s.prototype.request=function(n){return this._requestImpl(n)},s.prototype.parseEventData=function(n){var t="";for(var e in n)if(Object.prototype.hasOwnProperty.call(n,e)&&null!=n[e]){var o=n[e];switch(typeof o){case"string":t+=e+'="'+o.replace(/"/g,"")+'" ';break;case"boolean":case"number":t+=e+"="+o+" ";break;default:throw new Error("Event property must be string, number or boolean")}}return t},s.prototype.validateEvent=function(n){if(null===n)throw new Error("Event must not be null");if(void 0===n)throw new Error("Event must not be undefined");if("object"!=typeof n)throw new Error("Event must be an object")},s.prototype.getAdditionalInfo=function(){if("undefined"==typeof navigator||"undefined"==typeof window)return"";var n=window.screen,t=window.location;return{additional_info:navigator.userAgent.replace(/,/g,";")+","+(navigator.browserLanguage||navigator.language)+","+navigator.platform+","+(n.availWidth||"-")+","+(n.availHeight||"-")+","+t.hostname+","+t.pathname+","+t.protocol.replace(":","")+","+(t.hash||"-")}},s.prototype.formatEventsForSplunkBatch=function(n){return n.map((function(n){return JSON.stringify(n)})).join("\n")},s.prototype.validateConfig=function(){if(null==this.token)throw new Error("Token must not be null nor undefined");if(null==this.endpoint)throw new Error("Endpoint must not be null nor undefined")},s}();export default s; | ||
//# sourceMappingURL=splunk-events.esm.min.js.map |
/*! | ||
* splunk-events v1.5.0 | ||
* splunk-events v1.6.0 | ||
* Copyright (c) VTEX | ||
@@ -34,6 +34,49 @@ * Released under the MIT License. | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function debounce(func, wait) { | ||
if (wait === void 0) { wait = 100; } | ||
var timeout = null; | ||
var cancel = null; | ||
var debounced = function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
if (timeout) { | ||
@@ -43,3 +86,11 @@ clearTimeout(timeout); | ||
} | ||
timeout = setTimeout(func, wait); | ||
return new Promise(function (res, rej) { | ||
cancel = rej; | ||
timeout = setTimeout(function () { | ||
var maybePromise = func.apply(void 0, args); | ||
if (maybePromise != null) { | ||
maybePromise.then(res)["catch"](rej); | ||
} | ||
}, wait); | ||
}); | ||
}; | ||
@@ -51,2 +102,3 @@ debounced.clear = function () { | ||
clearTimeout(timeout); | ||
cancel === null || cancel === void 0 ? void 0 : cancel(); | ||
timeout = null; | ||
@@ -72,8 +124,26 @@ }; | ||
var DEFAULT_EXPONENTIAL_BACKOFF_LIMIT = 60000; | ||
var DEFAULT_DEBOUNCE_TIME = 2000; | ||
var SplunkEvents = /** @class */ (function () { | ||
function SplunkEvents() { | ||
function SplunkEvents(config) { | ||
var _this = this; | ||
this._requestImpl = fetchRequest; | ||
this.autoFlush = true; | ||
this.autoRetryFlush = true; | ||
this.debounceTime = DEFAULT_DEBOUNCE_TIME; | ||
this.debug = false; | ||
this.events = []; | ||
this.host = '-'; | ||
this.injectAdditionalInfo = false; | ||
this.injectTimestamp = false; | ||
this.isSendingEvents = false; | ||
this.path = '/services/collector/event'; | ||
this.pendingEvents = []; | ||
this.shouldParseEventData = true; | ||
this.source = 'log'; | ||
this.flushPending = false; | ||
this.useExponentialBackoff = false; | ||
this.exponentialBackoffLimit = DEFAULT_EXPONENTIAL_BACKOFF_LIMIT; | ||
this.isBackoffInProgress = false; | ||
this.maxNumberOfRetries = Infinity; | ||
/** | ||
@@ -103,3 +173,2 @@ * Logs an event to Splunk. | ||
this.logEvent = function (level, type, workflowType, workflowInstance, eventData, account) { | ||
var _a; | ||
if (account === void 0) { account = ''; } | ||
@@ -118,6 +187,18 @@ _this.validateEvent(eventData); | ||
if (_this.autoFlush) { | ||
(_a = _this.debouncedFlush) === null || _a === void 0 ? void 0 : _a.call(_this); | ||
_this.flushEvents(); | ||
} | ||
}; | ||
/** | ||
* Internal flush that contains the logic for debouncing or | ||
* backing off exponentially. | ||
*/ | ||
this.flushEvents = function () { | ||
if (_this.useExponentialBackoff) { | ||
_this._backoffFlush(); | ||
} | ||
else { | ||
_this.debouncedFlush(); | ||
} | ||
}; | ||
/** | ||
* Flushes pending events into one single request. | ||
@@ -128,4 +209,67 @@ * | ||
*/ | ||
this.flush = function () { | ||
var _a; | ||
this.flush = function (events) { | ||
if (events === void 0) { events = _this.events; } | ||
return __awaiter(_this, void 0, void 0, function () { | ||
var splunkBatchedFormattedEvents; | ||
var _this = this; | ||
var _a; | ||
return __generator(this, function (_b) { | ||
this.validateConfig(); | ||
if (events.length === 0) { | ||
return [2 /*return*/]; | ||
} | ||
if (this.debug) { | ||
console.log("sending " + events.length + " events to splunk"); | ||
} | ||
splunkBatchedFormattedEvents = this.formatEventsForSplunkBatch(events); | ||
return [2 /*return*/, this.request({ | ||
url: "" + this.endpoint + this.path, | ||
method: 'POST', | ||
data: splunkBatchedFormattedEvents, | ||
headers: (_a = this.headers) !== null && _a !== void 0 ? _a : {}, | ||
responseType: 'json', | ||
}) | ||
.then(function () { | ||
if (_this.debug) { | ||
console.log(events.length + " events successfuly sent to splunk"); | ||
} | ||
})["catch"](function (e) { | ||
if (_this.debug) { | ||
console.warn('Error sending events to splunk.', e); | ||
} | ||
throw e; | ||
})]; | ||
}); | ||
}); | ||
}; | ||
this._backoffFlush = function () { | ||
if (_this.isBackoffInProgress) { | ||
return; | ||
} | ||
_this.isBackoffInProgress = true; | ||
var backoffMultiplier = 2; | ||
var executeFlush = function (depth) { | ||
if (depth === void 0) { depth = 0; } | ||
return _this.flush() | ||
.then(function () { | ||
_this.events = []; | ||
_this.isBackoffInProgress = false; | ||
})["catch"](function () { | ||
var waitTime = Math.pow(backoffMultiplier, depth) * 1000; | ||
if (depth > _this.maxNumberOfRetries) { | ||
_this.events = []; | ||
_this.isBackoffInProgress = false; | ||
return; | ||
} | ||
return new Promise(function (resolve, reject) { | ||
setTimeout(function () { | ||
executeFlush(depth + 1) | ||
.then(resolve, reject)["catch"](reject); | ||
}, Math.min(waitTime, _this.exponentialBackoffLimit)); | ||
}); | ||
}); | ||
}; | ||
return executeFlush(); | ||
}; | ||
this._debouncedFlush = function () { | ||
if (_this.isSendingEvents) { | ||
@@ -135,32 +279,15 @@ _this.flushPending = true; | ||
} | ||
_this.validateConfig(); | ||
_this.pendingEvents = Array.from(_this.events); | ||
_this.events = []; | ||
_this.isSendingEvents = true; | ||
if (_this.debug) { | ||
console.log("sending " + _this.pendingEvents.length + " events to splunk"); | ||
} | ||
if (_this.pendingEvents.length === 0) { | ||
return; | ||
} | ||
var splunkBatchedFormattedEvents = _this.formatEventsForSplunkBatch(_this.pendingEvents); | ||
_this.request({ | ||
url: "" + _this.endpoint + _this.path, | ||
method: 'POST', | ||
data: splunkBatchedFormattedEvents, | ||
headers: (_a = _this.headers) !== null && _a !== void 0 ? _a : {}, | ||
responseType: 'json', | ||
}) | ||
_this.flush(_this.pendingEvents) | ||
.then(function () { | ||
if (_this.debug) { | ||
console.log(_this.pendingEvents.length + " events successfuly sent to splunk"); | ||
} | ||
_this.pendingEvents = []; | ||
_this.isSendingEvents = false; | ||
if (_this.flushPending) { | ||
_this.flushPending = false; | ||
return _this.flush(); | ||
if (!_this.flushPending) { | ||
return; | ||
} | ||
})["catch"](function (e) { | ||
var _a; | ||
_this.flushPending = false; | ||
return _this._debouncedFlush(); | ||
})["catch"](function () { | ||
_this.events = _this.events.concat(_this.pendingEvents); | ||
@@ -170,12 +297,10 @@ _this.pendingEvents = []; | ||
if (_this.autoRetryFlush) { | ||
if (_this.debug) { | ||
console.warn('Error sending events to splunk. Retrying in 5 seconds.', e); | ||
} | ||
(_a = _this.debouncedFlush) === null || _a === void 0 ? void 0 : _a.call(_this); | ||
_this.flushEvents(); | ||
} | ||
else if (_this.debug) { | ||
console.warn('Error sending events to splunk.', e); | ||
} | ||
}); | ||
}; | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime); | ||
if (config) { | ||
this.config(config); | ||
} | ||
} | ||
@@ -186,23 +311,33 @@ /** | ||
SplunkEvents.prototype.config = function (config) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; | ||
this.events = this.events || []; | ||
this.pendingEvents = this.pendingEvents || []; | ||
this.isSendingEvents = (_a = this.isSendingEvents) !== null && _a !== void 0 ? _a : false; | ||
this.endpoint = config.endpoint; // required | ||
this.token = config.token; // required | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; | ||
this.endpoint = (_a = config === null || config === void 0 ? void 0 : config.endpoint) !== null && _a !== void 0 ? _a : this.endpoint; // required | ||
this.token = (_b = config === null || config === void 0 ? void 0 : config.token) !== null && _b !== void 0 ? _b : this.endpoint; // required | ||
this.injectAdditionalInfo = | ||
(_c = (_b = config.injectAditionalInfo) !== null && _b !== void 0 ? _b : config.injectAdditionalInfo) !== null && _c !== void 0 ? _c : false; | ||
this.autoFlush = (_d = config.autoFlush) !== null && _d !== void 0 ? _d : true; | ||
this.autoRetryFlush = (_e = config.autoRetryFlush) !== null && _e !== void 0 ? _e : true; | ||
this.source = (_f = config.source) !== null && _f !== void 0 ? _f : 'log'; | ||
this.path = (_g = config.path) !== null && _g !== void 0 ? _g : '/services/collector/event'; | ||
this.host = (_h = config.host) !== null && _h !== void 0 ? _h : '-'; | ||
this.debug = (_j = config.debug) !== null && _j !== void 0 ? _j : false; | ||
this.debounceTime = (_l = (_k = config.debounceTime) !== null && _k !== void 0 ? _k : this.debounceTime) !== null && _l !== void 0 ? _l : 2000; | ||
this.debouncedFlush = | ||
(_m = this.debouncedFlush) !== null && _m !== void 0 ? _m : debounce(this.flush, this.debounceTime); | ||
this._requestImpl = (_p = (_o = config.request) !== null && _o !== void 0 ? _o : this._requestImpl) !== null && _p !== void 0 ? _p : fetchRequest; | ||
this.injectTimestamp = (_q = config.injectTimestamp) !== null && _q !== void 0 ? _q : false; | ||
this.shouldParseEventData = (_r = config.shouldParseEventData) !== null && _r !== void 0 ? _r : true; | ||
this.headers = __assign({ Authorization: "Splunk " + this.token, 'Content-Type': 'application/json' }, config.headers); | ||
(_d = (_c = config === null || config === void 0 ? void 0 : config.injectAditionalInfo) !== null && _c !== void 0 ? _c : config === null || config === void 0 ? void 0 : config.injectAdditionalInfo) !== null && _d !== void 0 ? _d : this.injectAdditionalInfo; | ||
this.useExponentialBackoff = | ||
(_e = config === null || config === void 0 ? void 0 : config.useExponentialBackoff) !== null && _e !== void 0 ? _e : this.useExponentialBackoff; | ||
this.exponentialBackoffLimit = | ||
(_f = config === null || config === void 0 ? void 0 : config.exponentialBackoffLimit) !== null && _f !== void 0 ? _f : this.exponentialBackoffLimit; | ||
this.autoFlush = this.useExponentialBackoff | ||
? // should always be true when using exponential backoff strategy | ||
true | ||
: (_g = config === null || config === void 0 ? void 0 : config.autoFlush) !== null && _g !== void 0 ? _g : this.autoFlush; | ||
this.autoRetryFlush = (_h = config === null || config === void 0 ? void 0 : config.autoRetryFlush) !== null && _h !== void 0 ? _h : this.autoRetryFlush; | ||
this.source = (_j = config === null || config === void 0 ? void 0 : config.source) !== null && _j !== void 0 ? _j : this.source; | ||
this.path = (_k = config === null || config === void 0 ? void 0 : config.path) !== null && _k !== void 0 ? _k : this.path; | ||
this.host = (_l = config === null || config === void 0 ? void 0 : config.host) !== null && _l !== void 0 ? _l : this.host; | ||
this.debug = (_m = config === null || config === void 0 ? void 0 : config.debug) !== null && _m !== void 0 ? _m : this.debug; | ||
var prevDebounceTime = this.debounceTime; | ||
this.debounceTime = (_o = config === null || config === void 0 ? void 0 : config.debounceTime) !== null && _o !== void 0 ? _o : this.debounceTime; | ||
if (this.debounceTime !== prevDebounceTime) { | ||
this.debouncedFlush.clear(); | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime); | ||
} | ||
this._requestImpl = (_p = config === null || config === void 0 ? void 0 : config.request) !== null && _p !== void 0 ? _p : this._requestImpl; | ||
this.injectTimestamp = (_q = config === null || config === void 0 ? void 0 : config.injectTimestamp) !== null && _q !== void 0 ? _q : this.injectTimestamp; | ||
this.shouldParseEventData = | ||
(_r = config === null || config === void 0 ? void 0 : config.shouldParseEventData) !== null && _r !== void 0 ? _r : this.shouldParseEventData; | ||
this.maxNumberOfRetries = | ||
(_s = config === null || config === void 0 ? void 0 : config.maxNumberOfRetries) !== null && _s !== void 0 ? _s : this.maxNumberOfRetries; | ||
this.headers = __assign({ Authorization: "Splunk " + this.token, 'Content-Type': 'application/json' }, ((_t = config === null || config === void 0 ? void 0 : config.headers) !== null && _t !== void 0 ? _t : {})); | ||
}; | ||
@@ -227,2 +362,3 @@ /** | ||
case 'boolean': | ||
// eslint-disable-next-line no-fallthrough | ||
case 'number': | ||
@@ -263,21 +399,11 @@ parsedEvent += key + "=" + value + " "; | ||
SplunkEvents.prototype.formatEventsForSplunkBatch = function (events) { | ||
var splunkBatchedFormattedEvents = ''; | ||
for (var i = 0; i < events.length; i++) { | ||
splunkBatchedFormattedEvents += "\n" + JSON.stringify(events[i]) + "\n"; | ||
} | ||
return splunkBatchedFormattedEvents; | ||
return events.map(function (event) { return JSON.stringify(event); }).join('\n'); | ||
}; | ||
SplunkEvents.prototype.validateConfig = function () { | ||
if (this.token === null) { | ||
throw new Error('Token must not be null'); | ||
if (this.token == null) { | ||
throw new Error('Token must not be null nor undefined'); | ||
} | ||
if (this.token === undefined) { | ||
throw new Error('Token must not be undefined'); | ||
if (this.endpoint == null) { | ||
throw new Error('Endpoint must not be null nor undefined'); | ||
} | ||
if (this.endpoint === null) { | ||
throw new Error('endpoint must not be null'); | ||
} | ||
if (this.endpoint === undefined) { | ||
throw new Error('endpoint must not be undefined'); | ||
} | ||
}; | ||
@@ -284,0 +410,0 @@ return SplunkEvents; |
/*! | ||
* splunk-events v1.5.0 | ||
* splunk-events v1.6.0 | ||
* Copyright (c) VTEX | ||
@@ -20,3 +20,3 @@ * Released under the MIT License. | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */var n=function(){return(n=Object.assign||function(n){for(var e,t=1,o=arguments.length;t<o;t++)for(var i in e=arguments[t])Object.prototype.hasOwnProperty.call(e,i)&&(n[i]=e[i]);return n}).apply(this,arguments)};function e(e){return"undefined"!=typeof window&&"function"!=typeof window.fetch||"undefined"!=typeof global&&"function"!=typeof global.fetch?(console.log("Error, using fetchRequest without fetch object"),Promise.resolve(null)):fetch(e.url,n(n({},e),{body:e.data})).then((function(n){return"json"===e.responseType?n.json():n}))}var t=function(){function t(){var e=this;this.events=[],this.pendingEvents=[],this.flushPending=!1,this.logEvent=function(t,o,i,s,r,l){var u;void 0===l&&(l=""),e.validateEvent(r);var a=n(n({level:t,type:o,workflowType:i,workflowInstance:s,account:l},r),e.injectAdditionalInfo?e.getAdditionalInfo():{}),d=e.shouldParseEventData?e.parseEventData(a):a,h=n(n({sourcetype:e.source,host:e.host},e.injectTimestamp&&{time:+new Date}),{event:d});e.events.push(h),e.autoFlush&&(null===(u=e.debouncedFlush)||void 0===u||u.call(e))},this.flush=function(){var n;if(e.isSendingEvents)e.flushPending=!0;else if(e.validateConfig(),e.pendingEvents=Array.from(e.events),e.events=[],e.isSendingEvents=!0,e.debug&&console.log("sending "+e.pendingEvents.length+" events to splunk"),0!==e.pendingEvents.length){var t=e.formatEventsForSplunkBatch(e.pendingEvents);e.request({url:""+e.endpoint+e.path,method:"POST",data:t,headers:null!==(n=e.headers)&&void 0!==n?n:{},responseType:"json"}).then((function(){if(e.debug&&console.log(e.pendingEvents.length+" events successfuly sent to splunk"),e.pendingEvents=[],e.isSendingEvents=!1,e.flushPending)return e.flushPending=!1,e.flush()})).catch((function(n){var t;e.events=e.events.concat(e.pendingEvents),e.pendingEvents=[],e.isSendingEvents=!1,e.autoRetryFlush?(e.debug&&console.warn("Error sending events to splunk. Retrying in 5 seconds.",n),null===(t=e.debouncedFlush)||void 0===t||t.call(e)):e.debug&&console.warn("Error sending events to splunk.",n)}))}}}return t.prototype.config=function(t){var o,i,s,r,l,u,a,d,h,v,c,p,f,g,E,b;this.events=this.events||[],this.pendingEvents=this.pendingEvents||[],this.isSendingEvents=null!==(o=this.isSendingEvents)&&void 0!==o&&o,this.endpoint=t.endpoint,this.token=t.token,this.injectAdditionalInfo=null!==(s=null!==(i=t.injectAditionalInfo)&&void 0!==i?i:t.injectAdditionalInfo)&&void 0!==s&&s,this.autoFlush=null===(r=t.autoFlush)||void 0===r||r,this.autoRetryFlush=null===(l=t.autoRetryFlush)||void 0===l||l,this.source=null!==(u=t.source)&&void 0!==u?u:"log",this.path=null!==(a=t.path)&&void 0!==a?a:"/services/collector/event",this.host=null!==(d=t.host)&&void 0!==d?d:"-",this.debug=null!==(h=t.debug)&&void 0!==h&&h,this.debounceTime=null!==(c=null!==(v=t.debounceTime)&&void 0!==v?v:this.debounceTime)&&void 0!==c?c:2e3,this.debouncedFlush=null!==(p=this.debouncedFlush)&&void 0!==p?p:function(n,e){void 0===e&&(e=100);var t=null,o=function(){t&&(clearTimeout(t),t=null),t=setTimeout(n,e)};return o.clear=function(){t&&(clearTimeout(t),t=null)},o}(this.flush,this.debounceTime),this._requestImpl=null!==(g=null!==(f=t.request)&&void 0!==f?f:this._requestImpl)&&void 0!==g?g:e,this.injectTimestamp=null!==(E=t.injectTimestamp)&&void 0!==E&&E,this.shouldParseEventData=null===(b=t.shouldParseEventData)||void 0===b||b,this.headers=n({Authorization:"Splunk "+this.token,"Content-Type":"application/json"},t.headers)},t.prototype.request=function(n){return this._requestImpl(n)},t.prototype.parseEventData=function(n){var e="";for(var t in n)if(Object.prototype.hasOwnProperty.call(n,t)&&null!=n[t]){var o=n[t];switch(typeof o){case"string":e+=t+'="'+o.replace(/"/g,"")+'" ';break;case"boolean":case"number":e+=t+"="+o+" ";break;default:throw new Error("Event property must be string, number or boolean")}}return e},t.prototype.validateEvent=function(n){if(null===n)throw new Error("Event must not be null");if(void 0===n)throw new Error("Event must not be undefined");if("object"!=typeof n)throw new Error("Event must be an object")},t.prototype.getAdditionalInfo=function(){if("undefined"==typeof navigator||"undefined"==typeof window)return"";var n=window.screen,e=window.location;return{additional_info:navigator.userAgent.replace(/,/g,";")+","+(navigator.browserLanguage||navigator.language)+","+navigator.platform+","+(n.availWidth||"-")+","+(n.availHeight||"-")+","+e.hostname+","+e.pathname+","+e.protocol.replace(":","")+","+(e.hash||"-")}},t.prototype.formatEventsForSplunkBatch=function(n){for(var e="",t=0;t<n.length;t++)e+="\n"+JSON.stringify(n[t])+"\n";return e},t.prototype.validateConfig=function(){if(null===this.token)throw new Error("Token must not be null");if(void 0===this.token)throw new Error("Token must not be undefined");if(null===this.endpoint)throw new Error("endpoint must not be null");if(void 0===this.endpoint)throw new Error("endpoint must not be undefined")},t}();module.exports=t; | ||
***************************************************************************** */var n=function(){return(n=Object.assign||function(n){for(var t,e=1,o=arguments.length;e<o;e++)for(var i in t=arguments[e])Object.prototype.hasOwnProperty.call(t,i)&&(n[i]=t[i]);return n}).apply(this,arguments)};function t(n,t,e,o){return new(e||(e=Promise))((function(i,s){function u(n){try{l(o.next(n))}catch(n){s(n)}}function r(n){try{l(o.throw(n))}catch(n){s(n)}}function l(n){var t;n.done?i(n.value):(t=n.value,t instanceof e?t:new e((function(n){n(t)}))).then(u,r)}l((o=o.apply(n,t||[])).next())}))}function e(n,t){var e,o,i,s,u={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return s={next:r(0),throw:r(1),return:r(2)},"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function r(s){return function(r){return function(s){if(e)throw new TypeError("Generator is already executing.");for(;u;)try{if(e=1,o&&(i=2&s[0]?o.return:s[0]?o.throw||((i=o.return)&&i.call(o),0):o.next)&&!(i=i.call(o,s[1])).done)return i;switch(o=0,i&&(s=[2&s[0],i.value]),s[0]){case 0:case 1:i=s;break;case 4:return u.label++,{value:s[1],done:!1};case 5:u.label++,o=s[1],s=[0];continue;case 7:s=u.ops.pop(),u.trys.pop();continue;default:if(!(i=u.trys,(i=i.length>0&&i[i.length-1])||6!==s[0]&&2!==s[0])){u=0;continue}if(3===s[0]&&(!i||s[1]>i[0]&&s[1]<i[3])){u.label=s[1];break}if(6===s[0]&&u.label<i[1]){u.label=i[1],i=s;break}if(i&&u.label<i[2]){u.label=i[2],u.ops.push(s);break}i[2]&&u.ops.pop(),u.trys.pop();continue}s=t.call(n,u)}catch(n){s=[6,n],o=0}finally{e=i=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,r])}}}function o(n,t){void 0===t&&(t=100);var e=null,o=null,i=function(){for(var i=[],s=0;s<arguments.length;s++)i[s]=arguments[s];return e&&(clearTimeout(e),e=null),new Promise((function(s,u){o=u,e=setTimeout((function(){var t=n.apply(void 0,i);null!=t&&t.then(s).catch(u)}),t)}))};return i.clear=function(){e&&(clearTimeout(e),null==o||o(),e=null)},i}function i(t){return"undefined"!=typeof window&&"function"!=typeof window.fetch||"undefined"!=typeof global&&"function"!=typeof global.fetch?(console.log("Error, using fetchRequest without fetch object"),Promise.resolve(null)):fetch(t.url,n(n({},t),{body:t.data})).then((function(n){return"json"===t.responseType?n.json():n}))}var s=function(){function s(s){var u=this;this._requestImpl=i,this.autoFlush=!0,this.autoRetryFlush=!0,this.debounceTime=2e3,this.debug=!1,this.events=[],this.host="-",this.injectAdditionalInfo=!1,this.injectTimestamp=!1,this.isSendingEvents=!1,this.path="/services/collector/event",this.pendingEvents=[],this.shouldParseEventData=!0,this.source="log",this.flushPending=!1,this.useExponentialBackoff=!1,this.exponentialBackoffLimit=6e4,this.isBackoffInProgress=!1,this.maxNumberOfRetries=1/0,this.logEvent=function(t,e,o,i,s,r){void 0===r&&(r=""),u.validateEvent(s);var l=n(n({level:t,type:e,workflowType:o,workflowInstance:i,account:r},s),u.injectAdditionalInfo?u.getAdditionalInfo():{}),a=u.shouldParseEventData?u.parseEventData(l):l,h=n(n({sourcetype:u.source,host:u.host},u.injectTimestamp&&{time:+new Date}),{event:a});u.events.push(h),u.autoFlush&&u.flushEvents()},this.flushEvents=function(){u.useExponentialBackoff?u._backoffFlush():u.debouncedFlush()},this.flush=function(n){return void 0===n&&(n=u.events),t(u,void 0,void 0,(function(){var t,o,i=this;return e(this,(function(e){return this.validateConfig(),0===n.length?[2]:(this.debug&&console.log("sending "+n.length+" events to splunk"),t=this.formatEventsForSplunkBatch(n),[2,this.request({url:""+this.endpoint+this.path,method:"POST",data:t,headers:null!==(o=this.headers)&&void 0!==o?o:{},responseType:"json"}).then((function(){i.debug&&console.log(n.length+" events successfuly sent to splunk")})).catch((function(n){throw i.debug&&console.warn("Error sending events to splunk.",n),n}))])}))}))},this._backoffFlush=function(){if(!u.isBackoffInProgress){u.isBackoffInProgress=!0;var n=function(t){return void 0===t&&(t=0),u.flush().then((function(){u.events=[],u.isBackoffInProgress=!1})).catch((function(){var e=1e3*Math.pow(2,t);return t>u.maxNumberOfRetries?(u.events=[],void(u.isBackoffInProgress=!1)):new Promise((function(o,i){setTimeout((function(){n(t+1).then(o,i).catch(i)}),Math.min(e,u.exponentialBackoffLimit))}))}))};return n()}},this._debouncedFlush=function(){u.isSendingEvents?u.flushPending=!0:(u.pendingEvents=Array.from(u.events),u.events=[],u.isSendingEvents=!0,u.flush(u.pendingEvents).then((function(){if(u.pendingEvents=[],u.isSendingEvents=!1,u.flushPending)return u.flushPending=!1,u._debouncedFlush()})).catch((function(){u.events=u.events.concat(u.pendingEvents),u.pendingEvents=[],u.isSendingEvents=!1,u.autoRetryFlush&&u.flushEvents()})))},this.debouncedFlush=o(this._debouncedFlush,this.debounceTime),s&&this.config(s)}return s.prototype.config=function(t){var e,i,s,u,r,l,a,h,c,f,d,v,p,g,b,m,y,w;this.endpoint=null!==(e=null==t?void 0:t.endpoint)&&void 0!==e?e:this.endpoint,this.token=null!==(i=null==t?void 0:t.token)&&void 0!==i?i:this.endpoint,this.injectAdditionalInfo=null!==(u=null!==(s=null==t?void 0:t.injectAditionalInfo)&&void 0!==s?s:null==t?void 0:t.injectAdditionalInfo)&&void 0!==u?u:this.injectAdditionalInfo,this.useExponentialBackoff=null!==(r=null==t?void 0:t.useExponentialBackoff)&&void 0!==r?r:this.useExponentialBackoff,this.exponentialBackoffLimit=null!==(l=null==t?void 0:t.exponentialBackoffLimit)&&void 0!==l?l:this.exponentialBackoffLimit,this.autoFlush=!!this.useExponentialBackoff||(null!==(a=null==t?void 0:t.autoFlush)&&void 0!==a?a:this.autoFlush),this.autoRetryFlush=null!==(h=null==t?void 0:t.autoRetryFlush)&&void 0!==h?h:this.autoRetryFlush,this.source=null!==(c=null==t?void 0:t.source)&&void 0!==c?c:this.source,this.path=null!==(f=null==t?void 0:t.path)&&void 0!==f?f:this.path,this.host=null!==(d=null==t?void 0:t.host)&&void 0!==d?d:this.host,this.debug=null!==(v=null==t?void 0:t.debug)&&void 0!==v?v:this.debug;var E=this.debounceTime;this.debounceTime=null!==(p=null==t?void 0:t.debounceTime)&&void 0!==p?p:this.debounceTime,this.debounceTime!==E&&(this.debouncedFlush.clear(),this.debouncedFlush=o(this._debouncedFlush,this.debounceTime)),this._requestImpl=null!==(g=null==t?void 0:t.request)&&void 0!==g?g:this._requestImpl,this.injectTimestamp=null!==(b=null==t?void 0:t.injectTimestamp)&&void 0!==b?b:this.injectTimestamp,this.shouldParseEventData=null!==(m=null==t?void 0:t.shouldParseEventData)&&void 0!==m?m:this.shouldParseEventData,this.maxNumberOfRetries=null!==(y=null==t?void 0:t.maxNumberOfRetries)&&void 0!==y?y:this.maxNumberOfRetries,this.headers=n({Authorization:"Splunk "+this.token,"Content-Type":"application/json"},null!==(w=null==t?void 0:t.headers)&&void 0!==w?w:{})},s.prototype.request=function(n){return this._requestImpl(n)},s.prototype.parseEventData=function(n){var t="";for(var e in n)if(Object.prototype.hasOwnProperty.call(n,e)&&null!=n[e]){var o=n[e];switch(typeof o){case"string":t+=e+'="'+o.replace(/"/g,"")+'" ';break;case"boolean":case"number":t+=e+"="+o+" ";break;default:throw new Error("Event property must be string, number or boolean")}}return t},s.prototype.validateEvent=function(n){if(null===n)throw new Error("Event must not be null");if(void 0===n)throw new Error("Event must not be undefined");if("object"!=typeof n)throw new Error("Event must be an object")},s.prototype.getAdditionalInfo=function(){if("undefined"==typeof navigator||"undefined"==typeof window)return"";var n=window.screen,t=window.location;return{additional_info:navigator.userAgent.replace(/,/g,";")+","+(navigator.browserLanguage||navigator.language)+","+navigator.platform+","+(n.availWidth||"-")+","+(n.availHeight||"-")+","+t.hostname+","+t.pathname+","+t.protocol.replace(":","")+","+(t.hash||"-")}},s.prototype.formatEventsForSplunkBatch=function(n){return n.map((function(n){return JSON.stringify(n)})).join("\n")},s.prototype.validateConfig=function(){if(null==this.token)throw new Error("Token must not be null nor undefined");if(null==this.endpoint)throw new Error("Endpoint must not be null nor undefined")},s}();module.exports=s; | ||
//# sourceMappingURL=splunk-events.min.js.map |
/*! | ||
* splunk-events v1.5.0 | ||
* splunk-events v1.6.0 | ||
* Copyright (c) VTEX | ||
@@ -38,6 +38,49 @@ * Released under the MIT License. | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function debounce(func, wait) { | ||
if (wait === void 0) { wait = 100; } | ||
var timeout = null; | ||
var cancel = null; | ||
var debounced = function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
if (timeout) { | ||
@@ -47,3 +90,11 @@ clearTimeout(timeout); | ||
} | ||
timeout = setTimeout(func, wait); | ||
return new Promise(function (res, rej) { | ||
cancel = rej; | ||
timeout = setTimeout(function () { | ||
var maybePromise = func.apply(void 0, args); | ||
if (maybePromise != null) { | ||
maybePromise.then(res)["catch"](rej); | ||
} | ||
}, wait); | ||
}); | ||
}; | ||
@@ -55,2 +106,3 @@ debounced.clear = function () { | ||
clearTimeout(timeout); | ||
cancel === null || cancel === void 0 ? void 0 : cancel(); | ||
timeout = null; | ||
@@ -76,8 +128,26 @@ }; | ||
var DEFAULT_EXPONENTIAL_BACKOFF_LIMIT = 60000; | ||
var DEFAULT_DEBOUNCE_TIME = 2000; | ||
var SplunkEvents = /** @class */ (function () { | ||
function SplunkEvents() { | ||
function SplunkEvents(config) { | ||
var _this = this; | ||
this._requestImpl = fetchRequest; | ||
this.autoFlush = true; | ||
this.autoRetryFlush = true; | ||
this.debounceTime = DEFAULT_DEBOUNCE_TIME; | ||
this.debug = false; | ||
this.events = []; | ||
this.host = '-'; | ||
this.injectAdditionalInfo = false; | ||
this.injectTimestamp = false; | ||
this.isSendingEvents = false; | ||
this.path = '/services/collector/event'; | ||
this.pendingEvents = []; | ||
this.shouldParseEventData = true; | ||
this.source = 'log'; | ||
this.flushPending = false; | ||
this.useExponentialBackoff = false; | ||
this.exponentialBackoffLimit = DEFAULT_EXPONENTIAL_BACKOFF_LIMIT; | ||
this.isBackoffInProgress = false; | ||
this.maxNumberOfRetries = Infinity; | ||
/** | ||
@@ -107,3 +177,2 @@ * Logs an event to Splunk. | ||
this.logEvent = function (level, type, workflowType, workflowInstance, eventData, account) { | ||
var _a; | ||
if (account === void 0) { account = ''; } | ||
@@ -122,6 +191,18 @@ _this.validateEvent(eventData); | ||
if (_this.autoFlush) { | ||
(_a = _this.debouncedFlush) === null || _a === void 0 ? void 0 : _a.call(_this); | ||
_this.flushEvents(); | ||
} | ||
}; | ||
/** | ||
* Internal flush that contains the logic for debouncing or | ||
* backing off exponentially. | ||
*/ | ||
this.flushEvents = function () { | ||
if (_this.useExponentialBackoff) { | ||
_this._backoffFlush(); | ||
} | ||
else { | ||
_this.debouncedFlush(); | ||
} | ||
}; | ||
/** | ||
* Flushes pending events into one single request. | ||
@@ -132,4 +213,67 @@ * | ||
*/ | ||
this.flush = function () { | ||
var _a; | ||
this.flush = function (events) { | ||
if (events === void 0) { events = _this.events; } | ||
return __awaiter(_this, void 0, void 0, function () { | ||
var splunkBatchedFormattedEvents; | ||
var _this = this; | ||
var _a; | ||
return __generator(this, function (_b) { | ||
this.validateConfig(); | ||
if (events.length === 0) { | ||
return [2 /*return*/]; | ||
} | ||
if (this.debug) { | ||
console.log("sending " + events.length + " events to splunk"); | ||
} | ||
splunkBatchedFormattedEvents = this.formatEventsForSplunkBatch(events); | ||
return [2 /*return*/, this.request({ | ||
url: "" + this.endpoint + this.path, | ||
method: 'POST', | ||
data: splunkBatchedFormattedEvents, | ||
headers: (_a = this.headers) !== null && _a !== void 0 ? _a : {}, | ||
responseType: 'json', | ||
}) | ||
.then(function () { | ||
if (_this.debug) { | ||
console.log(events.length + " events successfuly sent to splunk"); | ||
} | ||
})["catch"](function (e) { | ||
if (_this.debug) { | ||
console.warn('Error sending events to splunk.', e); | ||
} | ||
throw e; | ||
})]; | ||
}); | ||
}); | ||
}; | ||
this._backoffFlush = function () { | ||
if (_this.isBackoffInProgress) { | ||
return; | ||
} | ||
_this.isBackoffInProgress = true; | ||
var backoffMultiplier = 2; | ||
var executeFlush = function (depth) { | ||
if (depth === void 0) { depth = 0; } | ||
return _this.flush() | ||
.then(function () { | ||
_this.events = []; | ||
_this.isBackoffInProgress = false; | ||
})["catch"](function () { | ||
var waitTime = Math.pow(backoffMultiplier, depth) * 1000; | ||
if (depth > _this.maxNumberOfRetries) { | ||
_this.events = []; | ||
_this.isBackoffInProgress = false; | ||
return; | ||
} | ||
return new Promise(function (resolve, reject) { | ||
setTimeout(function () { | ||
executeFlush(depth + 1) | ||
.then(resolve, reject)["catch"](reject); | ||
}, Math.min(waitTime, _this.exponentialBackoffLimit)); | ||
}); | ||
}); | ||
}; | ||
return executeFlush(); | ||
}; | ||
this._debouncedFlush = function () { | ||
if (_this.isSendingEvents) { | ||
@@ -139,32 +283,15 @@ _this.flushPending = true; | ||
} | ||
_this.validateConfig(); | ||
_this.pendingEvents = Array.from(_this.events); | ||
_this.events = []; | ||
_this.isSendingEvents = true; | ||
if (_this.debug) { | ||
console.log("sending " + _this.pendingEvents.length + " events to splunk"); | ||
} | ||
if (_this.pendingEvents.length === 0) { | ||
return; | ||
} | ||
var splunkBatchedFormattedEvents = _this.formatEventsForSplunkBatch(_this.pendingEvents); | ||
_this.request({ | ||
url: "" + _this.endpoint + _this.path, | ||
method: 'POST', | ||
data: splunkBatchedFormattedEvents, | ||
headers: (_a = _this.headers) !== null && _a !== void 0 ? _a : {}, | ||
responseType: 'json', | ||
}) | ||
_this.flush(_this.pendingEvents) | ||
.then(function () { | ||
if (_this.debug) { | ||
console.log(_this.pendingEvents.length + " events successfuly sent to splunk"); | ||
} | ||
_this.pendingEvents = []; | ||
_this.isSendingEvents = false; | ||
if (_this.flushPending) { | ||
_this.flushPending = false; | ||
return _this.flush(); | ||
if (!_this.flushPending) { | ||
return; | ||
} | ||
})["catch"](function (e) { | ||
var _a; | ||
_this.flushPending = false; | ||
return _this._debouncedFlush(); | ||
})["catch"](function () { | ||
_this.events = _this.events.concat(_this.pendingEvents); | ||
@@ -174,12 +301,10 @@ _this.pendingEvents = []; | ||
if (_this.autoRetryFlush) { | ||
if (_this.debug) { | ||
console.warn('Error sending events to splunk. Retrying in 5 seconds.', e); | ||
} | ||
(_a = _this.debouncedFlush) === null || _a === void 0 ? void 0 : _a.call(_this); | ||
_this.flushEvents(); | ||
} | ||
else if (_this.debug) { | ||
console.warn('Error sending events to splunk.', e); | ||
} | ||
}); | ||
}; | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime); | ||
if (config) { | ||
this.config(config); | ||
} | ||
} | ||
@@ -190,23 +315,33 @@ /** | ||
SplunkEvents.prototype.config = function (config) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; | ||
this.events = this.events || []; | ||
this.pendingEvents = this.pendingEvents || []; | ||
this.isSendingEvents = (_a = this.isSendingEvents) !== null && _a !== void 0 ? _a : false; | ||
this.endpoint = config.endpoint; // required | ||
this.token = config.token; // required | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; | ||
this.endpoint = (_a = config === null || config === void 0 ? void 0 : config.endpoint) !== null && _a !== void 0 ? _a : this.endpoint; // required | ||
this.token = (_b = config === null || config === void 0 ? void 0 : config.token) !== null && _b !== void 0 ? _b : this.endpoint; // required | ||
this.injectAdditionalInfo = | ||
(_c = (_b = config.injectAditionalInfo) !== null && _b !== void 0 ? _b : config.injectAdditionalInfo) !== null && _c !== void 0 ? _c : false; | ||
this.autoFlush = (_d = config.autoFlush) !== null && _d !== void 0 ? _d : true; | ||
this.autoRetryFlush = (_e = config.autoRetryFlush) !== null && _e !== void 0 ? _e : true; | ||
this.source = (_f = config.source) !== null && _f !== void 0 ? _f : 'log'; | ||
this.path = (_g = config.path) !== null && _g !== void 0 ? _g : '/services/collector/event'; | ||
this.host = (_h = config.host) !== null && _h !== void 0 ? _h : '-'; | ||
this.debug = (_j = config.debug) !== null && _j !== void 0 ? _j : false; | ||
this.debounceTime = (_l = (_k = config.debounceTime) !== null && _k !== void 0 ? _k : this.debounceTime) !== null && _l !== void 0 ? _l : 2000; | ||
this.debouncedFlush = | ||
(_m = this.debouncedFlush) !== null && _m !== void 0 ? _m : debounce(this.flush, this.debounceTime); | ||
this._requestImpl = (_p = (_o = config.request) !== null && _o !== void 0 ? _o : this._requestImpl) !== null && _p !== void 0 ? _p : fetchRequest; | ||
this.injectTimestamp = (_q = config.injectTimestamp) !== null && _q !== void 0 ? _q : false; | ||
this.shouldParseEventData = (_r = config.shouldParseEventData) !== null && _r !== void 0 ? _r : true; | ||
this.headers = __assign({ Authorization: "Splunk " + this.token, 'Content-Type': 'application/json' }, config.headers); | ||
(_d = (_c = config === null || config === void 0 ? void 0 : config.injectAditionalInfo) !== null && _c !== void 0 ? _c : config === null || config === void 0 ? void 0 : config.injectAdditionalInfo) !== null && _d !== void 0 ? _d : this.injectAdditionalInfo; | ||
this.useExponentialBackoff = | ||
(_e = config === null || config === void 0 ? void 0 : config.useExponentialBackoff) !== null && _e !== void 0 ? _e : this.useExponentialBackoff; | ||
this.exponentialBackoffLimit = | ||
(_f = config === null || config === void 0 ? void 0 : config.exponentialBackoffLimit) !== null && _f !== void 0 ? _f : this.exponentialBackoffLimit; | ||
this.autoFlush = this.useExponentialBackoff | ||
? // should always be true when using exponential backoff strategy | ||
true | ||
: (_g = config === null || config === void 0 ? void 0 : config.autoFlush) !== null && _g !== void 0 ? _g : this.autoFlush; | ||
this.autoRetryFlush = (_h = config === null || config === void 0 ? void 0 : config.autoRetryFlush) !== null && _h !== void 0 ? _h : this.autoRetryFlush; | ||
this.source = (_j = config === null || config === void 0 ? void 0 : config.source) !== null && _j !== void 0 ? _j : this.source; | ||
this.path = (_k = config === null || config === void 0 ? void 0 : config.path) !== null && _k !== void 0 ? _k : this.path; | ||
this.host = (_l = config === null || config === void 0 ? void 0 : config.host) !== null && _l !== void 0 ? _l : this.host; | ||
this.debug = (_m = config === null || config === void 0 ? void 0 : config.debug) !== null && _m !== void 0 ? _m : this.debug; | ||
var prevDebounceTime = this.debounceTime; | ||
this.debounceTime = (_o = config === null || config === void 0 ? void 0 : config.debounceTime) !== null && _o !== void 0 ? _o : this.debounceTime; | ||
if (this.debounceTime !== prevDebounceTime) { | ||
this.debouncedFlush.clear(); | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime); | ||
} | ||
this._requestImpl = (_p = config === null || config === void 0 ? void 0 : config.request) !== null && _p !== void 0 ? _p : this._requestImpl; | ||
this.injectTimestamp = (_q = config === null || config === void 0 ? void 0 : config.injectTimestamp) !== null && _q !== void 0 ? _q : this.injectTimestamp; | ||
this.shouldParseEventData = | ||
(_r = config === null || config === void 0 ? void 0 : config.shouldParseEventData) !== null && _r !== void 0 ? _r : this.shouldParseEventData; | ||
this.maxNumberOfRetries = | ||
(_s = config === null || config === void 0 ? void 0 : config.maxNumberOfRetries) !== null && _s !== void 0 ? _s : this.maxNumberOfRetries; | ||
this.headers = __assign({ Authorization: "Splunk " + this.token, 'Content-Type': 'application/json' }, ((_t = config === null || config === void 0 ? void 0 : config.headers) !== null && _t !== void 0 ? _t : {})); | ||
}; | ||
@@ -231,2 +366,3 @@ /** | ||
case 'boolean': | ||
// eslint-disable-next-line no-fallthrough | ||
case 'number': | ||
@@ -267,21 +403,11 @@ parsedEvent += key + "=" + value + " "; | ||
SplunkEvents.prototype.formatEventsForSplunkBatch = function (events) { | ||
var splunkBatchedFormattedEvents = ''; | ||
for (var i = 0; i < events.length; i++) { | ||
splunkBatchedFormattedEvents += "\n" + JSON.stringify(events[i]) + "\n"; | ||
} | ||
return splunkBatchedFormattedEvents; | ||
return events.map(function (event) { return JSON.stringify(event); }).join('\n'); | ||
}; | ||
SplunkEvents.prototype.validateConfig = function () { | ||
if (this.token === null) { | ||
throw new Error('Token must not be null'); | ||
if (this.token == null) { | ||
throw new Error('Token must not be null nor undefined'); | ||
} | ||
if (this.token === undefined) { | ||
throw new Error('Token must not be undefined'); | ||
if (this.endpoint == null) { | ||
throw new Error('Endpoint must not be null nor undefined'); | ||
} | ||
if (this.endpoint === null) { | ||
throw new Error('endpoint must not be null'); | ||
} | ||
if (this.endpoint === undefined) { | ||
throw new Error('endpoint must not be undefined'); | ||
} | ||
}; | ||
@@ -288,0 +414,0 @@ return SplunkEvents; |
/*! | ||
* splunk-events v1.5.0 | ||
* splunk-events v1.6.0 | ||
* Copyright (c) VTEX | ||
* Released under the MIT License. | ||
*/ | ||
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(n="undefined"!=typeof globalThis?globalThis:n||self).SplunkEvents=e()}(this,(function(){"use strict"; | ||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(n="undefined"!=typeof globalThis?globalThis:n||self).SplunkEvents=t()}(this,(function(){"use strict"; | ||
/*! ***************************************************************************** | ||
@@ -20,3 +20,3 @@ Copyright (c) Microsoft Corporation. | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */var n=function(){return(n=Object.assign||function(n){for(var e,t=1,o=arguments.length;t<o;t++)for(var i in e=arguments[t])Object.prototype.hasOwnProperty.call(e,i)&&(n[i]=e[i]);return n}).apply(this,arguments)};function e(e){return"undefined"!=typeof window&&"function"!=typeof window.fetch||"undefined"!=typeof global&&"function"!=typeof global.fetch?(console.log("Error, using fetchRequest without fetch object"),Promise.resolve(null)):fetch(e.url,n(n({},e),{body:e.data})).then((function(n){return"json"===e.responseType?n.json():n}))}return function(){function t(){var e=this;this.events=[],this.pendingEvents=[],this.flushPending=!1,this.logEvent=function(t,o,i,s,r,u){var l;void 0===u&&(u=""),e.validateEvent(r);var a=n(n({level:t,type:o,workflowType:i,workflowInstance:s,account:u},r),e.injectAdditionalInfo?e.getAdditionalInfo():{}),d=e.shouldParseEventData?e.parseEventData(a):a,h=n(n({sourcetype:e.source,host:e.host},e.injectTimestamp&&{time:+new Date}),{event:d});e.events.push(h),e.autoFlush&&(null===(l=e.debouncedFlush)||void 0===l||l.call(e))},this.flush=function(){var n;if(e.isSendingEvents)e.flushPending=!0;else if(e.validateConfig(),e.pendingEvents=Array.from(e.events),e.events=[],e.isSendingEvents=!0,e.debug&&console.log("sending "+e.pendingEvents.length+" events to splunk"),0!==e.pendingEvents.length){var t=e.formatEventsForSplunkBatch(e.pendingEvents);e.request({url:""+e.endpoint+e.path,method:"POST",data:t,headers:null!==(n=e.headers)&&void 0!==n?n:{},responseType:"json"}).then((function(){if(e.debug&&console.log(e.pendingEvents.length+" events successfuly sent to splunk"),e.pendingEvents=[],e.isSendingEvents=!1,e.flushPending)return e.flushPending=!1,e.flush()})).catch((function(n){var t;e.events=e.events.concat(e.pendingEvents),e.pendingEvents=[],e.isSendingEvents=!1,e.autoRetryFlush?(e.debug&&console.warn("Error sending events to splunk. Retrying in 5 seconds.",n),null===(t=e.debouncedFlush)||void 0===t||t.call(e)):e.debug&&console.warn("Error sending events to splunk.",n)}))}}}return t.prototype.config=function(t){var o,i,s,r,u,l,a,d,h,v,f,c,p,g,E,b;this.events=this.events||[],this.pendingEvents=this.pendingEvents||[],this.isSendingEvents=null!==(o=this.isSendingEvents)&&void 0!==o&&o,this.endpoint=t.endpoint,this.token=t.token,this.injectAdditionalInfo=null!==(s=null!==(i=t.injectAditionalInfo)&&void 0!==i?i:t.injectAdditionalInfo)&&void 0!==s&&s,this.autoFlush=null===(r=t.autoFlush)||void 0===r||r,this.autoRetryFlush=null===(u=t.autoRetryFlush)||void 0===u||u,this.source=null!==(l=t.source)&&void 0!==l?l:"log",this.path=null!==(a=t.path)&&void 0!==a?a:"/services/collector/event",this.host=null!==(d=t.host)&&void 0!==d?d:"-",this.debug=null!==(h=t.debug)&&void 0!==h&&h,this.debounceTime=null!==(f=null!==(v=t.debounceTime)&&void 0!==v?v:this.debounceTime)&&void 0!==f?f:2e3,this.debouncedFlush=null!==(c=this.debouncedFlush)&&void 0!==c?c:function(n,e){void 0===e&&(e=100);var t=null,o=function(){t&&(clearTimeout(t),t=null),t=setTimeout(n,e)};return o.clear=function(){t&&(clearTimeout(t),t=null)},o}(this.flush,this.debounceTime),this._requestImpl=null!==(g=null!==(p=t.request)&&void 0!==p?p:this._requestImpl)&&void 0!==g?g:e,this.injectTimestamp=null!==(E=t.injectTimestamp)&&void 0!==E&&E,this.shouldParseEventData=null===(b=t.shouldParseEventData)||void 0===b||b,this.headers=n({Authorization:"Splunk "+this.token,"Content-Type":"application/json"},t.headers)},t.prototype.request=function(n){return this._requestImpl(n)},t.prototype.parseEventData=function(n){var e="";for(var t in n)if(Object.prototype.hasOwnProperty.call(n,t)&&null!=n[t]){var o=n[t];switch(typeof o){case"string":e+=t+'="'+o.replace(/"/g,"")+'" ';break;case"boolean":case"number":e+=t+"="+o+" ";break;default:throw new Error("Event property must be string, number or boolean")}}return e},t.prototype.validateEvent=function(n){if(null===n)throw new Error("Event must not be null");if(void 0===n)throw new Error("Event must not be undefined");if("object"!=typeof n)throw new Error("Event must be an object")},t.prototype.getAdditionalInfo=function(){if("undefined"==typeof navigator||"undefined"==typeof window)return"";var n=window.screen,e=window.location;return{additional_info:navigator.userAgent.replace(/,/g,";")+","+(navigator.browserLanguage||navigator.language)+","+navigator.platform+","+(n.availWidth||"-")+","+(n.availHeight||"-")+","+e.hostname+","+e.pathname+","+e.protocol.replace(":","")+","+(e.hash||"-")}},t.prototype.formatEventsForSplunkBatch=function(n){for(var e="",t=0;t<n.length;t++)e+="\n"+JSON.stringify(n[t])+"\n";return e},t.prototype.validateConfig=function(){if(null===this.token)throw new Error("Token must not be null");if(void 0===this.token)throw new Error("Token must not be undefined");if(null===this.endpoint)throw new Error("endpoint must not be null");if(void 0===this.endpoint)throw new Error("endpoint must not be undefined")},t}()})); | ||
***************************************************************************** */var n=function(){return(n=Object.assign||function(n){for(var t,e=1,o=arguments.length;e<o;e++)for(var i in t=arguments[e])Object.prototype.hasOwnProperty.call(t,i)&&(n[i]=t[i]);return n}).apply(this,arguments)};function t(n,t,e,o){return new(e||(e=Promise))((function(i,s){function u(n){try{r(o.next(n))}catch(n){s(n)}}function l(n){try{r(o.throw(n))}catch(n){s(n)}}function r(n){var t;n.done?i(n.value):(t=n.value,t instanceof e?t:new e((function(n){n(t)}))).then(u,l)}r((o=o.apply(n,t||[])).next())}))}function e(n,t){var e,o,i,s,u={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return s={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function l(s){return function(l){return function(s){if(e)throw new TypeError("Generator is already executing.");for(;u;)try{if(e=1,o&&(i=2&s[0]?o.return:s[0]?o.throw||((i=o.return)&&i.call(o),0):o.next)&&!(i=i.call(o,s[1])).done)return i;switch(o=0,i&&(s=[2&s[0],i.value]),s[0]){case 0:case 1:i=s;break;case 4:return u.label++,{value:s[1],done:!1};case 5:u.label++,o=s[1],s=[0];continue;case 7:s=u.ops.pop(),u.trys.pop();continue;default:if(!(i=u.trys,(i=i.length>0&&i[i.length-1])||6!==s[0]&&2!==s[0])){u=0;continue}if(3===s[0]&&(!i||s[1]>i[0]&&s[1]<i[3])){u.label=s[1];break}if(6===s[0]&&u.label<i[1]){u.label=i[1],i=s;break}if(i&&u.label<i[2]){u.label=i[2],u.ops.push(s);break}i[2]&&u.ops.pop(),u.trys.pop();continue}s=t.call(n,u)}catch(n){s=[6,n],o=0}finally{e=i=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,l])}}}function o(n,t){void 0===t&&(t=100);var e=null,o=null,i=function(){for(var i=[],s=0;s<arguments.length;s++)i[s]=arguments[s];return e&&(clearTimeout(e),e=null),new Promise((function(s,u){o=u,e=setTimeout((function(){var t=n.apply(void 0,i);null!=t&&t.then(s).catch(u)}),t)}))};return i.clear=function(){e&&(clearTimeout(e),null==o||o(),e=null)},i}function i(t){return"undefined"!=typeof window&&"function"!=typeof window.fetch||"undefined"!=typeof global&&"function"!=typeof global.fetch?(console.log("Error, using fetchRequest without fetch object"),Promise.resolve(null)):fetch(t.url,n(n({},t),{body:t.data})).then((function(n){return"json"===t.responseType?n.json():n}))}return function(){function s(s){var u=this;this._requestImpl=i,this.autoFlush=!0,this.autoRetryFlush=!0,this.debounceTime=2e3,this.debug=!1,this.events=[],this.host="-",this.injectAdditionalInfo=!1,this.injectTimestamp=!1,this.isSendingEvents=!1,this.path="/services/collector/event",this.pendingEvents=[],this.shouldParseEventData=!0,this.source="log",this.flushPending=!1,this.useExponentialBackoff=!1,this.exponentialBackoffLimit=6e4,this.isBackoffInProgress=!1,this.maxNumberOfRetries=1/0,this.logEvent=function(t,e,o,i,s,l){void 0===l&&(l=""),u.validateEvent(s);var r=n(n({level:t,type:e,workflowType:o,workflowInstance:i,account:l},s),u.injectAdditionalInfo?u.getAdditionalInfo():{}),a=u.shouldParseEventData?u.parseEventData(r):r,h=n(n({sourcetype:u.source,host:u.host},u.injectTimestamp&&{time:+new Date}),{event:a});u.events.push(h),u.autoFlush&&u.flushEvents()},this.flushEvents=function(){u.useExponentialBackoff?u._backoffFlush():u.debouncedFlush()},this.flush=function(n){return void 0===n&&(n=u.events),t(u,void 0,void 0,(function(){var t,o,i=this;return e(this,(function(e){return this.validateConfig(),0===n.length?[2]:(this.debug&&console.log("sending "+n.length+" events to splunk"),t=this.formatEventsForSplunkBatch(n),[2,this.request({url:""+this.endpoint+this.path,method:"POST",data:t,headers:null!==(o=this.headers)&&void 0!==o?o:{},responseType:"json"}).then((function(){i.debug&&console.log(n.length+" events successfuly sent to splunk")})).catch((function(n){throw i.debug&&console.warn("Error sending events to splunk.",n),n}))])}))}))},this._backoffFlush=function(){if(!u.isBackoffInProgress){u.isBackoffInProgress=!0;var n=function(t){return void 0===t&&(t=0),u.flush().then((function(){u.events=[],u.isBackoffInProgress=!1})).catch((function(){var e=1e3*Math.pow(2,t);return t>u.maxNumberOfRetries?(u.events=[],void(u.isBackoffInProgress=!1)):new Promise((function(o,i){setTimeout((function(){n(t+1).then(o,i).catch(i)}),Math.min(e,u.exponentialBackoffLimit))}))}))};return n()}},this._debouncedFlush=function(){u.isSendingEvents?u.flushPending=!0:(u.pendingEvents=Array.from(u.events),u.events=[],u.isSendingEvents=!0,u.flush(u.pendingEvents).then((function(){if(u.pendingEvents=[],u.isSendingEvents=!1,u.flushPending)return u.flushPending=!1,u._debouncedFlush()})).catch((function(){u.events=u.events.concat(u.pendingEvents),u.pendingEvents=[],u.isSendingEvents=!1,u.autoRetryFlush&&u.flushEvents()})))},this.debouncedFlush=o(this._debouncedFlush,this.debounceTime),s&&this.config(s)}return s.prototype.config=function(t){var e,i,s,u,l,r,a,h,c,f,d,v,p,g,b,m,y,w;this.endpoint=null!==(e=null==t?void 0:t.endpoint)&&void 0!==e?e:this.endpoint,this.token=null!==(i=null==t?void 0:t.token)&&void 0!==i?i:this.endpoint,this.injectAdditionalInfo=null!==(u=null!==(s=null==t?void 0:t.injectAditionalInfo)&&void 0!==s?s:null==t?void 0:t.injectAdditionalInfo)&&void 0!==u?u:this.injectAdditionalInfo,this.useExponentialBackoff=null!==(l=null==t?void 0:t.useExponentialBackoff)&&void 0!==l?l:this.useExponentialBackoff,this.exponentialBackoffLimit=null!==(r=null==t?void 0:t.exponentialBackoffLimit)&&void 0!==r?r:this.exponentialBackoffLimit,this.autoFlush=!!this.useExponentialBackoff||(null!==(a=null==t?void 0:t.autoFlush)&&void 0!==a?a:this.autoFlush),this.autoRetryFlush=null!==(h=null==t?void 0:t.autoRetryFlush)&&void 0!==h?h:this.autoRetryFlush,this.source=null!==(c=null==t?void 0:t.source)&&void 0!==c?c:this.source,this.path=null!==(f=null==t?void 0:t.path)&&void 0!==f?f:this.path,this.host=null!==(d=null==t?void 0:t.host)&&void 0!==d?d:this.host,this.debug=null!==(v=null==t?void 0:t.debug)&&void 0!==v?v:this.debug;var E=this.debounceTime;this.debounceTime=null!==(p=null==t?void 0:t.debounceTime)&&void 0!==p?p:this.debounceTime,this.debounceTime!==E&&(this.debouncedFlush.clear(),this.debouncedFlush=o(this._debouncedFlush,this.debounceTime)),this._requestImpl=null!==(g=null==t?void 0:t.request)&&void 0!==g?g:this._requestImpl,this.injectTimestamp=null!==(b=null==t?void 0:t.injectTimestamp)&&void 0!==b?b:this.injectTimestamp,this.shouldParseEventData=null!==(m=null==t?void 0:t.shouldParseEventData)&&void 0!==m?m:this.shouldParseEventData,this.maxNumberOfRetries=null!==(y=null==t?void 0:t.maxNumberOfRetries)&&void 0!==y?y:this.maxNumberOfRetries,this.headers=n({Authorization:"Splunk "+this.token,"Content-Type":"application/json"},null!==(w=null==t?void 0:t.headers)&&void 0!==w?w:{})},s.prototype.request=function(n){return this._requestImpl(n)},s.prototype.parseEventData=function(n){var t="";for(var e in n)if(Object.prototype.hasOwnProperty.call(n,e)&&null!=n[e]){var o=n[e];switch(typeof o){case"string":t+=e+'="'+o.replace(/"/g,"")+'" ';break;case"boolean":case"number":t+=e+"="+o+" ";break;default:throw new Error("Event property must be string, number or boolean")}}return t},s.prototype.validateEvent=function(n){if(null===n)throw new Error("Event must not be null");if(void 0===n)throw new Error("Event must not be undefined");if("object"!=typeof n)throw new Error("Event must be an object")},s.prototype.getAdditionalInfo=function(){if("undefined"==typeof navigator||"undefined"==typeof window)return"";var n=window.screen,t=window.location;return{additional_info:navigator.userAgent.replace(/,/g,";")+","+(navigator.browserLanguage||navigator.language)+","+navigator.platform+","+(n.availWidth||"-")+","+(n.availHeight||"-")+","+t.hostname+","+t.pathname+","+t.protocol.replace(":","")+","+(t.hash||"-")}},s.prototype.formatEventsForSplunkBatch=function(n){return n.map((function(n){return JSON.stringify(n)})).join("\n")},s.prototype.validateConfig=function(){if(null==this.token)throw new Error("Token must not be null nor undefined");if(null==this.endpoint)throw new Error("Endpoint must not be null nor undefined")},s}()})); | ||
//# sourceMappingURL=splunk-events.umd.min.js.map |
{ | ||
"name": "splunk-events", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "Javascript lib to create Splunk Logs via HTTP", | ||
@@ -8,4 +8,6 @@ "main": "lib/splunk-events.min.js", | ||
"module": "lib/splunk-events.esm.min.js", | ||
"browser": "src/splunk-events.ts", | ||
"types": "types/splunk-events.d.ts", | ||
"unpkg": "lib/splunk-events.umd.min.js", | ||
"jsdelivr": "lib/splunk-events.umd.min.js", | ||
"umd:main": "lib/splunk-events.umd.min.js", | ||
"sideEffects": false, | ||
@@ -25,8 +27,8 @@ "scripts": { | ||
"devDependencies": { | ||
"@vtex/prettier-config": "^0.1.4", | ||
"@vtex/test-tools": "^3.1.0", | ||
"@vtex/tsconfig": "^0.5.0", | ||
"eslint": "6.8.0", | ||
"eslint-config-vtex": "^12.3.2", | ||
"prettier": "^2.0.4", | ||
"@vtex/prettier-config": "^0.3.6", | ||
"@vtex/test-tools": "^3.4.1", | ||
"@vtex/tsconfig": "^0.5.6", | ||
"eslint": "7.22.0", | ||
"eslint-config-vtex": "^13.0.0", | ||
"prettier": "^2.2.1", | ||
"rimraf": "^3.0.2", | ||
@@ -36,3 +38,4 @@ "rollup": "^2.42.4", | ||
"rollup-plugin-typescript2": "^0.30.0", | ||
"typescript": "^4.0.2" | ||
"tslib": "^2.1.0", | ||
"typescript": "^4.2.3" | ||
}, | ||
@@ -39,0 +42,0 @@ "contributors": [ |
@@ -15,3 +15,3 @@ # Splunk Events | ||
- [`config(params)`](#configparams) | ||
- [`log(event)`](#logeventlevel-type-workflowtype-workflowinstance-eventdata-account) | ||
- [`logEvent()`](#logeventlevel-type-workflowtype-workflowinstance-eventdata-account) | ||
- [`flush()`](#flush) | ||
@@ -18,0 +18,0 @@ - [Working on Node and old browsers](#working-on-node-and-old-browsers) |
import SplunkEvents from '../splunk-events' | ||
import { fetchRequest } from '../request' | ||
const SECOND = 1000 | ||
jest.mock('../request', () => ({ | ||
fetchRequest: jest.fn(() => Promise.resolve({} as Response)), | ||
fetchRequest: jest.fn().mockReturnValue(Promise.resolve({})), | ||
})) | ||
const SECOND = 1000 | ||
function flushPromises() { | ||
return new Promise((res) => process.nextTick(res)) | ||
} | ||
describe('SplunkEvents', () => { | ||
@@ -15,2 +18,4 @@ let splunkEvents: SplunkEvents | ||
jest.useFakeTimers() | ||
jest.clearAllMocks() | ||
jest.restoreAllMocks() | ||
splunkEvents = new SplunkEvents() | ||
@@ -21,3 +26,2 @@ }) | ||
jest.runAllTimers() | ||
jest.restoreAllMocks() | ||
}) | ||
@@ -28,3 +32,4 @@ | ||
expect( | ||
// @ts-ignore | ||
// @ts-expect-error: events is private but we want to | ||
// assert on it anyway without making it public | ||
splunkEvents.events | ||
@@ -37,3 +42,3 @@ ).toStrictEqual([]) | ||
expect( | ||
// @ts-ignore | ||
// @ts-expect-error: same as above | ||
splunkEvents.events | ||
@@ -92,68 +97,143 @@ ).toStrictEqual([]) | ||
it('should only make one request if called in timeout range', async () => { | ||
splunkEvents.config({ | ||
endpoint: '/splunk', | ||
token: 'splunk-token-123', | ||
autoFlush: true, | ||
debounceTime: 10 * SECOND, | ||
}) | ||
describe('Debounce strategy', () => { | ||
it('should only make one request if called in timeout range', async () => { | ||
splunkEvents.config({ | ||
endpoint: '/splunk', | ||
token: 'splunk-token-123', | ||
autoFlush: true, | ||
debounceTime: 10 * SECOND, | ||
}) | ||
const requestSpy = jest | ||
.spyOn(SplunkEvents.prototype, 'request') | ||
.mockImplementation(() => Promise.resolve(null)) | ||
const requestSpy = jest | ||
.spyOn(SplunkEvents.prototype, 'request') | ||
.mockImplementation(() => Promise.resolve(null)) | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'checkout-cart', { | ||
description: 'User accessed cart page', | ||
}) | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'checkout-cart', { | ||
description: 'User accessed cart page', | ||
}) | ||
// advance to half the time of the timeout delay | ||
jest.advanceTimersByTime(5 * SECOND) | ||
// advance to half the time of the timeout delay | ||
jest.advanceTimersByTime(5 * SECOND) | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'checkout-profile', { | ||
description: 'User accessed profile step', | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'checkout-profile', { | ||
description: 'User accessed profile step', | ||
}) | ||
// wait for timeout to end | ||
jest.runAllTimers() | ||
expect(requestSpy).toHaveBeenCalledTimes(1) | ||
expect(requestSpy).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('workflowInstance=\\"checkout-cart\\"'), | ||
}) | ||
) | ||
expect(requestSpy).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining( | ||
'workflowInstance=\\"checkout-profile\\"' | ||
), | ||
}) | ||
) | ||
await flushPromises() | ||
// this should be enqueued for 10 seconds from now | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'checkout-payment', { | ||
description: 'User accessed payment step', | ||
}) | ||
jest.advanceTimersByTime(5 * SECOND) | ||
expect(requestSpy).toHaveBeenCalledTimes(1) | ||
jest.advanceTimersByTime(5 * SECOND) | ||
expect(requestSpy).toHaveBeenCalledTimes(2) | ||
expect(requestSpy).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining( | ||
'workflowInstance=\\"checkout-payment\\"' | ||
), | ||
}) | ||
) | ||
}) | ||
// wait for timeout to end | ||
jest.runAllTimers() | ||
it('should update debounce time', async () => { | ||
splunkEvents.config({ | ||
endpoint: '/splunk', | ||
token: 'splunk-token-123', | ||
debounceTime: 1 * SECOND, | ||
}) | ||
expect(requestSpy).toHaveBeenCalledTimes(1) | ||
expect(requestSpy).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('workflowInstance=\\"checkout-cart\\"'), | ||
const requestSpy = jest | ||
.spyOn(SplunkEvents.prototype, 'request') | ||
.mockImplementation(() => Promise.resolve(null)) | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'add-to-cart', { | ||
itemId: '320', | ||
}) | ||
) | ||
expect(requestSpy).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining( | ||
'workflowInstance=\\"checkout-profile\\"' | ||
), | ||
expect(requestSpy).toHaveBeenCalledTimes(0) | ||
jest.advanceTimersByTime(1 * SECOND) | ||
await flushPromises() | ||
expect(requestSpy).toHaveBeenCalledTimes(1) | ||
splunkEvents.config({ debounceTime: 2 * SECOND }) | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'update-item', { | ||
index: 0, | ||
quantity: 10, | ||
}) | ||
) | ||
// flush pending promises | ||
await new Promise(resolve => resolve()) | ||
jest.advanceTimersByTime(1 * SECOND) | ||
await flushPromises() | ||
// this should be enqueued for 10 seconds from now | ||
splunkEvents.logEvent('debug', 'info', 'checkout', 'checkout-payment', { | ||
description: 'User accessed payment step', | ||
expect(requestSpy).toHaveBeenCalledTimes(1) | ||
jest.advanceTimersByTime(1 * SECOND) | ||
await flushPromises() | ||
expect(requestSpy).toHaveBeenCalledTimes(2) | ||
}) | ||
jest.advanceTimersByTime(5 * SECOND) | ||
it('should use configured debounce time when a request fails', async () => { | ||
const requestMock = jest.fn(() => Promise.resolve({} as Response)) | ||
expect(requestSpy).toHaveBeenCalledTimes(1) | ||
splunkEvents.config({ | ||
endpoint: '/splunk', | ||
token: 'splunk-token-123', | ||
debounceTime: 2 * SECOND, | ||
autoRetryFlush: true, | ||
request: requestMock, | ||
}) | ||
jest.advanceTimersByTime(5 * SECOND) | ||
requestMock.mockReturnValueOnce(Promise.reject('request failed')) | ||
expect(requestSpy).toHaveBeenCalledTimes(2) | ||
expect(requestSpy).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining( | ||
'workflowInstance=\\"checkout-payment\\"' | ||
), | ||
splunkEvents.logEvent('debug', 'info', 'request', 'defaultRequestImpl', { | ||
doesDefaultRequestWork: true, | ||
}) | ||
) | ||
jest.runOnlyPendingTimers() | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(1) | ||
// Skip half of the debounce time | ||
jest.advanceTimersByTime(1 * SECOND) | ||
expect(requestMock).toHaveBeenCalledTimes(1) | ||
// Skip the remaining of the debounce time | ||
jest.advanceTimersByTime(1 * SECOND) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(2) | ||
}) | ||
}) | ||
it('should use request function passed in config', () => { | ||
const request = jest.fn(() => Promise.resolve({} as Response)) | ||
it('should use request function passed in config', async () => { | ||
const request = jest.fn().mockReturnValue(Promise.resolve({})) | ||
@@ -171,2 +251,3 @@ splunkEvents.config({ | ||
jest.runAllTimers() | ||
await flushPromises() | ||
@@ -181,4 +262,4 @@ expect(request).toHaveBeenCalledTimes(1) | ||
it('should default to fetchRequest in case request is not configured', () => { | ||
const requestMock = fetchRequest as jest.Mock | ||
it('should default to fetchRequest in case request is not configured', async () => { | ||
const requestMock = jest.requireMock('../request').fetchRequest as jest.Mock | ||
@@ -203,2 +284,150 @@ splunkEvents.config({ | ||
}) | ||
it('should be able to receive config in constructor', () => { | ||
const mySplunkLogger = new SplunkEvents({ | ||
endpoint: '/splunk', | ||
token: 'my-splunk-token-123', | ||
}) | ||
const requestSpy = jest | ||
.spyOn(SplunkEvents.prototype, 'request') | ||
.mockImplementation(() => Promise.resolve(null)) | ||
mySplunkLogger.logEvent('debug', 'info', 'checkout', 'finish-purchase', { | ||
orderFormId: '1234abc', | ||
}) | ||
jest.runAllTimers() | ||
expect(requestSpy).toHaveBeenCalledTimes(1) | ||
expect(requestSpy).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('orderFormId=\\"1234abc\\"'), | ||
}) | ||
) | ||
}) | ||
describe('Exponential backoff', () => { | ||
it('should correctly backoff exponentially', async () => { | ||
const requestMock = jest | ||
.fn() | ||
.mockReturnValue(Promise.reject('request failed')) | ||
splunkEvents.config({ | ||
endpoint: '/splunk', | ||
token: 'splunk-token-123', | ||
useExponentialBackoff: true, | ||
request: requestMock, | ||
}) | ||
splunkEvents.logEvent( | ||
'debug', | ||
'info', | ||
'request', | ||
'defaultRequestImpl', | ||
{} | ||
) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(1) | ||
jest.advanceTimersByTime(1 * SECOND) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(2) | ||
jest.advanceTimersByTime(2 * SECOND) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(3) | ||
jest.advanceTimersByTime(4 * SECOND) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(4) | ||
}) | ||
it('should accumulate events during retries', async () => { | ||
const requestMock = jest.fn().mockReturnValue(Promise.resolve()) | ||
splunkEvents.config({ | ||
endpoint: '/splunk', | ||
token: 'splunk-token-123', | ||
useExponentialBackoff: true, | ||
request: requestMock, | ||
}) | ||
requestMock.mockReturnValueOnce(Promise.reject('request failed')) | ||
splunkEvents.logEvent('debug', 'info', 'request', 'requestMockImpl', { | ||
requestNum: 1, | ||
}) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(1) | ||
splunkEvents.logEvent('debug', 'info', 'request', 'requestMockImpl', { | ||
requestNum: 2, | ||
}) | ||
jest.advanceTimersByTime(1 * SECOND) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(2) | ||
expect(requestMock).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('requestNum=1'), | ||
}) | ||
) | ||
expect(requestMock).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('requestNum=2'), | ||
}) | ||
) | ||
}) | ||
it('should reset events to flush after successfull request', async () => { | ||
const requestMock = jest.fn().mockReturnValue(Promise.resolve()) | ||
splunkEvents.config({ | ||
endpoint: '/splunk', | ||
token: 'splunk-token-123', | ||
useExponentialBackoff: true, | ||
request: requestMock, | ||
}) | ||
splunkEvents.logEvent('debug', 'info', 'request', 'requestMockImpl', { | ||
requestNum: 1, | ||
}) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(1) | ||
expect(requestMock).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('requestNum=1'), | ||
}) | ||
) | ||
splunkEvents.logEvent('debug', 'info', 'request', 'requestMockImpl', { | ||
requestNum: 2, | ||
}) | ||
await flushPromises() | ||
expect(requestMock).toHaveBeenCalledTimes(2) | ||
expect(requestMock).not.toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('requestNum=1'), | ||
}) | ||
) | ||
expect(requestMock).toHaveBeenLastCalledWith( | ||
expect.objectContaining({ | ||
data: expect.stringContaining('requestNum=2'), | ||
}) | ||
) | ||
}) | ||
}) | ||
}) |
@@ -1,5 +0,9 @@ | ||
export default function debounce(func: () => void, wait = 100) { | ||
export default function debounce<T>( | ||
func: (...args: T[]) => void | Promise<void>, | ||
wait = 100 | ||
) { | ||
let timeout: NodeJS.Timeout | null = null | ||
let cancel: (() => void) | null = null | ||
const debounced = () => { | ||
const debounced = (...args: T[]) => { | ||
if (timeout) { | ||
@@ -10,3 +14,13 @@ clearTimeout(timeout) | ||
timeout = setTimeout(func, wait) | ||
return new Promise<void>((res, rej) => { | ||
cancel = rej | ||
timeout = setTimeout(() => { | ||
const maybePromise = func(...args) | ||
if (maybePromise != null) { | ||
maybePromise.then(res).catch(rej) | ||
} | ||
}, wait) | ||
}) | ||
} | ||
@@ -20,2 +34,4 @@ | ||
clearTimeout(timeout) | ||
cancel?.() | ||
timeout = null | ||
@@ -22,0 +38,0 @@ } |
@@ -14,2 +14,3 @@ export interface FetchContext extends Omit<RequestInit, 'body'> { | ||
console.log('Error, using fetchRequest without fetch object') | ||
return Promise.resolve(null) | ||
@@ -21,8 +22,9 @@ } | ||
body: context.data, | ||
}).then(response => { | ||
}).then((response) => { | ||
if (context.responseType === 'json') { | ||
return response.json() | ||
} | ||
return response | ||
}) | ||
} |
@@ -9,8 +9,15 @@ import debounce from './debounce' | ||
* Whether or not to automatically flush batched events | ||
* after calling {@link SplunkEvent#logEvent} | ||
* after calling {@link SplunkEvent#logEvent}. | ||
* | ||
* Turned on by default. This option will also be turned | ||
* on when using `useExponentialBackoff`, regardless of the | ||
* value passed the the configuration. | ||
*/ | ||
autoFlush?: boolean | ||
/** | ||
* Whether or not to automatically retry failed flushes. | ||
*/ | ||
autoRetryFlush?: boolean | ||
/** | ||
* Timeout used to batch events together in one single request. | ||
* Timeout, in milliseconds, used to batch events together in one single request. | ||
*/ | ||
@@ -65,3 +72,2 @@ debounceTime?: number | ||
token: string | ||
/** | ||
@@ -71,2 +77,20 @@ * Custom headers to be added in the request | ||
headers?: HeadersInit | ||
/** | ||
* Configures the {@link SplunkEvent#flush} method to use an | ||
* exponential backoff algorithm instead of a fixed debounce time. | ||
* | ||
* Turned off by default. | ||
*/ | ||
useExponentialBackoff?: boolean | ||
/** | ||
* Maximum time, in milliseconds, to use for the exponential backoff | ||
* algorithm. | ||
* | ||
* The default limit is 60_000 milliseconds. | ||
*/ | ||
exponentialBackoffLimit?: number | ||
/** | ||
* Maximum number of retries of failed requests before dropping the events. | ||
*/ | ||
maxNumberOfRetries?: number | ||
} | ||
@@ -83,53 +107,84 @@ | ||
const DEFAULT_EXPONENTIAL_BACKOFF_LIMIT = 60_000 | ||
const DEFAULT_DEBOUNCE_TIME = 2_000 | ||
export default class SplunkEvents { | ||
private _requestImpl?: ( | ||
private _requestImpl: ( | ||
fetchContext: FetchContext | ||
) => Promise<Response | null> | ||
) => Promise<Response | null> = fetchRequest | ||
private autoFlush?: boolean | ||
private autoRetryFlush?: boolean | ||
private debounceTime?: number | ||
private debouncedFlush?: () => void | ||
private debug?: boolean | ||
private autoFlush = true | ||
private autoRetryFlush = true | ||
private debounceTime = DEFAULT_DEBOUNCE_TIME | ||
private debouncedFlush: { (): Promise<void>; clear(): void } | ||
private debug = false | ||
private endpoint?: string | ||
private events: SplunkEvent[] = [] | ||
private headers?: HeadersInit | ||
private host?: string | ||
private injectAdditionalInfo?: boolean | ||
private injectTimestamp?: boolean | ||
private isSendingEvents?: boolean | ||
private path?: string | ||
private host = '-' | ||
private injectAdditionalInfo = false | ||
private injectTimestamp = false | ||
private isSendingEvents = false | ||
private path = '/services/collector/event' | ||
private pendingEvents: SplunkEvent[] = [] | ||
private shouldParseEventData?: boolean | ||
private source?: string | ||
private shouldParseEventData = true | ||
private source = 'log' | ||
private token?: string | ||
private flushPending = false | ||
private useExponentialBackoff = false | ||
private exponentialBackoffLimit = DEFAULT_EXPONENTIAL_BACKOFF_LIMIT | ||
private isBackoffInProgress = false | ||
private maxNumberOfRetries = Infinity | ||
constructor(config?: Config) { | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime) | ||
if (config) { | ||
this.config(config) | ||
} | ||
} | ||
/** | ||
* Configure (or reconfigure) this Splunk Event instance. | ||
*/ | ||
public config(config: Config) { | ||
this.events = this.events || [] | ||
this.pendingEvents = this.pendingEvents || [] | ||
this.isSendingEvents = this.isSendingEvents ?? false | ||
this.endpoint = config.endpoint // required | ||
this.token = config.token // required | ||
public config(config: Partial<Config>) { | ||
this.endpoint = config?.endpoint ?? this.endpoint // required | ||
this.token = config?.token ?? this.endpoint // required | ||
this.injectAdditionalInfo = | ||
config.injectAditionalInfo ?? config.injectAdditionalInfo ?? false | ||
this.autoFlush = config.autoFlush ?? true | ||
this.autoRetryFlush = config.autoRetryFlush ?? true | ||
this.source = config.source ?? 'log' | ||
this.path = config.path ?? '/services/collector/event' | ||
this.host = config.host ?? '-' | ||
this.debug = config.debug ?? false | ||
this.debounceTime = config.debounceTime ?? this.debounceTime ?? 2000 | ||
this.debouncedFlush = | ||
this.debouncedFlush ?? debounce(this.flush, this.debounceTime) | ||
this._requestImpl = config.request ?? this._requestImpl ?? fetchRequest | ||
this.injectTimestamp = config.injectTimestamp ?? false | ||
this.shouldParseEventData = config.shouldParseEventData ?? true | ||
config?.injectAditionalInfo ?? | ||
config?.injectAdditionalInfo ?? | ||
this.injectAdditionalInfo | ||
this.useExponentialBackoff = | ||
config?.useExponentialBackoff ?? this.useExponentialBackoff | ||
this.exponentialBackoffLimit = | ||
config?.exponentialBackoffLimit ?? this.exponentialBackoffLimit | ||
this.autoFlush = this.useExponentialBackoff | ||
? // should always be true when using exponential backoff strategy | ||
true | ||
: config?.autoFlush ?? this.autoFlush | ||
this.autoRetryFlush = config?.autoRetryFlush ?? this.autoRetryFlush | ||
this.source = config?.source ?? this.source | ||
this.path = config?.path ?? this.path | ||
this.host = config?.host ?? this.host | ||
this.debug = config?.debug ?? this.debug | ||
const prevDebounceTime = this.debounceTime | ||
this.debounceTime = config?.debounceTime ?? this.debounceTime | ||
if (this.debounceTime !== prevDebounceTime) { | ||
this.debouncedFlush.clear() | ||
this.debouncedFlush = debounce(this._debouncedFlush, this.debounceTime) | ||
} | ||
this._requestImpl = config?.request ?? this._requestImpl | ||
this.injectTimestamp = config?.injectTimestamp ?? this.injectTimestamp | ||
this.shouldParseEventData = | ||
config?.shouldParseEventData ?? this.shouldParseEventData | ||
this.maxNumberOfRetries = | ||
config?.maxNumberOfRetries ?? this.maxNumberOfRetries | ||
this.headers = { | ||
Authorization: `Splunk ${this.token}`, | ||
'Content-Type': 'application/json', | ||
...config.headers, | ||
...(config?.headers ?? {}), | ||
} | ||
@@ -180,2 +235,3 @@ } | ||
} | ||
const event = this.shouldParseEventData | ||
@@ -186,4 +242,4 @@ ? this.parseEventData(eventObj) | ||
const data = { | ||
sourcetype: this.source!, | ||
host: this.host!, | ||
sourcetype: this.source, | ||
host: this.host, | ||
...(this.injectTimestamp && { time: +new Date() }), | ||
@@ -196,3 +252,3 @@ event, | ||
if (this.autoFlush) { | ||
this.debouncedFlush?.() | ||
this.flushEvents() | ||
} | ||
@@ -206,3 +262,3 @@ } | ||
public request(fetchContext: FetchContext) { | ||
return this._requestImpl!(fetchContext) | ||
return this._requestImpl(fetchContext) | ||
} | ||
@@ -212,2 +268,3 @@ | ||
let parsedEvent = '' | ||
for (const key in event) { | ||
@@ -224,6 +281,10 @@ if ( | ||
break | ||
case 'boolean': | ||
// eslint-disable-next-line no-fallthrough | ||
case 'number': | ||
parsedEvent += `${key}=${value} ` | ||
break | ||
default: | ||
@@ -234,2 +295,3 @@ throw new Error('Event property must be string, number or boolean') | ||
} | ||
return parsedEvent | ||
@@ -256,2 +318,3 @@ } | ||
} | ||
const { screen, location } = window | ||
@@ -275,2 +338,14 @@ | ||
/** | ||
* Internal flush that contains the logic for debouncing or | ||
* backing off exponentially. | ||
*/ | ||
private flushEvents = () => { | ||
if (this.useExponentialBackoff) { | ||
this._backoffFlush() | ||
} else { | ||
this.debouncedFlush() | ||
} | ||
} | ||
/** | ||
* Flushes pending events into one single request. | ||
@@ -281,27 +356,16 @@ * | ||
*/ | ||
public flush = () => { | ||
if (this.isSendingEvents) { | ||
this.flushPending = true | ||
public flush = async (events = this.events): Promise<void> => { | ||
this.validateConfig() | ||
if (events.length === 0) { | ||
return | ||
} | ||
this.validateConfig() | ||
this.pendingEvents = Array.from(this.events) | ||
this.events = [] | ||
this.isSendingEvents = true | ||
if (this.debug) { | ||
console.log(`sending ${this.pendingEvents.length} events to splunk`) | ||
console.log(`sending ${events.length} events to splunk`) | ||
} | ||
if (this.pendingEvents.length === 0) { | ||
return | ||
} | ||
const splunkBatchedFormattedEvents = this.formatEventsForSplunkBatch(events) | ||
const splunkBatchedFormattedEvents = this.formatEventsForSplunkBatch( | ||
this.pendingEvents | ||
) | ||
this.request({ | ||
return this.request({ | ||
url: `${this.endpoint}${this.path}`, | ||
@@ -315,15 +379,77 @@ method: 'POST', | ||
if (this.debug) { | ||
console.log( | ||
`${this.pendingEvents.length} events successfuly sent to splunk` | ||
) | ||
console.log(`${events.length} events successfuly sent to splunk`) | ||
} | ||
}) | ||
.catch((e) => { | ||
if (this.debug) { | ||
console.warn('Error sending events to splunk.', e) | ||
} | ||
throw e | ||
}) | ||
} | ||
private _backoffFlush = () => { | ||
if (this.isBackoffInProgress) { | ||
return | ||
} | ||
this.isBackoffInProgress = true | ||
const backoffMultiplier = 2 | ||
const executeFlush = (depth = 0) => { | ||
return this.flush() | ||
.then(() => { | ||
this.events = [] | ||
this.isBackoffInProgress = false | ||
}) | ||
.catch(() => { | ||
const waitTime = backoffMultiplier ** depth * 1_000 | ||
if (depth > this.maxNumberOfRetries) { | ||
this.events = [] | ||
this.isBackoffInProgress = false | ||
return | ||
} | ||
return new Promise((resolve, reject) => { | ||
setTimeout(() => { | ||
executeFlush(depth + 1) | ||
.then(resolve, reject) | ||
.catch(reject) | ||
}, Math.min(waitTime, this.exponentialBackoffLimit)) | ||
}) | ||
}) | ||
} | ||
return executeFlush() | ||
} | ||
private _debouncedFlush = () => { | ||
if (this.isSendingEvents) { | ||
this.flushPending = true | ||
return | ||
} | ||
this.pendingEvents = Array.from(this.events) | ||
this.events = [] | ||
this.isSendingEvents = true | ||
this.flush(this.pendingEvents) | ||
.then(() => { | ||
this.pendingEvents = [] | ||
this.isSendingEvents = false | ||
if (this.flushPending) { | ||
this.flushPending = false | ||
return this.flush() | ||
if (!this.flushPending) { | ||
return | ||
} | ||
this.flushPending = false | ||
return this._debouncedFlush() | ||
}) | ||
.catch(e => { | ||
.catch(() => { | ||
this.events = this.events.concat(this.pendingEvents) | ||
@@ -334,11 +460,3 @@ this.pendingEvents = [] | ||
if (this.autoRetryFlush) { | ||
if (this.debug) { | ||
console.warn( | ||
'Error sending events to splunk. Retrying in 5 seconds.', | ||
e | ||
) | ||
} | ||
this.debouncedFlush?.() | ||
} else if (this.debug) { | ||
console.warn('Error sending events to splunk.', e) | ||
this.flushEvents() | ||
} | ||
@@ -349,28 +467,14 @@ }) | ||
private formatEventsForSplunkBatch(events: SplunkEvent[]) { | ||
let splunkBatchedFormattedEvents = '' | ||
for (let i = 0; i < events.length; i++) { | ||
splunkBatchedFormattedEvents += `\n${JSON.stringify(events[i])}\n` | ||
} | ||
return splunkBatchedFormattedEvents | ||
return events.map((event) => JSON.stringify(event)).join('\n') | ||
} | ||
private validateConfig() { | ||
if (this.token === null) { | ||
throw new Error('Token must not be null') | ||
if (this.token == null) { | ||
throw new Error('Token must not be null nor undefined') | ||
} | ||
if (this.token === undefined) { | ||
throw new Error('Token must not be undefined') | ||
if (this.endpoint == null) { | ||
throw new Error('Endpoint must not be null nor undefined') | ||
} | ||
if (this.endpoint === null) { | ||
throw new Error('endpoint must not be null') | ||
} | ||
if (this.endpoint === undefined) { | ||
throw new Error('endpoint must not be undefined') | ||
} | ||
} | ||
} |
@@ -1,5 +0,5 @@ | ||
export default function debounce(func: () => void, wait?: number): { | ||
(): void; | ||
export default function debounce<T>(func: (...args: T[]) => void | Promise<void>, wait?: number): { | ||
(...args: T[]): Promise<void>; | ||
clear(): void; | ||
}; | ||
//# sourceMappingURL=debounce.d.ts.map |
@@ -6,8 +6,15 @@ import { FetchContext } from './request'; | ||
* Whether or not to automatically flush batched events | ||
* after calling {@link SplunkEvent#logEvent} | ||
* after calling {@link SplunkEvent#logEvent}. | ||
* | ||
* Turned on by default. This option will also be turned | ||
* on when using `useExponentialBackoff`, regardless of the | ||
* value passed the the configuration. | ||
*/ | ||
autoFlush?: boolean; | ||
/** | ||
* Whether or not to automatically retry failed flushes. | ||
*/ | ||
autoRetryFlush?: boolean; | ||
/** | ||
* Timeout used to batch events together in one single request. | ||
* Timeout, in milliseconds, used to batch events together in one single request. | ||
*/ | ||
@@ -66,28 +73,57 @@ debounceTime?: number; | ||
headers?: HeadersInit; | ||
/** | ||
* Configures the {@link SplunkEvent#flush} method to use an | ||
* exponential backoff algorithm instead of a fixed debounce time. | ||
* | ||
* Turned off by default. | ||
*/ | ||
useExponentialBackoff?: boolean; | ||
/** | ||
* Maximum time, in milliseconds, to use for the exponential backoff | ||
* algorithm. | ||
* | ||
* The default limit is 60_000 milliseconds. | ||
*/ | ||
exponentialBackoffLimit?: number; | ||
/** | ||
* Maximum number of retries of failed requests before dropping the events. | ||
*/ | ||
maxNumberOfRetries?: number; | ||
} | ||
declare type EventData = Record<string, string | number | boolean>; | ||
interface SplunkEvent { | ||
host: string; | ||
sourcetype: string; | ||
time?: number; | ||
event: EventData | string; | ||
} | ||
export default class SplunkEvents { | ||
private _requestImpl?; | ||
private autoFlush?; | ||
private autoRetryFlush?; | ||
private debounceTime?; | ||
private debouncedFlush?; | ||
private debug?; | ||
private _requestImpl; | ||
private autoFlush; | ||
private autoRetryFlush; | ||
private debounceTime; | ||
private debouncedFlush; | ||
private debug; | ||
private endpoint?; | ||
private events; | ||
private headers?; | ||
private host?; | ||
private injectAdditionalInfo?; | ||
private injectTimestamp?; | ||
private isSendingEvents?; | ||
private path?; | ||
private host; | ||
private injectAdditionalInfo; | ||
private injectTimestamp; | ||
private isSendingEvents; | ||
private path; | ||
private pendingEvents; | ||
private shouldParseEventData?; | ||
private source?; | ||
private shouldParseEventData; | ||
private source; | ||
private token?; | ||
private flushPending; | ||
private useExponentialBackoff; | ||
private exponentialBackoffLimit; | ||
private isBackoffInProgress; | ||
private maxNumberOfRetries; | ||
constructor(config?: Config); | ||
/** | ||
* Configure (or reconfigure) this Splunk Event instance. | ||
*/ | ||
config(config: Config): void; | ||
config(config: Partial<Config>): void; | ||
/** | ||
@@ -128,2 +164,7 @@ * Logs an event to Splunk. | ||
/** | ||
* Internal flush that contains the logic for debouncing or | ||
* backing off exponentially. | ||
*/ | ||
private flushEvents; | ||
/** | ||
* Flushes pending events into one single request. | ||
@@ -134,3 +175,5 @@ * | ||
*/ | ||
flush: () => void; | ||
flush: (events?: SplunkEvent[]) => Promise<void>; | ||
private _backoffFlush; | ||
private _debouncedFlush; | ||
private formatEventsForSplunkBatch; | ||
@@ -137,0 +180,0 @@ private validateConfig; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
269178
2303
6
12