@muspellheim/shared 0.5.0 → 0.6.1
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/.prettierignore +3 -0
- package/.prettierrc +5 -0
- package/README.md +10 -5
- package/deno.json +4 -1
- package/deno.mk +68 -0
- package/eslint.config.js +23 -0
- package/lib/assert.js +2 -2
- package/lib/browser/index.js +0 -2
- package/lib/color.js +20 -22
- package/lib/health.js +3 -7
- package/lib/index.js +2 -1
- package/lib/lang.js +3 -5
- package/lib/logging.js +11 -10
- package/lib/long-polling-client.js +21 -10
- package/lib/message-client.js +0 -6
- package/lib/messages.js +68 -0
- package/lib/metrics.js +1 -1
- package/lib/node/actuator-controller.js +7 -8
- package/lib/node/configuration-properties.js +123 -86
- package/lib/node/handler.js +4 -2
- package/lib/node/index.js +1 -2
- package/lib/node/logging.js +5 -2
- package/lib/node/long-polling.js +2 -0
- package/lib/node/static-files-controller.js +15 -0
- package/lib/sse-client.js +21 -10
- package/lib/time.js +13 -11
- package/lib/util.js +45 -26
- package/lib/validation.js +13 -22
- package/lib/vector.js +1 -1
- package/lib/vitest/equality-testers.js +19 -0
- package/lib/vitest/index.js +1 -0
- package/lib/web-socket-client.js +26 -9
- package/package.json +12 -6
- package/tsconfig.json +13 -0
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/README.md
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
# Shared
|
|
1
|
+
# Shared
|
|
2
|
+
|
|
3
|
+
[](https://github.com/falkoschumann/muspellheim-utils-javascript/actions/workflows/build.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@muspellheim/shared)
|
|
2
5
|
|
|
3
6
|
Some shared modules for the browser and Node from my projects.
|
|
4
7
|
|
|
@@ -9,8 +12,8 @@ Some shared modules for the browser and Node from my projects.
|
|
|
9
12
|
## Usage
|
|
10
13
|
|
|
11
14
|
import { XXX } from '@muspellheim/shared';
|
|
12
|
-
import { XXX } from '@muspellheim/shared/browser
|
|
13
|
-
import { XXX } from '@muspellheim/shared/
|
|
15
|
+
import { XXX } from '@muspellheim/shared/browser';
|
|
16
|
+
import { XXX } from '@muspellheim/shared/node';
|
|
14
17
|
|
|
15
18
|
See https://falkoschumann.github.io/muspellheim-shared-javascript/
|
|
16
19
|
|
|
@@ -25,5 +28,7 @@ The `Makefile` runs the build as default task. Other tasks are
|
|
|
25
28
|
|
|
26
29
|
## Open issues
|
|
27
30
|
|
|
28
|
-
- [ ] Add missing docs
|
|
29
|
-
- [ ] Use asserts for parameters
|
|
31
|
+
- [ ] Add missing docs
|
|
32
|
+
- [ ] Use asserts for parameters
|
|
33
|
+
- [ ] Rename project to `muspellheim-shared-js`
|
|
34
|
+
- [ ] Use equatable protocol for value objects
|
package/deno.json
CHANGED
package/deno.mk
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Possible values: major, minor, patch or concrete version
|
|
2
|
+
VERSION = minor
|
|
3
|
+
|
|
4
|
+
all: dist docs check
|
|
5
|
+
|
|
6
|
+
clean:
|
|
7
|
+
rm -rf coverage docs
|
|
8
|
+
|
|
9
|
+
distclean: clean
|
|
10
|
+
rm -rf dist
|
|
11
|
+
rm -rf node_modules
|
|
12
|
+
|
|
13
|
+
dist: build
|
|
14
|
+
|
|
15
|
+
release: all
|
|
16
|
+
npm version $(VERSION) -m "chore: create release v%s"
|
|
17
|
+
git push
|
|
18
|
+
git push --tags
|
|
19
|
+
|
|
20
|
+
publish: all
|
|
21
|
+
deno publish --dry-run
|
|
22
|
+
|
|
23
|
+
docs:
|
|
24
|
+
# FIXME deno doc --html --name="Muspellheim Shared" --lint lib
|
|
25
|
+
# FIXME deno doc --html --name="Muspellheim Shared" lib
|
|
26
|
+
|
|
27
|
+
check: test
|
|
28
|
+
deno run --allow-all npm:eslint lib test
|
|
29
|
+
deno run --allow-all npm:prettier . --check
|
|
30
|
+
# TODO deno fmt --check
|
|
31
|
+
deno lint
|
|
32
|
+
|
|
33
|
+
format:
|
|
34
|
+
deno run --allow-all npm:eslint --fix lib test
|
|
35
|
+
deno run --allow-all npm:prettier . --write
|
|
36
|
+
# TODO deno fmt
|
|
37
|
+
deno lint --fix
|
|
38
|
+
|
|
39
|
+
dev: build
|
|
40
|
+
deno run --allow-all npm:vitest
|
|
41
|
+
|
|
42
|
+
test: build
|
|
43
|
+
deno run --allow-all npm:vitest run
|
|
44
|
+
|
|
45
|
+
unit-tests: build
|
|
46
|
+
deno run --allow-all npm:vitest run --testPathPattern=".*\/unit\/.*"
|
|
47
|
+
|
|
48
|
+
integration-tests: build
|
|
49
|
+
deno run --allow-all npm:vitest run --testPathPattern=".*\/integration\/.*"
|
|
50
|
+
|
|
51
|
+
e2e-tests: build
|
|
52
|
+
deno run --allow-all npm:vitest run --testPathPattern=".*\/e2e\/.*"
|
|
53
|
+
|
|
54
|
+
coverage: build
|
|
55
|
+
deno run --allow-all npm:vitest run --coverage
|
|
56
|
+
|
|
57
|
+
build: prepare
|
|
58
|
+
|
|
59
|
+
prepare: version
|
|
60
|
+
deno install
|
|
61
|
+
|
|
62
|
+
version:
|
|
63
|
+
@echo "Use Deno $(shell deno --version)"
|
|
64
|
+
|
|
65
|
+
.PHONY: all clean distclean dist release publish docs \
|
|
66
|
+
check format \
|
|
67
|
+
dev test unit-tests integration-tests e2e-tests coverage \
|
|
68
|
+
build prepare version
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
|
|
4
|
+
/** @type { import("eslint").Linter.FlatConfig[] } */
|
|
5
|
+
export default [
|
|
6
|
+
js.configs.recommended,
|
|
7
|
+
{
|
|
8
|
+
languageOptions: {
|
|
9
|
+
ecmaVersion: 2022,
|
|
10
|
+
globals: {
|
|
11
|
+
...globals.es2021,
|
|
12
|
+
...globals.node,
|
|
13
|
+
...globals.browser,
|
|
14
|
+
//...globals.serviceworker,
|
|
15
|
+
//...globals['shared-node-browser'],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
ignores: ['coverage/**', 'docs/**'],
|
|
19
|
+
rules: {
|
|
20
|
+
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
];
|
package/lib/assert.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export function assertNotNull(object, message) {
|
|
11
11
|
if (object == null) {
|
|
12
|
-
|
|
13
|
-
throw new ReferenceError(
|
|
12
|
+
const m = typeof message === 'function' ? message() : message;
|
|
13
|
+
throw new ReferenceError(m);
|
|
14
14
|
}
|
|
15
15
|
}
|
package/lib/browser/index.js
CHANGED
package/lib/color.js
CHANGED
|
@@ -6,37 +6,35 @@ const FACTOR = 0.7;
|
|
|
6
6
|
* The Color class represents a color in the RGB color space.
|
|
7
7
|
*/
|
|
8
8
|
export class Color {
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The RGB value of the color.
|
|
11
|
+
*
|
|
12
|
+
* @type {number}
|
|
13
|
+
*/
|
|
14
|
+
rgb;
|
|
10
15
|
|
|
11
16
|
/**
|
|
12
17
|
* Creates a color instance from RGB values.
|
|
13
18
|
*
|
|
14
|
-
* @param {number} red The red component or the RGB value.
|
|
19
|
+
* @param {number|string} [red] The red component or the RGB value.
|
|
15
20
|
* @param {number} [green] The green component.
|
|
16
21
|
* @param {number} [blue] The blue component.
|
|
17
22
|
*/
|
|
18
23
|
constructor(red, green, blue) {
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
if (typeof red === 'string') {
|
|
25
|
+
this.rgb = parseInt(red, 16);
|
|
26
|
+
} else if (
|
|
27
|
+
typeof red === 'number' &&
|
|
28
|
+
typeof green === 'number' &&
|
|
29
|
+
typeof blue === 'number'
|
|
30
|
+
) {
|
|
31
|
+
this.rgb =
|
|
32
|
+
((red & 0xff) << 16) | ((green & 0xff) << 8) | ((blue & 0xff) << 0);
|
|
33
|
+
} else if (typeof red === 'number') {
|
|
34
|
+
this.rgb = red;
|
|
35
|
+
} else {
|
|
36
|
+
this.rgb = NaN;
|
|
27
37
|
}
|
|
28
|
-
|
|
29
|
-
this.#value = ((red & 0xff) << 16) | ((green & 0xff) << 8) |
|
|
30
|
-
((blue & 0xff) << 0);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The RGB value of the color.
|
|
35
|
-
*
|
|
36
|
-
* @type {number}
|
|
37
|
-
*/
|
|
38
|
-
get rgb() {
|
|
39
|
-
return this.#value;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
/**
|
package/lib/health.js
CHANGED
|
@@ -161,10 +161,7 @@ export class Health {
|
|
|
161
161
|
* @param {Status} status The status of the health.
|
|
162
162
|
* @param {Record<string, *>} details The details of the health.
|
|
163
163
|
*/
|
|
164
|
-
constructor(
|
|
165
|
-
/** @type {Status} */ status,
|
|
166
|
-
/** @type {?Record<string, *>} */ details,
|
|
167
|
-
) {
|
|
164
|
+
constructor(status, details) {
|
|
168
165
|
assertNotNull(status, 'Status must not be null.');
|
|
169
166
|
// TODO assertNotNull(details, 'Details must not be null.');
|
|
170
167
|
|
|
@@ -502,9 +499,8 @@ export class HealthEndpoint {
|
|
|
502
499
|
|
|
503
500
|
let health;
|
|
504
501
|
if (statuses.length > 0) {
|
|
505
|
-
const status =
|
|
506
|
-
statuses
|
|
507
|
-
);
|
|
502
|
+
const status =
|
|
503
|
+
this.#groups.primary.statusAggregator.getAggregateStatus(statuses);
|
|
508
504
|
health = new CompositeHealth(status, components);
|
|
509
505
|
} else {
|
|
510
506
|
health = Health.up();
|
package/lib/index.js
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
export * from './assert.js';
|
|
4
4
|
export * from './color.js';
|
|
5
5
|
export * from './configurable-responses.js';
|
|
6
|
-
export * from './lang.js';
|
|
7
6
|
export * from './feature-toggle.js';
|
|
8
7
|
export * from './health.js';
|
|
8
|
+
export * from './lang.js';
|
|
9
9
|
export * from './logging.js';
|
|
10
10
|
export * from './long-polling-client.js';
|
|
11
11
|
export * from './message-client.js';
|
|
12
|
+
export * from './messages.js';
|
|
12
13
|
export * from './metrics.js';
|
|
13
14
|
export * from './output-tracker.js';
|
|
14
15
|
export * from './service-locator.js';
|
package/lib/lang.js
CHANGED
|
@@ -22,14 +22,12 @@ import { ensureArguments } from './validation.js';
|
|
|
22
22
|
* static NO = new YesNo('NO', 1);
|
|
23
23
|
* }
|
|
24
24
|
* ```
|
|
25
|
-
*
|
|
26
|
-
* @template [T=Enum] - the type of the enum object
|
|
27
25
|
*/
|
|
28
26
|
export class Enum {
|
|
29
27
|
/**
|
|
30
28
|
* Returns all enum constants.
|
|
31
29
|
*
|
|
32
|
-
* @return {
|
|
30
|
+
* @return {Enum[]} All enum constants.
|
|
33
31
|
*/
|
|
34
32
|
static values() {
|
|
35
33
|
return Object.values(this);
|
|
@@ -39,7 +37,7 @@ export class Enum {
|
|
|
39
37
|
* Returns an enum constant by its name.
|
|
40
38
|
*
|
|
41
39
|
* @param {string} name The name of the enum constant.
|
|
42
|
-
* @return {
|
|
40
|
+
* @return {Enum} The enum constant.
|
|
43
41
|
*/
|
|
44
42
|
static valueOf(name) {
|
|
45
43
|
const value = this.values().find((v) => v.name === name);
|
|
@@ -53,8 +51,8 @@ export class Enum {
|
|
|
53
51
|
/**
|
|
54
52
|
* Creates an enum object.
|
|
55
53
|
*
|
|
56
|
-
* @param {number} ordinal The ordinal of the enum constant.
|
|
57
54
|
* @param {string} name The name of the enum constant.
|
|
55
|
+
* @param {number} ordinal The ordinal of the enum constant.
|
|
58
56
|
*/
|
|
59
57
|
constructor(name, ordinal) {
|
|
60
58
|
ensureArguments(arguments, [String, Number]);
|
package/lib/logging.js
CHANGED
|
@@ -179,7 +179,7 @@ export class Logger extends EventTarget {
|
|
|
179
179
|
*
|
|
180
180
|
* The root logger has not a parent.
|
|
181
181
|
*
|
|
182
|
-
* @type {
|
|
182
|
+
* @type {Logger=}
|
|
183
183
|
*/
|
|
184
184
|
parent;
|
|
185
185
|
|
|
@@ -202,8 +202,7 @@ export class Logger extends EventTarget {
|
|
|
202
202
|
/**
|
|
203
203
|
* Initializes a new logger with the given name.
|
|
204
204
|
*
|
|
205
|
-
* @param {string} name The name of the logger.
|
|
206
|
-
* @private
|
|
205
|
+
* @param {?string} name The name of the logger.
|
|
207
206
|
*/
|
|
208
207
|
constructor(name) {
|
|
209
208
|
super();
|
|
@@ -213,7 +212,7 @@ export class Logger extends EventTarget {
|
|
|
213
212
|
/**
|
|
214
213
|
* The name of the logger.
|
|
215
214
|
*
|
|
216
|
-
* @type {string}
|
|
215
|
+
* @type {?string}
|
|
217
216
|
*/
|
|
218
217
|
get name() {
|
|
219
218
|
return this.#name;
|
|
@@ -307,7 +306,7 @@ export class Logger extends EventTarget {
|
|
|
307
306
|
isLoggable(level) {
|
|
308
307
|
return this.level != null
|
|
309
308
|
? level >= this.level
|
|
310
|
-
: this.parent
|
|
309
|
+
: (this.parent?.isLoggable(level) ?? false);
|
|
311
310
|
}
|
|
312
311
|
|
|
313
312
|
/**
|
|
@@ -376,7 +375,7 @@ export class LogRecord {
|
|
|
376
375
|
/**
|
|
377
376
|
* The name of the logger.
|
|
378
377
|
*
|
|
379
|
-
* @type {string|
|
|
378
|
+
* @type {string|null}
|
|
380
379
|
*/
|
|
381
380
|
loggerName;
|
|
382
381
|
|
|
@@ -428,7 +427,7 @@ export class Handler {
|
|
|
428
427
|
* @param {LogRecord} record The log record to publish.
|
|
429
428
|
* @abstract
|
|
430
429
|
*/
|
|
431
|
-
async publish() {
|
|
430
|
+
async publish(_record) {
|
|
432
431
|
await Promise.reject('Not implemented');
|
|
433
432
|
}
|
|
434
433
|
|
|
@@ -489,7 +488,7 @@ export class Formatter {
|
|
|
489
488
|
* @return {string} The formatted log record.
|
|
490
489
|
* @abstract
|
|
491
490
|
*/
|
|
492
|
-
format() {
|
|
491
|
+
format(_record) {
|
|
493
492
|
throw new Error('Not implemented');
|
|
494
493
|
}
|
|
495
494
|
}
|
|
@@ -507,7 +506,8 @@ export class SimpleFormatter extends Formatter {
|
|
|
507
506
|
s += ' [' + record.loggerName + ']';
|
|
508
507
|
}
|
|
509
508
|
s += ' ' + record.level.toString();
|
|
510
|
-
s +=
|
|
509
|
+
s +=
|
|
510
|
+
' - ' +
|
|
511
511
|
record.message
|
|
512
512
|
.map((m) => (typeof m === 'object' ? JSON.stringify(m) : m))
|
|
513
513
|
.join(' ');
|
|
@@ -572,7 +572,8 @@ class LogManager {
|
|
|
572
572
|
}
|
|
573
573
|
|
|
574
574
|
addLogger(/** @type {Logger} */ logger) {
|
|
575
|
-
|
|
575
|
+
const loggerName = logger.name;
|
|
576
|
+
this.#namedLoggers.set(loggerName, logger);
|
|
576
577
|
}
|
|
577
578
|
|
|
578
579
|
getLogger(/** @type {string} */ name) {
|
|
@@ -35,16 +35,14 @@ export class LongPollingClient extends MessageClient {
|
|
|
35
35
|
* @param {object} options
|
|
36
36
|
* @return {LongPollingClient} A new nulled long polling client.
|
|
37
37
|
*/
|
|
38
|
-
static createNull(
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} = {},
|
|
47
|
-
) {
|
|
38
|
+
static createNull({
|
|
39
|
+
fetchResponse = {
|
|
40
|
+
status: 304,
|
|
41
|
+
statusText: 'Not Modified',
|
|
42
|
+
headers: undefined,
|
|
43
|
+
body: null,
|
|
44
|
+
},
|
|
45
|
+
} = {}) {
|
|
48
46
|
return new LongPollingClient(90000, 0, createFetchStub(fetchResponse));
|
|
49
47
|
}
|
|
50
48
|
|
|
@@ -75,14 +73,23 @@ export class LongPollingClient extends MessageClient {
|
|
|
75
73
|
this.#aboutController = new AbortController();
|
|
76
74
|
}
|
|
77
75
|
|
|
76
|
+
/**
|
|
77
|
+
* @override
|
|
78
|
+
*/
|
|
78
79
|
get isConnected() {
|
|
79
80
|
return this.#connected;
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
/**
|
|
84
|
+
* @override
|
|
85
|
+
*/
|
|
82
86
|
get url() {
|
|
83
87
|
return this.#url;
|
|
84
88
|
}
|
|
85
89
|
|
|
90
|
+
/**
|
|
91
|
+
* @override
|
|
92
|
+
*/
|
|
86
93
|
async connect(url) {
|
|
87
94
|
if (this.isConnected) {
|
|
88
95
|
throw new Error('Already connected.');
|
|
@@ -103,6 +110,9 @@ export class LongPollingClient extends MessageClient {
|
|
|
103
110
|
return OutputTracker.create(this, REQUEST_SENT_EVENT);
|
|
104
111
|
}
|
|
105
112
|
|
|
113
|
+
/**
|
|
114
|
+
* @override
|
|
115
|
+
*/
|
|
106
116
|
async close() {
|
|
107
117
|
this.#aboutController.abort();
|
|
108
118
|
this.#connected = false;
|
|
@@ -126,6 +136,7 @@ export class LongPollingClient extends MessageClient {
|
|
|
126
136
|
});
|
|
127
137
|
await this.#handleResponse(response);
|
|
128
138
|
} catch (error) {
|
|
139
|
+
// @ts-ignore NodeJS error code
|
|
129
140
|
if (error.name === 'AbortError') {
|
|
130
141
|
break;
|
|
131
142
|
} else {
|
package/lib/message-client.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* @import { LongPollingClient } from './long-polling-client.js'
|
|
5
|
-
* @import { SseClient } from './sse-client.js'
|
|
6
|
-
* @import { WebSocketClient } from './web-socket-client.js'
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
3
|
/**
|
|
10
4
|
* An interface for a streaming message client.
|
|
11
5
|
*
|
package/lib/messages.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides CQNS features.
|
|
3
|
+
*
|
|
4
|
+
* The Command Query Notification Separation principle is a software design
|
|
5
|
+
* principle that separates the concerns of commands, queries, and
|
|
6
|
+
* notifications.
|
|
7
|
+
*
|
|
8
|
+
* Message hierarchy:
|
|
9
|
+
*
|
|
10
|
+
* - Message
|
|
11
|
+
* - Incoming / outgoing
|
|
12
|
+
* - Request (outgoing) -> response (incoming)
|
|
13
|
+
* - Command -> command status
|
|
14
|
+
* - Query -> query result
|
|
15
|
+
* - Notification
|
|
16
|
+
* - Incoming: notification -> commands
|
|
17
|
+
* - Outgoing
|
|
18
|
+
* - Event (internal)
|
|
19
|
+
*
|
|
20
|
+
* @see https://ralfw.de/command-query-notification-separation-cqns/
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The status returned by a command handler.
|
|
26
|
+
*/
|
|
27
|
+
export class CommandStatus {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a successful status.
|
|
30
|
+
*/
|
|
31
|
+
static success() {
|
|
32
|
+
return new CommandStatus(true);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates a failed status.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} errorMessage
|
|
39
|
+
*/
|
|
40
|
+
static failure(errorMessage) {
|
|
41
|
+
return new CommandStatus(false, errorMessage);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Indicates whether the command was successful.
|
|
46
|
+
*
|
|
47
|
+
* @type {boolean}
|
|
48
|
+
*/
|
|
49
|
+
isSuccess;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The error message if the command failed.
|
|
53
|
+
*
|
|
54
|
+
* @type {string}
|
|
55
|
+
*/
|
|
56
|
+
errorMessage;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new instance of CommandStatus.
|
|
60
|
+
*
|
|
61
|
+
* @param {boolean} isSuccess Indicates whether the command was successful.
|
|
62
|
+
* @param {string} [errorMessage] The error message if the command failed.
|
|
63
|
+
*/
|
|
64
|
+
constructor(isSuccess, errorMessage) {
|
|
65
|
+
this.isSuccess = isSuccess;
|
|
66
|
+
this.errorMessage = errorMessage;
|
|
67
|
+
}
|
|
68
|
+
}
|
package/lib/metrics.js
CHANGED
|
@@ -30,7 +30,7 @@ export class MeterRegistry {
|
|
|
30
30
|
counter(name, tags) {
|
|
31
31
|
const id = MeterId.create({ name, tags, type: MeterType.COUNTER });
|
|
32
32
|
/** @type {Counter} */ let meter = this.#meters.find((meter) =>
|
|
33
|
-
meter.id.equals(id)
|
|
33
|
+
meter.id.equals(id),
|
|
34
34
|
);
|
|
35
35
|
if (!meter) {
|
|
36
36
|
meter = new Counter(id);
|
|
@@ -10,6 +10,8 @@ import process from 'node:process';
|
|
|
10
10
|
|
|
11
11
|
import * as handler from './handler.js';
|
|
12
12
|
|
|
13
|
+
// TODO Remove dependency to express
|
|
14
|
+
|
|
13
15
|
export class ActuatorController {
|
|
14
16
|
#services;
|
|
15
17
|
#healthContributorRegistry;
|
|
@@ -36,8 +38,8 @@ export class ActuatorController {
|
|
|
36
38
|
/** @type {express.Request} */ request,
|
|
37
39
|
/** @type {express.Response} */ response,
|
|
38
40
|
) {
|
|
39
|
-
let requestedUrl =
|
|
40
|
-
request.originalUrl;
|
|
41
|
+
let requestedUrl =
|
|
42
|
+
request.protocol + '://' + request.get('host') + request.originalUrl;
|
|
41
43
|
if (!requestedUrl.endsWith('/')) {
|
|
42
44
|
requestedUrl += '/';
|
|
43
45
|
}
|
|
@@ -92,12 +94,9 @@ export class ActuatorController {
|
|
|
92
94
|
|
|
93
95
|
const metrics = await this.#services.getMetrics();
|
|
94
96
|
const timestamp = new Date().getTime();
|
|
95
|
-
let body =
|
|
96
|
-
|
|
97
|
-
body +=
|
|
98
|
-
`# TYPE presenters_count gauge\npresenters_count ${metrics.presentersCount} ${timestamp}\n\n`;
|
|
99
|
-
body +=
|
|
100
|
-
`# TYPE comments_count gauge\ncomments_count ${metrics.commentsCount} ${timestamp}\n\n`;
|
|
97
|
+
let body = `# TYPE talks_count gauge\ntalks_count ${metrics.talksCount} ${timestamp}\n\n`;
|
|
98
|
+
body += `# TYPE presenters_count gauge\npresenters_count ${metrics.presentersCount} ${timestamp}\n\n`;
|
|
99
|
+
body += `# TYPE comments_count gauge\ncomments_count ${metrics.commentsCount} ${timestamp}\n\n`;
|
|
101
100
|
handler.reply(response, { body });
|
|
102
101
|
}
|
|
103
102
|
}
|