Skip to content

Commit f7b965e

Browse files
committed
feat(udp): Enhance UDP drop logging to include breakdown of drop reasons and reset counters after logging
1 parent 88450ab commit f7b965e

11 files changed

Lines changed: 177 additions & 45 deletions

File tree

.claude/skills/generated/cluster-25/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ description: "Skill for the Cluster_25 area of butler. 6 symbols across 1 files.
2323

2424
Start here when exploring this area:
2525

26-
- **`constructor`** (Method) — `src/lib/udp_queue_manager.js:319`
26+
- **`constructor`** (Method) — `src/lib/udp_queue_manager.js:320`
2727

2828
## Key Symbols
2929

3030
| Symbol | Type | File | Line |
3131
|--------|------|------|------|
32-
| `constructor` | Method | `src/lib/udp_queue_manager.js` | 319 |
32+
| `constructor` | Method | `src/lib/udp_queue_manager.js` | 320 |
3333
| `DeduplicationCache` | Class | `src/lib/udp_queue_manager.js` | 16 |
3434
| `CircularBuffer` | Class | `src/lib/udp_queue_manager.js` | 144 |
3535
| `RateLimiter` | Class | `src/lib/udp_queue_manager.js` | 239 |

.claude/skills/generated/cluster-27/SKILL.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ description: "Skill for the Cluster_27 area of butler. 6 symbols across 1 files.
2323

2424
Start here when exploring this area:
2525

26-
- **`onSuccess`** (Function) — `src/lib/udp_queue_manager.js:635`
27-
- **`reserveExecutionId`** (Method) — `src/lib/udp_queue_manager.js:425`
28-
- **`markExecutionIdProcessed`** (Method) — `src/lib/udp_queue_manager.js:437`
26+
- **`onSuccess`** (Function) — `src/lib/udp_queue_manager.js:654`
27+
- **`reserveExecutionId`** (Method) — `src/lib/udp_queue_manager.js:433`
28+
- **`markExecutionIdProcessed`** (Method) — `src/lib/udp_queue_manager.js:445`
2929

3030
## Key Symbols
3131

3232
| Symbol | Type | File | Line |
3333
|--------|------|------|------|
34-
| `onSuccess` | Function | `src/lib/udp_queue_manager.js` | 635 |
35-
| `reserveExecutionId` | Method | `src/lib/udp_queue_manager.js` | 425 |
36-
| `markExecutionIdProcessed` | Method | `src/lib/udp_queue_manager.js` | 437 |
34+
| `onSuccess` | Function | `src/lib/udp_queue_manager.js` | 654 |
35+
| `reserveExecutionId` | Method | `src/lib/udp_queue_manager.js` | 433 |
36+
| `markExecutionIdProcessed` | Method | `src/lib/udp_queue_manager.js` | 445 |
3737
| `set` | Method | `src/lib/udp_queue_manager.js` | 80 |
3838
| `reserve` | Method | `src/lib/udp_queue_manager.js` | 93 |
3939
| `markProcessed` | Method | `src/lib/udp_queue_manager.js` | 110 |

.claude/skills/generated/cluster-28/SKILL.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,22 @@ description: "Skill for the Cluster_28 area of butler. 8 symbols across 1 files.
2323

2424
Start here when exploring this area:
2525

26-
- **`onFailure`** (Function) — `src/lib/udp_queue_manager.js:638`
27-
- **`releaseExecutionId`** (Method) — `src/lib/udp_queue_manager.js:448`
28-
- **`getBackpressureThreshold`** (Method) — `src/lib/udp_queue_manager.js:467`
29-
- **`checkBackpressure`** (Method) — `src/lib/udp_queue_manager.js:477`
30-
- **`addToQueue`** (Method) — `src/lib/udp_queue_manager.js:526`
26+
- **`onFailure`** (Function) — `src/lib/udp_queue_manager.js:657`
27+
- **`releaseExecutionId`** (Method) — `src/lib/udp_queue_manager.js:456`
28+
- **`getBackpressureThreshold`** (Method) — `src/lib/udp_queue_manager.js:475`
29+
- **`checkBackpressure`** (Method) — `src/lib/udp_queue_manager.js:485`
30+
- **`addToQueue`** (Method) — `src/lib/udp_queue_manager.js:545`
3131

3232
## Key Symbols
3333

