UNPKG

10.5 kBJavaScriptView Raw
1"use strict";
2
3function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
5function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
6
7function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
9function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
10
11function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
12
13var superagent = require('superagent');
14
15var formatDate = require('./formatDate');
16
17var DEFAULT_INTERVAL = 0;
18var DEFAULT_BATCH = 0;
19
20var NOOP = function NOOP() {};
21
22function getUUID() {
23 // eslint gets funny about bitwise
24
25 /* eslint-disable */
26 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
27 var piece = Math.random() * 16 | 0;
28 var elem = c === 'x' ? piece : piece & 0x3 | 0x8;
29 return elem.toString(16);
30 });
31 /* eslint-enable */
32}
33/**
34 * Axios has been replaced with SuperAgent (issue #28), to maintain some backwards
35 * compatibility the SuperAgent response object is marshaled to conform
36 * to the Axios response object
37 */
38
39
40function marshalHttpResponse(response) {
41 var statusMessage = response.res ? response.res.statusMessage : '';
42 return {
43 data: response.body,
44 status: response.status,
45 statusText: response.statusText || statusMessage,
46 headers: response.headers,
47 request: response.xhr || response.req,
48 config: response.req
49 };
50}
51
52var SumoLogger =
53/*#__PURE__*/
54function () {
55 function SumoLogger(options) {
56 _classCallCheck(this, SumoLogger);
57
58 if (!options || !Object.prototype.hasOwnProperty.call(options, 'endpoint') || options.endpoint === undefined || options.endpoint === '') {
59 console.error('An endpoint value must be provided');
60 return;
61 }
62
63 this.config = {};
64 this.pendingLogs = [];
65 this.interval = 0;
66 this.setConfig(options);
67 this.startLogSending();
68 }
69
70 _createClass(SumoLogger, [{
71 key: "setConfig",
72 value: function setConfig(newConfig) {
73 this.config = {
74 endpoint: newConfig.endpoint,
75 returnPromise: Object.prototype.hasOwnProperty.call(newConfig, 'returnPromise') ? newConfig.returnPromise : true,
76 clientUrl: newConfig.clientUrl || '',
77 useIntervalOnly: newConfig.useIntervalOnly || false,
78 interval: newConfig.interval || DEFAULT_INTERVAL,
79 batchSize: newConfig.batchSize || DEFAULT_BATCH,
80 sourceName: newConfig.sourceName || '',
81 hostName: newConfig.hostName || '',
82 sourceCategory: newConfig.sourceCategory || '',
83 session: newConfig.sessionKey || getUUID(),
84 onSuccess: newConfig.onSuccess || NOOP,
85 onError: newConfig.onError || NOOP,
86 graphite: newConfig.graphite || false,
87 raw: newConfig.raw || false
88 };
89 }
90 }, {
91 key: "updateConfig",
92 value: function updateConfig() {
93 var newConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
94
95 if (newConfig.endpoint) {
96 this.config.endpoint = newConfig.endpoint;
97 }
98
99 if (newConfig.returnPromise) {
100 this.config.returnPromise = newConfig.returnPromise;
101 }
102
103 if (newConfig.useIntervalOnly) {
104 this.config.useIntervalOnly = newConfig.useIntervalOnly;
105 }
106
107 if (newConfig.interval) {
108 this.config.interval = newConfig.interval;
109 this.startLogSending();
110 }
111
112 if (newConfig.batchSize) {
113 this.config.batchSize = newConfig.batchSize;
114 }
115
116 if (newConfig.sourceCategory) {
117 this.config.sourceCategory = newConfig.sourceCategory;
118 }
119 }
120 }, {
121 key: "batchReadyToSend",
122 value: function batchReadyToSend() {
123 if (this.config.batchSize === 0) {
124 return this.config.interval === 0;
125 } else {
126 var pendingMessages = this.pendingLogs.reduce(function (acc, curr) {
127 var log = JSON.parse(curr);
128 return acc + log.msg + '\n';
129 }, '');
130 var pendingBatchSize = pendingMessages.length;
131 var ready = pendingBatchSize >= this.config.batchSize;
132
133 if (ready) {
134 this.stopLogSending();
135 }
136
137 return ready;
138 }
139 }
140 }, {
141 key: "_postSuccess",
142 value: function _postSuccess(logsSentLength) {
143 this.pendingLogs = this.pendingLogs.slice(logsSentLength); // Reset interval if needed:
144
145 this.startLogSending();
146 this.config.onSuccess();
147 }
148 }, {
149 key: "sendLogs",
150 value: function sendLogs() {
151 var _this = this;
152
153 if (this.pendingLogs.length === 0) {
154 return false;
155 }
156
157 try {
158 var headers = {
159 'X-Sumo-Client': 'sumo-javascript-sdk'
160 };
161
162 if (this.config.graphite) {
163 _extends(headers, {
164 'Content-Type': 'application/vnd.sumologic.graphite'
165 });
166 } else {
167 _extends(headers, {
168 'Content-Type': 'application/json'
169 });
170 }
171
172 if (this.config.sourceName !== '') {
173 _extends(headers, {
174 'X-Sumo-Name': this.config.sourceName
175 });
176 }
177
178 if (this.config.sourceCategory !== '') {
179 _extends(headers, {
180 'X-Sumo-Category': this.config.sourceCategory
181 });
182 }
183
184 if (this.config.hostName !== '') {
185 _extends(headers, {
186 'X-Sumo-Host': this.config.hostName
187 });
188 }
189
190 if (this.config.returnPromise && this.pendingLogs.length === 1) {
191 return superagent.post(this.config.endpoint).set(headers).send(this.pendingLogs.join('\n')).then(marshalHttpResponse).then(function (res) {
192 _this._postSuccess(1);
193
194 return res;
195 })["catch"](function (error) {
196 _this.config.onError(error);
197
198 return Promise.reject(error);
199 });
200 }
201
202 var logsToSend = Array.from(this.pendingLogs);
203 return superagent.post(this.config.endpoint).set(headers).send(logsToSend.join('\n')).then(marshalHttpResponse).then(function () {
204 return _this._postSuccess(logsToSend.length);
205 })["catch"](function (error) {
206 _this.config.onError(error);
207
208 if (_this.config.returnPromise) {
209 return Promise.reject(error);
210 }
211 });
212 } catch (ex) {
213 this.config.onError(ex);
214 return false;
215 }
216 }
217 }, {
218 key: "startLogSending",
219 value: function startLogSending() {
220 var _this2 = this;
221
222 if (this.config.interval > 0) {
223 if (this.interval) {
224 this.stopLogSending();
225 }
226
227 this.interval = setInterval(function () {
228 _this2.sendLogs();
229 }, this.config.interval);
230 }
231 }
232 }, {
233 key: "stopLogSending",
234 value: function stopLogSending() {
235 clearInterval(this.interval);
236 }
237 }, {
238 key: "emptyLogQueue",
239 value: function emptyLogQueue() {
240 this.pendingLogs = [];
241 }
242 }, {
243 key: "flushLogs",
244 value: function flushLogs() {
245 return this.sendLogs();
246 }
247 }, {
248 key: "log",
249 value: function log(msg, optionalConfig) {
250 var _this3 = this;
251
252 var message = msg;
253
254 if (!message) {
255 console.error('A value must be provided');
256 return false;
257 }
258
259 var isArray = message instanceof Array;
260 var testEl = isArray ? message[0] : message;
261
262 var type = _typeof(testEl);
263
264 if (type === 'undefined') {
265 console.error('A value must be provided');
266 return false;
267 }
268
269 if (this.config.graphite && (!Object.prototype.hasOwnProperty.call(testEl, 'path') || !Object.prototype.hasOwnProperty.call(testEl, 'value'))) {
270 console.error('Both "path" and "value" properties must be provided in the message object to send Graphite metrics');
271 return false;
272 }
273
274 if (type === 'object') {
275 if (Object.keys(message).length === 0) {
276 console.error('A non-empty JSON object must be provided');
277 return false;
278 }
279 }
280
281 if (!isArray) {
282 message = [message];
283 }
284
285 var ts = new Date();
286 var sessKey = this.config.session;
287 var client = {
288 url: this.config.clientUrl
289 };
290
291 if (optionalConfig) {
292 if (Object.prototype.hasOwnProperty.call(optionalConfig, 'sessionKey')) {
293 sessKey = optionalConfig.sessionKey;
294 }
295
296 if (Object.prototype.hasOwnProperty.call(optionalConfig, 'timestamp')) {
297 ts = optionalConfig.timestamp;
298 }
299
300 if (Object.prototype.hasOwnProperty.call(optionalConfig, 'url')) {
301 client.url = optionalConfig.url;
302 }
303 }
304
305 var timestamp = formatDate(ts);
306 var messages = message.map(function (item) {
307 if (_this3.config.graphite) {
308 return "".concat(item.path, " ").concat(item.value, " ").concat(Math.round(ts.getTime() / 1000));
309 }
310
311 if (_this3.config.raw) {
312 return item;
313 }
314
315 if (typeof item === 'string') {
316 return JSON.stringify(_extends({
317 msg: item,
318 sessionId: sessKey,
319 timestamp: timestamp
320 }, client));
321 }
322
323 var current = {
324 sessionId: sessKey,
325 timestamp: timestamp
326 };
327 return JSON.stringify(_extends(current, client, item));
328 });
329 this.pendingLogs = this.pendingLogs.concat(messages);
330
331 if (!this.config.useIntervalOnly && this.batchReadyToSend()) {
332 return this.sendLogs();
333 }
334 }
335 }]);
336
337 return SumoLogger;
338}();
339
340module.exports = SumoLogger;
\No newline at end of file