New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

errsole

Package Overview
Dependencies
Maintainers
0
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

errsole - npm Package Compare versions

Comparing version 2.9.1 to 2.9.2

docs/advanced-configuration.md

84

docs/benchmarks.md

@@ -5,3 +5,3 @@ # Benchmarks

To benchmark Errsole against Elasticsearch, we conducted tests under the following setup:
To benchmark Errsole against Elasticsearch and Amazon CloudWatch, we conducted tests under the following setup:

@@ -14,66 +14,58 @@ 1. **Node.js Application:**

* **Specifications:** 2 CPUs, 8 GB RAM
3. **Elasticsearch Server:**
3. **PostgreSQL Server:**
* **Instance Type:** m5.large EC2 Instance
* **Specifications:** 2 CPUs, 8 GB RAM
4. **Load Testing Tool:** Grafana K6
4. **MongoDB Server:**
* **Instance Type:** m5.large EC2 Instance
* **Specifications:** 2 CPUs, 8 GB RAM
5. **Elasticsearch Server:**
* **Instance Type:** m5.large EC2 Instance
* **Specifications:** 2 CPUs, 8 GB RAM
6. **Load Testing Tool:** Grafana K6
## Elasticsearch
We conducted load testing under three different configurations to compare performance:
We tested the following configurations:
1. **Winston + Elasticsearch:**
1. **Winston + Elasticsearch:** Configured the Node.js app with Winston for logging and Elasticsearch as the storage backend.
2. **Pino + Elasticsearch:** Configured the Node.js app with Pino for logging and Elasticsearch as the storage backend.
3. **Errsole + SQLite:** Configured the Node.js app with Errsole for logging and SQLite as the storage backend.
4. **Errsole + MySQL:** Configured the Node.js app with Errsole for logging and MySQL as the storage backend.
5. **Errsole + PostgreSQL:** Configured the Node.js app with Errsole for logging and PostgreSQL as the storage backend.
6. **Errsole + MongoDB:** Configured the Node.js app with Errsole for logging and MongoDB as the storage backend.
Configured the Node.js app with Winston for logging and Elasticsearch as the storage backend.
2. **Pino + Elasticsearch:**
Configured the Node.js app with Pino for logging and Elasticsearch as the storage backend.
3. **Errsole + MySQL:**
Configured the Node.js app with Errsole for logging and MySQL as the storage backend.
### Results
Errsole demonstrated a significant performance advantage, handling 79,000 - 85,000 more requests per minute compared to Elasticsearch configurations.
Errsole demonstrated a significant performance advantage, handling 70,000 - 90,000 more requests per minute compared to Elasticsearch configurations.
| **Test No.** | **Pino + Elasticsearch** | **Winston + Elasticsearch** | **Errsole + MySQL** |
|-------------- |-------------------------- |----------------------------- |--------------------- |
| 1 | 265363 | 268917 | 349623 |
| 2 | 265160 | 273568 | 352383 |
| 3 | 272862 | 274449 | 351421 |
| 4 | 259297 | 270090 | 350173 |
| 5 | 263454 | 271782 | 350188 |
| **Average** | **265227** | **271761** | **350758** |
| **Test No.** | **Pino + Elasticsearch** | **Winston + Elasticsearch** | **Errsole + MongoDB** | **Errsole + MySQL** | **Errsole + PostgreSQL** | **Errsole + SQLite** |
|-------------- |-------------------------- |----------------------------- |----------------------- |--------------------- |-------------------------- |---------------------- |
| 1 | 265363 | 268917 | 340490 | 349623 | 360264 | 370499 |
| 2 | 265160 | 273568 | 338163 | 352383 | 360785 | 362611 |
| 3 | 272862 | 274449 | 338963 | 351421 | 364411 | 364310 |
| 4 | 259297 | 270090 | 337759 | 350173 | 367953 | 361347 |
| 5 | 263454 | 271782 | 340265 | 350188 | 367309 | 362578 |
| **Average** | **265227** | **271761** | **339128** | **350758** | **364144** | **364269** |
<img src="https://github.com/user-attachments/assets/14eb3290-a2d5-4365-8926-532120e2c6c5" alt="errsole-vs-elasticsearch-benchmarks" width="800">
<img src="https://github.com/user-attachments/assets/e193e016-a14a-46c1-92af-865b3be27df4" alt="errsole-vs-elasticsearch-benchmarks" width="800">
## Amazon CloudWatch
We also conducted tests comparing the performance of Errsole with Amazon CloudWatch.
We also conducted tests comparing the performance of Errsole with Amazon CloudWatch:
1. **Winston + CloudWatch:**
1. **Winston + CloudWatch:** Configured the Node.js app with Winston for logging and CloudWatch as the storage backend.
2. **Pino + CloudWatch:** Configured the Node.js app with Pino for logging and CloudWatch as the storage backend.
Configured the Node.js app with Winston for logging and CloudWatch as the storage backend.
2. **Pino + CloudWatch:**
Configured the Node.js app with Pino for logging and CloudWatch as the storage backend.
3. **Errsole + MySQL:**
Configured the Node.js app with Errsole for logging and MySQL as the storage backend.
### Results
Errsole significantly outperformed all CloudWatch configurations in benchmark tests. It handled 296,000 more requests per minute than direct CloudWatch and 55,000 more requests per minute than Pino + CloudWatch. Notably, Winston + CloudWatch failed in all test scenarios.
Errsole significantly outperformed all CloudWatch configurations in benchmark tests. It handled 280,000 - 300,000 more requests per minute than direct CloudWatch and 40,000 - 70,000 more requests per minute than Pino + CloudWatch. Notably, Winston + CloudWatch failed in all test scenarios.
| **Test No.** | **CloudWatch** | **Winston + CloudWatch** | **Pino + CloudWatch** | **Errsole + MySQL** |
|-------------- |---------------- |-------------------------- |----------------------- |--------------------- |
| 1 | 54185 | Failed | 296752 | 349623 |
| 2 | 55126 | Failed | 290988 | 352383 |
| 3 | 54932 | Failed | 301431 | 351421 |
| 4 | 54859 | Failed | 292222 | 350173 |
| 5 | 55239 | Failed | 294272 | 350188 |
| **Average** | **54868** | **Failed** | **295133** | **350758** |
| **Test No.** | **CloudWatch** | **Winston + CloudWatch** | **Pino + CloudWatch** | **Errsole + MongoDB** | **Errsole + MySQL** | **Errsole + PostgreSQL** | **Errsole + SQLite** |
|-------------- |---------------- |-------------------------- |----------------------- |----------------------- |--------------------- |-------------------------- |---------------------- |
| 1 | 54185 | Failed | 296752 | 340490 | 349623 | 360264 | 370499 |
| 2 | 55126 | Failed | 290988 | 338163 | 352383 | 360785 | 362611 |
| 3 | 54932 | Failed | 301431 | 338963 | 351421 | 364411 | 364310 |
| 4 | 54859 | Failed | 292222 | 337759 | 350173 | 367953 | 361347 |
| 5 | 55239 | Failed | 294272 | 340265 | 350188 | 367309 | 362578 |
| **Average** | **54868** | **Failed** | **295133** | **339128** | **350758** | **364144** | **364269** |