3434
| Symbol | Type | File | Line |
3535
|--------|------|------|------|
36-
| `onFailure` | Function | `src/lib/udp_queue_manager.js` | 638 |
37-
| `releaseExecutionId` | Method | `src/lib/udp_queue_manager.js` | 448 |
38-
| `getBackpressureThreshold` | Method | `src/lib/udp_queue_manager.js` | 467 |
39-
| `checkBackpressure` | Method | `src/lib/udp_queue_manager.js` | 477 |
40-
| `addToQueue` | Method | `src/lib/udp_queue_manager.js` | 526 |
41-
| `enqueueDeduplicated` | Method | `src/lib/udp_queue_manager.js` | 618 |
36+
| `onFailure` | Function | `src/lib/udp_queue_manager.js` | 657 |
37+
| `releaseExecutionId` | Method | `src/lib/udp_queue_manager.js` | 456 |
38+
| `getBackpressureThreshold` | Method | `src/lib/udp_queue_manager.js` | 475 |
39+
| `checkBackpressure` | Method | `src/lib/udp_queue_manager.js` | 485 |
40+
| `addToQueue` | Method | `src/lib/udp_queue_manager.js` | 545 |
41+
| `enqueueDeduplicated` | Method | `src/lib/udp_queue_manager.js` | 637 |
4242
| `release` | Method | `src/lib/udp_queue_manager.js` | 120 |
4343
| `add` | Method | `src/lib/udp_queue_manager.js` | 162 |
4444

.claude/skills/generated/cluster-30/SKILL.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@ description: "Skill for the Cluster_30 area of butler. 4 symbols across 1 files.
2323

2424
Start here when exploring this area:
2525

26-
- **`logDroppedMessages`** (Method) — `src/lib/udp_queue_manager.js:510`
27-
- **`handleRateLimitDrop`** (Method) — `src/lib/udp_queue_manager.js:656`
28-
- **`handleSizeDrop`** (Method) — `src/lib/udp_queue_manager.js:674`
29-
- **`handleDuplicateDrop`** (Method) — `src/lib/udp_queue_manager.js:692`
26+
- **`logDroppedMessages`** (Method) — `src/lib/udp_queue_manager.js:518`
27+
- **`handleRateLimitDrop`** (Method) — `src/lib/udp_queue_manager.js:675`
28+
- **`handleSizeDrop`** (Method) — `src/lib/udp_queue_manager.js:693`
29+
- **`handleDuplicateDrop`** (Method) — `src/lib/udp_queue_manager.js:711`
3030

3131
## Key Symbols
3232

3333
| Symbol | Type | File | Line |
3434
|--------|------|------|------|
35-
| `logDroppedMessages` | Method | `src/lib/udp_queue_manager.js` | 510 |
36-
| `handleRateLimitDrop` | Method | `src/lib/udp_queue_manager.js` | 656 |
37-
| `handleSizeDrop` | Method | `src/lib/udp_queue_manager.js` | 674 |
38-
| `handleDuplicateDrop` | Method | `src/lib/udp_queue_manager.js` | 692 |
35+
| `logDroppedMessages` | Method | `src/lib/udp_queue_manager.js` | 518 |
36+
| `handleRateLimitDrop` | Method | `src/lib/udp_queue_manager.js` | 675 |
37+
| `handleSizeDrop` | Method | `src/lib/udp_queue_manager.js` | 693 |
38+
| `handleDuplicateDrop` | Method | `src/lib/udp_queue_manager.js` | 711 |
3939

4040
## How to Explore
4141

.claude/skills/generated/get/SKILL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ description: "Skill for the Get area of butler. 7 symbols across 1 files."
2323

2424
Start here when exploring this area:
2525

26-
- **`getDeduplicationCacheSize`** (Method) — `src/lib/udp_queue_manager.js:458`
27-
- **`getMetrics`** (Method) — `src/lib/udp_queue_manager.js:710`
26+
- **`getDeduplicationCacheSize`** (Method) — `src/lib/udp_queue_manager.js:466`
27+
- **`getMetrics`** (Method) — `src/lib/udp_queue_manager.js:729`
2828

2929
## Key Symbols
3030

3131
| Symbol | Type | File | Line |
3232
|--------|------|------|------|
33-
| `getDeduplicationCacheSize` | Method | `src/lib/udp_queue_manager.js` | 458 |
34-
| `getMetrics` | Method | `src/lib/udp_queue_manager.js` | 710 |
33+
| `getDeduplicationCacheSize` | Method | `src/lib/udp_queue_manager.js` | 466 |
34+
| `getMetrics` | Method | `src/lib/udp_queue_manager.js` | 729 |
3535
| `getValues` | Method | `src/lib/udp_queue_manager.js` | 175 |
3636
| `getPercentile95` | Method | `src/lib/udp_queue_manager.js` | 191 |
3737
| `getAverage` | Method | `src/lib/udp_queue_manager.js` | 204 |

