@twin.org/telemetry-connector-opentelemetry 0.9.3-next.2 → 0.9.3-next.4

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.
@@ -3,7 +3,7 @@ import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
3
3
  import { resourceFromAttributes } from "@opentelemetry/resources";
4
4
  import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
5
5
  import { ContextIdKeys, ContextIdStore } from "@twin.org/context";
6
- import { ComponentFactory, Converter, GeneralError, Guards, Is, NotFoundError, RandomHelper } from "@twin.org/core";
6
+ import { AlreadyExistsError, BaseError, ComponentFactory, Converter, GeneralError, Guards, Is, NotFoundError, RandomHelper } from "@twin.org/core";
7
7
  import { MetricCounterOperation, MetricType } from "@twin.org/telemetry-models";
8
8
  import { OpenTelemetryReaderTypes } from "./models/openTelemetryReaderTypes.js";
9
9
  /**
@@ -106,12 +106,27 @@ export class OpenTelemetryTelemetryConnector {
106
106
  }
107
107
  }
108
108
  /**
109
- * Register a new metric definition. If the connector is already started,
109
+ * Register one or more metric definitions. If the connector is already started,
110
110
  * the OTEL instrument is registered immediately for the current context.
111
- * @param metric The metric details.
112
- * @returns A promise that resolves when the metric has been registered.
111
+ * @param metric The metric details, or the details of several metrics.
112
+ * @returns A promise that resolves when the metrics have been registered.
113
113
  */
114
114
  async createMetric(metric) {
115
+ if (Is.array(metric)) {
116
+ // An array declares the set that should exist, so the ones already registered are
117
+ // left alone. The definitions are held in memory, there is nothing to batch into.
118
+ for (const entry of metric) {
119
+ try {
120
+ await this.createMetric(entry);
121
+ }
122
+ catch (err) {
123
+ if (!BaseError.isErrorName(err, AlreadyExistsError.CLASS_NAME)) {
124
+ throw err;
125
+ }
126
+ }
127
+ }
128
+ return;
129
+ }
115
130
  Guards.object(OpenTelemetryTelemetryConnector.CLASS_NAME, "metric", metric);
116
131
  Guards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, "metric.id", metric.id);
117
132
  Guards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, "metric.label", metric.label);
@@ -208,6 +223,20 @@ export class OpenTelemetryTelemetryConnector {
208
223
  }
209
224
  return valueId;
210
225
  }
