Skip to content

Commit 09ae8b7

Browse files
author
Beatriz Rizental
authored
Bug 1687644 - Implement the external API for consumers (#27)
1 parent ac05d0d commit 09ae8b7

File tree

23 files changed

+211
-86
lines changed

23 files changed

+211
-86
lines changed

bin/qt-js-check.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ xvfb-run python main.py &> qml.log &
1919
sleep 10
2020

2121
if grep -q "Some Javascript error occured" "qml.log"; then
22-
echo "Javascript errors in found in QML! See more logs below."
22+
echo "Failed to initialize Glean in QML! See more logs below."
2323
cat qml.log
2424
exit 1
2525
fi

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
"lint": "eslint . --ext .ts,.js,.json --max-warnings=0",
1010
"fix": "eslint . --ext .ts,.js,.json --fix",
1111
"build:webext": "webpack --config webpack.config.webext.js --mode production",
12-
"dev:webext": "webpack --watch --config webpack.config.webext.js --mode development",
12+
"dev:webext": "webpack --watch --config webpack.config.webext.js --mode development --devtool inline-source-map",
1313
"build:qt": "webpack --config webpack.config.qt.js --mode production",
14-
"dev:qt": "webpack --watch --config webpack.config.qt.js --mode development",
14+
"dev:qt": "webpack --watch --config webpack.config.qt.js --mode development --devtool inline-source-map",
1515
"build:test-webext": "cd tests/utils/webext/sample/ && npm install && npm run build:xpi"
1616
},
1717
"repository": {

samples/qt-qml-app/main.qml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ Rectangle {
4747
}
4848

4949
Component.onCompleted: {
50-
// Initialize Glean when the application starts.
51-
try {
52-
Glean.Glean.initialize("qt-qml-app", true);
53-
} catch(err) {
54-
console.error(`Some Javascript error occured.\n${err}`);
55-
}
50+
// Initialize Glean when the application starts.
51+
Glean.Glean.initialize("qt-qml-app", true)
52+
// Note: If you change this console messages you should change
53+
// the console message verifications on `bin/qt-js-check.sh.
54+
.then(() => console.log("Called Glean.initialize succesfully."))
55+
.catch(err => console.error(`Some Javascript error occured.\n${err}`));
5656
}
5757
}

src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface Configuration {
1111
// The user visible version string fro the application running Glean.js.
1212
readonly appDisplayVersion?: string,
1313
// The server pings are sent to.
14-
readonly serverEndpoint?: URL
14+
readonly serverEndpoint?: string
1515
}
1616

1717
export default Configuration;