@@ -80,0 +72,0 @@ ## Benchmarks Code

'use strict';
const ErrsoleMain = require('./main');
const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware');

@@ -8,3 +8,3 @@ const koaProxies = require('koa-proxies');

const http = require('http');
const ErrsoleMain = require('./main');
const Errsole = {

@@ -183,3 +183,3 @@ port: 8001

Errsole.hapiProxyMiddleware = function (basePath) {
Errsole.hapiProxyMiddleware = function (basePath, auth = false) {
const targetURL = 'http://localhost:' + this.port;

@@ -204,2 +204,5 @@ return {

}
},
options: {
auth
}

@@ -211,1 +214,2 @@ });

module.exports = Errsole;
module.exports.default = Errsole;

@@ -12,2 +12,4 @@ 'use strict';

serverName: null,
pendingAlerts: [],
isInitializated: false,

@@ -20,2 +22,4 @@ initialize (options) {

this.handleUncaughtExceptions(options.exitOnException);
this.isInitializated = true;
this.flushAlerts();
},

@@ -55,3 +59,3 @@

async customLogger (level, message, metadata) {
Logs.customLogger(level, message, metadata);
Logs.logCustomMessage(level, message, metadata);
if (level === 'alert') {

@@ -63,3 +67,7 @@ const messageExtraInfo = {

};
await Alerts.customLoggerAlert(message, messageExtraInfo);
if (this.isInitializated) {
await Alerts.customLoggerAlert(message, messageExtraInfo);
} else {
this.pendingAlerts.push({ message, messageExtraInfo });
}
}

@@ -78,9 +86,26 @@ },

};
await Alerts.handleUncaughtExceptions(`${errorOrigin}\n${errorMessage}`, messageExtraInfo);
await Logs.clearLogsBeforeExit();
if (this.isInitializated) {
await Alerts.handleUncaughtExceptions(`${errorOrigin}\n${errorMessage}`, messageExtraInfo);
await Logs.flushLogs();
}
if (exitOnException) process.exit(1);
});
},
async flushAlerts () {
const alertsToFlush = [...this.pendingAlerts];
this.pendingAlerts = [];
try {
for (let i = 0; i < alertsToFlush.length; i++) {
const { message, messageExtraInfo } = alertsToFlush[i];
await Alerts.customLoggerAlert(message, messageExtraInfo);
}
} catch (err) {
console.error('Failed to flush alerts:', err);
}
}
};
module.exports = Main;