.claude/skills/generated/incident-mgmt/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ Start here when exploring this area:
3232

3333
- **`configVerifyAllTaskId`** (Function) — `src/lib/config_util.js:12`
3434
- **`callQlikSenseServerLicenseWebhook`** (Function) — `src/lib/qseow/webhook_notification.js:950`
35-
- **`checkDuplicate`** (Method) — `src/lib/udp_queue_manager.js:414`
35+
- **`checkDuplicate`** (Method) — `src/lib/udp_queue_manager.js:422`
3636

3737
## Key Symbols
3838

3939
| Symbol | Type | File | Line |
4040
|--------|------|------|------|
4141
| `configVerifyAllTaskId` | Function | `src/lib/config_util.js` | 12 |
4242
| `callQlikSenseServerLicenseWebhook` | Function | `src/lib/qseow/webhook_notification.js` | 950 |
43-
| `checkDuplicate` | Method | `src/lib/udp_queue_manager.js` | 414 |
43+
| `checkDuplicate` | Method | `src/lib/udp_queue_manager.js` | 422 |
4444
| `getReloadFailedEventConfig` | Function | `src/lib/incident_mgmt/new_relic.js` | 83 |
4545
| `getReloadFailedLogConfig` | Function | `src/lib/incident_mgmt/new_relic.js` | 164 |
4646
| `getReloadAbortedEventConfig` | Function | `src/lib/incident_mgmt/new_relic.js` | 242 |

.claude/skills/generated/udp/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ Start here when exploring this area:
4343
| `sanitizeField` | Function | `src/lib/udp_sanitizer.js` | 20 |
4444
| `sanitizeMessage` | Function | `src/lib/udp_sanitizer.js` | 39 |
4545
| `logRejection` | Method | `src/lib/udp_ip_validator.js` | 124 |
46-
| `validateMessageSize` | Method | `src/lib/udp_queue_manager.js` | 393 |
47-
| `checkRateLimit` | Method | `src/lib/udp_queue_manager.js` | 403 |
46+
| `validateMessageSize` | Method | `src/lib/udp_queue_manager.js` | 401 |
47+
| `checkRateLimit` | Method | `src/lib/udp_queue_manager.js` | 411 |
4848
| `resolveHostname` | Function | `src/lib/udp_ip_validator.js` | 27 |
4949
| `getMessageEnvelope` | Function | `src/udp/udp_handlers.js` | 64 |
5050
| `udpInitTaskErrorServer` | Function | `src/udp/udp_handlers.js` | 241 |

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ NEVER CANCEL builds or tests - they complete quickly except for Docker builds wh
147147
<!-- gitnexus:start -->
148148
# GitNexus — Code Intelligence
149149

