@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.
- package/package.json +1 -1
- package/src_working/authDefs.ts +37 -0
- package/src_working/authutilsnode.ts +373 -0
- package/src_working/commonTypes.ts +239 -0
- package/src_working/index.ts +22 -0
- package/src_working/influxdb/influxDBManager.ts +970 -0
- package/src_working/influxdb/influxDBManagerAgent.ts +314 -0
- package/src_working/influxdb/influxDBManagerBase.ts +109 -0
- package/src_working/influxdb/influxDBManagerService.ts +373 -0
- package/src_working/instrumentationsubscriber.ts +283 -0
- package/src_working/kafka/IMKafkaManager.ts +152 -0
- package/src_working/kafka/kafkaconsumer.ts +82 -0
- package/src_working/kafka/kafkamanager.ts +186 -0
- package/src_working/kafka/kafkaproducer.ts +58 -0
- package/src_working/kafkatesting/config.ts +10 -0
- package/src_working/kafkatesting/consume.ts +116 -0
- package/src_working/kafkatesting/produce.ts +153 -0
- package/src_working/masterprocessbase.ts +598 -0
- package/src_working/middleware/serverNetworkMiddleware.ts +240 -0
- package/src_working/network.ts +36 -0
- package/src_working/processbase.ts +411 -0
- package/src_working/processoptions.ts +164 -0
- package/src_working/publishertransports/publishTransportDirect.ts +45 -0
- package/src_working/publishertransports/publishTransportUtils.ts +53 -0
- package/src_working/server.ts +141 -0
- package/src_working/serverprocessbase.ts +393 -0
- package/src_working/singleprocessbase.ts +121 -0
- package/src_working/socketIoServerHelper.ts +177 -0
- package/src_working/stscontrollerbase.ts +15 -0
- package/src_working/stslatencycontroller.ts +27 -0
- package/src_working/stslatencyroute.ts +16 -0
- package/src_working/stsrouterbase.ts +22 -0
- package/src_working/tcpclient/app.ts +19 -0
- package/src_working/tcpclient/app2.ts +56 -0
- package/src_working/tcpserver/app.ts +11 -0
- package/src_working/tcpserver/appConfig.ts +65 -0
- package/src_working/tcpserver/appmaster.ts +544 -0
- package/src_working/validation/errors.ts +6 -0
- package/src_working/webworkertesting/app.ts +49 -0
- package/src_working/webworkertesting/worker.ts +24 -0
- package/src_working/workerprocessbase.test.ts +47 -0
- package/src_working/workerprocessbase.ts +185 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
|
|
2
|
+
// https://www.influxdata.com/blog/tldr-influxdb-tech-tips-multiple-aggregations-yield-flux/
|
|
3
|
+
// https://www.influxdata.com/blog/top-5-hurdles-for-intermediate-flux-users-and-resources-for-optimizing-flux/
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
option task = {name: "task-sts-agent-stats", every: 1s}
|
|
7
|
+
|
|
8
|
+
data =
|
|
9
|
+
from(bucket: "TestBucket01")
|
|
10
|
+
|> range(start: -5s)
|
|
11
|
+
|> last()
|
|
12
|
+
|> filter(fn: (r) => r["_measurement"] == "agent")
|
|
13
|
+
|
|
14
|
+
r1 =
|
|
15
|
+
data
|
|
16
|
+
|> filter(fn: (r) => r["_field"] == "requestCount"
|
|
17
|
+
or r["_field"] == "errorCount"
|
|
18
|
+
or r["_field"] == "retryCount"
|
|
19
|
+
or r["_field"] == "authenticationCount"
|
|
20
|
+
or r["_field"] == "activeRequestCount"
|
|
21
|
+
or r["_field"] == "coreCount"
|
|
22
|
+
or r["_field"] == "velocity"
|
|
23
|
+
or r["_field"] == "rx"
|
|
24
|
+
or r["_field"] == "tx"
|
|
25
|
+
or r["_field"] == "childCount"
|
|
26
|
+
or r["_field"] == "timer")
|
|
27
|
+
|
|
28
|
+
r2 =
|
|
29
|
+
data
|
|
30
|
+
|> filter(fn: (r) => float(v: r["_value"]) > 0.0 and (r["_field"] == "duration"
|
|
31
|
+
or r["_field"] == "latency"))
|
|
32
|
+
|
|
33
|
+
byagentthreadasyncunnersum =
|
|
34
|
+
r1
|
|
35
|
+
|> group(columns: ["agentName", "threadId", "asyncRunnerId", "_field"])
|
|
36
|
+
|> sum()
|
|
37
|
+
|> toFloat()
|
|
38
|
+
|
|
39
|
+
byagentthreadasyncunnermean =
|
|
40
|
+
r2
|
|
41
|
+
|> group(columns: ["agentName", "threadId", "asyncRunnerId", "_field"])
|
|
42
|
+
|> mean()
|
|
43
|
+
|> toFloat()
|
|
44
|
+
|
|
45
|
+
union(tables: [byagentthreadasyncunnersum, byagentthreadasyncunnermean])
|
|
46
|
+
|> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-agentthreadasyncunner"}))
|
|
47
|
+
|> to(org: "my-org", bucket: "TestBucket01")
|
|
48
|
+
|
|
49
|
+
byagentthreadsum =
|
|
50
|
+
r1
|
|
51
|
+
|> group(columns: ["agentName", "threadId", "_field"])
|
|
52
|
+
|> sum()
|
|
53
|
+
|> toFloat()
|
|
54
|
+
|
|
55
|
+
byagentthreadmean =
|
|
56
|
+
r2
|
|
57
|
+
|> group(columns: ["agentName", "threadId", "_field"])
|
|
58
|
+
|> mean()
|
|
59
|
+
|> toFloat()
|
|
60
|
+
|
|
61
|
+
union(tables: [byagentthreadsum, byagentthreadmean])
|
|
62
|
+
|> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-agentthread"}))
|
|
63
|
+
|> to(org: "my-org", bucket: "TestBucket01")
|
|
64
|
+
|
|
65
|
+
byagentsum =
|
|
66
|
+
r1
|
|
67
|
+
|> group(columns: ["agentName", "_field"])
|
|
68
|
+
|> sum()
|
|
69
|
+
|> toFloat()
|
|
70
|
+
|
|
71
|
+
byagentmean =
|
|
72
|
+
r2
|
|
73
|
+
|> group(columns: ["agentName", "_field"])
|
|
74
|
+
|> mean()
|
|
75
|
+
|> toFloat()
|
|
76
|
+
|
|
77
|
+
union(tables: [byagentsum, byagentmean])
|
|
78
|
+
|> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-by-agent"}))
|
|
79
|
+
|> to(org: "my-org", bucket: "TestBucket01")
|
|
80
|
+
|
|
81
|
+
globalagentsum =
|
|
82
|
+
r1
|
|
83
|
+
|> group(columns: ["_field"])
|
|
84
|
+
|> sum()
|
|
85
|
+
|> toFloat()
|
|
86
|
+
|
|
87
|
+
globalagentmean =
|
|
88
|
+
r2
|
|
89
|
+
|> group(columns: ["_field"])
|
|
90
|
+
|> mean()
|
|
91
|
+
|> toFloat()
|
|
92
|
+
|
|
93
|
+
union(tables: [globalagentsum, globalagentmean])
|
|
94
|
+
|> map(fn: (r) => ({r with _time: now(), _measurement: "sts-stats-globalagent"}))
|
|
95
|
+
|> to(org: "my-org", bucket: "TestBucket01")
|
|
96
|
+
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
import { Point, WriteApi, QueryApi } from '@influxdata/influxdb-client'
|
|
100
|
+
|
|
101
|
+
import { Gauge, InstrumentVelocity } from '@nsshunt/stsinstrumentation'
|
|
102
|
+
|
|
103
|
+
import { InfluxDBManagerBase } from './influxDBManagerBase'
|
|
104
|
+
|
|
105
|
+
import { IInfluxDBManagerOptions, InstrumentPayload } from './../commonTypes'
|
|
106
|
+
import { ISubscriptionPayload, ISubscriptionKey } from '@nsshunt/stssocketio-client'
|
|
107
|
+
|
|
108
|
+
const AGENT_STATS_BY_AGENT_THREAD_ASYNCRUNNER = "sts-stats-by-agentthreadasyncunner";
|
|
109
|
+
const AGENT_STATS_BY_AGENT_THREAD = "sts-stats-by-agentthread";
|
|
110
|
+
const AGENT_STATS_BY_AGENT = "sts-stats-by-agent";
|
|
111
|
+
const AGENT_STATS_GLOBALAGENT = "sts-stats-globalagent";
|
|
112
|
+
|
|
113
|
+
const _logPrefix = 'InfluxDBManagerService:'
|
|
114
|
+
|
|
115
|
+
export class InfluxDBManagerAgent extends InfluxDBManagerBase
|
|
116
|
+
{
|
|
117
|
+
constructor(options: IInfluxDBManagerOptions, queryApi: QueryApi) {
|
|
118
|
+
super(options, queryApi);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
override get modelType(): string {
|
|
122
|
+
return 'agent'
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Queries --------------------------------------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
// Counter metrics
|
|
128
|
+
#GetSTSCountGenericAgent = async (measurement: string, filterClause: string, showOutput: boolean = false) => {
|
|
129
|
+
try {
|
|
130
|
+
const query = `from(bucket: "${this.options.bucket}")
|
|
131
|
+
|> range(start: -5s)
|
|
132
|
+
|> last()
|
|
133
|
+
|> filter(fn: (r) => r["_measurement"] == "${measurement}" ${filterClause})`;
|
|
134
|
+
|
|
135
|
+
if (showOutput) {
|
|
136
|
+
console.log(query);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return this.queryApi.collectRows(query)
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error(`${_logPrefix}#GetSTSCountGeneric: Error: [${error}]`.red);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Histo metrics
|
|
146
|
+
#GetSTSHistoGenericService = async (measurement: string, filterClause: string): Promise<any> => {
|
|
147
|
+
try {
|
|
148
|
+
const query = `import "math"
|
|
149
|
+
from(bucket: "${this.options.bucket}")
|
|
150
|
+
|> range(start: -10m)
|
|
151
|
+
|> filter(fn: (r) => r["_measurement"] == "${measurement}" and (r["_field"] =="latency"
|
|
152
|
+
or r["_field"] =="duration") ${filterClause})
|
|
153
|
+
|> histogram(bins: [0.0, 10.0, 20.0, 50.0, 100.0, 1000.0, 50000.0, math.mInf(sign: 1) ])
|
|
154
|
+
|> difference()`;
|
|
155
|
+
return this.queryApi.collectRows(query)
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error(`${_logPrefix}#GetSTSHistoGeneric: Error: [${error}]`.red);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Quantile metrics
|
|
162
|
+
#GetSTSQuantileGenericAgent = async (measurement: string, filterClause: string) => {
|
|
163
|
+
try {
|
|
164
|
+
const query = `data = from(bucket: "${this.options.bucket}")
|
|
165
|
+
|> range(start: -10m)
|
|
166
|
+
|> filter(fn: (r) => r["_measurement"] == "${measurement}" and (r["_field"] == "latency"
|
|
167
|
+
or r["_field"] == "duration") ${filterClause})
|
|
168
|
+
|> aggregateWindow(every: 5s, fn: max, createEmpty: false)
|
|
169
|
+
|
|
170
|
+
dostsquantileex = (q) =>
|
|
171
|
+
data
|
|
172
|
+
|> quantile(q: q, method: "estimate_tdigest", compression: 1000.0)
|
|
173
|
+
|> set(key: "quantile", value: string(v:q))
|
|
174
|
+
|> group(columns: ["quantile"])
|
|
175
|
+
|
|
176
|
+
union(tables: [
|
|
177
|
+
dostsquantileex(q: 0.5),
|
|
178
|
+
dostsquantileex(q: 0.8),
|
|
179
|
+
dostsquantileex(q: 0.9),
|
|
180
|
+
dostsquantileex(q: 0.95),
|
|
181
|
+
dostsquantileex(q: 0.99)
|
|
182
|
+
])`;
|
|
183
|
+
|
|
184
|
+
return this.queryApi.collectRows(query)
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error(`${_logPrefix}#GetSTSQuantileGeneric: Error: [${error}]`.red);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Metric queries -------------------------------------------------------------------------------------------------
|
|
191
|
+
// Root level metrics
|
|
192
|
+
async GetInfluxDBResultsRootAgent(subscriptionKey: ISubscriptionKey): Promise<ISubscriptionPayload> { // ISubscriptionPayload
|
|
193
|
+
let retVal = null;
|
|
194
|
+
try {
|
|
195
|
+
retVal = await this.ProcessInfluxDBResults([
|
|
196
|
+
this.#GetSTSCountGenericAgent(AGENT_STATS_GLOBALAGENT, ''),
|
|
197
|
+
this.#GetSTSQuantileGenericAgent(AGENT_STATS_GLOBALAGENT, ''),
|
|
198
|
+
this.#GetSTSHistoGenericService(AGENT_STATS_GLOBALAGENT, '')],
|
|
199
|
+
[ ])
|
|
200
|
+
} catch (error) {
|
|
201
|
+
console.error(`${_logPrefix}GetInfluxDBResultsRootAgent: Error: [${error}]`.red);
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
subscriptionKey,
|
|
205
|
+
data: retVal
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Service level metrics
|
|
210
|
+
async GetInfluxDBResultsAgent(subscriptionKey: ISubscriptionKey): Promise<ISubscriptionPayload> {
|
|
211
|
+
let retVal = null;
|
|
212
|
+
try {
|
|
213
|
+
retVal = await this.ProcessInfluxDBResults([
|
|
214
|
+
this.#GetSTSCountGenericAgent(AGENT_STATS_BY_AGENT, ''),
|
|
215
|
+
this.#GetSTSQuantileGenericAgent(AGENT_STATS_BY_AGENT, ''),
|
|
216
|
+
this.#GetSTSHistoGenericService(AGENT_STATS_BY_AGENT, '')],
|
|
217
|
+
['agentName'])
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.error(`${_logPrefix}GetInfluxDBResultsAgent: Error: [${error}]`.red);
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
subscriptionKey,
|
|
223
|
+
data: retVal
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Service instance metrics for a particular service type
|
|
228
|
+
async GetInfluxDBResultsAgentThreads(subscriptionKey: ISubscriptionKey): Promise<ISubscriptionPayload> {
|
|
229
|
+
let retVal = null;
|
|
230
|
+
try {
|
|
231
|
+
const agentName = subscriptionKey.key as string;
|
|
232
|
+
retVal = await this.ProcessInfluxDBResults([
|
|
233
|
+
this.#GetSTSCountGenericAgent(AGENT_STATS_BY_AGENT_THREAD, `and r["agentName"] == "${agentName}"`),
|
|
234
|
+
this.#GetSTSQuantileGenericAgent(AGENT_STATS_BY_AGENT_THREAD, `and r["agentName"] == "${agentName}"`),
|
|
235
|
+
this.#GetSTSHistoGenericService(AGENT_STATS_BY_AGENT_THREAD, `and r["agentName"] == "${agentName}"`)],
|
|
236
|
+
['agentName', 'threadId'])
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error(`${_logPrefix}GetInfluxDBResultsAgentThreads: Error: [${error}]`.red);
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
subscriptionKey,
|
|
242
|
+
data: retVal
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Service instance thread metrics for a particular service instance
|
|
247
|
+
async GetInfluxDBResultsAgentThread(subscriptionKey: ISubscriptionKey): Promise<ISubscriptionPayload> {
|
|
248
|
+
let retVal = null;
|
|
249
|
+
try {
|
|
250
|
+
const agentName = subscriptionKey.key as string;
|
|
251
|
+
const threadId = subscriptionKey.subkey as string;
|
|
252
|
+
retVal = await this.ProcessInfluxDBResults([
|
|
253
|
+
this.#GetSTSCountGenericAgent(AGENT_STATS_BY_AGENT_THREAD_ASYNCRUNNER, `and r["agentName"] == "${agentName}" and r["threadId"] == "${threadId}"`),
|
|
254
|
+
this.#GetSTSQuantileGenericAgent(AGENT_STATS_BY_AGENT_THREAD_ASYNCRUNNER, `and r["agentName"] == "${agentName}" and r["threadId"] == "${threadId}"`),
|
|
255
|
+
this.#GetSTSHistoGenericService(AGENT_STATS_BY_AGENT_THREAD_ASYNCRUNNER, `and r["agentName"] == "${agentName}" and r["threadId"] == "${threadId}"`)],
|
|
256
|
+
['agentName', 'threadId', 'asyncRunnerId'])
|
|
257
|
+
} catch (error) {
|
|
258
|
+
console.error(`${_logPrefix}GetInfluxDBResultsAgentThread: Error: [${error}]`.red);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
subscriptionKey,
|
|
262
|
+
data: retVal
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Agent context payload
|
|
267
|
+
// {"nid":"somehost@e58f5d75-6ff6-4e04-92a4-f2bcd722fec0-someuseragent|MainProcess|0","id":"somehost@e58f5d75-6ff6-4e04-92a4-f2bcd722fec0-someuseragent|MainProcess|0","hostName":"somehost"
|
|
268
|
+
// ,"agentName":"e58f5d75-6ff6-4e04-92a4-f2bcd722fec0-someuseragent","threadId":"MainProcess","asyncRunnerId":"0"}
|
|
269
|
+
async OutputInfluxDB(writeApi: WriteApi, instrumentPayload: InstrumentPayload): Promise<boolean> {
|
|
270
|
+
if (writeApi) {
|
|
271
|
+
try {
|
|
272
|
+
const { nid, id, hostName, agentName, threadId, asyncRunnerId } = instrumentPayload.context;
|
|
273
|
+
|
|
274
|
+
let systemcpu = 0.0;
|
|
275
|
+
if (instrumentPayload.instruments[Gauge.CPU_SYSTEM_LOAD_GAUGE]) {
|
|
276
|
+
systemcpu = (instrumentPayload.instruments[Gauge.CPU_SYSTEM_LOAD_GAUGE].val as number);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const point = new Point('all')
|
|
280
|
+
.measurement('agent')
|
|
281
|
+
// Context settings
|
|
282
|
+
.tag('id', id as string) // Must be unique (uuid)
|
|
283
|
+
.tag('hostName', hostName as string) // Must be unique (uuid)
|
|
284
|
+
.tag('agentName', agentName as string) // Must be unique (uuid)
|
|
285
|
+
.tag('threadId', threadId as string) // Must be unique (uuid)
|
|
286
|
+
.tag('asyncRunnerId', asyncRunnerId as string)
|
|
287
|
+
// Data fields
|
|
288
|
+
.intField('requestCount', instrumentPayload.instruments[Gauge.REQUEST_COUNT_GAUGE].val) // q
|
|
289
|
+
.intField('errorCount', instrumentPayload.instruments[Gauge.ERROR_COUNT_GAUGE].val) // j
|
|
290
|
+
.intField('retryCount', instrumentPayload.instruments[Gauge.RETRY_COUNT_GAUGE].val) // r
|
|
291
|
+
.intField('authenticationCount', instrumentPayload.instruments[Gauge.AUTHENTICATION_COUNT_GAUGE].val) // b
|
|
292
|
+
.floatField('velocity', (instrumentPayload.instruments[Gauge.VELOCITY_GAUGE] as InstrumentVelocity).va) // t - Note: Using va not val here
|
|
293
|
+
.intField('coreCount', instrumentPayload.instruments[Gauge.CORE_COUNT_GAUGE].val) // x
|
|
294
|
+
.floatField('rx', (instrumentPayload.instruments[Gauge.NETWORK_RX_GAUGE] as InstrumentVelocity).va) // Note: Using va not val here
|
|
295
|
+
.floatField('tx', (instrumentPayload.instruments[Gauge.NETWORK_TX_GAUGE] as InstrumentVelocity).va) // Note: Using va not val here
|
|
296
|
+
.floatField('timer', instrumentPayload.instruments[Gauge.TIMER_GAUGE].val) // s
|
|
297
|
+
.floatField('duration', instrumentPayload.instruments[Gauge.DURATION_GAUGE].val) // h
|
|
298
|
+
.floatField('latency', instrumentPayload.instruments[Gauge.LATENCY_GAUGE].val) // h
|
|
299
|
+
.intField('activeRequestCount', instrumentPayload.instruments[Gauge.ACTIVE_REQUEST_GAUGE].val) // a
|
|
300
|
+
.intField('childCount', instrumentPayload.instruments[Gauge.CHILD_COUNT].val) // y
|
|
301
|
+
// logger // m
|
|
302
|
+
// duration histo // i
|
|
303
|
+
writeApi.writePoint(point);
|
|
304
|
+
return true;
|
|
305
|
+
} catch (error: any) {
|
|
306
|
+
console.error(`${_logPrefix}OutputInfluxDBAgent: Could not write data point: [${error}]`.red);
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
console.error(`${_logPrefix}OutputInfluxDBAgent: Could not write data point as writeClient is null`.red);
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
|
|
2
|
+
// https://www.influxdata.com/blog/tldr-influxdb-tech-tips-multiple-aggregations-yield-flux/
|
|
3
|
+
// https://www.influxdata.com/blog/top-5-hurdles-for-intermediate-flux-users-and-resources-for-optimizing-flux/
|
|
4
|
+
import { WriteApi, QueryApi } from '@influxdata/influxdb-client'
|
|
5
|
+
|
|
6
|
+
import { IInfluxDBManagerOptions, InstrumentPayload } from './../commonTypes'
|
|
7
|
+
|
|
8
|
+
import { JSONObject } from '@nsshunt/stsutils'
|
|
9
|
+
|
|
10
|
+
const _logPrefix = 'InfluxDBManager:'
|
|
11
|
+
|
|
12
|
+
export class InfluxDBManagerBase
|
|
13
|
+
{
|
|
14
|
+
#queryApi: QueryApi;
|
|
15
|
+
#shuttingDown: boolean = false;
|
|
16
|
+
#options: IInfluxDBManagerOptions;
|
|
17
|
+
|
|
18
|
+
constructor(options: IInfluxDBManagerOptions, queryApi: QueryApi) {
|
|
19
|
+
this.#queryApi = queryApi;
|
|
20
|
+
this.#options = options;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get options() {
|
|
24
|
+
return this.#options;
|
|
25
|
+
}
|
|
26
|
+
get queryApi() {
|
|
27
|
+
return this.#queryApi;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get shuttingDown() {
|
|
31
|
+
return this.#shuttingDown;
|
|
32
|
+
}
|
|
33
|
+
set shuttingDown(val: boolean) {
|
|
34
|
+
this.#shuttingDown = val;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get modelType(): string {
|
|
38
|
+
throw new Error('modelType(): Must override in sub-class')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Helpers --------------------------------------------------------------------------------------------------------
|
|
42
|
+
async ProcessInfluxDBResults(promArray: Promise<any>[], fields: string[]) {
|
|
43
|
+
try {
|
|
44
|
+
const promRetVal: any[] = await Promise.all(promArray).catch(error => {
|
|
45
|
+
console.error(error)
|
|
46
|
+
}) as any[];
|
|
47
|
+
|
|
48
|
+
const combinedResults: any = { };
|
|
49
|
+
|
|
50
|
+
if (promRetVal) {
|
|
51
|
+
const stscount: any[] = promRetVal[0];
|
|
52
|
+
const stsquantile: any[] = promRetVal[1];
|
|
53
|
+
const stshisto: any[] = promRetVal[2];
|
|
54
|
+
|
|
55
|
+
stscount.forEach((countRecord) => {
|
|
56
|
+
const values: any[] = fields.map(field => countRecord[field])
|
|
57
|
+
const { _field, _value } = countRecord;
|
|
58
|
+
this.CreateNestedObject(combinedResults, values)[_field] = _value;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
stsquantile.forEach((stsquantileRecord) => {
|
|
62
|
+
const values: any[] = fields.map(field => stsquantileRecord[field])
|
|
63
|
+
const { _field, quantile, _value} = stsquantileRecord;
|
|
64
|
+
const useField = _field + '_quantile'
|
|
65
|
+
this.CreateNestedObject(combinedResults, [...values, useField])[quantile] = _value;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
stshisto.forEach((stshistoRecord) => {
|
|
69
|
+
const values: any[] = fields.map(field => stshistoRecord[field])
|
|
70
|
+
const { _field, le, _value} = stshistoRecord;
|
|
71
|
+
const useField = _field + '_histo'
|
|
72
|
+
this.CreateNestedObject(combinedResults, [...values, useField])[le] = _value;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return combinedResults;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error(`${_logPrefix}ProcessInfluxDBResults: Error: [${error}]`.red);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
CreateGlobalCountModel = (stscount: any[]) => {
|
|
82
|
+
try {
|
|
83
|
+
const results: any = { };
|
|
84
|
+
stscount.forEach((o: any) => {
|
|
85
|
+
results[o._field] = o._value;
|
|
86
|
+
});
|
|
87
|
+
return results;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(`${_logPrefix}#CreateGlobalCountModel: Error: [${error}]`.red);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
CreateNestedObject(combinedResults: JSONObject, keyList: string[]): JSONObject {
|
|
94
|
+
let workingObject = combinedResults;
|
|
95
|
+
keyList.forEach((key) => {
|
|
96
|
+
if (!workingObject[key]) {
|
|
97
|
+
workingObject[key] = { };
|
|
98
|
+
}
|
|
99
|
+
workingObject = workingObject[key];
|
|
100
|
+
});
|
|
101
|
+
return workingObject;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Agent context payload
|
|
105
|
+
// {"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"}
|
|
106
|
+
async OutputInfluxDB(writeApi: WriteApi, instrumentPayload: InstrumentPayload): Promise<boolean> {
|
|
107
|
+
throw new Error('Must override in sub-class');
|
|
108
|
+
}
|
|
109
|
+
}
|