@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
154 lines (125 loc) • 3.93 kB
JavaScript
import { Deque } from "../../../core/collection/queue/Deque.js";
import { LoggerBackend } from "../LoggerBackend.js";
/**
Transformer function to transform log data as provided by winston into
a message structure which is more appropriate for indexing in ES.
@param {Object} logData
@param {Object} logData.message - the log message
@param {Object} logData.level - the log level
@param {Object} logData.meta - the log meta data (JSON object)
@returns {Object} transformed message
*/
function defaultTransformer(logData) {
const transformed = {};
transformed['@timestamp'] = logData.timestamp ? logData.timestamp : new Date().toISOString();
transformed.message = logData.message;
transformed.severity = logData.level;
transformed.fields = logData.meta;
if (logData.meta['transaction.id']) transformed.transaction = { id: logData.meta['transaction.id'] };
if (logData.meta['trace.id']) transformed.trace = { id: logData.meta['trace.id'] };
if (logData.meta['span.id']) transformed.span = { id: logData.meta['span.id'] };
return transformed;
}
class Record {
constructor() {
this.time = 0;
this.message = 0;
this.level = 0;
}
}
export class ElasticSearchLogger extends LoggerBackend {
constructor({
url = 'http://localhost:9200',
target = `log-${new Date().toISOString()}`
} = {}) {
super();
/**
*
* @type {Deque<Record>}
* @private
*/
this.__buffer = new Deque();
/**
* Number of records
* @type {number}
* @private
*/
this.__flush_size = 500;
/**
* In milliseconds
* @type {number}
* @private
*/
this.__flush_timeout = 2000;
/**
*
* @type {string}
* @private
*/
this.__url = url;
/**
*
* @type {string}
* @private
*/
this.__target = target;
/**
* setTimeout handle
* @type {number}
* @private
*/
this.__timeout_ms = -1;
/**
*
* @type {any}
* @private
*/
this.__bound_flush = this.flush.bind(this);
}
flush() {
// clear timeout
if (this.__timeout !== -1) {
clearTimeout(this.__timeout);
this.__timeout = -1;
}
const buffer = this.__buffer;
if (buffer.isEmpty()) {
// do nothing
return;
}
const data = [];
while (!buffer.isEmpty()) {
const record = buffer.removeFirst();
data.push({
create: {
'@timestamp': record.time,
'level': record.level,
'message': record.message
}
});
}
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = (evt) => {
console.warn(evt);
};
xhr.open('POST', `${this.__url}/${this.__target}/_bulk`, true);
xhr.overrideMimeType('text/plain');
xhr.send(JSON.stringify(data));
}
__prod() {
const buffer_size = this.__buffer.size();
if (buffer_size >= this.__flush_size) {
this.flush();
} else if (this.__timeout === -1) {
this.__timeout = setTimeout(this.__bound_flush, this.__flush_timeout);
}
}
log(level, message) {
const record = new Record();
record.message = message;
record.level = level;
record.time = performance.now();
this.__buffer.addLast(record);
this.__prod();
}
}