@@ -11,94 +11,156 @@ const stream = require('stream');

const CollectLogsHook = {
const logCollector = {
storage: {},
collectLogs: [],
hostname: null,
collectLogs: [LogLevel.INFO, LogLevel.ERROR],
enableConsoleOutput: process.env.NODE_ENV !== 'production',
hostname: os.hostname(),
pid,
enableConsoleOutput: process.env.NODE_ENV !== 'production'
};
isInitializationFailed: false,
originalStdoutWrite: process.stdout.write,
originalStderrWrite: process.stderr.write,
CollectLogsHook.initialize = function (options) {
this.storage = options.storage;
this.hostname = options.serverName || os.hostname();
if (options && typeof options.enableConsoleOutput !== 'undefined') {
this.enableConsoleOutput = options.enableConsoleOutput;
}
this.collectLogs = options.collectLogs || ['info', 'error'];
if (this.collectLogs.includes(LogLevel.INFO)) {
this.captureLogs(LogLevel.INFO);
console.log('Errsole is capturing INFO logs.');
} else {
console.log('Errsole is NOT capturing INFO logs.');
}
if (this.collectLogs.includes(LogLevel.ERROR)) {
this.captureLogs(LogLevel.ERROR);
console.log('Errsole is capturing ERROR logs.');
} else {
console.log('Errsole is NOT capturing ERROR logs.');
}
};
setInitializationTimeout () {
this.initializationTimeoutId = setTimeout(() => {
this.createEmptyLogStream();
this.isInitializationFailed = true;
console.error('Error: Unable to initialize Errsole');
}, 10000);
},
CollectLogsHook.captureLogs = function (level) {
const self = this;
if (self.storage.once) {
self.storage.once('ready', function () {
if (!self.enableConsoleOutput) {
const writeFunction = level === LogLevel.INFO ? process.stdout : process.stderr;
writeFunction.write = function () {
try {
const argsArray = Array.from(arguments);
logBuffer.write.apply(logBuffer, argsArray);
} catch (err) { }
};
initialize (options = {}) {
this.storage = options.storage;
this.collectLogs = options.collectLogs || [LogLevel.INFO, LogLevel.ERROR];
if (typeof options.enableConsoleOutput !== 'undefined') {
this.enableConsoleOutput = options.enableConsoleOutput;
}
this.hostname = options.serverName || os.hostname();
if (this.storage.once) {
this.storage.once('ready', () => {
clearTimeout(this.initializationTimeoutId);
if (this.isInitializationFailed) {
this.createLogStream();
this.isInitializationFailed = false;
} else {
this.logStream.uncork();
}
});
}
if (this.enableConsoleOutput) {
process.stdout.write = this.originalStdoutWrite;
process.stderr.write = this.originalStderrWrite;
} else {
process.stdout.write = (chunk, encoding, done) => done();
process.stderr.write = (chunk, encoding, done) => done();
}
if (this.collectLogs.includes(LogLevel.INFO)) {
this.interceptLogs(LogLevel.INFO);
console.log(`Errsole is capturing ${LogLevel.INFO.toUpperCase()} logs.`);
} else {
console.log(`Errsole is NOT capturing ${LogLevel.INFO.toUpperCase()} logs.`);
}
if (this.collectLogs.includes(LogLevel.ERROR)) {
this.interceptLogs(LogLevel.ERROR);
console.log(`Errsole is capturing ${LogLevel.ERROR.toUpperCase()} logs.`);
} else {
console.log(`Errsole is NOT capturing ${LogLevel.ERROR.toUpperCase()} logs.`);
}
},
createLogStream () {
this.logStream = new stream.Writable({
objectMode: true,
write: (logEntry, encoding, callback) => {
this.storage.postLogs([logEntry]);
setImmediate(callback);
}
});
}
const logBuffer = new stream.Writable();
logBuffer._write = (chunk, encoding, done) => {
try {
const cleanedChunk = stripAnsi(chunk.toString());
const logEntry = { timestamp: new Date().toISOString(), message: cleanedChunk, source: 'console', level, hostname: self.hostname || '', pid: self.pid || 0 };
self.logStream.write(logEntry);
done();
} catch (err) { }
};
},
const originalWrite = level === LogLevel.INFO ? process.stdout.write : process.stderr.write;
const writeFunction = level === LogLevel.INFO ? process.stdout : process.stderr;
createEmptyLogStream () {
if (this.logStream) {
this.logStream.destroy();
}
this.logStream = new stream.Writable({
objectMode: true,
write: (logEntry, encoding, callback) => {
setImmediate(callback);
}
});
},
writeFunction.write = function () {
try {
const argsArray = Array.from(arguments);
originalWrite.apply(writeFunction, argsArray);
logBuffer.write.apply(logBuffer, argsArray);
} catch (err) { }
};
};
interceptLogs (level) {
let logStream;
let originalWrite;
switch (level) {
case LogLevel.INFO:
logStream = process.stdout;
originalWrite = this.originalStdoutWrite;
break;
case LogLevel.ERROR:
logStream = process.stderr;
originalWrite = this.originalStderrWrite;
break;
default:
return;
}
CollectLogsHook.customLogger = function (level, message, metadata) {
try {
const logEntry = { timestamp: new Date().toISOString(), message, meta: metadata || '{}', source: 'errsole', level, hostname: this.hostname || '', pid: this.pid || 0 };
this.logStream.write(logEntry);
} catch (err) { }
};
logStream.write = (chunk, encoding, done) => {
const cleanedChunk = stripAnsi(chunk.toString());
const logEntry = {
timestamp: new Date().toISOString(),
message: cleanedChunk,
source: 'console',
level,
hostname: this.hostname,
pid: this.pid
};
this.logStream.write(logEntry);
CollectLogsHook.logStream = new stream.Writable({
objectMode: true,
write (logEntry, encoding, callback) {
CollectLogsHook.storage.postLogs([logEntry]);
setImmediate(() => callback());
}
});
if (this.enableConsoleOutput) {
originalWrite.call(logStream, chunk, encoding, done);
} else if (done) {
done();
}
};
},
CollectLogsHook.clearLogsBeforeExit = async function (timeout = 5000) {
if (typeof this.storage.flushLogs === 'function') {
async flushLogs (timeout = 5000) {
if (typeof this.storage.flushLogs === 'function') {
try {
await Promise.race([
this.storage.flushLogs(),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('flushLogs timed out')), timeout))
]);
} catch (err) {
console.error(err);
}
}
},
logCustomMessage (level, message, metadata) {
const logEntry = {
timestamp: new Date().toISOString(),
message,
meta: metadata || '{}',
source: 'errsole',
level,
hostname: this.hostname,
pid: this.pid
};
try {
await Promise.race([
this.storage.flushLogs(),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('flushLogs timed out')), timeout))
]);
} catch (err) { }
this.logStream.write(logEntry);
} catch (err) {
console.error(err);
}
}
};
module.exports = CollectLogsHook;
logCollector.setInitializationTimeout();
logCollector.createLogStream();
logCollector.logStream.cork();
logCollector.interceptLogs(LogLevel.INFO);
logCollector.interceptLogs(LogLevel.ERROR);
module.exports = logCollector;

