You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
5.3 KiB
JavaScript
187 lines
5.3 KiB
JavaScript
// Copyright (C) 2019-2021 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
const PluginRegistry = require('./plugins');
|
|
const serverProxy = require('./server-proxy');
|
|
const logFactory = require('./log');
|
|
const { ArgumentError } = require('./exceptions');
|
|
const { LogType } = require('./enums');
|
|
|
|
const WORKING_TIME_THRESHOLD = 100000; // ms, 1.66 min
|
|
|
|
function sleep(ms) {
|
|
return new Promise((resolve) => {
|
|
setTimeout(resolve, ms);
|
|
});
|
|
}
|
|
|
|
class LoggerStorage {
|
|
constructor() {
|
|
this.clientID = Date.now().toString().substr(-6);
|
|
this.lastLogTime = Date.now();
|
|
this.workingTime = 0;
|
|
this.collection = [];
|
|
this.ignoreRules = {}; // by event
|
|
this.isActiveChecker = null;
|
|
this.saving = false;
|
|
|
|
this.ignoreRules[LogType.zoomImage] = {
|
|
lastLog: null,
|
|
timeThreshold: 1000,
|
|
ignore(previousLog) {
|
|
return Date.now() - previousLog.time < this.timeThreshold;
|
|
},
|
|
};
|
|
|
|
this.ignoreRules[LogType.changeAttribute] = {
|
|
lastLog: null,
|
|
ignore(previousLog, currentPayload) {
|
|
return (
|
|
currentPayload.object_id === previousLog.payload.object_id &&
|
|
currentPayload.id === previousLog.payload.id
|
|
);
|
|
},
|
|
};
|
|
}
|
|
|
|
updateWorkingTime() {
|
|
if (!this.isActiveChecker || this.isActiveChecker()) {
|
|
const lastLogTime = Date.now();
|
|
const diff = lastLogTime - this.lastLogTime;
|
|
this.workingTime += diff < WORKING_TIME_THRESHOLD ? diff : 0;
|
|
this.lastLogTime = lastLogTime;
|
|
}
|
|
}
|
|
|
|
async configure(isActiveChecker, activityHelper) {
|
|
const result = await PluginRegistry.apiWrapper.call(
|
|
this,
|
|
LoggerStorage.prototype.configure,
|
|
isActiveChecker,
|
|
activityHelper,
|
|
);
|
|
return result;
|
|
}
|
|
|
|
async log(logType, payload = {}, wait = false) {
|
|
const result = await PluginRegistry.apiWrapper.call(this, LoggerStorage.prototype.log, logType, payload, wait);
|
|
return result;
|
|
}
|
|
|
|
async save() {
|
|
const result = await PluginRegistry.apiWrapper.call(this, LoggerStorage.prototype.save);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
LoggerStorage.prototype.configure.implementation = function (isActiveChecker, userActivityCallback) {
|
|
if (typeof isActiveChecker !== 'function') {
|
|
throw new ArgumentError('isActiveChecker argument must be callable');
|
|
}
|
|
|
|
if (!Array.isArray(userActivityCallback)) {
|
|
throw new ArgumentError('userActivityCallback argument must be an array');
|
|
}
|
|
|
|
this.isActiveChecker = () => !!isActiveChecker();
|
|
userActivityCallback.push(this.updateWorkingTime.bind(this));
|
|
};
|
|
|
|
LoggerStorage.prototype.log.implementation = function (logType, payload, wait) {
|
|
if (typeof payload !== 'object') {
|
|
throw new ArgumentError('Payload must be an object');
|
|
}
|
|
|
|
if (typeof wait !== 'boolean') {
|
|
throw new ArgumentError('Payload must be an object');
|
|
}
|
|
|
|
if (logType in this.ignoreRules) {
|
|
const ignoreRule = this.ignoreRules[logType];
|
|
const { lastLog } = ignoreRule;
|
|
if (lastLog && ignoreRule.ignore(lastLog, payload)) {
|
|
lastLog.payload = {
|
|
...lastLog.payload,
|
|
...payload,
|
|
};
|
|
|
|
this.updateWorkingTime();
|
|
return ignoreRule.lastLog;
|
|
}
|
|
}
|
|
|
|
const logPayload = { ...payload };
|
|
logPayload.client_id = this.clientID;
|
|
if (this.isActiveChecker) {
|
|
logPayload.is_active = this.isActiveChecker();
|
|
}
|
|
|
|
const log = logFactory(logType, { ...logPayload });
|
|
if (logType in this.ignoreRules) {
|
|
this.ignoreRules[logType].lastLog = log;
|
|
}
|
|
|
|
const pushEvent = () => {
|
|
this.updateWorkingTime();
|
|
log.validatePayload();
|
|
log.onClose(null);
|
|
this.collection.push(log);
|
|
};
|
|
|
|
if (log.type === LogType.sendException) {
|
|
serverProxy.server.exception(log.dump()).catch(() => {
|
|
pushEvent();
|
|
});
|
|
|
|
return log;
|
|
}
|
|
|
|
if (wait) {
|
|
log.onClose(pushEvent);
|
|
} else {
|
|
pushEvent();
|
|
}
|
|
|
|
return log;
|
|
};
|
|
|
|
LoggerStorage.prototype.save.implementation = async function () {
|
|
while (this.saving) {
|
|
await sleep(100);
|
|
}
|
|
|
|
const collectionToSend = [...this.collection];
|
|
const lastLog = this.collection[this.collection.length - 1];
|
|
|
|
const logPayload = {};
|
|
logPayload.client_id = this.clientID;
|
|
logPayload.working_time = this.workingTime;
|
|
if (this.isActiveChecker) {
|
|
logPayload.is_active = this.isActiveChecker();
|
|
}
|
|
|
|
if (lastLog && lastLog.type === LogType.sendTaskInfo) {
|
|
logPayload.job_id = lastLog.payload.job_id;
|
|
logPayload.task_id = lastLog.payload.task_id;
|
|
}
|
|
|
|
const userActivityLog = logFactory(LogType.sendUserActivity, logPayload);
|
|
collectionToSend.push(userActivityLog);
|
|
|
|
try {
|
|
this.saving = true;
|
|
await serverProxy.logs.save(collectionToSend.map((log) => log.dump()));
|
|
for (const rule of Object.values(this.ignoreRules)) {
|
|
rule.lastLog = null;
|
|
}
|
|
this.collection = [];
|
|
this.workingTime = 0;
|
|
this.lastLogTime = Date.now();
|
|
} finally {
|
|
this.saving = false;
|
|
}
|
|
};
|
|
|
|
module.exports = new LoggerStorage();
|