@nsshunt/stsappframework 3.0.95 → 3.0.96

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.
Files changed (42) hide show
  1. package/package.json +1 -1
  2. package/src_working/authDefs.ts +37 -0
  3. package/src_working/authutilsnode.ts +373 -0
  4. package/src_working/commonTypes.ts +239 -0
  5. package/src_working/index.ts +22 -0
  6. package/src_working/influxdb/influxDBManager.ts +970 -0
  7. package/src_working/influxdb/influxDBManagerAgent.ts +314 -0
  8. package/src_working/influxdb/influxDBManagerBase.ts +109 -0
  9. package/src_working/influxdb/influxDBManagerService.ts +373 -0
  10. package/src_working/instrumentationsubscriber.ts +283 -0
  11. package/src_working/kafka/IMKafkaManager.ts +152 -0
  12. package/src_working/kafka/kafkaconsumer.ts +82 -0
  13. package/src_working/kafka/kafkamanager.ts +186 -0
  14. package/src_working/kafka/kafkaproducer.ts +58 -0
  15. package/src_working/kafkatesting/config.ts +10 -0
  16. package/src_working/kafkatesting/consume.ts +116 -0
  17. package/src_working/kafkatesting/produce.ts +153 -0
  18. package/src_working/masterprocessbase.ts +598 -0
  19. package/src_working/middleware/serverNetworkMiddleware.ts +240 -0
  20. package/src_working/network.ts +36 -0
  21. package/src_working/processbase.ts +411 -0
  22. package/src_working/processoptions.ts +164 -0
  23. package/src_working/publishertransports/publishTransportDirect.ts +45 -0
  24. package/src_working/publishertransports/publishTransportUtils.ts +53 -0
  25. package/src_working/server.ts +141 -0
  26. package/src_working/serverprocessbase.ts +393 -0
  27. package/src_working/singleprocessbase.ts +121 -0
  28. package/src_working/socketIoServerHelper.ts +177 -0
  29. package/src_working/stscontrollerbase.ts +15 -0
  30. package/src_working/stslatencycontroller.ts +27 -0
  31. package/src_working/stslatencyroute.ts +16 -0
  32. package/src_working/stsrouterbase.ts +22 -0
  33. package/src_working/tcpclient/app.ts +19 -0
  34. package/src_working/tcpclient/app2.ts +56 -0
  35. package/src_working/tcpserver/app.ts +11 -0
  36. package/src_working/tcpserver/appConfig.ts +65 -0
  37. package/src_working/tcpserver/appmaster.ts +544 -0
  38. package/src_working/validation/errors.ts +6 -0
  39. package/src_working/webworkertesting/app.ts +49 -0
  40. package/src_working/webworkertesting/worker.ts +24 -0
  41. package/src_working/workerprocessbase.test.ts +47 -0
  42. package/src_working/workerprocessbase.ts +185 -0