226
+ /**
227
+ * Add multiple metric values.
228
+ * @param values The metric values to add.
229
+ * @returns The created metric value ids, in the order the values were supplied.
230
+ */
231
+ async addMetricValues(values) {
232
+ Guards.array(OpenTelemetryTelemetryConnector.CLASS_NAME, "values", values);
233
+ // The instruments are recorded one at a time, there is nothing to batch into.
234
+ const valueIds = [];
235
+ for (const entry of values) {
236
+ valueIds.push(await this.addMetricValue(entry.id, entry.value, entry.customData));
237
+ }
238
+ return valueIds;
239
+ }
211
240
  /**
212
241
  * Remove a metric from the in-memory registry and from all cached provider instrument maps.
213
242
  * @param id The id of the metric.
@@ -1 +1 @@
1
- {"version":3,"file":"openTelemetryTelemetryConnector.js","sourceRoot":"","sources":["../../src/openTelemetryTelemetryConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { Attributes, Counter, Gauge, Meter, UpDownCounter } from \"@opentelemetry/api\";\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-http\";\nimport { PrometheusExporter } from \"@opentelemetry/exporter-prometheus\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport {\n\tMeterProvider,\n\tPeriodicExportingMetricReader,\n\ttype MetricReader\n} from \"@opentelemetry/sdk-metrics\";\nimport { ContextIdKeys, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tComponentFactory,\n\tConverter,\n\tGeneralError,\n\tGuards,\n\tIs,\n\tNotFoundError,\n\tRandomHelper\n} from \"@twin.org/core\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\ttype ITelemetryConnector,\n\ttype ITelemetryMetric,\n\tMetricCounterOperation,\n\tMetricType\n} from \"@twin.org/telemetry-models\";\nimport type { IOpenTelemetryTelemetryConnectorConfig } from \"./models/IOpenTelemetryTelemetryConnectorConfig.js\";\nimport type { IOpenTelemetryTelemetryConnectorConstructorOptions } from \"./models/IOpenTelemetryTelemetryConnectorConstructorOptions.js\";\nimport { OpenTelemetryReaderTypes } from \"./models/openTelemetryReaderTypes.js\";\n\n/**\n * Class for performing telemetry operations using OpenTelemetry instruments.\n * Metric definitions are held in memory. Persistence and querying are not supported;\n * use a multi-connector with an EntityStorageTelemetryConnector for those capabilities.\n */\nexport class OpenTelemetryTelemetryConnector implements ITelemetryConnector {\n\t/**\n\t * The namespace supported by the telemetry connector.\n\t */\n\tpublic static readonly NAMESPACE: string = \"open-telemetry\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<OpenTelemetryTelemetryConnector>();\n\n\t/**\n\t * Config options stored so provider creation can initialise readers and meter identity.\n\t * @internal\n\t */\n\tprivate readonly _config: IOpenTelemetryTelemetryConnectorConfig;\n\n\t/**\n\t * Whether start() has been called. Drives OTEL forwarding on/off.\n\t * @internal\n\t */\n\tprivate _started: boolean;\n\n\t/**\n\t * Cache of MeterProvider+Meter+instruments keyed by \"nodeId/tenantId\".\n\t * Providers are created on demand when the first metric measurement arrives\n\t * for a given tenant/node pair.\n\t * @internal\n\t */\n\tprivate readonly _providers: {\n\t\t[key: string]: {\n\t\t\tmeterProvider: MeterProvider;\n\t\t\tmeter: Meter;\n\t\t\tinstruments: {\n\t\t\t\t[id: string]: { metricType: MetricType; instrument: Counter | UpDownCounter | Gauge };\n\t\t\t};\n\t\t};\n\t};\n\n\t/**\n\t * In-memory metric definition registry keyed by metric id.\n\t * @internal\n\t */\n\tprivate readonly _metricDefs: {\n\t\t[id: string]: { type: MetricType; label: string; description?: string; unit?: string };\n\t};\n\n\t/**\n\t * Create a new instance of OpenTelemetryTelemetryConnector.\n\t * @param options The options for the connector.\n\t * @throws GuardError When a reader config specifies an unsupported type.\n\t */\n\tconstructor(options?: IOpenTelemetryTelemetryConnectorConstructorOptions) {\n\t\tthis._config = options?.config ?? {};\n\n\t\tfor (const [, readerConfig] of Object.entries(this._config.readers ?? {})) {\n\t\t\tGuards.arrayOneOf(\n\t\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\t\tnameof(readerConfig.type),\n\t\t\t\treaderConfig.type,\n\t\t\t\tObject.values(OpenTelemetryReaderTypes)\n\t\t\t);\n\t\t}\n\n\t\tthis._started = false;\n\t\tthis._providers = {};\n\t\tthis._metricDefs = {};\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 OpenTelemetryTelemetryConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Enable OTEL forwarding. Subsequent calls to addMetricValue will create\n\t * per-tenant/node MeterProviders on demand.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when OTEL forwarding is enabled.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._started) {\n\t\t\treturn;\n\t\t}\n\t\tthis._started = true;\n\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\t\tawait nodeLogging?.log({\n\t\t\tsource: OpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tmessage: \"connectorStarted\",\n\t\t\tlevel: \"info\",\n\t\t\tdata: { readerCount: Object.keys(this._config.readers ?? {}).length }\n\t\t});\n\t}\n\n\t/**\n\t * Shut down all cached MeterProviders and disable OTEL forwarding.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when all MeterProviders have shut down.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._started) {\n\t\t\tfor (const { meterProvider } of Object.values(this._providers)) {\n\t\t\t\tawait meterProvider.shutdown();\n\t\t\t}\n\t\t\tfor (const key of Object.keys(this._providers)) {\n\t\t\t\tdelete this._providers[key];\n\t\t\t}\n\t\t\tthis._started = false;\n\n\t\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tsource: OpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\t\tmessage: \"connectorStopped\",\n\t\t\t\tlevel: \"info\",\n\t\t\t\tdata: {}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Register a new metric definition. If the connector is already started,\n\t * the OTEL instrument is registered immediately for the current context.\n\t * @param metric The metric details.\n\t * @returns A promise that resolves when the metric has been registered.\n\t */\n\tpublic async createMetric(metric: ITelemetryMetric): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(\n\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tnameof(metric),\n\t\t\tmetric\n\t\t);\n\t\tGuards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(metric.id), metric.id);\n\t\tGuards.stringValue(\n\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tnameof(metric.label),\n\t\t\tmetric.label\n\t\t);\n\n\t\tthis._metricDefs[metric.id] = {\n\t\t\ttype: metric.type,\n\t\t\tlabel: metric.label,\n\t\t\tdescription: metric.description,\n\t\t\tunit: metric.unit\n\t\t};\n\n\t\tif (this._started) {\n\t\t\tconst contextIds = (await ContextIdStore.getContextIds()) ?? {};\n\t\t\tconst { meter, instruments } = this.getOrCreateProvider(contextIds);\n\t\t\tthis.registerInstrument(\n\t\t\t\tmetric.id,\n\t\t\t\tmetric.type,\n\t\t\t\tmetric.description,\n\t\t\t\tmetric.unit,\n\t\t\t\tmeter,\n\t\t\t\tinstruments\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Update the in-memory metadata for a registered metric.\n\t * OpenTelemetry instrument descriptors are immutable once created; only the\n\t * cached label, description and unit are updated.\n\t * @param metric The metric details (type cannot be changed).\n\t * @returns A promise that resolves when the metadata has been updated.\n\t */\n\tpublic async updateMetric(metric: Omit<ITelemetryMetric, \"type\">): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(\n\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tnameof(metric),\n\t\t\tmetric\n\t\t);\n\t\tGuards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(metric.id), metric.id);\n\n\t\tconst def = this._metricDefs[metric.id];\n\t\tif (Is.undefined(def)) {\n\t\t\tthrow new NotFoundError(\n\t\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\t\t\"metricNotFound\",\n\t\t\t\tmetric.id\n\t\t\t);\n\t\t}\n\n\t\tthis._metricDefs[metric.id] = {\n\t\t\ttype: def.type,\n\t\t\tlabel: metric.label,\n\t\t\tdescription: metric.description,\n\t\t\tunit: metric.unit\n\t\t};\n\t}\n\n\t/**\n\t * Record a metric value and forward it to the appropriate OTEL instrument.\n\t * The current tenant and node IDs are read from `ContextIdStore` and used to\n\t * select (or create) the matching per-tenant/node `MeterProvider`.\n\t * @param id The id of the metric.\n\t * @param value The value for the operation.\n\t * @param customData Optional custom data forwarded as OTEL attributes.\n\t * @returns A generated 32-character hex id for the recorded value.\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(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(id), id);\n\t\tGuards.defined(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(value), value);\n\n\t\tconst def = this._metricDefs[id];\n\t\tif (Is.undefined(def)) {\n\t\t\tthrow new NotFoundError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"metricNotFound\", id);\n\t\t}\n\n\t\tif (def.type === MetricType.Counter) {\n\t\t\tif (value !== MetricCounterOperation.Increment && (!Is.integer(value) || value <= 0)) {\n\t\t\t\tthrow new GeneralError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"counterIncOnly\");\n\t\t\t}\n\t\t} else if (def.type === MetricType.Gauge) {\n\t\t\tif (!Is.number(value)) {\n\t\t\t\tthrow new GeneralError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"gaugeNoIncDec\");\n\t\t\t}\n\t\t}\n\n\t\tconst valueId = Converter.bytesToHex(RandomHelper.generate(16));\n\n\t\tif (this._started) {\n\t\t\tconst contextIds = (await ContextIdStore.getContextIds()) ?? {};\n\t\t\tconst { meter, instruments } = this.getOrCreateProvider(contextIds);\n\n\t\t\tif (!(id in instruments)) {\n\t\t\t\tthis.registerInstrument(id, def.type, def.description, def.unit, meter, instruments);\n\t\t\t}\n\n\t\t\tconst entry = instruments[id];\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst attributes = this.toAttributes(customData);\n\t\t\t\tconst { metricType, instrument } = entry;\n\n\t\t\t\tif (metricType === MetricType.Counter) {\n\t\t\t\t\t(instrument as Counter).add(\n\t\t\t\t\t\tvalue === MetricCounterOperation.Increment ? 1 : (value as number),\n\t\t\t\t\t\tattributes\n\t\t\t\t\t);\n\t\t\t\t} else if (metricType === MetricType.IncDecCounter) {\n\t\t\t\t\tlet delta: number;\n\t\t\t\t\tif (value === MetricCounterOperation.Increment) {\n\t\t\t\t\t\tdelta = 1;\n\t\t\t\t\t} else if (value === MetricCounterOperation.Decrement) {\n\t\t\t\t\t\tdelta = -1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelta = value;\n\t\t\t\t\t}\n\t\t\t\t\t(instrument as UpDownCounter).add(delta, attributes);\n\t\t\t\t} else {\n\t\t\t\t\t(instrument as Gauge).record(value as number, attributes);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn valueId;\n\t}\n\n\t/**\n\t * Remove a metric from the in-memory registry and from all cached provider instrument maps.\n\t * @param id The id of the metric.\n\t * @returns A promise that resolves when the metric has been removed.\n\t */\n\tpublic async removeMetric(id: string): Promise<void> {\n\t\tGuards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(id), id);\n\n\t\tif (Is.undefined(this._metricDefs[id])) {\n\t\t\tthrow new NotFoundError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"metricNotFound\", id);\n\t\t}\n\n\t\tfor (const { instruments } of Object.values(this._providers)) {\n\t\t\tdelete instruments[id];\n\t\t}\n\t\tdelete this._metricDefs[id];\n\t}\n\n\t/**\n\t * Return or create the MeterProvider for the given tenant/node pair.\n\t * @param contextIds The current execution context IDs.\n\t * @returns The cached or newly created provider entry.\n\t * @internal\n\t */\n\tprivate getOrCreateProvider(contextIds: IContextIds): {\n\t\tmeterProvider: MeterProvider;\n\t\tmeter: Meter;\n\t\tinstruments: {\n\t\t\t[id: string]: { metricType: MetricType; instrument: Counter | UpDownCounter | Gauge };\n\t\t};\n\t} {\n\t\tconst node = contextIds[ContextIdKeys.Node];\n\t\tconst tenantId = contextIds[ContextIdKeys.Tenant];\n\n\t\tconst key = `${node ?? \"\"}/${tenantId ?? \"\"}`;\n\n\t\tlet cached = this._providers[key];\n\t\tif (!Is.undefined(cached)) {\n\t\t\treturn cached;\n\t\t}\n\n\t\tconst readers = this.createReaders();\n\t\tconst resourcePrefix = \"service\";\n\t\tconst resourceAttrs: { [id: string]: string } = {};\n\t\tif (Is.stringValue(node)) {\n\t\t\tresourceAttrs[`${resourcePrefix}.instance.id`] = node;\n\t\t}\n\t\tif (Is.stringValue(tenantId)) {\n\t\t\tresourceAttrs[`${resourcePrefix}.namespace`] = tenantId;\n\t\t}\n\t\tconst resource =\n\t\t\tObject.keys(resourceAttrs).length > 0 ? resourceFromAttributes(resourceAttrs) : undefined;\n\t\tconst meterProvider = new MeterProvider({ readers, resource });\n\t\tconst meter = meterProvider.getMeter(\n\t\t\tthis._config.meterName ?? \"twin-telemetry\",\n\t\t\tthis._config.meterVersion ?? \"1.0.0\"\n\t\t);\n\t\tcached = { meterProvider, meter, instruments: {} };\n\t\tthis._providers[key] = cached;\n\n\t\treturn cached;\n\t}\n\n\t/**\n\t * Instantiate fresh MetricReader instances from the connector config.\n\t * @returns The list of reader instances.\n\t * @internal\n\t */\n\tprivate createReaders(): MetricReader[] {\n\t\tconst readers: MetricReader[] = [];\n\t\tfor (const [, config] of Object.entries(this._config.readers ?? {})) {\n\t\t\tif (config.type === OpenTelemetryReaderTypes.Prometheus) {\n\t\t\t\treaders.push(\n\t\t\t\t\tnew PrometheusExporter({\n\t\t\t\t\t\tport: config.port,\n\t\t\t\t\t\tendpoint: config.endpoint,\n\t\t\t\t\t\tpreventServerStart: !(config.startServer ?? true),\n\t\t\t\t\t\tprefix: config.prefix\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t} else if (config.type === OpenTelemetryReaderTypes.OtlpHttp) {\n\t\t\t\treaders.push(\n\t\t\t\t\tnew PeriodicExportingMetricReader({\n\t\t\t\t\t\texporter: new OTLPMetricExporter({\n\t\t\t\t\t\t\turl: config.url,\n\t\t\t\t\t\t\theaders: config.headers\n\t\t\t\t\t\t}),\n\t\t\t\t\t\texportIntervalMillis: config.exportIntervalMs\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn readers;\n\t}\n\n\t/**\n\t * Register an OTEL instrument on a provider's instruments map if not already present.\n\t * @param id The metric id.\n\t * @param type The metric type.\n\t * @param description The metric description.\n\t * @param unit The metric unit.\n\t * @param meter The meter to create instruments on.\n\t * @param instruments The per-provider instruments map to update.\n\t * @internal\n\t */\n\tprivate registerInstrument(\n\t\tid: string,\n\t\ttype: MetricType,\n\t\tdescription: string | undefined,\n\t\tunit: string | undefined,\n\t\tmeter: Meter,\n\t\tinstruments: {\n\t\t\t[id: string]: { metricType: MetricType; instrument: Counter | UpDownCounter | Gauge };\n\t\t}\n\t): void {\n\t\tif (id in instruments) {\n\t\t\treturn;\n\t\t}\n\t\tconst instrumentOptions = { description, unit };\n\t\tlet instrument: Counter | UpDownCounter | Gauge;\n\t\tif (type === MetricType.Counter) {\n\t\t\tinstrument = meter.createCounter(id, instrumentOptions);\n\t\t} else if (type === MetricType.IncDecCounter) {\n\t\t\tinstrument = meter.createUpDownCounter(id, instrumentOptions);\n\t\t} else {\n\t\t\tinstrument = meter.createGauge(id, instrumentOptions);\n\t\t}\n\t\tinstruments[id] = { metricType: type, instrument };\n\t}\n\n\t/**\n\t * Convert customData to OTEL-compatible Attributes.\n\t * @param customData The raw custom data map.\n\t * @returns An OTEL Attributes object.\n\t * @internal\n\t */\n\tprivate toAttributes(customData?: { [key: string]: unknown }): Attributes {\n\t\tif (Is.empty(customData)) {\n\t\t\treturn {};\n\t\t}\n\t\tconst attributes: Attributes = {};\n\t\tfor (const [key, val] of Object.entries(customData)) {\n\t\t\tif (Is.string(val) || Is.number(val) || Is.boolean(val)) {\n\t\t\t\tattributes[key] = val;\n\t\t\t} else if (Is.arrayValue(val)) {\n\t\t\t\tif (Is.string(val[0]) && val.every(el => Is.string(el))) {\n\t\t\t\t\tattributes[key] = val;\n\t\t\t\t} else if (Is.number(val[0]) && val.every(el => Is.number(el))) {\n\t\t\t\t\tattributes[key] = val;\n\t\t\t\t} else if (Is.boolean(val[0]) && val.every(el => Is.boolean(el))) {\n\t\t\t\t\tattributes[key] = val;\n\t\t\t\t} else {\n\t\t\t\t\tattributes[key] = JSON.stringify(val);\n\t\t\t\t}\n\t\t\t} else if (!Is.undefined(val)) {\n\t\t\t\tattributes[key] = JSON.stringify(val);\n\t\t\t}\n\t\t}\n\t\treturn attributes;\n\t}\n}\n"]}
1
+ {"version":3,"file":"openTelemetryTelemetryConnector.js","sourceRoot":"","sources":["../../src/openTelemetryTelemetryConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { Attributes, Counter, Gauge, Meter, UpDownCounter } from \"@opentelemetry/api\";\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-http\";\nimport { PrometheusExporter } from \"@opentelemetry/exporter-prometheus\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport {\n\tMeterProvider,\n\tPeriodicExportingMetricReader,\n\ttype MetricReader\n} from \"@opentelemetry/sdk-metrics\";\nimport { ContextIdKeys, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tAlreadyExistsError,\n\tBaseError,\n\tComponentFactory,\n\tConverter,\n\tGeneralError,\n\tGuards,\n\tIs,\n\tNotFoundError,\n\tRandomHelper\n} from \"@twin.org/core\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\ttype ITelemetryConnector,\n\ttype ITelemetryMetric,\n\ttype ITelemetryMetricValueEntry,\n\tMetricCounterOperation,\n\tMetricType\n} from \"@twin.org/telemetry-models\";\nimport type { IOpenTelemetryTelemetryConnectorConfig } from \"./models/IOpenTelemetryTelemetryConnectorConfig.js\";\nimport type { IOpenTelemetryTelemetryConnectorConstructorOptions } from \"./models/IOpenTelemetryTelemetryConnectorConstructorOptions.js\";\nimport { OpenTelemetryReaderTypes } from \"./models/openTelemetryReaderTypes.js\";\n\n/**\n * Class for performing telemetry operations using OpenTelemetry instruments.\n * Metric definitions are held in memory. Persistence and querying are not supported;\n * use a multi-connector with an EntityStorageTelemetryConnector for those capabilities.\n */\nexport class OpenTelemetryTelemetryConnector implements ITelemetryConnector {\n\t/**\n\t * The namespace supported by the telemetry connector.\n\t */\n\tpublic static readonly NAMESPACE: string = \"open-telemetry\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<OpenTelemetryTelemetryConnector>();\n\n\t/**\n\t * Config options stored so provider creation can initialise readers and meter identity.\n\t * @internal\n\t */\n\tprivate readonly _config: IOpenTelemetryTelemetryConnectorConfig;\n\n\t/**\n\t * Whether start() has been called. Drives OTEL forwarding on/off.\n\t * @internal\n\t */\n\tprivate _started: boolean;\n\n\t/**\n\t * Cache of MeterProvider+Meter+instruments keyed by \"nodeId/tenantId\".\n\t * Providers are created on demand when the first metric measurement arrives\n\t * for a given tenant/node pair.\n\t * @internal\n\t */\n\tprivate readonly _providers: {\n\t\t[key: string]: {\n\t\t\tmeterProvider: MeterProvider;\n\t\t\tmeter: Meter;\n\t\t\tinstruments: {\n\t\t\t\t[id: string]: { metricType: MetricType; instrument: Counter | UpDownCounter | Gauge };\n\t\t\t};\n\t\t};\n\t};\n\n\t/**\n\t * In-memory metric definition registry keyed by metric id.\n\t * @internal\n\t */\n\tprivate readonly _metricDefs: {\n\t\t[id: string]: { type: MetricType; label: string; description?: string; unit?: string };\n\t};\n\n\t/**\n\t * Create a new instance of OpenTelemetryTelemetryConnector.\n\t * @param options The options for the connector.\n\t * @throws GuardError When a reader config specifies an unsupported type.\n\t */\n\tconstructor(options?: IOpenTelemetryTelemetryConnectorConstructorOptions) {\n\t\tthis._config = options?.config ?? {};\n\n\t\tfor (const [, readerConfig] of Object.entries(this._config.readers ?? {})) {\n\t\t\tGuards.arrayOneOf(\n\t\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\t\tnameof(readerConfig.type),\n\t\t\t\treaderConfig.type,\n\t\t\t\tObject.values(OpenTelemetryReaderTypes)\n\t\t\t);\n\t\t}\n\n\t\tthis._started = false;\n\t\tthis._providers = {};\n\t\tthis._metricDefs = {};\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 OpenTelemetryTelemetryConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Enable OTEL forwarding. Subsequent calls to addMetricValue will create\n\t * per-tenant/node MeterProviders on demand.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when OTEL forwarding is enabled.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._started) {\n\t\t\treturn;\n\t\t}\n\t\tthis._started = true;\n\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\t\tawait nodeLogging?.log({\n\t\t\tsource: OpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tmessage: \"connectorStarted\",\n\t\t\tlevel: \"info\",\n\t\t\tdata: { readerCount: Object.keys(this._config.readers ?? {}).length }\n\t\t});\n\t}\n\n\t/**\n\t * Shut down all cached MeterProviders and disable OTEL forwarding.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when all MeterProviders have shut down.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._started) {\n\t\t\tfor (const { meterProvider } of Object.values(this._providers)) {\n\t\t\t\tawait meterProvider.shutdown();\n\t\t\t}\n\t\t\tfor (const key of Object.keys(this._providers)) {\n\t\t\t\tdelete this._providers[key];\n\t\t\t}\n\t\t\tthis._started = false;\n\n\t\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tsource: OpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\t\tmessage: \"connectorStopped\",\n\t\t\t\tlevel: \"info\",\n\t\t\t\tdata: {}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Register one or more metric definitions. If the connector is already started,\n\t * the OTEL instrument is registered immediately for the current context.\n\t * @param metric The metric details, or the details of several metrics.\n\t * @returns A promise that resolves when the metrics have been registered.\n\t */\n\tpublic async createMetric(metric: ITelemetryMetric | ITelemetryMetric[]): Promise<void> {\n\t\tif (Is.array<ITelemetryMetric>(metric)) {\n\t\t\t// An array declares the set that should exist, so the ones already registered are\n\t\t\t// left alone. The definitions are held in memory, there is nothing to batch into.\n\t\t\tfor (const entry of metric) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.createMetric(entry);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (!BaseError.isErrorName(err, AlreadyExistsError.CLASS_NAME)) {\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tGuards.object<ITelemetryMetric>(\n\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tnameof(metric),\n\t\t\tmetric\n\t\t);\n\t\tGuards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(metric.id), metric.id);\n\t\tGuards.stringValue(\n\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tnameof(metric.label),\n\t\t\tmetric.label\n\t\t);\n\n\t\tthis._metricDefs[metric.id] = {\n\t\t\ttype: metric.type,\n\t\t\tlabel: metric.label,\n\t\t\tdescription: metric.description,\n\t\t\tunit: metric.unit\n\t\t};\n\n\t\tif (this._started) {\n\t\t\tconst contextIds = (await ContextIdStore.getContextIds()) ?? {};\n\t\t\tconst { meter, instruments } = this.getOrCreateProvider(contextIds);\n\t\t\tthis.registerInstrument(\n\t\t\t\tmetric.id,\n\t\t\t\tmetric.type,\n\t\t\t\tmetric.description,\n\t\t\t\tmetric.unit,\n\t\t\t\tmeter,\n\t\t\t\tinstruments\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Update the in-memory metadata for a registered metric.\n\t * OpenTelemetry instrument descriptors are immutable once created; only the\n\t * cached label, description and unit are updated.\n\t * @param metric The metric details (type cannot be changed).\n\t * @returns A promise that resolves when the metadata has been updated.\n\t */\n\tpublic async updateMetric(metric: Omit<ITelemetryMetric, \"type\">): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(\n\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tnameof(metric),\n\t\t\tmetric\n\t\t);\n\t\tGuards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(metric.id), metric.id);\n\n\t\tconst def = this._metricDefs[metric.id];\n\t\tif (Is.undefined(def)) {\n\t\t\tthrow new NotFoundError(\n\t\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\t\t\"metricNotFound\",\n\t\t\t\tmetric.id\n\t\t\t);\n\t\t}\n\n\t\tthis._metricDefs[metric.id] = {\n\t\t\ttype: def.type,\n\t\t\tlabel: metric.label,\n\t\t\tdescription: metric.description,\n\t\t\tunit: metric.unit\n\t\t};\n\t}\n\n\t/**\n\t * Record a metric value and forward it to the appropriate OTEL instrument.\n\t * The current tenant and node IDs are read from `ContextIdStore` and used to\n\t * select (or create) the matching per-tenant/node `MeterProvider`.\n\t * @param id The id of the metric.\n\t * @param value The value for the operation.\n\t * @param customData Optional custom data forwarded as OTEL attributes.\n\t * @returns A generated 32-character hex id for the recorded value.\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(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(id), id);\n\t\tGuards.defined(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(value), value);\n\n\t\tconst def = this._metricDefs[id];\n\t\tif (Is.undefined(def)) {\n\t\t\tthrow new NotFoundError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"metricNotFound\", id);\n\t\t}\n\n\t\tif (def.type === MetricType.Counter) {\n\t\t\tif (value !== MetricCounterOperation.Increment && (!Is.integer(value) || value <= 0)) {\n\t\t\t\tthrow new GeneralError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"counterIncOnly\");\n\t\t\t}\n\t\t} else if (def.type === MetricType.Gauge) {\n\t\t\tif (!Is.number(value)) {\n\t\t\t\tthrow new GeneralError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"gaugeNoIncDec\");\n\t\t\t}\n\t\t}\n\n\t\tconst valueId = Converter.bytesToHex(RandomHelper.generate(16));\n\n\t\tif (this._started) {\n\t\t\tconst contextIds = (await ContextIdStore.getContextIds()) ?? {};\n\t\t\tconst { meter, instruments } = this.getOrCreateProvider(contextIds);\n\n\t\t\tif (!(id in instruments)) {\n\t\t\t\tthis.registerInstrument(id, def.type, def.description, def.unit, meter, instruments);\n\t\t\t}\n\n\t\t\tconst entry = instruments[id];\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst attributes = this.toAttributes(customData);\n\t\t\t\tconst { metricType, instrument } = entry;\n\n\t\t\t\tif (metricType === MetricType.Counter) {\n\t\t\t\t\t(instrument as Counter).add(\n\t\t\t\t\t\tvalue === MetricCounterOperation.Increment ? 1 : (value as number),\n\t\t\t\t\t\tattributes\n\t\t\t\t\t);\n\t\t\t\t} else if (metricType === MetricType.IncDecCounter) {\n\t\t\t\t\tlet delta: number;\n\t\t\t\t\tif (value === MetricCounterOperation.Increment) {\n\t\t\t\t\t\tdelta = 1;\n\t\t\t\t\t} else if (value === MetricCounterOperation.Decrement) {\n\t\t\t\t\t\tdelta = -1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelta = value;\n\t\t\t\t\t}\n\t\t\t\t\t(instrument as UpDownCounter).add(delta, attributes);\n\t\t\t\t} else {\n\t\t\t\t\t(instrument as Gauge).record(value as number, attributes);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn valueId;\n\t}\n\n\t/**\n\t * Add multiple metric values.\n\t * @param values The metric values to add.\n\t * @returns The created metric value ids, in the order the values were supplied.\n\t */\n\tpublic async addMetricValues(values: ITelemetryMetricValueEntry[]): Promise<string[]> {\n\t\tGuards.array<ITelemetryMetricValueEntry>(\n\t\t\tOpenTelemetryTelemetryConnector.CLASS_NAME,\n\t\t\tnameof(values),\n\t\t\tvalues\n\t\t);\n\n\t\t// The instruments are recorded one at a time, there is nothing to batch into.\n\t\tconst valueIds: string[] = [];\n\t\tfor (const entry of values) {\n\t\t\tvalueIds.push(await this.addMetricValue(entry.id, entry.value, entry.customData));\n\t\t}\n\t\treturn valueIds;\n\t}\n\n\t/**\n\t * Remove a metric from the in-memory registry and from all cached provider instrument maps.\n\t * @param id The id of the metric.\n\t * @returns A promise that resolves when the metric has been removed.\n\t */\n\tpublic async removeMetric(id: string): Promise<void> {\n\t\tGuards.stringValue(OpenTelemetryTelemetryConnector.CLASS_NAME, nameof(id), id);\n\n\t\tif (Is.undefined(this._metricDefs[id])) {\n\t\t\tthrow new NotFoundError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"metricNotFound\", id);\n\t\t}\n\n\t\tfor (const { instruments } of Object.values(this._providers)) {\n\t\t\tdelete instruments[id];\n\t\t}\n\t\tdelete this._metricDefs[id];\n\t}\n\n\t/**\n\t * Return or create the MeterProvider for the given tenant/node pair.\n\t * @param contextIds The current execution context IDs.\n\t * @returns The cached or newly created provider entry.\n\t * @internal\n\t */\n\tprivate getOrCreateProvider(contextIds: IContextIds): {\n\t\tmeterProvider: MeterProvider;\n\t\tmeter: Meter;\n\t\tinstruments: {\n\t\t\t[id: string]: { metricType: MetricType; instrument: Counter | UpDownCounter | Gauge };\n\t\t};\n\t} {\n\t\tconst node = contextIds[ContextIdKeys.Node];\n\t\tconst tenantId = contextIds[ContextIdKeys.Tenant];\n\n\t\tconst key = `${node ?? \"\"}/${tenantId ?? \"\"}`;\n\n\t\tlet cached = this._providers[key];\n\t\tif (!Is.undefined(cached)) {\n\t\t\treturn cached;\n\t\t}\n\n\t\tconst readers = this.createReaders();\n\t\tconst resourcePrefix = \"service\";\n\t\tconst resourceAttrs: { [id: string]: string } = {};\n\t\tif (Is.stringValue(node)) {\n\t\t\tresourceAttrs[`${resourcePrefix}.instance.id`] = node;\n\t\t}\n\t\tif (Is.stringValue(tenantId)) {\n\t\t\tresourceAttrs[`${resourcePrefix}.namespace`] = tenantId;\n\t\t}\n\t\tconst resource =\n\t\t\tObject.keys(resourceAttrs).length > 0 ? resourceFromAttributes(resourceAttrs) : undefined;\n\t\tconst meterProvider = new MeterProvider({ readers, resource });\n\t\tconst meter = meterProvider.getMeter(\n\t\t\tthis._config.meterName ?? \"twin-telemetry\",\n\t\t\tthis._config.meterVersion ?? \"1.0.0\"\n\t\t);\n\t\tcached = { meterProvider, meter, instruments: {} };\n\t\tthis._providers[key] = cached;\n\n\t\treturn cached;\n\t}\n\n\t/**\n\t * Instantiate fresh MetricReader instances from the connector config.\n\t * @returns The list of reader instances.\n\t * @internal\n\t */\n\tprivate createReaders(): MetricReader[] {\n\t\tconst readers: MetricReader[] = [];\n\t\tfor (const [, config] of Object.entries(this._config.readers ?? {})) {\n\t\t\tif (config.type === OpenTelemetryReaderTypes.Prometheus) {\n\t\t\t\treaders.push(\n\t\t\t\t\tnew PrometheusExporter({\n\t\t\t\t\t\tport: config.port,\n\t\t\t\t\t\tendpoint: config.endpoint,\n\t\t\t\t\t\tpreventServerStart: !(config.startServer ?? true),\n\t\t\t\t\t\tprefix: config.prefix\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t} else if (config.type === OpenTelemetryReaderTypes.OtlpHttp) {\n\t\t\t\treaders.push(\n\t\t\t\t\tnew PeriodicExportingMetricReader({\n\t\t\t\t\t\texporter: new OTLPMetricExporter({\n\t\t\t\t\t\t\turl: config.url,\n\t\t\t\t\t\t\theaders: config.headers\n\t\t\t\t\t\t}),\n\t\t\t\t\t\texportIntervalMillis: config.exportIntervalMs\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn readers;\n\t}\n\n\t/**\n\t * Register an OTEL instrument on a provider's instruments map if not already present.\n\t * @param id The metric id.\n\t * @param type The metric type.\n\t * @param description The metric description.\n\t * @param unit The metric unit.\n\t * @param meter The meter to create instruments on.\n\t * @param instruments The per-provider instruments map to update.\n\t * @internal\n\t */\n\tprivate registerInstrument(\n\t\tid: string,\n\t\ttype: MetricType,\n\t\tdescription: string | undefined,\n\t\tunit: string | undefined,\n\t\tmeter: Meter,\n\t\tinstruments: {\n\t\t\t[id: string]: { metricType: MetricType; instrument: Counter | UpDownCounter | Gauge };\n\t\t}\n\t): void {\n\t\tif (id in instruments) {\n\t\t\treturn;\n\t\t}\n\t\tconst instrumentOptions = { description, unit };\n\t\tlet instrument: Counter | UpDownCounter | Gauge;\n\t\tif (type === MetricType.Counter) {\n\t\t\tinstrument = meter.createCounter(id, instrumentOptions);\n\t\t} else if (type === MetricType.IncDecCounter) {\n\t\t\tinstrument = meter.createUpDownCounter(id, instrumentOptions);\n\t\t} else {\n\t\t\tinstrument = meter.createGauge(id, instrumentOptions);\n\t\t}\n\t\tinstruments[id] = { metricType: type, instrument };\n\t}\n\n\t/**\n\t * Convert customData to OTEL-compatible Attributes.\n\t * @param customData The raw custom data map.\n\t * @returns An OTEL Attributes object.\n\t * @internal\n\t */\n\tprivate toAttributes(customData?: { [key: string]: unknown }): Attributes {\n\t\tif (Is.empty(customData)) {\n\t\t\treturn {};\n\t\t}\n\t\tconst attributes: Attributes = {};\n\t\tfor (const [key, val] of Object.entries(customData)) {\n\t\t\tif (Is.string(val) || Is.number(val) || Is.boolean(val)) {\n\t\t\t\tattributes[key] = val;\n\t\t\t} else if (Is.arrayValue(val)) {\n\t\t\t\tif (Is.string(val[0]) && val.every(el => Is.string(el))) {\n\t\t\t\t\tattributes[key] = val;\n\t\t\t\t} else if (Is.number(val[0]) && val.every(el => Is.number(el))) {\n\t\t\t\t\tattributes[key] = val;\n\t\t\t\t} else if (Is.boolean(val[0]) && val.every(el => Is.boolean(el))) {\n\t\t\t\t\tattributes[key] = val;\n\t\t\t\t} else {\n\t\t\t\t\tattributes[key] = JSON.stringify(val);\n\t\t\t\t}\n\t\t\t} else if (!Is.undefined(val)) {\n\t\t\t\tattributes[key] = JSON.stringify(val);\n\t\t\t}\n\t\t}\n\t\treturn attributes;\n\t}\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type ITelemetryConnector, type ITelemetryMetric, MetricCounterOperation } from "@twin.org/telemetry-models";
1
+ import { type ITelemetryConnector, type ITelemetryMetric, type ITelemetryMetricValueEntry, MetricCounterOperation } from "@twin.org/telemetry-models";
2
2
  import type { IOpenTelemetryTelemetryConnectorConstructorOptions } from "./models/IOpenTelemetryTelemetryConnectorConstructorOptions.js";
3
3
  /**
4
4
  * Class for performing telemetry operations using OpenTelemetry instruments.
@@ -39,12 +39,12 @@ export declare class OpenTelemetryTelemetryConnector implements ITelemetryConnec
39
39
  */
40
40
  stop(nodeLoggingComponentType?: string): Promise<void>;
41
41
  /**
42
- * Register a new metric definition. If the connector is already started,
42
+ * Register one or more metric definitions. If the connector is already started,
43
43
  * the OTEL instrument is registered immediately for the current context.
44
- * @param metric The metric details.
45
- * @returns A promise that resolves when the metric has been registered.
44
+ * @param metric The metric details, or the details of several metrics.
45
+ * @returns A promise that resolves when the metrics have been registered.
46
46
  */
47
- createMetric(metric: ITelemetryMetric): Promise<void>;
47
+ createMetric(metric: ITelemetryMetric | ITelemetryMetric[]): Promise<void>;
48
48
  /**
49
49
  * Update the in-memory metadata for a registered metric.
50
50
  * OpenTelemetry instrument descriptors are immutable once created; only the
@@ -65,6 +65,12 @@ export declare class OpenTelemetryTelemetryConnector implements ITelemetryConnec
65
65
  addMetricValue(id: string, value: MetricCounterOperation | number, customData?: {
66
66
  [key: string]: unknown;
67
67
  }): Promise<string>;
68
+ /**
69
+ * Add multiple metric values.
70
+ * @param values The metric values to add.
71
+ * @returns The created metric value ids, in the order the values were supplied.
72
+ */
73
+ addMetricValues(values: ITelemetryMetricValueEntry[]): Promise<string[]>;
68
74
  /**
69
75
  * Remove a metric from the in-memory registry and from all cached provider instrument maps.
70
76
  * @param id The id of the metric.
package/docs/changelog.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.3-next.4](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.9.3-next.3...telemetry-connector-opentelemetry-v0.9.3-next.4) (2026-09-08)
4
+
5
+
6
+ ### Features
7
+
8
+ * metric values in background ([#118](https://github.com/iotaledger/twin-telemetry/issues/118)) ([4a13bc4](https://github.com/iotaledger/twin-telemetry/commit/4a13bc465847c64bd99ec19c2f6fbb10e303164e))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/telemetry-connector-entity-storage bumped from 0.9.3-next.3 to 0.9.3-next.4
16
+ * @twin.org/telemetry-models bumped from 0.9.3-next.3 to 0.9.3-next.4
17
+
18
+ ## [0.9.3-next.3](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.9.3-next.2...telemetry-connector-opentelemetry-v0.9.3-next.3) (2026-09-07)
19
+
20
+
21
+ ### Miscellaneous Chores
22
+
23
+ * **telemetry-connector-opentelemetry:** Synchronize repo versions
24
+
25
+
26
+ ### Dependencies
27
+
28
+ * The following workspace dependencies were updated
29
+ * dependencies
30
+ * @twin.org/telemetry-connector-entity-storage bumped from 0.9.3-next.2 to 0.9.3-next.3
31
+ * @twin.org/telemetry-models bumped from 0.9.3-next.2 to 0.9.3-next.3
32
+
3
33
  ## [0.9.3-next.2](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.9.3-next.1...telemetry-connector-opentelemetry-v0.9.3-next.2) (2026-09-01)
4
34
 
5
35
 
@@ -125,22 +125,22 @@ A promise that resolves when all MeterProviders have shut down.
125
125
 
126
126
  > **createMetric**(`metric`): `Promise`\<`void`\>
127
127
 
128
- Register a new metric definition. If the connector is already started,
128
+ Register one or more metric definitions. If the connector is already started,
129
129
  the OTEL instrument is registered immediately for the current context.
130
130
 
131
131
  #### Parameters
132
132
 
133
133
  ##### metric
134
134
 
135
- `ITelemetryMetric`
135
+ `ITelemetryMetric` \| `ITelemetryMetric`[]
136
136
 
137
- The metric details.
137
+ The metric details, or the details of several metrics.
138
138
 
139
139
  #### Returns
140
140
 
141
141
  `Promise`\<`void`\>
142
142
 
143
- A promise that resolves when the metric has been registered.
143
+ A promise that resolves when the metrics have been registered.
144
144
 
145
145
  #### Implementation of
146
146
 
@@ -214,6 +214,32 @@ A generated 32-character hex id for the recorded value.
214
214
 
215
215
  ***
216
216
 
217
+ ### addMetricValues() {#addmetricvalues}
218
+
219
+ > **addMetricValues**(`values`): `Promise`\<`string`[]\>
220
+
221
+ Add multiple metric values.
222
+
223
+ #### Parameters
224
+
225
+ ##### values
226
+
227
+ `ITelemetryMetricValueEntry`[]
228
+
229
+ The metric values to add.
230
+
231
+ #### Returns
232
+
233
+ `Promise`\<`string`[]\>
234
+
235
+ The created metric value ids, in the order the values were supplied.
236
+
237
+ #### Implementation of
238
+
239
+ `ITelemetryConnector.addMetricValues`
240
+
241
+ ***
242
+
217
243
  ### removeMetric() {#removemetric}
218
244
 
219
245
  > **removeMetric**(`id`): `Promise`\<`void`\>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/telemetry-connector-opentelemetry",
3
- "version": "0.9.3-next.2",
3
+ "version": "0.9.3-next.4",
4
4
  "description": "OpenTelemetry connector for pushing telemetry metrics to OTEL-compatible backends.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,8 +24,8 @@
24
24
  "@twin.org/entity-storage-models": "next",
25
25
  "@twin.org/logging-models": "next",
26
26
  "@twin.org/nameof": "next",
27
- "@twin.org/telemetry-connector-entity-storage": "0.9.3-next.2",
28
- "@twin.org/telemetry-models": "0.9.3-next.2"
27
+ "@twin.org/telemetry-connector-entity-storage": "0.9.3-next.4",
28
+ "@twin.org/telemetry-models": "0.9.3-next.4"
29
29
  },
30
30
  "main": "./dist/es/index.js",
31
31
  "types": "./dist/types/index.d.ts",