src/glean.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Configuration from "config";
77
import MetricsDatabase from "metrics/database";
88
import PingsDatabase from "pings/database";
99
import PingUploader from "upload";
10-
import { isUndefined, sanitizeApplicationId } from "utils";
10+
import { isUndefined, sanitizeApplicationId, validateURL } from "utils";
1111
import { CoreMetrics } from "internal_metrics";
1212
import { Lifetime } from "metrics";
1313
import { DatetimeMetric } from "metrics/types/datetime";
@@ -33,7 +33,7 @@ class Glean {
3333
// The application ID (will be sanitized during initialization).
3434
private _applicationId?: string;
3535
// The server pings are sent to.
36-
private _serverEndpoint?: URL;
36+
private _serverEndpoint?: string;
3737
// Whether or not to record metrics.
3838
private _uploadEnabled?: boolean;
3939

@@ -181,8 +181,11 @@ class Glean {
181181
}
182182
Glean.instance._applicationId = sanitizeApplicationId(applicationId);
183183

184-
Glean.instance._serverEndpoint = config
185-
? config.serverEndpoint : new URL(DEFAULT_TELEMETRY_ENDPOINT);
184+
if (config && config.serverEndpoint && !validateURL(config.serverEndpoint)) {
185+
throw new Error(`Unable to initialize Glean, serverEndpoint ${config.serverEndpoint} is an invalid URL.`);
186+
}
187+
Glean.instance._serverEndpoint = (config && config.serverEndpoint)
188+
? config.serverEndpoint : DEFAULT_TELEMETRY_ENDPOINT;
186189

187190
if (uploadEnabled) {
188191
await Glean.onUploadEnabled();
@@ -232,7 +235,7 @@ class Glean {
232235
return Glean.instance._applicationId;
233236
}
234237

235-
static get serverEndpoint(): URL | undefined {
238+
static get serverEndpoint(): string | undefined {
236239
if (!Glean.instance._initialized) {
237240
console.warn("Attempted to access the Glean.serverEndpoint before Glean was initialized.");
238241
}

src/index.ts

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,81 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5+
import Glean from "glean";
6+
import Configuration from "config";
7+
8+
// Private Glean types to export.
9+
import PingType from "pings";
10+
import BooleanMetricType from "metrics/types/boolean";
11+
import CounterMetricType from "metrics/types/counter";
12+
import DatetimeMetricType from "metrics/types/datetime";
13+
import StringMetricType from "metrics/types/string";
14+
import UUIDMetricType from "metrics/types/uuid";
15+
516
export = {
617
/**
7-
* Initializes Glean.
18+
* Initialize Glean. This method should only be called once, subsequent calls will be no-op.
19+
*
20+
* # Note
21+
*
22+
* Before this method is called Glean will not be able to upload pings or record metrics,
23+
* all such operations will be no-op.
824
*
9-
* Before calling this function Glean.js won't submit any pings.
25+
* This is _not_ the way glean-core deals with this. It will record tasks performed before init
26+
* and flush them on init. We have a bug to figure out how to do that for Glean.js, Bug 1687491.
1027
*
11-
* @param appId Analogous to a Glean SDK application id.
12-
* @param uploadEnabled Whether upload is enabled or not.
28+
* @param applicationId The application ID (will be sanitized during initialization).
29+
* @param uploadEnabled Determines whether telemetry is enabled.
30+
* If disabled, all persisted metrics, events and queued pings (except
31+
* first_run_date) are cleared.
32+
* @param config Glean configuration options.
33+
*
34+
* @returns A promise that is resolved once initialize is completed.
1335
*/
14-
initialize(appId: string, uploadEnabled: boolean): void {
15-
console.info(`Called Glean.initialize("${appId}", ${uploadEnabled})).`);
36+
async initialize(
37+
applicationId: string,
38+
uploadEnabled: boolean,
39+
config?: Configuration
40+
): Promise<void> {
41+
await Glean.initialize(applicationId, uploadEnabled, config);
1642
},
1743

1844
/**
19-
* Enables / Disables upload.
45+
* Sets whether upload is enabled or not.
46+
*
47+
* When uploading is disabled, metrics aren't recorded at all and no data is uploaded.
48+
*
49+
* When disabling, all pending metrics, events and queued pings are cleared.
2050
*
21-
* @param flag Whether to disable or enable upload.
51+
* When enabling, the core Glean metrics are recreated.
52+
*
53+
* If the value of this flag is not actually changed, this is a no-op.
54+
*
55+
* If Glean has not been initialized yet, this is also a no-op.
56+
*
57+
* @param flag When true, enable metric collection.
58+
*
59+
* @returns A promise that is resolved once setUploadEnabled is completed.
2260
*/
23-
setUploadEnabled(flag: boolean): void {
24-
console.info(`Called Glean.setUploadEnabled(${flag})).`);
61+
async setUploadEnabled(flag: boolean): Promise<void> {
62+
if (!Glean.initialized) {
63+
console.error(
64+
`Changing upload enabled before Glean is initialized is not supported.
65+
Pass the correct state into \`Glean.initialize\`.
66+
See documentation at https://mozilla.github.io/glean/book/user/general-api.html#initializing-the-glean-sdk`
67+
);
68+
return;
69+
}
70+
71+
await Glean.setUploadEnabled(flag);
72+
},
73+
74+
_private: {
75+
PingType,
76+
BooleanMetricType,
77+
CounterMetricType,
78+
DatetimeMetricType,
79+
StringMetricType,
80+
UUIDMetricType
2581
}
2682
}

src/metrics/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,6 @@ export abstract class MetricType implements CommonMetricData {
147147
* @returns Whether or not this metric instance should be recorded.
148148
*/
149149
shouldRecord(): boolean {
150-
return (Glean.uploadEnabled && !this.disabled);
150+
return (Glean.isUploadEnabled() && !this.disabled);
151151
}
152152
}

src/metrics/types/uuid.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,32 @@ import { Metric, MetricType, CommonMetricData } from "metrics";
99
import { isString } from "utils";
1010
import Glean from "glean";
1111

12+
/**
13+
* Generates a UUIDv4.
14+
*
15+
* Will provide a fallback in case `crypto` is not available,
16+
* which makes the "uuid" package generator not work.
17+
*
18+
* # Important
19+
*
20+
* This workaround is here for usage in Qt/QML environments, where `crypto` is not available.
21+
* Bug 1688015 was opened to figure out a less hacky way to do this.
22+
*
23+
* @returns A randomly generated UUIDv4.
24+
*/
25+
function generateUUIDv4(): string {
26+
if (typeof crypto !== "undefined") {
27+
return UUIDv4();
28+
} else {
29+
// Copied from https://stackoverflow.com/a/2117523/261698
30+
// and https://stackoverflow.com/questions/105034/how-to-create-guid-uuid
31+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
32+
const r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8);
33+
return v.toString(16);
34+
});
35+
}
36+
}
37+
1238
export class UUIDMetric extends Metric<string, string> {
1339
constructor(v: unknown) {
1440
super(v);
@@ -54,7 +80,7 @@ class UUIDMetricType extends MetricType {
5480
}
5581

5682
if (!value) {
57-
value = UUIDv4();
83+
value = generateUUIDv4();
5884
}
5985

6086
let metric: UUIDMetric;
@@ -79,7 +105,7 @@ class UUIDMetricType extends MetricType {
79105
return;
80106
}
81107

82-
const value = UUIDv4();
108+
const value = generateUUIDv4();
83109
await this.set(value);
84110

85111
return value;

src/pings/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class PingType {
5050
return false;
5151
}
5252

53-
if (!Glean.uploadEnabled) {
53+
if (!Glean.isUploadEnabled()) {
5454
console.info("Glean disabled: not submitting any pings.");
5555
return false;
5656
}

src/pings/maker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import CounterMetricType, { CounterMetric } from "metrics/types/counter";
77
import DatetimeMetricType, { DatetimeMetric } from "metrics/types/datetime";
88
import { Lifetime } from "metrics";
99
import TimeUnit from "metrics/time_unit";
10-
import { ClientInfo, PingInfo, PingHeaders, PingPayload } from "pings/database";
10+
import { ClientInfo, PingInfo, PingPayload } from "pings/database";
1111
import PingType from "pings";
1212
import Glean from "glean";
1313

@@ -151,7 +151,7 @@ export async function buildClientInfoSection(ping: PingType): Promise<ClientInfo
151151
* @returns An object with the headers to include
152152
* or `undefined` if there are no headers to include.
153153
*/
154-
export async function getPingHeaders(): Promise<PingHeaders | undefined> {
154+
export async function getPingHeaders(): Promise<Record<string, string> | undefined> {
155155
// TODO: Returning nothing for now until Bug 1685718 is resolved.
156156
return;
157157
}

0 commit comments

Comments
 (0)