@@ -0,0 +1,970 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
2
+ import { InfluxDB, WriteApi, QueryApi, DEFAULT_WriteOptions, WriteOptions } from '@influxdata/influxdb-client'
3
+ // Use below for production https mode - needs to be config item
4
+ //import { Agent } from 'https'
5
+ import { Agent } from 'http'
6
+
7
+ import { $Options } from '@nsshunt/stsconfig'
8
+ import { JSONObject } from '@nsshunt/stsutils'
9
+ const goptions = $Options()
10
+
11
+ import { InfluxDBManagerBase } from './influxDBManagerBase'
12
+ import { InfluxDBManagerService} from './influxDBManagerService'
13
+ import { InfluxDBManagerAgent } from './influxDBManagerAgent'
14
+ import { IInfluxDBManagerOptions, InstrumentPayload } from './../commonTypes'
15
+
16
+ import { TasksAPI, Tasks, Task } from '@influxdata/influxdb-client-apis'
17
+
18
+ import debugModule from 'debug'
19
+ const debug = debugModule(`proc:${process.pid}`);
20
+
21
+ /*
22
+ Manual docker run command and setup -------------------------------------------------------
23
+
24
+ docker run -d -p 8086:8086 --name influxdb \
25
+ -v $PWD/data:/var/lib/influxdb2 \
26
+ -v $PWD/config:/etc/influxdb2 \
27
+ -e DOCKER_INFLUXDB_INIT_MODE=setup \
28
+ -e DOCKER_INFLUXDB_INIT_USERNAME=my-user \
29
+ -e DOCKER_INFLUXDB_INIT_PASSWORD=my-password \
30
+ -e DOCKER_INFLUXDB_INIT_ORG=my-org \
31
+ -e DOCKER_INFLUXDB_INIT_BUCKET=my-bucket \
32
+ -e DOCKER_INFLUXDB_INIT_RETENTION=1w \
33
+ -e DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=my-super-secret-auth-token \
34
+ --restart unless-stopped \
35
+ influxdb:latest
36
+
37
+ Then access admin portal via;
38
+ https://192.168.14.92:8086
39
+
40
+ Login using credentials above
41
+ username: my-user
42
+ password: my-password
43
+
44
+ Select Buckets from the menu
45
+ Create buckets as required
46
+ Example: TestBucket01
47
+ Note: We will not use the default bucket as specified in the docker initial setup (my-bucket)
48
+
49
+ Select API Tokens from the menu
50
+ Generate an API token / custom API token for read/write access to the bucket about
51
+ Bucket: TestBucket01 (from above bucket create)
52
+
53
+ Copy the API token and use in the ENV file for access
54
+ INFLUXDB_API_TOKEN=<< generated from InfluxDB web admin tool >> \
55
+ INFLUXDB_URL=http://192.168.14.92:8086 \
56
+ INFLUXDB_ORG=my-org \
57
+ INFLUXDB_BUCKET=TestBucket01 \
58
+
59
+ Docker compose file --------------------------------------------------------------
60
+
61
+ version: '2'
62
+ services:
63
+ influxdb:
64
+ image: influxdb:latest
65
+ ports:
66
+ - "8086:8086"
67
+ environment:
68
+ DOCKER_INFLUXDB_INIT_MODE: setup
69
+ DOCKER_INFLUXDB_INIT_USERNAME: my-user
70
+ DOCKER_INFLUXDB_INIT_PASSWORD: my-password
71
+ DOCKER_INFLUXDB_INIT_ORG: my-org
72
+ DOCKER_INFLUXDB_INIT_BUCKET: my-bucket
73
+ DOCKER_INFLUXDB_INIT_RETENTION: 1w
74
+ DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: my-super-secret-auth-token
75
+ volumes:
76
+ - /var/run/influxdb/data:/var/lib/influxdb2
77
+ - /var/run/influxdb/config:/etc/influxdb2
78
+ restart: unless-stopped
79
+
80
+
81
+ // Exam Queries Below ----------------------------------------------------------------------
82
+
83
+ from(bucket: "TestBucket01")
84
+ |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
85
+ |> filter(fn: (r) => r["_measurement"] == "stsServicePointV3")
86
+ |> group(columns: ["serviceId"], mode: "by")
87
+ |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
88
+ |> yield(name: "mean")
89
+
90
+ from(bucket: "TestBucket01")
91
+ |> range(start: -10m)
92
+ |> filter(fn: (r) => r["_measurement"] == "requestCount")
93
+ |> group(columns: ["serviceInstanceId"])
94
+ |> mean()
95
+
96
+ from(bucket: "TestBucket01")
97
+ |> range(start: -10m)
98
+ |> filter(fn: (r) => r["_measurement"] == "cpu")
99
+ |> group(columns: ["serviceInstanceId"])
100
+ |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)
101
+
102
+ from(bucket: "TestBucket01")
103
+ |> range(start: -2m)
104
+ |> filter(fn: (r) => r["_measurement"] == "cpu")
105
+ |> group(columns: ["serviceInstanceId"])
106
+ |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)
107
+
108
+ from(bucket: "TestBucket01")
109
+ |> range(start: -10s)
110
+ |> filter(fn: (r) => r["_measurement"] == "all")
111
+ |> filter(fn: (r) => r["_field"] == "requestCount")
112
+ |> group(columns: ["serviceInstanceId"])
113
+ |> max()
114
+
115
+ from(bucket: "TestBucket01")
116
+ |> range(start: -10s)
117
+ |> filter(fn: (r) => r["_measurement"] == "all")
118
+ |> filter(fn: (r) => r["_field"] == "requestCount" or r["_field"] == "errorCount")
119
+ |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
120
+ |> group(columns: ["serviceInstanceId"])
121
+ |> max()
122
+
123
+ from(bucket: "TestBucket01")
124
+ |> range(start: -5s)
125
+ |> filter(fn: (r) => r["_measurement"] == "all") |> filter(fn: (r) => r["_field"] == "cpu")
126
+ |> last()
127
+ |> group(columns: ["serviceInstanceId", "serviceId", "_field"])
128
+ |> sum()
129
+ |> group(columns: ["_field"])
130
+ |> sum()
131
+
132
+ // Histo ---------------------------------------
133
+
134
+ import "math"
135
+ from(bucket: "TestBucket01")
136
+ |> range(start: -10m)
137
+ |> filter(fn: (r) => r["_measurement"] == "all") |> filter(fn: (r) => r["_field"] == "latency")
138
+ |> group(columns: ["serviceInstanceIsssd", "serviceId", "_field"])
139
+ |> aggregateWindow(every: 1s, fn: mean, createEmpty: false)
140
+ |> histogram(bins: [0.0, 5.0, 10.0, 20.0, 50.0, math.mInf(sign: 1) ])
141
+ |> difference()
142
+
143
+ // Velocity ------------------------------------------------------------------------
144
+
145
+ dostsvelocityex = (r, ds, d) =>
146
+ from(bucket: "TestBucket01")
147
+ |> range(start: r)
148
+ |> filter(fn: (r) => r["_measurement"] == "all")
149
+ |> filter(fn: (r) => r["_field"] == "requestCount")
150
+ |> group(columns: ["serviceInstanceIsssd", "serviceId", "_field", "serviceInstanceProcessId"])
151
+ |> aggregateWindow(every: ds, fn: last, createEmpty: false)
152
+ |> limit(n: 5)
153
+ |> difference()
154
+ |> last()
155
+ |> group(columns: ["serviceInstanceIsssd", "serviceId", "_field"])
156
+ |> sum()
157
+ |> map(fn: (r) => ({r with _value: float(v: r._value) / d}))
158
+
159
+ dostsvelocity = () =>
160
+ dostsvelocityex(r: -30s, ds: 5s, d: 5.0)
161
+
162
+ dostsvelocity()
163
+
164
+ // Velocity - for a specific service instance ----------------------------------
165
+
166
+ dostsvelocitybyserviceinstanceex = (sid, r, ds, d) =>
167
+ from(bucket: "TestBucket01")
168
+ |> range(start: r)
169
+ |> filter(fn: (r) => r["_measurement"] == "all")
170
+ |> filter(fn: (r) => r["_field"] == "requestCount")
171
+ |> filter(fn: (r) => r["serviceId"] == sid)
172
+ |> group(columns: ["serviceInstanceId", "serviceId", "_field", "serviceInstanceProcessId"])
173
+ |> aggregateWindow(every: ds, fn: last, createEmpty: false)
174
+ |> limit(n: 5)
175
+ |> difference()
176
+ |> last()
177
+ |> sum()
178
+ |> map(fn: (r) => ({r with _value: float(v: r._value) / d}))
179
+
180
+ dostsvelocitybyserviceinstance = (sid) =>
181
+ dostsvelocitybyserviceinstanceex(sid: sid, r: -30s, ds: 5s, d: 5.0)
182
+
183
+ dostsvelocitybyserviceinstance(sid: "STSAuth@1.0.0")
184
+
185
+ // Percentile --------------------------------------------------------------
186
+
187
+ from(bucket: "TestBucket01")
188
+ |> range(start: -10m)
189
+ |> filter(fn: (r) => r["_measurement"] == "all") |> filter(fn: (r) => r["_field"] == "latency")
190
+ |> group(columns: ["serviceInstanceIsssd", "serviceId", "_field"])
191
+ |> aggregateWindow(every: 10s, fn: mean, createEmpty: false)
192
+ |> quantile(q: 0.99, method: "exact_mean")
193
+ */
194
+
195
+ // export INFLUXDB_TOKEN=W6GztqLmWEqqpP9hAOW9nucgVfESk32dC0JYzFCaYD2yJtS8Ox_WK_1hwSkPUaheWjwwcavkE7_J2aRzm3-E7w==
196
+
197
+
198
+ const _logPrefix = 'InfluxDBManager:'
199
+
200
+ export class InfluxDBManager
201
+ {
202
+ #shuttingDown: boolean = false;
203
+
204
+ //#token = process.env.INFLUXDB_TOKEN;
205
+ #token = '';
206
+ #url = '' // 'http://192.168.14.92:8086'
207
+ #org = '' // `my-org`
208
+ #bucket = '' // `TestBucket01`
209
+ #client: InfluxDB;
210
+ #writeClient: WriteApi | null = null;
211
+ #queryApi: QueryApi;
212
+ #writeDataPointFlushTimeout: NodeJS.Timeout | null = null;
213
+ #agent: Agent | null = null;
214
+ #influxDBManagerClients: Record<string, InfluxDBManagerBase> = { };
215
+ #options: IInfluxDBManagerOptions;
216
+
217
+ constructor()
218
+ {
219
+ this.#options = {
220
+ token: goptions.influxDB_APIToken,
221
+ url: goptions.influxDB_Url,
222
+ org: goptions.influxDB_Org,
223
+ bucket:goptions.influxDB_Bucket,
224
+ agent: {
225
+ influxDB_keepAlive: goptions.influxDB_keepAlive,
226
+ influxDB_maxSockets: goptions.influxDB_maxSockets,
227
+ influxDB_maxTotalSockets: goptions.influxDB_maxTotalSockets,
228
+ influxDB_maxFreeSockets: goptions.influxDB_maxFreeSockets,
229
+ influxDB_timeout: goptions.influxDB_timeout,
230
+ }
231
+ };
232
+
233
+ this.#token = this.#options.token;
234
+ this.#url = this.#options.url;
235
+ this.#org = this.#options.org;
236
+ this.#bucket = this.#options.bucket;
237
+
238
+ if (this.#options.agent) {
239
+ this.#agent = new Agent({
240
+ keepAlive: this.#options.agent.influxDB_keepAlive,
241
+ keepAliveMsecs: 20000, //@@
242
+ maxSockets: this.#options.agent.influxDB_maxSockets,
243
+ maxTotalSockets: this.#options.agent.influxDB_maxTotalSockets,
244
+ maxFreeSockets: this.#options.agent.influxDB_maxFreeSockets,
245
+ timeout: this.#options.agent.influxDB_timeout,
246
+ //rejectUnauthorized: this.#options.agent.influxDB_rejectUnauthorized, // only for SSL
247
+ })
248
+
249
+ this.#client = new InfluxDB({
250
+ url: this.#url,
251
+ token: this.#token,
252
+ transportOptions: { agent: this.#agent }
253
+ })
254
+ } else {
255
+ this.#agent = null;
256
+
257
+ this.#client = new InfluxDB({
258
+ url: this.#url,
259
+ token: this.#token
260
+ })
261
+ }
262
+
263
+ this.#BoostrapInfluxDB();
264
+
265
+ this.#queryApi = this.#client.getQueryApi(this.#org);
266
+
267
+ this.CreateInfluxDBManagerClient('service');
268
+ this.CreateInfluxDBManagerClient('agent');
269
+ }
270
+
271
+ #BoostrapInfluxDB = async(): Promise<void> => {
272
+ const tasksAPI = new TasksAPI(this.#client);
273
+ const tasks: Tasks = await tasksAPI.getTasks({
274
+ org: 'my-org'
275
+ });
276
+ if (tasks.tasks) {
277
+ console.log(`[InfluxDB Tasks] - Count: [${tasks.tasks.length}]`.cyan);
278
+ tasks.tasks.forEach((task: Task) => {
279
+ console.log(`-- [ Start Task Definition ]--`.cyan);
280
+ console.log(`${JSON.stringify(task)}`.green);
281
+ console.log(`authorizationID: [${task.authorizationID}]`.yellow);
282
+ console.log(`-- [ End Task Definition ]--`.cyan);
283
+ });
284
+ } else {
285
+ console.log(`[InfluxDB Tasks] - Could not get tasks from the InfluxDB API`.magenta);
286
+ }
287
+ }
288
+
289
+ CreateInfluxDBManagerClient(modelType: string) {
290
+ switch (modelType) {
291
+ case 'service':
292
+ this.#influxDBManagerClients[modelType] = new InfluxDBManagerService(this.#options, this.#queryApi);
293
+ break;
294
+ case 'agent':
295
+ this.#influxDBManagerClients[modelType] = new InfluxDBManagerAgent(this.#options, this.#queryApi);
296
+ break;
297
+ default:
298
+ throw new Error(`Model type: [${modelType} not supported.]`);
299
+ }
300
+ }
301
+
302
+ get serviceManager(): InfluxDBManagerService {
303
+ return this.#influxDBManagerClients['service'] as InfluxDBManagerService;
304
+ }
305
+
306
+ get agentManager(): InfluxDBManagerAgent {
307
+ return this.#influxDBManagerClients['agent'] as InfluxDBManagerAgent;
308
+ }
309
+
310
+ Start = async () => {
311
+ // perform any setup here
312
+ }
313
+
314
+ Terminate = async () => {
315
+ if (this.#shuttingDown) {
316
+ console.log(`${_logPrefix}Terminate: Terminate already called. Ignoring.`.yellow);
317
+ } else {
318
+ this.#shuttingDown = true;
319
+ if (this.#writeClient) {
320
+ try {
321
+ this.#writeClient.flush();
322
+ this.#shuttingDown = true;
323
+ if (this.#writeDataPointFlushTimeout) {
324
+ clearTimeout(this.#writeDataPointFlushTimeout);
325
+ this.#writeDataPointFlushTimeout = null;
326
+ }
327
+
328
+ if (this.#agent) {
329
+ this.#agent?.destroy();
330
+ this.#agent = null;
331
+ }
332
+
333
+ this.#writeClient = null;
334
+
335
+ console.log(`ProducerDisconnect`.yellow);
336
+ } catch (error) {
337
+ console.error(`${_logPrefix}#Terminate: Error: [${error}]`.red);
338
+ }
339
+ }
340
+ }
341
+ }
342
+
343
+ /*
344
+ .floatField('timer', instrumentPayload.instruments[Gauge.TIMER_GAUGE].val)
345
+ .floatField('duration', instrumentPayload.instruments[Gauge.DURATION_GAUGE].val)
346
+ .floatField('latency', instrumentPayload.instruments[Gauge.LATENCY_GAUGE].val)
347
+ */
348
+
349
+ CreateGlobalCountModel = (stscount: any[]) => {
350
+ try {
351
+ const results: any = { };
352
+ stscount.forEach((o: any) => {
353
+ results[o._field] = o._value;
354
+ });
355
+ return results;
356
+ } catch (error) {
357
+ console.error(`${_logPrefix}#CreateGlobalCountModel: Error: [${error}]`.red);
358
+ }
359
+ }
360
+
361
+
362
+ CreateNestedObject(combinedResults: JSONObject, keyList: string[]): JSONObject {
363
+ let workingObject = combinedResults;
364
+ keyList.forEach((key) => {
365
+ if (!workingObject[key]) {
366
+ workingObject[key] = { };
367
+ workingObject = workingObject[key];
368
+ }
369
+ });
370
+ return combinedResults;
371
+ }
372
+
373
+ get writeClient(): WriteApi {
374
+ if (!this.#writeClient) {
375
+ /* Defaults from the library as at 12/11/2023
376
+ // default RetryDelayStrategyOptions
377
+ export const DEFAULT_RetryDelayStrategyOptions = {
378
+ retryJitter: 200,
379
+ minRetryDelay: 5000,
380
+ maxRetryDelay: 125000,
381
+ exponentialBase: 5,
382
+ randomRetry: true,
383
+ }
384
+
385
+ // default writeOptions
386
+ export const DEFAULT_WriteOptions: WriteOptions = {
387
+ batchSize: 1000,
388
+ maxBatchBytes: 50_000_000, // default max batch size in the cloud
389
+ flushInterval: 60000,
390
+ writeFailed: function () {},
391
+ writeSuccess: function () {},
392
+ writeRetrySkipped: function () {},
393
+ maxRetries: 5,
394
+ maxRetryTime: 180_000,
395
+ maxBufferLines: 32_000,
396
+ // a copy of DEFAULT_RetryDelayStrategyOptions, so that DEFAULT_WriteOptions could be tree-shaken
397
+ retryJitter: 200,
398
+ minRetryDelay: 5000,
399
+ maxRetryDelay: 125000,
400
+ exponentialBase: 2,
401
+ gzipThreshold: 1000,
402
+ randomRetry: true,
403
+ }
404
+ */
405
+
406
+ const flushBatchSize = DEFAULT_WriteOptions.batchSize;
407
+
408
+ const writeOptions: Partial<WriteOptions> = {
409
+ /* the maximum points/lines to send in a single batch to InfluxDB server */
410
+ batchSize: flushBatchSize + 1, // don't let automatically flush data
411
+ /* default tags to add to every point */
412
+ //defaultTags: {location: hostname},
413
+ /* maximum time in millis to keep points in an unflushed batch, 0 means don't periodically flush */
414
+ flushInterval: 0,
415
+ // max size of a batch in bytes
416
+ maxBatchBytes: 50_000_000, // default max batch size in the cloud
417
+
418
+ // Retry Options
419
+
420
+ /* maximum size of the retry buffer - it contains items that could not be sent for the first time */
421
+ maxBufferLines: 30000,
422
+ /* the count of internally-scheduled retries upon write failure, the delays between write attempts follow an exponential backoff strategy if there is no Retry-After HTTP header */
423
+ maxRetries: 5, // do not retry writes
424
+ // max time (millis) that can be spent with retries
425
+ maxRetryTime: 180_000,
426
+
427
+ // ... there are more write options that can be customized, see
428
+ // https://influxdata.github.io/influxdb-client-js/influxdb-client.writeoptions.html and
429
+ // https://influxdata.github.io/influxdb-client-js/influxdb-client.writeretryoptions.html
430
+ writeFailed(error, lines, attempt, expires) {
431
+ debug(`writeOptions:writeSuccess(): Error: [${error}], Attempt: [${attempt}], Expires: [${expires}], Lines: [${lines}]`.red);
432
+ },
433
+ writeSuccess(lines) {
434
+ debug(`writeOptions:writeSuccess(): Lines: [${lines}]`.green);
435
+ },
436
+ writeRetrySkipped(entry) {
437
+ debug(`writeOptions:writeSuccess(): Expires: [${entry.expires}], Lines: [${entry.lines}]`.magenta);
438
+ }
439
+ }
440
+
441
+ this.#writeClient = this.#client.getWriteApi(this.#org, this.#bucket, 'ns', writeOptions);
442
+
443
+ let attemptCount = 0;
444
+ const maxAttemptCount = 5;
445
+ const normalFlushDelay = 1000;
446
+ const retryFlushDelay = 2500;
447
+
448
+ const StartWriteClient = (delay: number) => {
449
+ this.#writeDataPointFlushTimeout = setTimeout(async () => {
450
+ if (this.#writeClient) {
451
+ try {
452
+ attemptCount++;
453
+ const start = performance.now();
454
+ await this.#writeClient.flush();
455
+ const end = performance.now();
456
+ debug(`InfluxDB Flush time: [${end-start}]`.grey)
457
+ attemptCount = 0;
458
+ StartWriteClient(normalFlushDelay);
459
+ } catch (error) {
460
+ console.error(`InfluxDBManager:StartWriteClient(): Attempt: [${attemptCount}], Error: [${error}]`.red)
461
+ if (attemptCount === maxAttemptCount) {
462
+ console.error(`InfluxDBManager:StartWriteClient(): Max Attempts reached. Will no longer retry.`.red);
463
+ console.error(`InfluxDBManager:StartWriteClient(): InfluxDB data capture ended in permanent faiilure.`.red);
464
+ } else {
465
+ StartWriteClient(retryFlushDelay);
466
+ }
467
+ }
468
+ }
469
+ }, delay).unref();
470
+ }
471
+
472
+ StartWriteClient(normalFlushDelay);
473
+ }
474
+ return this.#writeClient;
475
+ }
476
+
477
+ // Agent context payload
478
+ // {"nid":"somehost@e58f5d75-6ff6-4e04-92a4-f2bcd722fec0-someuseragent|MainProcess|0","id":"somehost@e58f5d75-6ff6-4e04-92a4-f2bcd722fec0-someuseragent|MainProcess|0","hostName":"somehost","agentName":"e58f5d75-6ff6-4e04-92a4-f2bcd722fec0-someuseragent","threadId":"MainProcess","asyncRunnerId":"0"}
479
+ async OutputInfluxDB(instrumentPayload: InstrumentPayload): Promise<boolean> {
480
+ try {
481
+ if (this.#shuttingDown) {
482
+ return false;
483
+ }
484
+ if (instrumentPayload.context.agentName) {
485
+ return this.#influxDBManagerClients['agent'].OutputInfluxDB(this.writeClient, instrumentPayload);
486
+ } else {
487
+ return this.#influxDBManagerClients['service'].OutputInfluxDB(this.writeClient, instrumentPayload);
488
+ }
489
+ } catch (error) {
490
+ console.error(`${_logPrefix}OutputInfluxDB: Could not write data point: [${error}]`.red);
491
+ return false;
492
+ }
493
+ }
494
+ }
495
+
496
+
497
+
498
+ /*
499
+ |> histogram(bins: [0.0, 10.0, 20.0, 50.0, 100.0, 1000.0, 50000.0, math.mInf(sign: 1) ])
500
+
501
+
502
+ |> histogramQuantile(quantile: 0.99999)
503
+
504
+
505
+
506
+ option task = {name: "downsample-daily", every: 1d}
507
+
508
+
509
+ option task = {name: "downsample-daily", every: 1d}
510
+
511
+ from(bucket: "my-db/")
512
+ |> range(start: -task.every)
513
+ |> filter(fn: (r) => r._measurement == "example-measurement")
514
+ |> filter(fn: (r) => r._field == "example-field")
515
+ |> aggregateWindow(every: 1h, fn: mean)
516
+ |> set(key: "_measurement", value: "average-example-measurement")
517
+ |> to(org: "example-org", bucket: "my-db/example-rp")
518
+
519
+
520
+
521
+
522
+ |> set(key: "_measurement", value: "sts01")
523
+ |> to(org: "my-org", bucket: "TestBucket01")
524
+
525
+
526
+
527
+
528
+
529
+
530
+
531
+
532
+
533
+
534
+ from(bucket: "TestBucket01")
535
+ |> range(start: -5s)
536
+ |> last()
537
+ |> filter(fn: (r) => r["_measurement"] == "service")
538
+ |> filter(fn: (r) => r["_field"] != "memory")
539
+ |> group(columns: ["_field"])
540
+ |> sum()
541
+ |> map(
542
+ fn: (r) => ({r with _time: now(), _measurement: "sts01"}),
543
+ )
544
+ |> to(org: "my-org", bucket: "TestBucket01")
545
+
546
+
547
+
548
+
549
+ group(columns: ["serviceId", "serviceInstanceId", "_field"])
550
+
551
+ option task = {name: "task-sts-stats-sum-byserviceInstanceprocessid", every: 1s}
552
+ from(bucket: "TestBucket01")
553
+ |> range(start: -5s)
554
+ |> last()
555
+ |> filter(fn: (r) => r["_measurement"] == "service" and r["_field"] != "memory")
556
+ |> group(columns: ["serviceId", "serviceInstanceId", "serviceInstanceProcessId", "_field"])
557
+ |> sum()
558
+ |> toFloat()
559
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum-byserviceInstanceprocessid"}))
560
+ |> to(org: "my-org", bucket: "TestBucket01")
561
+
562
+ option task = {name: "task-sts-stats-sum-byserviceinstance", every: 1s}
563
+ from(bucket: "TestBucket01")
564
+ |> range(start: -5s)
565
+ |> last()
566
+ |> filter(fn: (r) => r["_measurement"] == "service" and r["_field"] != "memory")
567
+ |> group(columns: ["serviceId", "serviceInstanceId", "_field"])
568
+ |> sum()
569
+ |> toFloat()
570
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum-byserviceinstance"}))
571
+ |> to(org: "my-org", bucket: "TestBucket01")
572
+
573
+ option task = {name: "task-sts-stats-sum-byservice", every: 1s}
574
+ from(bucket: "TestBucket01")
575
+ |> range(start: -5s)
576
+ |> last()
577
+ |> filter(fn: (r) => r["_measurement"] == "service" and r["_field"] != "memory")
578
+ |> group(columns: ["serviceId", "_field"])
579
+ |> sum()
580
+ |> toFloat()
581
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum-byservice"}))
582
+ |> to(org: "my-org", bucket: "TestBucket01")
583
+
584
+ option task = {name: "task-sts-stats-sum", every: 1s}
585
+ from(bucket: "TestBucket01")
586
+ |> range(start: -5s)
587
+ |> last()
588
+ |> filter(fn: (r) => r["_measurement"] == "service" and r["_field"] != "memory")
589
+ |> group(columns: ["_field"])
590
+ |> sum()
591
+ |> toFloat()
592
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum"}))
593
+ |> to(org: "my-org", bucket: "TestBucket01")
594
+
595
+
596
+
597
+
598
+
599
+ option task = {name: "task-sts-stats-sum-byagentthreadasyncrunner-agent", every: 1s}
600
+ from(bucket: "TestBucket01")
601
+ |> range(start: -5s)
602
+ |> last()
603
+ |> filter(fn: (r) => r["_measurement"] == "agent")
604
+ |> group(columns: ["agentName", "threadId", "asyncRunnerId", "_field"])
605
+ |> sum()
606
+ |> toFloat()
607
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum-byagentthreadasyncunner-agent"}))
608
+ |> to(org: "my-org", bucket: "TestBucket01")
609
+
610
+ option task = {name: "task-sts-stats-sum-byagentthread-agent", every: 1s}
611
+ from(bucket: "TestBucket01")
612
+ |> range(start: -5s)
613
+ |> last()
614
+ |> filter(fn: (r) => r["_measurement"] == "agent")
615
+ |> group(columns: ["agentName", "threadId", "_field"])
616
+ |> sum()
617
+ |> toFloat()
618
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum-byagentthread-agent"}))
619
+ |> to(org: "my-org", bucket: "TestBucket01")
620
+
621
+ option task = {name: "task-sts-stats-sum-byagent-agent", every: 1s}
622
+ from(bucket: "TestBucket01")
623
+ |> range(start: -5s)
624
+ |> last()
625
+ |> filter(fn: (r) => r["_measurement"] == "agent")
626
+ |> group(columns: ["agentName", "_field"])
627
+ |> sum()
628
+ |> toFloat()
629
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum-byagent-agent"}))
630
+ |> to(org: "my-org", bucket: "TestBucket01")
631
+
632
+ option task = {name: "task-sts-stats-sum-agent", every: 1s}
633
+ from(bucket: "TestBucket01")
634
+ |> range(start: -5s)
635
+ |> last()
636
+ |> filter(fn: (r) => r["_measurement"] == "agent")
637
+ |> group(columns: ["_field"])
638
+ |> sum()
639
+ |> toFloat()
640
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-sum-agent"}))
641
+ |> to(org: "my-org", bucket: "TestBucket01")
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+
650
+ import "math"
651
+ from(bucket: "TestBucket01")
652
+ |> range(start: -10m)
653
+ |> filter(fn: (r) => r["_measurement"] == "sts-stats-sum-byservice" and r["serviceId"] == "STSBroker@1.0.0" and r["_field"] == "cpu")
654
+ |> histogram(bins: [0.0, 10.0, 20.0, 50.0, 100.0, 200.0, 250.0, 1000.0, 50000.0, math.mInf(sign: 1) ])
655
+ |> difference()
656
+
657
+
658
+
659
+ import "math"
660
+ from(bucket: "TestBucket01")
661
+ |> range(start: -10m)
662
+ |> filter(fn: (r) => r["_measurement"] == "sts-stats-sum" and r["_field"] == "cpu")
663
+ |> histogram(bins: [0.0, 10.0, 20.0, 50.0, 100.0, 200.0, 250.0, 1000.0, 50000.0, math.mInf(sign: 1) ])
664
+ |> difference()
665
+
666
+
667
+
668
+
669
+ // More accurate
670
+
671
+ data = from(bucket: "TestBucket01")
672
+ |> range(start: -10m)
673
+ |> filter(fn: (r) => r["_measurement"] == "sts-stats-sum-byservice" and r["serviceId"] == "STSBroker@1.0.0" and r["_field"] == "cpu")
674
+ |> aggregateWindow(every: 5s, fn: max, createEmpty: false)
675
+
676
+ dostsquantileex = (q) =>
677
+ data
678
+ |> quantile(q: q, method: "estimate_tdigest", compression: 1000.0)
679
+ |> set(key: "quantile", value: string(v:q))
680
+ |> group(columns: ["quantile"])
681
+
682
+ union(tables: [
683
+ dostsquantileex(q: 0.5),
684
+ dostsquantileex(q: 0.8),
685
+ dostsquantileex(q: 0.9),
686
+ dostsquantileex(q: 0.95),
687
+ dostsquantileex(q: 0.99)
688
+ ])
689
+
690
+
691
+
692
+
693
+ // Less accurate
694
+
695
+ import "math"
696
+ data = from(bucket: "TestBucket01")
697
+ |> range(start: -10m)
698
+ |> filter(fn: (r) => r["_measurement"] == "sts-stats-sum-byservice" and r["serviceId"] == "STSBroker@1.0.0" and r["_field"] == "cpu")
699
+ |> histogram(bins: [0.0, 10.0, 20.0, 50.0, 100.0, 200.0, 250.0, 1000.0, 50000.0, math.mInf(sign: 1) ])
700
+
701
+
702
+ dostsquantileex = (q) =>
703
+ data
704
+ |> histogramQuantile(quantile: q)
705
+ |> set(key: "quantile", value: string(v:q))
706
+ |> group(columns: ["quantile"])
707
+
708
+ union(tables: [
709
+ dostsquantileex(q: 0.5),
710
+ dostsquantileex(q: 0.8),
711
+ dostsquantileex(q: 0.9),
712
+ dostsquantileex(q: 0.95),
713
+ dostsquantileex(q: 0.99)
714
+ ])
715
+
716
+
717
+
718
+
719
+
720
+
721
+ activeRequestCount 0 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
722
+ 1 sts-stats-sum authenticationCount 0 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
723
+ 2 sts-stats-sum connectionCount 40 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
724
+ 3 sts-stats-sum connectionIdleCount 12 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
725
+ 4 sts-stats-sum connectionPoolCount 12 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
726
+ 5 sts-stats-sum connectionWaitingCount 0 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
727
+ 6 sts-stats-sum coreCount
728
+
729
+
730
+ cpu 50.91 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
731
+ 8 sts-stats-sum duration 3.6900000000000004 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
732
+ 9 sts-stats-sum errorCount 0 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
733
+ 10 sts-stats-sum latency 22.82 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
734
+ 11 sts-stats-sum requestCount 4485612 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
735
+ 12 sts-stats-sum retryCount 0 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
736
+ 13 sts-stats-sum systemcpu
737
+
738
+ timer 72578365.22 2023-11-11T06:23:52.761Z 2023-11-11T06:33:52.761Z 2023-11-11T06:33:52.000Z
739
+ 15 sts-stats-sum velocity
740
+
741
+
742
+
743
+
744
+
745
+
746
+
747
+
748
+
749
+
750
+
751
+
752
+
753
+ option task = {
754
+ name: "sts-service-stats",
755
+ every: 1s,
756
+ }
757
+
758
+ data = from(bucket: "TestBucket01")
759
+ |> range(start: -5s)
760
+ |> last()
761
+ |> filter(fn: (r) => r["_measurement"] == "service" and r["_field"] != "memory")
762
+
763
+ r1 = data
764
+ |> filter(fn: (r) => r["_field"] == "requestCount"
765
+ or r["_field"] == "errorCount"
766
+ or r["_field"] == "retryCount"
767
+ or r["_field"] == "authenticationCount"
768
+ or r["_field"] == "activeRequestCount"
769
+ or r["_field"] == "connectionCount"
770
+ or r["_field"] == "connectionPoolCount"
771
+ or r["_field"] == "connectionIdleCount"
772
+ or r["_field"] == "connectionWaitingCount"
773
+ or r["_field"] == "coreCount"
774
+ or r["_field"] == "cpu"
775
+ or r["_field"] == "systemcpu"
776
+ or r["_field"] == "velocity"
777
+ or r["_field"] == "timer")
778
+ |> group(columns: ["_field"])
779
+ |> sum()
780
+ |> toFloat()
781
+
782
+ r2 = data
783
+ |> filter(fn: (r) => float(v: r["_value"]) > 0.0 and (r["_field"] == "duration"
784
+ or r["_field"] == "latency"))
785
+
786
+ serviceInstanceProcessSum = r1
787
+ |> group(columns: ["serviceId", "serviceInstanceId", "serviceInstanceProcessId", "_field"])
788
+ |> sum()
789
+ |> toFloat()
790
+
791
+ serviceInstanceProcessMean = r2
792
+ |> group(columns: ["serviceId", "serviceInstanceId", "serviceInstanceProcessId", "_field"])
793
+ |> mean()
794
+ |> toFloat()
795
+
796
+ union(tables: [serviceInstanceProcessSum, serviceInstanceProcessMean])
797
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-serviceinstanceprocess"}))
798
+ |> to(org: "my-org", bucket: "TestBucket01")
799
+
800
+ serviceInstanceSum = r1
801
+ |> group(columns: ["serviceId", "serviceInstanceId", "_field"])
802
+ |> sum()
803
+ |> toFloat()
804
+
805
+ serviceInstanceMean = r2
806
+ |> group(columns: ["serviceId", "serviceInstanceId", "_field"])
807
+ |> mean()
808
+ |> toFloat()
809
+
810
+ union(tables: [serviceInstanceSum, serviceInstanceMean])
811
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-serviceinstance"}))
812
+ |> to(org: "my-org", bucket: "TestBucket01")
813
+
814
+ serviceSum = r1
815
+ |> group(columns: ["serviceId", "_field"])
816
+ |> sum()
817
+ |> toFloat()
818
+
819
+ serviceMean = r2
820
+ |> group(columns: ["serviceId", "_field"])
821
+ |> mean()
822
+ |> toFloat()
823
+
824
+ union(tables: [serviceSum, serviceMean])
825
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-service"}))
826
+ |> to(org: "my-org", bucket: "TestBucket01")
827
+
828
+ globalServiceSum = r1
829
+ |> group(columns: ["_field"])
830
+ |> sum()
831
+ |> toFloat()
832
+
833
+ globalServiceMean = r2
834
+ |> group(columns: ["_field"])
835
+ |> mean()
836
+ |> toFloat()
837
+
838
+ union(tables: [globalServiceSum, globalServiceMean])
839
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-globalservice"}))
840
+ |> to(org: "my-org", bucket: "TestBucket01")
841
+
842
+
843
+
844
+
845
+
846
+
847
+
848
+
849
+
850
+
851
+
852
+
853
+
854
+
855
+
856
+
857
+
858
+
859
+
860
+
861
+
862
+
863
+
864
+
865
+
866
+ option task = {name: "task-sts-service-stats", every: 1s}
867
+
868
+ data =
869
+ from(bucket: "TestBucket01")
870
+ |> range(start: -5s)
871
+ |> last()
872
+ |> filter(fn: (r) => r["_measurement"] == "service" and r["_field"] != "memory")
873
+
874
+ r1 =
875
+ data
876
+ |> filter(
877
+ fn: (r) =>
878
+ r["_field"] == "requestCount" or r["_field"] == "errorCount" or r["_field"]
879
+ ==
880
+ "retryCount" or r["_field"] == "authenticationCount" or r["_field"]
881
+ ==
882
+ "activeRequestCount" or r["_field"] == "connectionCount" or r["_field"]
883
+ ==
884
+ "connectionPoolCount" or r["_field"] == "connectionIdleCount" or r["_field"]
885
+ ==
886
+ "connectionWaitingCount" or r["_field"] == "coreCount" or r["_field"] == "cpu"
887
+ or
888
+ r["_field"] == "systemcpu" or r["_field"] == "velocity" or r["_field"]
889
+ ==
890
+ "timer",
891
+ )
892
+
893
+ r2 =
894
+ data
895
+ |> filter(
896
+ fn: (r) =>
897
+ float(v: r["_value"]) > 0.0 and (r["_field"] == "duration" or r["_field"]
898
+ ==
899
+ "latency"),
900
+ )
901
+
902
+ serviceInstanceProcessSum =
903
+ r1
904
+ |> group(columns: ["serviceId", "serviceInstanceId", "serviceInstanceProcessId", "_field"])
905
+ |> sum()
906
+ |> toFloat()
907
+
908
+ serviceInstanceProcessMean =
909
+ r2
910
+ |> group(columns: ["serviceId", "serviceInstanceId", "serviceInstanceProcessId", "_field"])
911
+ |> mean()
912
+ |> toFloat()
913
+
914
+ union(tables: [serviceInstanceProcessSum, serviceInstanceProcessMean])
915
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-serviceinstanceprocess"}))
916
+ |> to(org: "my-org", bucket: "TestBucket01")
917
+
918
+ serviceInstanceSum =
919
+ r1
920
+ |> group(columns: ["serviceId", "serviceInstanceId", "_field"])
921
+ |> sum()
922
+ |> toFloat()
923
+
924
+ serviceInstanceMean =
925
+ r2
926
+ |> group(columns: ["serviceId", "serviceInstanceId", "_field"])
927
+ |> mean()
928
+ |> toFloat()
929
+
930
+ union(tables: [serviceInstanceSum, serviceInstanceMean])
931
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-serviceinstance"}))
932
+ |> to(org: "my-org", bucket: "TestBucket01")
933
+
934
+ serviceSum =
935
+ r1
936
+ |> group(columns: ["serviceId", "_field"])
937
+ |> sum()
938
+ |> toFloat()
939
+
940
+ serviceMean =
941
+ r2
942
+ |> group(columns: ["serviceId", "_field"])
943
+ |> mean()
944
+ |> toFloat()
945
+
946
+ union(tables: [serviceSum, serviceMean])
947
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-service"}))
948
+ |> to(org: "my-org", bucket: "TestBucket01")
949
+
950
+ globalServiceSum =
951
+ r1
952
+ |> group(columns: ["_field"])
953
+ |> sum()
954
+ |> toFloat()
955
+
956
+ globalServiceMean =
957
+ r2
958
+ |> group(columns: ["_field"])
959
+ |> mean()
960
+ |> toFloat()
961
+
962
+ union(tables: [globalServiceSum, globalServiceMean])
963
+ |> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-globalservice"}))
964
+ |> to(org: "my-org", bucket: "TestBucket01")
965
+
966
+
967
+
968
+
969
+
970
+ */