@muspellheim/shared 0.6.1 → 0.7.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/LICENSE.txt +1 -1
- package/README.md +11 -13
- package/dist/shared.d.ts +423 -0
- package/dist/shared.js +535 -0
- package/dist/shared.umd.cjs +1 -0
- package/package.json +27 -23
- package/.prettierignore +0 -3
- package/.prettierrc +0 -5
- package/deno.json +0 -15
- package/deno.mk +0 -68
- package/eslint.config.js +0 -23
- package/lib/assert.js +0 -15
- package/lib/browser/components.js +0 -165
- package/lib/browser/index.js +0 -3
- package/lib/color.js +0 -137
- package/lib/configurable-responses.js +0 -69
- package/lib/feature-toggle.js +0 -9
- package/lib/health.js +0 -510
- package/lib/index.js +0 -23
- package/lib/lang.js +0 -100
- package/lib/logging.js +0 -599
- package/lib/long-polling-client.js +0 -186
- package/lib/message-client.js +0 -68
- package/lib/messages.js +0 -68
- package/lib/metrics.js +0 -120
- package/lib/node/actuator-controller.js +0 -102
- package/lib/node/configuration-properties.js +0 -291
- package/lib/node/handler.js +0 -25
- package/lib/node/index.js +0 -9
- package/lib/node/logging.js +0 -60
- package/lib/node/long-polling.js +0 -83
- package/lib/node/sse-emitter.js +0 -104
- package/lib/node/static-files-controller.js +0 -15
- package/lib/output-tracker.js +0 -89
- package/lib/service-locator.js +0 -44
- package/lib/sse-client.js +0 -163
- package/lib/stop-watch.js +0 -54
- package/lib/store.js +0 -129
- package/lib/time.js +0 -445
- package/lib/util.js +0 -380
- package/lib/validation.js +0 -290
- package/lib/vector.js +0 -194
- package/lib/vitest/equality-testers.js +0 -19
- package/lib/vitest/index.js +0 -1
- package/lib/web-socket-client.js +0 -262
- package/tsconfig.json +0 -13
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
import { ConfigurableResponses } from './configurable-responses.js';
|
|
4
|
-
import { MessageClient } from './message-client.js';
|
|
5
|
-
import { OutputTracker } from './output-tracker.js';
|
|
6
|
-
import { sleep } from './lang.js';
|
|
7
|
-
|
|
8
|
-
const REQUEST_SENT_EVENT = 'request-sent';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A client handling long polling a HTTP request.
|
|
12
|
-
*
|
|
13
|
-
* @implements {MessageClient}
|
|
14
|
-
*/
|
|
15
|
-
export class LongPollingClient extends MessageClient {
|
|
16
|
-
/**
|
|
17
|
-
* Creates a long polling client.
|
|
18
|
-
*
|
|
19
|
-
* @param {object} options
|
|
20
|
-
* @param {number} [options.wait=90000] The wait interval for a response.
|
|
21
|
-
* @param {number} [options.retry=1000] The retry interval after an error.
|
|
22
|
-
* @return {LongPollingClient} A new long polling client.
|
|
23
|
-
*/
|
|
24
|
-
static create({ wait = 90000, retry = 1000 } = {}) {
|
|
25
|
-
return new LongPollingClient(
|
|
26
|
-
wait,
|
|
27
|
-
retry,
|
|
28
|
-
globalThis.fetch.bind(globalThis),
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Creates a nulled long polling client.
|
|
34
|
-
*
|
|
35
|
-
* @param {object} options
|
|
36
|
-
* @return {LongPollingClient} A new nulled long polling client.
|
|
37
|
-
*/
|
|
38
|
-
static createNull({
|
|
39
|
-
fetchResponse = {
|
|
40
|
-
status: 304,
|
|
41
|
-
statusText: 'Not Modified',
|
|
42
|
-
headers: undefined,
|
|
43
|
-
body: null,
|
|
44
|
-
},
|
|
45
|
-
} = {}) {
|
|
46
|
-
return new LongPollingClient(90000, 0, createFetchStub(fetchResponse));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
#wait;
|
|
50
|
-
#retry;
|
|
51
|
-
#fetch;
|
|
52
|
-
#connected;
|
|
53
|
-
#aboutController;
|
|
54
|
-
#url;
|
|
55
|
-
#tag;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* The constructor is for internal use. Use the factory methods instead.
|
|
59
|
-
*
|
|
60
|
-
* @see LongPollingClient.create
|
|
61
|
-
* @see LongPollingClient.createNull
|
|
62
|
-
*/
|
|
63
|
-
constructor(
|
|
64
|
-
/** @type {number} */ wait,
|
|
65
|
-
/** @type {number} */ retry,
|
|
66
|
-
/** @type {fetch} */ fetchFunc,
|
|
67
|
-
) {
|
|
68
|
-
super();
|
|
69
|
-
this.#wait = wait;
|
|
70
|
-
this.#retry = retry;
|
|
71
|
-
this.#fetch = fetchFunc;
|
|
72
|
-
this.#connected = false;
|
|
73
|
-
this.#aboutController = new AbortController();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @override
|
|
78
|
-
*/
|
|
79
|
-
get isConnected() {
|
|
80
|
-
return this.#connected;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @override
|
|
85
|
-
*/
|
|
86
|
-
get url() {
|
|
87
|
-
return this.#url;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @override
|
|
92
|
-
*/
|
|
93
|
-
async connect(url) {
|
|
94
|
-
if (this.isConnected) {
|
|
95
|
-
throw new Error('Already connected.');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
this.#url = url;
|
|
99
|
-
this.#startPolling();
|
|
100
|
-
this.dispatchEvent(new Event('open'));
|
|
101
|
-
await Promise.resolve();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Returns a tracker for requests sent.
|
|
106
|
-
*
|
|
107
|
-
* @return {OutputTracker} A new output tracker.
|
|
108
|
-
*/
|
|
109
|
-
trackRequestSent() {
|
|
110
|
-
return OutputTracker.create(this, REQUEST_SENT_EVENT);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @override
|
|
115
|
-
*/
|
|
116
|
-
async close() {
|
|
117
|
-
this.#aboutController.abort();
|
|
118
|
-
this.#connected = false;
|
|
119
|
-
await Promise.resolve();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async #startPolling() {
|
|
123
|
-
this.#connected = true;
|
|
124
|
-
while (this.isConnected) {
|
|
125
|
-
try {
|
|
126
|
-
const headers = { Prefer: `wait=${this.#wait / 1000}` };
|
|
127
|
-
if (this.#tag) {
|
|
128
|
-
headers['If-None-Match'] = this.#tag;
|
|
129
|
-
}
|
|
130
|
-
this.dispatchEvent(
|
|
131
|
-
new CustomEvent(REQUEST_SENT_EVENT, { detail: { headers } }),
|
|
132
|
-
);
|
|
133
|
-
const response = await this.#fetch(this.#url, {
|
|
134
|
-
headers,
|
|
135
|
-
signal: this.#aboutController.signal,
|
|
136
|
-
});
|
|
137
|
-
await this.#handleResponse(response);
|
|
138
|
-
} catch (error) {
|
|
139
|
-
// @ts-ignore NodeJS error code
|
|
140
|
-
if (error.name === 'AbortError') {
|
|
141
|
-
break;
|
|
142
|
-
} else {
|
|
143
|
-
await this.#handleError(error);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
async #handleResponse(/** @type {Response} */ response) {
|
|
150
|
-
if (response.status === 304) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (!response.ok) {
|
|
155
|
-
throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
this.#tag = response.headers.get('ETag');
|
|
159
|
-
const message = await response.text();
|
|
160
|
-
this.dispatchEvent(new MessageEvent('message', { data: message }));
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async #handleError(error) {
|
|
164
|
-
console.error(error);
|
|
165
|
-
this.dispatchEvent(new Event('error'));
|
|
166
|
-
await sleep(this.#retry);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function createFetchStub(response) {
|
|
171
|
-
const responses = ConfigurableResponses.create(response);
|
|
172
|
-
return async (_url, options) => {
|
|
173
|
-
await sleep(0);
|
|
174
|
-
return new Promise((resolve, reject) => {
|
|
175
|
-
options?.signal?.addEventListener('abort', () => reject());
|
|
176
|
-
const res = responses.next();
|
|
177
|
-
resolve(
|
|
178
|
-
new Response(res.body, {
|
|
179
|
-
status: res.status,
|
|
180
|
-
statusText: res.statusText,
|
|
181
|
-
headers: res.headers,
|
|
182
|
-
}),
|
|
183
|
-
);
|
|
184
|
-
});
|
|
185
|
-
};
|
|
186
|
-
}
|
package/lib/message-client.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* An interface for a streaming message client.
|
|
5
|
-
*
|
|
6
|
-
* Emits the following events:
|
|
7
|
-
*
|
|
8
|
-
* - open, {@link Event}
|
|
9
|
-
* - message, {@link MessageEvent}
|
|
10
|
-
* - error, {@link Event}
|
|
11
|
-
*
|
|
12
|
-
* It is used for wrappers around {@link EventSource} and {@link WebSocket},
|
|
13
|
-
* also for long polling.
|
|
14
|
-
*
|
|
15
|
-
* @interface
|
|
16
|
-
* @see SseClient
|
|
17
|
-
* @see WebSocketClient
|
|
18
|
-
* @see LongPollingClient
|
|
19
|
-
*/
|
|
20
|
-
export class MessageClient extends EventTarget {
|
|
21
|
-
/**
|
|
22
|
-
* Returns whether the client is connected.
|
|
23
|
-
*
|
|
24
|
-
* @type {boolean}
|
|
25
|
-
* @readonly
|
|
26
|
-
*/
|
|
27
|
-
get isConnected() {
|
|
28
|
-
throw new Error('Not implemented.');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Returns the server URL.
|
|
33
|
-
*
|
|
34
|
-
* @type {string}
|
|
35
|
-
* @readonly
|
|
36
|
-
*/
|
|
37
|
-
get url() {
|
|
38
|
-
throw new Error('Not implemented.');
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Connects to the server.
|
|
43
|
-
*
|
|
44
|
-
* @param {URL | string} url The server URL to connect to.
|
|
45
|
-
*/
|
|
46
|
-
async connect(_url) {
|
|
47
|
-
await Promise.reject('Not implemented.');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Sends a message to the server.
|
|
52
|
-
*
|
|
53
|
-
* This is an optional method for streams with bidirectional communication.
|
|
54
|
-
*
|
|
55
|
-
* @param {string} message The message to send.
|
|
56
|
-
* @param {string} type The optional message type.
|
|
57
|
-
*/
|
|
58
|
-
async send(_message, _type) {
|
|
59
|
-
await Promise.reject('Not implemented.');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Closes the connection.
|
|
64
|
-
*/
|
|
65
|
-
async close() {
|
|
66
|
-
await Promise.reject('Not implemented.');
|
|
67
|
-
}
|
|
68
|
-
}
|
package/lib/messages.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Defines a simple metrics library.
|
|
5
|
-
*
|
|
6
|
-
* Portated from
|
|
7
|
-
* [Micrometer](https://docs.micrometer.io/micrometer/reference/overview.html).
|
|
8
|
-
*
|
|
9
|
-
* @module
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { Enum } from './lang.js';
|
|
13
|
-
|
|
14
|
-
// TODO Create gauges (can increment and decrement)
|
|
15
|
-
// TODO Create timers (total time, average time and count)
|
|
16
|
-
// TODO Publish metrics to a server via HTTP
|
|
17
|
-
// TODO Provide metrics for Prometheus
|
|
18
|
-
|
|
19
|
-
export class MeterRegistry {
|
|
20
|
-
static create() {
|
|
21
|
-
return new MeterRegistry();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
#meters = [];
|
|
25
|
-
|
|
26
|
-
get meters() {
|
|
27
|
-
return this.#meters;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
counter(name, tags) {
|
|
31
|
-
const id = MeterId.create({ name, tags, type: MeterType.COUNTER });
|
|
32
|
-
/** @type {Counter} */ let meter = this.#meters.find((meter) =>
|
|
33
|
-
meter.id.equals(id),
|
|
34
|
-
);
|
|
35
|
-
if (!meter) {
|
|
36
|
-
meter = new Counter(id);
|
|
37
|
-
this.#meters.push(meter);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// TODO validate found meter is a counter
|
|
41
|
-
return meter;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export class Meter {
|
|
46
|
-
#id;
|
|
47
|
-
|
|
48
|
-
constructor(/** @type {MeterId} */ id) {
|
|
49
|
-
// TODO validate parameters are not null
|
|
50
|
-
this.#id = id;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
get id() {
|
|
54
|
-
return this.#id;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export class Counter extends Meter {
|
|
59
|
-
#count = 0;
|
|
60
|
-
|
|
61
|
-
constructor(/** @type {MeterId} */ id) {
|
|
62
|
-
super(id);
|
|
63
|
-
// TODO validate type is counter
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
count() {
|
|
67
|
-
return this.#count;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
increment(amount = 1) {
|
|
71
|
-
this.#count += amount;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export class MeterId {
|
|
76
|
-
static create({ name, tags = [], type }) {
|
|
77
|
-
return new MeterId(name, tags, type);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
#name;
|
|
81
|
-
#tags;
|
|
82
|
-
#type;
|
|
83
|
-
|
|
84
|
-
constructor(
|
|
85
|
-
/** @type {string} */ name,
|
|
86
|
-
/** @type {string[]} */ tags,
|
|
87
|
-
/** @type {MeterType} */ type,
|
|
88
|
-
) {
|
|
89
|
-
// TODO validate parameters are not null
|
|
90
|
-
this.#name = name;
|
|
91
|
-
this.#tags = Array.from(tags).sort();
|
|
92
|
-
this.#type = type;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
get name() {
|
|
96
|
-
return this.#name;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
get tags() {
|
|
100
|
-
return this.#tags;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
get type() {
|
|
104
|
-
return this.#type;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
equals(other) {
|
|
108
|
-
return (
|
|
109
|
-
this.name === other.name &&
|
|
110
|
-
this.tags.length === other.tags.length &&
|
|
111
|
-
this.tags.every((tag, index) => tag === other.tags[index])
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export class MeterType extends Enum {
|
|
117
|
-
static COUNTER = new MeterType('COUNTER', 0);
|
|
118
|
-
static GAUGE = new MeterType('GAUGE', 1);
|
|
119
|
-
static TIMER = new MeterType('TIMER', 2);
|
|
120
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @import * as express from 'express'
|
|
5
|
-
*
|
|
6
|
-
* @import { HealthContributorRegistry } from '../health.js'
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import process from 'node:process';
|
|
10
|
-
|
|
11
|
-
import * as handler from './handler.js';
|
|
12
|
-
|
|
13
|
-
// TODO Remove dependency to express
|
|
14
|
-
|
|
15
|
-
export class ActuatorController {
|
|
16
|
-
#services;
|
|
17
|
-
#healthContributorRegistry;
|
|
18
|
-
|
|
19
|
-
constructor(
|
|
20
|
-
services, // FIXME Services is not defined in library
|
|
21
|
-
/** @type {HealthContributorRegistry} */ healthContributorRegistry,
|
|
22
|
-
/** @type {express.Express} */ app,
|
|
23
|
-
) {
|
|
24
|
-
this.#services = services;
|
|
25
|
-
this.#healthContributorRegistry = healthContributorRegistry;
|
|
26
|
-
|
|
27
|
-
app.get('/actuator', this.#getActuator.bind(this));
|
|
28
|
-
app.get('/actuator/info', this.#getActuatorInfo.bind(this));
|
|
29
|
-
app.get('/actuator/metrics', this.#getActuatorMetrics.bind(this));
|
|
30
|
-
app.get('/actuator/health', this.#getActuatorHealth.bind(this));
|
|
31
|
-
app.get(
|
|
32
|
-
'/actuator/prometheus',
|
|
33
|
-
handler.runSafe(this.#getMetrics.bind(this)),
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
#getActuator(
|
|
38
|
-
/** @type {express.Request} */ request,
|
|
39
|
-
/** @type {express.Response} */ response,
|
|
40
|
-
) {
|
|
41
|
-
let requestedUrl =
|
|
42
|
-
request.protocol + '://' + request.get('host') + request.originalUrl;
|
|
43
|
-
if (!requestedUrl.endsWith('/')) {
|
|
44
|
-
requestedUrl += '/';
|
|
45
|
-
}
|
|
46
|
-
response.status(200).json({
|
|
47
|
-
_links: {
|
|
48
|
-
self: { href: requestedUrl },
|
|
49
|
-
info: { href: requestedUrl + 'info' },
|
|
50
|
-
metrics: { href: requestedUrl + 'metrics' },
|
|
51
|
-
health: { href: requestedUrl + 'health' },
|
|
52
|
-
prometheus: { href: requestedUrl + 'prometheus' },
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
#getActuatorInfo(
|
|
58
|
-
/** @type {express.Request} */ _request,
|
|
59
|
-
/** @type {express.Response} */ response,
|
|
60
|
-
) {
|
|
61
|
-
const info = {};
|
|
62
|
-
info[process.env.npm_package_name] = {
|
|
63
|
-
version: process.env.npm_package_version,
|
|
64
|
-
};
|
|
65
|
-
response.status(200).json(info);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
#getActuatorMetrics(
|
|
69
|
-
/** @type {express.Request} */ _request,
|
|
70
|
-
/** @type {express.Response} */ response,
|
|
71
|
-
) {
|
|
72
|
-
response.status(200).json({
|
|
73
|
-
cpu: process.cpuUsage(),
|
|
74
|
-
mem: process.memoryUsage(),
|
|
75
|
-
uptime: process.uptime(),
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
#getActuatorHealth(
|
|
80
|
-
/** @type {express.Request} */ _request,
|
|
81
|
-
/** @type {express.Response} */ response,
|
|
82
|
-
) {
|
|
83
|
-
const health = this.#healthContributorRegistry.health();
|
|
84
|
-
const status = health.status === 'UP' ? 200 : 503;
|
|
85
|
-
response.status(status).json(health);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async #getMetrics(
|
|
89
|
-
/** @type {express.Request} */ _request,
|
|
90
|
-
/** @type {express.Response} */ response,
|
|
91
|
-
) {
|
|
92
|
-
// TODO count warnings and errors
|
|
93
|
-
// TODO create class MeterRegistry
|
|
94
|
-
|
|
95
|
-
const metrics = await this.#services.getMetrics();
|
|
96
|
-
const timestamp = new Date().getTime();
|
|
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`;
|
|
100
|
-
handler.reply(response, { body });
|
|
101
|
-
}
|
|
102
|
-
}
|