@@ -209,1 +209,3 @@ const { getStorageConnection } = require('../storageConnection');

};
exports.SlackService = SlackService;
exports.EmailService = EmailService;
{
"name": "errsole",
"version": "2.9.1",
"version": "2.9.2",
"description": "Collect, Store, and Visualize Logs with a Single Module",

@@ -24,5 +24,7 @@ "keywords": [

"examples",
"lib"
"lib",
"types"
],
"main": "lib/errsole",
"main": "lib/errsole.js",
"types": "types/errsole.d.ts",
"scripts": {

@@ -79,8 +81,3 @@ "build:web": "NODE_OPTIONS=--openssl-legacy-provider webpack --config lib/web/webpack/website.config.js",

"webpack-merge": "^5.10.0"
},
"jest": {
"coveragePathIgnorePatterns": [
"/lib/main/server/utils/alerts.js"
]
}
}

@@ -41,5 +41,5 @@ <p align="center">

Errsole outperforms Elasticsearch by 80,000 requests per minute. [Read More](https://github.com/errsole/errsole.js/blob/master/docs/benchmarks.md)
A Node.js app using Errsole Logger can handle 90,000 more requests per minute than when using Elasticsearch and 70,000 more requests per minute than when using Amazon CloudWatch. [Read More](https://github.com/errsole/errsole.js/blob/master/docs/benchmarks.md)
<img src="https://github.com/user-attachments/assets/14eb3290-a2d5-4365-8926-532120e2c6c5" alt="errsole-vs-elasticsearch-benchmarks" width="800">
<img src="https://github.com/user-attachments/assets/e193e016-a14a-46c1-92af-865b3be27df4" alt="errsole-vs-elasticsearch-benchmarks" width="800">

@@ -54,2 +54,3 @@ ## Setup

* [Errsole with OracleDB](https://github.com/errsole/errsole.js/blob/master/docs/oracledb-storage.md)
* [Advanced Configuration](https://github.com/errsole/errsole.js/blob/master/docs/advanced-configuration.md)

@@ -148,10 +149,16 @@ ## Web Dashboard Access

## Contribution and Support
## Useful Links
**Contribution:** We welcome contributions! If you have ideas for improvements, feel free to fork the repository, make your changes, and submit a pull request.
* [FAQs](https://github.com/errsole/errsole.js/discussions/categories/faqs)
**Support:** Have questions, facing issues, or want to request a feature? [Open an issue](https://github.com/errsole/errsole.js/issues/new) on the GitHub repository.
* **Encountering issues?** [Open an issue](https://github.com/errsole/errsole.js/issues/new) on our GitHub repository.
* **Have questions?** Use our [Q&A forum](https://github.com/errsole/errsole.js/discussions/categories/q-a).
* **Want to request a feature or share your ideas?** Use our [discussion forum](https://github.com/errsole/errsole.js/discussions/categories/general).
* **Want to contribute?** First, share your idea with the community in our [discussion forum](https://github.com/errsole/errsole.js/discussions/categories/general) to see what others are saying. Then, fork the repository, make your changes, and submit a pull request.
## License
[MIT](https://github.com/errsole/errsole.js/blob/master/LICENSE)

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc