vibex-sh 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +108 -17
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -17,6 +17,7 @@ const MAX_POLL_ATTEMPTS = 60;
|
|
|
17
17
|
const WEBSOCKET_CLOSE_TIMEOUT_MS = 2000;
|
|
18
18
|
const DEFAULT_WORKER_URL = 'https://ingest.vibex.sh';
|
|
19
19
|
const DEFAULT_WEB_URL = 'https://vibex.sh';
|
|
20
|
+
const PIPED_INPUT_DELAY_MS = parseInt(process.env.VIBEX_PIPE_DELAY_MS || '300', 10);
|
|
20
21
|
|
|
21
22
|
// Get version from package.json
|
|
22
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -389,24 +390,38 @@ async function handleInit(options) {
|
|
|
389
390
|
];
|
|
390
391
|
}
|
|
391
392
|
|
|
392
|
-
//
|
|
393
|
-
const
|
|
393
|
+
// Mandatory parsers that are always included
|
|
394
|
+
const mandatoryParserIds = ['json-in-text', 'raw', 'keyvalue', 'stacktrace', 'smart-pattern'];
|
|
394
395
|
|
|
395
|
-
|
|
396
|
+
// Filter out mandatory parsers for selection (only optional parsers can be selected)
|
|
397
|
+
const selectableParsers = availableParsers.filter(p => !mandatoryParserIds.includes(p.id) && !p.isMandatory);
|
|
398
|
+
|
|
399
|
+
// Pre-select mandatory parsers
|
|
400
|
+
let enabledParsers = [...mandatoryParserIds];
|
|
401
|
+
|
|
402
|
+
console.log(' Mandatory parsers are automatically included:');
|
|
403
|
+
mandatoryParserIds.forEach(id => {
|
|
404
|
+
const parser = availableParsers.find(p => p.id === id);
|
|
405
|
+
if (parser) {
|
|
406
|
+
console.log(` ✓ ${parser.name}`);
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
console.log('');
|
|
410
|
+
|
|
411
|
+
console.log(' Select additional optional parsers (leave empty for mandatory only):');
|
|
396
412
|
if (selectableParsers.length > 0) {
|
|
397
|
-
console.log(' Available
|
|
413
|
+
console.log(' Available optional parsers:');
|
|
398
414
|
selectableParsers.forEach((p, i) => {
|
|
399
415
|
console.log(` ${i + 1}. ${p.name} (${p.id})`);
|
|
400
416
|
});
|
|
401
|
-
console.log(' (Leave empty for
|
|
417
|
+
console.log(' (Leave empty for mandatory parsers only)\n');
|
|
402
418
|
} else {
|
|
403
|
-
console.log('
|
|
419
|
+
console.log(' No additional optional parsers available.\n');
|
|
404
420
|
}
|
|
405
421
|
|
|
406
|
-
const answer = await question(' Enter comma-separated numbers or parser IDs (e.g., 1,2 or
|
|
422
|
+
const answer = await question(' Enter comma-separated numbers or parser IDs (e.g., 1,2 or docker,kubernetes): ');
|
|
407
423
|
rl.close();
|
|
408
424
|
|
|
409
|
-
let enabledParsers = [];
|
|
410
425
|
if (answer.trim()) {
|
|
411
426
|
const selections = answer.split(',').map(s => s.trim());
|
|
412
427
|
selections.forEach(sel => {
|
|
@@ -424,7 +439,9 @@ async function handleInit(options) {
|
|
|
424
439
|
const parserFlag = options.parser || options.parsers;
|
|
425
440
|
if (parserFlag) {
|
|
426
441
|
if (typeof parserFlag === 'string') {
|
|
427
|
-
|
|
442
|
+
// Add optional parsers from flag, but always include mandatory
|
|
443
|
+
const flagParsers = parserFlag.split(',').map(p => p.trim());
|
|
444
|
+
enabledParsers = [...new Set([...mandatoryParserIds, ...flagParsers])];
|
|
428
445
|
}
|
|
429
446
|
}
|
|
430
447
|
|
|
@@ -466,10 +483,18 @@ async function handleInit(options) {
|
|
|
466
483
|
|
|
467
484
|
console.log('\n ✅ Session created successfully!\n');
|
|
468
485
|
printBanner(createdSessionId, createdAuthCode);
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
486
|
+
|
|
487
|
+
// Separate mandatory and optional parsers for display
|
|
488
|
+
const mandatoryIncluded = enabledParsers.filter(id => mandatoryParserIds.includes(id));
|
|
489
|
+
const optionalIncluded = enabledParsers.filter(id => !mandatoryParserIds.includes(id));
|
|
490
|
+
|
|
491
|
+
if (mandatoryIncluded.length > 0) {
|
|
492
|
+
console.log(` 📋 Mandatory parsers: ${mandatoryIncluded.join(', ')}`);
|
|
493
|
+
}
|
|
494
|
+
if (optionalIncluded.length > 0) {
|
|
495
|
+
console.log(` 📋 Optional parsers: ${optionalIncluded.join(', ')}`);
|
|
496
|
+
} else if (mandatoryIncluded.length === mandatoryParserIds.length) {
|
|
497
|
+
console.log(' 📋 Using mandatory parsers only');
|
|
473
498
|
}
|
|
474
499
|
console.log(`\n 💡 Use this session ID: ${createdSessionId}`);
|
|
475
500
|
console.log(` Example: echo '{"cpu": 45}' | npx vibex-sh -s ${createdSessionId}\n`);
|
|
@@ -1036,6 +1061,56 @@ async function handleSendLogs(options) {
|
|
|
1036
1061
|
process.exit(0);
|
|
1037
1062
|
}
|
|
1038
1063
|
|
|
1064
|
+
// Rate limiting queue for piped input
|
|
1065
|
+
const pipedLogQueue = [];
|
|
1066
|
+
let isProcessingQueue = false;
|
|
1067
|
+
let queueProcessingTimeout = null;
|
|
1068
|
+
|
|
1069
|
+
const processPipedLogQueue = async () => {
|
|
1070
|
+
if (isProcessingQueue) {
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
if (pipedLogQueue.length === 0) {
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
isProcessingQueue = true;
|
|
1079
|
+
|
|
1080
|
+
try {
|
|
1081
|
+
while (pipedLogQueue.length > 0) {
|
|
1082
|
+
const logData = pipedLogQueue.shift();
|
|
1083
|
+
await sendLogViaHTTP(logData);
|
|
1084
|
+
|
|
1085
|
+
// Wait before sending the next log (only if there are more logs in queue)
|
|
1086
|
+
if (pipedLogQueue.length > 0) {
|
|
1087
|
+
await new Promise(resolve => setTimeout(resolve, PIPED_INPUT_DELAY_MS));
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
} finally {
|
|
1091
|
+
isProcessingQueue = false;
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
|
|
1095
|
+
const queuePipedLog = (logData) => {
|
|
1096
|
+
pipedLogQueue.push(logData);
|
|
1097
|
+
|
|
1098
|
+
// Start processing if not already processing
|
|
1099
|
+
if (!isProcessingQueue) {
|
|
1100
|
+
// Clear any existing timeout
|
|
1101
|
+
if (queueProcessingTimeout) {
|
|
1102
|
+
clearTimeout(queueProcessingTimeout);
|
|
1103
|
+
queueProcessingTimeout = null;
|
|
1104
|
+
}
|
|
1105
|
+
// Process queue with a small initial delay to batch rapid inputs
|
|
1106
|
+
queueProcessingTimeout = setTimeout(() => {
|
|
1107
|
+
processPipedLogQueue().catch((error) => {
|
|
1108
|
+
console.error(' ✗ Error processing log queue:', error.message);
|
|
1109
|
+
});
|
|
1110
|
+
}, 10);
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1039
1114
|
const rl = readline.createInterface({
|
|
1040
1115
|
input: process.stdin,
|
|
1041
1116
|
output: process.stdout,
|
|
@@ -1086,13 +1161,29 @@ async function handleSendLogs(options) {
|
|
|
1086
1161
|
};
|
|
1087
1162
|
}
|
|
1088
1163
|
|
|
1089
|
-
//
|
|
1090
|
-
//
|
|
1091
|
-
|
|
1164
|
+
// Queue logs for rate-limited sending when input is piped
|
|
1165
|
+
// This prevents overwhelming rate limits when piping large files
|
|
1166
|
+
queuePipedLog(logData);
|
|
1092
1167
|
});
|
|
1093
1168
|
|
|
1094
1169
|
rl.on('close', async () => {
|
|
1095
|
-
//
|
|
1170
|
+
// Clear any pending queue processing timeout
|
|
1171
|
+
if (queueProcessingTimeout) {
|
|
1172
|
+
clearTimeout(queueProcessingTimeout);
|
|
1173
|
+
queueProcessingTimeout = null;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
// Process any remaining logs in the piped queue
|
|
1177
|
+
// Keep processing until queue is empty and not currently processing
|
|
1178
|
+
while (pipedLogQueue.length > 0 || isProcessingQueue) {
|
|
1179
|
+
await processPipedLogQueue();
|
|
1180
|
+
// Small delay to allow processing to complete
|
|
1181
|
+
if (pipedLogQueue.length > 0 || isProcessingQueue) {
|
|
1182
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// Wait for queued logs to be sent (WebSocket queue)
|
|
1096
1187
|
const waitForQueue = () => {
|
|
1097
1188
|
return new Promise((resolve) => {
|
|
1098
1189
|
if (logQueue.length === 0) {
|