150-
This project is indexed by GitNexus as **butler** (2709 symbols, 5355 relationships, 226 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
150+
This project is indexed by GitNexus as **butler** (2712 symbols, 5361 relationships, 227 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
151151

152152
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
153153

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- gitnexus:start -->
22
# GitNexus — Code Intelligence
33

4-
This project is indexed by GitNexus as **butler** (2709 symbols, 5355 relationships, 226 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
4+
This project is indexed by GitNexus as **butler** (2712 symbols, 5361 relationships, 227 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
55

66
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
77

src/lib/__tests__/udp_queue_manager.test.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,4 +281,120 @@ describe('UdpQueueManager', () => {
281281

282282
dedupDisabledQueue.destroy();
283283
});
284+
285+
test('should include drop reason breakdown in warning log', async () => {
286+
// Trigger 2 duplicate drops
287+
await queueManager.handleDuplicateDrop();
288+
await queueManager.handleDuplicateDrop();
289+
290+
// Trigger 1 size drop
291+
await queueManager.handleSizeDrop();
292+
293+
// Force the time check to pass
294+
queueManager.lastDropLog = 0;
295+
296+
// Call logDroppedMessages
297+
queueManager.logDroppedMessages();
298+
299+
// Verify warn was called with breakdown
300+
const warnCalls = mockLogger.warn.mock.calls;
301+
const dropLog = warnCalls.find((call) => call[0].includes('Dropped') && call[0].includes('messages'));
302+
expect(dropLog).toBeTruthy();
303+
expect(dropLog[0]).toContain('Dropped 3 messages');
304+
expect(dropLog[0]).toContain('duplicate: 2');
305+
expect(dropLog[0]).toContain('size: 1');
306+
});
307+
308+
test('should only include non-zero drop reasons in warning log', async () => {
309+
// Trigger only 1 duplicate drop
310+
await queueManager.handleDuplicateDrop();
311+
312+
// Force the time check to pass
313+
queueManager.lastDropLog = 0;
314+
315+
// Call logDroppedMessages
316+
queueManager.logDroppedMessages();
317+
318+
// Verify warn was called with only duplicate reason
319+
const warnCalls = mockLogger.warn.mock.calls;
320+
const dropLog = warnCalls.find((call) => call[0].includes('Dropped') && call[0].includes('messages'));
321+
expect(dropLog).toBeTruthy();
322+
expect(dropLog[0]).toContain('duplicate: 1');
323+
expect(dropLog[0]).not.toContain('queueFull');
324+
expect(dropLog[0]).not.toContain('rateLimit');
325+
expect(dropLog[0]).not.toContain('size');
326+
});
327+
328+
test('should reset drop counters after logging', async () => {
329+
// Trigger some drops
330+
await queueManager.handleDuplicateDrop();
331+
await queueManager.handleSizeDrop();
332+
333+
// Force the time check to pass
334+
queueManager.lastDropLog = 0;
335+
336+
// Call logDroppedMessages
337+
queueManager.logDroppedMessages();
338+
339+
// Verify warn was called once
340+
const warnCalls1 = mockLogger.warn.mock.calls.filter((call) => call[0].includes('Dropped') && call[0].includes('messages'));
341+
expect(warnCalls1).toHaveLength(1);
342+
343+
// Reset time and call again
344+
queueManager.lastDropLog = 0;
345+
queueManager.logDroppedMessages();
346+
347+
// Verify warn was NOT called again (counters were reset)
348+
const warnCalls2 = mockLogger.warn.mock.calls.filter((call) => call[0].includes('Dropped') && call[0].includes('messages'));
349+
expect(warnCalls2).toHaveLength(1);
350+
});
351+
352+
test('should not log when no messages were dropped', async () => {
353+
// Don't trigger any drops
354+
355+
// Force the time check to pass
356+
queueManager.lastDropLog = 0;
357+
358+
// Call logDroppedMessages
359+
queueManager.logDroppedMessages();
360+
361+
// Verify warn was NOT called
362+
const warnCalls = mockLogger.warn.mock.calls.filter((call) => call[0].includes('Dropped') && call[0].includes('messages'));
363+
expect(warnCalls).toHaveLength(0);
364+
});
365+
366+
test('should track all four drop reasons correctly', async () => {
367+
// Trigger rate limit drop
368+
await queueManager.handleRateLimitDrop();
369+
370+
// Trigger size drop
371+
await queueManager.handleSizeDrop();
372+
373+
// Trigger duplicate drop
374+
await queueManager.handleDuplicateDrop();
375+
376+
// Trigger queue full drop by filling the queue
377+
const slowFn = () => new Promise((r) => setTimeout(r, 5000));
378+
for (let i = 0; i < 12; i++) {
379+
await queueManager.addToQueue(slowFn);
380+
}
381+
await new Promise((r) => setTimeout(r, 100));
382+
await queueManager.addToQueue(() => Promise.resolve());
383+
384+
// Force the time check to pass
385+
queueManager.lastDropLog = 0;
386+
387+
// Call logDroppedMessages
388+
queueManager.logDroppedMessages();
389+
390+
// Verify warn was called with all four reasons
391+
const warnCalls = mockLogger.warn.mock.calls;
392+
const dropLog = warnCalls.find((call) => call[0].includes('Dropped') && call[0].includes('messages'));
393+
expect(dropLog).toBeTruthy();
394+
expect(dropLog[0]).toContain('Dropped 4 messages');
395+
expect(dropLog[0]).toContain('queueFull: 1');
396+
expect(dropLog[0]).toContain('rateLimit: 1');
397+
expect(dropLog[0]).toContain('size: 1');
398+
expect(dropLog[0]).toContain('duplicate: 1');
399+
});
284400
});

0 commit comments

Comments
 (0)