@onlineapps/conn-base-monitoring 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/coverage/clover.xml +64 -0
- package/coverage/coverage-final.json +2 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +116 -0
- package/coverage/lcov-report/index.js.html +625 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +147 -0
- package/onlineapps-conn-base-monitoring-1.0.0.tgz +0 -0
- package/package.json +34 -0
- package/src/index.js +181 -0
- package/test/component/integration.test.js +460 -0
- package/test/unit/monitoring.test.js +376 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for conn-base-monitoring
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Mock monitoring-core to avoid RabbitMQ connections in tests
|
|
6
|
+
jest.mock('@onlineapps/monitoring-core', () => ({
|
|
7
|
+
init: jest.fn(async (config) => ({
|
|
8
|
+
config: {
|
|
9
|
+
...config,
|
|
10
|
+
mode: config.mode || 'off' // Default to 'off' mode
|
|
11
|
+
},
|
|
12
|
+
logger: {
|
|
13
|
+
info: jest.fn(),
|
|
14
|
+
error: jest.fn(),
|
|
15
|
+
warn: jest.fn(),
|
|
16
|
+
debug: jest.fn(),
|
|
17
|
+
log: jest.fn()
|
|
18
|
+
},
|
|
19
|
+
workflow: {
|
|
20
|
+
start: jest.fn((id) => id),
|
|
21
|
+
step: jest.fn(),
|
|
22
|
+
end: jest.fn(),
|
|
23
|
+
error: jest.fn(),
|
|
24
|
+
activeWorkflows: new Map(),
|
|
25
|
+
getWorkflow: jest.fn()
|
|
26
|
+
},
|
|
27
|
+
createCounter: jest.fn(() => ({ add: jest.fn() })),
|
|
28
|
+
createHistogram: jest.fn(() => ({ record: jest.fn() })),
|
|
29
|
+
createMetric: jest.fn(() => ({ add: jest.fn(), record: jest.fn() })),
|
|
30
|
+
shutdown: jest.fn(() => Promise.resolve())
|
|
31
|
+
})),
|
|
32
|
+
getInstance: jest.fn(() => null),
|
|
33
|
+
createLogger: jest.fn((config) => ({
|
|
34
|
+
info: jest.fn(),
|
|
35
|
+
error: jest.fn(),
|
|
36
|
+
warn: jest.fn(),
|
|
37
|
+
debug: jest.fn()
|
|
38
|
+
})),
|
|
39
|
+
WorkflowTracker: jest.fn().mockImplementation((name) => ({
|
|
40
|
+
serviceName: name,
|
|
41
|
+
start: jest.fn(),
|
|
42
|
+
activeWorkflows: new Map()
|
|
43
|
+
}))
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
const { init, getInstance, createLogger, WorkflowTracker } = require('../../src');
|
|
47
|
+
|
|
48
|
+
describe('conn-base-monitoring Unit Tests', () => {
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
jest.clearAllMocks();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('Module Exports', () => {
|
|
54
|
+
test('should export init function', () => {
|
|
55
|
+
expect(init).toBeDefined();
|
|
56
|
+
expect(typeof init).toBe('function');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('should export getInstance function', () => {
|
|
60
|
+
expect(getInstance).toBeDefined();
|
|
61
|
+
expect(typeof getInstance).toBe('function');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('should export createLogger function', () => {
|
|
65
|
+
expect(createLogger).toBeDefined();
|
|
66
|
+
expect(typeof createLogger).toBe('function');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('should export WorkflowTracker class', () => {
|
|
70
|
+
expect(WorkflowTracker).toBeDefined();
|
|
71
|
+
expect(typeof WorkflowTracker).toBe('function');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('Initialization', () => {
|
|
76
|
+
test('should initialize monitoring with config', async () => {
|
|
77
|
+
const monitoring = await init({
|
|
78
|
+
serviceName: 'test-service',
|
|
79
|
+
mode: 'off'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(monitoring).toBeDefined();
|
|
83
|
+
expect(monitoring.logger).toBeDefined();
|
|
84
|
+
expect(monitoring.workflow).toBeDefined();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('should provide logger methods', async () => {
|
|
88
|
+
const monitoring = await init({
|
|
89
|
+
serviceName: 'logger-test',
|
|
90
|
+
mode: 'off'
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(monitoring.info).toBeDefined();
|
|
94
|
+
expect(monitoring.error).toBeDefined();
|
|
95
|
+
expect(monitoring.warn).toBeDefined();
|
|
96
|
+
expect(monitoring.debug).toBeDefined();
|
|
97
|
+
expect(monitoring.log).toBeDefined();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('should provide workflow methods', async () => {
|
|
101
|
+
const monitoring = await init({
|
|
102
|
+
serviceName: 'workflow-test',
|
|
103
|
+
mode: 'off'
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
expect(monitoring.startWorkflow).toBeDefined();
|
|
107
|
+
expect(monitoring.stepWorkflow).toBeDefined();
|
|
108
|
+
expect(monitoring.endWorkflow).toBeDefined();
|
|
109
|
+
expect(monitoring.errorWorkflow).toBeDefined();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('should provide metric methods', async () => {
|
|
113
|
+
const monitoring = await init({
|
|
114
|
+
serviceName: 'metrics-test',
|
|
115
|
+
mode: 'off'
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
expect(monitoring.createCounter).toBeDefined();
|
|
119
|
+
expect(monitoring.createHistogram).toBeDefined();
|
|
120
|
+
expect(monitoring.createMetric).toBeDefined();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('Logger Operations', () => {
|
|
125
|
+
let monitoring;
|
|
126
|
+
|
|
127
|
+
beforeEach(async () => {
|
|
128
|
+
monitoring = await init({
|
|
129
|
+
serviceName: 'logger-ops',
|
|
130
|
+
mode: 'off',
|
|
131
|
+
logLevel: 'DEBUG'
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('should log info messages', () => {
|
|
136
|
+
expect(() => {
|
|
137
|
+
monitoring.info('Info message', { data: 'test' });
|
|
138
|
+
}).not.toThrow();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('should log error messages', () => {
|
|
142
|
+
expect(() => {
|
|
143
|
+
monitoring.error('Error message', { error: 'details' });
|
|
144
|
+
}).not.toThrow();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('should log warning messages', () => {
|
|
148
|
+
expect(() => {
|
|
149
|
+
monitoring.warn('Warning message');
|
|
150
|
+
}).not.toThrow();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('should log debug messages', () => {
|
|
154
|
+
expect(() => {
|
|
155
|
+
monitoring.debug('Debug message', { verbose: true });
|
|
156
|
+
}).not.toThrow();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('should handle log without data', () => {
|
|
160
|
+
expect(() => {
|
|
161
|
+
monitoring.info('Simple message');
|
|
162
|
+
monitoring.error('Error without data');
|
|
163
|
+
}).not.toThrow();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('Workflow Operations', () => {
|
|
168
|
+
let monitoring;
|
|
169
|
+
|
|
170
|
+
beforeEach(async () => {
|
|
171
|
+
monitoring = await init({
|
|
172
|
+
serviceName: 'workflow-ops',
|
|
173
|
+
mode: 'off'
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('should start workflow', () => {
|
|
178
|
+
const workflowId = monitoring.startWorkflow('wf-1', 'process', {
|
|
179
|
+
userId: '123'
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
expect(workflowId).toBe('wf-1');
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('should add workflow step', () => {
|
|
186
|
+
monitoring.startWorkflow('wf-2', 'pipeline');
|
|
187
|
+
|
|
188
|
+
expect(() => {
|
|
189
|
+
monitoring.stepWorkflow('wf-2', 'validation', { status: 'ok' });
|
|
190
|
+
}).not.toThrow();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
test('should end workflow', () => {
|
|
194
|
+
monitoring.startWorkflow('wf-3', 'batch');
|
|
195
|
+
|
|
196
|
+
expect(() => {
|
|
197
|
+
monitoring.endWorkflow('wf-3', 'success', { records: 100 });
|
|
198
|
+
}).not.toThrow();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('should handle workflow error', () => {
|
|
202
|
+
monitoring.startWorkflow('wf-error', 'risky');
|
|
203
|
+
|
|
204
|
+
expect(() => {
|
|
205
|
+
monitoring.errorWorkflow('wf-error', new Error('Test error'), {
|
|
206
|
+
code: 500
|
|
207
|
+
});
|
|
208
|
+
}).not.toThrow();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test('should handle non-existent workflow gracefully', () => {
|
|
212
|
+
expect(() => {
|
|
213
|
+
monitoring.stepWorkflow('non-existent', 'step');
|
|
214
|
+
monitoring.endWorkflow('non-existent', 'failed');
|
|
215
|
+
}).not.toThrow();
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('Metrics Operations', () => {
|
|
220
|
+
let monitoring;
|
|
221
|
+
|
|
222
|
+
beforeEach(async () => {
|
|
223
|
+
monitoring = await init({
|
|
224
|
+
serviceName: 'metrics-ops',
|
|
225
|
+
mode: 'off'
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('should create counter metric', () => {
|
|
230
|
+
const counter = monitoring.createCounter('requests', {
|
|
231
|
+
description: 'Request counter'
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
expect(counter).toBeDefined();
|
|
235
|
+
expect(counter.add).toBeDefined();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test('should create histogram metric', () => {
|
|
239
|
+
const histogram = monitoring.createHistogram('latency', {
|
|
240
|
+
description: 'Response latency',
|
|
241
|
+
unit: 'ms'
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
expect(histogram).toBeDefined();
|
|
245
|
+
expect(histogram.record).toBeDefined();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('should create metric with type', () => {
|
|
249
|
+
const metric = monitoring.createMetric('custom', 'counter', {
|
|
250
|
+
description: 'Custom counter'
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
expect(metric).toBeDefined();
|
|
254
|
+
expect(metric.add).toBeDefined();
|
|
255
|
+
expect(metric.record).toBeDefined();
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
test('should use counter metric', () => {
|
|
259
|
+
const counter = monitoring.createCounter('api.calls');
|
|
260
|
+
|
|
261
|
+
expect(() => {
|
|
262
|
+
counter.add(1, { endpoint: '/api/users' });
|
|
263
|
+
}).not.toThrow();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test('should use histogram metric', () => {
|
|
267
|
+
const histogram = monitoring.createHistogram('response.time');
|
|
268
|
+
|
|
269
|
+
expect(() => {
|
|
270
|
+
histogram.record(235.5, { endpoint: '/api/users' });
|
|
271
|
+
}).not.toThrow();
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe('Configuration', () => {
|
|
276
|
+
test('should use default configuration', async () => {
|
|
277
|
+
const monitoring = await init({
|
|
278
|
+
serviceName: 'default-config'
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
expect(monitoring.config).toBeDefined();
|
|
282
|
+
expect(monitoring.config.serviceName).toBe('default-config');
|
|
283
|
+
// Default mode is 'light' when not specified
|
|
284
|
+
expect(monitoring.config.mode).toBe('light');
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test('should override with environment variables', async () => {
|
|
288
|
+
process.env.MONITORING_MODE = 'debug';
|
|
289
|
+
|
|
290
|
+
const monitoring = await init({
|
|
291
|
+
serviceName: 'env-config'
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
expect(monitoring.config.mode).toBe('debug');
|
|
295
|
+
|
|
296
|
+
delete process.env.MONITORING_MODE;
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test('should handle all monitoring modes', async () => {
|
|
300
|
+
const modes = ['off', 'light', 'full', 'debug'];
|
|
301
|
+
|
|
302
|
+
for (const mode of modes) {
|
|
303
|
+
const monitoring = await init({
|
|
304
|
+
serviceName: `mode-${mode}`,
|
|
305
|
+
mode
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
expect(monitoring.config.mode).toBe(mode);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
describe('Singleton Pattern', () => {
|
|
314
|
+
test('should return singleton instance', () => {
|
|
315
|
+
const instance1 = getInstance();
|
|
316
|
+
const instance2 = getInstance();
|
|
317
|
+
|
|
318
|
+
expect(instance1).toBe(instance2);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
test('should create singleton on first getInstance', () => {
|
|
322
|
+
// Clear any existing singleton
|
|
323
|
+
const module = require('../../src');
|
|
324
|
+
if (module._singletonInstance) {
|
|
325
|
+
delete module._singletonInstance;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const instance = getInstance();
|
|
329
|
+
expect(instance).toBeDefined();
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe('Direct Module Usage', () => {
|
|
334
|
+
test('should create logger directly', () => {
|
|
335
|
+
const logger = createLogger({
|
|
336
|
+
serviceName: 'direct-logger',
|
|
337
|
+
mode: 'off'
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
expect(logger).toBeDefined();
|
|
341
|
+
expect(logger.info).toBeDefined();
|
|
342
|
+
expect(logger.error).toBeDefined();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
test('should create workflow tracker directly', () => {
|
|
346
|
+
const tracker = new WorkflowTracker('direct-tracker');
|
|
347
|
+
|
|
348
|
+
expect(tracker).toBeDefined();
|
|
349
|
+
expect(tracker.serviceName).toBe('direct-tracker');
|
|
350
|
+
expect(tracker.start).toBeDefined();
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe('Shutdown', () => {
|
|
355
|
+
test('should handle shutdown gracefully', async () => {
|
|
356
|
+
const monitoring = await init({
|
|
357
|
+
serviceName: 'shutdown-test',
|
|
358
|
+
mode: 'off'
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
await monitoring.shutdown();
|
|
362
|
+
expect(monitoring.core.shutdown).toHaveBeenCalled();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
test('should handle multiple shutdowns', async () => {
|
|
366
|
+
const monitoring = await init({
|
|
367
|
+
serviceName: 'multi-shutdown',
|
|
368
|
+
mode: 'off'
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
await monitoring.shutdown();
|
|
372
|
+
await monitoring.shutdown(); // Should handle multiple calls gracefully
|
|
373
|
+
expect(monitoring.core.shutdown).toHaveBeenCalledTimes(2);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
});
|