@twin.org/telemetry-service 0.9.2-next.4 → 0.9.2-next.6

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.
@@ -1,4 +1,4 @@
1
- import { BaseError, ComponentFactory } from "@twin.org/core";
1
+ import { BaseError, ComponentFactory, Guards, Validation } from "@twin.org/core";
2
2
  import { MetricsProducerFactory } from "@twin.org/telemetry-models";
3
3
  /**
4
4
  * Collects metrics from registered producers at a fixed interval.
@@ -36,15 +36,16 @@ export class MetricsCollectorService {
36
36
  /**
37
37
  * Create a new instance of MetricsCollectorService.
38
38
  * @param options The options for the service.
39
- * @throws {RangeError} If intervalMs is not a finite positive number.
39
+ * @throws ValidationError If intervalMs is not a positive integer.
40
40
  */
41
41
  constructor(options) {
42
42
  this._loggingComponent = ComponentFactory.getIfExists(options?.loggingComponentType);
43
43
  this._platformComponent = ComponentFactory.get(options?.platformComponentType ?? "platform");
44
44
  const intervalMs = options?.config?.intervalMs ?? 60_000;
45
- if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
46
- throw new RangeError(`intervalMs must be a finite positive number, got ${intervalMs}`);
47
- }
45
+ Guards.integer(MetricsCollectorService.CLASS_NAME, "intervalMs", intervalMs);
46
+ const failures = [];
47
+ Validation.integer("intervalMs", intervalMs, failures, undefined, { minValue: 1 });
48
+ Validation.asValidationError(MetricsCollectorService.CLASS_NAME, "MetricsCollectorService", failures);
48
49
  this._intervalMs = intervalMs;
49
50
  this._running = false;
50
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"metricsCollectorService.js","sourceRoot":"","sources":["../../src/metricsCollectorService.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG7D,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,kBAAkB,CAAqB;IAExD;;;OAGG;IACc,WAAW,CAAS;IAErC;;;OAGG;IACK,MAAM,CAAuD;IAErE;;;OAGG;IACK,QAAQ,CAAU;IAE1B;;;;OAIG;IACH,YAAY,OAAoD;QAC/D,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,WAAW,CACpD,OAAO,EAAE,oBAAoB,CAC7B,CAAC;QACF,IAAI,CAAC,kBAAkB,GAAG,gBAAgB,CAAC,GAAG,CAC7C,OAAO,EAAE,qBAAqB,IAAI,UAAU,CAC5C,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;;;;OAIG;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,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,iFAAiF;QACjF,yDAAyD;QACzD,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;YAC9C,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC,EAAE,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,IAAI;QAChB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,SAAS,EAAE,CAAC;QAClB,CAAC;IACF,CAAC;IAED;;;;OAIG;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,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;YACvE,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,UAAU,EAAE,CAAC;IACnB,CAAC;IAED;;;OAGG;IACK,UAAU;QACjB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,EAAE,CAAC;YAEjB,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;IAED;;;OAGG;IACK,SAAS;QAChB,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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IPlatformComponent } from \"@twin.org/api-models\";\nimport { BaseError, ComponentFactory } 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 * Platform component.\n\t * @internal\n\t */\n\tprivate readonly _platformComponent: IPlatformComponent;\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 * @throws {RangeError} If intervalMs is not a finite positive number.\n\t */\n\tconstructor(options?: IMetricsCollectorServiceConstructorOptions) {\n\t\tthis._loggingComponent = ComponentFactory.getIfExists<ILoggingComponent>(\n\t\t\toptions?.loggingComponentType\n\t\t);\n\t\tthis._platformComponent = ComponentFactory.get<IPlatformComponent>(\n\t\t\toptions?.platformComponentType ?? \"platform\"\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 * The first collection tick fires immediately but does not block start() from returning.\n\t * @returns A promise that resolves once producers are registered and the first tick is in flight.\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\tawait this._platformComponent.execute(async () => producer.register());\n\t\t}\n\n\t\t// Defer the first tick to the next event-loop turn so start() returns before any\n\t\t// collection work begins, keeping engine boot unblocked.\n\t\tthis._timer = globalThis.setTimeout(async () => {\n\t\t\tawait this.tick();\n\t\t}, 0);\n\t}\n\n\t/**\n\t * Stop the service and cancel the pending timer.\n\t * @returns A promise that resolves when the service has stopped.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tif (this._running) {\n\t\t\tthis._running = false;\n\t\t\tthis.stopTimer();\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 * @returns A promise that resolves when all producers have been polled and the next tick scheduled.\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\tawait this._platformComponent.execute(async () => producer.collect());\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.startTimer();\n\t}\n\n\t/**\n\t * Schedule the next tick after the configured interval.\n\t * @internal\n\t */\n\tprivate startTimer(): void {\n\t\tif (this._running) {\n\t\t\tthis.stopTimer();\n\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\t/**\n\t * Stop the timer.\n\t * @internal\n\t */\n\tprivate stopTimer(): void {\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"]}
1
+ {"version":3,"file":"metricsCollectorService.js","sourceRoot":"","sources":["../../src/metricsCollectorService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IPlatformComponent } from \"@twin.org/api-models\";\nimport {\n\tBaseError,\n\tComponentFactory,\n\tGuards,\n\ttype IValidationFailure,\n\tValidation\n} 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 * Platform component.\n\t * @internal\n\t */\n\tprivate readonly _platformComponent: IPlatformComponent;\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 * @throws ValidationError If intervalMs is not a positive integer.\n\t */\n\tconstructor(options?: IMetricsCollectorServiceConstructorOptions) {\n\t\tthis._loggingComponent = ComponentFactory.getIfExists<ILoggingComponent>(\n\t\t\toptions?.loggingComponentType\n\t\t);\n\t\tthis._platformComponent = ComponentFactory.get<IPlatformComponent>(\n\t\t\toptions?.platformComponentType ?? \"platform\"\n\t\t);\n\n\t\tconst intervalMs = options?.config?.intervalMs ?? 60_000;\n\t\tGuards.integer(MetricsCollectorService.CLASS_NAME, nameof(intervalMs), intervalMs);\n\t\tconst failures: IValidationFailure[] = [];\n\t\tValidation.integer(nameof(intervalMs), intervalMs, failures, undefined, { minValue: 1 });\n\t\tValidation.asValidationError(\n\t\t\tMetricsCollectorService.CLASS_NAME,\n\t\t\tnameof<MetricsCollectorService>(),\n\t\t\tfailures\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 * The first collection tick fires immediately but does not block start() from returning.\n\t * @returns A promise that resolves once producers are registered and the first tick is in flight.\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\tawait this._platformComponent.execute(async () => producer.register());\n\t\t}\n\n\t\t// Defer the first tick to the next event-loop turn so start() returns before any\n\t\t// collection work begins, keeping engine boot unblocked.\n\t\tthis._timer = globalThis.setTimeout(async () => {\n\t\t\tawait this.tick();\n\t\t}, 0);\n\t}\n\n\t/**\n\t * Stop the service and cancel the pending timer.\n\t * @returns A promise that resolves when the service has stopped.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tif (this._running) {\n\t\t\tthis._running = false;\n\t\t\tthis.stopTimer();\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 * @returns A promise that resolves when all producers have been polled and the next tick scheduled.\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\tawait this._platformComponent.execute(async () => producer.collect());\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.startTimer();\n\t}\n\n\t/**\n\t * Schedule the next tick after the configured interval.\n\t * @internal\n\t */\n\tprivate startTimer(): void {\n\t\tif (this._running) {\n\t\t\tthis.stopTimer();\n\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\t/**\n\t * Stop the timer.\n\t * @internal\n\t */\n\tprivate stopTimer(): void {\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"]}
@@ -11,7 +11,7 @@ export declare class MetricsCollectorService implements IMetricsCollectorCompone
11
11
  /**
12
12
  * Create a new instance of MetricsCollectorService.
13
13
  * @param options The options for the service.
14
- * @throws {RangeError} If intervalMs is not a finite positive number.
14
+ * @throws ValidationError If intervalMs is not a positive integer.
15
15
  */
