@aws-amplify/analytics 6.1.2-unstable.ffe65ea.1 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Providers/AWSPinpointProvider.d.ts +2 -5
- package/lib/Providers/AWSPinpointProvider.js +61 -96
- package/lib/Providers/AWSPinpointProvider.js.map +1 -1
- package/lib/Providers/EventBuffer.d.ts +1 -3
- package/lib/Providers/EventBuffer.js +22 -20
- package/lib/Providers/EventBuffer.js.map +1 -1
- package/lib-esm/Providers/AWSPinpointProvider.d.ts +2 -5
- package/lib-esm/Providers/AWSPinpointProvider.js +63 -98
- package/lib-esm/Providers/AWSPinpointProvider.js.map +1 -1
- package/lib-esm/Providers/EventBuffer.d.ts +1 -3
- package/lib-esm/Providers/EventBuffer.js +22 -20
- package/lib-esm/Providers/EventBuffer.js.map +1 -1
- package/package.json +6 -7
- package/src/Providers/AWSPinpointProvider.ts +62 -118
- package/src/Providers/EventBuffer.ts +47 -52
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import { Cache } from '@aws-amplify/cache';
|
|
4
5
|
import {
|
|
5
6
|
ConsoleLogger as Logger,
|
|
6
7
|
ClientDevice,
|
|
7
8
|
Credentials,
|
|
8
9
|
Signer,
|
|
9
10
|
Hub,
|
|
10
|
-
getAmplifyUserAgent,
|
|
11
11
|
transferKeyToLowerCase,
|
|
12
12
|
transferKeyToUpperCase,
|
|
13
13
|
} from '@aws-amplify/core';
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
putEvents,
|
|
16
|
+
PutEventsInput,
|
|
17
|
+
PutEventsOutput,
|
|
18
|
+
updateEndpoint,
|
|
19
|
+
UpdateEndpointInput,
|
|
20
|
+
UpdateEndpointOutput,
|
|
21
|
+
} from '@aws-amplify/core/internals/aws-clients/pinpoint';
|
|
22
22
|
|
|
23
23
|
import {
|
|
24
24
|
AnalyticsProvider,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
EndpointFailureData,
|
|
30
30
|
} from '../types';
|
|
31
31
|
import { v1 as uuid } from 'uuid';
|
|
32
|
-
import
|
|
32
|
+
import EventBuffer from './EventBuffer';
|
|
33
33
|
|
|
34
34
|
const AMPLIFY_SYMBOL = (
|
|
35
35
|
typeof Symbol !== 'undefined' && typeof Symbol.for === 'function'
|
|
@@ -68,10 +68,9 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
68
68
|
static providerName = 'AWSPinpoint';
|
|
69
69
|
|
|
70
70
|
private _config;
|
|
71
|
-
private pinpointClient;
|
|
72
71
|
private _sessionId;
|
|
73
72
|
private _sessionStartTimestamp;
|
|
74
|
-
private _buffer:
|
|
73
|
+
private _buffer: EventBuffer | null;
|
|
75
74
|
private _endpointBuffer: EndpointBuffer;
|
|
76
75
|
private _clientInfo;
|
|
77
76
|
private _endpointGenerating = true;
|
|
@@ -152,7 +151,7 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
152
151
|
);
|
|
153
152
|
}
|
|
154
153
|
|
|
155
|
-
this.
|
|
154
|
+
this._init(credentials);
|
|
156
155
|
|
|
157
156
|
const timestamp = new Date().getTime();
|
|
158
157
|
// attach the session and eventId
|
|
@@ -194,7 +193,7 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
194
193
|
return;
|
|
195
194
|
}
|
|
196
195
|
|
|
197
|
-
this._buffer
|
|
196
|
+
this._buffer?.push({ params, handlers });
|
|
198
197
|
}
|
|
199
198
|
|
|
200
199
|
private _generateSession(params) {
|
|
@@ -249,34 +248,31 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
249
248
|
}
|
|
250
249
|
}
|
|
251
250
|
|
|
252
|
-
private _generateBatchItemContext(params) {
|
|
251
|
+
private _generateBatchItemContext(params): PutEventsInput {
|
|
253
252
|
const { event, timestamp, config } = params;
|
|
254
253
|
const { name, attributes, metrics, eventId, session } = event;
|
|
255
254
|
const { appId, endpointId } = config;
|
|
256
|
-
|
|
257
255
|
const endpointContext = {};
|
|
258
256
|
|
|
259
|
-
|
|
257
|
+
return {
|
|
260
258
|
ApplicationId: appId,
|
|
261
259
|
EventsRequest: {
|
|
262
|
-
BatchItem: {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
260
|
+
BatchItem: {
|
|
261
|
+
[endpointId]: {
|
|
262
|
+
Endpoint: endpointContext,
|
|
263
|
+
Events: {
|
|
264
|
+
[eventId]: {
|
|
265
|
+
EventType: name,
|
|
266
|
+
Timestamp: new Date(timestamp).toISOString(),
|
|
267
|
+
Attributes: attributes,
|
|
268
|
+
Metrics: metrics,
|
|
269
|
+
Session: session,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
275
274
|
},
|
|
276
275
|
};
|
|
277
|
-
eventParams.EventsRequest.BatchItem[endpointId] = endpointObj;
|
|
278
|
-
|
|
279
|
-
return eventParams;
|
|
280
276
|
}
|
|
281
277
|
|
|
282
278
|
private async _pinpointPutEvents(params, handlers) {
|
|
@@ -285,33 +281,30 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
285
281
|
config: { endpointId },
|
|
286
282
|
} = params;
|
|
287
283
|
const eventParams = this._generateBatchItemContext(params);
|
|
288
|
-
const command: PutEventsCommand = new PutEventsCommand(eventParams);
|
|
289
284
|
|
|
290
285
|
try {
|
|
291
|
-
const
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if (ACCEPTED_CODES.includes(StatusCode)) {
|
|
286
|
+
const { credentials, region } = this._config;
|
|
287
|
+
const data: PutEventsOutput = await putEvents(
|
|
288
|
+
{ credentials, region },
|
|
289
|
+
eventParams
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const { StatusCode, Message } =
|
|
293
|
+
data.EventsResponse?.Results?.[endpointId]?.EventsItemResponse?.[
|
|
294
|
+
eventId
|
|
295
|
+
] ?? {};
|
|
296
|
+
|
|
297
|
+
if (StatusCode && ACCEPTED_CODES.includes(StatusCode)) {
|
|
304
298
|
logger.debug('record event success. ', data);
|
|
305
299
|
return handlers.resolve(data);
|
|
300
|
+
} else if (StatusCode && RETRYABLE_CODES.includes(StatusCode)) {
|
|
301
|
+
// TODO: v6 integrate retry to the service handler retryDecider
|
|
302
|
+
this._retry(params, handlers);
|
|
306
303
|
} else {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
`Event ${eventId} is not accepted, the error is ${Message}`
|
|
312
|
-
);
|
|
313
|
-
return handlers.reject(data);
|
|
314
|
-
}
|
|
304
|
+
logger.error(
|
|
305
|
+
`Event ${eventId} is not accepted, the error is ${Message}`
|
|
306
|
+
);
|
|
307
|
+
return handlers.reject(data);
|
|
315
308
|
}
|
|
316
309
|
} catch (err) {
|
|
317
310
|
this._eventError(err);
|
|
@@ -319,7 +312,7 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
319
312
|
}
|
|
320
313
|
}
|
|
321
314
|
|
|
322
|
-
private _pinpointSendStopSession(params, handlers): Promise<string> {
|
|
315
|
+
private _pinpointSendStopSession(params, handlers): Promise<string> | void {
|
|
323
316
|
if (!BEACON_SUPPORTED) {
|
|
324
317
|
this._pinpointPutEvents(params, handlers);
|
|
325
318
|
return;
|
|
@@ -348,12 +341,7 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
348
341
|
|
|
349
342
|
const serviceInfo = { region, service: MOBILE_SERVICE_NAME };
|
|
350
343
|
|
|
351
|
-
const requestUrl: string = Signer.signUrl(
|
|
352
|
-
request,
|
|
353
|
-
accessInfo,
|
|
354
|
-
serviceInfo,
|
|
355
|
-
null
|
|
356
|
-
);
|
|
344
|
+
const requestUrl: string = Signer.signUrl(request, accessInfo, serviceInfo);
|
|
357
345
|
|
|
358
346
|
const success: boolean = navigator.sendBeacon(requestUrl, body);
|
|
359
347
|
|
|
@@ -393,18 +381,18 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
393
381
|
['attributes', 'userAttributes', 'Attributes', 'UserAttributes']
|
|
394
382
|
)
|
|
395
383
|
);
|
|
396
|
-
const update_params = {
|
|
384
|
+
const update_params: UpdateEndpointInput = {
|
|
397
385
|
ApplicationId: appId,
|
|
398
386
|
EndpointId: endpointId,
|
|
399
387
|
EndpointRequest: request,
|
|
400
388
|
};
|
|
401
389
|
|
|
402
390
|
try {
|
|
403
|
-
const
|
|
391
|
+
const { credentials, region } = this._config;
|
|
392
|
+
const data: UpdateEndpointOutput = await updateEndpoint(
|
|
393
|
+
{ credentials, region },
|
|
404
394
|
update_params
|
|
405
395
|
);
|
|
406
|
-
const data = await this.pinpointClient.send(command);
|
|
407
|
-
|
|
408
396
|
logger.debug('updateEndpoint success', data);
|
|
409
397
|
this._endpointGenerating = false;
|
|
410
398
|
this._resumeBuffer();
|
|
@@ -492,13 +480,12 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
492
480
|
/**
|
|
493
481
|
* @private
|
|
494
482
|
* @param config
|
|
495
|
-
*
|
|
483
|
+
* Configure credentials and init buffer
|
|
496
484
|
*/
|
|
497
|
-
private async
|
|
498
|
-
logger.debug('init
|
|
485
|
+
private async _init(credentials) {
|
|
486
|
+
logger.debug('init provider');
|
|
499
487
|
|
|
500
488
|
if (
|
|
501
|
-
this.pinpointClient &&
|
|
502
489
|
this._config.credentials &&
|
|
503
490
|
this._config.credentials.sessionToken === credentials.sessionToken &&
|
|
504
491
|
this._config.credentials.identityId === credentials.identityId
|
|
@@ -512,43 +499,17 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
512
499
|
: null;
|
|
513
500
|
|
|
514
501
|
this._config.credentials = credentials;
|
|
515
|
-
const { region } = this._config;
|
|
516
|
-
logger.debug('init clients with credentials', credentials);
|
|
517
|
-
this.pinpointClient = new PinpointClient({
|
|
518
|
-
region,
|
|
519
|
-
credentials,
|
|
520
|
-
customUserAgent: getAmplifyUserAgent(),
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
// TODO: remove this middleware once a long term fix is implemented by aws-sdk-js team.
|
|
524
|
-
this.pinpointClient.middlewareStack.addRelativeTo(
|
|
525
|
-
next => args => {
|
|
526
|
-
delete args.request.headers['amz-sdk-invocation-id'];
|
|
527
|
-
delete args.request.headers['amz-sdk-request'];
|
|
528
|
-
return next(args);
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
step: 'finalizeRequest',
|
|
532
|
-
relation: 'after',
|
|
533
|
-
toMiddleware: 'retryMiddleware',
|
|
534
|
-
}
|
|
535
|
-
);
|
|
536
502
|
|
|
537
|
-
if (this._bufferExists()
|
|
538
|
-
// if the identity has
|
|
539
|
-
this._updateBufferClient();
|
|
540
|
-
} else {
|
|
541
|
-
// otherwise flush the buffer and instantiate a new one
|
|
503
|
+
if (!this._bufferExists() || identityId !== credentials.identityId) {
|
|
504
|
+
// if the identity has changed, flush the buffer and instantiate a new one
|
|
542
505
|
// this will cause the old buffer to send any remaining events
|
|
543
506
|
// with the old credentials and then stop looping and shortly thereafter get picked up by GC
|
|
544
507
|
this._initBuffer();
|
|
545
508
|
}
|
|
546
|
-
|
|
547
|
-
this._customizePinpointClientReq();
|
|
548
509
|
}
|
|
549
510
|
|
|
550
511
|
private _bufferExists() {
|
|
551
|
-
return this._buffer && this._buffer instanceof
|
|
512
|
+
return this._buffer && this._buffer instanceof EventBuffer;
|
|
552
513
|
}
|
|
553
514
|
|
|
554
515
|
private _initBuffer() {
|
|
@@ -556,7 +517,7 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
556
517
|
this._flushBuffer();
|
|
557
518
|
}
|
|
558
519
|
|
|
559
|
-
this._buffer = new
|
|
520
|
+
this._buffer = new EventBuffer(this._config);
|
|
560
521
|
|
|
561
522
|
// if the first endpoint update hasn't yet resolved pause the buffer to
|
|
562
523
|
// prevent race conditions. It will be resumed as soon as that request succeeds
|
|
@@ -565,36 +526,19 @@ export class AWSPinpointProvider implements AnalyticsProvider {
|
|
|
565
526
|
}
|
|
566
527
|
}
|
|
567
528
|
|
|
568
|
-
private _updateBufferClient() {
|
|
569
|
-
if (this._bufferExists()) {
|
|
570
|
-
this._buffer.updateClient(this.pinpointClient);
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
529
|
private _flushBuffer() {
|
|
575
530
|
if (this._bufferExists()) {
|
|
576
|
-
this._buffer
|
|
531
|
+
this._buffer?.flush();
|
|
577
532
|
this._buffer = null;
|
|
578
533
|
}
|
|
579
534
|
}
|
|
580
535
|
|
|
581
536
|
private _resumeBuffer() {
|
|
582
537
|
if (this._bufferExists()) {
|
|
583
|
-
this._buffer
|
|
538
|
+
this._buffer?.resume();
|
|
584
539
|
}
|
|
585
540
|
}
|
|
586
541
|
|
|
587
|
-
private _customizePinpointClientReq() {
|
|
588
|
-
// TODO FIXME: Find a middleware to do this with AWS V3 SDK
|
|
589
|
-
// if (Platform.isReactNative) {
|
|
590
|
-
// this.pinpointClient.customizeRequests(request => {
|
|
591
|
-
// request.on('build', req => {
|
|
592
|
-
// req.httpRequest.headers['user-agent'] = Platform.userAgent;
|
|
593
|
-
// });
|
|
594
|
-
// });
|
|
595
|
-
// }
|
|
596
|
-
}
|
|
597
|
-
|
|
598
542
|
private async _getEndpointId(cacheKey) {
|
|
599
543
|
// try to get from cache
|
|
600
544
|
let endpointId = await Cache.getItem(cacheKey);
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import { ConsoleLogger as Logger } from '@aws-amplify/core';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
PutEventsResponse,
|
|
5
|
-
EventBuffer,
|
|
6
|
-
EventObject,
|
|
7
|
-
EventMap,
|
|
8
|
-
} from '../types';
|
|
9
2
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
putEvents,
|
|
4
|
+
PutEventsInput,
|
|
5
|
+
PutEventsOutput,
|
|
6
|
+
} from '@aws-amplify/core/internals/aws-clients/pinpoint';
|
|
7
|
+
import { EventBuffer, EventObject, EventMap } from '../types';
|
|
13
8
|
import { isAppInForeground } from '../utils/AppUtils';
|
|
14
9
|
|
|
15
10
|
const logger = new Logger('EventsBuffer');
|
|
@@ -25,16 +20,14 @@ type EventsBufferConfig = {
|
|
|
25
20
|
|
|
26
21
|
export default class EventsBuffer {
|
|
27
22
|
private _config;
|
|
28
|
-
private _client;
|
|
29
23
|
private _interval;
|
|
30
24
|
private _buffer: EventBuffer;
|
|
31
25
|
private _pause = false;
|
|
32
26
|
private _flush = false;
|
|
33
27
|
|
|
34
|
-
constructor(
|
|
28
|
+
constructor(config: EventsBufferConfig) {
|
|
35
29
|
logger.debug('Instantiating buffer with config:', config);
|
|
36
30
|
this._buffer = [];
|
|
37
|
-
this._client = client;
|
|
38
31
|
this._config = config;
|
|
39
32
|
|
|
40
33
|
this._sendBatch = this._sendBatch.bind(this);
|
|
@@ -64,10 +57,6 @@ export default class EventsBuffer {
|
|
|
64
57
|
this._pause = false;
|
|
65
58
|
}
|
|
66
59
|
|
|
67
|
-
public updateClient(client) {
|
|
68
|
-
this._client = client;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
60
|
public flush() {
|
|
72
61
|
this._flush = true;
|
|
73
62
|
}
|
|
@@ -110,15 +99,18 @@ export default class EventsBuffer {
|
|
|
110
99
|
const batchEventParams = this._generateBatchEventParams(eventMap);
|
|
111
100
|
|
|
112
101
|
try {
|
|
113
|
-
const
|
|
114
|
-
const data:
|
|
102
|
+
const { credentials, region } = this._config;
|
|
103
|
+
const data: PutEventsOutput = await putEvents(
|
|
104
|
+
{ credentials, region },
|
|
105
|
+
batchEventParams
|
|
106
|
+
);
|
|
115
107
|
this._processPutEventsSuccessResponse(data, eventMap);
|
|
116
108
|
} catch (err) {
|
|
117
109
|
return this._handlePutEventsFailure(err, eventMap);
|
|
118
110
|
}
|
|
119
111
|
}
|
|
120
112
|
|
|
121
|
-
private _generateBatchEventParams(eventMap: EventMap) {
|
|
113
|
+
private _generateBatchEventParams(eventMap: EventMap): PutEventsInput {
|
|
122
114
|
const batchEventParams = {
|
|
123
115
|
ApplicationId: '',
|
|
124
116
|
EventsRequest: {
|
|
@@ -167,50 +159,53 @@ export default class EventsBuffer {
|
|
|
167
159
|
}
|
|
168
160
|
|
|
169
161
|
private _processPutEventsSuccessResponse(
|
|
170
|
-
data:
|
|
162
|
+
data: PutEventsOutput,
|
|
171
163
|
eventMap: EventMap
|
|
172
164
|
) {
|
|
173
|
-
const { Results } = data.EventsResponse;
|
|
165
|
+
const { Results = {} } = data.EventsResponse ?? {};
|
|
174
166
|
const retryableEvents: EventObject[] = [];
|
|
175
167
|
|
|
176
168
|
Object.entries(Results).forEach(([endpointId, endpointValues]) => {
|
|
177
|
-
const responses = endpointValues.EventsItemResponse;
|
|
178
|
-
|
|
179
|
-
Object.entries(responses).forEach(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
169
|
+
const responses = endpointValues.EventsItemResponse ?? {};
|
|
170
|
+
|
|
171
|
+
Object.entries(responses).forEach(([eventId, eventValues]) => {
|
|
172
|
+
const eventObject = eventMap[eventId];
|
|
173
|
+
if (!eventObject) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const { StatusCode, Message } = eventValues ?? {};
|
|
178
|
+
|
|
179
|
+
// manually crafting handlers response to keep API consistant
|
|
180
|
+
const response = {
|
|
181
|
+
EventsResponse: {
|
|
182
|
+
Results: {
|
|
183
|
+
[endpointId]: {
|
|
184
|
+
EventsItemResponse: {
|
|
185
|
+
[eventId]: { StatusCode, Message },
|
|
191
186
|
},
|
|
192
187
|
},
|
|
193
188
|
},
|
|
194
|
-
}
|
|
189
|
+
},
|
|
190
|
+
};
|
|
195
191
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
192
|
+
if (StatusCode && ACCEPTED_CODES.includes(StatusCode)) {
|
|
193
|
+
eventObject.handlers.resolve(response);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
200
196
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
197
|
+
if (StatusCode && RETRYABLE_CODES.includes(StatusCode)) {
|
|
198
|
+
retryableEvents.push(eventObject);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
205
201
|
|
|
206
|
-
|
|
202
|
+
const { name } = eventObject.params.event;
|
|
207
203
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
);
|
|
204
|
+
logger.error(
|
|
205
|
+
`event ${eventId} : ${name} failed with error: ${Message}`
|
|
206
|
+
);
|
|
207
|
+
return eventObject.handlers.reject(response);
|
|
208
|
+
});
|
|
214
209
|
});
|
|
215
210
|
|
|
216
211
|
if (retryableEvents.length) {
|