feat: Complete zCode CLI X with Telegram bot integration

- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation

🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
This commit is contained in:
admin
2026-05-05 09:01:26 +00:00
Unverified
parent 4a7035dd92
commit 875c7f9b91
24688 changed files with 3224957 additions and 221 deletions

View File

@@ -0,0 +1,32 @@
import type { HrTime } from '@opentelemetry/api';
import type { Accumulation, Aggregator } from '../aggregator/types';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
import { MetricStorage } from './MetricStorage';
import type { MetricData } from '../export/MetricData';
import type { Maybe } from '../utils';
import type { MetricCollectorHandle } from './MetricCollector';
import { AttributeHashMap } from './HashMap';
import type { AsyncWritableMetricStorage } from './WritableMetricStorage';
import type { IAttributesProcessor } from '../view/AttributesProcessor';
/**
* Internal interface.
*
* Stores and aggregates {@link MetricData} for asynchronous instruments.
*/
export declare class AsyncMetricStorage<T extends Maybe<Accumulation>> extends MetricStorage implements AsyncWritableMetricStorage {
private _aggregationCardinalityLimit?;
private _deltaMetricStorage;
private _temporalMetricStorage;
private _attributesProcessor;
constructor(_instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, attributesProcessor: IAttributesProcessor, collectorHandles: MetricCollectorHandle[], aggregationCardinalityLimit?: number);
record(measurements: AttributeHashMap<number>, observationTime: HrTime): void;
/**
* Collects the metrics from this storage. The ObservableCallback is invoked
* during the collection.
*
* Note: This is a stateful operation and may reset any interval-related
* state for the MetricCollector.
*/
collect(collector: MetricCollectorHandle, collectionTime: HrTime): Maybe<MetricData>;
}
//# sourceMappingURL=AsyncMetricStorage.d.ts.map

View File

@@ -0,0 +1,45 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { MetricStorage } from './MetricStorage';
import { DeltaMetricProcessor } from './DeltaMetricProcessor';
import { TemporalMetricProcessor } from './TemporalMetricProcessor';
import { AttributeHashMap } from './HashMap';
/**
* Internal interface.
*
* Stores and aggregates {@link MetricData} for asynchronous instruments.
*/
export class AsyncMetricStorage extends MetricStorage {
_aggregationCardinalityLimit;
_deltaMetricStorage;
_temporalMetricStorage;
_attributesProcessor;
constructor(_instrumentDescriptor, aggregator, attributesProcessor, collectorHandles, aggregationCardinalityLimit) {
super(_instrumentDescriptor);
this._aggregationCardinalityLimit = aggregationCardinalityLimit;
this._deltaMetricStorage = new DeltaMetricProcessor(aggregator, this._aggregationCardinalityLimit);
this._temporalMetricStorage = new TemporalMetricProcessor(aggregator, collectorHandles);
this._attributesProcessor = attributesProcessor;
}
record(measurements, observationTime) {
const processed = new AttributeHashMap();
Array.from(measurements.entries()).forEach(([attributes, value]) => {
processed.set(this._attributesProcessor.process(attributes), value);
});
this._deltaMetricStorage.batchCumulate(processed, observationTime);
}
/**
* Collects the metrics from this storage. The ObservableCallback is invoked
* during the collection.
*
* Note: This is a stateful operation and may reset any interval-related
* state for the MetricCollector.
*/
collect(collector, collectionTime) {
const accumulations = this._deltaMetricStorage.collect();
return this._temporalMetricStorage.buildMetrics(collector, this._instrumentDescriptor, accumulations, collectionTime);
}
}
//# sourceMappingURL=AsyncMetricStorage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"AsyncMetricStorage.js","sourceRoot":"","sources":["../../../src/state/AsyncMetricStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAI7C;;;;GAIG;AACH,MAAM,OAAO,kBACX,SAAQ,aAAa;IAGb,4BAA4B,CAAU;IACtC,mBAAmB,CAA0B;IAC7C,sBAAsB,CAA6B;IACnD,oBAAoB,CAAuB;IAEnD,YACE,qBAA2C,EAC3C,UAAyB,EACzB,mBAAyC,EACzC,gBAAyC,EACzC,2BAAoC;QAEpC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC7B,IAAI,CAAC,4BAA4B,GAAG,2BAA2B,CAAC;QAChE,IAAI,CAAC,mBAAmB,GAAG,IAAI,oBAAoB,CACjD,UAAU,EACV,IAAI,CAAC,4BAA4B,CAClC,CAAC;QACF,IAAI,CAAC,sBAAsB,GAAG,IAAI,uBAAuB,CACvD,UAAU,EACV,gBAAgB,CACjB,CAAC;QACF,IAAI,CAAC,oBAAoB,GAAG,mBAAmB,CAAC;IAClD,CAAC;IAED,MAAM,CAAC,YAAsC,EAAE,eAAuB;QACpE,MAAM,SAAS,GAAG,IAAI,gBAAgB,EAAU,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE;YACjE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CACL,SAAgC,EAChC,cAAsB;QAEtB,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;QAEzD,OAAO,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAC7C,SAAS,EACT,IAAI,CAAC,qBAAqB,EAC1B,aAAa,EACb,cAAc,CACf,CAAC;IACJ,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { HrTime } from '@opentelemetry/api';\nimport type { Accumulation, Aggregator } from '../aggregator/types';\nimport type { InstrumentDescriptor } from '../InstrumentDescriptor';\nimport { MetricStorage } from './MetricStorage';\nimport type { MetricData } from '../export/MetricData';\nimport { DeltaMetricProcessor } from './DeltaMetricProcessor';\nimport { TemporalMetricProcessor } from './TemporalMetricProcessor';\nimport type { Maybe } from '../utils';\nimport type { MetricCollectorHandle } from './MetricCollector';\nimport { AttributeHashMap } from './HashMap';\nimport type { AsyncWritableMetricStorage } from './WritableMetricStorage';\nimport type { IAttributesProcessor } from '../view/AttributesProcessor';\n\n/**\n * Internal interface.\n *\n * Stores and aggregates {@link MetricData} for asynchronous instruments.\n */\nexport class AsyncMetricStorage<T extends Maybe<Accumulation>>\n extends MetricStorage\n implements AsyncWritableMetricStorage\n{\n private _aggregationCardinalityLimit?: number;\n private _deltaMetricStorage: DeltaMetricProcessor<T>;\n private _temporalMetricStorage: TemporalMetricProcessor<T>;\n private _attributesProcessor: IAttributesProcessor;\n\n constructor(\n _instrumentDescriptor: InstrumentDescriptor,\n aggregator: Aggregator<T>,\n attributesProcessor: IAttributesProcessor,\n collectorHandles: MetricCollectorHandle[],\n aggregationCardinalityLimit?: number\n ) {\n super(_instrumentDescriptor);\n this._aggregationCardinalityLimit = aggregationCardinalityLimit;\n this._deltaMetricStorage = new DeltaMetricProcessor(\n aggregator,\n this._aggregationCardinalityLimit\n );\n this._temporalMetricStorage = new TemporalMetricProcessor(\n aggregator,\n collectorHandles\n );\n this._attributesProcessor = attributesProcessor;\n }\n\n record(measurements: AttributeHashMap<number>, observationTime: HrTime) {\n const processed = new AttributeHashMap<number>();\n Array.from(measurements.entries()).forEach(([attributes, value]) => {\n processed.set(this._attributesProcessor.process(attributes), value);\n });\n this._deltaMetricStorage.batchCumulate(processed, observationTime);\n }\n\n /**\n * Collects the metrics from this storage. The ObservableCallback is invoked\n * during the collection.\n *\n * Note: This is a stateful operation and may reset any interval-related\n * state for the MetricCollector.\n */\n collect(\n collector: MetricCollectorHandle,\n collectionTime: HrTime\n ): Maybe<MetricData> {\n const accumulations = this._deltaMetricStorage.collect();\n\n return this._temporalMetricStorage.buildMetrics(\n collector,\n this._instrumentDescriptor,\n accumulations,\n collectionTime\n );\n }\n}\n"]}

View File

