@opentelemetry/sdk-metrics
Advanced tools
Comparing version 1.28.0 to 1.29.0
@@ -8,2 +8,3 @@ import { AggregationTemporality } from './AggregationTemporality'; | ||
import { AggregationSelector, AggregationTemporalitySelector } from './AggregationSelector'; | ||
import { CardinalitySelector } from './CardinalitySelector'; | ||
export interface MetricReaderOptions { | ||
@@ -22,2 +23,7 @@ /** | ||
/** | ||
* Cardinality selector based on metric instrument types. If not configured, | ||
* a default value is used. | ||
*/ | ||
cardinalitySelector?: CardinalitySelector; | ||
/** | ||
* **Note, this option is experimental**. Additional MetricProducers to use as a source of | ||
@@ -40,2 +46,3 @@ * aggregated metric data in addition to the SDK's metric data. The resource returned by | ||
private readonly _aggregationSelector; | ||
private readonly _cardinalitySelector?; | ||
constructor(options?: MetricReaderOptions); | ||
@@ -64,2 +71,7 @@ /** | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* reader. | ||
*/ | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
/** | ||
* Handle once the SDK has initialized this {@link MetricReader} | ||
@@ -66,0 +78,0 @@ * Overriding this method is optional. |
@@ -95,2 +95,3 @@ /* | ||
this._metricProducers = (_c = options === null || options === void 0 ? void 0 : options.metricProducers) !== null && _c !== void 0 ? _c : []; | ||
this._cardinalitySelector = options === null || options === void 0 ? void 0 : options.cardinalitySelector; | ||
} | ||
@@ -129,2 +130,11 @@ /** | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* reader. | ||
*/ | ||
MetricReader.prototype.selectCardinalityLimit = function (instrumentType) { | ||
return this._cardinalitySelector | ||
? this._cardinalitySelector(instrumentType) | ||
: 2000; // default value if no selector is provided | ||
}; | ||
/** | ||
* Handle once the SDK has initialized this {@link MetricReader} | ||
@@ -131,0 +141,0 @@ * Overriding this method is optional. |
@@ -18,5 +18,6 @@ import { HrTime } from '@opentelemetry/api'; | ||
private _attributesProcessor; | ||
private _aggregationCardinalityLimit?; | ||
private _deltaMetricStorage; | ||
private _temporalMetricStorage; | ||
constructor(_instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[]); | ||
constructor(_instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[], _aggregationCardinalityLimit?: number | undefined); | ||
record(measurements: AttributeHashMap<number>, observationTime: HrTime): void; | ||
@@ -23,0 +24,0 @@ /** |
@@ -58,6 +58,7 @@ /* | ||
__extends(AsyncMetricStorage, _super); | ||
function AsyncMetricStorage(_instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles) { | ||
function AsyncMetricStorage(_instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles, _aggregationCardinalityLimit) { | ||
var _this = _super.call(this, _instrumentDescriptor) || this; | ||
_this._attributesProcessor = _attributesProcessor; | ||
_this._deltaMetricStorage = new DeltaMetricProcessor(aggregator); | ||
_this._aggregationCardinalityLimit = _aggregationCardinalityLimit; | ||
_this._deltaMetricStorage = new DeltaMetricProcessor(aggregator, _this._aggregationCardinalityLimit); | ||
_this._temporalMetricStorage = new TemporalMetricProcessor(aggregator, collectorHandles); | ||
@@ -64,0 +65,0 @@ return _this; |
@@ -16,3 +16,6 @@ import { Context, HrTime, Attributes } from '@opentelemetry/api'; | ||
private _cumulativeMemoStorage; | ||
constructor(_aggregator: Aggregator<T>); | ||
private _cardinalityLimit; | ||
private _overflowAttributes; | ||
private _overflowHashCode; | ||
constructor(_aggregator: Aggregator<T>, aggregationCardinalityLimit?: number); | ||
record(value: number, attributes: Attributes, _context: Context, collectionTime: HrTime): void; | ||
@@ -19,0 +22,0 @@ batchCumulate(measurements: AttributeHashMap<number>, collectionTime: HrTime): void; |
@@ -32,2 +32,3 @@ /* | ||
}; | ||
import { hashAttributes } from '../utils'; | ||
import { AttributeHashMap } from './HashMap'; | ||
@@ -42,3 +43,3 @@ /** | ||
var DeltaMetricProcessor = /** @class */ (function () { | ||
function DeltaMetricProcessor(_aggregator) { | ||
function DeltaMetricProcessor(_aggregator, aggregationCardinalityLimit) { | ||
this._aggregator = _aggregator; | ||
@@ -49,6 +50,18 @@ this._activeCollectionStorage = new AttributeHashMap(); | ||
this._cumulativeMemoStorage = new AttributeHashMap(); | ||
this._overflowAttributes = { 'otel.metric.overflow': true }; | ||
this._cardinalityLimit = (aggregationCardinalityLimit !== null && aggregationCardinalityLimit !== void 0 ? aggregationCardinalityLimit : 2000) - 1; | ||
this._overflowHashCode = hashAttributes(this._overflowAttributes); | ||
} | ||
DeltaMetricProcessor.prototype.record = function (value, attributes, _context, collectionTime) { | ||
var _this = this; | ||
var accumulation = this._activeCollectionStorage.getOrDefault(attributes, function () { return _this._aggregator.createAccumulation(collectionTime); }); | ||
var accumulation = this._activeCollectionStorage.get(attributes); | ||
if (!accumulation) { | ||
if (this._activeCollectionStorage.size >= this._cardinalityLimit) { | ||
var overflowAccumulation = this._activeCollectionStorage.getOrDefault(this._overflowAttributes, function () { return _this._aggregator.createAccumulation(collectionTime); }); | ||
overflowAccumulation === null || overflowAccumulation === void 0 ? void 0 : overflowAccumulation.record(value); | ||
return; | ||
} | ||
accumulation = this._aggregator.createAccumulation(collectionTime); | ||
this._activeCollectionStorage.set(attributes, accumulation); | ||
} | ||
accumulation === null || accumulation === void 0 ? void 0 : accumulation.record(value); | ||
@@ -70,2 +83,13 @@ }; | ||
} | ||
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)) { | ||
var previous = _this._cumulativeMemoStorage.get(attributes, hashCode); | ||
delta = _this._aggregator.diff(previous, accumulation); | ||
} | ||
} | ||
} | ||
// Merge with uncollected active delta. | ||
@@ -72,0 +96,0 @@ if (_this._activeCollectionStorage.has(attributes, hashCode)) { |
@@ -148,3 +148,3 @@ /* | ||
var aggregator = view.aggregation.createAggregator(viewDescriptor); | ||
var viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor, _this._meterProviderSharedState.metricCollectors); | ||
var viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor, _this._meterProviderSharedState.metricCollectors, view.aggregationCardinalityLimit); | ||
_this.metricStorageRegistry.register(viewStorage); | ||
@@ -163,3 +163,4 @@ return viewStorage; | ||
var aggregator = aggregation.createAggregator(descriptor); | ||
var storage = new MetricStorageType(descriptor, aggregator, AttributesProcessor.Noop(), [collector]); | ||
var cardinalityLimit = collector.selectCardinalityLimit(descriptor.type); | ||
var storage = new MetricStorageType(descriptor, aggregator, AttributesProcessor.Noop(), [collector], cardinalityLimit); | ||
_this.metricStorageRegistry.registerForCollector(collector, storage); | ||
@@ -166,0 +167,0 @@ return storage; |
@@ -28,2 +28,7 @@ import { AggregationTemporalitySelector } from '../export/AggregationSelector'; | ||
selectAggregation(instrumentType: InstrumentType): import("..").Aggregation; | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* collector. | ||
*/ | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
} | ||
@@ -36,3 +41,4 @@ /** | ||
selectAggregationTemporality: AggregationTemporalitySelector; | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
} | ||
//# sourceMappingURL=MetricCollector.d.ts.map |
@@ -167,2 +167,10 @@ /* | ||
}; | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* collector. | ||
*/ | ||
MetricCollector.prototype.selectCardinalityLimit = function (instrumentType) { | ||
var _a, _b, _c; | ||
return (_c = (_b = (_a = this._metricReader).selectCardinalityLimit) === null || _b === void 0 ? void 0 : _b.call(_a, instrumentType)) !== null && _c !== void 0 ? _c : 2000; | ||
}; | ||
return MetricCollector; | ||
@@ -169,0 +177,0 @@ }()); |
@@ -17,5 +17,6 @@ import { Context, HrTime, Attributes } from '@opentelemetry/api'; | ||
private _attributesProcessor; | ||
private _aggregationCardinalityLimit?; | ||
private _deltaMetricStorage; | ||
private _temporalMetricStorage; | ||
constructor(instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[]); | ||
constructor(instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[], _aggregationCardinalityLimit?: number | undefined); | ||
record(value: number, attributes: Attributes, context: Context, recordTime: HrTime): void; | ||
@@ -22,0 +23,0 @@ /** |
@@ -41,6 +41,7 @@ /* | ||
__extends(SyncMetricStorage, _super); | ||
function SyncMetricStorage(instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles) { | ||
function SyncMetricStorage(instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles, _aggregationCardinalityLimit) { | ||
var _this = _super.call(this, instrumentDescriptor) || this; | ||
_this._attributesProcessor = _attributesProcessor; | ||
_this._deltaMetricStorage = new DeltaMetricProcessor(aggregator); | ||
_this._aggregationCardinalityLimit = _aggregationCardinalityLimit; | ||
_this._deltaMetricStorage = new DeltaMetricProcessor(aggregator, _this._aggregationCardinalityLimit); | ||
_this._temporalMetricStorage = new TemporalMetricProcessor(aggregator, collectorHandles); | ||
@@ -47,0 +48,0 @@ return _this; |
@@ -1,2 +0,2 @@ | ||
export declare const VERSION = "1.28.0"; | ||
export declare const VERSION = "1.29.0"; | ||
//# sourceMappingURL=version.d.ts.map |
@@ -17,3 +17,3 @@ /* | ||
// this is autogenerated file, see scripts/version-update.js | ||
export var VERSION = '1.28.0'; | ||
export var VERSION = '1.29.0'; | ||
//# sourceMappingURL=version.js.map |
@@ -44,2 +44,11 @@ import { AttributesProcessor } from './AttributesProcessor'; | ||
/** | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit will be used. | ||
* | ||
* @example <caption>sets the cardinality limit to 1000</caption> | ||
* aggregationCardinalityLimit: 1000 | ||
*/ | ||
aggregationCardinalityLimit?: number; | ||
/** | ||
* Instrument selection criteria: | ||
@@ -109,2 +118,3 @@ * The original type of the Instrument(s). | ||
readonly meterSelector: MeterSelector; | ||
readonly aggregationCardinalityLimit?: number; | ||
/** | ||
@@ -132,2 +142,6 @@ * Create a new {@link View} instance. | ||
* If not provided, all attribute keys will be used by default. | ||
* @param viewOptions.aggregationCardinalityLimit | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit of 2000 will be used. | ||
* @param viewOptions.aggregation | ||
@@ -134,0 +148,0 @@ * Alters the metric stream: |
@@ -55,2 +55,6 @@ /* | ||
* If not provided, all attribute keys will be used by default. | ||
* @param viewOptions.aggregationCardinalityLimit | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit of 2000 will be used. | ||
* @param viewOptions.aggregation | ||
@@ -120,2 +124,3 @@ * Alters the metric stream: | ||
}); | ||
this.aggregationCardinalityLimit = viewOptions.aggregationCardinalityLimit; | ||
} | ||
@@ -122,0 +127,0 @@ return View; |
@@ -8,2 +8,3 @@ import { AggregationTemporality } from './AggregationTemporality'; | ||
import { AggregationSelector, AggregationTemporalitySelector } from './AggregationSelector'; | ||
import { CardinalitySelector } from './CardinalitySelector'; | ||
export interface MetricReaderOptions { | ||
@@ -22,2 +23,7 @@ /** | ||
/** | ||
* Cardinality selector based on metric instrument types. If not configured, | ||
* a default value is used. | ||
*/ | ||
cardinalitySelector?: CardinalitySelector; | ||
/** | ||
* **Note, this option is experimental**. Additional MetricProducers to use as a source of | ||
@@ -40,2 +46,3 @@ * aggregated metric data in addition to the SDK's metric data. The resource returned by | ||
private readonly _aggregationSelector; | ||
private readonly _cardinalitySelector?; | ||
constructor(options?: MetricReaderOptions); | ||
@@ -64,2 +71,7 @@ /** | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* reader. | ||
*/ | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
/** | ||
* Handle once the SDK has initialized this {@link MetricReader} | ||
@@ -66,0 +78,0 @@ * Overriding this method is optional. |
@@ -34,2 +34,3 @@ /* | ||
this._metricProducers = (_c = options === null || options === void 0 ? void 0 : options.metricProducers) !== null && _c !== void 0 ? _c : []; | ||
this._cardinalitySelector = options === null || options === void 0 ? void 0 : options.cardinalitySelector; | ||
} | ||
@@ -68,2 +69,11 @@ /** | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* reader. | ||
*/ | ||
selectCardinalityLimit(instrumentType) { | ||
return this._cardinalitySelector | ||
? this._cardinalitySelector(instrumentType) | ||
: 2000; // default value if no selector is provided | ||
} | ||
/** | ||
* Handle once the SDK has initialized this {@link MetricReader} | ||
@@ -70,0 +80,0 @@ * Overriding this method is optional. |
@@ -18,5 +18,6 @@ import { HrTime } from '@opentelemetry/api'; | ||
private _attributesProcessor; | ||
private _aggregationCardinalityLimit?; | ||
private _deltaMetricStorage; | ||
private _temporalMetricStorage; | ||
constructor(_instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[]); | ||
constructor(_instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[], _aggregationCardinalityLimit?: number | undefined); | ||
record(measurements: AttributeHashMap<number>, observationTime: HrTime): void; | ||
@@ -23,0 +24,0 @@ /** |
@@ -26,6 +26,7 @@ /* | ||
export class AsyncMetricStorage extends MetricStorage { | ||
constructor(_instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles) { | ||
constructor(_instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles, _aggregationCardinalityLimit) { | ||
super(_instrumentDescriptor); | ||
this._attributesProcessor = _attributesProcessor; | ||
this._deltaMetricStorage = new DeltaMetricProcessor(aggregator); | ||
this._aggregationCardinalityLimit = _aggregationCardinalityLimit; | ||
this._deltaMetricStorage = new DeltaMetricProcessor(aggregator, this._aggregationCardinalityLimit); | ||
this._temporalMetricStorage = new TemporalMetricProcessor(aggregator, collectorHandles); | ||
@@ -32,0 +33,0 @@ } |
@@ -16,3 +16,6 @@ import { Context, HrTime, Attributes } from '@opentelemetry/api'; | ||
private _cumulativeMemoStorage; | ||
constructor(_aggregator: Aggregator<T>); | ||
private _cardinalityLimit; | ||
private _overflowAttributes; | ||
private _overflowHashCode; | ||
constructor(_aggregator: Aggregator<T>, aggregationCardinalityLimit?: number); | ||
record(value: number, attributes: Attributes, _context: Context, collectionTime: HrTime): void; | ||
@@ -19,0 +22,0 @@ batchCumulate(measurements: AttributeHashMap<number>, collectionTime: HrTime): void; |
@@ -16,2 +16,3 @@ /* | ||
*/ | ||
import { hashAttributes } from '../utils'; | ||
import { AttributeHashMap } from './HashMap'; | ||
@@ -26,3 +27,3 @@ /** | ||
export class DeltaMetricProcessor { | ||
constructor(_aggregator) { | ||
constructor(_aggregator, aggregationCardinalityLimit) { | ||
this._aggregator = _aggregator; | ||
@@ -33,5 +34,17 @@ this._activeCollectionStorage = new AttributeHashMap(); | ||
this._cumulativeMemoStorage = new AttributeHashMap(); | ||
this._overflowAttributes = { 'otel.metric.overflow': true }; | ||
this._cardinalityLimit = (aggregationCardinalityLimit !== null && aggregationCardinalityLimit !== void 0 ? aggregationCardinalityLimit : 2000) - 1; | ||
this._overflowHashCode = hashAttributes(this._overflowAttributes); | ||
} | ||
record(value, attributes, _context, collectionTime) { | ||
const accumulation = this._activeCollectionStorage.getOrDefault(attributes, () => this._aggregator.createAccumulation(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 === null || overflowAccumulation === void 0 ? void 0 : overflowAccumulation.record(value); | ||
return; | ||
} | ||
accumulation = this._aggregator.createAccumulation(collectionTime); | ||
this._activeCollectionStorage.set(attributes, accumulation); | ||
} | ||
accumulation === null || accumulation === void 0 ? void 0 : accumulation.record(value); | ||
@@ -51,2 +64,13 @@ } | ||
} | ||
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)) { | ||
const previous = this._cumulativeMemoStorage.get(attributes, hashCode); | ||
delta = this._aggregator.diff(previous, accumulation); | ||
} | ||
} | ||
} | ||
// Merge with uncollected active delta. | ||
@@ -53,0 +77,0 @@ if (this._activeCollectionStorage.has(attributes, hashCode)) { |
@@ -90,3 +90,3 @@ /* | ||
const aggregator = view.aggregation.createAggregator(viewDescriptor); | ||
const viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor, this._meterProviderSharedState.metricCollectors); | ||
const viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor, this._meterProviderSharedState.metricCollectors, view.aggregationCardinalityLimit); | ||
this.metricStorageRegistry.register(viewStorage); | ||
@@ -104,3 +104,4 @@ return viewStorage; | ||
const aggregator = aggregation.createAggregator(descriptor); | ||
const storage = new MetricStorageType(descriptor, aggregator, AttributesProcessor.Noop(), [collector]); | ||
const cardinalityLimit = collector.selectCardinalityLimit(descriptor.type); | ||
const storage = new MetricStorageType(descriptor, aggregator, AttributesProcessor.Noop(), [collector], cardinalityLimit); | ||
this.metricStorageRegistry.registerForCollector(collector, storage); | ||
@@ -107,0 +108,0 @@ return storage; |
@@ -28,2 +28,7 @@ import { AggregationTemporalitySelector } from '../export/AggregationSelector'; | ||
selectAggregation(instrumentType: InstrumentType): import("..").Aggregation; | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* collector. | ||
*/ | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
} | ||
@@ -36,3 +41,4 @@ /** | ||
selectAggregationTemporality: AggregationTemporalitySelector; | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
} | ||
//# sourceMappingURL=MetricCollector.d.ts.map |
@@ -69,3 +69,11 @@ /* | ||
} | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* collector. | ||
*/ | ||
selectCardinalityLimit(instrumentType) { | ||
var _a, _b, _c; | ||
return (_c = (_b = (_a = this._metricReader).selectCardinalityLimit) === null || _b === void 0 ? void 0 : _b.call(_a, instrumentType)) !== null && _c !== void 0 ? _c : 2000; | ||
} | ||
} | ||
//# sourceMappingURL=MetricCollector.js.map |
@@ -17,5 +17,6 @@ import { Context, HrTime, Attributes } from '@opentelemetry/api'; | ||
private _attributesProcessor; | ||
private _aggregationCardinalityLimit?; | ||
private _deltaMetricStorage; | ||
private _temporalMetricStorage; | ||
constructor(instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[]); | ||
constructor(instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[], _aggregationCardinalityLimit?: number | undefined); | ||
record(value: number, attributes: Attributes, context: Context, recordTime: HrTime): void; | ||
@@ -22,0 +23,0 @@ /** |
@@ -25,6 +25,7 @@ /* | ||
export class SyncMetricStorage extends MetricStorage { | ||
constructor(instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles) { | ||
constructor(instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles, _aggregationCardinalityLimit) { | ||
super(instrumentDescriptor); | ||
this._attributesProcessor = _attributesProcessor; | ||
this._deltaMetricStorage = new DeltaMetricProcessor(aggregator); | ||
this._aggregationCardinalityLimit = _aggregationCardinalityLimit; | ||
this._deltaMetricStorage = new DeltaMetricProcessor(aggregator, this._aggregationCardinalityLimit); | ||
this._temporalMetricStorage = new TemporalMetricProcessor(aggregator, collectorHandles); | ||
@@ -31,0 +32,0 @@ } |
@@ -1,2 +0,2 @@ | ||
export declare const VERSION = "1.28.0"; | ||
export declare const VERSION = "1.29.0"; | ||
//# sourceMappingURL=version.d.ts.map |
@@ -17,3 +17,3 @@ /* | ||
// this is autogenerated file, see scripts/version-update.js | ||
export const VERSION = '1.28.0'; | ||
export const VERSION = '1.29.0'; | ||
//# sourceMappingURL=version.js.map |
@@ -44,2 +44,11 @@ import { AttributesProcessor } from './AttributesProcessor'; | ||
/** | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit will be used. | ||
* | ||
* @example <caption>sets the cardinality limit to 1000</caption> | ||
* aggregationCardinalityLimit: 1000 | ||
*/ | ||
aggregationCardinalityLimit?: number; | ||
/** | ||
* Instrument selection criteria: | ||
@@ -109,2 +118,3 @@ * The original type of the Instrument(s). | ||
readonly meterSelector: MeterSelector; | ||
readonly aggregationCardinalityLimit?: number; | ||
/** | ||
@@ -132,2 +142,6 @@ * Create a new {@link View} instance. | ||
* If not provided, all attribute keys will be used by default. | ||
* @param viewOptions.aggregationCardinalityLimit | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit of 2000 will be used. | ||
* @param viewOptions.aggregation | ||
@@ -134,0 +148,0 @@ * Alters the metric stream: |
@@ -55,2 +55,6 @@ /* | ||
* If not provided, all attribute keys will be used by default. | ||
* @param viewOptions.aggregationCardinalityLimit | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit of 2000 will be used. | ||
* @param viewOptions.aggregation | ||
@@ -120,4 +124,5 @@ * Alters the metric stream: | ||
}); | ||
this.aggregationCardinalityLimit = viewOptions.aggregationCardinalityLimit; | ||
} | ||
} | ||
//# sourceMappingURL=View.js.map |
@@ -8,2 +8,3 @@ import { AggregationTemporality } from './AggregationTemporality'; | ||
import { AggregationSelector, AggregationTemporalitySelector } from './AggregationSelector'; | ||
import { CardinalitySelector } from './CardinalitySelector'; | ||
export interface MetricReaderOptions { | ||
@@ -22,2 +23,7 @@ /** | ||
/** | ||
* Cardinality selector based on metric instrument types. If not configured, | ||
* a default value is used. | ||
*/ | ||
cardinalitySelector?: CardinalitySelector; | ||
/** | ||
* **Note, this option is experimental**. Additional MetricProducers to use as a source of | ||
@@ -40,2 +46,3 @@ * aggregated metric data in addition to the SDK's metric data. The resource returned by | ||
private readonly _aggregationSelector; | ||
private readonly _cardinalitySelector?; | ||
constructor(options?: MetricReaderOptions); | ||
@@ -64,2 +71,7 @@ /** | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* reader. | ||
*/ | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
/** | ||
* Handle once the SDK has initialized this {@link MetricReader} | ||
@@ -66,0 +78,0 @@ * Overriding this method is optional. |
@@ -37,2 +37,3 @@ "use strict"; | ||
this._metricProducers = (_c = options === null || options === void 0 ? void 0 : options.metricProducers) !== null && _c !== void 0 ? _c : []; | ||
this._cardinalitySelector = options === null || options === void 0 ? void 0 : options.cardinalitySelector; | ||
} | ||
@@ -71,2 +72,11 @@ /** | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* reader. | ||
*/ | ||
selectCardinalityLimit(instrumentType) { | ||
return this._cardinalitySelector | ||
? this._cardinalitySelector(instrumentType) | ||
: 2000; // default value if no selector is provided | ||
} | ||
/** | ||
* Handle once the SDK has initialized this {@link MetricReader} | ||
@@ -73,0 +83,0 @@ * Overriding this method is optional. |
@@ -18,5 +18,6 @@ import { HrTime } from '@opentelemetry/api'; | ||
private _attributesProcessor; | ||
private _aggregationCardinalityLimit?; | ||
private _deltaMetricStorage; | ||
private _temporalMetricStorage; | ||
constructor(_instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[]); | ||
constructor(_instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[], _aggregationCardinalityLimit?: number | undefined); | ||
record(measurements: AttributeHashMap<number>, observationTime: HrTime): void; | ||
@@ -23,0 +24,0 @@ /** |
@@ -29,6 +29,7 @@ "use strict"; | ||
class AsyncMetricStorage extends MetricStorage_1.MetricStorage { | ||
constructor(_instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles) { | ||
constructor(_instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles, _aggregationCardinalityLimit) { | ||
super(_instrumentDescriptor); | ||
this._attributesProcessor = _attributesProcessor; | ||
this._deltaMetricStorage = new DeltaMetricProcessor_1.DeltaMetricProcessor(aggregator); | ||
this._aggregationCardinalityLimit = _aggregationCardinalityLimit; | ||
this._deltaMetricStorage = new DeltaMetricProcessor_1.DeltaMetricProcessor(aggregator, this._aggregationCardinalityLimit); | ||
this._temporalMetricStorage = new TemporalMetricProcessor_1.TemporalMetricProcessor(aggregator, collectorHandles); | ||
@@ -35,0 +36,0 @@ } |
@@ -16,3 +16,6 @@ import { Context, HrTime, Attributes } from '@opentelemetry/api'; | ||
private _cumulativeMemoStorage; | ||
constructor(_aggregator: Aggregator<T>); | ||
private _cardinalityLimit; | ||
private _overflowAttributes; | ||
private _overflowHashCode; | ||
constructor(_aggregator: Aggregator<T>, aggregationCardinalityLimit?: number); | ||
record(value: number, attributes: Attributes, _context: Context, collectionTime: HrTime): void; | ||
@@ -19,0 +22,0 @@ batchCumulate(measurements: AttributeHashMap<number>, collectionTime: HrTime): void; |
@@ -19,2 +19,3 @@ "use strict"; | ||
exports.DeltaMetricProcessor = void 0; | ||
const utils_1 = require("../utils"); | ||
const HashMap_1 = require("./HashMap"); | ||
@@ -29,3 +30,3 @@ /** | ||
class DeltaMetricProcessor { | ||
constructor(_aggregator) { | ||
constructor(_aggregator, aggregationCardinalityLimit) { | ||
this._aggregator = _aggregator; | ||
@@ -36,5 +37,17 @@ this._activeCollectionStorage = new HashMap_1.AttributeHashMap(); | ||
this._cumulativeMemoStorage = new HashMap_1.AttributeHashMap(); | ||
this._overflowAttributes = { 'otel.metric.overflow': true }; | ||
this._cardinalityLimit = (aggregationCardinalityLimit !== null && aggregationCardinalityLimit !== void 0 ? aggregationCardinalityLimit : 2000) - 1; | ||
this._overflowHashCode = (0, utils_1.hashAttributes)(this._overflowAttributes); | ||
} | ||
record(value, attributes, _context, collectionTime) { | ||
const accumulation = this._activeCollectionStorage.getOrDefault(attributes, () => this._aggregator.createAccumulation(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 === null || overflowAccumulation === void 0 ? void 0 : overflowAccumulation.record(value); | ||
return; | ||
} | ||
accumulation = this._aggregator.createAccumulation(collectionTime); | ||
this._activeCollectionStorage.set(attributes, accumulation); | ||
} | ||
accumulation === null || accumulation === void 0 ? void 0 : accumulation.record(value); | ||
@@ -54,2 +67,13 @@ } | ||
} | ||
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)) { | ||
const previous = this._cumulativeMemoStorage.get(attributes, hashCode); | ||
delta = this._aggregator.diff(previous, accumulation); | ||
} | ||
} | ||
} | ||
// Merge with uncollected active delta. | ||
@@ -56,0 +80,0 @@ if (this._activeCollectionStorage.has(attributes, hashCode)) { |
@@ -93,3 +93,3 @@ "use strict"; | ||
const aggregator = view.aggregation.createAggregator(viewDescriptor); | ||
const viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor, this._meterProviderSharedState.metricCollectors); | ||
const viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor, this._meterProviderSharedState.metricCollectors, view.aggregationCardinalityLimit); | ||
this.metricStorageRegistry.register(viewStorage); | ||
@@ -107,3 +107,4 @@ return viewStorage; | ||
const aggregator = aggregation.createAggregator(descriptor); | ||
const storage = new MetricStorageType(descriptor, aggregator, AttributesProcessor_1.AttributesProcessor.Noop(), [collector]); | ||
const cardinalityLimit = collector.selectCardinalityLimit(descriptor.type); | ||
const storage = new MetricStorageType(descriptor, aggregator, AttributesProcessor_1.AttributesProcessor.Noop(), [collector], cardinalityLimit); | ||
this.metricStorageRegistry.registerForCollector(collector, storage); | ||
@@ -110,0 +111,0 @@ return storage; |
@@ -28,2 +28,7 @@ import { AggregationTemporalitySelector } from '../export/AggregationSelector'; | ||
selectAggregation(instrumentType: InstrumentType): import("..").Aggregation; | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* collector. | ||
*/ | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
} | ||
@@ -36,3 +41,4 @@ /** | ||
selectAggregationTemporality: AggregationTemporalitySelector; | ||
selectCardinalityLimit(instrumentType: InstrumentType): number; | ||
} | ||
//# sourceMappingURL=MetricCollector.d.ts.map |
@@ -72,4 +72,12 @@ "use strict"; | ||
} | ||
/** | ||
* Select the cardinality limit for the given {@link InstrumentType} for this | ||
* collector. | ||
*/ | ||
selectCardinalityLimit(instrumentType) { | ||
var _a, _b, _c; | ||
return (_c = (_b = (_a = this._metricReader).selectCardinalityLimit) === null || _b === void 0 ? void 0 : _b.call(_a, instrumentType)) !== null && _c !== void 0 ? _c : 2000; | ||
} | ||
} | ||
exports.MetricCollector = MetricCollector; | ||
//# sourceMappingURL=MetricCollector.js.map |
@@ -17,5 +17,6 @@ import { Context, HrTime, Attributes } from '@opentelemetry/api'; | ||
private _attributesProcessor; | ||
private _aggregationCardinalityLimit?; | ||
private _deltaMetricStorage; | ||
private _temporalMetricStorage; | ||
constructor(instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[]); | ||
constructor(instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator<T>, _attributesProcessor: AttributesProcessor, collectorHandles: MetricCollectorHandle[], _aggregationCardinalityLimit?: number | undefined); | ||
record(value: number, attributes: Attributes, context: Context, recordTime: HrTime): void; | ||
@@ -22,0 +23,0 @@ /** |
@@ -28,6 +28,7 @@ "use strict"; | ||
class SyncMetricStorage extends MetricStorage_1.MetricStorage { | ||
constructor(instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles) { | ||
constructor(instrumentDescriptor, aggregator, _attributesProcessor, collectorHandles, _aggregationCardinalityLimit) { | ||
super(instrumentDescriptor); | ||
this._attributesProcessor = _attributesProcessor; | ||
this._deltaMetricStorage = new DeltaMetricProcessor_1.DeltaMetricProcessor(aggregator); | ||
this._aggregationCardinalityLimit = _aggregationCardinalityLimit; | ||
this._deltaMetricStorage = new DeltaMetricProcessor_1.DeltaMetricProcessor(aggregator, this._aggregationCardinalityLimit); | ||
this._temporalMetricStorage = new TemporalMetricProcessor_1.TemporalMetricProcessor(aggregator, collectorHandles); | ||
@@ -34,0 +35,0 @@ } |
@@ -1,2 +0,2 @@ | ||
export declare const VERSION = "1.28.0"; | ||
export declare const VERSION = "1.29.0"; | ||
//# sourceMappingURL=version.d.ts.map |
@@ -20,3 +20,3 @@ "use strict"; | ||
// this is autogenerated file, see scripts/version-update.js | ||
exports.VERSION = '1.28.0'; | ||
exports.VERSION = '1.29.0'; | ||
//# sourceMappingURL=version.js.map |
@@ -44,2 +44,11 @@ import { AttributesProcessor } from './AttributesProcessor'; | ||
/** | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit will be used. | ||
* | ||
* @example <caption>sets the cardinality limit to 1000</caption> | ||
* aggregationCardinalityLimit: 1000 | ||
*/ | ||
aggregationCardinalityLimit?: number; | ||
/** | ||
* Instrument selection criteria: | ||
@@ -109,2 +118,3 @@ * The original type of the Instrument(s). | ||
readonly meterSelector: MeterSelector; | ||
readonly aggregationCardinalityLimit?: number; | ||
/** | ||
@@ -132,2 +142,6 @@ * Create a new {@link View} instance. | ||
* If not provided, all attribute keys will be used by default. | ||
* @param viewOptions.aggregationCardinalityLimit | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit of 2000 will be used. | ||
* @param viewOptions.aggregation | ||
@@ -134,0 +148,0 @@ * Alters the metric stream: |
@@ -58,2 +58,6 @@ "use strict"; | ||
* If not provided, all attribute keys will be used by default. | ||
* @param viewOptions.aggregationCardinalityLimit | ||
* Alters the metric stream: | ||
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated. | ||
* If not provided, the default limit of 2000 will be used. | ||
* @param viewOptions.aggregation | ||
@@ -123,2 +127,3 @@ * Alters the metric stream: | ||
}); | ||
this.aggregationCardinalityLimit = viewOptions.aggregationCardinalityLimit; | ||
} | ||
@@ -125,0 +130,0 @@ } |
{ | ||
"name": "@opentelemetry/sdk-metrics", | ||
"version": "1.28.0", | ||
"version": "1.29.0", | ||
"description": "OpenTelemetry metrics SDK", | ||
@@ -60,3 +60,3 @@ "main": "build/src/index.js", | ||
"@opentelemetry/api": ">=1.3.0 <1.10.0", | ||
"@types/mocha": "10.0.9", | ||
"@types/mocha": "10.0.10", | ||
"@types/node": "18.6.5", | ||
@@ -86,8 +86,8 @@ "@types/sinon": "17.0.3", | ||
"dependencies": { | ||
"@opentelemetry/core": "1.28.0", | ||
"@opentelemetry/resources": "1.28.0" | ||
"@opentelemetry/core": "1.29.0", | ||
"@opentelemetry/resources": "1.29.0" | ||
}, | ||
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/sdk-metrics", | ||
"sideEffects": false, | ||
"gitHead": "4b1ad3fda0cde58907e30fab25c3c767546708e5" | ||
"gitHead": "85dcbc7c55f002837f1bf1bf01145dbb34a55b40" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 3 instances in 1 package
1958784
570
0
100
22283
3
0
+ Added@opentelemetry/core@1.29.0(transitive)
+ Added@opentelemetry/resources@1.29.0(transitive)
+ Added@opentelemetry/semantic-conventions@1.28.0(transitive)
- Removed@opentelemetry/core@1.28.0(transitive)
- Removed@opentelemetry/resources@1.28.0(transitive)
- Removed@opentelemetry/semantic-conventions@1.27.0(transitive)
Updated@opentelemetry/core@1.29.0