@theotherwillembotha/node-red-plugincore 0.1.0 → 0.2.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/README.md +616 -220
- package/build/GenerateNodes.js +3 -6
- package/build/Nodes.html +3 -1504
- package/build/Nodes.js +5 -15
- package/build/Plugins.html +227 -0
- package/build/Plugins.js +18 -8
- package/build/core/NodeConstructor.d.ts +9 -16
- package/build/core/NodeConstructor.d.ts.map +1 -1
- package/build/core/NodeConstructor.js +109 -146
- package/build/core/NodeGenerator.d.ts.map +1 -1
- package/build/core/NodeGenerator.js +79 -28
- package/build/core/NodeManagerRuntime.d.ts +44 -0
- package/build/core/NodeManagerRuntime.d.ts.map +1 -0
- package/build/core/NodeManagerRuntime.js +140 -0
- package/build/core/Utils.d.ts.map +1 -1
- package/build/core/logger/service/LoggerService.d.ts +6 -5
- package/build/core/logger/service/LoggerService.d.ts.map +1 -1
- package/build/core/logger/service/LoggerService.js +51 -20
- package/build/core/logger/template/LoggerTemplate.d.ts.map +1 -1
- package/build/core/metrics/MetricsDecorator.d.ts +1 -2
- package/build/core/metrics/MetricsDecorator.d.ts.map +1 -1
- package/build/core/metrics/MetricsDecorator.js +89 -116
- package/build/core/metrics/node/CounterMetricConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/CounterMetricConfigNode.js +4 -5
- package/build/core/metrics/node/GaugeMetricConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/GaugeMetricConfigNode.js +5 -6
- package/build/core/metrics/node/MetricsConfigNode.d.ts +19 -9
- package/build/core/metrics/node/MetricsConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/MetricsConfigNode.js +14 -45
- package/build/core/metrics/node/TimerMetricConfigNode.d.ts.map +1 -1
- package/build/core/metrics/node/TimerMetricConfigNode.js +11 -17
- package/build/core/metrics/service/MetricsService.d.ts +110 -114
- package/build/core/metrics/service/MetricsService.d.ts.map +1 -1
- package/build/core/metrics/service/MetricsService.js +122 -339
- package/build/core/metrics/template/CounterMetricTemplate.d.ts.map +1 -1
- package/build/core/metrics/template/GaugeMetricTemplate.d.ts.map +1 -1
- package/build/core/metrics/template/MetricsTemplate.d.ts.map +1 -1
- package/build/core/metrics/template/MetricsTemplate.js +1 -2
- package/build/core/metrics/template/TimerMetricTemplate.d.ts.map +1 -1
- package/build/core/other/node/DelegatedConfigReferenceNode.d.ts +1 -1
- package/build/core/other/node/DelegatedConfigReferenceNode.d.ts.map +1 -1
- package/build/core/other/node/DelegatedConfigReferenceNode.js +1 -1
- package/build/core/other/service/InputService.d.ts.map +1 -1
- package/build/core/other/service/SettingsService.d.ts +1 -2
- package/build/core/other/service/SettingsService.d.ts.map +1 -1
- package/build/core/other/service/SettingsService.js +19 -5
- package/build/core/other/template/BasicTemplate.d.ts.map +1 -1
- package/build/core/other/template/SettingsTemplate.d.ts.map +1 -1
- package/build/core/state/node/InternalStateConfigNode.d.ts +16 -0
- package/build/core/state/node/InternalStateConfigNode.d.ts.map +1 -0
- package/build/core/state/node/InternalStateConfigNode.js +89 -0
- package/build/core/state/node/StateConfigNode.d.ts +24 -0
- package/build/core/state/node/StateConfigNode.d.ts.map +1 -0
- package/build/core/state/node/StateConfigNode.js +22 -0
- package/build/core/state/service/StateService.d.ts +34 -0
- package/build/core/state/service/StateService.d.ts.map +1 -0
- package/build/core/state/service/StateService.js +201 -0
- package/build/core/state/template/StateTemplate.d.ts +8 -0
- package/build/core/state/template/StateTemplate.d.ts.map +1 -0
- package/build/core/state/template/StateTemplate.js +11 -0
- package/build/core/tagging/ServiceDescriptionDecorator.d.ts +10 -0
- package/build/core/tagging/ServiceDescriptionDecorator.d.ts.map +1 -0
- package/build/core/tagging/ServiceDescriptionDecorator.js +10 -0
- package/build/core/tagging/service/NodeTypeService.d.ts +1 -2
- package/build/core/tagging/service/NodeTypeService.d.ts.map +1 -1
- package/build/core/tagging/service/NodeTypeService.js +19 -5
- package/build/core/ui/template/ScriptEditorTemplate.d.ts.map +1 -1
- package/build/core/ui/template/UIHelperTemplate.d.ts.map +1 -1
- package/build/core/webhook/node/WebhookServerConfigNode.d.ts.map +1 -1
- package/build/core/webhook/service/ReverseProxyTypeService.d.ts.map +1 -1
- package/build/core/webhook/service/WebhookServerService.d.ts +3 -4
- package/build/core/webhook/service/WebhookServerService.d.ts.map +1 -1
- package/build/core/webhook/service/WebhookServerService.js +48 -18
- package/build/core/webhook/template/WebhookTemplate.d.ts.map +1 -1
- package/build/index.d.ts +5 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +6 -2
- package/build/runtime/NodeManagerRuntime.js +140 -0
- package/documentation/CounterMetricConfigNode.png +0 -0
- package/documentation/GaugeMetricConfigNode.png +0 -0
- package/documentation/LoggerTemplate.png +0 -0
- package/documentation/MetricsTemplate.png +0 -0
- package/documentation/StateTemplate.png +0 -0
- package/documentation/TimerMetricConfigNode_histogram.png +0 -0
- package/documentation/TimerMetricConfigNode_summary.png +0 -0
- package/documentation/WebhookServerConfigNode.png +0 -0
- package/documentation/WebhookTemplate.png +0 -0
- package/package.json +4 -10
- package/src/GenerateNodes.ts +7 -11
- package/src/core/NodeConstructor.ts +130 -186
- package/src/core/NodeGenerator.ts +88 -33
- package/src/core/NodeManagerRuntime.ts +179 -0
- package/src/core/logger/service/LoggerService.ts +39 -26
- package/src/core/logger/template/LoggerTemplate.html +11 -6
- package/src/core/metrics/MetricsDecorator.ts +140 -168
- package/src/core/metrics/node/CounterMetricConfigNode.ts +20 -20
- package/src/core/metrics/node/GaugeMetricConfigNode.ts +24 -25
- package/src/core/metrics/node/MetricsConfigNode.ts +29 -48
- package/src/core/metrics/node/TimerMetricConfigNode.ts +50 -59
- package/src/core/metrics/service/MetricsService.ts +214 -489
- package/src/core/metrics/template/CounterMetricTemplate.html +0 -1
- package/src/core/metrics/template/GaugeMetricTemplate.html +1 -1
- package/src/core/metrics/template/MetricsTemplate.html +132 -13
- package/src/core/metrics/template/MetricsTemplate.ts +3 -4
- package/src/core/other/node/DelegatedConfigReferenceNode.ts +1 -1
- package/src/core/other/service/SettingsService.ts +6 -10
- package/src/core/other/template/BasicTemplate.html +1 -1
- package/src/core/state/node/InternalStateConfigNode.html +77 -0
- package/src/core/state/node/InternalStateConfigNode.ts +102 -0
- package/src/core/state/node/StateConfigNode.ts +29 -0
- package/src/core/state/service/StateService.ts +180 -0
- package/src/core/state/template/StateTemplate.html +244 -0
- package/src/core/state/template/StateTemplate.ts +17 -0
- package/src/core/tagging/ServiceDescriptionDecorator.ts +23 -0
- package/src/core/tagging/service/NodeTypeService.ts +6 -11
- package/src/core/ui/template/UIHelperTemplate.html +41 -26
- package/src/core/webhook/service/WebhookServerService.ts +39 -23
- package/src/core/webhook/template/WebhookTemplate.html +28 -35
- package/src/index.ts +7 -2
- package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts +0 -20
- package/build/core/logger/node/ConsoleLoggerConfigNode.d.ts.map +0 -1
- package/build/core/logger/node/ConsoleLoggerConfigNode.js +0 -62
- package/build/core/logger/node/RestLoggerConfigNode.d.ts +0 -40
- package/build/core/logger/node/RestLoggerConfigNode.d.ts.map +0 -1
- package/build/core/logger/node/RestLoggerConfigNode.js +0 -128
- package/documentation/ConsoleLoggerConfigNode.png +0 -0
- package/documentation/MetricsConfigNode.png +0 -0
- package/documentation/RestLoggerConfigNode.png +0 -0
- package/documentation/TimerMetricConfigNode.png +0 -0
- package/documentation/WebhookNode.png +0 -0
- package/src/core/logger/node/ConsoleLoggerConfigNode.html +0 -90
- package/src/core/logger/node/ConsoleLoggerConfigNode.ts +0 -71
- package/src/core/logger/node/RestLoggerConfigNode.html +0 -183
- package/src/core/logger/node/RestLoggerConfigNode.ts +0 -170
|
@@ -1,560 +1,285 @@
|
|
|
1
|
-
import {BaseNode, BaseNodeConfig, BaseService, FlowDeployment
|
|
2
|
-
import
|
|
1
|
+
import {BaseNode, BaseNodeConfig, BaseService, FlowDeployment} from "../../NodeConstructor"
|
|
2
|
+
import { ServiceDescription } from "../../tagging/ServiceDescriptionDecorator";
|
|
3
3
|
import { NodeAPI, NodeAPISettingsWithData } from "node-red";
|
|
4
|
-
import deepEqual from "deep-equal";
|
|
5
4
|
|
|
5
|
+
// ******************************************************* //
|
|
6
|
+
// Capability //
|
|
7
|
+
// ******************************************************* //
|
|
6
8
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
this._config = config;
|
|
13
|
-
this._labels = {flow:config.node.flow, type:config.node.type, name:config.node.name, id:config.node.id, metric:config.metricname};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public labels():Labels {
|
|
17
|
-
return this._labels;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public config():ConfigType{
|
|
21
|
-
return this._config;
|
|
22
|
-
}
|
|
9
|
+
export enum MetricCapability {
|
|
10
|
+
Counter = "Counter",
|
|
11
|
+
Gauge = "Gauge",
|
|
12
|
+
Histogram = "Histogram",
|
|
13
|
+
Summary = "Summary",
|
|
23
14
|
}
|
|
24
15
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// **************************************************** //
|
|
31
|
-
// Counter //
|
|
32
|
-
// **************************************************** //
|
|
33
|
-
|
|
16
|
+
// ******************************************************* //
|
|
17
|
+
// Base / Config Types //
|
|
18
|
+
// ******************************************************* //
|
|
34
19
|
|
|
35
|
-
type
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export type CounterState = {
|
|
40
|
-
value:number,
|
|
41
|
-
labels:{}
|
|
20
|
+
export type MetricsReference = {
|
|
21
|
+
metricsEnabled: boolean,
|
|
22
|
+
metricsReference: string
|
|
42
23
|
}
|
|
43
24
|
|
|
44
|
-
export interface
|
|
45
|
-
|
|
25
|
+
export interface MetricsConfig {
|
|
26
|
+
id: string;
|
|
46
27
|
}
|
|
47
28
|
|
|
48
|
-
export
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
super(config);
|
|
54
|
-
|
|
55
|
-
this.counter = new Counter({
|
|
56
|
-
name: id,
|
|
57
|
-
help: (config.metricdescription) ? config.metricdescription: config.metricname,
|
|
58
|
-
labelNames: Object.keys(this.labels()),
|
|
59
|
-
registers: [registry]
|
|
60
|
-
});
|
|
61
|
-
this.counter.reset();
|
|
62
|
-
this.internalCounter = this.counter.labels(this.labels() as any);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
public inc():CounterMetric{
|
|
66
|
-
this.internalCounter.inc();
|
|
67
|
-
this.get().then(state => Object.values(this.subscribers).forEach(callback => callback(state)));
|
|
68
|
-
return this;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public async get():Promise<CounterState> {
|
|
72
|
-
return this.counter.get().then(t => t.values[0]);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public reset():void{
|
|
76
|
-
this.counter.reset();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public subscribe(node:BaseNode<BaseNodeConfig>, callback:CounterCallback){
|
|
80
|
-
this.subscribers[node.id()] = callback;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public unsubscribe(node:BaseNode<BaseNodeConfig>){
|
|
84
|
-
delete this.subscribers[node.id()];
|
|
85
|
-
}
|
|
29
|
+
export interface NodeReference {
|
|
30
|
+
name: string;
|
|
31
|
+
type: string;
|
|
32
|
+
flow: string;
|
|
33
|
+
id: string;
|
|
86
34
|
}
|
|
87
35
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
(state:GaugeState):void;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
export interface GaugeState {
|
|
96
|
-
value: number
|
|
36
|
+
export interface MetricConfig {
|
|
37
|
+
node: NodeReference;
|
|
38
|
+
metricname: string;
|
|
39
|
+
metricdescription?: string;
|
|
97
40
|
}
|
|
98
41
|
|
|
99
|
-
|
|
100
|
-
|
|
42
|
+
interface Labels {
|
|
43
|
+
flow: string;
|
|
44
|
+
type: string;
|
|
45
|
+
name: string;
|
|
46
|
+
id: string;
|
|
47
|
+
metric: string;
|
|
101
48
|
}
|
|
102
49
|
|
|
103
|
-
export class
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
labelNames: Object.keys(this.labels()),
|
|
117
|
-
// this function is called every time the stats are collected.
|
|
118
|
-
// the response value needs to be set.
|
|
119
|
-
collect() { this.labels(_this.labels() as {}).set(_this.collector); }
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
public inc():GaugeMetric{
|
|
124
|
-
this.collector+=1;
|
|
125
|
-
let state:GaugeState = this.get();
|
|
126
|
-
Object.values(this.subscribers).forEach(sub => sub(state));
|
|
127
|
-
return this;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public dec():GaugeMetric{
|
|
131
|
-
this.collector-=1;
|
|
132
|
-
let state:GaugeState = this.get();
|
|
133
|
-
Object.values(this.subscribers).forEach(sub => sub(state));
|
|
134
|
-
return this;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public get():GaugeState {
|
|
138
|
-
return {
|
|
139
|
-
value:this.collector,
|
|
50
|
+
export abstract class Metric<ConfigType extends MetricConfig> {
|
|
51
|
+
private _config: ConfigType;
|
|
52
|
+
private _labels: Labels;
|
|
53
|
+
|
|
54
|
+
protected constructor(config: ConfigType) {
|
|
55
|
+
this._config = config;
|
|
56
|
+
this._labels = {
|
|
57
|
+
flow: config.node.flow,
|
|
58
|
+
type: config.node.type,
|
|
59
|
+
name: config.node.name,
|
|
60
|
+
id: config.node.id,
|
|
61
|
+
metric: config.metricname
|
|
62
|
+
};
|
|
140
63
|
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
public reset():void {
|
|
144
|
-
this.collector = 0;
|
|
145
|
-
}
|
|
146
64
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
public unsubscribe(node:BaseNode<BaseNodeConfig>){
|
|
152
|
-
delete this.subscribers[node.id()];
|
|
153
|
-
}
|
|
65
|
+
public labels(): Labels { return this._labels; }
|
|
66
|
+
public config(): ConfigType { return this._config; }
|
|
154
67
|
}
|
|
155
68
|
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
type HistogramCallback = {
|
|
161
|
-
(state:HistogramState):void;
|
|
162
|
-
};
|
|
69
|
+
// ******************************************************* //
|
|
70
|
+
// Counter //
|
|
71
|
+
// ******************************************************* //
|
|
163
72
|
|
|
164
|
-
export
|
|
73
|
+
export type CounterState = { value: number, labels: {} }
|
|
74
|
+
export type CounterCallback = (state: CounterState) => void;
|
|
75
|
+
export interface CounterMetricConfig extends MetricConfig { }
|
|
165
76
|
|
|
77
|
+
export interface CounterMetric {
|
|
78
|
+
inc(): this;
|
|
79
|
+
reset(): void;
|
|
80
|
+
get(): Promise<CounterState>;
|
|
81
|
+
subscribe(node: BaseNode<BaseNodeConfig>, callback: CounterCallback): void;
|
|
82
|
+
unsubscribe(node: BaseNode<BaseNodeConfig>): void;
|
|
166
83
|
}
|
|
167
84
|
|
|
168
|
-
export
|
|
169
|
-
|
|
85
|
+
export class DoNothingCounterMetric implements CounterMetric {
|
|
86
|
+
public inc(): this { return this; }
|
|
87
|
+
public reset(): void {}
|
|
88
|
+
public get(): Promise<CounterState> { return Promise.resolve({ value: 0, labels: {} }); }
|
|
89
|
+
public subscribe(_node: BaseNode<BaseNodeConfig>, _callback: CounterCallback): void {}
|
|
90
|
+
public unsubscribe(_node: BaseNode<BaseNodeConfig>): void {}
|
|
170
91
|
}
|
|
171
92
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
93
|
+
// ******************************************************* //
|
|
94
|
+
// Gauge //
|
|
95
|
+
// ******************************************************* //
|
|
96
|
+
|
|
97
|
+
export type GaugeState = { value: number }
|
|
98
|
+
export type GaugeCallback = (state: GaugeState) => void;
|
|
99
|
+
export interface GaugeMetricConfig extends MetricConfig { }
|
|
100
|
+
|
|
101
|
+
export interface GaugeMetric {
|
|
102
|
+
inc(): this;
|
|
103
|
+
dec(): this;
|
|
104
|
+
reset(): void;
|
|
105
|
+
get(): GaugeState;
|
|
106
|
+
subscribe(node: BaseNode<BaseNodeConfig>, callback: GaugeCallback): void;
|
|
107
|
+
unsubscribe(node: BaseNode<BaseNodeConfig>): void;
|
|
176
108
|
}
|
|
177
109
|
|
|
178
|
-
export
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
110
|
+
export class DoNothingGaugeMetric implements GaugeMetric {
|
|
111
|
+
public inc(): this { return this; }
|
|
112
|
+
public dec(): this { return this; }
|
|
113
|
+
public reset(): void {}
|
|
114
|
+
public get(): GaugeState { return { value: 0 }; }
|
|
115
|
+
public subscribe(_node: BaseNode<BaseNodeConfig>, _callback: GaugeCallback): void {}
|
|
116
|
+
public unsubscribe(_node: BaseNode<BaseNodeConfig>): void {}
|
|
182
117
|
}
|
|
183
118
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
119
|
+
// ******************************************************* //
|
|
120
|
+
// Histogram //
|
|
121
|
+
// ******************************************************* //
|
|
188
122
|
|
|
189
|
-
export
|
|
190
|
-
|
|
191
|
-
manual = "manual",
|
|
192
|
-
linear = "linear",
|
|
193
|
-
exponential = "exponential"
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export class HistogramMetric extends Metric<HistogramMetricConfig> {
|
|
197
|
-
|
|
198
|
-
private histogram: client.Histogram<string>;
|
|
199
|
-
private subscribers:{[key:string]:HistogramCallback} = {};
|
|
200
|
-
|
|
201
|
-
constructor(id:string, config:HistogramMetricConfig, registry:Registry){
|
|
202
|
-
super(config);
|
|
203
|
-
|
|
204
|
-
// Build the Histogram Config.
|
|
205
|
-
let histogramConfig:HistogramConfiguration<string> = {
|
|
206
|
-
name: id,
|
|
207
|
-
help: (config.metricdescription) ? config.metricdescription: config.metricname,
|
|
208
|
-
labelNames: Object.keys(this.labels()),
|
|
209
|
-
registers:[registry]
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if(config.buckettype === BucketType.default){
|
|
213
|
-
let bucketConfig = (config.bucketconfig as DefaultBucketConfig);
|
|
214
|
-
// do nothing
|
|
215
|
-
}
|
|
216
|
-
if(config.buckettype === BucketType.manual){
|
|
217
|
-
let bucketConfig = (config.bucketconfig as ManualBucketConfig);
|
|
218
|
-
histogramConfig.buckets = bucketConfig.intervals;
|
|
219
|
-
}
|
|
220
|
-
if(config.buckettype === BucketType.linear){
|
|
221
|
-
let bucketConfig = (config.bucketconfig as LinearBucketConfig);
|
|
222
|
-
histogramConfig.buckets = client.linearBuckets(bucketConfig.start, bucketConfig.interval, bucketConfig.count);
|
|
223
|
-
}
|
|
224
|
-
if(config.buckettype === BucketType.exponential){
|
|
225
|
-
let bucketConfig = (config.bucketconfig as ExponentialBucketConfig);
|
|
226
|
-
histogramConfig.buckets = client.exponentialBuckets(bucketConfig.start, bucketConfig.factor, bucketConfig.count);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
this.histogram = new Histogram(histogramConfig);
|
|
230
|
-
this.histogram.zero(this.labels() as any);
|
|
231
|
-
}
|
|
123
|
+
export type HistogramState = { average(): number | undefined; }
|
|
124
|
+
export type HistogramCallback = (state: HistogramState) => void;
|
|
232
125
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return this.histogram.get().then(t => new HistogramState(t.values));
|
|
240
|
-
}
|
|
126
|
+
export enum BucketType {
|
|
127
|
+
default = "default",
|
|
128
|
+
manual = "manual",
|
|
129
|
+
linear = "linear",
|
|
130
|
+
exponential = "exponential"
|
|
131
|
+
}
|
|
241
132
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
133
|
+
export interface DefaultBucketConfig { }
|
|
134
|
+
export interface ManualBucketConfig { intervals: number[]; }
|
|
135
|
+
export interface LinearBucketConfig { start: number; interval: number; count: number; }
|
|
136
|
+
export interface ExponentialBucketConfig { start: number; factor: number; count: number; }
|
|
245
137
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
138
|
+
export interface HistogramMetricConfig extends MetricConfig {
|
|
139
|
+
buckettype: BucketType;
|
|
140
|
+
bucketconfig: DefaultBucketConfig | ManualBucketConfig | LinearBucketConfig | ExponentialBucketConfig;
|
|
249
141
|
}
|
|
250
142
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
constructor(values:{labels:any, value:number, metricName?:string}[]){
|
|
256
|
-
this._values = values;
|
|
257
|
-
|
|
258
|
-
let sum = this._values.find(value => value.metricName?.endsWith("_sum"))?.value;
|
|
259
|
-
let count = this._values.find(value => value.metricName?.endsWith("_count"))?.value;
|
|
260
|
-
this._average = (sum && count) ? sum/count : undefined;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
public average():number|undefined{
|
|
264
|
-
return this._average;
|
|
265
|
-
}
|
|
143
|
+
export interface HistogramMetric {
|
|
144
|
+
observe(value: number): void;
|
|
145
|
+
subscribe(node: BaseNode<BaseNodeConfig>, callback: HistogramCallback): void;
|
|
146
|
+
unsubscribe(node: BaseNode<BaseNodeConfig>): void;
|
|
266
147
|
}
|
|
267
148
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
interface PercentileConfig{}
|
|
273
|
-
|
|
274
|
-
class SummaryState {
|
|
275
|
-
private _values: { labels: any; value: number; metricName?:string }[];
|
|
276
|
-
private _average: number | undefined;
|
|
277
|
-
|
|
278
|
-
constructor(values:{labels:any, value:number, metricName?:string}[]){
|
|
279
|
-
this._values = values;
|
|
280
|
-
|
|
281
|
-
let sum = this._values.find(value => value.metricName?.endsWith("_sum"))?.value;
|
|
282
|
-
let count = this._values.find(value => value.metricName?.endsWith("_count"))?.value;
|
|
283
|
-
this._average = (sum && count) ? sum/count : undefined;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
public average():number|undefined{
|
|
287
|
-
return this._average;
|
|
288
|
-
}
|
|
149
|
+
export class DoNothingHistogramMetric implements HistogramMetric {
|
|
150
|
+
public observe(_value: number): void {}
|
|
151
|
+
public subscribe(_node: BaseNode<BaseNodeConfig>, _callback: HistogramCallback): void {}
|
|
152
|
+
public unsubscribe(_node: BaseNode<BaseNodeConfig>): void {}
|
|
289
153
|
}
|
|
290
154
|
|
|
291
|
-
|
|
155
|
+
// ******************************************************* //
|
|
156
|
+
// Summary //
|
|
157
|
+
// ******************************************************* //
|
|
292
158
|
|
|
293
|
-
export
|
|
294
|
-
|
|
159
|
+
export type SummaryState = { average(): number | undefined; }
|
|
160
|
+
export type SummaryCallback = (state: SummaryState) => void;
|
|
295
161
|
|
|
296
|
-
export
|
|
297
|
-
|
|
162
|
+
export enum PercentileType {
|
|
163
|
+
default = "default",
|
|
164
|
+
manual = "manual"
|
|
298
165
|
}
|
|
299
166
|
|
|
167
|
+
export interface DefaultPercentileConfig { }
|
|
168
|
+
export interface ManualPercentileConfig { percentiles: number[]; }
|
|
169
|
+
|
|
300
170
|
export interface SummaryMetricConfig extends MetricConfig {
|
|
301
|
-
|
|
302
|
-
|
|
171
|
+
percentileType: PercentileType;
|
|
172
|
+
percentileConfig: DefaultPercentileConfig | ManualPercentileConfig;
|
|
303
173
|
}
|
|
304
174
|
|
|
305
|
-
export
|
|
306
|
-
|
|
307
|
-
|
|
175
|
+
export interface SummaryMetric {
|
|
176
|
+
observe(value: number): void;
|
|
177
|
+
subscribe(node: BaseNode<BaseNodeConfig>, callback: SummaryCallback): void;
|
|
178
|
+
unsubscribe(node: BaseNode<BaseNodeConfig>): void;
|
|
308
179
|
}
|
|
309
180
|
|
|
310
|
-
export class
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
constructor(id:string, config:SummaryMetricConfig, registry:Registry){
|
|
315
|
-
super(config);
|
|
316
|
-
|
|
317
|
-
let summaryConfig:SummaryConfiguration<string> = {
|
|
318
|
-
name: id,
|
|
319
|
-
help: (config.metricdescription) ? config.metricdescription: config.metricname,
|
|
320
|
-
labelNames: Object.keys(this.labels()),
|
|
321
|
-
registers:[registry],
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
if(config.percentileType === PercentileType.default){
|
|
325
|
-
// do nothing.
|
|
326
|
-
let perceintileConfig:DefaultPercentileConfig = config.percentileConfig as DefaultPercentileConfig;
|
|
327
|
-
summaryConfig.percentiles = [0.01, 0.1, 0.9, 0.99];
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if(config.percentileType === PercentileType.manual){
|
|
331
|
-
let percentilesConfig:ManualPercentileConfig = config.percentileConfig as ManualPercentileConfig;
|
|
332
|
-
summaryConfig.percentiles = percentilesConfig.percentiles;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
this.summary = new Summary(summaryConfig);
|
|
336
|
-
//this.summary.zero(this._labels as any);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
public observe(value:number){
|
|
340
|
-
this.summary.labels(this.labels() as any).observe(value);
|
|
341
|
-
this.get().then(status => Object.values(this.subscribers).forEach(subscriber => subscriber(status)));
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
public async get():Promise<SummaryState>{
|
|
345
|
-
return this.summary.get().then(s => new SummaryState(s.values));
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
public subscribe(node:BaseNode<BaseNodeConfig>, callback:SummaryCallback){
|
|
349
|
-
this.subscribers[node.id()] = callback;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
public unsubscribe(node:BaseNode<BaseNodeConfig>){
|
|
353
|
-
delete this.subscribers[node.id()];
|
|
354
|
-
}
|
|
181
|
+
export class DoNothingSummaryMetric implements SummaryMetric {
|
|
182
|
+
public observe(_value: number): void {}
|
|
183
|
+
public subscribe(_node: BaseNode<BaseNodeConfig>, _callback: SummaryCallback): void {}
|
|
184
|
+
public unsubscribe(_node: BaseNode<BaseNodeConfig>): void {}
|
|
355
185
|
}
|
|
356
186
|
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
//
|
|
360
|
-
interface Labels {
|
|
361
|
-
flow:string;
|
|
362
|
-
type:string;
|
|
363
|
-
name:string;
|
|
364
|
-
id:string;
|
|
365
|
-
metric:string;
|
|
366
|
-
}
|
|
187
|
+
// ******************************************************* //
|
|
188
|
+
// MetricsContainer //
|
|
189
|
+
// ******************************************************* //
|
|
367
190
|
|
|
368
|
-
export class MetricsContainer {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
constructor(config:MetricsConfig){
|
|
378
|
-
this._config = config;
|
|
379
|
-
|
|
380
|
-
// create a registry with the config.
|
|
381
|
-
this._registry = new client.Registry();
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
close() {
|
|
386
|
-
this._registry.clear();
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
public registry():client.Registry{
|
|
390
|
-
return this._registry;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// return true if the two configurations are not the same.
|
|
394
|
-
hasChanged(config: MetricsConfig): boolean {
|
|
395
|
-
return !(
|
|
396
|
-
this._config.metricsPath === config.metricsPath &&
|
|
397
|
-
this._config.metricsPort === config.metricsPort
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
public counter(config: CounterMetricConfig): CounterMetric{
|
|
402
|
-
const counterId = `counter_${config.node.id}`;
|
|
403
|
-
let counter:CounterMetric = this.counters[counterId];
|
|
404
|
-
if(counter){
|
|
405
|
-
// check if the config has changed much.
|
|
406
|
-
if(!deepEqual(counter.config(), config)){
|
|
407
|
-
this._registry.removeSingleMetric(counterId);
|
|
408
|
-
this.counters[counterId] = (counter = new CounterMetric(counterId, config, this._registry));
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
else{
|
|
412
|
-
this.counters[counterId] = (counter = new CounterMetric(counterId, config, this._registry));
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
return counter;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
public gauge(config: GaugeMetricConfig): GaugeMetric {
|
|
419
|
-
var gaugeId = `gauge_${config.node.id}`;
|
|
420
|
-
var gauge:GaugeMetric = this.gauges[gaugeId];
|
|
421
|
-
if(gauge){
|
|
422
|
-
// check if the config has changed much.
|
|
423
|
-
if(!deepEqual(gauge.config(), config)){
|
|
424
|
-
this._registry.removeSingleMetric(gaugeId);
|
|
425
|
-
this.gauges[gaugeId] = (gauge = new GaugeMetric(gaugeId, config, this._registry));
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
else{
|
|
429
|
-
this.gauges[gaugeId] = (gauge = new GaugeMetric(gaugeId, config, this._registry));
|
|
430
|
-
}
|
|
431
|
-
return gauge;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
public histogram(config: HistogramMetricConfig): HistogramMetric {
|
|
435
|
-
const histogramId = `histogram_${config.node.id}`;
|
|
436
|
-
let histogram:HistogramMetric = this.histograms[histogramId];
|
|
437
|
-
if(histogram){
|
|
438
|
-
// check if the config has changed much.
|
|
439
|
-
if(!deepEqual(histogram.config(), config)){
|
|
440
|
-
this._registry.removeSingleMetric(histogramId);
|
|
441
|
-
this.histograms[histogramId] = (histogram = new HistogramMetric(histogramId, config, this._registry));
|
|
442
|
-
}
|
|
191
|
+
export abstract class MetricsContainer {
|
|
192
|
+
public abstract supports(capability: MetricCapability): boolean;
|
|
193
|
+
public abstract hasChanged(config: MetricsConfig): boolean;
|
|
194
|
+
public abstract close(): void;
|
|
195
|
+
|
|
196
|
+
// Default implementations warn and return DoNothing - providers override what they support.
|
|
197
|
+
public counter(_config: CounterMetricConfig): CounterMetric {
|
|
198
|
+
console.warn(`[PluginCore] MetricsContainer: Counter is not supported by this provider.`);
|
|
199
|
+
return new DoNothingCounterMetric();
|
|
443
200
|
}
|
|
444
|
-
|
|
445
|
-
|
|
201
|
+
public gauge(_config: GaugeMetricConfig): GaugeMetric {
|
|
202
|
+
console.warn(`[PluginCore] MetricsContainer: Gauge is not supported by this provider.`);
|
|
203
|
+
return new DoNothingGaugeMetric();
|
|
446
204
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
public summary(config: SummaryMetricConfig): SummaryMetric {
|
|
452
|
-
const summaryId = `summary_${config.node.id}`;
|
|
453
|
-
let summary:SummaryMetric = this.summaries[summaryId];
|
|
454
|
-
if(summary){
|
|
455
|
-
if(!deepEqual(summary.config(), config)){
|
|
456
|
-
this._registry.removeSingleMetric(summaryId);
|
|
457
|
-
this.summaries[summaryId] = (summary = new SummaryMetric(summaryId, config, this._registry));
|
|
458
|
-
}
|
|
205
|
+
public histogram(_config: HistogramMetricConfig): HistogramMetric {
|
|
206
|
+
console.warn(`[PluginCore] MetricsContainer: Histogram is not supported by this provider.`);
|
|
207
|
+
return new DoNothingHistogramMetric();
|
|
459
208
|
}
|
|
460
|
-
|
|
461
|
-
|
|
209
|
+
public summary(_config: SummaryMetricConfig): SummaryMetric {
|
|
210
|
+
console.warn(`[PluginCore] MetricsContainer: Summary is not supported by this provider.`);
|
|
211
|
+
return new DoNothingSummaryMetric();
|
|
462
212
|
}
|
|
213
|
+
}
|
|
463
214
|
|
|
464
|
-
|
|
465
|
-
|
|
215
|
+
// Silent DoNothing - returned when no provider is installed. Does not warn since this is expected.
|
|
216
|
+
export class DoNothingMetricsContainer extends MetricsContainer {
|
|
217
|
+
public supports(_capability: MetricCapability): boolean { return false; }
|
|
218
|
+
public hasChanged(_config: MetricsConfig): boolean { return false; }
|
|
219
|
+
public close(): void {}
|
|
220
|
+
public counter(_config: CounterMetricConfig): CounterMetric { return new DoNothingCounterMetric(); }
|
|
221
|
+
public gauge(_config: GaugeMetricConfig): GaugeMetric { return new DoNothingGaugeMetric(); }
|
|
222
|
+
public histogram(_config: HistogramMetricConfig): HistogramMetric { return new DoNothingHistogramMetric(); }
|
|
223
|
+
public summary(_config: SummaryMetricConfig): SummaryMetric { return new DoNothingSummaryMetric(); }
|
|
466
224
|
}
|
|
467
225
|
|
|
226
|
+
// ******************************************************* //
|
|
227
|
+
// MetricsService //
|
|
228
|
+
// ******************************************************* //
|
|
468
229
|
|
|
469
|
-
|
|
230
|
+
const _GLOBAL_METRICS_KEY = '__plugincore_metrics__';
|
|
470
231
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
public constructor(){
|
|
475
|
-
super("MetricsService");
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
public init(red: NodeAPI<NodeAPISettingsWithData>): void {
|
|
479
|
-
this.red = red;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
public deinit(red: NodeAPI<NodeAPISettingsWithData>): void {
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
public async onDeploy(deployment: FlowDeployment): Promise<void> {
|
|
486
|
-
// get the FlowElements.
|
|
487
|
-
let configNodes:{[key:string]:MetricsConfig} = {};
|
|
488
|
-
deployment.flows
|
|
489
|
-
.filter(element => element.type === "MetricsConfigNode")
|
|
490
|
-
.forEach(element => configNodes[element.id] = element as any as MetricsConfig);
|
|
491
|
-
|
|
492
|
-
// retire metrics that have been removed or that have changed.
|
|
493
|
-
Object.entries(MetricsService.metrics)
|
|
494
|
-
.filter(([id, metric]) => !configNodes[id] || metric.hasChanged(configNodes[id]))
|
|
495
|
-
.forEach(([id, metric]) => {
|
|
496
|
-
delete MetricsService.metrics[id];
|
|
497
|
-
metric.close();
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
// create the new metrics.
|
|
501
|
-
Object.entries(configNodes)
|
|
502
|
-
.filter(([id, metricConfig]) => !MetricsService.metrics[id])
|
|
503
|
-
.forEach(([id, metricConfig]) => {
|
|
504
|
-
MetricsService.metrics[id] = new MetricsContainer(metricConfig);
|
|
505
|
-
})
|
|
506
|
-
|
|
507
|
-
return Promise.resolve();
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
public static get(reference:MetricsReference):MetricsContainer{
|
|
511
|
-
return MetricsService.metrics[reference.metricsReference];
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
static override getServiceDescriptor():ServiceDescriptor {
|
|
515
|
-
return new ServiceDescriptor(
|
|
516
|
-
"@theotherwillembotha/metricsservice",
|
|
517
|
-
"MetricsService",
|
|
518
|
-
"services-plugin",
|
|
519
|
-
"@theotherwillembotha/node-red-plugincore",
|
|
520
|
-
MetricsService
|
|
521
|
-
);
|
|
522
|
-
}
|
|
232
|
+
function getMetricsStore(): { [key: string]: MetricsContainer } {
|
|
233
|
+
if (!(global as any)[_GLOBAL_METRICS_KEY]) (global as any)[_GLOBAL_METRICS_KEY] = {};
|
|
234
|
+
return (global as any)[_GLOBAL_METRICS_KEY];
|
|
523
235
|
}
|
|
524
236
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
237
|
+
@ServiceDescription({
|
|
238
|
+
id: "@theotherwillembotha/metricsservice",
|
|
239
|
+
sourceFile: "@theotherwillembotha/node-red-plugincore"
|
|
240
|
+
})
|
|
241
|
+
export class MetricsService extends BaseService {
|
|
530
242
|
|
|
531
|
-
|
|
532
|
-
name: string;
|
|
533
|
-
type: string;
|
|
534
|
-
flow: string;
|
|
535
|
-
id: string;
|
|
536
|
-
}
|
|
243
|
+
private red!: NodeAPI<NodeAPISettingsWithData>;
|
|
537
244
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
245
|
+
public constructor() {
|
|
246
|
+
super("MetricsService");
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
public init(red: NodeAPI<NodeAPISettingsWithData>): void {
|
|
250
|
+
this.red = red;
|
|
251
|
+
}
|
|
543
252
|
|
|
544
|
-
|
|
545
|
-
Quick explanation of how this is supposed to work:
|
|
253
|
+
public deinit(_red: NodeAPI<NodeAPISettingsWithData>): void {}
|
|
546
254
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
flow deployments or to have the Metric / Repository become unavialable between deployments.
|
|
255
|
+
public async onDeploy(deployment: FlowDeployment): Promise<void> {
|
|
256
|
+
const store = getMetricsStore();
|
|
257
|
+
const flowIds = new Set(deployment.flows.map(e => e.id));
|
|
551
258
|
|
|
552
|
-
|
|
259
|
+
Object.entries(store)
|
|
260
|
+
.filter(([id]) => !flowIds.has(id))
|
|
261
|
+
.forEach(([id, container]) => {
|
|
262
|
+
delete store[id];
|
|
263
|
+
container.close();
|
|
264
|
+
});
|
|
553
265
|
|
|
554
|
-
|
|
266
|
+
return Promise.resolve();
|
|
267
|
+
}
|
|
555
268
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Called by MetricsConfigNode subclasses on construction.
|
|
271
|
+
* Preserves an existing container across redeploys if the config has not changed
|
|
272
|
+
* (so counters/gauges are not reset unnecessarily).
|
|
273
|
+
*/
|
|
274
|
+
public static register(id: string, config: MetricsConfig, factory: () => MetricsContainer): void {
|
|
275
|
+
const store = getMetricsStore();
|
|
276
|
+
const existing = store[id];
|
|
277
|
+
if (existing && !existing.hasChanged(config)) return;
|
|
278
|
+
if (existing) existing.close();
|
|
279
|
+
store[id] = factory();
|
|
280
|
+
}
|
|
559
281
|
|
|
560
|
-
|
|
282
|
+
public static get(reference: MetricsReference): MetricsContainer {
|
|
283
|
+
return getMetricsStore()[reference.metricsReference] ?? new DoNothingMetricsContainer();
|
|
284
|
+
}
|
|
285
|
+
}
|