Skip to content

Commit be3f79f

Browse files
author
Beatriz Rizental
authored
Merge pull request #303 from brizental/1709787-set-raw
Bug 1709787 - Implement setRawNanos API for the TimespanMetricType
2 parents 5d28189 + f7fbc42 commit be3f79f

File tree

3 files changed

+110
-27
lines changed

3 files changed

+110
-27
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
* [#279](https://github.com/mozilla/glean.js/pull/279): BUGFIX: Ensure only empty pings triggers logging of "empty ping" messages.
66
* [#288](https://github.com/mozilla/glean.js/pull/288): Support collecting `PlatformInfo` from `Qt` applications. Only OS name and locale are supported.
7-
* [#281](https://github.com/mozilla/glean.js/pull/281): Add the QuantityMetricType
7+
* [#281](https://github.com/mozilla/glean.js/pull/281): Add the QuantityMetricType.
8+
* [#303](https://github.com/mozilla/glean.js/pull/303): Implement setRawNanos API for the TimespanMetricType.
89

910
# v0.11.0 (2021-05-03)
1011

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

Lines changed: 73 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,57 @@ class TimespanMetricType extends MetricType {
6969
this.timeUnit = timeUnit as TimeUnit;
7070
}
7171

72+
/**
73+
* An internal implemention of `setRaw` that does not dispatch the recording task.
74+
*
75+
* # Important
76+
*
77+
* This is absolutely not meant to be used outside of Glean itself.
78+
* It may cause multiple issues because it cannot guarantee
79+
* that the recording of the metric will happen in order with other Glean API calls.
80+
*
81+
* @param instance The metric instance to record to.
82+
* @param elapsed The elapsed time to record, in milliseconds.
83+
*/
84+
static async _private_setRawUndispatched(instance: TimespanMetricType, elapsed: number): Promise<void> {
85+
if (!instance.shouldRecord(Context.uploadEnabled)) {
86+
return;
87+
}
88+
89+
if (!isUndefined(instance.startTime)) {
90+
// TODO: record error once Bug 1682574 is resolved.
91+
console.error("Timespan already running. Raw value not recorded.");
92+
return;
93+
}
94+
95+
let reportValueExists = false;
96+
const transformFn = ((elapsed) => {
97+
return (old?: JSONValue): TimespanMetric => {
98+
let metric: TimespanMetric;
99+
try {
100+
metric = new TimespanMetric(old);
101+
// If creating the metric didn't error,
102+
// there is a valid timespan already recorded for this metric.
103+
reportValueExists = true;
104+
} catch {
105+
metric = new TimespanMetric({
106+
timespan: elapsed,
107+
timeUnit: instance.timeUnit,
108+
});
109+
}
110+
111+
return metric;
112+
};
113+
})(elapsed);
114+
115+
await Context.metricsDatabase.transform(instance, transformFn);
116+
117+
if (reportValueExists) {
118+
// TODO: record error once Bug 1682574 is resolved.
119+
console.error("Timespan value already recorded. New value discarded.");
120+
}
121+
}
122+
72123
/**
73124
* Starts tracking time for the provided metric.
74125
*
@@ -131,32 +182,7 @@ class TimespanMetricType extends MetricType {
131182
return;
132183
}
133184

134-
let reportValueExists = false;
135-
const transformFn = ((elapsed) => {
136-
return (old?: JSONValue): TimespanMetric => {
137-
let metric: TimespanMetric;
138-
try {
139-
metric = new TimespanMetric(old);
140-
// If creating the metric didn't error,
141-
// there is a valid timespan already recorded for this metric.
142-
reportValueExists = true;
143-
} catch {
144-
metric = new TimespanMetric({
145-
timespan: elapsed,
146-
timeUnit: this.timeUnit,
147-
});
148-
}
149-
150-
return metric;
151-
};
152-
})(elapsed);
153-
154-
await Context.metricsDatabase.transform(this, transformFn);
155-
156-
if (reportValueExists) {
157-
// TODO: record error once Bug 1682574 is resolved.
158-
console.error("Timespan value already recorded. New value discarded.");
159-
}
185+
await TimespanMetricType._private_setRawUndispatched(this, elapsed);
160186
});
161187
}
162188

@@ -172,6 +198,27 @@ class TimespanMetricType extends MetricType {
172198
});
173199
}
174200

201+
/**
202+
* Explicitly sets the timespan value.
203+
*
204+
* This API should only be used if your library or application requires
205+
* recording times in a way that can not make use of
206+
* {@link TimespanMetricType#start}/{@link TimespanMetricType#stop}.
207+
*
208+
* Care should be taken using this if the ping lifetime might contain more
209+
* than one timespan measurement. To be safe, this function should generally
210+
* be followed by sending a custom ping containing the timespan.
211+
*
212+
* @param elapsed The elapsed time to record, in nanoseconds.
213+
*/
214+
setRawNanos(elapsed: number): void {
215+
Context.dispatcher.launch(async () => {
216+
// `elapsed` is in nanoseconds in order to match the glean-core API.
217+
const elapsedMillis = elapsed * 10**(-6);
218+
await TimespanMetricType._private_setRawUndispatched(this, elapsedMillis);
219+
});
220+
}
221+
175222
/**
176223
* **Test-only API.**
177224
*

glean/tests/core/metrics/timespan.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,4 +297,39 @@ describe("TimespanMetric", function() {
297297

298298
assert.deepStrictEqual(consoleErrorSpy.callCount, 1);
299299
});
300+
301+
it("setting raw time works correctly", async function () {
302+
const metric = new TimespanMetricType({
303+
category: "aCategory",
304+
name: "aTimespan",
305+
sendInPings: ["aPing"],
306+
lifetime: Lifetime.Ping,
307+
disabled: false
308+
}, "millisecond");
309+
310+
metric.setRawNanos(1000000); // 1ms
311+
assert.strictEqual(await metric.testGetValue("aPing"), 1);
312+
});
313+
314+
it("setting raw time does nothing when times is running", async function () {
315+
fakeNow.onCall(0).callsFake(() => 0);
316+
fakeNow.onCall(1).callsFake(() => 100);
317+
318+
const metric = new TimespanMetricType({
319+
category: "aCategory",
320+
name: "aTimespan",
321+
sendInPings: ["aPing"],
322+
lifetime: Lifetime.Ping,
323+
disabled: false
324+
}, "millisecond");
325+
326+
metric.start();
327+
metric.setRawNanos(42);
328+
metric.stop();
329+
330+
// We expect the start/stop value, not the raw value.
331+
assert.strictEqual(await metric.testGetValue("aPing"), 100);
332+
333+
// TODO: check number of recorded errors instead once Bug 1682574 is resolved.
334+
});
300335
});

0 commit comments

Comments
 (0)