Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
621f6f6
feat: adds cardinalitySelector option in the PeriodicExportingMetricR…
starzlocker Mar 2, 2026
c7c9cca
tests: add unit tests to assert the functionality of the new argument
starzlocker Mar 2, 2026
f2f3562
refactor: allow cardinalityLimits to be passed to constructor
starzlocker Mar 19, 2026
6de4deb
tests: adjusts tests for the cardinalityLimits parameter
starzlocker Mar 19, 2026
712f263
Merge branch 'main' into feat/adds_cardinality_selector_opt
starzlocker Mar 19, 2026
c8dde4e
fix: small typo in cardinalityLimits default values
starzlocker Mar 19, 2026
38a120e
Merge branch 'feat/adds_cardinality_selector_opt' of github.com:starz…
starzlocker Mar 19, 2026
03a4bba
fix: instrument type being imported as a type
starzlocker Mar 19, 2026
eb62521
fix: white space
starzlocker Mar 19, 2026
cf40adb
refactor: adds all the instrument types scenarios to the cardinality …
starzlocker Apr 2, 2026
cc10bfa
refactor: improves test name
starzlocker Apr 2, 2026
62b20c2
fix: fixes the use of the default value
starzlocker Apr 8, 2026
98d2c46
tests: adds more tests to increase coverage and test different cases
starzlocker Apr 8, 2026
fb067a4
fix: removes .only from describe
starzlocker Apr 8, 2026
b934c8b
refactor: alters test to use a forEach approach
starzlocker Apr 8, 2026
9ca22be
fix: apply suggestions from code review
starzlocker Apr 8, 2026
ef66406
docs: added changelog entry
starzlocker Apr 9, 2026
6b9f8d4
docs: readme
starzlocker Apr 9, 2026
75696cb
fix: linting
starzlocker Apr 9, 2026
f5c11e3
Apply suggestion from @maryliag
maryliag Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { MetricReader } from './MetricReader';
import type { PushMetricExporter } from './MetricExporter';
import { callWithTimeout, TimeoutError } from '../utils';
import type { MetricProducer } from './MetricProducer';
import { InstrumentType } from './MetricData';

export type PeriodicExportingMetricReaderOptions = {
/**
Expand All @@ -35,6 +36,20 @@ export type PeriodicExportingMetricReaderOptions = {
* @experimental
*/
metricProducers?: MetricProducer[];
/**
* Cardinality limits for the metric reader, applied per instrument. If not configured, defaults to 2000 time series per instrument. These are wrapped in a cardinalitySelector function that returns limits based on the instrument type, so they can be configured differently per type if desired.
*
*/
cardinalityLimits?: {
counter?: number;
gauge?: number;
histogram?: number;
upDownCounter?: number;
observableCounter?: number;
observableGauge?: number;
observableUpDownCounter?: number;
default?: number;
};
};

/**
Expand All @@ -48,14 +63,51 @@ export class PeriodicExportingMetricReader extends MetricReader {
private readonly _exportTimeout: number;

constructor(options: PeriodicExportingMetricReaderOptions) {
const { exporter, exportIntervalMillis = 60000, metricProducers } = options;
const {
exporter,
exportIntervalMillis = 60000,
metricProducers,
cardinalityLimits,
} = options;
let { exportTimeoutMillis = 30000 } = options;

super({
aggregationSelector: exporter.selectAggregation?.bind(exporter),
aggregationTemporalitySelector:
exporter.selectAggregationTemporality?.bind(exporter),
metricProducers,
cardinalitySelector: (instrumentType: InstrumentType) => {
const limits = {
Comment thread
maryliag marked this conversation as resolved.
counter: 2000,
gauge: 2000,
histogram: 2000,
upDownCounter: 2000,
observableCounter: 2000,
observableGauge: 2000,
observableUpDownCounter: 2000,
default: 2000,
...(cardinalityLimits ?? {}),
};

switch (instrumentType) {
case InstrumentType.COUNTER:
return limits.counter;
case InstrumentType.GAUGE:
return limits.gauge;
case InstrumentType.HISTOGRAM:
return limits.histogram;
case InstrumentType.OBSERVABLE_COUNTER:
return limits.observableCounter;
case InstrumentType.OBSERVABLE_UP_DOWN_COUNTER:
return limits.observableUpDownCounter;
case InstrumentType.OBSERVABLE_GAUGE:
return limits.observableGauge;
case InstrumentType.UP_DOWN_COUNTER:
return limits.upDownCounter;
default:
return limits.default;
}
},
});

if (exportIntervalMillis <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { AggregationTemporality } from '../../src/export/AggregationTemporality'
import type {
AggregationOption,
CollectionResult,
InstrumentType,
MetricProducer,
PushMetricExporter,
} from '../../src';
import { InstrumentType } from '../../src/export/MetricData';
import { AggregationType } from '../../src';
import type {
ResourceMetrics,
Expand Down Expand Up @@ -250,6 +250,44 @@ describe('PeriodicExportingMetricReader', () => {
});
});

describe('cardinalityLimits', () => {
it('should use default cardinality limits with no exporter preference', () => {
const exporter = new TestDeltaMetricExporter();

const p = new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1,
exportTimeoutMillis: 1,
});

assert.strictEqual(
p.selectCardinalityLimit(InstrumentType.COUNTER),
2000
);
});

it('provided cardinalityLimits over defaults', () => {
Comment thread
maryliag marked this conversation as resolved.
Outdated
const exporter = new TestDeltaMetricExporter();

const p = new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1,
exportTimeoutMillis: 1,
cardinalityLimits: {
counter: 5000,
gauge: 5000,
histogram: 5000,
default: 5000,
Comment thread
maryliag marked this conversation as resolved.
Outdated
},
});

assert.strictEqual(
p.selectCardinalityLimit(InstrumentType.COUNTER),
5000
);
});
});

describe('setMetricProducer', () => {
it('should start exporting periodically', async () => {
const exporter = new TestMetricExporter();
Expand Down
Loading