Skip to content

Commit

Permalink
feat: interval reporting (#715)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew authored Feb 26, 2025
1 parent 4961eeb commit 2e89dc2
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type PlatformData = {
interface BaseMetricsData {
appName: string;
instanceId: string;
connectionId: string;
platformName: PlatformName;
platformVersion: string;
yggdrasilVersion: null;
Expand Down Expand Up @@ -257,6 +258,7 @@ export default class Metrics extends EventEmitter {
appName: this.appName,
instanceId: this.instanceId,
connectionId: this.connectionId,
interval: this.metricsInterval,
headers,
timeout: this.timeout,
httpOptions: this.httpOptions,
Expand Down Expand Up @@ -360,6 +362,7 @@ export default class Metrics extends EventEmitter {
return {
appName: this.appName,
instanceId: this.instanceId,
connectionId: this.connectionId,
bucket,
platformName: this.platformData.name,
platformVersion: this.platformData.version,
Expand Down Expand Up @@ -394,6 +397,7 @@ export default class Metrics extends EventEmitter {
strategies: this.strategies,
started: this.started,
interval: this.metricsInterval,
connectionId: this.connectionId,
platformName: this.platformData.name,
platformVersion: this.platformData.version,
yggdrasilVersion: null,
Expand Down
1 change: 1 addition & 0 deletions src/repository/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ Message: ${err.message}`,
timeout: this.timeout,
instanceId: this.instanceId,
connectionId: this.connectionId,
interval: this.refreshInterval,
headers,
httpOptions: this.httpOptions,
supportedSpecVersion: SUPPORTED_SPEC_VERSION,
Expand Down
12 changes: 12 additions & 0 deletions src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface GetRequestOptions extends RequestOptions {
connectionId: string;
supportedSpecVersion?: string;
httpOptions?: HttpOptions;
interval?: number;
}

export interface Data {
Expand All @@ -33,6 +34,7 @@ export interface PostRequestOptions extends RequestOptions {
appName?: string;
instanceId?: string;
connectionId?: string;
interval?: number;
httpOptions?: HttpOptions;
}

Expand Down Expand Up @@ -66,6 +68,7 @@ type HeaderOptions = {
custom?: CustomHeaders;
specVersionSupported?: string;
connectionId?: string;
interval?: number;
};

export const buildHeaders = ({
Expand All @@ -76,6 +79,7 @@ export const buildHeaders = ({
custom,
specVersionSupported,
connectionId,
interval,
}: HeaderOptions): Record<string, string> => {
const head: Record<string, string> = {};
if (appName) {
Expand Down Expand Up @@ -108,6 +112,10 @@ export const buildHeaders = ({
head['unleash-connection-id'] = connectionId;
}

// expressed in milliseconds to match refreshInterval and metricsInterval units
// attach when set explicitly to non-zero value
head['unleash-interval'] = String(interval);

return head;
};

Expand All @@ -117,6 +125,7 @@ export const post = ({
timeout,
instanceId,
connectionId,
interval,
headers,
json,
httpOptions,
Expand All @@ -129,6 +138,7 @@ export const post = ({
appName,
instanceId,
connectionId,
interval,
etag: undefined,
contentType: 'application/json',
custom: headers,
Expand All @@ -144,6 +154,7 @@ export const get = ({
timeout,
instanceId,
connectionId,
interval,
headers,
httpOptions,
supportedSpecVersion,
Expand All @@ -155,6 +166,7 @@ export const get = ({
headers: buildHeaders({
appName,
instanceId,
interval,
etag,
contentType: undefined,
custom: headers,
Expand Down
9 changes: 7 additions & 2 deletions src/test/metrics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ test('should sendMetrics and register when metricsInterval is a positive number'

test('should sendMetrics', async (t) => {
const url = getUrl();
t.plan(6);
t.plan(7);
const metricsEP = nock(url)
.post(metricsUrl, (payload) => {
t.truthy(payload.bucket);
Expand All @@ -99,6 +99,7 @@ test('should sendMetrics', async (t) => {
'toggle-x': { yes: 1, no: 1, variants: { 'variant-a': 2 } },
'toggle-y': { yes: 1, no: 0, variants: {} },
});
t.deepEqual(payload.connectionId, 'connection-id');
return true;
})
.reply(200, '');
Expand All @@ -108,6 +109,7 @@ test('should sendMetrics', async (t) => {
const metrics = new Metrics({
url,
metricsInterval: 50,
connectionId: 'connection-id',
});

metrics.count('toggle-x', true);
Expand All @@ -131,7 +133,8 @@ test('should send correct custom and unleash headers', (t) =>
.matchHeader('randomKey', randomKey)
.matchHeader('unleash-appname', 'appName')
.matchHeader('unleash-sdk', /^unleash-client-node:\d+\.\d+\.\d+/)
.matchHeader('unleash-connection-id', 'connectionId');
.matchHeader('unleash-connection-id', 'connectionId')
.matchHeader('unleash-interval', '50');
const regEP = nockRegister(url)
.matchHeader('randomKey', randomKey)
.matchHeader('unleash-appname', 'appName')
Expand Down Expand Up @@ -578,6 +581,7 @@ test('getClientData should include extended metrics', (t) => {
// @ts-expect-error
const metrics = new Metrics({
url,
connectionId: 'connection-id',
});
metrics.start();

Expand All @@ -586,6 +590,7 @@ test('getClientData should include extended metrics', (t) => {
t.truthy(result.platformVersion);
t.true(result.yggdrasilVersion === null);
t.true(result.specVersion === SUPPORTED_SPEC_VERSION);
t.deepEqual(result.connectionId, 'connection-id');
});

test('createMetricsData should include extended metrics', (t) => {
Expand Down
2 changes: 2 additions & 0 deletions src/test/repository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ test('should request with correct custom and unleash headers', (t) =>
.matchHeader('randomKey', randomKey)
.matchHeader('unleash-appname', appName)
.matchHeader('unleash-connection-id', connectionId)
.matchHeader('unleash-interval', '10')
.matchHeader('unleash-sdk', /^unleash-client-node:\d+\.\d+\.\d+/)
.persist()
.get('/client/features')
Expand All @@ -214,6 +215,7 @@ test('should request with correct custom and unleash headers', (t) =>
headers: {
randomKey,
'unleash-connection-id': 'ignore',
'unleash-interval': 'ignore',
},
mode: { type: 'polling', format: 'full' },
});
Expand Down
2 changes: 2 additions & 0 deletions src/test/request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ test('Correct headers should be included', (t) => {
etag: undefined,
contentType: undefined,
connectionId: 'connectionId',
interval: 10000,
custom: {
hello: 'world',
},
});
t.is(headers.hello, 'world');
t.is(headers['UNLEASH-INSTANCEID'], 'instanceId');
t.is(headers['unleash-connection-id'], 'connectionId');
t.is(headers['unleash-interval'], '10000');
t.is(headers['unleash-appname'], 'myApp');
t.regex(headers['unleash-sdk'], /^unleash-client-node:\d+\.\d+\.\d+/);
});

0 comments on commit 2e89dc2

Please sign in to comment.