@@ -0,0 +1,28 @@
import type { Context, HrTime, Attributes } from '@opentelemetry/api';
import type { Maybe } from '../utils';
import type { Accumulation, Aggregator } from '../aggregator/types';
import { AttributeHashMap } from './HashMap';
/**
* Internal interface.
*
* Allows synchronous collection of metrics. This processor should allow
* allocation of new aggregation cells for metrics and convert cumulative
* recording to delta data points.
*/
export declare class DeltaMetricProcessor<T extends Maybe<Accumulation>> {
private _activeCollectionStorage;
private _cumulativeMemoStorage;
private _cardinalityLimit;
private _overflowAttributes;
private _overflowHashCode;
private _aggregator;
constructor(aggregator: Aggregator<T>, aggregationCardinalityLimit?: number);
record(value: number, attributes: Attributes, _context: Context, collectionTime: HrTime): void;
batchCumulate(measurements: AttributeHashMap<number>, collectionTime: HrTime): void;
/**
* Returns a collection of delta metrics. Start time is the when first
* time event collected.
*/
collect(): AttributeHashMap<T>;
}
//# sourceMappingURL=DeltaMetricProcessor.d.ts.map

View File

@@ -0,0 +1,88 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { hashAttributes } from '../utils';
import { AttributeHashMap } from './HashMap';
/**
* Internal interface.
*
* Allows synchronous collection of metrics. This processor should allow
* allocation of new aggregation cells for metrics and convert cumulative
* recording to delta data points.
*/
export class DeltaMetricProcessor {
_activeCollectionStorage = new AttributeHashMap();
// TODO: find a reasonable mean to clean the memo;
// https://github.com/open-telemetry/opentelemetry-specification/pull/2208
_cumulativeMemoStorage = new AttributeHashMap();
_cardinalityLimit;
_overflowAttributes = { 'otel.metric.overflow': true };
_overflowHashCode;
_aggregator;
constructor(aggregator, aggregationCardinalityLimit) {
this._aggregator = aggregator;
this._cardinalityLimit = (aggregationCardinalityLimit ?? 2000) - 1;
this._overflowHashCode = hashAttributes(this._overflowAttributes);
}
record(value, attributes, _context, collectionTime) {
let accumulation = this._activeCollectionStorage.get(attributes);
if (!accumulation) {
if (this._activeCollectionStorage.size >= this._cardinalityLimit) {
const overflowAccumulation = this._activeCollectionStorage.getOrDefault(this._overflowAttributes, () => this._aggregator.createAccumulation(collectionTime));
overflowAccumulation?.record(value);
return;
}
accumulation = this._aggregator.createAccumulation(collectionTime);
this._activeCollectionStorage.set(attributes, accumulation);
}
accumulation?.record(value);
}
batchCumulate(measurements, collectionTime) {
Array.from(measurements.entries()).forEach(([attributes, value, hashCode]) => {
const accumulation = this._aggregator.createAccumulation(collectionTime);
accumulation?.record(value);
let delta = accumulation;
// Diff with recorded cumulative memo.
if (this._cumulativeMemoStorage.has(attributes, hashCode)) {
// has() returned true, previous is present.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const previous = this._cumulativeMemoStorage.get(attributes, hashCode);
delta = this._aggregator.diff(previous, accumulation);
}
else {
// If the cardinality limit is reached, we need to change the attributes
if (this._cumulativeMemoStorage.size >= this._cardinalityLimit) {
attributes = this._overflowAttributes;
hashCode = this._overflowHashCode;
if (this._cumulativeMemoStorage.has(attributes, hashCode)) {
// has() returned true, previous is present.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const previous = this._cumulativeMemoStorage.get(attributes, hashCode);
delta = this._aggregator.diff(previous, accumulation);
}
}
}
// Merge with uncollected active delta.
if (this._activeCollectionStorage.has(attributes, hashCode)) {
// has() returned true, active is present.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const active = this._activeCollectionStorage.get(attributes, hashCode);
delta = this._aggregator.merge(active, delta);
}
// Save the current record and the delta record.
this._cumulativeMemoStorage.set(attributes, accumulation, hashCode);
this._activeCollectionStorage.set(attributes, delta, hashCode);
});
}
/**
* Returns a collection of delta metrics. Start time is the when first
* time event collected.
*/
collect() {
const unreportedDelta = this._activeCollectionStorage;
this._activeCollectionStorage = new AttributeHashMap();
return unreportedDelta;
}
}
//# sourceMappingURL=DeltaMetricProcessor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import type { Attributes } from '@opentelemetry/api';
export interface Hash<ValueType, HashCodeType> {
(value: ValueType): HashCodeType;
}
export declare class HashMap<KeyType, ValueType, HashCodeType> {
private _valueMap;
private _keyMap;
private _hash;
constructor(hash: Hash<KeyType, HashCodeType>);
get(key: KeyType, hashCode?: HashCodeType): ValueType | undefined;
getOrDefault(key: KeyType, defaultFactory: () => ValueType): ValueType | undefined;
set(key: KeyType, value: ValueType, hashCode?: HashCodeType): void;
has(key: KeyType, hashCode?: HashCodeType): boolean;
keys(): IterableIterator<[KeyType, HashCodeType]>;
entries(): IterableIterator<[KeyType, ValueType, HashCodeType]>;
get size(): number;
}
export declare class AttributeHashMap<ValueType> extends HashMap<Attributes, ValueType, string> {
constructor();
}
//# sourceMappingURL=HashMap.d.ts.map

View File

@@ -0,0 +1,67 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { hashAttributes } from '../utils';
export class HashMap {
_valueMap = new Map();
_keyMap = new Map();
_hash;
constructor(hash) {
this._hash = hash;
}
get(key, hashCode) {
hashCode ??= this._hash(key);
return this._valueMap.get(hashCode);
}
getOrDefault(key, defaultFactory) {
const hash = this._hash(key);
if (this._valueMap.has(hash)) {
return this._valueMap.get(hash);
}
const val = defaultFactory();
if (!this._keyMap.has(hash)) {
this._keyMap.set(hash, key);
}
this._valueMap.set(hash, val);
return val;
}
set(key, value, hashCode) {
hashCode ??= this._hash(key);
if (!this._keyMap.has(hashCode)) {
this._keyMap.set(hashCode, key);
}
this._valueMap.set(hashCode, value);
}
has(key, hashCode) {
hashCode ??= this._hash(key);
return this._valueMap.has(hashCode);
}
*keys() {
const keyIterator = this._keyMap.entries();
let next = keyIterator.next();
while (next.done !== true) {
yield [next.value[1], next.value[0]];
next = keyIterator.next();
}
}
*entries() {
const valueIterator = this._valueMap.entries();
let next = valueIterator.next();
while (next.done !== true) {
// next.value[0] here can not be undefined
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
yield [this._keyMap.get(next.value[0]), next.value[1], next.value[0]];
next = valueIterator.next();
}
}
get size() {
return this._valueMap.size;
}
}
export class AttributeHashMap extends HashMap {
constructor() {
super(hashAttributes);
}
}
//# sourceMappingURL=HashMap.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HashMap.js","sourceRoot":"","sources":["../../../src/state/HashMap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM1C,MAAM,OAAO,OAAO;IACV,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC/C,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC3C,KAAK,CAAC;IAEd,YAAY,IAAiC;QAC3C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,GAAG,CAAC,GAAY,EAAE,QAAuB;QACvC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,YAAY,CAAC,GAAY,EAAE,cAA+B;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;SACjC;QACD,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;SAC7B;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,GAAG,CAAC,GAAY,EAAE,KAAgB,EAAE,QAAuB;QACzD,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;SACjC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,GAAG,CAAC,GAAY,EAAE,QAAuB;QACvC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,CAAC,IAAI;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;YACzB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;SAC3B;IACH,CAAC;IAED,CAAC,OAAO;QACN,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QAC/C,IAAI,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;YACzB,0CAA0C;YAC1C,oEAAoE;YACpE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;SAC7B;IACH,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,gBAA4B,SAAQ,OAIhD;IACC;QACE,KAAK,CAAC,cAAc,CAAC,CAAC;IACxB,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Attributes } from '@opentelemetry/api';\nimport { hashAttributes } from '../utils';\n\nexport interface Hash<ValueType, HashCodeType> {\n (value: ValueType): HashCodeType;\n}\n\nexport class HashMap<KeyType, ValueType, HashCodeType> {\n private _valueMap = new Map<HashCodeType, ValueType>();\n private _keyMap = new Map<HashCodeType, KeyType>();\n private _hash;\n\n constructor(hash: Hash<KeyType, HashCodeType>) {\n this._hash = hash;\n }\n\n get(key: KeyType, hashCode?: HashCodeType) {\n hashCode ??= this._hash(key);\n return this._valueMap.get(hashCode);\n }\n\n getOrDefault(key: KeyType, defaultFactory: () => ValueType) {\n const hash = this._hash(key);\n if (this._valueMap.has(hash)) {\n return this._valueMap.get(hash);\n }\n const val = defaultFactory();\n if (!this._keyMap.has(hash)) {\n this._keyMap.set(hash, key);\n }\n this._valueMap.set(hash, val);\n return val;\n }\n\n set(key: KeyType, value: ValueType, hashCode?: HashCodeType) {\n hashCode ??= this._hash(key);\n if (!this._keyMap.has(hashCode)) {\n this._keyMap.set(hashCode, key);\n }\n this._valueMap.set(hashCode, value);\n }\n\n has(key: KeyType, hashCode?: HashCodeType) {\n hashCode ??= this._hash(key);\n return this._valueMap.has(hashCode);\n }\n\n *keys(): IterableIterator<[KeyType, HashCodeType]> {\n const keyIterator = this._keyMap.entries();\n let next = keyIterator.next();\n while (next.done !== true) {\n yield [next.value[1], next.value[0]];\n next = keyIterator.next();\n }\n }\n\n *entries(): IterableIterator<[KeyType, ValueType, HashCodeType]> {\n const valueIterator = this._valueMap.entries();\n let next = valueIterator.next();\n while (next.done !== true) {\n // next.value[0] here can not be undefined\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n yield [this._keyMap.get(next.value[0])!, next.value[1], next.value[0]];\n next = valueIterator.next();\n }\n }\n\n get size() {\n return this._valueMap.size;\n }\n}\n\nexport class AttributeHashMap<ValueType> extends HashMap<\n Attributes,\n ValueType,\n string\n> {\n constructor() {\n super(hashAttributes);\n }\n}\n"]}

