Skip to content

Commit 9198bed

Browse files
committed
Add smoke test for the rate metric
1 parent 117f089 commit 9198bed

File tree

3 files changed

+40
-91
lines changed

3 files changed

+40
-91
lines changed

glean/src/core/metrics/types/rate.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ import { MetricType } from "../index.js";
77
import { Context } from "../../context.js";
88
import { Metric } from "../metric.js";
99
import { testOnly } from "../../utils.js";
10-
import type { JSONValue } from "../../utils.js";
10+
import { isNumber, isObject, JSONValue } from "../../utils.js";
1111
import { ErrorType } from "../../error/error_type.js";
12-
import { isMap } from "util/types";
1312

1413
const LOG_TAG = "core.metrics.RateMetricType";
1514

@@ -18,26 +17,36 @@ export type RateInternalRepresentation = {
1817
numerator: number,
1918
// The denominator
2019
denominator: number
21-
}
20+
};
2221

2322
export type RatePayloadRepresentation = {
2423
// numerator
2524
numerator: number,
2625
// The denominator
2726
denominator: number
28-
}
27+
};
2928

3029
export class RateMetric extends Metric<RateInternalRepresentation, RatePayloadRepresentation> {
3130
constructor(v: unknown) {
3231
super(v);
3332
}
3433

34+
get numerator(): number {
35+
return this._inner.numerator;
36+
}
37+
38+
get denominator(): number {
39+
return this._inner.denominator;
40+
}
41+
3542
validate(v: unknown): v is RateInternalRepresentation {
36-
if (!isMap(v)) {
43+
if (!isObject(v) || Object.keys(v).length !== 2) {
3744
return false;
3845
}
3946

40-
return ("numerator" in v && "denominator" in v && Object.keys(v).length == 2);
47+
const numeratorVerification = "numerator" in v && isNumber(v.numerator) && v.numerator >= 0;
48+
const denominatorVerification = "denominator" in v && isNumber(v.denominator) && v.denominator >= 0;
49+
return numeratorVerification && denominatorVerification;
4150
}
4251

4352
payload(): RatePayloadRepresentation {
@@ -92,11 +101,11 @@ class RateMetricType extends MetricType {
92101
let result: number;
93102
try {
94103
metric = new RateMetric(v);
95-
result = metric.get().numerator + amount;
104+
result = metric.numerator + amount;
96105
} catch {
97106
metric = new RateMetric({
98107
numerator: amount,
99-
denominator: 1
108+
denominator: 0
100109
});
101110
result = amount;
102111
}
@@ -107,7 +116,7 @@ class RateMetricType extends MetricType {
107116

108117
metric.set({
109118
numerator: result,
110-
denominator: metric.get().denominator
119+
denominator: metric.denominator
111120
});
112121
return metric;
113122
};
@@ -146,10 +155,10 @@ class RateMetricType extends MetricType {
146155
let result: number;
147156
try {
148157
metric = new RateMetric(v);
149-
result = metric.get().denominator + amount;
158+
result = metric.denominator + amount;
150159
} catch {
151160
metric = new RateMetric({
152-
numerator: 1,
161+
numerator: 0,
153162
denominator: amount
154163
});
155164
result = amount;
@@ -160,7 +169,7 @@ class RateMetricType extends MetricType {
160169
}
161170

162171
metric.set({
163-
numerator: metric.get().numerator,
172+
numerator: metric.numerator,
164173
denominator: result
165174
});
166175
return metric;

glean/src/core/metrics/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { BooleanMetric } from "./types/boolean.js";
1111
import { CounterMetric } from "./types/counter.js";
1212
import { DatetimeMetric } from "./types/datetime.js";
1313
import { QuantityMetric } from "./types/quantity.js";
14+
import { RateMetric } from "./types/rate.js";
1415
import { StringMetric } from "./types/string.js";
1516
import { StringListMetric } from "./types/string_list.js";
1617
import { TextMetric } from "./types/text.js";
@@ -31,6 +32,7 @@ const METRIC_MAP: {
3132
"labeled_counter": LabeledMetric,
3233
"labeled_string": LabeledMetric,
3334
"quantity": QuantityMetric,
35+
"rate": RateMetric,
3436
"string": StringMetric,
3537
"string_list": StringListMetric,
3638
"text": TextMetric,

glean/tests/unit/core/metrics/rate.spec.ts

Lines changed: 17 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import assert from "assert";
6-
import { Context } from "../../../../src/core/context";
76
import { ErrorType } from "../../../../src/core/error/error_type";
87

98
import Glean from "../../../../src/core/glean";
109
import { Lifetime } from "../../../../src/core/metrics/lifetime";
11-
import QuantityMetricType from "../../../../src/core/metrics/types/quantity";
10+
import RateMetricType from "../../../../src/core/metrics/types/rate";
1211

1312
describe("RateMetric", function() {
1413
const testAppId = `gleanjs.test.${this.title}`;
@@ -17,93 +16,32 @@ describe("RateMetric", function() {
1716
await Glean.testResetGlean(testAppId);
1817
});
1918

20-
it("attempting to get the value of a metric that hasn't been recorded doesn't error", async function() {
21-
const metric = new QuantityMetricType({
22-
category: "aCategory",
23-
name: "aQuantityMetric",
24-
sendInPings: ["aPing", "twoPing", "threePing"],
25-
lifetime: Lifetime.Ping,
26-
disabled: false
27-
});
28-
29-
assert.strictEqual(await metric.testGetValue("aPing"), undefined);
30-
});
31-
32-
it("attempting to set when glean upload is disabled is a no-op", async function() {
33-
Glean.setUploadEnabled(false);
34-
35-
const metric = new QuantityMetricType({
36-
category: "aCategory",
37-
name: "aQuantityMetric",
38-
sendInPings: ["aPing", "twoPing", "threePing"],
39-
lifetime: Lifetime.Ping,
40-
disabled: false
41-
});
42-
43-
metric.set(10);
44-
assert.strictEqual(await metric.testGetValue("aPing"), undefined);
45-
});
19+
it("smoke test for rate metric", async function() {
20+
Glean.setUploadEnabled(true);
4621

47-
it("ping payload is correct", async function() {
48-
const metric = new QuantityMetricType({
22+
const metric = new RateMetricType({
4923
category: "aCategory",
50-
name: "aQuantityMetric",
24+
name: "aRate",
5125
sendInPings: ["aPing"],
5226
lifetime: Lifetime.Ping,
5327
disabled: false
5428
});
5529

56-
metric.set(10);
57-
assert.strictEqual(await metric.testGetValue("aPing"), 10);
30+
metric.add_to_numerator(0);
31+
metric.add_to_denominator(0);
5832

59-
const snapshot = await Context.metricsDatabase.getPingMetrics("aPing", true);
60-
assert.deepStrictEqual(snapshot, {
61-
"quantity": {
62-
"aCategory.aQuantityMetric": 10
63-
}
64-
});
65-
});
33+
assert.strictEqual(await metric.testGetNumRecordedErrors(ErrorType.InvalidValue), 0);
6634

67-
it("set properly sets the value in all pings", async function() {
68-
const metric = new QuantityMetricType({
69-
category: "aCategory",
70-
name: "aQuantityMetric",
71-
sendInPings: ["aPing", "twoPing", "threePing"],
72-
lifetime: Lifetime.Ping,
73-
disabled: false
74-
});
35+
metric.add_to_numerator(-1);
36+
metric.add_to_denominator(-1);
7537

76-
metric.set(0);
77-
assert.strictEqual(await metric.testGetValue("aPing"), 0);
78-
assert.strictEqual(await metric.testGetValue("twoPing"), 0);
79-
assert.strictEqual(await metric.testGetValue("threePing"), 0);
80-
});
38+
assert.strictEqual(await metric.testGetNumRecordedErrors(ErrorType.InvalidValue), 2);
8139

82-
it("must not set when passed negative", async function() {
83-
const metric = new QuantityMetricType({
84-
category: "aCategory",
85-
name: "aQuantityMetric",
86-
sendInPings: ["aPing"],
87-
lifetime: Lifetime.Ping,
88-
disabled: false
89-
});
40+
assert.deepStrictEqual(await metric.testGetValue("aPing"), {numerator: 0, denominator: 0});
9041

91-
metric.set(-1);
92-
assert.strictEqual(await metric.testGetValue("aPing"), undefined);
42+
metric.add_to_numerator(22);
43+
metric.add_to_denominator(7);
9344

94-
assert.strictEqual(await metric.testGetNumRecordedErrors(ErrorType.InvalidValue, "aPing"), 1);
95-
});
96-
97-
it("saturates at boundary", async function() {
98-
const metric = new QuantityMetricType({
99-
category: "aCategory",
100-
name: "aQuantityMetric",
101-
sendInPings: ["aPing"],
102-
lifetime: Lifetime.Ping,
103-
disabled: false
104-
});
105-
106-
metric.set(Number.MAX_SAFE_INTEGER+1);
107-
assert.strictEqual(await metric.testGetValue("aPing"), Number.MAX_SAFE_INTEGER);
108-
});
109-
});
45+
assert.deepStrictEqual(await metric.testGetValue("aPing"), {numerator: 22, denominator: 7});
46+
});
47+
});

0 commit comments

Comments
 (0)