Conversation
index.js
Outdated
| this._errorBatchTimer = null | ||
| } | ||
|
|
||
| this._processBatchedErrors().catch(err => { |
There was a problem hiding this comment.
please change linting here
README.md
Outdated
| "env": "development", | ||
| "errorBatching": { // optional | ||
| "interval": 60000, | ||
| "maxSize": 50, |
There was a problem hiding this comment.
is it possible to compose and send 50x4000 symbols to slack at once?
There was a problem hiding this comment.
We can create and send a file in that case
index.js
Outdated
| * @param {Object} payload - Payload to log | ||
| * @param {...any} extra - Additional information to log | ||
| */ | ||
| async batchLogErrorToSlack (reqChannel, err, functionName, payload, ...extra) { |
There was a problem hiding this comment.
| async batchLogErrorToSlack (reqChannel, err, functionName, payload, ...extra) { | |
| async logErrorEnqueue (reqChannel, err, ...extra) { |
index.js
Outdated
| errorEntry.lastSeen = now | ||
| errorEntry.payloads.push(payload) | ||
|
|
||
| if (this._errorBatch.size >= this._errorBatchingConfig.maxSize) { |
There was a problem hiding this comment.
i don't think we should flush if buffer is full. We should evict oldest keys. Maybe it would be better to use lru here
index.js
Outdated
| message += `*Summary:* ${totalErrors} errors across ${errors.length} types (${timeRange})\n\n` | ||
|
|
||
| let truncated = false | ||
| for (const error of errors.slice(0, 10)) { |
There was a problem hiding this comment.
If the message is too large the API will fail so have kept it to only 10 different error per function
There was a problem hiding this comment.
what happens to the rest?
There was a problem hiding this comment.
question still stands. I suggest we log only last to slack to fulfill length requirement
| for (const error of errors.slice(0, 10)) { | ||
| if (truncated) break | ||
|
|
||
| message += `• *${error.errorMessage}* (${error.count}x)\n` |
There was a problem hiding this comment.
what about the rest message info? like extra, etc.
index.js
Outdated
| if (opts.conf) this.conf = opts.conf | ||
|
|
||
| this._errorBatchingConfig = { | ||
| interval: this.conf.errorBatching.interval || 60000, |
There was a problem hiding this comment.
let's assume errorBatching may be absent completely cause we're not going to update all existing running places
index.js
Outdated
| * @param {Object} payload - Payload to log | ||
| * @param {...any} extra - Additional information to log | ||
| */ | ||
| async logErrorEnqueue (reqChannel, err, functionName, payload, ...extra) { |
There was a problem hiding this comment.
let's make parameter functionName more generalized, i.e. errorOrigin or originName or errorSource or sourceName etc. You can come up with something better.
| * @param {Error} err - Error to log | ||
| * @param {string} functionName - Name of the function where the error occurred | ||
| * @param {Object} payload - Payload to log | ||
| * @param {...any} extra - Additional information to log |
There was a problem hiding this comment.
is extra a required parameter?
There was a problem hiding this comment.
no we're just putting all other params in 1 object. It can be undefined also
There was a problem hiding this comment.
| * @param {...any} extra - Additional information to log | |
| * @param {...any} [extra] - Additional information to log |
| let errorEntry = this._errorBatch.get(errorKey) | ||
|
|
||
| if (!errorEntry) { | ||
| errorEntry = { |
There was a problem hiding this comment.
extra is not used, what is it for then?
index.js
Outdated
|
|
||
| if (opts.conf) this.conf = opts.conf | ||
|
|
||
| this._errorBatchingConfig = { |
There was a problem hiding this comment.
why do we store it again if we already have it in this.conf?
additionally, if it's omitted (in readme it's commented as optional), you gonna get error trying to access this.conf.errorBatching
if there is no this.conf.errorBatching, this instance is not using batching, we should not setup it. I think additional timer is an overhead cause not all workers need batching
There was a problem hiding this comment.
removed extra variable and not setting up batch logging interval if config does not exist
index.js
Outdated
| maxMessageLength: this.conf.errorBatching?.maxMessageLength || 4000 | ||
| } | ||
|
|
||
| this._errorBatch = new LRU({ |
There was a problem hiding this comment.
if there is no this.conf.errorBatching, we should not setup it
index.js
Outdated
| max: this._errorBatchingConfig.maxSize | ||
| }) | ||
|
|
||
| this._initErrorBatching() |
There was a problem hiding this comment.
if there is no this.conf.errorBatching, we should not setup it
| * @param {Error} err - Error to log | ||
| * @param {string} functionName - Name of the function where the error occurred | ||
| * @param {Object} payload - Payload to log | ||
| * @param {...any} extra - Additional information to log |
There was a problem hiding this comment.
| * @param {...any} extra - Additional information to log | |
| * @param {...any} [extra] - Additional information to log |
There was a problem hiding this comment.
pls create folder test and put a file there named facility.test.js
package.json
Outdated
| "lru": "^3.1.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/jest": "^30.0.0", |
There was a problem hiding this comment.
needed it for local syntax highlighting. Removed it
package.json
Outdated
| "dependencies": { | ||
| "bfx-facs-base": "git+https://github.com/bitfinexcom/bfx-facs-base.git" | ||
| "bfx-facs-base": "git+https://github.com/bitfinexcom/bfx-facs-base.git", | ||
| "lru": "^3.1.0" |
There was a problem hiding this comment.
let's lock dep and add package-lock.json (use node 16.20)
index.js
Outdated
| const earliest = new Date(Math.min(...allTimes)) | ||
| const latest = new Date(Math.max(...allTimes)) | ||
|
|
||
| const formatTime = (date) => date.toISOString().substring(11, 19) |
There was a problem hiding this comment.
looks like a utility function that should not be re-defined inside a function each time
index.js
Outdated
| await this._sendBatchedErrorMessage(reqChannel, sourceName, errors) | ||
| } | ||
|
|
||
| this._errorBatch.clear() |
There was a problem hiding this comment.
if _sendBatchedErrorMessage fails, we never clear?
There was a problem hiding this comment.
now it should, added clear to finally block
- batching init is now conf based - moved test to test/facility.test.js - clear batch if sending fails so error don't pile up
|
cannot have optional parameter with spread operator. If no args are present it will be empty |
package.json
Outdated
| "dependencies": { | ||
| "bfx-facs-base": "git+https://github.com/bitfinexcom/bfx-facs-base.git" | ||
| "bfx-facs-base": "git+https://github.com/bitfinexcom/bfx-facs-base.git", | ||
| "lru": "3.1.0" |
There was a problem hiding this comment.
adding another fac that implements base and starting it in the constructor felt like an unnecessary complication for something simple like this
There was a problem hiding this comment.
@AceTheNinja let's add an optional lru fac dependency for slack for the cases when we enable batch logging
| } | ||
|
|
||
| try { | ||
| await this._processBatchedErrors() |
There was a problem hiding this comment.
why this is called on stop? wouldn't it hang for a long time possibly?
There was a problem hiding this comment.
i think it's called to flush the last batch of errors, otherwise it'll be lost
not sure about long time, i think it should be reasonable time since it's an api call. We can limit the call / stop function in time and exit abruptly if we exceed graceful exit limit.
|
|
||
| if (opts.conf) this.conf = opts.conf | ||
|
|
||
| if (this.conf.errorBatching && opts.lru) { |
There was a problem hiding this comment.
why are we using lru and not map? with lru we would lose data right?
There was a problem hiding this comment.
i think in order to keep the buffer fixed in length. If a worker starts to spam, we don't want to keep the spam rather than track let's say last 100 messages of a certain type.
for instance, a worker sends error messages for different occasions, i.e. API call failure and processing issue. Let's say it reports 1 api call failure and 1000 processing issues, We want both types to be reported, however we don't want 1000 processing issues (same type issue) being reported, we cut it down to, let's say, 10 only
that was the idea behind this update in general. If a worker starts spamming, this logic would still allow us to know about the problem, however, would cut down api calls and payload significantly.
anyways, if i missed the purppose, @AceTheNinja please clarify
index.js
Outdated
| } | ||
|
|
||
| _createErrorKey (reqChannel, err, sourceName) { | ||
| const errorMsg = err?.message || 'Unknown error' |
There was a problem hiding this comment.
maybe you compute hash of stringified error instead of using it directly?
|
|
||
| errorEntry.count++ | ||
| errorEntry.lastSeen = now | ||
| errorEntry.payloads.push({ payload, extras: extra }) |
There was a problem hiding this comment.
you're adding same stuff twice if you just initialized cache entry.
btw if we spam under same errorKey, aren't we bloating the payloads array? Size should be restricted, otherwise we can run out of memory
index.js
Outdated
| payloads: [ | ||
| { payload, extras: extra } | ||
| ], | ||
| count: 0, |
There was a problem hiding this comment.
is it 0? you just seen it first time
index.js
Outdated
| } | ||
| } | ||
|
|
||
| _createErrorKey (reqChannel, err, sourceName) { |
There was a problem hiding this comment.
make a default value for sourceName
index.js
Outdated
| message += payloadStr | ||
| } | ||
|
|
||
| if (error.payloads.length > 3) { |
index.js
Outdated
| } | ||
| } | ||
|
|
||
| if (errors.length > 10 && !truncated) { |
index.js
Outdated
| } | ||
|
|
||
| async _sendBatchedErrorMessage (reqChannel, sourceName, errors) { | ||
| const totalErrors = errors.reduce((sum, error) => sum + error.count, 0) |
There was a problem hiding this comment.
you can keep the counter separately to avoid computing it here, 1 less array pass
| { payload, extras: extra } | ||
| ], | ||
| count: 0, | ||
| firstSeen: now, |
There was a problem hiding this comment.
looks like you use these dates just to know when you got first and last errors. Use separate properties, do not store inside the object and avoid excessive array passes
package.json
Outdated
| "bfx-facs-base": "git+https://github.com/bitfinexcom/bfx-facs-base.git" | ||
| }, | ||
| "optionalDependencies": { | ||
| "bfx-facs-lru": "git+https://github.com/bitfinexcom/bfx-facs-lru.git" |
There was a problem hiding this comment.
do we need it here? it should come from outside as dependency when we instantiate the fac, i think
Co-authored-by: batrudinych <batrudinych@gmail.com>
No description provided.