View File

@@ -0,0 +1,20 @@
import type { InstrumentationScope } from '@opentelemetry/core';
import type { Resource } from '@opentelemetry/resources';
import { ViewRegistry } from '../view/ViewRegistry';
import { MeterSharedState } from './MeterSharedState';
import type { MetricCollector, MetricCollectorHandle } from './MetricCollector';
import type { Aggregation } from '../view/Aggregation';
import type { InstrumentType } from '../export/MetricData';
/**
* An internal record for shared meter provider states.
*/
export declare class MeterProviderSharedState {
viewRegistry: ViewRegistry;
metricCollectors: MetricCollector[];
meterSharedStates: Map<string, MeterSharedState>;
resource: Resource;
constructor(resource: Resource);
getMeterSharedState(instrumentationScope: InstrumentationScope): MeterSharedState;
selectAggregations(instrumentType: InstrumentType): [MetricCollectorHandle, Aggregation][];
}
//# sourceMappingURL=MeterProviderSharedState.d.ts.map

View File

@@ -0,0 +1,40 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { instrumentationScopeId } from '../utils';
import { ViewRegistry } from '../view/ViewRegistry';
import { MeterSharedState } from './MeterSharedState';
import { toAggregation } from '../view/AggregationOption';
/**
* An internal record for shared meter provider states.
*/
export class MeterProviderSharedState {
viewRegistry = new ViewRegistry();
metricCollectors = [];
meterSharedStates = new Map();
resource;
constructor(resource) {
this.resource = resource;
}
getMeterSharedState(instrumentationScope) {
const id = instrumentationScopeId(instrumentationScope);
let meterSharedState = this.meterSharedStates.get(id);
if (meterSharedState == null) {
meterSharedState = new MeterSharedState(this, instrumentationScope);
this.meterSharedStates.set(id, meterSharedState);
}
return meterSharedState;
}
selectAggregations(instrumentType) {
const result = [];
for (const collector of this.metricCollectors) {
result.push([
collector,
toAggregation(collector.selectAggregation(instrumentType)),
]);
}
return result;
}
}
//# sourceMappingURL=MeterProviderSharedState.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MeterProviderSharedState.js","sourceRoot":"","sources":["../../../src/state/MeterProviderSharedState.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI1D;;GAEG;AACH,MAAM,OAAO,wBAAwB;IACnC,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;IAElC,gBAAgB,GAAsB,EAAE,CAAC;IAEzC,iBAAiB,GAAkC,IAAI,GAAG,EAAE,CAAC;IACtD,QAAQ,CAAW;IAE1B,YAAY,QAAkB;QAC5B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,mBAAmB,CAAC,oBAA0C;QAC5D,MAAM,EAAE,GAAG,sBAAsB,CAAC,oBAAoB,CAAC,CAAC;QACxD,IAAI,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtD,IAAI,gBAAgB,IAAI,IAAI,EAAE;YAC5B,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;YACpE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;SAClD;QACD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,kBAAkB,CAAC,cAA8B;QAC/C,MAAM,MAAM,GAA2C,EAAE,CAAC;QAC1D,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAC7C,MAAM,CAAC,IAAI,CAAC;gBACV,SAAS;gBACT,aAAa,CAAC,SAAS,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;aAC3D,CAAC,CAAC;SACJ;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { InstrumentationScope } from '@opentelemetry/core';\nimport type { Resource } from '@opentelemetry/resources';\nimport { instrumentationScopeId } from '../utils';\nimport { ViewRegistry } from '../view/ViewRegistry';\nimport { MeterSharedState } from './MeterSharedState';\nimport type { MetricCollector, MetricCollectorHandle } from './MetricCollector';\nimport { toAggregation } from '../view/AggregationOption';\nimport type { Aggregation } from '../view/Aggregation';\nimport type { InstrumentType } from '../export/MetricData';\n\n/**\n * An internal record for shared meter provider states.\n */\nexport class MeterProviderSharedState {\n viewRegistry = new ViewRegistry();\n\n metricCollectors: MetricCollector[] = [];\n\n meterSharedStates: Map<string, MeterSharedState> = new Map();\n public resource: Resource;\n\n constructor(resource: Resource) {\n this.resource = resource;\n }\n\n getMeterSharedState(instrumentationScope: InstrumentationScope) {\n const id = instrumentationScopeId(instrumentationScope);\n let meterSharedState = this.meterSharedStates.get(id);\n if (meterSharedState == null) {\n meterSharedState = new MeterSharedState(this, instrumentationScope);\n this.meterSharedStates.set(id, meterSharedState);\n }\n return meterSharedState;\n }\n\n selectAggregations(instrumentType: InstrumentType) {\n const result: [MetricCollectorHandle, Aggregation][] = [];\n for (const collector of this.metricCollectors) {\n result.push([\n collector,\n toAggregation(collector.selectAggregation(instrumentType)),\n ]);\n }\n return result;\n }\n}\n"]}

View File

@@ -0,0 +1,42 @@
import type { HrTime } from '@opentelemetry/api';
import type { InstrumentationScope } from '@opentelemetry/core';
import type { MetricCollectOptions } from '../export/MetricProducer';
import type { ScopeMetrics } from '../export/MetricData';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
import { Meter } from '../Meter';
import type { Maybe } from '../utils';
import { AsyncMetricStorage } from './AsyncMetricStorage';
import type { MeterProviderSharedState } from './MeterProviderSharedState';
import type { MetricCollectorHandle } from './MetricCollector';
import { MetricStorageRegistry } from './MetricStorageRegistry';
import { MultiMetricStorage } from './MultiWritableMetricStorage';
import { ObservableRegistry } from './ObservableRegistry';
import { SyncMetricStorage } from './SyncMetricStorage';
import type { Accumulation } from '../aggregator/types';
/**
* An internal record for shared meter provider states.
*/
export declare class MeterSharedState {
metricStorageRegistry: MetricStorageRegistry;
observableRegistry: ObservableRegistry;
meter: Meter;
private _meterProviderSharedState;
private _instrumentationScope;
constructor(meterProviderSharedState: MeterProviderSharedState, instrumentationScope: InstrumentationScope);
registerMetricStorage(descriptor: InstrumentDescriptor): MultiMetricStorage | SyncMetricStorage<Maybe<Accumulation>>;
registerAsyncMetricStorage(descriptor: InstrumentDescriptor): AsyncMetricStorage<Maybe<Accumulation>>[];
/**
* @param collector opaque handle of {@link MetricCollector} which initiated the collection.
* @param collectionTime the HrTime at which the collection was initiated.
* @param options options for collection.
* @returns the list of metric data collected.
*/
collect(collector: MetricCollectorHandle, collectionTime: HrTime, options?: MetricCollectOptions): Promise<ScopeMetricsResult | null>;
private _registerMetricStorage;
}
interface ScopeMetricsResult {
scopeMetrics?: ScopeMetrics;
errors: unknown[];
}
export {};
//# sourceMappingURL=MeterSharedState.d.ts.map

View File

@@ -0,0 +1,106 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { createInstrumentDescriptorWithView } from '../InstrumentDescriptor';
import { Meter } from '../Meter';
import { AsyncMetricStorage } from './AsyncMetricStorage';
import { MetricStorageRegistry } from './MetricStorageRegistry';
import { MultiMetricStorage } from './MultiWritableMetricStorage';
import { ObservableRegistry } from './ObservableRegistry';
import { SyncMetricStorage } from './SyncMetricStorage';
import { createNoopAttributesProcessor } from '../view/AttributesProcessor';
/**
* An internal record for shared meter provider states.
*/
export class MeterSharedState {
metricStorageRegistry = new MetricStorageRegistry();
observableRegistry = new ObservableRegistry();
meter;
_meterProviderSharedState;
_instrumentationScope;
constructor(meterProviderSharedState, instrumentationScope) {
this.meter = new Meter(this);
this._meterProviderSharedState = meterProviderSharedState;
this._instrumentationScope = instrumentationScope;
}
registerMetricStorage(descriptor) {
const storages = this._registerMetricStorage(descriptor, SyncMetricStorage);
if (storages.length === 1) {
return storages[0];
}
return new MultiMetricStorage(storages);
}
registerAsyncMetricStorage(descriptor) {
const storages = this._registerMetricStorage(descriptor, AsyncMetricStorage);
return storages;
}
/**
* @param collector opaque handle of {@link MetricCollector} which initiated the collection.
* @param collectionTime the HrTime at which the collection was initiated.
* @param options options for collection.
* @returns the list of metric data collected.
*/
async collect(collector, collectionTime, options) {
/**
* 1. Call all observable callbacks first.
* 2. Collect metric result for the collector.
*/
const errors = await this.observableRegistry.observe(collectionTime, options?.timeoutMillis);
const storages = this.metricStorageRegistry.getStorages(collector);
// prevent more allocations if there are no storages.
if (storages.length === 0) {
return null;
}
const metricDataList = [];
storages.forEach(metricStorage => {
const metricData = metricStorage.collect(collector, collectionTime);
if (metricData != null) {
metricDataList.push(metricData);
}
});
// skip this scope if no data was collected (storage created, but no data observed)
if (metricDataList.length === 0) {
return { errors };
}
return {
scopeMetrics: {
scope: this._instrumentationScope,
metrics: metricDataList,
},
errors,
};
}
_registerMetricStorage(descriptor, MetricStorageType) {
const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationScope);
let storages = views.map(view => {
const viewDescriptor = createInstrumentDescriptorWithView(view, descriptor);
const compatibleStorage = this.metricStorageRegistry.findOrUpdateCompatibleStorage(viewDescriptor);
if (compatibleStorage != null) {
return compatibleStorage;
}
const aggregator = view.aggregation.createAggregator(viewDescriptor);
const viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor, this._meterProviderSharedState.metricCollectors, view.aggregationCardinalityLimit);
this.metricStorageRegistry.register(viewStorage);
return viewStorage;
});
// Fallback to the per-collector aggregations if no view is configured for the instrument.
if (storages.length === 0) {
const perCollectorAggregations = this._meterProviderSharedState.selectAggregations(descriptor.type);
const collectorStorages = perCollectorAggregations.map(([collector, aggregation]) => {
const compatibleStorage = this.metricStorageRegistry.findOrUpdateCompatibleCollectorStorage(collector, descriptor);
if (compatibleStorage != null) {
return compatibleStorage;
}
const aggregator = aggregation.createAggregator(descriptor);
const cardinalityLimit = collector.selectCardinalityLimit(descriptor.type);
const storage = new MetricStorageType(descriptor, aggregator, createNoopAttributesProcessor(), [collector], cardinalityLimit);
this.metricStorageRegistry.registerForCollector(collector, storage);
return storage;
});
storages = storages.concat(collectorStorages);
}
return storages;
}
}
//# sourceMappingURL=MeterSharedState.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,41 @@
import type { AggregationTemporalitySelector } from '../export/AggregationSelector';
import type { CollectionResult, InstrumentType } from '../export/MetricData';
import type { MetricCollectOptions, MetricProducer } from '../export/MetricProducer';
import type { IMetricReader } from '../export/MetricReader';
import type { ForceFlushOptions, ShutdownOptions } from '../types';
import type { MeterProviderSharedState } from './MeterProviderSharedState';
/**
* An internal opaque interface that the MetricReader receives as
* MetricProducer. It acts as the storage key to the internal metric stream
* state for each MetricReader.
*/
export declare class MetricCollector implements MetricProducer {
private _sharedState;
private _metricReader;
constructor(sharedState: MeterProviderSharedState, metricReader: IMetricReader);
collect(options?: MetricCollectOptions): Promise<CollectionResult>;
/**
* Delegates for MetricReader.forceFlush.
*/
forceFlush(options?: ForceFlushOptions): Promise<void>;
/**
* Delegates for MetricReader.shutdown.
*/
shutdown(options?: ShutdownOptions): Promise<void>;
selectAggregationTemporality(instrumentType: InstrumentType): import("..").AggregationTemporality;
selectAggregation(instrumentType: InstrumentType): import("..").AggregationOption;
/**
* Select the cardinality limit for the given {@link InstrumentType} for this
* collector.
*/
selectCardinalityLimit(instrumentType: InstrumentType): number;
}
/**
* An internal interface for MetricCollector. Exposes the necessary
* information for metric collection.
*/
export interface MetricCollectorHandle {
selectAggregationTemporality: AggregationTemporalitySelector;
selectCardinalityLimit(instrumentType: InstrumentType): number;
}
//# sourceMappingURL=MetricCollector.d.ts.map

View File

@@ -0,0 +1,68 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { millisToHrTime } from '@opentelemetry/core';
/**
* An internal opaque interface that the MetricReader receives as
* MetricProducer. It acts as the storage key to the internal metric stream
* state for each MetricReader.
*/
export class MetricCollector {
_sharedState;
_metricReader;
constructor(sharedState, metricReader) {
this._sharedState = sharedState;
this._metricReader = metricReader;
}
async collect(options) {
const collectionTime = millisToHrTime(Date.now());
const scopeMetrics = [];
const errors = [];
const meterCollectionPromises = Array.from(this._sharedState.meterSharedStates.values()).map(async (meterSharedState) => {
const current = await meterSharedState.collect(this, collectionTime, options);
// only add scope metrics if available
if (current?.scopeMetrics != null) {
scopeMetrics.push(current.scopeMetrics);
}
// only add errors if available
if (current?.errors != null) {
errors.push(...current.errors);
}
});
await Promise.all(meterCollectionPromises);
return {
resourceMetrics: {
resource: this._sharedState.resource,
scopeMetrics: scopeMetrics,
},
errors: errors,
};
}
/**
* Delegates for MetricReader.forceFlush.
*/
async forceFlush(options) {
await this._metricReader.forceFlush(options);
}
/**
* Delegates for MetricReader.shutdown.
*/
async shutdown(options) {
await this._metricReader.shutdown(options);
}
selectAggregationTemporality(instrumentType) {
return this._metricReader.selectAggregationTemporality(instrumentType);
}
selectAggregation(instrumentType) {
return this._metricReader.selectAggregation(instrumentType);
}
/**
* Select the cardinality limit for the given {@link InstrumentType} for this
* collector.
*/
selectCardinalityLimit(instrumentType) {
return this._metricReader.selectCardinalityLimit?.(instrumentType) ?? 2000;
}
}
//# sourceMappingURL=MetricCollector.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
import type { HrTime } from '@opentelemetry/api';
import type { MetricData } from '../export/MetricData';
import type { Maybe } from '../utils';
import type { MetricCollectorHandle } from './MetricCollector';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
/**
* Internal interface.
*
* Represents a storage from which we can collect metrics.
*/
export declare abstract class MetricStorage {
protected _instrumentDescriptor: InstrumentDescriptor;
constructor(instrumentDescriptor: InstrumentDescriptor);
/**
* Collects the metrics from this storage.
*
* Note: This is a stateful operation and may reset any interval-related
* state for the MetricCollector.
*/
abstract collect(collector: MetricCollectorHandle, collectionTime: HrTime): Maybe<MetricData>;
getInstrumentDescriptor(): Readonly<InstrumentDescriptor>;
updateDescription(description: string): void;
}
//# sourceMappingURL=MetricStorage.d.ts.map

View File

@@ -0,0 +1,28 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { createInstrumentDescriptor } from '../InstrumentDescriptor';
/**
* Internal interface.
*
* Represents a storage from which we can collect metrics.
*/
export class MetricStorage {
_instrumentDescriptor;
constructor(instrumentDescriptor) {
this._instrumentDescriptor = instrumentDescriptor;
}
getInstrumentDescriptor() {
return this._instrumentDescriptor;
}
updateDescription(description) {
this._instrumentDescriptor = createInstrumentDescriptor(this._instrumentDescriptor.name, this._instrumentDescriptor.type, {
description: description,
valueType: this._instrumentDescriptor.valueType,
unit: this._instrumentDescriptor.unit,
advice: this._instrumentDescriptor.advice,
});
}
}
//# sourceMappingURL=MetricStorage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MetricStorage.js","sourceRoot":"","sources":["../../../src/state/MetricStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAErE;;;;GAIG;AACH,MAAM,OAAgB,aAAa;IACvB,qBAAqB,CAAuB;IACtD,YAAY,oBAA0C;QACpD,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;IACpD,CAAC;IAaD,uBAAuB;QACrB,OAAO,IAAI,CAAC,qBAAqB,CAAC;IACpC,CAAC;IAED,iBAAiB,CAAC,WAAmB;QACnC,IAAI,CAAC,qBAAqB,GAAG,0BAA0B,CACrD,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAC/B,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAC/B;YACE,WAAW,EAAE,WAAW;YACxB,SAAS,EAAE,IAAI,CAAC,qBAAqB,CAAC,SAAS;YAC/C,IAAI,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI;YACrC,MAAM,EAAE,IAAI,CAAC,qBAAqB,CAAC,MAAM;SAC1C,CACF,CAAC;IACJ,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { HrTime } from '@opentelemetry/api';\nimport type { MetricData } from '../export/MetricData';\nimport type { Maybe } from '../utils';\nimport type { MetricCollectorHandle } from './MetricCollector';\nimport type { InstrumentDescriptor } from '../InstrumentDescriptor';\nimport { createInstrumentDescriptor } from '../InstrumentDescriptor';\n\n/**\n * Internal interface.\n *\n * Represents a storage from which we can collect metrics.\n */\nexport abstract class MetricStorage {\n protected _instrumentDescriptor: InstrumentDescriptor;\n constructor(instrumentDescriptor: InstrumentDescriptor) {\n this._instrumentDescriptor = instrumentDescriptor;\n }\n\n /**\n * Collects the metrics from this storage.\n *\n * Note: This is a stateful operation and may reset any interval-related\n * state for the MetricCollector.\n */\n abstract collect(\n collector: MetricCollectorHandle,\n collectionTime: HrTime\n ): Maybe<MetricData>;\n\n getInstrumentDescriptor(): Readonly<InstrumentDescriptor> {\n return this._instrumentDescriptor;\n }\n\n updateDescription(description: string): void {\n this._instrumentDescriptor = createInstrumentDescriptor(\n this._instrumentDescriptor.name,\n this._instrumentDescriptor.type,\n {\n description: description,\n valueType: this._instrumentDescriptor.valueType,\n unit: this._instrumentDescriptor.unit,\n advice: this._instrumentDescriptor.advice,\n }\n );\n }\n}\n"]}

View File

@@ -0,0 +1,19 @@
import type { MetricStorage } from './MetricStorage';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
import type { MetricCollectorHandle } from './MetricCollector';
/**
* Internal class for storing {@link MetricStorage}
*/
export declare class MetricStorageRegistry {
private readonly _sharedRegistry;
private readonly _perCollectorRegistry;
static create(): MetricStorageRegistry;
getStorages(collector: MetricCollectorHandle): MetricStorage[];
register(storage: MetricStorage): void;
registerForCollector(collector: MetricCollectorHandle, storage: MetricStorage): void;
findOrUpdateCompatibleStorage<T extends MetricStorage>(expectedDescriptor: InstrumentDescriptor): T | null;
findOrUpdateCompatibleCollectorStorage<T extends MetricStorage>(collector: MetricCollectorHandle, expectedDescriptor: InstrumentDescriptor): T | null;
private _registerStorage;
private _findOrUpdateCompatibleStorage;
}
//# sourceMappingURL=MetricStorageRegistry.d.ts.map

View File

@@ -0,0 +1,97 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { isDescriptorCompatibleWith } from '../InstrumentDescriptor';
import * as api from '@opentelemetry/api';
import { getConflictResolutionRecipe, getIncompatibilityDetails, } from '../view/RegistrationConflicts';
/**
* Internal class for storing {@link MetricStorage}
*/
export class MetricStorageRegistry {
_sharedRegistry = new Map();
_perCollectorRegistry = new Map();
static create() {
return new MetricStorageRegistry();
}
getStorages(collector) {
let storages = [];
for (const metricStorages of this._sharedRegistry.values()) {
storages = storages.concat(metricStorages);
}
const perCollectorStorages = this._perCollectorRegistry.get(collector);
if (perCollectorStorages != null) {
for (const metricStorages of perCollectorStorages.values()) {
storages = storages.concat(metricStorages);
}
}
return storages;
}
register(storage) {
this._registerStorage(storage, this._sharedRegistry);
}
registerForCollector(collector, storage) {
let storageMap = this._perCollectorRegistry.get(collector);
if (storageMap == null) {
storageMap = new Map();
this._perCollectorRegistry.set(collector, storageMap);
}
this._registerStorage(storage, storageMap);
}
findOrUpdateCompatibleStorage(expectedDescriptor) {
const storages = this._sharedRegistry.get(expectedDescriptor.name);
if (storages === undefined) {
return null;
}
// If the descriptor is compatible, the type of their metric storage
// (either SyncMetricStorage or AsyncMetricStorage) must be compatible.
return this._findOrUpdateCompatibleStorage(expectedDescriptor, storages);
}
findOrUpdateCompatibleCollectorStorage(collector, expectedDescriptor) {
const storageMap = this._perCollectorRegistry.get(collector);
if (storageMap === undefined) {
return null;
}
const storages = storageMap.get(expectedDescriptor.name);
if (storages === undefined) {
return null;
}
// If the descriptor is compatible, the type of their metric storage
// (either SyncMetricStorage or AsyncMetricStorage) must be compatible.
return this._findOrUpdateCompatibleStorage(expectedDescriptor, storages);
}
_registerStorage(storage, storageMap) {
const descriptor = storage.getInstrumentDescriptor();
const storages = storageMap.get(descriptor.name);
if (storages === undefined) {
storageMap.set(descriptor.name, [storage]);
return;
}
storages.push(storage);
}
_findOrUpdateCompatibleStorage(expectedDescriptor, existingStorages) {
let compatibleStorage = null;
for (const existingStorage of existingStorages) {
const existingDescriptor = existingStorage.getInstrumentDescriptor();
if (isDescriptorCompatibleWith(existingDescriptor, expectedDescriptor)) {
// Use the longer description if it does not match.
if (existingDescriptor.description !== expectedDescriptor.description) {
if (expectedDescriptor.description.length >
existingDescriptor.description.length) {
existingStorage.updateDescription(expectedDescriptor.description);
}
api.diag.warn('A view or instrument with the name ', expectedDescriptor.name, ' has already been registered, but has a different description and is incompatible with another registered view.\n', 'Details:\n', getIncompatibilityDetails(existingDescriptor, expectedDescriptor), 'The longer description will be used.\nTo resolve the conflict:', getConflictResolutionRecipe(existingDescriptor, expectedDescriptor));
}
// Storage is fully compatible. There will never be more than one pre-existing fully compatible storage.
compatibleStorage = existingStorage;
}
else {
// The implementation SHOULD warn about duplicate instrument registration
// conflicts after applying View configuration.
api.diag.warn('A view or instrument with the name ', expectedDescriptor.name, ' has already been registered and is incompatible with another registered view.\n', 'Details:\n', getIncompatibilityDetails(existingDescriptor, expectedDescriptor), 'To resolve the conflict:\n', getConflictResolutionRecipe(existingDescriptor, expectedDescriptor));
}
}
return compatibleStorage;
}
}
//# sourceMappingURL=MetricStorageRegistry.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
import type { Context, HrTime, Attributes } from '@opentelemetry/api';
import type { WritableMetricStorage } from './WritableMetricStorage';
/**
* Internal interface.
*/
export declare class MultiMetricStorage implements WritableMetricStorage {
private readonly _backingStorages;
constructor(backingStorages: WritableMetricStorage[]);
record(value: number, attributes: Attributes, context: Context, recordTime: HrTime): void;
}
//# sourceMappingURL=MultiWritableMetricStorage.d.ts.map

