@logdash/node 1.0.0
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.editorconfig +13 -0
- package/.github/workflows/build-and-publish.yml +39 -0
- package/.github/workflows/ci.yml +36 -0
- package/.prettierignore +12 -0
- package/.prettierrc +12 -0
- package/CHANGELOG.md +146 -0
- package/LICENSE.md +21 -0
- package/README.md +81 -0
- package/dist/Logdash.d.ts +36 -0
- package/dist/Logdash.d.ts.map +1 -0
- package/dist/Logdash.js +145 -0
- package/dist/Logdash.js.map +1 -0
- package/dist/__tests__/HttpTransport.test.d.ts +2 -0
- package/dist/__tests__/HttpTransport.test.d.ts.map +1 -0
- package/dist/__tests__/HttpTransport.test.js +148 -0
- package/dist/__tests__/HttpTransport.test.js.map +1 -0
- package/dist/__tests__/Logdash.test.d.ts +2 -0
- package/dist/__tests__/Logdash.test.d.ts.map +1 -0
- package/dist/__tests__/Logdash.test.js +131 -0
- package/dist/__tests__/Logdash.test.js.map +1 -0
- package/dist/__tests__/RequestQueue.test.d.ts +2 -0
- package/dist/__tests__/RequestQueue.test.d.ts.map +1 -0
- package/dist/__tests__/RequestQueue.test.js +129 -0
- package/dist/__tests__/RequestQueue.test.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/internalLogger.d.ts +7 -0
- package/dist/logger/internalLogger.d.ts.map +1 -0
- package/dist/logger/internalLogger.js +17 -0
- package/dist/logger/internalLogger.js.map +1 -0
- package/dist/queue/RequestQueue.d.ts +24 -0
- package/dist/queue/RequestQueue.d.ts.map +1 -0
- package/dist/queue/RequestQueue.js +87 -0
- package/dist/queue/RequestQueue.js.map +1 -0
- package/dist/transport/HttpTransport.d.ts +28 -0
- package/dist/transport/HttpTransport.d.ts.map +1 -0
- package/dist/transport/HttpTransport.js +37 -0
- package/dist/transport/HttpTransport.js.map +1 -0
- package/dist/types/LogLevel.d.ts +10 -0
- package/dist/types/LogLevel.d.ts.map +1 -0
- package/dist/types/LogLevel.js +11 -0
- package/dist/types/LogLevel.js.map +1 -0
- package/docs/delta.png +0 -0
- package/docs/logs.png +0 -0
- package/package.json +49 -0
- package/test.ts +32 -0
- package/tsconfig.json +20 -0
- package/tsconfig.lib.json +29 -0
- package/vite.config.ts +8 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { HttpTransport } from '../transport/HttpTransport.js';
|
|
3
|
+
describe('HttpTransport', () => {
|
|
4
|
+
let mockFetch;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
mockFetch = vi.fn().mockResolvedValue({
|
|
7
|
+
ok: true,
|
|
8
|
+
status: 200,
|
|
9
|
+
statusText: 'OK',
|
|
10
|
+
});
|
|
11
|
+
vi.stubGlobal('fetch', mockFetch);
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
vi.unstubAllGlobals();
|
|
15
|
+
vi.restoreAllMocks();
|
|
16
|
+
});
|
|
17
|
+
describe('constructor', () => {
|
|
18
|
+
it('creates instance with required options', () => {
|
|
19
|
+
const transport = new HttpTransport({
|
|
20
|
+
host: 'https://api.test.com',
|
|
21
|
+
apiKey: 'test-key',
|
|
22
|
+
});
|
|
23
|
+
expect(transport).toBeInstanceOf(HttpTransport);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe('sendLogs', () => {
|
|
27
|
+
it('sends logs to /logs/batch endpoint', async () => {
|
|
28
|
+
const transport = new HttpTransport({
|
|
29
|
+
host: 'https://api.test.com',
|
|
30
|
+
apiKey: 'test-key',
|
|
31
|
+
});
|
|
32
|
+
await transport.sendLogs([
|
|
33
|
+
{
|
|
34
|
+
message: 'test',
|
|
35
|
+
level: 'info',
|
|
36
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
37
|
+
sequenceNumber: 0,
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
expect(mockFetch).toHaveBeenCalledWith('https://api.test.com/logs/batch', expect.objectContaining({
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: {
|
|
43
|
+
'Content-Type': 'application/json',
|
|
44
|
+
'project-api-key': 'test-key',
|
|
45
|
+
},
|
|
46
|
+
}));
|
|
47
|
+
});
|
|
48
|
+
it('wraps logs in batch format', async () => {
|
|
49
|
+
const transport = new HttpTransport({
|
|
50
|
+
host: 'https://api.test.com',
|
|
51
|
+
apiKey: 'test-key',
|
|
52
|
+
});
|
|
53
|
+
await transport.sendLogs([
|
|
54
|
+
{
|
|
55
|
+
message: 'test message',
|
|
56
|
+
level: 'error',
|
|
57
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
58
|
+
sequenceNumber: 42,
|
|
59
|
+
namespace: 'auth',
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
62
|
+
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
63
|
+
const call = mockFetch.mock.calls[0];
|
|
64
|
+
const body = JSON.parse(call[1].body);
|
|
65
|
+
expect(body).toEqual({
|
|
66
|
+
logs: [
|
|
67
|
+
{
|
|
68
|
+
message: 'test message',
|
|
69
|
+
level: 'error',
|
|
70
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
71
|
+
sequenceNumber: 42,
|
|
72
|
+
namespace: 'auth',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('sendMetrics', () => {
|
|
79
|
+
it('sends metrics to /metrics endpoint', async () => {
|
|
80
|
+
const transport = new HttpTransport({
|
|
81
|
+
host: 'https://api.test.com',
|
|
82
|
+
apiKey: 'test-key',
|
|
83
|
+
});
|
|
84
|
+
await transport.sendMetrics([
|
|
85
|
+
{
|
|
86
|
+
name: 'users',
|
|
87
|
+
value: 100,
|
|
88
|
+
operation: 'set',
|
|
89
|
+
},
|
|
90
|
+
]);
|
|
91
|
+
expect(mockFetch).toHaveBeenCalledWith('https://api.test.com/metrics', expect.objectContaining({
|
|
92
|
+
method: 'PUT',
|
|
93
|
+
headers: {
|
|
94
|
+
'Content-Type': 'application/json',
|
|
95
|
+
'project-api-key': 'test-key',
|
|
96
|
+
},
|
|
97
|
+
}));
|
|
98
|
+
});
|
|
99
|
+
it('sends each metric individually', async () => {
|
|
100
|
+
const transport = new HttpTransport({
|
|
101
|
+
host: 'https://api.test.com',
|
|
102
|
+
apiKey: 'test-key',
|
|
103
|
+
});
|
|
104
|
+
await transport.sendMetrics([
|
|
105
|
+
{ name: 'users', value: 100, operation: 'set' },
|
|
106
|
+
{ name: 'requests', value: 1, operation: 'change' },
|
|
107
|
+
]);
|
|
108
|
+
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe('error handling', () => {
|
|
112
|
+
it('throws on non-ok response', async () => {
|
|
113
|
+
mockFetch.mockResolvedValueOnce({
|
|
114
|
+
ok: false,
|
|
115
|
+
status: 500,
|
|
116
|
+
statusText: 'Internal Server Error',
|
|
117
|
+
});
|
|
118
|
+
const transport = new HttpTransport({
|
|
119
|
+
host: 'https://api.test.com',
|
|
120
|
+
apiKey: 'test-key',
|
|
121
|
+
});
|
|
122
|
+
await expect(transport.sendLogs([
|
|
123
|
+
{
|
|
124
|
+
message: 'test',
|
|
125
|
+
level: 'info',
|
|
126
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
127
|
+
sequenceNumber: 0,
|
|
128
|
+
},
|
|
129
|
+
])).rejects.toThrow('HTTP 500: Internal Server Error');
|
|
130
|
+
});
|
|
131
|
+
it('throws on network error', async () => {
|
|
132
|
+
mockFetch.mockRejectedValueOnce(new Error('Network error'));
|
|
133
|
+
const transport = new HttpTransport({
|
|
134
|
+
host: 'https://api.test.com',
|
|
135
|
+
apiKey: 'test-key',
|
|
136
|
+
});
|
|
137
|
+
await expect(transport.sendLogs([
|
|
138
|
+
{
|
|
139
|
+
message: 'test',
|
|
140
|
+
level: 'info',
|
|
141
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
142
|
+
sequenceNumber: 0,
|
|
143
|
+
},
|
|
144
|
+
])).rejects.toThrow('Network error');
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=HttpTransport.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpTransport.test.js","sourceRoot":"","sources":["../../src/__tests__/HttpTransport.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC9B,IAAI,SAAmC,CAAC;IAExC,UAAU,CAAC,GAAG,EAAE;QACf,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YACrC,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,IAAI;SAChB,CAAC,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,eAAe,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YACjD,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,UAAU;aAClB,CAAC,CAAC;YACH,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,UAAU;aAClB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,QAAQ,CAAC;gBACxB;oBACC,OAAO,EAAE,MAAM;oBACf,KAAK,EAAE,MAAM;oBACb,SAAS,EAAE,0BAA0B;oBACrC,cAAc,EAAE,CAAC;iBACjB;aACD,CAAC,CAAC;YAEH,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CACrC,iCAAiC,EACjC,MAAM,CAAC,gBAAgB,CAAC;gBACvB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACR,cAAc,EAAE,kBAAkB;oBAClC,iBAAiB,EAAE,UAAU;iBAC7B;aACD,CAAC,CACF,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC3C,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,UAAU;aAClB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,QAAQ,CAAC;gBACxB;oBACC,OAAO,EAAE,cAAc;oBACvB,KAAK,EAAE,OAAO;oBACd,SAAS,EAAE,0BAA0B;oBACrC,cAAc,EAAE,EAAE;oBAClB,SAAS,EAAE,MAAM;iBACjB;aACD,CAAC,CAAC;YAEH,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAEtC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;gBACpB,IAAI,EAAE;oBACL;wBACC,OAAO,EAAE,cAAc;wBACvB,KAAK,EAAE,OAAO;wBACd,SAAS,EAAE,0BAA0B;wBACrC,cAAc,EAAE,EAAE;wBAClB,SAAS,EAAE,MAAM;qBACjB;iBACD;aACD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,UAAU;aAClB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,WAAW,CAAC;gBAC3B;oBACC,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,GAAG;oBACV,SAAS,EAAE,KAAK;iBAChB;aACD,CAAC,CAAC;YAEH,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CACrC,8BAA8B,EAC9B,MAAM,CAAC,gBAAgB,CAAC;gBACvB,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACR,cAAc,EAAE,kBAAkB;oBAClC,iBAAiB,EAAE,UAAU;iBAC7B;aACD,CAAC,CACF,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,UAAU;aAClB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,WAAW,CAAC;gBAC3B,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE;gBAC/C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;aACnD,CAAC,CAAC;YAEH,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;YAC1C,SAAS,CAAC,qBAAqB,CAAC;gBAC/B,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,GAAG;gBACX,UAAU,EAAE,uBAAuB;aACnC,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,UAAU;aAClB,CAAC,CAAC;YAEH,MAAM,MAAM,CACX,SAAS,CAAC,QAAQ,CAAC;gBAClB;oBACC,OAAO,EAAE,MAAM;oBACf,KAAK,EAAE,MAAM;oBACb,SAAS,EAAE,0BAA0B;oBACrC,cAAc,EAAE,CAAC;iBACjB;aACD,CAAC,CACF,CAAC,OAAO,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;YACxC,SAAS,CAAC,qBAAqB,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;YAE5D,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,MAAM,EAAE,UAAU;aAClB,CAAC,CAAC;YAEH,MAAM,MAAM,CACX,SAAS,CAAC,QAAQ,CAAC;gBAClB;oBACC,OAAO,EAAE,MAAM;oBACf,KAAK,EAAE,MAAM;oBACb,SAAS,EAAE,0BAA0B;oBACrC,cAAc,EAAE,CAAC;iBACjB;aACD,CAAC,CACF,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logdash.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Logdash.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { Logdash } from '../Logdash.js';
|
|
3
|
+
describe('Logdash', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
6
|
+
});
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
vi.restoreAllMocks();
|
|
9
|
+
});
|
|
10
|
+
describe('constructor', () => {
|
|
11
|
+
it('creates instance without options', () => {
|
|
12
|
+
const logdash = new Logdash();
|
|
13
|
+
expect(logdash).toBeInstanceOf(Logdash);
|
|
14
|
+
logdash.destroy();
|
|
15
|
+
});
|
|
16
|
+
it('creates instance with apiKey', () => {
|
|
17
|
+
const logdash = new Logdash('test-key');
|
|
18
|
+
expect(logdash).toBeInstanceOf(Logdash);
|
|
19
|
+
logdash.destroy();
|
|
20
|
+
});
|
|
21
|
+
it('creates instance with custom host', () => {
|
|
22
|
+
const logdash = new Logdash('test-key', {
|
|
23
|
+
host: 'https://custom.api.com',
|
|
24
|
+
});
|
|
25
|
+
expect(logdash).toBeInstanceOf(Logdash);
|
|
26
|
+
logdash.destroy();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('logging methods', () => {
|
|
30
|
+
let logdash;
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
logdash = new Logdash();
|
|
33
|
+
});
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
logdash.destroy();
|
|
36
|
+
});
|
|
37
|
+
it('logs error messages', () => {
|
|
38
|
+
logdash.error('test error');
|
|
39
|
+
expect(console.log).toHaveBeenCalled();
|
|
40
|
+
});
|
|
41
|
+
it('logs warn messages', () => {
|
|
42
|
+
logdash.warn('test warning');
|
|
43
|
+
expect(console.log).toHaveBeenCalled();
|
|
44
|
+
});
|
|
45
|
+
it('logs info messages', () => {
|
|
46
|
+
logdash.info('test info');
|
|
47
|
+
expect(console.log).toHaveBeenCalled();
|
|
48
|
+
});
|
|
49
|
+
it('logs http messages', () => {
|
|
50
|
+
logdash.http('test http');
|
|
51
|
+
expect(console.log).toHaveBeenCalled();
|
|
52
|
+
});
|
|
53
|
+
it('logs verbose messages', () => {
|
|
54
|
+
logdash.verbose('test verbose');
|
|
55
|
+
expect(console.log).toHaveBeenCalled();
|
|
56
|
+
});
|
|
57
|
+
it('logs debug messages', () => {
|
|
58
|
+
logdash.debug('test debug');
|
|
59
|
+
expect(console.log).toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
it('logs silly messages', () => {
|
|
62
|
+
logdash.silly('test silly');
|
|
63
|
+
expect(console.log).toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
it('formats objects as JSON', () => {
|
|
66
|
+
logdash.info('data:', { key: 'value' });
|
|
67
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('{"key":"value"}'));
|
|
68
|
+
});
|
|
69
|
+
it('handles multiple arguments', () => {
|
|
70
|
+
logdash.info('first', 'second', 123);
|
|
71
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('first second 123'));
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('withNamespace', () => {
|
|
75
|
+
let logdash;
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
logdash = new Logdash();
|
|
78
|
+
});
|
|
79
|
+
afterEach(() => {
|
|
80
|
+
logdash.destroy();
|
|
81
|
+
});
|
|
82
|
+
it('returns a new Logdash instance', () => {
|
|
83
|
+
const namespaced = logdash.withNamespace('auth');
|
|
84
|
+
expect(namespaced).toBeInstanceOf(Logdash);
|
|
85
|
+
});
|
|
86
|
+
it('includes namespace in log output', () => {
|
|
87
|
+
const namespaced = logdash.withNamespace('auth');
|
|
88
|
+
namespaced.info('test message');
|
|
89
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('[auth]'));
|
|
90
|
+
});
|
|
91
|
+
it('allows creating multiple namespaces', () => {
|
|
92
|
+
const auth = logdash.withNamespace('auth');
|
|
93
|
+
const db = logdash.withNamespace('db');
|
|
94
|
+
auth.info('auth message');
|
|
95
|
+
db.info('db message');
|
|
96
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('[auth]'));
|
|
97
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('[db]'));
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('metrics', () => {
|
|
101
|
+
let logdash;
|
|
102
|
+
beforeEach(() => {
|
|
103
|
+
logdash = new Logdash();
|
|
104
|
+
});
|
|
105
|
+
afterEach(() => {
|
|
106
|
+
logdash.destroy();
|
|
107
|
+
});
|
|
108
|
+
it('queues setMetric calls', () => {
|
|
109
|
+
// This shouldn't throw
|
|
110
|
+
expect(() => logdash.setMetric('users', 100)).not.toThrow();
|
|
111
|
+
});
|
|
112
|
+
it('queues mutateMetric calls', () => {
|
|
113
|
+
// This shouldn't throw
|
|
114
|
+
expect(() => logdash.mutateMetric('requests', 1)).not.toThrow();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe('flush', () => {
|
|
118
|
+
it('resolves when queue is empty', async () => {
|
|
119
|
+
const logdash = new Logdash();
|
|
120
|
+
await expect(logdash.flush()).resolves.toBeUndefined();
|
|
121
|
+
logdash.destroy();
|
|
122
|
+
});
|
|
123
|
+
it('waits for pending items', async () => {
|
|
124
|
+
const logdash = new Logdash();
|
|
125
|
+
logdash.info('test message');
|
|
126
|
+
await expect(logdash.flush()).resolves.toBeUndefined();
|
|
127
|
+
logdash.destroy();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
//# sourceMappingURL=Logdash.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logdash.test.js","sourceRoot":"","sources":["../../src/__tests__/Logdash.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestQueue.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/RequestQueue.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { RequestQueue } from '../queue/RequestQueue.js';
|
|
3
|
+
describe('RequestQueue', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
6
|
+
});
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
vi.restoreAllMocks();
|
|
9
|
+
});
|
|
10
|
+
describe('add', () => {
|
|
11
|
+
it('adds items to the queue', () => {
|
|
12
|
+
const sendFn = vi.fn().mockResolvedValue(undefined);
|
|
13
|
+
const queue = new RequestQueue(sendFn);
|
|
14
|
+
queue.add({ id: 1 });
|
|
15
|
+
queue.add({ id: 2 });
|
|
16
|
+
queue.destroy();
|
|
17
|
+
expect(sendFn).not.toHaveBeenCalled(); // Not flushed yet
|
|
18
|
+
});
|
|
19
|
+
it('ignores items after destroy', () => {
|
|
20
|
+
const sendFn = vi.fn().mockResolvedValue(undefined);
|
|
21
|
+
const queue = new RequestQueue(sendFn);
|
|
22
|
+
queue.destroy();
|
|
23
|
+
queue.add({ id: 1 });
|
|
24
|
+
expect(sendFn).not.toHaveBeenCalled();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('batching', () => {
|
|
28
|
+
it('flushes when batch size is reached', async () => {
|
|
29
|
+
const sendFn = vi.fn().mockResolvedValue(undefined);
|
|
30
|
+
const queue = new RequestQueue(sendFn, { batchSize: 3 });
|
|
31
|
+
queue.add({ id: 1 });
|
|
32
|
+
queue.add({ id: 2 });
|
|
33
|
+
expect(sendFn).not.toHaveBeenCalled();
|
|
34
|
+
queue.add({ id: 3 }); // Triggers flush
|
|
35
|
+
// Wait for the async operation
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
37
|
+
expect(sendFn).toHaveBeenCalledWith([
|
|
38
|
+
{ id: 1 },
|
|
39
|
+
{ id: 2 },
|
|
40
|
+
{ id: 3 },
|
|
41
|
+
]);
|
|
42
|
+
queue.destroy();
|
|
43
|
+
});
|
|
44
|
+
it('flushes on interval', async () => {
|
|
45
|
+
const sendFn = vi.fn().mockResolvedValue(undefined);
|
|
46
|
+
const queue = new RequestQueue(sendFn, {
|
|
47
|
+
batchSize: 100,
|
|
48
|
+
flushIntervalMs: 50,
|
|
49
|
+
});
|
|
50
|
+
queue.add({ id: 1 });
|
|
51
|
+
queue.add({ id: 2 });
|
|
52
|
+
// Wait for interval
|
|
53
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
54
|
+
expect(sendFn).toHaveBeenCalledWith([{ id: 1 }, { id: 2 }]);
|
|
55
|
+
queue.destroy();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('retry', () => {
|
|
59
|
+
it('retries failed requests', async () => {
|
|
60
|
+
const sendFn = vi
|
|
61
|
+
.fn()
|
|
62
|
+
.mockRejectedValueOnce(new Error('Network error'))
|
|
63
|
+
.mockResolvedValueOnce(undefined);
|
|
64
|
+
const queue = new RequestQueue(sendFn, {
|
|
65
|
+
batchSize: 1,
|
|
66
|
+
maxRetries: 3,
|
|
67
|
+
baseRetryDelayMs: 10,
|
|
68
|
+
});
|
|
69
|
+
queue.add({ id: 1 });
|
|
70
|
+
// Wait for retries
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
72
|
+
expect(sendFn).toHaveBeenCalledTimes(2);
|
|
73
|
+
queue.destroy();
|
|
74
|
+
});
|
|
75
|
+
it('stops after max retries', async () => {
|
|
76
|
+
const sendFn = vi
|
|
77
|
+
.fn()
|
|
78
|
+
.mockRejectedValue(new Error('Network error'));
|
|
79
|
+
const queue = new RequestQueue(sendFn, {
|
|
80
|
+
batchSize: 1,
|
|
81
|
+
maxRetries: 3,
|
|
82
|
+
baseRetryDelayMs: 10,
|
|
83
|
+
});
|
|
84
|
+
queue.add({ id: 1 });
|
|
85
|
+
// Wait for all retries (10 + 20 + 40 = 70ms base, add buffer)
|
|
86
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
87
|
+
expect(sendFn).toHaveBeenCalledTimes(3);
|
|
88
|
+
queue.destroy();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('flush', () => {
|
|
92
|
+
it('sends remaining items immediately', async () => {
|
|
93
|
+
const sendFn = vi.fn().mockResolvedValue(undefined);
|
|
94
|
+
const queue = new RequestQueue(sendFn, { batchSize: 100 });
|
|
95
|
+
queue.add({ id: 1 });
|
|
96
|
+
queue.add({ id: 2 });
|
|
97
|
+
await queue.flush();
|
|
98
|
+
expect(sendFn).toHaveBeenCalledWith([{ id: 1 }, { id: 2 }]);
|
|
99
|
+
queue.destroy();
|
|
100
|
+
});
|
|
101
|
+
it('waits for in-flight requests', async () => {
|
|
102
|
+
let resolveRequest;
|
|
103
|
+
const sendFn = vi.fn().mockImplementation(() => new Promise((resolve) => {
|
|
104
|
+
resolveRequest = resolve;
|
|
105
|
+
}));
|
|
106
|
+
const queue = new RequestQueue(sendFn, { batchSize: 1 });
|
|
107
|
+
queue.add({ id: 1 });
|
|
108
|
+
// Start flush but don't await yet
|
|
109
|
+
const flushPromise = queue.flush();
|
|
110
|
+
// Resolve the pending request
|
|
111
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
112
|
+
resolveRequest();
|
|
113
|
+
await flushPromise;
|
|
114
|
+
expect(sendFn).toHaveBeenCalled();
|
|
115
|
+
queue.destroy();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('destroy', () => {
|
|
119
|
+
it('stops the flush timer', async () => {
|
|
120
|
+
const sendFn = vi.fn().mockResolvedValue(undefined);
|
|
121
|
+
const queue = new RequestQueue(sendFn, { flushIntervalMs: 50 });
|
|
122
|
+
queue.add({ id: 1 });
|
|
123
|
+
queue.destroy();
|
|
124
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
125
|
+
expect(sendFn).not.toHaveBeenCalled();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
//# sourceMappingURL=RequestQueue.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestQueue.test.js","sourceRoot":"","sources":["../../src/__tests__/RequestQueue.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internalLogger.d.ts","sourceRoot":"","sources":["../../src/logger/internalLogger.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc;qBACT,OAAO,EAAE;oBAGV,OAAO,EAAE;oBAGT,OAAO,EAAE;uBAGN,OAAO,EAAE;CAG5B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
const PREFIX = chalk.rgb(230, 0, 118)('[Logdash]');
|
|
3
|
+
export const internalLogger = {
|
|
4
|
+
error: (...args) => {
|
|
5
|
+
console.log(PREFIX, chalk.red('ERROR'), ...args);
|
|
6
|
+
},
|
|
7
|
+
warn: (...args) => {
|
|
8
|
+
console.log(PREFIX, chalk.yellow('WARN'), ...args);
|
|
9
|
+
},
|
|
10
|
+
info: (...args) => {
|
|
11
|
+
console.log(PREFIX, ...args);
|
|
12
|
+
},
|
|
13
|
+
verbose: (...args) => {
|
|
14
|
+
console.log(PREFIX, chalk.gray(...args));
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=internalLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internalLogger.js","sourceRoot":"","sources":["../../src/logger/internalLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;AAEnD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,KAAK,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;QAC7B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;QAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;QAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;QAC/B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1C,CAAC;CACD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type SendFunction<T> = (items: T[]) => Promise<void>;
|
|
2
|
+
export interface RequestQueueOptions {
|
|
3
|
+
batchSize?: number;
|
|
4
|
+
flushIntervalMs?: number;
|
|
5
|
+
maxRetries?: number;
|
|
6
|
+
baseRetryDelayMs?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class RequestQueue<T> {
|
|
9
|
+
private readonly sendFn;
|
|
10
|
+
private queue;
|
|
11
|
+
private inFlightPromises;
|
|
12
|
+
private flushTimer;
|
|
13
|
+
private destroyed;
|
|
14
|
+
private readonly options;
|
|
15
|
+
constructor(sendFn: SendFunction<T>, options?: RequestQueueOptions);
|
|
16
|
+
add(item: T): void;
|
|
17
|
+
flush(): Promise<void>;
|
|
18
|
+
destroy(): void;
|
|
19
|
+
private scheduleFlush;
|
|
20
|
+
private flushBatch;
|
|
21
|
+
private sendWithRetry;
|
|
22
|
+
private sleep;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=RequestQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestQueue.d.ts","sourceRoot":"","sources":["../../src/queue/RequestQueue.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5D,MAAM,WAAW,mBAAmB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AASD,qBAAa,YAAY,CAAC,CAAC;IAQzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPxB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;gBAGtC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACxC,OAAO,CAAC,EAAE,mBAAmB;IAM9B,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAYZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,UAAU;YAcJ,aAAa;IA0B3B,OAAO,CAAC,KAAK;CAGb"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { internalLogger } from '../logger/internalLogger.js';
|
|
2
|
+
const DEFAULT_OPTIONS = {
|
|
3
|
+
batchSize: 25,
|
|
4
|
+
flushIntervalMs: 1000,
|
|
5
|
+
maxRetries: 3,
|
|
6
|
+
baseRetryDelayMs: 1000,
|
|
7
|
+
};
|
|
8
|
+
export class RequestQueue {
|
|
9
|
+
constructor(sendFn, options) {
|
|
10
|
+
this.sendFn = sendFn;
|
|
11
|
+
this.queue = [];
|
|
12
|
+
this.inFlightPromises = new Set();
|
|
13
|
+
this.flushTimer = null;
|
|
14
|
+
this.destroyed = false;
|
|
15
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
16
|
+
this.scheduleFlush();
|
|
17
|
+
}
|
|
18
|
+
add(item) {
|
|
19
|
+
if (this.destroyed) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
this.queue.push(item);
|
|
23
|
+
if (this.queue.length >= this.options.batchSize) {
|
|
24
|
+
this.flushBatch();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async flush() {
|
|
28
|
+
// Flush any remaining items in the queue
|
|
29
|
+
if (this.queue.length > 0) {
|
|
30
|
+
this.flushBatch();
|
|
31
|
+
}
|
|
32
|
+
// Wait for all in-flight requests to complete
|
|
33
|
+
await Promise.all(Array.from(this.inFlightPromises));
|
|
34
|
+
}
|
|
35
|
+
destroy() {
|
|
36
|
+
this.destroyed = true;
|
|
37
|
+
if (this.flushTimer) {
|
|
38
|
+
clearTimeout(this.flushTimer);
|
|
39
|
+
this.flushTimer = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
scheduleFlush() {
|
|
43
|
+
if (this.destroyed) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.flushTimer = setTimeout(() => {
|
|
47
|
+
if (this.queue.length > 0) {
|
|
48
|
+
this.flushBatch();
|
|
49
|
+
}
|
|
50
|
+
this.scheduleFlush();
|
|
51
|
+
}, this.options.flushIntervalMs);
|
|
52
|
+
}
|
|
53
|
+
flushBatch() {
|
|
54
|
+
if (this.queue.length === 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const batch = this.queue.splice(0, this.options.batchSize);
|
|
58
|
+
const promise = this.sendWithRetry(batch);
|
|
59
|
+
this.inFlightPromises.add(promise);
|
|
60
|
+
promise.finally(() => {
|
|
61
|
+
this.inFlightPromises.delete(promise);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async sendWithRetry(items) {
|
|
65
|
+
let lastError = null;
|
|
66
|
+
for (let attempt = 0; attempt < this.options.maxRetries; attempt++) {
|
|
67
|
+
try {
|
|
68
|
+
await this.sendFn(items);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
lastError =
|
|
73
|
+
error instanceof Error ? error : new Error(String(error));
|
|
74
|
+
if (attempt < this.options.maxRetries - 1) {
|
|
75
|
+
const delay = this.options.baseRetryDelayMs * Math.pow(2, attempt);
|
|
76
|
+
await this.sleep(delay);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// All retries exhausted - log error but don't throw to avoid breaking the app
|
|
81
|
+
internalLogger.error(`Failed to send batch after ${this.options.maxRetries} attempts:`, lastError?.message);
|
|
82
|
+
}
|
|
83
|
+
sleep(ms) {
|
|
84
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=RequestQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestQueue.js","sourceRoot":"","sources":["../../src/queue/RequestQueue.ts"],"names":[],"mappings":"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"}
|