16
16
  constructor(options?: IMetricsCollectorServiceConstructorOptions);
17
17
  /**
package/docs/changelog.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.2-next.6](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.9.2-next.5...telemetry-service-v0.9.2-next.6) (2026-08-19)
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.9.2-next.5 to 0.9.2-next.6
16
+
17
+ ## [0.9.2-next.5](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.9.2-next.4...telemetry-service-v0.9.2-next.5) (2026-08-19)
18
+
19
+
20
+ ### Features
21
+
22
+ * use standard validation not RangeError ([31e2c79](https://github.com/iotaledger/twin-telemetry/commit/31e2c791fa264827175b23843398a2792654819a))
23
+
24
+
25
+ ### Dependencies
26
+
27
+ * The following workspace dependencies were updated
28
+ * dependencies
29
+ * @twin.org/telemetry-models bumped from 0.9.2-next.4 to 0.9.2-next.5
30
+
3
31
  ## [0.9.2-next.4](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.9.2-next.3...telemetry-service-v0.9.2-next.4) (2026-08-17)
4
32
 
5
33
 
@@ -28,7 +28,7 @@ The options for the service.
28
28
 
29
29
  #### Throws
30
30
 
31
- If intervalMs is not a finite positive number.
31
+ ValidationError If intervalMs is not a positive integer.
32
32
 
33
33
  ## Properties
34
34
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/telemetry-service",
3
- "version": "0.9.2-next.4",
3
+ "version": "0.9.2-next.6",
4
4
  "description": "Telemetry service implementation with REST entry points.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "@twin.org/entity": "next",
21
21
  "@twin.org/logging-models": "next",
22
22
  "@twin.org/nameof": "next",
23
- "@twin.org/telemetry-models": "0.9.2-next.4",
23
+ "@twin.org/telemetry-models": "0.9.2-next.6",
24
24
  "@twin.org/web": "next"
25
25
  },
26
26
  "main": "./dist/es/index.js",