Skip to content

Commit 92bdb9a

Browse files
author
Robert-Jan Huijsman
authored
Set Analytics event.timestamp from event.data.logTime if timestamp is invalid (#129)
Currently, the Analytics backend is still sending an invalid (1969 or 1970) timestamp in 'event.timestamp'. This PR adds a shim to detect that, and pull a better timestamp from 'event.data.logTime', if available. This is temporary; we'll remove the shim when we roll a fix for the backend out to production.
1 parent 75faf94 commit 92bdb9a

File tree

3 files changed

+86
-63
lines changed

3 files changed

+86
-63
lines changed

spec/providers/analytics.spec.input.ts

Lines changed: 68 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
/* tslint:disable:max-line-length */
2424
import { AnalyticsEvent } from '../../src/providers/analytics';
25+
import { Event } from '../../src/cloud-functions';
2526

2627
// A payload, as it might arrive over the wire. Every possible field is filled out at least once.
2728
export const fullPayload = JSON.parse(`{
@@ -124,70 +125,77 @@ export const fullPayload = JSON.parse(`{
124125
}`);
125126

126127
// The event data that we expect would be constructed if the payload above were to arrive.
127-
export const fullEventData: AnalyticsEvent = {
128-
reportingDate: '20170202',
129-
name: 'Loaded_In_Background',
130-
params: {
131-
build: '1350',
132-
calls_remaining: 10,
133-
fraction_calls_dropped: 0.0123456,
134-
average_call_rating: 4.5,
135-
},
136-
logTime: '2017-02-02T23:06:26.124Z',
137-
previousLogTime: '2017-02-02T23:01:19.797Z',
138-
valueInUSD: 1234.5,
139-
user: {
140-
userId: 'abcdefghijklmnop!',
141-
appInfo: {
142-
appId: 'com.mobileday.MobileDay',
143-
appInstanceId: 'E3C9939401814B9B954725A740B8C7BC',
144-
appPlatform: 'IOS',
145-
appStore: 'iTunes',
146-
appVersion: '5.2.0',
147-
},
148-
trafficSource: {
149-
userAcquiredSource: 'Pizza Everywhere',
150-
userAcquiredCampaign: 'Functions launch party',
151-
userAcquiredMedium: 'Free food',
152-
},
153-
bundleInfo: {
154-
bundleSequenceId: 6034,
155-
serverTimestampOffset: 371,
128+
export const fullEvent: Event<AnalyticsEvent> = {
129+
eventId: '1486080145623867projects/analytics-integration-fd82a/events/i_made_this_upproviders/google.firebase.analytics/eventTypes/event.sendprojects/f949d1bb9ef782579-tp/topics/cloud-functions-u54ejabpzs4prfjh7433eklhae',
130+
eventType: 'providers/google.firebase.analytics/eventTypes/event.send',
131+
resource: 'projects/analytics-integration-fd82a/events/i_made_this_up',
132+
timestamp: '2017-02-02T23:06:26.124Z',
133+
params: {},
134+
data: {
135+
reportingDate: '20170202',
136+
name: 'Loaded_In_Background',
137+
params: {
138+
build: '1350',
139+
calls_remaining: 10,
140+
fraction_calls_dropped: 0.0123456,
141+
average_call_rating: 4.5,
156142
},
157-
deviceInfo: {
158-
deviceCategory: 'mobile',
159-
deviceModel: 'iPhone7,2',
160-
deviceTimeZoneOffsetSeconds: -21600,
161-
mobileBrandName: 'Apple',
162-
mobileMarketingName: 'iPhone 6',
163-
mobileModelName: 'iPhone 6',
164-
platformVersion: '10.2.1',
165-
userDefaultLanguage: 'en-us',
166-
deviceId: '599F9C00-92DC-4B5C-9464-7971F01F8370',
167-
resettableDeviceId: '599F9C00-92DC-4B5C-9464-7971F01F8370',
168-
limitedAdTracking: true,
169-
},
170-
firstOpenTime: '2016-04-28T15:00:35.819Z',
171-
geoInfo: {
172-
city: 'Plano',
173-
continent: '021',
174-
country: 'United States',
175-
region: 'Texas',
176-
},
177-
userProperties: {
178-
build: {
179-
setTime: '2017-02-02T23:06:26.090Z',
180-
value: '1350',
143+
logTime: '2017-02-02T23:06:26.124Z',
144+
previousLogTime: '2017-02-02T23:01:19.797Z',
145+
valueInUSD: 1234.5,
146+
user: {
147+
userId: 'abcdefghijklmnop!',
148+
appInfo: {
149+
appId: 'com.mobileday.MobileDay',
150+
appInstanceId: 'E3C9939401814B9B954725A740B8C7BC',
151+
appPlatform: 'IOS',
152+
appStore: 'iTunes',
153+
appVersion: '5.2.0',
154+
},
155+
trafficSource: {
156+
userAcquiredSource: 'Pizza Everywhere',
157+
userAcquiredCampaign: 'Functions launch party',
158+
userAcquiredMedium: 'Free food',
181159
},
182-
calls_remaining: {
183-
setTime: '2017-02-02T23:06:26.094Z',
184-
value: '10',
160+
bundleInfo: {
161+
bundleSequenceId: 6034,
162+
serverTimestampOffset: 371,
185163
},
186-
version: {
187-
setTime: '2017-02-02T23:06:26.085Z',
188-
value: '5.2.0',
164+
deviceInfo: {
165+
deviceCategory: 'mobile',
166+
deviceModel: 'iPhone7,2',
167+
deviceTimeZoneOffsetSeconds: -21600,
168+
mobileBrandName: 'Apple',
169+
mobileMarketingName: 'iPhone 6',
170+
mobileModelName: 'iPhone 6',
171+
platformVersion: '10.2.1',
172+
userDefaultLanguage: 'en-us',
173+
deviceId: '599F9C00-92DC-4B5C-9464-7971F01F8370',
174+
resettableDeviceId: '599F9C00-92DC-4B5C-9464-7971F01F8370',
175+
limitedAdTracking: true,
176+
},
177+
firstOpenTime: '2016-04-28T15:00:35.819Z',
178+
geoInfo: {
179+
city: 'Plano',
180+
continent: '021',
181+
country: 'United States',
182+
region: 'Texas',
183+
},
184+
userProperties: {
185+
build: {
186+
setTime: '2017-02-02T23:06:26.090Z',
187+
value: '1350',
188+
},
189+
calls_remaining: {
190+
setTime: '2017-02-02T23:06:26.094Z',
191+
value: '10',
192+
},
193+
version: {
194+
setTime: '2017-02-02T23:06:26.085Z',
195+
value: '5.2.0',
196+
},
189197
},
198+
ltvInUSD: 133.7,
190199
},
191-
ltvInUSD: 133.7,
192200
},
193201
};

spec/providers/analytics.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,10 @@ describe('AnalyticsEventBuilder', () => {
226226
});
227227

228228
it('should recognize all the fields the payload can contain', () => {
229-
const cloudFunction = analytics.event('first_open').onLog((ev: Event<analytics.AnalyticsEvent>) => ev.data);
229+
const cloudFunction = analytics.event('first_open').onLog((ev: Event<analytics.AnalyticsEvent>) => ev);
230230
// The payload in analytics_spec_input contains all possible fields at least once.
231231
return expect(cloudFunction(analytics_spec_input.fullPayload))
232-
.to.eventually.deep.equal(analytics_spec_input.fullEventData);
232+
.to.eventually.deep.equal(analytics_spec_input.fullEvent);
233233
});
234234
});
235235
});

src/providers/analytics.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,23 @@ export class AnalyticsEventBuilder {
4444
const dataConstructor = (raw: Event<any>) => {
4545
return new AnalyticsEvent(raw.data);
4646
};
47+
const attemptTimestampFix = (event: Event<AnalyticsEvent>) => {
48+
// This is a temporary shim, to mask an issue in which Analytics events may carry an
49+
// incorrect Event.timestamp. Often there's a correct timestamp present in
50+
// Event.data.logTime, so until the production backend sends correct top-level timestamps
51+
// we can pull a timestamp from there.
52+
// BUG(36001921).
53+
if (event.timestamp && (event.timestamp.substr(0, 4) === '1969' || event.timestamp.substr(0, 4) === '1970')) {
54+
event.timestamp = undefined; // If we don't have a good timestamp, prefer no timestamp at all.
55+
if (event.data && event.data.logTime) {
56+
event.timestamp = event.data.logTime;
57+
}
58+
}
59+
return handler(event);
60+
};
4761
return makeCloudFunction({
48-
provider, handler,
62+
provider,
63+
handler: attemptTimestampFix,
4964
eventType: 'event.log',
5065
resource: this.resource,
5166
dataConstructor,

0 commit comments

Comments
 (0)