@twin.org/telemetry-connector-opentelemetry 0.0.3-next.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -72,7 +72,7 @@ export class OpenTelemetryTelemetryConnector {
72
72
  /**
73
73
  * Initialise the MeterProvider and configured exporters.
74
74
  * @param nodeLoggingComponentType The node logging component type.
75
- * @returns Nothing.
75
+ * @returns A promise that resolves when the MeterProvider is running.
76
76
  */
77
77
  async start(nodeLoggingComponentType) {
78
78
  if (!Is.undefined(this._meterProvider)) {
@@ -113,7 +113,7 @@ export class OpenTelemetryTelemetryConnector {
113
113
  * Shut down the MeterProvider and release resources.
114
114
  * Calling stop() on a connector that has not been started is a no-op.
115
115
  * @param nodeLoggingComponentType The node logging component type.
116
- * @returns Nothing.
116
+ * @returns A promise that resolves when the MeterProvider has shut down.
117
117
  */
118
118
  async stop(nodeLoggingComponentType) {
119
119
  if (!Is.undefined(this._meterProvider)) {
@@ -135,7 +135,7 @@ export class OpenTelemetryTelemetryConnector {
135
135
  * The definition is always persisted via the inner entity-storage connector.
136
136
  * If the MeterProvider is running the corresponding OTEL instrument is also registered.
137
137
  * @param metric The metric details.
138
- * @returns Nothing.
138
+ * @returns A promise that resolves when the metric has been persisted and the OTEL instrument registered.
139
139
  */
140
140
  async createMetric(metric) {
141
141
  try {
@@ -191,7 +191,7 @@ export class OpenTelemetryTelemetryConnector {
191
191
  * are NOT propagated to the registered MeterProvider and will not appear at the
192
192
  * OTEL backend (Prometheus, OTLP, etc.).
193
193
  * @param metric The metric details (type cannot be changed).
194
- * @returns Nothing.
194
+ * @returns A promise that resolves when the persisted metadata has been updated.
195
195
  */
196
196
  async updateMetric(metric) {
197
197
  return this._inner.updateMetric(metric);
@@ -248,7 +248,7 @@ export class OpenTelemetryTelemetryConnector {
248
248
  * of the process. Re-creating a metric with the same id but a different MetricType
249
249
  * is therefore not safe.
250
250
  * @param id The id of the metric.
251
- * @returns Nothing.
251
+ * @returns A promise that resolves when the metric and its value history have been removed.
252
252
  */
253
253
  async removeMetric(id) {
254
254
  this._instruments.delete(id);
@@ -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 { MeterProvider, type MetricReader } from \"@opentelemetry/sdk-metrics\";\nimport { AlreadyExistsError, BaseError, ComponentFactory, GeneralError, Is } from \"@twin.org/core\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { EntityStorageTelemetryConnector } from \"@twin.org/telemetry-connector-entity-storage\";\nimport {\n\ttype ITelemetryConnector,\n\ttype ITelemetryMetric,\n\ttype ITelemetryMetricValue,\n\tMetricCounterOperation,\n\tMetricType\n} from \"@twin.org/telemetry-models\";\nimport type { IOpenTelemetryTelemetryConnectorConfig } from \"./models/IOpenTelemetryTelemetryConnectorConfig.js\";\nimport type { IOpenTelemetryTelemetryConnectorConstructorOptions } from \"./models/IOpenTelemetryTelemetryConnectorConstructorOptions.js\";\n\n/**\n * Class for performing telemetry operations using OpenTelemetry instruments.\n * Metric definitions and value history are persisted via an internal\n * EntityStorageTelemetryConnector instance created at construction time.\n * Call `start()` to initialise the MeterProvider and exporters; metrics can be\n * created and queried before start() — OTEL forwarding is simply skipped until\n * the MeterProvider is running.\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 = \"opentelemetry\";\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 start() can initialise the MeterProvider.\n\t * @internal\n\t */\n\tprivate readonly _config: IOpenTelemetryTelemetryConnectorConfig;\n\n\t/**\n\t * Internal entity-storage connector that owns all metric metadata and value history.\n\t * Created at construction time — fails fast if entity storage is not set up.\n\t * @internal\n\t */\n\tprivate readonly _inner: EntityStorageTelemetryConnector;\n\n\t/**\n\t * Live OTEL instrument handles keyed by metric id, paired with the metric type\n\t * so addMetricValue can dispatch without querying storage.\n\t * These are runtime objects and cannot be persisted.\n\t * @internal\n\t */\n\tprivate readonly _instruments: Map<\n\t\tstring,\n\t\t{ metricType: MetricType; instrument: Counter | UpDownCounter | Gauge }\n\t>;\n\n\t/**\n\t * The MeterProvider that owns all instruments. Set by start(), cleared by stop().\n\t * @internal\n\t */\n\tprivate _meterProvider?: MeterProvider;\n\n\t/**\n\t * The Meter used to create instruments. Set by start(), cleared by stop().\n\t * @internal\n\t */\n\tprivate _meter?: Meter;\n\n\t/**\n\t * Create a new instance of OpenTelemetryTelemetryConnector.\n\t * Eagerly constructs the inner EntityStorageTelemetryConnector — if the required\n\t * entity storage types are not registered this constructor will throw (fail fast).\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: IOpenTelemetryTelemetryConnectorConstructorOptions) {\n\t\tthis._config = options?.config ?? {};\n\t\tthis._inner = new EntityStorageTelemetryConnector({\n\t\t\tloggingComponentType: options?.loggingComponentType,\n\t\t\ttelemetryMetricStorageConnectorType: options?.telemetryMetricStorageConnectorType,\n\t\t\ttelemetryMetricValueStorageConnectorType: options?.telemetryMetricValueStorageConnectorType\n\t\t});\n\t\tthis._instruments = new Map();\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 * Initialise the MeterProvider and configured exporters.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (!Is.undefined(this._meterProvider)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst readers: MetricReader[] = [];\n\t\tfor (const [, config] of Object.entries(this._config.readers ?? {})) {\n\t\t\tif (config.type === \"prometheus\") {\n\t\t\t\t// Dynamic import so @opentelemetry/exporter-prometheus is an optional peer dep;\n\t\t\t\t// consumers only need to install it if they actually configure a Prometheus reader.\n\t\t\t\tconst { PrometheusExporter: prometheusExporterClass } =\n\t\t\t\t\tawait import(\"@opentelemetry/exporter-prometheus\");\n\t\t\t\treaders.push(\n\t\t\t\t\tnew prometheusExporterClass({\n\t\t\t\t\t\tport: config.port,\n\t\t\t\t\t\tendpoint: config.endpoint,\n\t\t\t\t\t\t// PrometheusExporter uses preventServerStart (inverted); our config\n\t\t\t\t\t\t// exposes the more intuitive startServer (defaults to true).\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 {\n\t\t\t\tthrow new GeneralError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"unknownReaderType\", {\n\t\t\t\t\ttype: config.type\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis._meterProvider = new MeterProvider({ readers });\n\t\tthis._meter = this._meterProvider.getMeter(\n\t\t\tthis._config.meterName ?? \"twin-telemetry\",\n\t\t\tthis._config.meterVersion ?? \"1.0.0\"\n\t\t);\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 the MeterProvider and release resources.\n\t * Calling stop() on a connector that has not been started is a no-op.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (!Is.undefined(this._meterProvider)) {\n\t\t\tawait this._meterProvider.shutdown();\n\t\t\tthis._meterProvider = undefined;\n\t\t\tthis._meter = undefined;\n\t\t\tthis._instruments.clear();\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 * Create a new metric.\n\t * The definition is always persisted via the inner entity-storage connector.\n\t * If the MeterProvider is running the corresponding OTEL instrument is also registered.\n\t * @param metric The metric details.\n\t * @returns Nothing.\n\t */\n\tpublic async createMetric(metric: ITelemetryMetric): Promise<void> {\n\t\ttry {\n\t\t\tawait this._inner.createMetric(metric);\n\t\t} catch (err) {\n\t\t\t// Entity storage performs all validation and throws AlreadyExistsError on duplicates.\n\t\t\t// OTP doesn't care about duplicates and will create a new instrument instance on each call\n\t\t\t// so we catch this error and ignore it to allow the OTEL instruments to be registered.\n\t\t\tif (!BaseError.isErrorName(err, AlreadyExistsError.CLASS_NAME)) {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\n\t\t// Register an OTEL instrument when the MeterProvider is running.\n\t\t// This runs even when the metric already exists in storage so instruments\n\t\t// survive process restarts (AlreadyExistsError path).\n\t\tconst meter = this._meter;\n\t\tif (meter !== undefined && !this._instruments.has(metric.id)) {\n\t\t\tconst instrumentOptions = {\n\t\t\t\tdescription: metric.description,\n\t\t\t\tunit: metric.unit\n\t\t\t};\n\t\t\tlet instrument: Counter | UpDownCounter | Gauge;\n\t\t\tif (metric.type === MetricType.Counter) {\n\t\t\t\tinstrument = meter.createCounter(metric.id, instrumentOptions);\n\t\t\t} else if (metric.type === MetricType.IncDecCounter) {\n\t\t\t\tinstrument = meter.createUpDownCounter(metric.id, instrumentOptions);\n\t\t\t} else {\n\t\t\t\tinstrument = meter.createGauge(metric.id, instrumentOptions);\n\t\t\t}\n\t\t\tthis._instruments.set(metric.id, { metricType: metric.type, instrument });\n\t\t}\n\t}\n\n\t/**\n\t * Get the metric details and its most recent value.\n\t * @param id The metric id.\n\t * @returns The metric details and its most recent value.\n\t */\n\tpublic async getMetric(id: string): Promise<{\n\t\tmetric: ITelemetryMetric;\n\t\tvalue: ITelemetryMetricValue;\n\t}> {\n\t\tconst result = await this._inner.getMetric(id);\n\n\t\t// When the metric has no recorded values yet the inner connector returns\n\t\t// entities[0] = undefined via queryValues. Return a placeholder so callers\n\t\t// are not surprised by a null value field — treat id=\"\" as \"no measurements yet\".\n\t\tconst value = result.value ?? { id: \"\", ts: 0, value: 0 };\n\t\treturn { metric: result.metric, value };\n\t}\n\n\t/**\n\t * Update the metric metadata.\n\t * Note: OpenTelemetry instrument descriptors are immutable once created.\n\t * This method updates the persisted metadata mirror; the description/unit changes\n\t * are NOT propagated to the registered MeterProvider and will not appear at the\n\t * OTEL backend (Prometheus, OTLP, etc.).\n\t * @param metric The metric details (type cannot be changed).\n\t * @returns Nothing.\n\t */\n\tpublic async updateMetric(metric: Omit<ITelemetryMetric, \"type\">): Promise<void> {\n\t\treturn this._inner.updateMetric(metric);\n\t}\n\n\t/**\n\t * Record a metric value.\n\t * Entity storage always receives the value first and performs all validation.\n\t * If the MeterProvider is running the measurement is also forwarded to the OTEL instrument.\n\t * Counter accepts positive integers or \"inc\".\n\t * UpDownCounter accepts integers (positive or negative) or \"inc\"/\"dec\".\n\t * Gauge accepts any number.\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 The id of the new metric value entry.\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\t// Entity storage validates and persists first; throws NotFoundError if metric not found.\n\t\tconst valueId = await this._inner.addMetricValue(id, value, customData);\n\n\t\t// Forward to the OTEL instrument only when the MeterProvider is running.\n\t\tif (this._meter !== undefined) {\n\t\t\tconst entry = this._instruments.get(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\t// Value already validated by inner connector — dispatch unconditionally.\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 and its persisted value history.\n\t * Note: OpenTelemetry exposes no API to deregister an instrument from a Meter,\n\t * so the underlying Counter/UpDownCounter/Gauge remains resident for the lifetime\n\t * of the process. Re-creating a metric with the same id but a different MetricType\n\t * is therefore not safe.\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\tthis._instruments.delete(id);\n\t\t// The inner connector cascades and removes all associated metric values.\n\t\treturn this._inner.removeMetric(id);\n\t}\n\n\t/**\n\t * Query the registered metrics, optionally filtered by type.\n\t * @param type The type of the metric.\n\t * @param cursor The cursor to request the next page.\n\t * @param limit Limit the number of entities to return.\n\t * @returns The matching metrics and an optional cursor for the next page.\n\t */\n\tpublic async query(\n\t\ttype?: MetricType,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\tentities: ITelemetryMetric[];\n\t\tcursor?: string;\n\t}> {\n\t\treturn this._inner.query(type, cursor, limit);\n\t}\n\n\t/**\n\t * Query the recorded values for a metric, ordered by most recent first.\n\t * @param id The id of the metric.\n\t * @param timeStart The inclusive start time (epoch ms).\n\t * @param timeEnd The inclusive end time (epoch ms).\n\t * @param cursor The cursor returned by the previous call.\n\t * @param limit Limit the number of values to return.\n\t * @returns The metric details, matching values, and an optional cursor for the next page.\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\tmetric: ITelemetryMetric;\n\t\tentities: ITelemetryMetricValue[];\n\t\tcursor?: string;\n\t}> {\n\t\treturn this._inner.queryValues(id, timeStart, timeEnd, cursor, limit);\n\t}\n\n\t/**\n\t * Convert customData to OTEL-compatible Attributes.\n\t * Scalar values (string, number, boolean) and uniform primitive arrays\n\t * (string[], number[], boolean[]) are forwarded; other values are silently dropped.\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 attrs: 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\tattrs[key] = val;\n\t\t\t} else if (Is.arrayValue(val)) {\n\t\t\t\tif (\n\t\t\t\t\t(Is.string(val[0]) || Is.number(val[0]) || Is.boolean(val[0])) &&\n\t\t\t\t\tval.every(el => typeof el === typeof val[0])\n\t\t\t\t) {\n\t\t\t\t\tattrs[key] = val as string[] | number[] | boolean[];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn attrs;\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 { MeterProvider, type MetricReader } from \"@opentelemetry/sdk-metrics\";\nimport { AlreadyExistsError, BaseError, ComponentFactory, GeneralError, Is } from \"@twin.org/core\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { EntityStorageTelemetryConnector } from \"@twin.org/telemetry-connector-entity-storage\";\nimport {\n\ttype ITelemetryConnector,\n\ttype ITelemetryMetric,\n\ttype ITelemetryMetricValue,\n\tMetricCounterOperation,\n\tMetricType\n} from \"@twin.org/telemetry-models\";\nimport type { IOpenTelemetryTelemetryConnectorConfig } from \"./models/IOpenTelemetryTelemetryConnectorConfig.js\";\nimport type { IOpenTelemetryTelemetryConnectorConstructorOptions } from \"./models/IOpenTelemetryTelemetryConnectorConstructorOptions.js\";\n\n/**\n * Class for performing telemetry operations using OpenTelemetry instruments.\n * Metric definitions and value history are persisted via an internal\n * EntityStorageTelemetryConnector instance created at construction time.\n * Call `start()` to initialise the MeterProvider and exporters; metrics can be\n * created and queried before start() — OTEL forwarding is simply skipped until\n * the MeterProvider is running.\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 = \"opentelemetry\";\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 start() can initialise the MeterProvider.\n\t * @internal\n\t */\n\tprivate readonly _config: IOpenTelemetryTelemetryConnectorConfig;\n\n\t/**\n\t * Internal entity-storage connector that owns all metric metadata and value history.\n\t * Created at construction time — fails fast if entity storage is not set up.\n\t * @internal\n\t */\n\tprivate readonly _inner: EntityStorageTelemetryConnector;\n\n\t/**\n\t * Live OTEL instrument handles keyed by metric id, paired with the metric type\n\t * so addMetricValue can dispatch without querying storage.\n\t * These are runtime objects and cannot be persisted.\n\t * @internal\n\t */\n\tprivate readonly _instruments: Map<\n\t\tstring,\n\t\t{ metricType: MetricType; instrument: Counter | UpDownCounter | Gauge }\n\t>;\n\n\t/**\n\t * The MeterProvider that owns all instruments. Set by start(), cleared by stop().\n\t * @internal\n\t */\n\tprivate _meterProvider?: MeterProvider;\n\n\t/**\n\t * The Meter used to create instruments. Set by start(), cleared by stop().\n\t * @internal\n\t */\n\tprivate _meter?: Meter;\n\n\t/**\n\t * Create a new instance of OpenTelemetryTelemetryConnector.\n\t * Eagerly constructs the inner EntityStorageTelemetryConnector — if the required\n\t * entity storage types are not registered this constructor will throw (fail fast).\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: IOpenTelemetryTelemetryConnectorConstructorOptions) {\n\t\tthis._config = options?.config ?? {};\n\t\tthis._inner = new EntityStorageTelemetryConnector({\n\t\t\tloggingComponentType: options?.loggingComponentType,\n\t\t\ttelemetryMetricStorageConnectorType: options?.telemetryMetricStorageConnectorType,\n\t\t\ttelemetryMetricValueStorageConnectorType: options?.telemetryMetricValueStorageConnectorType\n\t\t});\n\t\tthis._instruments = new Map();\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 * Initialise the MeterProvider and configured exporters.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when the MeterProvider is running.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (!Is.undefined(this._meterProvider)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst readers: MetricReader[] = [];\n\t\tfor (const [, config] of Object.entries(this._config.readers ?? {})) {\n\t\t\tif (config.type === \"prometheus\") {\n\t\t\t\t// Dynamic import so @opentelemetry/exporter-prometheus is an optional peer dep;\n\t\t\t\t// consumers only need to install it if they actually configure a Prometheus reader.\n\t\t\t\tconst { PrometheusExporter: prometheusExporterClass } =\n\t\t\t\t\tawait import(\"@opentelemetry/exporter-prometheus\");\n\t\t\t\treaders.push(\n\t\t\t\t\tnew prometheusExporterClass({\n\t\t\t\t\t\tport: config.port,\n\t\t\t\t\t\tendpoint: config.endpoint,\n\t\t\t\t\t\t// PrometheusExporter uses preventServerStart (inverted); our config\n\t\t\t\t\t\t// exposes the more intuitive startServer (defaults to true).\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 {\n\t\t\t\tthrow new GeneralError(OpenTelemetryTelemetryConnector.CLASS_NAME, \"unknownReaderType\", {\n\t\t\t\t\ttype: config.type\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis._meterProvider = new MeterProvider({ readers });\n\t\tthis._meter = this._meterProvider.getMeter(\n\t\t\tthis._config.meterName ?? \"twin-telemetry\",\n\t\t\tthis._config.meterVersion ?? \"1.0.0\"\n\t\t);\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 the MeterProvider and release resources.\n\t * Calling stop() on a connector that has not been started is a no-op.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when the MeterProvider has shut down.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (!Is.undefined(this._meterProvider)) {\n\t\t\tawait this._meterProvider.shutdown();\n\t\t\tthis._meterProvider = undefined;\n\t\t\tthis._meter = undefined;\n\t\t\tthis._instruments.clear();\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 * Create a new metric.\n\t * The definition is always persisted via the inner entity-storage connector.\n\t * If the MeterProvider is running the corresponding OTEL instrument is also registered.\n\t * @param metric The metric details.\n\t * @returns A promise that resolves when the metric has been persisted and the OTEL instrument registered.\n\t */\n\tpublic async createMetric(metric: ITelemetryMetric): Promise<void> {\n\t\ttry {\n\t\t\tawait this._inner.createMetric(metric);\n\t\t} catch (err) {\n\t\t\t// Entity storage performs all validation and throws AlreadyExistsError on duplicates.\n\t\t\t// OTP doesn't care about duplicates and will create a new instrument instance on each call\n\t\t\t// so we catch this error and ignore it to allow the OTEL instruments to be registered.\n\t\t\tif (!BaseError.isErrorName(err, AlreadyExistsError.CLASS_NAME)) {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\n\t\t// Register an OTEL instrument when the MeterProvider is running.\n\t\t// This runs even when the metric already exists in storage so instruments\n\t\t// survive process restarts (AlreadyExistsError path).\n\t\tconst meter = this._meter;\n\t\tif (meter !== undefined && !this._instruments.has(metric.id)) {\n\t\t\tconst instrumentOptions = {\n\t\t\t\tdescription: metric.description,\n\t\t\t\tunit: metric.unit\n\t\t\t};\n\t\t\tlet instrument: Counter | UpDownCounter | Gauge;\n\t\t\tif (metric.type === MetricType.Counter) {\n\t\t\t\tinstrument = meter.createCounter(metric.id, instrumentOptions);\n\t\t\t} else if (metric.type === MetricType.IncDecCounter) {\n\t\t\t\tinstrument = meter.createUpDownCounter(metric.id, instrumentOptions);\n\t\t\t} else {\n\t\t\t\tinstrument = meter.createGauge(metric.id, instrumentOptions);\n\t\t\t}\n\t\t\tthis._instruments.set(metric.id, { metricType: metric.type, instrument });\n\t\t}\n\t}\n\n\t/**\n\t * Get the metric details and its most recent value.\n\t * @param id The metric id.\n\t * @returns The metric details and its most recent value.\n\t */\n\tpublic async getMetric(id: string): Promise<{\n\t\tmetric: ITelemetryMetric;\n\t\tvalue: ITelemetryMetricValue;\n\t}> {\n\t\tconst result = await this._inner.getMetric(id);\n\n\t\t// When the metric has no recorded values yet the inner connector returns\n\t\t// entities[0] = undefined via queryValues. Return a placeholder so callers\n\t\t// are not surprised by a null value field — treat id=\"\" as \"no measurements yet\".\n\t\tconst value = result.value ?? { id: \"\", ts: 0, value: 0 };\n\t\treturn { metric: result.metric, value };\n\t}\n\n\t/**\n\t * Update the metric metadata.\n\t * Note: OpenTelemetry instrument descriptors are immutable once created.\n\t * This method updates the persisted metadata mirror; the description/unit changes\n\t * are NOT propagated to the registered MeterProvider and will not appear at the\n\t * OTEL backend (Prometheus, OTLP, etc.).\n\t * @param metric The metric details (type cannot be changed).\n\t * @returns A promise that resolves when the persisted metadata has been updated.\n\t */\n\tpublic async updateMetric(metric: Omit<ITelemetryMetric, \"type\">): Promise<void> {\n\t\treturn this._inner.updateMetric(metric);\n\t}\n\n\t/**\n\t * Record a metric value.\n\t * Entity storage always receives the value first and performs all validation.\n\t * If the MeterProvider is running the measurement is also forwarded to the OTEL instrument.\n\t * Counter accepts positive integers or \"inc\".\n\t * UpDownCounter accepts integers (positive or negative) or \"inc\"/\"dec\".\n\t * Gauge accepts any number.\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 The id of the new metric value entry.\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\t// Entity storage validates and persists first; throws NotFoundError if metric not found.\n\t\tconst valueId = await this._inner.addMetricValue(id, value, customData);\n\n\t\t// Forward to the OTEL instrument only when the MeterProvider is running.\n\t\tif (this._meter !== undefined) {\n\t\t\tconst entry = this._instruments.get(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\t// Value already validated by inner connector — dispatch unconditionally.\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 and its persisted value history.\n\t * Note: OpenTelemetry exposes no API to deregister an instrument from a Meter,\n\t * so the underlying Counter/UpDownCounter/Gauge remains resident for the lifetime\n\t * of the process. Re-creating a metric with the same id but a different MetricType\n\t * is therefore not safe.\n\t * @param id The id of the metric.\n\t * @returns A promise that resolves when the metric and its value history have been removed.\n\t */\n\tpublic async removeMetric(id: string): Promise<void> {\n\t\tthis._instruments.delete(id);\n\t\t// The inner connector cascades and removes all associated metric values.\n\t\treturn this._inner.removeMetric(id);\n\t}\n\n\t/**\n\t * Query the registered metrics, optionally filtered by type.\n\t * @param type The type of the metric.\n\t * @param cursor The cursor to request the next page.\n\t * @param limit Limit the number of entities to return.\n\t * @returns The matching metrics and an optional cursor for the next page.\n\t */\n\tpublic async query(\n\t\ttype?: MetricType,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\tentities: ITelemetryMetric[];\n\t\tcursor?: string;\n\t}> {\n\t\treturn this._inner.query(type, cursor, limit);\n\t}\n\n\t/**\n\t * Query the recorded values for a metric, ordered by most recent first.\n\t * @param id The id of the metric.\n\t * @param timeStart The inclusive start time (epoch ms).\n\t * @param timeEnd The inclusive end time (epoch ms).\n\t * @param cursor The cursor returned by the previous call.\n\t * @param limit Limit the number of values to return.\n\t * @returns The metric details, matching values, and an optional cursor for the next page.\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\tmetric: ITelemetryMetric;\n\t\tentities: ITelemetryMetricValue[];\n\t\tcursor?: string;\n\t}> {\n\t\treturn this._inner.queryValues(id, timeStart, timeEnd, cursor, limit);\n\t}\n\n\t/**\n\t * Convert customData to OTEL-compatible Attributes.\n\t * Scalar values (string, number, boolean) and uniform primitive arrays\n\t * (string[], number[], boolean[]) are forwarded; other values are silently dropped.\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 attrs: 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\tattrs[key] = val;\n\t\t\t} else if (Is.arrayValue(val)) {\n\t\t\t\tif (\n\t\t\t\t\t(Is.string(val[0]) || Is.number(val[0]) || Is.boolean(val[0])) &&\n\t\t\t\t\tval.every(el => typeof el === typeof val[0])\n\t\t\t\t) {\n\t\t\t\t\tattrs[key] = val as string[] | number[] | boolean[];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn attrs;\n\t}\n}\n"]}
@@ -32,14 +32,14 @@ export declare class OpenTelemetryTelemetryConnector implements ITelemetryConnec
32
32
  /**
33
33
  * Initialise the MeterProvider and configured exporters.
34
34
  * @param nodeLoggingComponentType The node logging component type.
35
- * @returns Nothing.
35
+ * @returns A promise that resolves when the MeterProvider is running.
36
36
  */
37
37
  start(nodeLoggingComponentType?: string): Promise<void>;
38
38
  /**
39
39
  * Shut down the MeterProvider and release resources.
40
40
  * Calling stop() on a connector that has not been started is a no-op.
41
41
  * @param nodeLoggingComponentType The node logging component type.
42
- * @returns Nothing.
42
+ * @returns A promise that resolves when the MeterProvider has shut down.
43
43
  */
44
44
  stop(nodeLoggingComponentType?: string): Promise<void>;
45
45
  /**
@@ -47,7 +47,7 @@ export declare class OpenTelemetryTelemetryConnector implements ITelemetryConnec
47
47
  * The definition is always persisted via the inner entity-storage connector.
48
48
  * If the MeterProvider is running the corresponding OTEL instrument is also registered.
49
49
  * @param metric The metric details.
50
- * @returns Nothing.
50
+ * @returns A promise that resolves when the metric has been persisted and the OTEL instrument registered.
51
51
  */
52
52
  createMetric(metric: ITelemetryMetric): Promise<void>;
53
53
  /**
@@ -66,7 +66,7 @@ export declare class OpenTelemetryTelemetryConnector implements ITelemetryConnec
66
66
  * are NOT propagated to the registered MeterProvider and will not appear at the
67
67
  * OTEL backend (Prometheus, OTLP, etc.).
68
68
  * @param metric The metric details (type cannot be changed).
69
- * @returns Nothing.
69
+ * @returns A promise that resolves when the persisted metadata has been updated.
70
70
  */
71
71
  updateMetric(metric: Omit<ITelemetryMetric, "type">): Promise<void>;
72
72
  /**
@@ -91,7 +91,7 @@ export declare class OpenTelemetryTelemetryConnector implements ITelemetryConnec
91
91
  * of the process. Re-creating a metric with the same id but a different MetricType
92
92
  * is therefore not safe.
93
93
  * @param id The id of the metric.
94
- * @returns Nothing.
94
+ * @returns A promise that resolves when the metric and its value history have been removed.
95
95
  */
96
96
  removeMetric(id: string): Promise<void>;
97
97
  /**
package/docs/changelog.md CHANGED
@@ -1,5 +1,100 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.0](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.9.0...telemetry-connector-opentelemetry-v0.9.0) (2026-06-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * release to production ([df2151d](https://github.com/iotaledger/twin-telemetry/commit/df2151d24844fd2c3e6092ce3a6f888ac16219a0))
9
+ * release to production ([#50](https://github.com/iotaledger/twin-telemetry/issues/50)) ([192bfe3](https://github.com/iotaledger/twin-telemetry/commit/192bfe3bea060163f2887e51fc6c2ceb74a7683f))
10
+
11
+ ## [0.9.0-next.1](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.9.0-next.0...telemetry-connector-opentelemetry-v0.9.0-next.1) (2026-06-23)
12
+
13
+
14
+ ### Features
15
+
16
+ * add helper and command types ([7166013](https://github.com/iotaledger/twin-telemetry/commit/7166013f8a0693a1d92101cb600c37a1aba66417))
17
+ * add metrics producer infrastructure ([#30](https://github.com/iotaledger/twin-telemetry/issues/30)) ([8990b99](https://github.com/iotaledger/twin-telemetry/commit/8990b990d22f331d44562c2781c9b6ddf846db88))
18
+ * add OpenTelemetry connector, tests and a graphana example ([#22](https://github.com/iotaledger/twin-telemetry/issues/22)) ([ae3e08f](https://github.com/iotaledger/twin-telemetry/commit/ae3e08f459cb20ff5d2a149982676de8c2f90ae1))
19
+ * improve open telemetry config ([8803201](https://github.com/iotaledger/twin-telemetry/commit/8803201611b1799a00cd657e0675f85596c4edce))
20
+ * typescript 6 update ([0acecc2](https://github.com/iotaledger/twin-telemetry/commit/0acecc2692b174fbaec6a8a89bd9277fa3530b5f))
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * docs ([acc23a6](https://github.com/iotaledger/twin-telemetry/commit/acc23a674e75752e3817e2717d6b029d0b1404ff))
26
+ * open-telemetry config options ([c35ee76](https://github.com/iotaledger/twin-telemetry/commit/c35ee764ccad9168985fcac6efc3461422884ce4))
27
+ * use async getStore in tests ([da1ea59](https://github.com/iotaledger/twin-telemetry/commit/da1ea5948c7ece9c614d9e9056fe6a4efab16180))
28
+ * use async getStore in tests ([38dade0](https://github.com/iotaledger/twin-telemetry/commit/38dade0537b30e10ef598d3303328136f5c113eb))
29
+
30
+
31
+ ### Dependencies
32
+
33
+ * The following workspace dependencies were updated
34
+ * dependencies
35
+ * @twin.org/telemetry-connector-entity-storage bumped from 0.9.0-next.0 to 0.9.0-next.1
36
+ * @twin.org/telemetry-models bumped from 0.9.0-next.0 to 0.9.0-next.1
37
+
38
+ ## [0.0.3-next.13](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.0.3-next.12...telemetry-connector-opentelemetry-v0.0.3-next.13) (2026-06-11)
39
+
40
+
41
+ ### Miscellaneous Chores
42
+
43
+ * **telemetry-connector-opentelemetry:** Synchronize repo versions
44
+
45
+
46
+ ### Dependencies
47
+
48
+ * The following workspace dependencies were updated
49
+ * dependencies
50
+ * @twin.org/telemetry-connector-entity-storage bumped from 0.0.3-next.12 to 0.0.3-next.13
51
+ * @twin.org/telemetry-models bumped from 0.0.3-next.12 to 0.0.3-next.13
52
+
53
+ ## [0.0.3-next.12](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.0.3-next.11...telemetry-connector-opentelemetry-v0.0.3-next.12) (2026-06-08)
54
+
55
+
56
+ ### Miscellaneous Chores
57
+
58
+ * **telemetry-connector-opentelemetry:** Synchronize repo versions
59
+
60
+
61
+ ### Dependencies
62
+
63
+ * The following workspace dependencies were updated
64
+ * dependencies
65
+ * @twin.org/telemetry-connector-entity-storage bumped from 0.0.3-next.11 to 0.0.3-next.12
66
+ * @twin.org/telemetry-models bumped from 0.0.3-next.11 to 0.0.3-next.12
67
+
68
+ ## [0.0.3-next.11](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.0.3-next.10...telemetry-connector-opentelemetry-v0.0.3-next.11) (2026-06-04)
69
+
70
+
71
+ ### Miscellaneous Chores
72
+
73
+ * **telemetry-connector-opentelemetry:** Synchronize repo versions
74
+
75
+
76
+ ### Dependencies
77
+
78
+ * The following workspace dependencies were updated
79
+ * dependencies
80
+ * @twin.org/telemetry-connector-entity-storage bumped from 0.0.3-next.10 to 0.0.3-next.11
81
+ * @twin.org/telemetry-models bumped from 0.0.3-next.10 to 0.0.3-next.11
82
+
83
+ ## [0.0.3-next.10](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.0.3-next.9...telemetry-connector-opentelemetry-v0.0.3-next.10) (2026-05-20)
84
+
85
+
86
+ ### Miscellaneous Chores
87
+
88
+ * **telemetry-connector-opentelemetry:** Synchronize repo versions
89
+
90
+
91
+ ### Dependencies
92
+
93
+ * The following workspace dependencies were updated
94
+ * dependencies
95
+ * @twin.org/telemetry-connector-entity-storage bumped from 0.0.3-next.9 to 0.0.3-next.10
96
+ * @twin.org/telemetry-models bumped from 0.0.3-next.9 to 0.0.3-next.10
97
+
3
98
  ## [0.0.3-next.9](https://github.com/iotaledger/twin-telemetry/compare/telemetry-connector-opentelemetry-v0.0.3-next.8...telemetry-connector-opentelemetry-v0.0.3-next.9) (2026-05-20)
4
99
 
5
100
 
@@ -87,7 +87,7 @@ The node logging component type.
87
87
 
88
88
  `Promise`\<`void`\>
89
89
 
90
- Nothing.
90
+ A promise that resolves when the MeterProvider is running.
91
91
 
92
92
  #### Implementation of
93
93
 
@@ -114,7 +114,7 @@ The node logging component type.
114
114
 
115
115
  `Promise`\<`void`\>
116
116
 
117
- Nothing.
117
+ A promise that resolves when the MeterProvider has shut down.
118
118
 
119
119
  #### Implementation of
120
120
 
@@ -142,7 +142,7 @@ The metric details.
142
142
 
143
143
  `Promise`\<`void`\>
144
144
 
145
- Nothing.
145
+ A promise that resolves when the metric has been persisted and the OTEL instrument registered.
146
146
 
147
147
  #### Implementation of
148
148
 
@@ -198,7 +198,7 @@ The metric details (type cannot be changed).
198
198
 
199
199
  `Promise`\<`void`\>
200
200
 
201
- Nothing.
201
+ A promise that resolves when the persisted metadata has been updated.
202
202
 
203
203
  #### Implementation of
204
204
 
@@ -269,7 +269,7 @@ The id of the metric.
269
269
 
270
270
  `Promise`\<`void`\>
271
271
 
272
- Nothing.
272
+ A promise that resolves when the metric and its value history have been removed.
273
273
 
274
274
  #### Implementation of
275
275
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@twin.org/telemetry-connector-opentelemetry",
3
- "version": "0.0.3-next.9",
3
+ "version": "0.9.0",
4
4
  "description": "OpenTelemetry connector for pushing telemetry metrics to OTEL-compatible backends.",
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-connector-opentelemetry"
9
9
  },
10
10
  "author": "adrian.sanchez.sequeira@iota.org",
@@ -15,13 +15,13 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@opentelemetry/api": "1.9.1",
18
- "@opentelemetry/sdk-metrics": "2.7.1",
19
- "@twin.org/core": "next",
20
- "@twin.org/entity-storage-models": "next",
21
- "@twin.org/logging-models": "next",
22
- "@twin.org/nameof": "next",
23
- "@twin.org/telemetry-connector-entity-storage": "0.0.3-next.9",
24
- "@twin.org/telemetry-models": "0.0.3-next.9"
18
+ "@opentelemetry/sdk-metrics": "2.8.0",
19
+ "@twin.org/core": "^0.9.0",
20
+ "@twin.org/entity-storage-models": "^0.9.0",
21
+ "@twin.org/logging-models": "^0.9.0",
22
+ "@twin.org/nameof": "^0.9.0",
23
+ "@twin.org/telemetry-connector-entity-storage": "^0.9.0",
24
+ "@twin.org/telemetry-models": "^0.9.0"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@opentelemetry/exporter-prometheus": ">=0.200.0"
@@ -64,7 +64,7 @@
64
64
  "integration"
65
65
  ],
66
66
  "bugs": {
67
- "url": "git+https://github.com/iotaledger/telemetry/issues"
67
+ "url": "git+https://github.com/iotaledger/twin-telemetry/issues"
68
68
  },
69
69
  "homepage": "https://twindev.org"
70
70
  }