vtex
Version:
The platform for e-commerce apps
120 lines (119 loc) • 4.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const ramda_1 = require("ramda");
const env_1 = require("../../api/env");
const ErrorKinds_1 = require("../../api/error/ErrorKinds");
const ErrorReport_1 = require("../../api/error/ErrorReport");
const locator_1 = require("../../api/locator");
const logger_1 = tslib_1.__importDefault(require("../../api/logger"));
const verbose_1 = require("../../verbose");
const CustomEventSource_1 = require("./CustomEventSource");
const levelAdapter = { warning: 'warn' };
const onOpen = (type) => () => logger_1.default.debug(`Connected to ${type} server`);
const onError = (type) => (err) => {
logger_1.default.error(`Connection to ${type} server has failed with status ${err.event.status}`);
ErrorReport_1.ErrorReport.createAndMaybeRegisterOnTelemetry({
kind: ErrorKinds_1.ErrorKinds.SSE_ERROR,
originalError: err,
}).logErrorForUser({ coreLogLevelDefault: 'debug', logLevels: { core: { errorId: 'error' } } });
};
const parseMessage = (msg) => {
const { sender, subject, level, body } = JSON.parse(msg.data);
return {
body,
level: levelAdapter[level] || level,
sender,
subject,
};
};
const parseKeyToQueryParameter = (keys) => {
let urlQueryParameters = '';
ramda_1.forEach(key => {
urlQueryParameters += `&keys=${key}`;
}, keys);
return urlQueryParameters;
};
const matchSubject = (msg, subject) => {
return (msg.subject.startsWith(subject) ||
(msg.subject.startsWith('-') && ramda_1.pathOr('', ['body', 'subject'], msg).startsWith(subject)));
};
const hasNoSubject = (msg) => {
return msg.subject.startsWith('-') && !ramda_1.path(['body', 'subject'], msg);
};
const filterMessage = (subject, logAny = false, senders) => (msg) => {
return ((matchSubject(msg, subject) || (logAny && hasNoSubject(msg))) &&
(!senders || ramda_1.contains(locator_1.removeVersion(msg.sender), senders)) &&
msg);
};
const maybeCall = (callback) => (msg) => {
if (msg) {
callback(msg);
}
};
const onLog = (ctx, subject, logLevel, callback, senders) => {
const source = `${env_1.colossusEndpoint()}/${ctx.account}/${ctx.workspace}/logs?level=${logLevel}`;
const es = CustomEventSource_1.CustomEventSource.create({ source, closeOnInvalidToken: true });
es.onopen = onOpen(`${logLevel} log`);
es.onmessage = ramda_1.compose(maybeCall(callback), filterMessage(subject, true, senders), parseMessage);
es.onerror = onError(`${logLevel} log`);
return es.close.bind(es);
};
exports.onEvent = (ctx, sender, subject, keys, callback) => {
const source = `${env_1.colossusEndpoint()}/${ctx.account}/${ctx.workspace}/events?onUnsubscribe=link_interrupted&sender=${sender}${parseKeyToQueryParameter(keys)}`;
const es = CustomEventSource_1.CustomEventSource.create({ source, closeOnInvalidToken: true });
es.onopen = onOpen('event');
es.onmessage = ramda_1.compose(maybeCall(callback), filterMessage(subject), parseMessage);
es.onerror = onError('event');
return es.close.bind(es);
};
const filterAndMaybeLogVTEXLogs = (message) => {
// Because stdout is buffered, __VTEX_IO_LOG objects might be interpolated with regular stdout messages.
if (!message) {
return '';
}
return (message
.split('\n')
.map((m) => {
try {
const obj = JSON.parse(m);
if (obj.__VTEX_IO_LOG) {
if (verbose_1.isVerbose) {
delete obj.__VTEX_IO_LOG;
console.log(chalk_1.default.dim('// The following object was logged to Splunk:'));
console.log(obj);
}
return '';
}
// Not a log object, just return original string
return m;
}
catch (e) {
// Not an object, just return original string
return m;
}
})
.filter(s => s !== '')
// Undo split
.join('\n'));
};
exports.logAll = (context, logLevel, id, senders) => {
let previous = '';
const callback = ({ sender, level, body: { message: rawMessage, code } }) => {
if (!(rawMessage || code)) {
return; // Ignore logs without message or code.
}
const message = filterAndMaybeLogVTEXLogs(rawMessage);
if (!message) {
return;
}
const suffix = sender.startsWith(id) ? '' : ` ${chalk_1.default.gray(sender)}`;
const formatted = (message || code || '').replace(/\n\s*$/, '') + suffix;
if (previous !== formatted) {
previous = formatted;
logger_1.default.log(level, formatted);
}
};
return onLog(context, id, logLevel, callback, senders);
};