View File

@@ -0,0 +1,19 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
/**
* Internal interface.
*/
export class MultiMetricStorage {
_backingStorages;
constructor(backingStorages) {
this._backingStorages = backingStorages;
}
record(value, attributes, context, recordTime) {
this._backingStorages.forEach(it => {
it.record(value, attributes, context, recordTime);
});
}
}
//# sourceMappingURL=MultiWritableMetricStorage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MultiWritableMetricStorage.js","sourceRoot":"","sources":["../../../src/state/MultiWritableMetricStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACZ,gBAAgB,CAA0B;IAC3D,YAAY,eAAwC;QAClD,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;IAED,MAAM,CACJ,KAAa,EACb,UAAsB,EACtB,OAAgB,EAChB,UAAkB;QAElB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;YACjC,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Context, HrTime, Attributes } from '@opentelemetry/api';\nimport type { WritableMetricStorage } from './WritableMetricStorage';\n\n/**\n * Internal interface.\n */\nexport class MultiMetricStorage implements WritableMetricStorage {\n private readonly _backingStorages: WritableMetricStorage[];\n constructor(backingStorages: WritableMetricStorage[]) {\n this._backingStorages = backingStorages;\n }\n\n record(\n value: number,\n attributes: Attributes,\n context: Context,\n recordTime: HrTime\n ) {\n this._backingStorages.forEach(it => {\n it.record(value, attributes, context, recordTime);\n });\n }\n}\n"]}

View File

@@ -0,0 +1,25 @@
import type { HrTime, BatchObservableCallback, Observable, ObservableCallback } from '@opentelemetry/api';
import type { ObservableInstrument } from '../Instruments';
/**
* An internal interface for managing ObservableCallbacks.
*
* Every registered callback associated with a set of instruments are be evaluated
* exactly once during collection prior to reading data for that instrument.
*/
export declare class ObservableRegistry {
private _callbacks;
private _batchCallbacks;
addCallback(callback: ObservableCallback, instrument: ObservableInstrument): void;
removeCallback(callback: ObservableCallback, instrument: ObservableInstrument): void;
addBatchCallback(callback: BatchObservableCallback, instruments: Observable[]): void;
removeBatchCallback(callback: BatchObservableCallback, instruments: Observable[]): void;
/**
* @returns a promise of rejected reasons for invoking callbacks.
*/
observe(collectionTime: HrTime, timeoutMillis?: number): Promise<unknown[]>;
private _observeCallbacks;
private _observeBatchCallbacks;
private _findCallback;
private _findBatchCallback;
}
//# sourceMappingURL=ObservableRegistry.d.ts.map

View File

@@ -0,0 +1,113 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { diag } from '@opentelemetry/api';
import { isObservableInstrument } from '../Instruments';
import { BatchObservableResultImpl, ObservableResultImpl, } from '../ObservableResult';
import { callWithTimeout, setEquals } from '../utils';
/**
* An internal interface for managing ObservableCallbacks.
*
* Every registered callback associated with a set of instruments are be evaluated
* exactly once during collection prior to reading data for that instrument.
*/
export class ObservableRegistry {
_callbacks = [];
_batchCallbacks = [];
addCallback(callback, instrument) {
const idx = this._findCallback(callback, instrument);
if (idx >= 0) {
return;
}
this._callbacks.push({ callback, instrument });
}
removeCallback(callback, instrument) {
const idx = this._findCallback(callback, instrument);
if (idx < 0) {
return;
}
this._callbacks.splice(idx, 1);
}
addBatchCallback(callback, instruments) {
// Create a set of unique instruments.
const observableInstruments = new Set(instruments.filter(isObservableInstrument));
if (observableInstruments.size === 0) {
diag.error('BatchObservableCallback is not associated with valid instruments', instruments);
return;
}
const idx = this._findBatchCallback(callback, observableInstruments);
if (idx >= 0) {
return;
}
this._batchCallbacks.push({ callback, instruments: observableInstruments });
}
removeBatchCallback(callback, instruments) {
// Create a set of unique instruments.
const observableInstruments = new Set(instruments.filter(isObservableInstrument));
const idx = this._findBatchCallback(callback, observableInstruments);
if (idx < 0) {
return;
}
this._batchCallbacks.splice(idx, 1);
}
/**
* @returns a promise of rejected reasons for invoking callbacks.
*/
async observe(collectionTime, timeoutMillis) {
const callbackFutures = this._observeCallbacks(collectionTime, timeoutMillis);
const batchCallbackFutures = this._observeBatchCallbacks(collectionTime, timeoutMillis);
const results = await Promise.allSettled([
...callbackFutures,
...batchCallbackFutures,
]);
const rejections = results
.filter(result => result.status === 'rejected')
.map(result => result.reason);
return rejections;
}
_observeCallbacks(observationTime, timeoutMillis) {
return this._callbacks.map(async ({ callback, instrument }) => {
const observableResult = new ObservableResultImpl(instrument._descriptor.name, instrument._descriptor.valueType);
let callPromise = Promise.resolve(callback(observableResult));
if (timeoutMillis != null) {
callPromise = callWithTimeout(callPromise, timeoutMillis);
}
await callPromise;
instrument._metricStorages.forEach(metricStorage => {
metricStorage.record(observableResult._buffer, observationTime);
});
});
}
_observeBatchCallbacks(observationTime, timeoutMillis) {
return this._batchCallbacks.map(async ({ callback, instruments }) => {
const observableResult = new BatchObservableResultImpl();
let callPromise = Promise.resolve(callback(observableResult));
if (timeoutMillis != null) {
callPromise = callWithTimeout(callPromise, timeoutMillis);
}
await callPromise;
instruments.forEach(instrument => {
const buffer = observableResult._buffer.get(instrument);
if (buffer == null) {
return;
}
instrument._metricStorages.forEach(metricStorage => {
metricStorage.record(buffer, observationTime);
});
});
});
}
_findCallback(callback, instrument) {
return this._callbacks.findIndex(record => {
return record.callback === callback && record.instrument === instrument;
});
}
_findBatchCallback(callback, instruments) {
return this._batchCallbacks.findIndex(record => {
return (record.callback === callback &&
setEquals(record.instruments, instruments));
});
}
}
//# sourceMappingURL=ObservableRegistry.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
import type { Context, HrTime, Attributes } from '@opentelemetry/api';
import type { WritableMetricStorage } from './WritableMetricStorage';
import type { Accumulation, Aggregator } from '../aggregator/types';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
import type { IAttributesProcessor } from '../view/AttributesProcessor';
import { MetricStorage } from './MetricStorage';
import type { MetricData } from '../export/MetricData';
import type { Maybe } from '../utils';
import type { MetricCollectorHandle } from './MetricCollector';
/**
* Internal interface.
*
* Stores and aggregates {@link MetricData} for synchronous instruments.
*/
export declare class SyncMetricStorage<T extends Maybe<Accumulation>> extends MetricStorage implements WritableMetricStorage {
private _aggregationCardinalityLimit?;
private _deltaMetricStorage;
private _temporalMetricStorage;
private _attributesProcessor;
constructor(instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, attributesProcessor: IAttributesProcessor, collectorHandles: MetricCollectorHandle[], aggregationCardinalityLimit?: number);
record(value: number, attributes: Attributes, context: Context, recordTime: HrTime): void;
/**
* Collects the metrics from this storage.
*
* Note: This is a stateful operation and may reset any interval-related
* state for the MetricCollector.
*/
collect(collector: MetricCollectorHandle, collectionTime: HrTime): Maybe<MetricData>;
}
//# sourceMappingURL=SyncMetricStorage.d.ts.map

