зеркало из https://github.com/mozilla/fxa.git
feat(metrics): set available ping metrics during Glean init
Because: - we want to send known metric values in the automatic page load events This commit: - set the available metrics when initializing Glean, before any page load events
This commit is contained in:
Родитель
1328ec8597
Коммит
5a80a63555
|
@ -172,7 +172,7 @@ Start.prototype = {
|
|||
},
|
||||
|
||||
initializeGlean() {
|
||||
GleanMetrics.initialize(this._config.glean, {
|
||||
return GleanMetrics.initialize(this._config.glean, {
|
||||
metrics: this._metrics,
|
||||
relier: this._relier,
|
||||
user: this._user,
|
||||
|
|
|
@ -87,7 +87,7 @@ const hashUid = async (uid) => {
|
|||
return hex;
|
||||
};
|
||||
|
||||
const populateMetrics = async (properties: EventProperties = {}) => {
|
||||
const initMetrics = async () => {
|
||||
const account = gleanMetricsContext.user.getSignedInAccount();
|
||||
|
||||
// the "signed in" account could just be the most recently used account from
|
||||
|
@ -103,10 +103,6 @@ const populateMetrics = async (properties: EventProperties = {}) => {
|
|||
userIdSha256.set('');
|
||||
}
|
||||
|
||||
for (const n of eventPropertyNames) {
|
||||
event[n].set(properties[n] || '');
|
||||
}
|
||||
|
||||
const flowEventMetadata = gleanMetricsContext.metrics.getFlowEventMetadata();
|
||||
|
||||
oauthClientId.set(gleanMetricsContext.relier.get('clientId') || '');
|
||||
|
@ -126,6 +122,13 @@ const populateMetrics = async (properties: EventProperties = {}) => {
|
|||
entrypointQuery.variation.set(flowEventMetadata.entrypointVariation || '');
|
||||
};
|
||||
|
||||
const populateMetrics = async (properties: EventProperties = {}) => {
|
||||
await initMetrics();
|
||||
for (const n of eventPropertyNames) {
|
||||
event[n].set(properties[n] || '');
|
||||
}
|
||||
};
|
||||
|
||||
const recordEventMetric = (eventName: string, properties: EventProperties) => {
|
||||
switch (eventName) {
|
||||
case 'email_first_view':
|
||||
|
@ -349,7 +352,10 @@ const createEventFn =
|
|||
};
|
||||
|
||||
export const GleanMetrics = {
|
||||
initialize: (config: GleanMetricsConfig, context: GleanMetricsContext) => {
|
||||
initialize: async (
|
||||
config: GleanMetricsConfig,
|
||||
context: GleanMetricsContext
|
||||
) => {
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1859629
|
||||
// Starting with glean.js v2, accessing localStorage during
|
||||
// initialization could cause an error
|
||||
|
@ -373,6 +379,7 @@ export const GleanMetrics = {
|
|||
gleanMetricsContext = context;
|
||||
}
|
||||
GleanMetrics.setEnabled(config.enabled);
|
||||
await initMetrics();
|
||||
} catch (_) {
|
||||
// set some states so we won't try to do anything with glean.js later
|
||||
config.enabled = false;
|
||||
|
|
|
@ -187,7 +187,8 @@ describe('lib/glean', () => {
|
|||
});
|
||||
|
||||
it('submits a ping on an event', async () => {
|
||||
await GleanMetrics.registration.view();
|
||||
GleanMetrics.registration.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(submitPingStub);
|
||||
});
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ jest.mock('../../lib/glean', () => ({
|
|||
default: {
|
||||
initialize: jest.fn(),
|
||||
getEnabled: jest.fn(),
|
||||
useGlean: jest.fn().mockReturnValue({ enabled: true }),
|
||||
accountPref: { view: jest.fn(), promoMonitorView: jest.fn() },
|
||||
pageLoad: jest.fn(),
|
||||
},
|
||||
|
|
|
@ -161,6 +161,11 @@ export const App = ({
|
|||
return;
|
||||
}
|
||||
|
||||
// This is in a useMemo because we want Glean to be initialized _before_
|
||||
// other components are rendered. `useEffect` is called after a component
|
||||
// is rendered, which for this means _after_ all the children components
|
||||
// are rendered and _their `useEffect` hooks are called_.
|
||||
|
||||
GleanMetrics.initialize(
|
||||
{
|
||||
...config.glean,
|
||||
|
@ -297,10 +302,11 @@ const AuthAndAccountSetupRoutes = ({
|
|||
// TODO: MozServices / string discrepancy, FXA-6802
|
||||
const serviceName = integration.getServiceName() as MozServices;
|
||||
const location = useLocation();
|
||||
const { enabled: gleanEnabled } = GleanMetrics.useGlean();
|
||||
|
||||
useEffect(() => {
|
||||
GleanMetrics.pageLoad(location.pathname);
|
||||
}, [location.pathname]);
|
||||
gleanEnabled && GleanMetrics.pageLoad(location.pathname);
|
||||
}, [location.pathname, gleanEnabled]);
|
||||
|
||||
return (
|
||||
<Router>
|
||||
|
|
|
@ -73,10 +73,11 @@ export const Settings = ({
|
|||
}, [account, session]);
|
||||
|
||||
const { loading, error } = useInitialSettingsState();
|
||||
const { enabled: gleanEnabled } = GleanMetrics.useGlean();
|
||||
|
||||
useEffect(() => {
|
||||
!loading && GleanMetrics.pageLoad(location.pathname);
|
||||
}, [loading, location.pathname]);
|
||||
!loading && gleanEnabled && GleanMetrics.pageLoad(location.pathname);
|
||||
}, [loading, location.pathname, gleanEnabled]);
|
||||
|
||||
if (loading) {
|
||||
return <LoadingSpinner fullScreen />;
|
||||
|
|
|
@ -166,6 +166,10 @@ describe('lib/glean', () => {
|
|||
sinon.assert.notCalled(setEntrypointExperimentStub);
|
||||
sinon.assert.notCalled(setEntrypointVariationStub);
|
||||
});
|
||||
|
||||
it('returns false for enabed in useGlean', () => {
|
||||
expect(GleanMetrics.useGlean().enabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('initialization error', () => {
|
||||
|
@ -211,6 +215,10 @@ describe('lib/glean', () => {
|
|||
sinon.assert.calledWith(setEnabledSpy, true);
|
||||
});
|
||||
|
||||
it('returns true for enabed in useGlean', () => {
|
||||
expect(GleanMetrics.useGlean().enabled).toBe(true);
|
||||
});
|
||||
|
||||
it('submits a ping on an event', async () => {
|
||||
GleanMetrics.registration.view();
|
||||
await GleanMetrics.isDone();
|
||||
|
|
|
@ -66,6 +66,8 @@ type GleanMetricsT = {
|
|||
isDone: () => Promise<void>;
|
||||
pageLoad: (url?: string) => void;
|
||||
handleClickEvent(event: Event): void;
|
||||
|
||||
useGlean: () => { enabled: boolean };
|
||||
} & {
|
||||
[k in EventMapKeys]: { [eventKey in keyof EventsMap[k]]: PingFn };
|
||||
};
|
||||
|
@ -127,34 +129,7 @@ const getDeviceType: () => DeviceTypes | void = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const populateMetrics = async (gleanPingMetrics: GleanPingMetrics) => {
|
||||
if (gleanPingMetrics?.event) {
|
||||
// The event here is the Glean `event` metric type, not an "metrics event" in
|
||||
// a more general sense
|
||||
|
||||
for (const name of booleanEventPropertyNames) {
|
||||
const eventValue = gleanPingMetrics.event[name];
|
||||
if (eventValue) {
|
||||
event[name].set(eventValue);
|
||||
}
|
||||
}
|
||||
for (const name of stringEventPropertyNames) {
|
||||
event[name].set(gleanPingMetrics.event[name] || '');
|
||||
}
|
||||
}
|
||||
|
||||
if (gleanPingMetrics?.sync?.cwts) {
|
||||
Object.entries(gleanPingMetrics.sync.cwts).forEach(([k, v]) => {
|
||||
sync.cwts[k].set(v);
|
||||
});
|
||||
}
|
||||
|
||||
if (gleanPingMetrics?.standard?.marketing) {
|
||||
Object.entries(gleanPingMetrics.standard.marketing).forEach(([k, v]) => {
|
||||
standard.marketing[k].set(v);
|
||||
});
|
||||
}
|
||||
|
||||
const initMetrics = async () => {
|
||||
userId.set('');
|
||||
userIdSha256.set('');
|
||||
try {
|
||||
|
@ -187,6 +162,37 @@ const populateMetrics = async (gleanPingMetrics: GleanPingMetrics) => {
|
|||
);
|
||||
};
|
||||
|
||||
const populateMetrics = async (gleanPingMetrics: GleanPingMetrics) => {
|
||||
await initMetrics();
|
||||
|
||||
if (gleanPingMetrics?.event) {
|
||||
// The event here is the Glean `event` metric type, not an "metrics event" in
|
||||
// a more general sense
|
||||
|
||||
for (const name of booleanEventPropertyNames) {
|
||||
const eventValue = gleanPingMetrics.event[name];
|
||||
if (eventValue) {
|
||||
event[name].set(eventValue);
|
||||
}
|
||||
}
|
||||
for (const name of stringEventPropertyNames) {
|
||||
event[name].set(gleanPingMetrics.event[name] || '');
|
||||
}
|
||||
}
|
||||
|
||||
if (gleanPingMetrics?.sync?.cwts) {
|
||||
Object.entries(gleanPingMetrics.sync.cwts).forEach(([k, v]) => {
|
||||
sync.cwts[k].set(v);
|
||||
});
|
||||
}
|
||||
|
||||
if (gleanPingMetrics?.standard?.marketing) {
|
||||
Object.entries(gleanPingMetrics.standard.marketing).forEach(([k, v]) => {
|
||||
standard.marketing[k].set(v);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const recordEventMetric = (
|
||||
eventName: string,
|
||||
gleanPingMetrics: GleanPingMetrics
|
||||
|
@ -532,11 +538,15 @@ export const GleanMetrics: Pick<
|
|||
| 'initialize'
|
||||
| 'setEnabled'
|
||||
| 'getEnabled'
|
||||
| 'useGlean'
|
||||
| 'isDone'
|
||||
| 'pageLoad'
|
||||
| 'handleClickEvent'
|
||||
> = {
|
||||
initialize: (config: GleanMetricsConfig, context: GleanMetricsContext) => {
|
||||
initialize: async (
|
||||
config: GleanMetricsConfig,
|
||||
context: GleanMetricsContext
|
||||
) => {
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1859629
|
||||
// Starting with glean.js v2, accessing localStorage during
|
||||
// initialization could cause an error
|
||||
|
@ -557,6 +567,10 @@ export const GleanMetrics: Pick<
|
|||
GleanMetrics.setEnabled(config.enabled);
|
||||
metricsContext = context;
|
||||
ua = null;
|
||||
|
||||
// try to initialize any available metrics prior to any automatic Glean
|
||||
// events
|
||||
await initMetrics();
|
||||
} catch (_) {
|
||||
// set some states so we won't try to do anything with glean.js later
|
||||
config.enabled = false;
|
||||
|
@ -573,6 +587,8 @@ export const GleanMetrics: Pick<
|
|||
return gleanEnabled;
|
||||
},
|
||||
|
||||
useGlean: () => ({ enabled: GleanMetrics.getEnabled() }),
|
||||
|
||||
pageLoad: (url?: string) => {
|
||||
if (url) {
|
||||
GleanMetricsAPI.pageLoad({ url });
|
||||
|
|
Загрузка…
Ссылка в новой задаче