@twin.org/telemetry-service 0.0.3-next.10 → 0.0.3-next.12
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/dist/es/metricsCollectorService.js +20 -5
- package/dist/es/metricsCollectorService.js.map +1 -1
- package/dist/es/models/IMetricsCollectorServiceConstructorOptions.js.map +1 -1
- package/dist/es/models/ITelemetryServiceConstructorOptions.js.map +1 -1
- package/dist/es/telemetryService.js +18 -4
- package/dist/es/telemetryService.js.map +1 -1
- package/dist/types/metricsCollectorService.d.ts +0 -4
- package/dist/types/models/IMetricsCollectorServiceConstructorOptions.d.ts +5 -0
- package/dist/types/models/ITelemetryServiceConstructorOptions.d.ts +5 -0
- package/docs/changelog.md +28 -0
- package/docs/reference/interfaces/IMetricsCollectorServiceConstructorOptions.md +14 -0
- package/docs/reference/interfaces/ITelemetryServiceConstructorOptions.md +14 -0
- package/package.json +5 -4
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
-
import { BaseError, ComponentFactory } from "@twin.org/core";
|
|
1
|
+
import { BaseError, ComponentFactory, Is } from "@twin.org/core";
|
|
4
2
|
import { MetricsProducerFactory } from "@twin.org/telemetry-models";
|
|
5
3
|
/**
|
|
6
4
|
* Collects metrics from registered producers at a fixed interval.
|
|
@@ -12,8 +10,14 @@ export class MetricsCollectorService {
|
|
|
12
10
|
static CLASS_NAME = "MetricsCollectorService";
|
|
13
11
|
/**
|
|
14
12
|
* Resolved logging component for internal use.
|
|
13
|
+
* @internal
|
|
15
14
|
*/
|
|
16
15
|
_loggingComponent;
|
|
16
|
+
/**
|
|
17
|
+
* Tenant component if configured.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
_tenantComponent;
|
|
17
21
|
/**
|
|
18
22
|
* Polling interval in milliseconds.
|
|
19
23
|
* @internal
|
|
@@ -35,6 +39,7 @@ export class MetricsCollectorService {
|
|
|
35
39
|
*/
|
|
36
40
|
constructor(options) {
|
|
37
41
|
this._loggingComponent = ComponentFactory.getIfExists(options?.loggingComponentType ?? "logging");
|
|
42
|
+
this._tenantComponent = ComponentFactory.getIfExists(options?.tenantComponentType ?? "tenant");
|
|
38
43
|
const intervalMs = options?.config?.intervalMs ?? 60_000;
|
|
39
44
|
if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
|
|
40
45
|
throw new RangeError(`intervalMs must be a finite positive number, got ${intervalMs}`);
|
|
@@ -60,7 +65,12 @@ export class MetricsCollectorService {
|
|
|
60
65
|
const names = MetricsProducerFactory.names();
|
|
61
66
|
const producers = names.map(name => MetricsProducerFactory.get(name));
|
|
62
67
|
for (const producer of producers) {
|
|
63
|
-
|
|
68
|
+
if (!Is.empty(this._tenantComponent)) {
|
|
69
|
+
await this._tenantComponent.runPerTenant(async () => producer.register());
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
await producer.register();
|
|
73
|
+
}
|
|
64
74
|
}
|
|
65
75
|
await this.tick();
|
|
66
76
|
}
|
|
@@ -83,7 +93,12 @@ export class MetricsCollectorService {
|
|
|
83
93
|
const producers = names.map(name => MetricsProducerFactory.get(name));
|
|
84
94
|
for (const producer of producers) {
|
|
85
95
|
try {
|
|
86
|
-
|
|
96
|
+
if (!Is.empty(this._tenantComponent)) {
|
|
97
|
+
await this._tenantComponent.runPerTenant(async () => producer.collect());
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
await producer.collect();
|
|
101
|
+
}
|
|
87
102
|
}
|
|
88
103
|
catch (err) {
|
|
89
104
|
await this._loggingComponent?.log({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metricsCollectorService.js","sourceRoot":"","sources":["../../src/metricsCollectorService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metricsCollectorService.js","sourceRoot":"","sources":["../../src/metricsCollectorService.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEN,sBAAsB,EACtB,MAAM,4BAA4B,CAAC;AAGpC;;GAEG;AACH,MAAM,OAAO,uBAAuB;IACnC;;OAEG;IACI,MAAM,CAAU,UAAU,6BAA6C;IAE9E;;;OAGG;IACc,iBAAiB,CAAqB;IAEvD;;;OAGG;IACc,gBAAgB,CAAoB;IAErD;;;OAGG;IACc,WAAW,CAAS;IAErC;;;OAGG;IACK,MAAM,CAAuD;IAErE;;;OAGG;IACK,QAAQ,CAAU;IAE1B;;;OAGG;IACH,YAAY,OAAoD;QAC/D,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,WAAW,CACpD,OAAO,EAAE,oBAAoB,IAAI,SAAS,CAC1C,CAAC;QACF,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,WAAW,CACnD,OAAO,EAAE,mBAAmB,IAAI,QAAQ,CACxC,CAAC;QAEF,MAAM,UAAU,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,IAAI,MAAM,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,UAAU,CAAC,oDAAoD,UAAU,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,uBAAuB,CAAC,UAAU,CAAC;IAC3C,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,KAAK;QACjB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO;QACR,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAEtE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3E,CAAC;iBAAM,CAAC;gBACP,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC3B,CAAC;QACF,CAAC;QAED,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,IAAI;QAChB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACzB,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,IAAI;QAChB,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAEtE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC;gBACJ,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;oBACtC,MAAM,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC1E,CAAC;qBAAM,CAAC;oBACP,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAC1B,CAAC;YACF,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,MAAM,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAC;oBACjC,MAAM,EAAE,uBAAuB,CAAC,UAAU;oBAC1C,KAAK,EAAE,OAAO;oBACd,OAAO,EAAE,0BAA0B;oBACnC,IAAI,EAAE;wBACL,QAAQ,EAAE,QAAQ,CAAC,SAAS,EAAE;qBAC9B;oBACD,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC;iBAC/B,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;IACrB,CAAC;IAED;;;OAGG;IACK,YAAY;QACnB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;gBAC9C,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QACtB,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenantComponent } from \"@twin.org/api-models\";\nimport { BaseError, ComponentFactory, Is } from \"@twin.org/core\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\ttype IMetricsCollectorComponent,\n\tMetricsProducerFactory\n} from \"@twin.org/telemetry-models\";\nimport type { IMetricsCollectorServiceConstructorOptions } from \"./models/IMetricsCollectorServiceConstructorOptions.js\";\n\n/**\n * Collects metrics from registered producers at a fixed interval.\n */\nexport class MetricsCollectorService implements IMetricsCollectorComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MetricsCollectorService>();\n\n\t/**\n\t * Resolved logging component for internal use.\n\t * @internal\n\t */\n\tprivate readonly _loggingComponent?: ILoggingComponent;\n\n\t/**\n\t * Tenant component if configured.\n\t * @internal\n\t */\n\tprivate readonly _tenantComponent?: ITenantComponent;\n\n\t/**\n\t * Polling interval in milliseconds.\n\t * @internal\n\t */\n\tprivate readonly _intervalMs: number;\n\n\t/**\n\t * Pending scheduled tick handle.\n\t * @internal\n\t */\n\tprivate _timer: ReturnType<typeof globalThis.setTimeout> | undefined;\n\n\t/**\n\t * Whether the service is currently running.\n\t * @internal\n\t */\n\tprivate _running: boolean;\n\n\t/**\n\t * Create a new instance of MetricsCollectorService.\n\t * @param options The options for the service.\n\t */\n\tconstructor(options?: IMetricsCollectorServiceConstructorOptions) {\n\t\tthis._loggingComponent = ComponentFactory.getIfExists<ILoggingComponent>(\n\t\t\toptions?.loggingComponentType ?? \"logging\"\n\t\t);\n\t\tthis._tenantComponent = ComponentFactory.getIfExists<ITenantComponent>(\n\t\t\toptions?.tenantComponentType ?? \"tenant\"\n\t\t);\n\n\t\tconst intervalMs = options?.config?.intervalMs ?? 60_000;\n\t\tif (!Number.isFinite(intervalMs) || intervalMs <= 0) {\n\t\t\tthrow new RangeError(`intervalMs must be a finite positive number, got ${intervalMs}`);\n\t\t}\n\t\tthis._intervalMs = intervalMs;\n\t\tthis._running = false;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MetricsCollectorService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Start the service: register all producers and begin the polling cycle.\n\t */\n\tpublic async start(): Promise<void> {\n\t\tif (this._running) {\n\t\t\treturn;\n\t\t}\n\t\tthis._running = true;\n\n\t\tconst names = MetricsProducerFactory.names();\n\t\tconst producers = names.map(name => MetricsProducerFactory.get(name));\n\n\t\tfor (const producer of producers) {\n\t\t\tif (!Is.empty(this._tenantComponent)) {\n\t\t\t\tawait this._tenantComponent.runPerTenant(async () => producer.register());\n\t\t\t} else {\n\t\t\t\tawait producer.register();\n\t\t\t}\n\t\t}\n\n\t\tawait this.tick();\n\t}\n\n\t/**\n\t * Stop the service and cancel the pending timer.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tthis._running = false;\n\t\tif (this._timer !== undefined) {\n\t\t\tglobalThis.clearTimeout(this._timer);\n\t\t\tthis._timer = undefined;\n\t\t}\n\t}\n\n\t/**\n\t * One collection cycle across all registered producers.\n\t * Public so tests can drive it deterministically.\n\t */\n\tpublic async tick(): Promise<void> {\n\t\tconst names = MetricsProducerFactory.names();\n\t\tconst producers = names.map(name => MetricsProducerFactory.get(name));\n\n\t\tfor (const producer of producers) {\n\t\t\ttry {\n\t\t\t\tif (!Is.empty(this._tenantComponent)) {\n\t\t\t\t\tawait this._tenantComponent.runPerTenant(async () => producer.collect());\n\t\t\t\t} else {\n\t\t\t\t\tawait producer.collect();\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tawait this._loggingComponent?.log({\n\t\t\t\t\tsource: MetricsCollectorService.CLASS_NAME,\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tmessage: \"producerCollectionFailed\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tproducer: producer.className()\n\t\t\t\t\t},\n\t\t\t\t\terror: BaseError.fromError(err)\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis.scheduleNext();\n\t}\n\n\t/**\n\t * Schedule the next tick. Re-schedules itself after each tick completes.\n\t * @internal\n\t */\n\tprivate scheduleNext(): void {\n\t\tif (this._running) {\n\t\t\tthis._timer = globalThis.setTimeout(async () => {\n\t\t\t\tawait this.tick();\n\t\t\t}, this._intervalMs);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IMetricsCollectorServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IMetricsCollectorServiceConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IMetricsCollectorServiceConfig } from \"./IMetricsCollectorServiceConfig.js\";\n\n/**\n * The options for the metrics collector service constructor.\n */\nexport interface IMetricsCollectorServiceConstructorOptions {\n\t/**\n\t * The type of the logging component to use.\n\t * @default logging\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * The configuration options for the metrics collector service.\n\t */\n\tconfig?: IMetricsCollectorServiceConfig;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"IMetricsCollectorServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IMetricsCollectorServiceConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IMetricsCollectorServiceConfig } from \"./IMetricsCollectorServiceConfig.js\";\n\n/**\n * The options for the metrics collector service constructor.\n */\nexport interface IMetricsCollectorServiceConstructorOptions {\n\t/**\n\t * The type of the logging component to use.\n\t * @default logging\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * The type of the tenant component to use for partitioned producers.\n\t * @default tenant\n\t */\n\ttenantComponentType?: string;\n\n\t/**\n\t * The configuration options for the metrics collector service.\n\t */\n\tconfig?: IMetricsCollectorServiceConfig;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ITelemetryServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ITelemetryServiceConstructorOptions.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The options for the telemetry service constructor.\n */\nexport interface ITelemetryServiceConstructorOptions {\n\t/**\n\t * The type of the telemetry connector to use.\n\t * @default telemetry\n\t */\n\ttelemetryConnectorType?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ITelemetryServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ITelemetryServiceConstructorOptions.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The options for the telemetry service constructor.\n */\nexport interface ITelemetryServiceConstructorOptions {\n\t/**\n\t * The type of the telemetry connector to use.\n\t * @default telemetry\n\t */\n\ttelemetryConnectorType?: string;\n\n\t/**\n\t * The type of the tenant component to use for partition iteration.\n\t * @default tenant\n\t */\n\ttenantComponentType?: string;\n}\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { Guards } from "@twin.org/core";
|
|
1
|
+
import { ContextIdKeys, ContextIdStore } from "@twin.org/context";
|
|
2
|
+
import { ComponentFactory, Guards, Is } from "@twin.org/core";
|
|
4
3
|
import { TelemetryConnectorFactory } from "@twin.org/telemetry-models";
|
|
5
4
|
/**
|
|
6
5
|
* Service for performing telemetry operations to a connector.
|
|
@@ -15,12 +14,18 @@ export class TelemetryService {
|
|
|
15
14
|
* @internal
|
|
16
15
|
*/
|
|
17
16
|
_telemetryConnector;
|
|
17
|
+
/**
|
|
18
|
+
* Tenant component for internal use, if configured.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
_tenantComponent;
|
|
18
22
|
/**
|
|
19
23
|
* Create a new instance of TelemetryService.
|
|
20
24
|
* @param options The options for the connector.
|
|
21
25
|
*/
|
|
22
26
|
constructor(options) {
|
|
23
27
|
this._telemetryConnector = TelemetryConnectorFactory.get(options?.telemetryConnectorType ?? "telemetry");
|
|
28
|
+
this._tenantComponent = ComponentFactory.getIfExists(options?.tenantComponentType ?? "tenant");
|
|
24
29
|
}
|
|
25
30
|
/**
|
|
26
31
|
* Returns the class name of the component.
|
|
@@ -36,7 +41,16 @@ export class TelemetryService {
|
|
|
36
41
|
*/
|
|
37
42
|
async createMetric(metric) {
|
|
38
43
|
Guards.object(TelemetryService.CLASS_NAME, "metric", metric);
|
|
39
|
-
|
|
44
|
+
// Create metric must be run once per tenant in multi tenant mode
|
|
45
|
+
// if the tenant id is not already set in the context
|
|
46
|
+
// as these are most likely startup metrics run outside of a tenant context
|
|
47
|
+
const contextIds = (await ContextIdStore.getContextIds()) ?? {};
|
|
48
|
+
if (Is.stringValue(contextIds[ContextIdKeys.Tenant]) || Is.empty(this._tenantComponent)) {
|
|
49
|
+
await this._telemetryConnector.createMetric(metric);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
await this._tenantComponent.runPerTenant(async () => this._telemetryConnector.createMetric(metric));
|
|
53
|
+
}
|
|
40
54
|
}
|
|
41
55
|
/**
|
|
42
56
|
* Get the metric details and it's most recent value.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetryService.js","sourceRoot":"","sources":["../../src/telemetryService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"telemetryService.js","sourceRoot":"","sources":["../../src/telemetryService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenantComponent } from \"@twin.org/api-models\";\nimport { ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { ComponentFactory, Guards, Is } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\tTelemetryConnectorFactory,\n\ttype ITelemetryComponent,\n\ttype ITelemetryConnector,\n\ttype ITelemetryMetric,\n\ttype ITelemetryMetricValue,\n\ttype MetricCounterOperation,\n\ttype MetricType\n} from \"@twin.org/telemetry-models\";\nimport type { ITelemetryServiceConstructorOptions } from \"./models/ITelemetryServiceConstructorOptions.js\";\n\n/**\n * Service for performing telemetry operations to a connector.\n */\nexport class TelemetryService implements ITelemetryComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TelemetryService>();\n\n\t/**\n\t * Telemetry connector used by the service.\n\t * @internal\n\t */\n\tprivate readonly _telemetryConnector: ITelemetryConnector;\n\n\t/**\n\t * Tenant component for internal use, if configured.\n\t * @internal\n\t */\n\tprivate readonly _tenantComponent?: ITenantComponent;\n\n\t/**\n\t * Create a new instance of TelemetryService.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: ITelemetryServiceConstructorOptions) {\n\t\tthis._telemetryConnector = TelemetryConnectorFactory.get(\n\t\t\toptions?.telemetryConnectorType ?? \"telemetry\"\n\t\t);\n\t\tthis._tenantComponent = ComponentFactory.getIfExists<ITenantComponent>(\n\t\t\toptions?.tenantComponentType ?? \"tenant\"\n\t\t);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn TelemetryService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Create a new metric.\n\t * @param metric The metric details.\n\t * @returns Nothing.\n\t */\n\tpublic async createMetric(metric: ITelemetryMetric): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(TelemetryService.CLASS_NAME, nameof(metric), metric);\n\n\t\t// Create metric must be run once per tenant in multi tenant mode\n\t\t// if the tenant id is not already set in the context\n\t\t// as these are most likely startup metrics run outside of a tenant context\n\t\tconst contextIds = (await ContextIdStore.getContextIds()) ?? {};\n\t\tif (Is.stringValue(contextIds[ContextIdKeys.Tenant]) || Is.empty(this._tenantComponent)) {\n\t\t\tawait this._telemetryConnector.createMetric(metric);\n\t\t} else {\n\t\t\tawait this._tenantComponent.runPerTenant(async () =>\n\t\t\t\tthis._telemetryConnector.createMetric(metric)\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Get the metric details and it's most recent value.\n\t * @param id The metric id.\n\t * @returns The metric details and it's most recent value.\n\t */\n\tpublic async getMetric(id: string): Promise<{\n\t\tmetric: ITelemetryMetric;\n\t\tvalue: ITelemetryMetricValue;\n\t}> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\treturn this._telemetryConnector.getMetric(id);\n\t}\n\n\t/**\n\t * Update metric.\n\t * @param metric The metric details.\n\t * @returns Nothing.\n\t */\n\tpublic async updateMetric(metric: Omit<ITelemetryMetric, \"type\">): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(TelemetryService.CLASS_NAME, nameof(metric), metric);\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(metric.id), metric.id);\n\t\treturn this._telemetryConnector.updateMetric(metric);\n\t}\n\n\t/**\n\t * Add a metric value.\n\t * @param id The id of the metric.\n\t * @param value The value for the add operation.\n\t * @param customData The custom data for the add operation.\n\t * @returns The created metric value id.\n\t */\n\tpublic async addMetricValue(\n\t\tid: string,\n\t\tvalue: MetricCounterOperation | number,\n\t\tcustomData?: { [key: string]: unknown }\n\t): Promise<string> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\tGuards.defined(TelemetryService.CLASS_NAME, nameof(value), value);\n\t\treturn this._telemetryConnector.addMetricValue(id, value, customData);\n\t}\n\n\t/**\n\t * Remove metric.\n\t * @param id The id of the metric.\n\t * @returns Nothing.\n\t */\n\tpublic async removeMetric(id: string): Promise<void> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\treturn this._telemetryConnector.removeMetric(id);\n\t}\n\n\t/**\n\t * Query the metrics.\n\t * @param type The type of the metric.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit Limit the number of entities to return.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t * @throws NotImplementedError if the implementation does not support retrieval.\n\t */\n\tpublic async query(\n\t\ttype?: MetricType,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The metrics.\n\t\t */\n\t\tentities: ITelemetryMetric[];\n\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more values.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\treturn this._telemetryConnector.query(type, cursor, limit);\n\t}\n\n\t/**\n\t * Query the metric values.\n\t * @param id The id of the metric.\n\t * @param timeStart The inclusive time as the start of the metric entries.\n\t * @param timeEnd The inclusive time as the end of the metric entries.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit Limit the number of entities to return.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t * @throws NotImplementedError if the implementation does not support retrieval.\n\t */\n\tpublic async queryValues(\n\t\tid: string,\n\t\ttimeStart?: number,\n\t\ttimeEnd?: number,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The metric details.\n\t\t */\n\t\tmetric: ITelemetryMetric;\n\t\t/**\n\t\t * The values for the metric.\n\t\t */\n\t\tentities: ITelemetryMetricValue[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more values.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\treturn this._telemetryConnector.queryValues(id, timeStart, timeEnd, cursor, limit);\n\t}\n}\n"]}
|
|
@@ -8,10 +8,6 @@ export declare class MetricsCollectorService implements IMetricsCollectorCompone
|
|
|
8
8
|
* Runtime name for the class.
|
|
9
9
|
*/
|
|
10
10
|
static readonly CLASS_NAME: string;
|
|
11
|
-
/**
|
|
12
|
-
* Resolved logging component for internal use.
|
|
13
|
-
*/
|
|
14
|
-
private readonly _loggingComponent?;
|
|
15
11
|
/**
|
|
16
12
|
* Create a new instance of MetricsCollectorService.
|
|
17
13
|
* @param options The options for the service.
|
|
@@ -8,6 +8,11 @@ export interface IMetricsCollectorServiceConstructorOptions {
|
|
|
8
8
|
* @default logging
|
|
9
9
|
*/
|
|
10
10
|
loggingComponentType?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The type of the tenant component to use for partitioned producers.
|
|
13
|
+
* @default tenant
|
|
14
|
+
*/
|
|
15
|
+
tenantComponentType?: string;
|
|
11
16
|
/**
|
|
12
17
|
* The configuration options for the metrics collector service.
|
|
13
18
|
*/
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.12](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.0.3-next.11...telemetry-service-v0.0.3-next.12) (2026-06-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Miscellaneous Chores
|
|
7
|
+
|
|
8
|
+
* **telemetry-service:** Synchronize repo versions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/telemetry-models bumped from 0.0.3-next.11 to 0.0.3-next.12
|
|
16
|
+
|
|
17
|
+
## [0.0.3-next.11](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.0.3-next.10...telemetry-service-v0.0.3-next.11) (2026-06-04)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* system metrics partitioning ([#38](https://github.com/iotaledger/twin-telemetry/issues/38)) ([3914183](https://github.com/iotaledger/twin-telemetry/commit/3914183bc17d0fd0adc8e30b7bb7aaee5d75e986))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
|
|
27
|
+
* The following workspace dependencies were updated
|
|
28
|
+
* dependencies
|
|
29
|
+
* @twin.org/telemetry-models bumped from 0.0.3-next.10 to 0.0.3-next.11
|
|
30
|
+
|
|
3
31
|
## [0.0.3-next.10](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.0.3-next.9...telemetry-service-v0.0.3-next.10) (2026-05-20)
|
|
4
32
|
|
|
5
33
|
|
|
@@ -18,6 +18,20 @@ logging
|
|
|
18
18
|
|
|
19
19
|
***
|
|
20
20
|
|
|
21
|
+
### tenantComponentType? {#tenantcomponenttype}
|
|
22
|
+
|
|
23
|
+
> `optional` **tenantComponentType?**: `string`
|
|
24
|
+
|
|
25
|
+
The type of the tenant component to use for partitioned producers.
|
|
26
|
+
|
|
27
|
+
#### Default
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
tenant
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
***
|
|
34
|
+
|
|
21
35
|
### config? {#config}
|
|
22
36
|
|
|
23
37
|
> `optional` **config?**: [`IMetricsCollectorServiceConfig`](IMetricsCollectorServiceConfig.md)
|
|
@@ -15,3 +15,17 @@ The type of the telemetry connector to use.
|
|
|
15
15
|
```ts
|
|
16
16
|
telemetry
|
|
17
17
|
```
|
|
18
|
+
|
|
19
|
+
***
|
|
20
|
+
|
|
21
|
+
### tenantComponentType? {#tenantcomponenttype}
|
|
22
|
+
|
|
23
|
+
> `optional` **tenantComponentType?**: `string`
|
|
24
|
+
|
|
25
|
+
The type of the tenant component to use for partition iteration.
|
|
26
|
+
|
|
27
|
+
#### Default
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
tenant
|
|
31
|
+
```
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/telemetry-service",
|
|
3
|
-
"version": "0.0.3-next.
|
|
3
|
+
"version": "0.0.3-next.12",
|
|
4
4
|
"description": "Telemetry service implementation with REST entry points.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/iotaledger/telemetry.git",
|
|
7
|
+
"url": "git+https://github.com/iotaledger/twin-telemetry.git",
|
|
8
8
|
"directory": "packages/telemetry-service"
|
|
9
9
|
},
|
|
10
10
|
"author": "martyn.janes@iota.org",
|
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@twin.org/api-models": "next",
|
|
18
|
+
"@twin.org/context": "next",
|
|
18
19
|
"@twin.org/core": "next",
|
|
19
20
|
"@twin.org/entity": "next",
|
|
20
21
|
"@twin.org/logging-models": "next",
|
|
21
22
|
"@twin.org/nameof": "next",
|
|
22
|
-
"@twin.org/telemetry-models": "0.0.3-next.
|
|
23
|
+
"@twin.org/telemetry-models": "0.0.3-next.12",
|
|
23
24
|
"@twin.org/web": "next"
|
|
24
25
|
},
|
|
25
26
|
"main": "./dist/es/index.js",
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
"business-logic"
|
|
51
52
|
],
|
|
52
53
|
"bugs": {
|
|
53
|
-
"url": "git+https://github.com/iotaledger/telemetry/issues"
|
|
54
|
+
"url": "git+https://github.com/iotaledger/twin-telemetry/issues"
|
|
54
55
|
},
|
|
55
56
|
"homepage": "https://twindev.org"
|
|
56
57
|
}
|