View File

@@ -0,0 +1,40 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { MetricStorage } from './MetricStorage';
import { DeltaMetricProcessor } from './DeltaMetricProcessor';
import { TemporalMetricProcessor } from './TemporalMetricProcessor';
/**
* Internal interface.
*
* Stores and aggregates {@link MetricData} for synchronous instruments.
*/
export class SyncMetricStorage extends MetricStorage {
_aggregationCardinalityLimit;
_deltaMetricStorage;
_temporalMetricStorage;
_attributesProcessor;
constructor(instrumentDescriptor, aggregator, attributesProcessor, collectorHandles, aggregationCardinalityLimit) {
super(instrumentDescriptor);
this._aggregationCardinalityLimit = aggregationCardinalityLimit;
this._deltaMetricStorage = new DeltaMetricProcessor(aggregator, this._aggregationCardinalityLimit);
this._temporalMetricStorage = new TemporalMetricProcessor(aggregator, collectorHandles);
this._attributesProcessor = attributesProcessor;
}
record(value, attributes, context, recordTime) {
attributes = this._attributesProcessor.process(attributes, context);
this._deltaMetricStorage.record(value, attributes, context, recordTime);
}
/**
* Collects the metrics from this storage.
*
* Note: This is a stateful operation and may reset any interval-related
* state for the MetricCollector.
*/
collect(collector, collectionTime) {
const accumulations = this._deltaMetricStorage.collect();
return this._temporalMetricStorage.buildMetrics(collector, this._instrumentDescriptor, accumulations, collectionTime);
}
}
//# sourceMappingURL=SyncMetricStorage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"SyncMetricStorage.js","sourceRoot":"","sources":["../../../src/state/SyncMetricStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAIpE;;;;GAIG;AACH,MAAM,OAAO,iBACX,SAAQ,aAAa;IAGb,4BAA4B,CAAU;IACtC,mBAAmB,CAA0B;IAC7C,sBAAsB,CAA6B;IACnD,oBAAoB,CAAuB;IAEnD,YACE,oBAA0C,EAC1C,UAAyB,EACzB,mBAAyC,EACzC,gBAAyC,EACzC,2BAAoC;QAEpC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC5B,IAAI,CAAC,4BAA4B,GAAG,2BAA2B,CAAC;QAChE,IAAI,CAAC,mBAAmB,GAAG,IAAI,oBAAoB,CACjD,UAAU,EACV,IAAI,CAAC,4BAA4B,CAClC,CAAC;QACF,IAAI,CAAC,sBAAsB,GAAG,IAAI,uBAAuB,CACvD,UAAU,EACV,gBAAgB,CACjB,CAAC;QACF,IAAI,CAAC,oBAAoB,GAAG,mBAAmB,CAAC;IAClD,CAAC;IAED,MAAM,CACJ,KAAa,EACb,UAAsB,EACtB,OAAgB,EAChB,UAAkB;QAElB,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACpE,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAC1E,CAAC;IAED;;;;;OAKG;IACH,OAAO,CACL,SAAgC,EAChC,cAAsB;QAEtB,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;QAEzD,OAAO,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAC7C,SAAS,EACT,IAAI,CAAC,qBAAqB,EAC1B,aAAa,EACb,cAAc,CACf,CAAC;IACJ,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Context, HrTime, Attributes } from '@opentelemetry/api';\nimport type { WritableMetricStorage } from './WritableMetricStorage';\nimport type { Accumulation, Aggregator } from '../aggregator/types';\nimport type { InstrumentDescriptor } from '../InstrumentDescriptor';\nimport type { IAttributesProcessor } from '../view/AttributesProcessor';\nimport { MetricStorage } from './MetricStorage';\nimport type { MetricData } from '../export/MetricData';\nimport { DeltaMetricProcessor } from './DeltaMetricProcessor';\nimport { TemporalMetricProcessor } from './TemporalMetricProcessor';\nimport type { Maybe } from '../utils';\nimport type { MetricCollectorHandle } from './MetricCollector';\n\n/**\n * Internal interface.\n *\n * Stores and aggregates {@link MetricData} for synchronous instruments.\n */\nexport class SyncMetricStorage<T extends Maybe<Accumulation>>\n extends MetricStorage\n implements WritableMetricStorage\n{\n private _aggregationCardinalityLimit?: number;\n private _deltaMetricStorage: DeltaMetricProcessor<T>;\n private _temporalMetricStorage: TemporalMetricProcessor<T>;\n private _attributesProcessor: IAttributesProcessor;\n\n constructor(\n instrumentDescriptor: InstrumentDescriptor,\n aggregator: Aggregator<T>,\n attributesProcessor: IAttributesProcessor,\n collectorHandles: MetricCollectorHandle[],\n aggregationCardinalityLimit?: number\n ) {\n super(instrumentDescriptor);\n this._aggregationCardinalityLimit = aggregationCardinalityLimit;\n this._deltaMetricStorage = new DeltaMetricProcessor(\n aggregator,\n this._aggregationCardinalityLimit\n );\n this._temporalMetricStorage = new TemporalMetricProcessor(\n aggregator,\n collectorHandles\n );\n this._attributesProcessor = attributesProcessor;\n }\n\n record(\n value: number,\n attributes: Attributes,\n context: Context,\n recordTime: HrTime\n ) {\n attributes = this._attributesProcessor.process(attributes, context);\n this._deltaMetricStorage.record(value, attributes, context, recordTime);\n }\n\n /**\n * Collects the metrics from this storage.\n *\n * Note: This is a stateful operation and may reset any interval-related\n * state for the MetricCollector.\n */\n collect(\n collector: MetricCollectorHandle,\n collectionTime: HrTime\n ): Maybe<MetricData> {\n const accumulations = this._deltaMetricStorage.collect();\n\n return this._temporalMetricStorage.buildMetrics(\n collector,\n this._instrumentDescriptor,\n accumulations,\n collectionTime\n );\n }\n}\n"]}

View File

