@grest-ts/metrics 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +40 -0
- package/dist/src/GGMetric.d.ts +60 -0
- package/dist/src/GGMetric.d.ts.map +1 -0
- package/dist/src/GGMetric.js +64 -0
- package/dist/src/GGMetric.js.map +1 -0
- package/dist/src/GGMetricKey.d.ts +13 -0
- package/dist/src/GGMetricKey.d.ts.map +1 -0
- package/dist/src/GGMetricKey.js +29 -0
- package/dist/src/GGMetricKey.js.map +1 -0
- package/dist/src/GGMetrics.d.ts +10 -0
- package/dist/src/GGMetrics.d.ts.map +1 -0
- package/dist/src/GGMetrics.js +29 -0
- package/dist/src/GGMetrics.js.map +1 -0
- package/dist/src/GGMetricsDefineStorage.d.ts +4 -0
- package/dist/src/GGMetricsDefineStorage.d.ts.map +1 -0
- package/dist/src/GGMetricsDefineStorage.js +7 -0
- package/dist/src/GGMetricsDefineStorage.js.map +1 -0
- package/dist/src/GGMetricsLoader.d.ts +8 -0
- package/dist/src/GGMetricsLoader.d.ts.map +1 -0
- package/dist/src/GGMetricsLoader.js +17 -0
- package/dist/src/GGMetricsLoader.js.map +1 -0
- package/dist/src/GGMetricsStore.d.ts +9 -0
- package/dist/src/GGMetricsStore.d.ts.map +1 -0
- package/dist/src/GGMetricsStore.js +20 -0
- package/dist/src/GGMetricsStore.js.map +1 -0
- package/dist/src/exporters/GGJsonMetricsExporter.d.ts +41 -0
- package/dist/src/exporters/GGJsonMetricsExporter.d.ts.map +1 -0
- package/dist/src/exporters/GGJsonMetricsExporter.js +129 -0
- package/dist/src/exporters/GGJsonMetricsExporter.js.map +1 -0
- package/dist/src/exporters/GGMetricsExporter.d.ts +41 -0
- package/dist/src/exporters/GGMetricsExporter.d.ts.map +1 -0
- package/dist/src/exporters/GGMetricsExporter.js +70 -0
- package/dist/src/exporters/GGMetricsExporter.js.map +1 -0
- package/dist/src/exporters/GGNestedMetricsExporter.d.ts +33 -0
- package/dist/src/exporters/GGNestedMetricsExporter.d.ts.map +1 -0
- package/dist/src/exporters/GGNestedMetricsExporter.js +275 -0
- package/dist/src/exporters/GGNestedMetricsExporter.js.map +1 -0
- package/dist/src/index-browser.d.ts +17 -0
- package/dist/src/index-browser.d.ts.map +1 -0
- package/dist/src/index-browser.js +17 -0
- package/dist/src/index-browser.js.map +1 -0
- package/dist/src/index-node.d.ts +17 -0
- package/dist/src/index-node.d.ts.map +1 -0
- package/dist/src/index-node.js +20 -0
- package/dist/src/index-node.js.map +1 -0
- package/dist/src/keys/GGCounterKey.d.ts +11 -0
- package/dist/src/keys/GGCounterKey.d.ts.map +1 -0
- package/dist/src/keys/GGCounterKey.js +21 -0
- package/dist/src/keys/GGCounterKey.js.map +1 -0
- package/dist/src/keys/GGGaugeKey.d.ts +13 -0
- package/dist/src/keys/GGGaugeKey.d.ts.map +1 -0
- package/dist/src/keys/GGGaugeKey.js +27 -0
- package/dist/src/keys/GGGaugeKey.js.map +1 -0
- package/dist/src/keys/GGHistogramKey.d.ts +13 -0
- package/dist/src/keys/GGHistogramKey.d.ts.map +1 -0
- package/dist/src/keys/GGHistogramKey.js +27 -0
- package/dist/src/keys/GGHistogramKey.js.map +1 -0
- package/dist/src/keys/GGLazyGaugeKey.d.ts +21 -0
- package/dist/src/keys/GGLazyGaugeKey.d.ts.map +1 -0
- package/dist/src/keys/GGLazyGaugeKey.js +25 -0
- package/dist/src/keys/GGLazyGaugeKey.js.map +1 -0
- package/dist/src/metric/GGCounter.d.ts +7 -0
- package/dist/src/metric/GGCounter.d.ts.map +1 -0
- package/dist/src/metric/GGCounter.js +14 -0
- package/dist/src/metric/GGCounter.js.map +1 -0
- package/dist/src/metric/GGGauge.d.ts +9 -0
- package/dist/src/metric/GGGauge.d.ts.map +1 -0
- package/dist/src/metric/GGGauge.js +31 -0
- package/dist/src/metric/GGGauge.js.map +1 -0
- package/dist/src/metric/GGHistogram.d.ts +27 -0
- package/dist/src/metric/GGHistogram.d.ts.map +1 -0
- package/dist/src/metric/GGHistogram.js +41 -0
- package/dist/src/metric/GGHistogram.js.map +1 -0
- package/dist/src/metric/GGLazyGauge.d.ts +20 -0
- package/dist/src/metric/GGLazyGauge.d.ts.map +1 -0
- package/dist/src/metric/GGLazyGauge.js +27 -0
- package/dist/src/metric/GGLazyGauge.js.map +1 -0
- package/dist/src/tsconfig.json +16 -0
- package/dist/testkit/GGMetricsCommands.d.ts +18 -0
- package/dist/testkit/GGMetricsCommands.d.ts.map +1 -0
- package/dist/testkit/GGMetricsCommands.js +77 -0
- package/dist/testkit/GGMetricsCommands.js.map +1 -0
- package/dist/testkit/GGMetricsInterceptor.d.ts +34 -0
- package/dist/testkit/GGMetricsInterceptor.d.ts.map +1 -0
- package/dist/testkit/GGMetricsInterceptor.js +202 -0
- package/dist/testkit/GGMetricsInterceptor.js.map +1 -0
- package/dist/testkit/GGMetricsWith.d.ts +22 -0
- package/dist/testkit/GGMetricsWith.d.ts.map +1 -0
- package/dist/testkit/GGMetricsWith.js +61 -0
- package/dist/testkit/GGMetricsWith.js.map +1 -0
- package/dist/testkit/GGTestMetricsExporter.d.ts +40 -0
- package/dist/testkit/GGTestMetricsExporter.d.ts.map +1 -0
- package/dist/testkit/GGTestMetricsExporter.js +119 -0
- package/dist/testkit/GGTestMetricsExporter.js.map +1 -0
- package/dist/testkit/GGTestSelectorMetrics.d.ts +15 -0
- package/dist/testkit/GGTestSelectorMetrics.d.ts.map +1 -0
- package/dist/testkit/GGTestSelectorMetrics.js +16 -0
- package/dist/testkit/GGTestSelectorMetrics.js.map +1 -0
- package/dist/testkit/index-testkit.d.ts +6 -0
- package/dist/testkit/index-testkit.d.ts.map +1 -0
- package/dist/testkit/index-testkit.js +6 -0
- package/dist/testkit/index-testkit.js.map +1 -0
- package/dist/tsconfig.publish.tsbuildinfo +1 -0
- package/package.json +58 -0
- package/src/GGMetric.ts +124 -0
- package/src/GGMetricKey.ts +38 -0
- package/src/GGMetrics.ts +34 -0
- package/src/GGMetricsDefineStorage.ts +8 -0
- package/src/GGMetricsLoader.ts +21 -0
- package/src/GGMetricsStore.ts +26 -0
- package/src/exporters/GGJsonMetricsExporter.ts +176 -0
- package/src/exporters/GGMetricsExporter.ts +88 -0
- package/src/exporters/GGNestedMetricsExporter.ts +335 -0
- package/src/index-browser.ts +16 -0
- package/src/index-node.ts +21 -0
- package/src/keys/GGCounterKey.ts +29 -0
- package/src/keys/GGGaugeKey.ts +37 -0
- package/src/keys/GGHistogramKey.ts +37 -0
- package/src/keys/GGLazyGaugeKey.ts +36 -0
- package/src/metric/GGCounter.ts +19 -0
- package/src/metric/GGGauge.ts +38 -0
- package/src/metric/GGHistogram.ts +68 -0
- package/src/metric/GGLazyGauge.ts +31 -0
- package/src/tsconfig.json +16 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Grest Games OÜ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# @grest-ts/metrics
|
|
2
|
+
|
|
3
|
+
Type-safe metrics collection library for Grest Framework.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
Type-safe metrics collection library with support for counters, gauges, and histograms.
|
|
8
|
+
|
|
9
|
+
Provides a structured way to define, collect, and export application metrics with:
|
|
10
|
+
|
|
11
|
+
- Prometheus-style metrics (Counter, Gauge, Histogram)
|
|
12
|
+
- Type-safe labels
|
|
13
|
+
- Centralized metric definitions
|
|
14
|
+
- Multiple export formats
|
|
15
|
+
|
|
16
|
+
Type-safe metrics collection library with support for counters, gauges, and histograms.
|
|
17
|
+
|
|
18
|
+
## Quick usage example
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// Define metric keys.
|
|
22
|
+
// This additionally acts as documentation of metrics provided by the application.
|
|
23
|
+
export const AppMetrics = GGMetrics.define('/app/', () => ({
|
|
24
|
+
actions: new GGCounterKey('actions_total', {
|
|
25
|
+
help: 'Total number of actions',
|
|
26
|
+
labelNames: ['type']
|
|
27
|
+
}),
|
|
28
|
+
// ... add more metrics here. All well documented and type safe.
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
// Usage in the runtime.
|
|
32
|
+
AppMetrics.actions.inc(1, {type: "read"}); // labels are typesafe (values are always strings)
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Documentation
|
|
37
|
+
|
|
38
|
+
- [Usage](./README-usage.md) - How to define and collect metrics
|
|
39
|
+
- [Testing](./README-testkit.md) - How to test metric changes with testkit
|
|
40
|
+
- [Extending](./README-extending.md) - How to add custom exporters
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { GGMetricKey } from "./GGMetricKey";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for grouping metrics in nested exporters.
|
|
4
|
+
* - labels: Which labels to use for grouping (must be subset of labelNames)
|
|
5
|
+
* - template: Optional template string for the group key. Use {labelName} for placeholders.
|
|
6
|
+
* Missing values become empty strings. Defaults to values.join(',')
|
|
7
|
+
* Example: "{api}.{method}" produces "MyApi.myMethod"
|
|
8
|
+
*/
|
|
9
|
+
export interface GroupByConfig<TLabels extends GGMetricLabels = {}> {
|
|
10
|
+
labels: readonly (keyof TLabels & string)[];
|
|
11
|
+
template?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface GGMetricOptionsBase {
|
|
14
|
+
help: string;
|
|
15
|
+
maxLabelCombinations?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface GGMetricOptionsWithLabels<TLabels extends GGMetricLabels> {
|
|
18
|
+
help: string;
|
|
19
|
+
maxLabelCombinations?: number;
|
|
20
|
+
labelNames: readonly (keyof TLabels & string)[];
|
|
21
|
+
groupBy?: GroupByConfig<TLabels>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Options for metrics. When TLabels has keys, labelNames is required and must match those keys.
|
|
25
|
+
* Uses {} as "no labels" because keyof {} = never, while keyof Record<string, never> = string.
|
|
26
|
+
*/
|
|
27
|
+
export type GGMetricOptions<TLabels extends GGMetricLabels = {}> = keyof TLabels extends never ? GGMetricOptionsBase : GGMetricOptionsWithLabels<TLabels>;
|
|
28
|
+
export declare abstract class GGMetric<TLabels extends GGMetricLabels = {}, TValue = unknown, TKey extends GGMetricKey<TLabels> = GGMetricKey<TLabels>> {
|
|
29
|
+
readonly key: TKey;
|
|
30
|
+
private readonly values;
|
|
31
|
+
private readonly compiledGetKey;
|
|
32
|
+
constructor(key: TKey);
|
|
33
|
+
private compileGetKey;
|
|
34
|
+
get name(): string;
|
|
35
|
+
reset(): void;
|
|
36
|
+
protected abstract getDefaultValue(): TValue;
|
|
37
|
+
/**
|
|
38
|
+
* Can't throw.
|
|
39
|
+
* Uses AOT-compiled function for fast key generation.
|
|
40
|
+
*/
|
|
41
|
+
protected getKey(labels: TLabels): tMetricKey;
|
|
42
|
+
/**
|
|
43
|
+
* Can't throw.
|
|
44
|
+
*/
|
|
45
|
+
protected getByKey(key: tMetricKey): TValue | undefined;
|
|
46
|
+
protected setByKey(key: tMetricKey, value: TValue): void;
|
|
47
|
+
getValue(...args: LabelsArgs<TLabels>): TValue;
|
|
48
|
+
getValues(): Map<string, TValue>;
|
|
49
|
+
}
|
|
50
|
+
export type tMetricKey = string & {
|
|
51
|
+
tMetricKey: never;
|
|
52
|
+
};
|
|
53
|
+
export type GGMetricLabels = Record<string, string | number | boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* Helper type for labels parameter. Makes labels required when TLabels has keys.
|
|
56
|
+
* - When TLabels = {}, no argument needed
|
|
57
|
+
* - When TLabels has keys, labels argument is required
|
|
58
|
+
*/
|
|
59
|
+
export type LabelsArgs<TLabels extends GGMetricLabels> = keyof TLabels extends never ? [] : [labels: TLabels];
|
|
60
|
+
//# sourceMappingURL=GGMetric.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetric.d.ts","sourceRoot":"","sources":["../../src/GGMetric.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,aAAa,CAAC,OAAO,SAAS,cAAc,GAAG,EAAE;IAC9D,MAAM,EAAE,SAAS,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,yBAAyB,CAAC,OAAO,SAAS,cAAc;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,EAAE,SAAS,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;IAChD,OAAO,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,OAAO,SAAS,cAAc,GAAG,EAAE,IAC3D,MAAM,OAAO,SAAS,KAAK,GACrB,mBAAmB,GACnB,yBAAyB,CAAC,OAAO,CAAC,CAAC;AAE7C,8BAAsB,QAAQ,CAC1B,OAAO,SAAS,cAAc,GAAG,EAAE,EACnC,MAAM,GAAG,OAAO,EAChB,IAAI,SAAS,WAAW,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC;IAGxD,SAAgB,GAAG,EAAE,IAAI,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkC;gBAE9C,GAAG,EAAE,IAAI;IAK5B,OAAO,CAAC,aAAa;IAerB,IAAW,IAAI,IAAI,MAAM,CAExB;IAEM,KAAK,IAAI,IAAI;IAIpB,SAAS,CAAC,QAAQ,CAAC,eAAe,IAAI,MAAM;IAE5C;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,UAAU;IAI7C;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS;IAcvD,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjD,QAAQ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,MAAM;IAI9C,SAAS,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAG1C;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG;IAAE,UAAU,EAAE,KAAK,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEvE;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,OAAO,SAAS,cAAc,IACjD,MAAM,OAAO,SAAS,KAAK,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export class GGMetric {
|
|
2
|
+
key;
|
|
3
|
+
values = new Map();
|
|
4
|
+
compiledGetKey;
|
|
5
|
+
constructor(key) {
|
|
6
|
+
this.key = key;
|
|
7
|
+
this.compiledGetKey = this.compileGetKey();
|
|
8
|
+
}
|
|
9
|
+
compileGetKey() {
|
|
10
|
+
const labelNames = this.key.labelNames;
|
|
11
|
+
if (labelNames.length === 0) {
|
|
12
|
+
return () => '';
|
|
13
|
+
}
|
|
14
|
+
// Build the function body: "name1=" + (l?.name1 ?? "") + ",name2=" + (l?.name2 ?? "")
|
|
15
|
+
let body = 'return ';
|
|
16
|
+
for (let i = 0; i < labelNames.length; i++) {
|
|
17
|
+
const name = labelNames[i];
|
|
18
|
+
if (i > 0)
|
|
19
|
+
body += '+","+';
|
|
20
|
+
body += `"${name}="+(l?.${name}??"")`;
|
|
21
|
+
}
|
|
22
|
+
return new Function('l', body);
|
|
23
|
+
}
|
|
24
|
+
get name() {
|
|
25
|
+
return this.key.name;
|
|
26
|
+
}
|
|
27
|
+
reset() {
|
|
28
|
+
this.values.clear();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Can't throw.
|
|
32
|
+
* Uses AOT-compiled function for fast key generation.
|
|
33
|
+
*/
|
|
34
|
+
getKey(labels) {
|
|
35
|
+
return this.compiledGetKey(labels);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Can't throw.
|
|
39
|
+
*/
|
|
40
|
+
getByKey(key) {
|
|
41
|
+
const value = this.values.get(key);
|
|
42
|
+
if (value === undefined) {
|
|
43
|
+
if (this.values.size >= this.key.maxLabelCombinations) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const defaultValue = this.getDefaultValue();
|
|
47
|
+
this.setByKey(key, defaultValue);
|
|
48
|
+
return defaultValue;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
setByKey(key, value) {
|
|
55
|
+
this.values.set(key, value);
|
|
56
|
+
}
|
|
57
|
+
getValue(...args) {
|
|
58
|
+
return this.getByKey(this.getKey(args[0]));
|
|
59
|
+
}
|
|
60
|
+
getValues() {
|
|
61
|
+
return this.values;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=GGMetric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetric.js","sourceRoot":"","sources":["../../src/GGMetric.ts"],"names":[],"mappings":"AAmCA,MAAM,OAAgB,QAAQ;IAMV,GAAG,CAAO;IACT,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnC,cAAc,CAAkC;IAEjE,YAAmB,GAAS;QACxB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;IAC/C,CAAC;IAEO,aAAa;QACjB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;QACvC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,GAAG,EAAE,CAAC,EAAgB,CAAC;QAClC,CAAC;QACD,sFAAsF;QACtF,IAAI,IAAI,GAAG,SAAS,CAAC;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC;gBAAE,IAAI,IAAI,OAAO,CAAC;YAC3B,IAAI,IAAI,IAAI,IAAI,UAAU,IAAI,OAAO,CAAC;QAC1C,CAAC;QACD,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAoC,CAAC;IACtE,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACzB,CAAC;IAEM,KAAK;QACR,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAID;;;OAGG;IACO,MAAM,CAAC,MAAe;QAC5B,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACO,QAAQ,CAAC,GAAe;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;gBACpD,OAAO,SAAS,CAAC;YACrB,CAAC;YACD,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YAC5C,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YACjC,OAAO,YAAY,CAAC;QACxB,CAAC;aAAM,CAAC;YACJ,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAES,QAAQ,CAAC,GAAe,EAAE,KAAa;QAC7C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAEM,QAAQ,CAAC,GAAG,IAAyB;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC;IAC1D,CAAC;IAEM,SAAS;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;CACJ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { GGMetric, GGMetricLabels, GGMetricOptions, GroupByConfig } from "./GGMetric.js";
|
|
2
|
+
export declare abstract class GGMetricKey<TLabels extends GGMetricLabels = {}, TMetric extends GGMetric<TLabels, any, any> = GGMetric<TLabels, any, any>> {
|
|
3
|
+
readonly root: string;
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly help: string;
|
|
6
|
+
readonly labelNames: readonly string[];
|
|
7
|
+
readonly maxLabelCombinations?: number;
|
|
8
|
+
readonly groupBy?: GroupByConfig<TLabels>;
|
|
9
|
+
protected constructor(name: string, options: GGMetricOptions<TLabels>);
|
|
10
|
+
protected getMetric(): TMetric;
|
|
11
|
+
abstract create(): TMetric;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=GGMetricKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricKey.d.ts","sourceRoot":"","sources":["../../src/GGMetricKey.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAC,MAAM,eAAe,CAAC;AAEvF,8BAAsB,WAAW,CAC7B,OAAO,SAAS,cAAc,GAAG,EAAE,EACnC,OAAO,SAAS,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC;IAGzE,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,SAAgB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9C,SAAgB,OAAO,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAEjD,SAAS,aAAa,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC;IAgBrE,SAAS,CAAC,SAAS,IAAI,OAAO;aAId,MAAM,IAAI,OAAO;CACpC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { GGMetrics } from "./GGMetrics.js";
|
|
2
|
+
import { GG_METRICS } from "./GGMetricsLoader.js";
|
|
3
|
+
export class GGMetricKey {
|
|
4
|
+
root;
|
|
5
|
+
name;
|
|
6
|
+
help;
|
|
7
|
+
labelNames;
|
|
8
|
+
maxLabelCombinations;
|
|
9
|
+
groupBy;
|
|
10
|
+
constructor(name, options) {
|
|
11
|
+
this.root = GGMetrics.getDefinitionContext();
|
|
12
|
+
if (!this.root) {
|
|
13
|
+
throw new Error("Metric key must be created inside GGMetrics.define()");
|
|
14
|
+
}
|
|
15
|
+
this.name = this.root + name;
|
|
16
|
+
this.help = options.help;
|
|
17
|
+
this.labelNames = ('labelNames' in options ? options.labelNames : []);
|
|
18
|
+
this.maxLabelCombinations = options.maxLabelCombinations;
|
|
19
|
+
this.groupBy = ('groupBy' in options ? options.groupBy : undefined);
|
|
20
|
+
Object.freeze(this.labelNames);
|
|
21
|
+
if (this.groupBy) {
|
|
22
|
+
Object.freeze(this.groupBy.labels);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
getMetric() {
|
|
26
|
+
return GG_METRICS.get().get(this);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=GGMetricKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricKey.js","sourceRoot":"","sources":["../../src/GGMetricKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAGhD,MAAM,OAAgB,WAAW;IAKb,IAAI,CAAS;IACb,IAAI,CAAS;IACb,IAAI,CAAS;IACb,UAAU,CAAoB;IAC9B,oBAAoB,CAAU;IAC9B,OAAO,CAA0B;IAEjD,YAAsB,IAAY,EAAE,OAAiC;QACjE,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,oBAAoB,EAAE,CAAC;QAC7C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAwC,CAAC;QAC7G,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAuC,CAAC;QAC1G,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;IACL,CAAC;IAES,SAAS;QACf,OAAO,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAY,CAAC;IACjD,CAAC;CAGJ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type GGMetricsDefinition<T> = T & {
|
|
2
|
+
__isGGMetricsDefinition: never;
|
|
3
|
+
};
|
|
4
|
+
export declare class GGMetrics {
|
|
5
|
+
static define<T>(name: string, define: () => T): GGMetricsDefinition<T>;
|
|
6
|
+
static getDefinitionContext(): string;
|
|
7
|
+
static toJSON(metrics: GGMetricsDefinition<any>): Record<string, unknown>;
|
|
8
|
+
private static collectKeys;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=GGMetrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetrics.d.ts","sourceRoot":"","sources":["../../src/GGMetrics.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,uBAAuB,EAAE,KAAK,CAAA;CAAE,CAAC;AAE5E,qBAAa,SAAS;WAEJ,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC;WAIhE,oBAAoB,IAAI,MAAM;WAI9B,MAAM,CAAC,OAAO,EAAE,mBAAmB,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAMhF,OAAO,CAAC,MAAM,CAAC,WAAW;CAY7B"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { GGMetricKey } from "./GGMetricKey.js";
|
|
2
|
+
import { METRICS_DEFINE_CONTEXT } from "./GGMetricsDefineStorage.js";
|
|
3
|
+
export class GGMetrics {
|
|
4
|
+
static define(name, define) {
|
|
5
|
+
return METRICS_DEFINE_CONTEXT.run(name, define);
|
|
6
|
+
}
|
|
7
|
+
static getDefinitionContext() {
|
|
8
|
+
return METRICS_DEFINE_CONTEXT.getStore();
|
|
9
|
+
}
|
|
10
|
+
static toJSON(metrics) {
|
|
11
|
+
const result = {};
|
|
12
|
+
this.collectKeys(metrics, result);
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
static collectKeys(obj, result) {
|
|
16
|
+
if (obj instanceof GGMetricKey) {
|
|
17
|
+
result[obj.name] = {
|
|
18
|
+
type: obj.constructor.name,
|
|
19
|
+
help: obj.help
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
else if (obj && typeof obj === 'object') {
|
|
23
|
+
for (const value of Object.values(obj)) {
|
|
24
|
+
this.collectKeys(value, result);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=GGMetrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetrics.js","sourceRoot":"","sources":["../../src/GGMetrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAC;AAIhE,MAAM,OAAO,SAAS;IAEX,MAAM,CAAC,MAAM,CAAI,IAAY,EAAE,MAAe;QACjD,OAAO,sBAAsB,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAA2B,CAAA;IAC7E,CAAC;IAEM,MAAM,CAAC,oBAAoB;QAC9B,OAAO,sBAAsB,CAAC,QAAQ,EAAG,CAAA;IAC7C,CAAC;IAEM,MAAM,CAAC,MAAM,CAAC,OAAiC;QAClD,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,MAAM,CAAC,WAAW,CAAC,GAAY,EAAE,MAA+B;QACpE,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG;gBACf,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,IAAI;gBAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;aACjB,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACxC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACpC,CAAC;QACL,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricsDefineStorage.d.ts","sourceRoot":"","sources":["../../src/GGMetricsDefineStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAGzE,eAAO,IAAI,sBAAsB,EAAE,aAAa,CAAC,MAAM,CAA6B,CAAC;AAErF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAExE"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BrowserAsyncStorage } from "@grest-ts/common";
|
|
2
|
+
// Browser-safe by default. Node.js entry replaces with real AsyncLocalStorage.
|
|
3
|
+
export let METRICS_DEFINE_CONTEXT = new BrowserAsyncStorage();
|
|
4
|
+
export function _initMetricsStorage(storage) {
|
|
5
|
+
METRICS_DEFINE_CONTEXT = storage;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=GGMetricsDefineStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricsDefineStorage.js","sourceRoot":"","sources":["../../src/GGMetricsDefineStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAqB,MAAM,kBAAkB,CAAC;AAEzE,+EAA+E;AAC/E,MAAM,CAAC,IAAI,sBAAsB,GAA0B,IAAI,mBAAmB,EAAE,CAAC;AAErF,MAAM,UAAU,mBAAmB,CAAC,OAA8B;IAC9D,sBAAsB,GAAG,OAAO,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GGMetricsStore } from "./GGMetricsStore";
|
|
2
|
+
import { GGLocatorKey } from "@grest-ts/locator";
|
|
3
|
+
export declare const GG_METRICS: GGLocatorKey<GGMetricsStore>;
|
|
4
|
+
export declare class GGMetricsLoader {
|
|
5
|
+
private readonly store;
|
|
6
|
+
constructor(store?: GGMetricsStore);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=GGMetricsLoader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricsLoader.d.ts","sourceRoot":"","sources":["../../src/GGMetricsLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAY,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAEhF,eAAO,MAAM,UAAU,8BAAgD,CAAC;AAExE,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;gBAE3B,KAAK,CAAC,EAAE,cAAc;CAWrC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { GGMetricsStore } from "./GGMetricsStore.js";
|
|
2
|
+
import { GGLocator, GGLocatorKey, GGLocatorServiceType } from "@grest-ts/locator";
|
|
3
|
+
export const GG_METRICS = new GGLocatorKey("GGMetrics");
|
|
4
|
+
export class GGMetricsLoader {
|
|
5
|
+
store;
|
|
6
|
+
constructor(store) {
|
|
7
|
+
this.store = store ?? new GGMetricsStore();
|
|
8
|
+
GGLocator.getScope().setWithLifecycle(GG_METRICS, this.store, {
|
|
9
|
+
type: GGLocatorServiceType.CONFIG + 1,
|
|
10
|
+
start: async () => {
|
|
11
|
+
},
|
|
12
|
+
teardown: async () => {
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=GGMetricsLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricsLoader.js","sourceRoot":"","sources":["../../src/GGMetricsLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAC,SAAS,EAAE,YAAY,EAAE,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAEhF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,YAAY,CAAiB,WAAW,CAAC,CAAC;AAExE,MAAM,OAAO,eAAe;IAEP,KAAK,CAAiB;IAEvC,YAAY,KAAsB;QAC9B,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,IAAI,cAAc,EAAE,CAAC;QAE3C,SAAS,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE;YAC1D,IAAI,EAAE,oBAAoB,CAAC,MAAM,GAAG,CAAC;YACrC,KAAK,EAAE,KAAK,IAAI,EAAE;YAClB,CAAC;YACD,QAAQ,EAAE,KAAK,IAAI,EAAE;YACrB,CAAC;SACJ,CAAC,CAAA;IACN,CAAC;CACJ"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { GGMetric, GGMetricLabels } from "./GGMetric.js";
|
|
2
|
+
import { GGMetricKey } from "./GGMetricKey.js";
|
|
3
|
+
export declare class GGMetricsStore {
|
|
4
|
+
private readonly metrics;
|
|
5
|
+
get<TLabel extends GGMetricLabels>(key: GGMetricKey<TLabel>): GGMetric<TLabel>;
|
|
6
|
+
getAllMetrics(): IterableIterator<GGMetric<any>>;
|
|
7
|
+
reset(): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=GGMetricsStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricsStore.d.ts","sourceRoot":"","sources":["../../src/GGMetricsStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAC,MAAM,eAAe,CAAC;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAE7C,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAErD,GAAG,CAAC,MAAM,SAAS,cAAc,EAAE,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;IAS9E,aAAa,IAAI,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAIhD,KAAK,IAAI,IAAI;CAKvB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class GGMetricsStore {
|
|
2
|
+
metrics = new Map();
|
|
3
|
+
get(key) {
|
|
4
|
+
let metric = this.metrics.get(key.name);
|
|
5
|
+
if (!metric) {
|
|
6
|
+
metric = key.create();
|
|
7
|
+
this.metrics.set(key.name, metric);
|
|
8
|
+
}
|
|
9
|
+
return metric;
|
|
10
|
+
}
|
|
11
|
+
getAllMetrics() {
|
|
12
|
+
return this.metrics.values();
|
|
13
|
+
}
|
|
14
|
+
reset() {
|
|
15
|
+
for (const metric of this.metrics.values()) {
|
|
16
|
+
metric.reset();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=GGMetricsStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricsStore.js","sourceRoot":"","sources":["../../src/GGMetricsStore.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,cAAc;IAEN,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAErD,GAAG,CAAgC,GAAwB;QAC9D,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEM,aAAa;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK;QACR,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { GGMetric } from "../GGMetric.js";
|
|
2
|
+
import { GGMetricsExporter, ExporterConfig } from "./GGMetricsExporter.js";
|
|
3
|
+
export type JsonMetricConverter = (metric: GGMetric<any>, exporter: GGJsonMetricsExporter) => JsonMetric;
|
|
4
|
+
export declare class GGJsonMetricsExporter extends GGMetricsExporter<JsonMetricsOutput> {
|
|
5
|
+
private static converters;
|
|
6
|
+
/**
|
|
7
|
+
* Register a converter for a custom metric type.
|
|
8
|
+
*/
|
|
9
|
+
static registerConverter(metricClass: Function, converter: JsonMetricConverter): void;
|
|
10
|
+
constructor(config?: ExporterConfig);
|
|
11
|
+
getMetrics(): JsonMetricsOutput;
|
|
12
|
+
private convertMetric;
|
|
13
|
+
/**
|
|
14
|
+
* Parse a label key string into a labels object.
|
|
15
|
+
* Exposed for use by converters.
|
|
16
|
+
*/
|
|
17
|
+
parseLabels(labelKey: string): Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
export interface JsonMetricValue {
|
|
20
|
+
labels: Record<string, string>;
|
|
21
|
+
value: number | JsonHistogramValue;
|
|
22
|
+
}
|
|
23
|
+
export interface JsonHistogramValue {
|
|
24
|
+
count: number;
|
|
25
|
+
sum: number;
|
|
26
|
+
avg: number;
|
|
27
|
+
min: number;
|
|
28
|
+
max: number;
|
|
29
|
+
buckets: Record<string, number>;
|
|
30
|
+
}
|
|
31
|
+
export interface JsonMetric {
|
|
32
|
+
name: string;
|
|
33
|
+
type: string;
|
|
34
|
+
help: string;
|
|
35
|
+
values: JsonMetricValue[];
|
|
36
|
+
}
|
|
37
|
+
export interface JsonMetricsOutput {
|
|
38
|
+
timestamp: number;
|
|
39
|
+
metrics: Record<string, JsonMetric>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=GGJsonMetricsExporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGJsonMetricsExporter.d.ts","sourceRoot":"","sources":["../../../src/exporters/GGJsonMetricsExporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAKxC,OAAO,EAAC,iBAAiB,EAAE,cAAc,EAAC,MAAM,wBAAwB,CAAC;AAEzE,MAAM,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,qBAAqB,KAAK,UAAU,CAAC;AAEzG,qBAAa,qBAAsB,SAAQ,iBAAiB,CAAC,iBAAiB,CAAC;IAG3E,OAAO,CAAC,MAAM,CAAC,UAAU,CAA4C;IASrE;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,mBAAmB,GAAG,IAAI;gBAIzE,MAAM,GAAE,cAAmB;IAIvC,UAAU,IAAI,iBAAiB;IAa/B,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAYxD;AAkFD,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACvC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { GGCounter } from "../metric/GGCounter.js";
|
|
2
|
+
import { GGGauge } from "../metric/GGGauge.js";
|
|
3
|
+
import { GGLazyGauge } from "../metric/GGLazyGauge.js";
|
|
4
|
+
import { GGHistogram } from "../metric/GGHistogram.js";
|
|
5
|
+
import { GGMetricsExporter } from "./GGMetricsExporter.js";
|
|
6
|
+
export class GGJsonMetricsExporter extends GGMetricsExporter {
|
|
7
|
+
// Static map for extensibility - register converters for new metric types
|
|
8
|
+
static converters = new Map();
|
|
9
|
+
static {
|
|
10
|
+
GGJsonMetricsExporter.registerConverter(GGCounter, convertCounter);
|
|
11
|
+
GGJsonMetricsExporter.registerConverter(GGGauge, convertGauge);
|
|
12
|
+
GGJsonMetricsExporter.registerConverter(GGLazyGauge, convertLazyGauge);
|
|
13
|
+
GGJsonMetricsExporter.registerConverter(GGHistogram, convertHistogram);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Register a converter for a custom metric type.
|
|
17
|
+
*/
|
|
18
|
+
static registerConverter(metricClass, converter) {
|
|
19
|
+
GGJsonMetricsExporter.converters.set(metricClass, converter);
|
|
20
|
+
}
|
|
21
|
+
constructor(config = {}) {
|
|
22
|
+
super(config);
|
|
23
|
+
}
|
|
24
|
+
getMetrics() {
|
|
25
|
+
const output = {
|
|
26
|
+
timestamp: Date.now(),
|
|
27
|
+
metrics: {}
|
|
28
|
+
};
|
|
29
|
+
for (const metric of this.getFilteredMetrics()) {
|
|
30
|
+
output.metrics[metric.name] = this.convertMetric(metric);
|
|
31
|
+
}
|
|
32
|
+
return output;
|
|
33
|
+
}
|
|
34
|
+
convertMetric(metric) {
|
|
35
|
+
const converter = GGJsonMetricsExporter.converters.get(metric.constructor);
|
|
36
|
+
if (!converter) {
|
|
37
|
+
throw new Error(`No converter registered for metric type: ${metric.constructor.name}`);
|
|
38
|
+
}
|
|
39
|
+
return converter(metric, this);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parse a label key string into a labels object.
|
|
43
|
+
* Exposed for use by converters.
|
|
44
|
+
*/
|
|
45
|
+
parseLabels(labelKey) {
|
|
46
|
+
if (!labelKey)
|
|
47
|
+
return {};
|
|
48
|
+
const labels = {};
|
|
49
|
+
const parts = labelKey.split(',');
|
|
50
|
+
for (const part of parts) {
|
|
51
|
+
const [key, val] = part.split('=');
|
|
52
|
+
if (key && val !== undefined) {
|
|
53
|
+
labels[key] = val;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return labels;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Built-in converters
|
|
60
|
+
function convertCounter(metric, exporter) {
|
|
61
|
+
const values = [];
|
|
62
|
+
for (const [labelKey, value] of metric.getValues()) {
|
|
63
|
+
values.push({
|
|
64
|
+
labels: exporter.parseLabels(labelKey),
|
|
65
|
+
value
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
name: metric.name,
|
|
70
|
+
type: 'counter',
|
|
71
|
+
help: metric.key.help,
|
|
72
|
+
values
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function convertGauge(metric, exporter) {
|
|
76
|
+
const values = [];
|
|
77
|
+
for (const [labelKey, value] of metric.getValues()) {
|
|
78
|
+
values.push({
|
|
79
|
+
labels: exporter.parseLabels(labelKey),
|
|
80
|
+
value
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
name: metric.name,
|
|
85
|
+
type: 'gauge',
|
|
86
|
+
help: metric.key.help,
|
|
87
|
+
values
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function convertLazyGauge(metric, exporter) {
|
|
91
|
+
// Lazy gauge computes value on read - no labels
|
|
92
|
+
return {
|
|
93
|
+
name: metric.name,
|
|
94
|
+
type: 'gauge',
|
|
95
|
+
help: metric.key.help,
|
|
96
|
+
values: [{
|
|
97
|
+
labels: {},
|
|
98
|
+
value: metric.getValue()
|
|
99
|
+
}]
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function convertHistogram(metric, exporter) {
|
|
103
|
+
const values = [];
|
|
104
|
+
const buckets = metric.getBuckets();
|
|
105
|
+
for (const [labelKey, data] of metric.getValues()) {
|
|
106
|
+
const bucketObj = {};
|
|
107
|
+
for (let i = 0; i < buckets.length; i++) {
|
|
108
|
+
bucketObj[String(buckets[i])] = data.values[i] ?? 0;
|
|
109
|
+
}
|
|
110
|
+
values.push({
|
|
111
|
+
labels: exporter.parseLabels(labelKey),
|
|
112
|
+
value: {
|
|
113
|
+
count: data.count,
|
|
114
|
+
sum: data.sum,
|
|
115
|
+
avg: data.count > 0 ? data.sum / data.count : 0,
|
|
116
|
+
min: data.min === Infinity ? 0 : data.min,
|
|
117
|
+
max: data.max === -Infinity ? 0 : data.max,
|
|
118
|
+
buckets: bucketObj
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
name: metric.name,
|
|
124
|
+
type: 'histogram',
|
|
125
|
+
help: metric.key.help,
|
|
126
|
+
values
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=GGJsonMetricsExporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGJsonMetricsExporter.js","sourceRoot":"","sources":["../../../src/exporters/GGJsonMetricsExporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { GGMetricsStore } from "../GGMetricsStore.js";
|
|
2
|
+
import { GGMetric } from "../GGMetric.js";
|
|
3
|
+
export interface ExporterConfig {
|
|
4
|
+
store?: GGMetricsStore;
|
|
5
|
+
include?: unknown[];
|
|
6
|
+
exclude?: unknown[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Abstract base class for metrics exporters.
|
|
10
|
+
* Handles config parsing, metric filtering, and key discovery.
|
|
11
|
+
*/
|
|
12
|
+
export declare abstract class GGMetricsExporter<TOutput> {
|
|
13
|
+
protected readonly store: GGMetricsStore;
|
|
14
|
+
private readonly includeKeys?;
|
|
15
|
+
private readonly excludeKeys?;
|
|
16
|
+
constructor(config?: ExporterConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Discover all GGMetricKey instances from an array of objects.
|
|
19
|
+
* Objects can be individual keys, or nested structures containing keys.
|
|
20
|
+
*/
|
|
21
|
+
private discoverKeys;
|
|
22
|
+
private discoverKeysRecursive;
|
|
23
|
+
/**
|
|
24
|
+
* Check if a metric should be included in the export.
|
|
25
|
+
* Exclude takes precedence over include.
|
|
26
|
+
*/
|
|
27
|
+
protected shouldIncludeMetric(metric: GGMetric<any>): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Get all metrics that pass the include/exclude filters.
|
|
30
|
+
*/
|
|
31
|
+
protected getFilteredMetrics(): Iterable<GGMetric<any>>;
|
|
32
|
+
/**
|
|
33
|
+
* Export metrics to the output format.
|
|
34
|
+
*/
|
|
35
|
+
abstract getMetrics(): TOutput;
|
|
36
|
+
/**
|
|
37
|
+
* Export metrics as a JSON string.
|
|
38
|
+
*/
|
|
39
|
+
getMetricsString(): string;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=GGMetricsExporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGMetricsExporter.d.ts","sourceRoot":"","sources":["../../../src/exporters/GGMetricsExporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAGxC,MAAM,WAAW,cAAc;IAC3B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,8BAAsB,iBAAiB,CAAC,OAAO;IAC3C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAwB;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAwB;gBAEzC,MAAM,GAAE,cAAmB;IAMvC;;;OAGG;IACH,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,qBAAqB;IAU7B;;;OAGG;IACH,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,OAAO;IAa7D;;OAEG;IACH,SAAS,CAAE,kBAAkB,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAQxD;;OAEG;IACH,QAAQ,CAAC,UAAU,IAAI,OAAO;IAE9B;;OAEG;IACH,gBAAgB,IAAI,MAAM;CAG7B"}
|