@@ -0,0 +1,38 @@
import type { HrTime } from '@opentelemetry/api';
import type { Accumulation, Aggregator } from '../aggregator/types';
import type { MetricData } from '../export/MetricData';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
import type { Maybe } from '../utils';
import type { MetricCollectorHandle } from './MetricCollector';
import { AttributeHashMap } from './HashMap';
/**
* Internal interface.
*
* Provides unique reporting for each collector. Allows synchronous collection
* of metrics and reports given temporality values.
*/
export declare class TemporalMetricProcessor<T extends Maybe<Accumulation>> {
private _aggregator;
private _unreportedAccumulations;
private _reportHistory;
constructor(aggregator: Aggregator<T>, collectorHandles: MetricCollectorHandle[]);
/**
* Builds the {@link MetricData} streams to report against a specific MetricCollector.
* @param collector The information of the MetricCollector.
* @param collectors The registered collectors.
* @param instrumentDescriptor The instrumentation descriptor that these metrics generated with.
* @param currentAccumulations The current accumulation of metric data from instruments.
* @param collectionTime The current collection timestamp.
* @returns The {@link MetricData} points or `null`.
*/
buildMetrics(collector: MetricCollectorHandle, instrumentDescriptor: InstrumentDescriptor, currentAccumulations: AttributeHashMap<T>, collectionTime: HrTime): Maybe<MetricData>;
private _stashAccumulations;
private _getMergedUnreportedAccumulations;
static merge<T extends Maybe<Accumulation>>(last: AttributeHashMap<T>, current: AttributeHashMap<T>, aggregator: Aggregator<T>): AttributeHashMap<T>;
/**
* Calibrate the reported metric streams' startTime to lastCollectionTime. Leaves
* the new stream to be the initial observation time unchanged.
*/
static calibrateStartTime<T extends Maybe<Accumulation>>(last: AttributeHashMap<T>, current: AttributeHashMap<T>, lastCollectionTime: HrTime): AttributeHashMap<T>;
}
//# sourceMappingURL=TemporalMetricProcessor.d.ts.map

View File

@@ -0,0 +1,141 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { AggregationTemporality } from '../export/AggregationTemporality';
import { AttributeHashMap } from './HashMap';
/**
* Internal interface.
*
* Provides unique reporting for each collector. Allows synchronous collection
* of metrics and reports given temporality values.
*/
export class TemporalMetricProcessor {
_aggregator;
_unreportedAccumulations = new Map();
_reportHistory = new Map();
constructor(aggregator, collectorHandles) {
this._aggregator = aggregator;
collectorHandles.forEach(handle => {
this._unreportedAccumulations.set(handle, []);
});
}
/**
* Builds the {@link MetricData} streams to report against a specific MetricCollector.
* @param collector The information of the MetricCollector.
* @param collectors The registered collectors.
* @param instrumentDescriptor The instrumentation descriptor that these metrics generated with.
* @param currentAccumulations The current accumulation of metric data from instruments.
* @param collectionTime The current collection timestamp.
* @returns The {@link MetricData} points or `null`.
*/
buildMetrics(collector, instrumentDescriptor, currentAccumulations, collectionTime) {
this._stashAccumulations(currentAccumulations);
const unreportedAccumulations = this._getMergedUnreportedAccumulations(collector);
let result = unreportedAccumulations;
let aggregationTemporality;
// Check our last report time.
if (this._reportHistory.has(collector)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const last = this._reportHistory.get(collector);
const lastCollectionTime = last.collectionTime;
aggregationTemporality = last.aggregationTemporality;
// Use aggregation temporality + instrument to determine if we do a merge or a diff of
// previous. We have the following four scenarios:
// 1. Cumulative Aggregation (temporality) + Delta recording (sync instrument).
// Here we merge with our last record to get a cumulative aggregation.
// 2. Cumulative Aggregation + Cumulative recording (async instrument).
// Cumulative records are converted to delta recording with DeltaMetricProcessor.
// Here we merge with our last record to get a cumulative aggregation.
// 3. Delta Aggregation + Delta recording
// Calibrate the startTime of metric streams to be the reader's lastCollectionTime.
// 4. Delta Aggregation + Cumulative recording.
// Cumulative records are converted to delta recording with DeltaMetricProcessor.
// Calibrate the startTime of metric streams to be the reader's lastCollectionTime.
if (aggregationTemporality === AggregationTemporality.CUMULATIVE) {
// We need to make sure the current delta recording gets merged into the previous cumulative
// for the next cumulative recording.
result = TemporalMetricProcessor.merge(last.accumulations, unreportedAccumulations, this._aggregator);
}
else {
result = TemporalMetricProcessor.calibrateStartTime(last.accumulations, unreportedAccumulations, lastCollectionTime);
}
}
else {
// Call into user code to select aggregation temporality for the instrument.
aggregationTemporality = collector.selectAggregationTemporality(instrumentDescriptor.type);
}
// Update last reported (cumulative) accumulation.
this._reportHistory.set(collector, {
accumulations: result,
collectionTime,
aggregationTemporality,
});
const accumulationRecords = AttributesMapToAccumulationRecords(result);
// do not convert to metric data if there is nothing to convert.
if (accumulationRecords.length === 0) {
return undefined;
}
return this._aggregator.toMetricData(instrumentDescriptor, aggregationTemporality, accumulationRecords,
/* endTime */ collectionTime);
}
_stashAccumulations(currentAccumulation) {
const registeredCollectors = this._unreportedAccumulations.keys();
for (const collector of registeredCollectors) {
let stash = this._unreportedAccumulations.get(collector);
if (stash === undefined) {
stash = [];
this._unreportedAccumulations.set(collector, stash);
}
stash.push(currentAccumulation);
}
}
_getMergedUnreportedAccumulations(collector) {
let result = new AttributeHashMap();
const unreportedList = this._unreportedAccumulations.get(collector);
this._unreportedAccumulations.set(collector, []);
if (unreportedList === undefined) {
return result;
}
for (const it of unreportedList) {
result = TemporalMetricProcessor.merge(result, it, this._aggregator);
}
return result;
}
static merge(last, current, aggregator) {
const result = last;
const iterator = current.entries();
let next = iterator.next();
while (next.done !== true) {
const [key, record, hash] = next.value;
if (last.has(key, hash)) {
const lastAccumulation = last.get(key, hash);
// last.has() returned true, lastAccumulation is present.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const accumulation = aggregator.merge(lastAccumulation, record);
result.set(key, accumulation, hash);
}
else {
result.set(key, record, hash);
}
next = iterator.next();
}
return result;
}
/**
* Calibrate the reported metric streams' startTime to lastCollectionTime. Leaves
* the new stream to be the initial observation time unchanged.
*/
static calibrateStartTime(last, current, lastCollectionTime) {
for (const [key, hash] of last.keys()) {
const currentAccumulation = current.get(key, hash);
currentAccumulation?.setStartTime(lastCollectionTime);
}
return current;
}
}
// TypeScript complains about converting 3 elements tuple to AccumulationRecord<T>.
function AttributesMapToAccumulationRecords(map) {
return Array.from(map.entries());
}
//# sourceMappingURL=TemporalMetricProcessor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
import type { Context, HrTime, Attributes } from '@opentelemetry/api';
import type { AttributeHashMap } from './HashMap';
/**
* Internal interface. Stores measurements and allows synchronous writes of
* measurements.
*
* An interface representing SyncMetricStorage with type parameters removed.
*/
export interface WritableMetricStorage {
/** Records a measurement. */
record(value: number, attributes: Attributes, context: Context, recordTime: HrTime): void;
}
/**
* Internal interface. Stores measurements and allows asynchronous writes of
* measurements.
*
* An interface representing AsyncMetricStorage with type parameters removed.
*/
export interface AsyncWritableMetricStorage {
/** Records a batch of measurements. */
record(measurements: AttributeHashMap<number>, observationTime: HrTime): void;
}
//# sourceMappingURL=WritableMetricStorage.d.ts.map

View File

@@ -0,0 +1,6 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
export {};
//# sourceMappingURL=WritableMetricStorage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"WritableMetricStorage.js","sourceRoot":"","sources":["../../../src/state/WritableMetricStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Context, HrTime, Attributes } from '@opentelemetry/api';\nimport type { AttributeHashMap } from './HashMap';\n\n/**\n * Internal interface. Stores measurements and allows synchronous writes of\n * measurements.\n *\n * An interface representing SyncMetricStorage with type parameters removed.\n */\nexport interface WritableMetricStorage {\n /** Records a measurement. */\n record(\n value: number,\n attributes: Attributes,\n context: Context,\n recordTime: HrTime\n ): void;\n}\n\n/**\n * Internal interface. Stores measurements and allows asynchronous writes of\n * measurements.\n *\n * An interface representing AsyncMetricStorage with type parameters removed.\n */\nexport interface AsyncWritableMetricStorage {\n /** Records a batch of measurements. */\n record(measurements: AttributeHashMap<number>, observationTime: HrTime): void;\n}\n"]}