@aws-amplify/core 4.4.1 → 4.4.2-api-logging.5

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.
Files changed (113) hide show
  1. package/dist/aws-amplify-core.js +1041 -202
  2. package/dist/aws-amplify-core.js.map +1 -1
  3. package/dist/aws-amplify-core.min.js +7 -7
  4. package/dist/aws-amplify-core.min.js.map +1 -1
  5. package/lib/Logger/ConsoleLogger.d.ts +12 -1
  6. package/lib/Logger/ConsoleLogger.js +69 -6
  7. package/lib/Logger/ConsoleLogger.js.map +1 -1
  8. package/lib/Platform/version.d.ts +1 -1
  9. package/lib/Platform/version.js +1 -1
  10. package/lib/Providers/APIProvider/APILoggingProvider.d.ts +28 -0
  11. package/lib/Providers/APIProvider/APILoggingProvider.js +320 -0
  12. package/lib/Providers/APIProvider/APILoggingProvider.js.map +1 -0
  13. package/lib/Providers/APIProvider/CloudWatchEventFormatter.d.ts +5 -0
  14. package/lib/Providers/APIProvider/CloudWatchEventFormatter.js +78 -0
  15. package/lib/Providers/APIProvider/CloudWatchEventFormatter.js.map +1 -0
  16. package/lib/Providers/APIProvider/Fetch.d.ts +10 -0
  17. package/lib/Providers/APIProvider/Fetch.js +13 -0
  18. package/lib/Providers/APIProvider/Fetch.js.map +1 -0
  19. package/lib/Providers/APIProvider/LoggerReachability/index.d.ts +3 -0
  20. package/lib/Providers/APIProvider/LoggerReachability/index.js +5 -0
  21. package/lib/Providers/APIProvider/LoggerReachability/index.js.map +1 -0
  22. package/lib/Providers/APIProvider/LoggerReachability/index.native.d.ts +3 -0
  23. package/lib/Providers/APIProvider/LoggerReachability/index.native.js +9 -0
  24. package/lib/Providers/APIProvider/LoggerReachability/index.native.js.map +1 -0
  25. package/lib/Providers/APIProvider/index.d.ts +1 -0
  26. package/lib/Providers/APIProvider/index.js +5 -0
  27. package/lib/Providers/APIProvider/index.js.map +1 -0
  28. package/lib/Providers/APIProvider/loggerConnectivity.d.ts +14 -0
  29. package/lib/Providers/APIProvider/loggerConnectivity.js +55 -0
  30. package/lib/Providers/APIProvider/loggerConnectivity.js.map +1 -0
  31. package/lib/Providers/AWSCloudWatchProvider.js +8 -1
  32. package/lib/Providers/AWSCloudWatchProvider.js.map +1 -1
  33. package/lib/Providers/index.d.ts +1 -0
  34. package/lib/Providers/index.js +2 -0
  35. package/lib/Providers/index.js.map +1 -1
  36. package/lib/Util/Constants.d.ts +3 -1
  37. package/lib/Util/Constants.js +4 -0
  38. package/lib/Util/Constants.js.map +1 -1
  39. package/lib/Util/Reachability.js +7 -5
  40. package/lib/Util/Reachability.js.map +1 -1
  41. package/lib/Util/Retry.js +2 -2
  42. package/lib/Util/Retry.js.map +1 -1
  43. package/lib/Util/StringUtils.d.ts +1 -0
  44. package/lib/Util/StringUtils.js +11 -6
  45. package/lib/Util/StringUtils.js.map +1 -1
  46. package/lib/types/index.js +4 -0
  47. package/lib/types/index.js.map +1 -1
  48. package/lib/types/types.d.ts +38 -1
  49. package/lib/types/types.js +4 -0
  50. package/lib/types/types.js.map +1 -1
  51. package/lib-esm/Logger/ConsoleLogger.d.ts +12 -1
  52. package/lib-esm/Logger/ConsoleLogger.js +67 -4
  53. package/lib-esm/Logger/ConsoleLogger.js.map +1 -1
  54. package/lib-esm/Platform/version.d.ts +1 -1
  55. package/lib-esm/Platform/version.js +1 -1
  56. package/lib-esm/Providers/APIProvider/APILoggingProvider.d.ts +28 -0
  57. package/lib-esm/Providers/APIProvider/APILoggingProvider.js +315 -0
  58. package/lib-esm/Providers/APIProvider/APILoggingProvider.js.map +1 -0
  59. package/lib-esm/Providers/APIProvider/CloudWatchEventFormatter.d.ts +5 -0
  60. package/lib-esm/Providers/APIProvider/CloudWatchEventFormatter.js +76 -0
  61. package/lib-esm/Providers/APIProvider/CloudWatchEventFormatter.js.map +1 -0
  62. package/lib-esm/Providers/APIProvider/Fetch.d.ts +10 -0
  63. package/lib-esm/Providers/APIProvider/Fetch.js +11 -0
  64. package/lib-esm/Providers/APIProvider/Fetch.js.map +1 -0
  65. package/lib-esm/Providers/APIProvider/LoggerReachability/index.d.ts +3 -0
  66. package/lib-esm/Providers/APIProvider/LoggerReachability/index.js +3 -0
  67. package/lib-esm/Providers/APIProvider/LoggerReachability/index.js.map +1 -0
  68. package/lib-esm/Providers/APIProvider/LoggerReachability/index.native.d.ts +3 -0
  69. package/lib-esm/Providers/APIProvider/LoggerReachability/index.native.js +4 -0
  70. package/lib-esm/Providers/APIProvider/LoggerReachability/index.native.js.map +1 -0
  71. package/lib-esm/Providers/APIProvider/index.d.ts +1 -0
  72. package/lib-esm/Providers/APIProvider/index.js +2 -0
  73. package/lib-esm/Providers/APIProvider/index.js.map +1 -0
  74. package/lib-esm/Providers/APIProvider/loggerConnectivity.d.ts +14 -0
  75. package/lib-esm/Providers/APIProvider/loggerConnectivity.js +50 -0
  76. package/lib-esm/Providers/APIProvider/loggerConnectivity.js.map +1 -0
  77. package/lib-esm/Providers/AWSCloudWatchProvider.js +8 -1
  78. package/lib-esm/Providers/AWSCloudWatchProvider.js.map +1 -1
  79. package/lib-esm/Providers/index.d.ts +1 -0
  80. package/lib-esm/Providers/index.js +1 -0
  81. package/lib-esm/Providers/index.js.map +1 -1
  82. package/lib-esm/Util/Constants.d.ts +3 -1
  83. package/lib-esm/Util/Constants.js +3 -1
  84. package/lib-esm/Util/Constants.js.map +1 -1
  85. package/lib-esm/Util/Reachability.js +5 -3
  86. package/lib-esm/Util/Reachability.js.map +1 -1
  87. package/lib-esm/Util/Retry.js +2 -2
  88. package/lib-esm/Util/Retry.js.map +1 -1
  89. package/lib-esm/Util/StringUtils.d.ts +1 -0
  90. package/lib-esm/Util/StringUtils.js +11 -6
  91. package/lib-esm/Util/StringUtils.js.map +1 -1
  92. package/lib-esm/types/index.js +1 -0
  93. package/lib-esm/types/index.js.map +1 -1
  94. package/lib-esm/types/types.d.ts +38 -1
  95. package/lib-esm/types/types.js +3 -0
  96. package/lib-esm/types/types.js.map +1 -1
  97. package/package.json +2 -2
  98. package/src/Logger/ConsoleLogger.ts +54 -2
  99. package/src/Platform/version.ts +1 -1
  100. package/src/Providers/APIProvider/APILoggingProvider.ts +286 -0
  101. package/src/Providers/APIProvider/CloudWatchEventFormatter.ts +100 -0
  102. package/src/Providers/APIProvider/Fetch.ts +10 -0
  103. package/src/Providers/APIProvider/LoggerReachability/index.native.ts +4 -0
  104. package/src/Providers/APIProvider/LoggerReachability/index.ts +2 -0
  105. package/src/Providers/APIProvider/index.ts +1 -0
  106. package/src/Providers/APIProvider/loggerConnectivity.ts +49 -0
  107. package/src/Providers/AWSCloudWatchProvider.ts +9 -1
  108. package/src/Providers/index.ts +1 -0
  109. package/src/Util/Constants.ts +4 -0
  110. package/src/Util/Reachability.ts +9 -7
  111. package/src/Util/Retry.ts +2 -2
  112. package/src/Util/StringUtils.ts +15 -6
  113. package/src/types/types.ts +106 -62
@@ -0,0 +1,286 @@
1
+ import { ConsoleLogger as Logger, LOG_LEVELS, LOG_TYPE } from '../../Logger';
2
+ import LoggerConnectivity from './loggerConnectivity';
3
+ import {
4
+ LoggingProvider,
5
+ GenericLogEvent,
6
+ APILoggingProviderOptions,
7
+ isLoggerEvent,
8
+ } from '../../types/types';
9
+ import { jitteredExponentialRetry, NonRetryableError } from '../../../';
10
+ import { postOptions } from './Fetch';
11
+ import {
12
+ API_LOGGING_PROVIDER_NAME,
13
+ API_LOGGING_PROVIDER_CATEGORY,
14
+ } from '../../Util/Constants';
15
+ import { getStringByteSize } from '../../Util/StringUtils';
16
+ import { InputLogEvent } from '@aws-sdk/client-cloudwatch-logs';
17
+
18
+ const logger = new Logger('APILoggingProvider');
19
+ const HTTPS = 'https';
20
+ const LOCALHOST = 'http://localhost';
21
+ const DEFAULT_INTERVAL = 3000;
22
+
23
+ // Exclude these to avoid infinite loop
24
+ const DEFAULT_CLASS_EXCLUDE_LIST = [
25
+ 'APILoggingProvider',
26
+ 'AWSCloudWatch',
27
+ 'Retry', // causes a loop because we're using jitteredExponentialRetry below
28
+ ];
29
+ const LAMBDA_PAYLOAD_LIMIT = 6 * 1024 * 1024; // 6MB
30
+
31
+ /*
32
+ Todo:
33
+ * Refactor this into a FSM - managing state will become complex when remote config functionality gets added in P1
34
+ */
35
+ class APILoggingProvider implements LoggingProvider {
36
+ static readonly PROVIDER_NAME = API_LOGGING_PROVIDER_NAME;
37
+ static readonly CATEGORY = API_LOGGING_PROVIDER_CATEGORY;
38
+
39
+ private config: APILoggingProviderOptions;
40
+ private connectivity: LoggerConnectivity;
41
+ private online: boolean = false;
42
+ private bufferInterval: ReturnType<typeof setInterval>;
43
+ private eventBuffer: GenericLogEvent[] = [];
44
+
45
+ constructor(config?: APILoggingProviderOptions) {
46
+ this.configure(config);
47
+ }
48
+
49
+ public getProviderName(): string {
50
+ return APILoggingProvider.PROVIDER_NAME;
51
+ }
52
+
53
+ public getCategoryName(): string {
54
+ return APILoggingProvider.CATEGORY;
55
+ }
56
+
57
+ public configure(
58
+ config: APILoggingProviderOptions
59
+ ): object | APILoggingProviderOptions {
60
+ try {
61
+ this.validateConfig(config);
62
+ this.config = this.normalizeConfig(config);
63
+
64
+ if (this.config.enabled === true) {
65
+ this.initialize();
66
+ } else {
67
+ this.disable();
68
+ }
69
+
70
+ return this.config;
71
+ } catch (error) {
72
+ logger.error('Unable to start: ', error);
73
+ }
74
+ }
75
+
76
+ public pushLogs(events: InputLogEvent[]): void {
77
+ if (this.config?.enabled === false) {
78
+ return;
79
+ }
80
+
81
+ events.forEach(event => {
82
+ if (!isLoggerEvent(event)) {
83
+ return;
84
+ }
85
+
86
+ const {
87
+ message,
88
+ timestamp,
89
+ loggerInfo: {
90
+ level,
91
+ data,
92
+ name,
93
+ error: { message: errorMessage, name: errorName } = {},
94
+ },
95
+ } = event;
96
+
97
+ const error = errorName &&
98
+ errorMessage && {
99
+ errorMessage,
100
+ errorName,
101
+ };
102
+
103
+ const combinedEvent: GenericLogEvent = {
104
+ level,
105
+ error,
106
+ message,
107
+ context: {
108
+ category: name,
109
+ data: { ...data, ...this.config.metadata },
110
+ logTime: timestamp,
111
+ },
112
+ };
113
+
114
+ if (this.verifyEvent(combinedEvent)) {
115
+ this.eventBuffer.push(combinedEvent);
116
+ }
117
+ });
118
+ }
119
+
120
+ private validateConfig(config: APILoggingProviderOptions): void {
121
+ if (typeof config?.endpoint !== 'string') {
122
+ throw new Error(
123
+ `Invalid configuration. \`config.endpoint\` must be a string. Received: ${typeof config?.endpoint}`
124
+ );
125
+ }
126
+
127
+ const protocolStr = config.endpoint.substring(0, 5).toLowerCase();
128
+ const isUsingLocalhost =
129
+ config.endpoint.substring(0, LOCALHOST.length).toLowerCase() ===
130
+ LOCALHOST;
131
+
132
+ if (protocolStr !== HTTPS && !isUsingLocalhost) {
133
+ throw new Error(
134
+ `Invalid configuration. Only HTTPS endpoints are supported. Received: ${protocolStr}`
135
+ );
136
+ }
137
+ }
138
+
139
+ private normalizeConfig(
140
+ config: APILoggingProviderOptions
141
+ ): APILoggingProviderOptions {
142
+ const normalizedConfig = {
143
+ endpoint: config.endpoint,
144
+ apiKey: config.apiKey,
145
+ metadata: config.metadata,
146
+ enabled: config.enabled ?? true,
147
+ level: config.level ?? LOG_TYPE.WARN,
148
+ bufferInterval: config.bufferInterval ?? DEFAULT_INTERVAL,
149
+ excludeClassList:
150
+ config.excludeClassList instanceof Array
151
+ ? [...DEFAULT_CLASS_EXCLUDE_LIST, ...config.excludeClassList]
152
+ : DEFAULT_CLASS_EXCLUDE_LIST,
153
+ };
154
+
155
+ return normalizedConfig;
156
+ }
157
+
158
+ private initialize() {
159
+ this.subscribeConnectivity();
160
+ }
161
+
162
+ private disable() {
163
+ this.clearInterval();
164
+ this.unsubscribeConnectivity();
165
+ this.eventBuffer = [];
166
+ }
167
+
168
+ private subscribeConnectivity() {
169
+ if (this.connectivity) {
170
+ return;
171
+ }
172
+
173
+ this.connectivity = new LoggerConnectivity();
174
+ this.connectivity.status().subscribe(({ online }) => {
175
+ if (online && !this.online) {
176
+ this.startInterval();
177
+ } else {
178
+ this.clearInterval();
179
+ }
180
+
181
+ this.online = online;
182
+ logger.debug('Connectivity status: ', online);
183
+ });
184
+ }
185
+
186
+ private unsubscribeConnectivity() {
187
+ if (this.connectivity) {
188
+ this.connectivity.unsubscribe();
189
+ this.connectivity = undefined;
190
+ }
191
+ }
192
+
193
+ private startInterval() {
194
+ if (this.bufferInterval) {
195
+ this.clearInterval();
196
+ }
197
+
198
+ this.bufferInterval = setInterval(async () => {
199
+ try {
200
+ await this.uploadEvents();
201
+ } catch (error) {
202
+ logger.error(`Could not upload log events`, error);
203
+ }
204
+ }, this.config.bufferInterval);
205
+ }
206
+
207
+ private clearInterval() {
208
+ clearInterval(this.bufferInterval);
209
+ this.bufferInterval = undefined;
210
+ }
211
+
212
+ /*
213
+ Filter out events that don't adhere to config settings
214
+ */
215
+ private verifyEvent(event: GenericLogEvent): boolean {
216
+ const { level, context } = event;
217
+
218
+ const configLevelValue = LOG_LEVELS[this.config.level];
219
+ const eventLevelValue = LOG_LEVELS[level];
220
+
221
+ if (eventLevelValue < configLevelValue) {
222
+ return false;
223
+ }
224
+
225
+ if (this.config.excludeClassList.includes(context.category)) {
226
+ return false;
227
+ }
228
+
229
+ return true;
230
+ }
231
+
232
+ private async uploadEvents(): Promise<void> {
233
+ const eventBatch = this.genericLogEventBatch(this.eventBuffer);
234
+
235
+ if (eventBatch.length < 1) {
236
+ return;
237
+ }
238
+
239
+ const body = {
240
+ logs: eventBatch,
241
+ };
242
+
243
+ const options = postOptions(body);
244
+
245
+ await jitteredExponentialRetry(
246
+ async (endpoint, options) => {
247
+ try {
248
+ await fetch(endpoint, options); // fetch doesnt return info for no-cors request
249
+ } catch (error) {
250
+ // fetch will only fail in the event of a network error. Don't retry
251
+ if (error.message === 'Failed to fetch') {
252
+ throw new NonRetryableError(error.message);
253
+ }
254
+ // all other errors are logged and retried
255
+ logger.warn(error);
256
+ throw error;
257
+ }
258
+ },
259
+ [this.config.endpoint, options]
260
+ );
261
+
262
+ // remove events from buffer after the request succeeds
263
+ this.eventBuffer.splice(0, eventBatch.length);
264
+ }
265
+
266
+ private genericLogEventBatch(buffer: GenericLogEvent[]): GenericLogEvent[] {
267
+ let totalByteSize = 0;
268
+ let currentEventIdx = 0;
269
+
270
+ while (currentEventIdx < buffer.length) {
271
+ const currentEvent = buffer[currentEventIdx];
272
+ const eventSize = getStringByteSize(JSON.stringify(currentEvent));
273
+
274
+ if (totalByteSize + eventSize > LAMBDA_PAYLOAD_LIMIT) {
275
+ break;
276
+ }
277
+
278
+ totalByteSize += eventSize;
279
+ currentEventIdx += 1;
280
+ }
281
+
282
+ return buffer.slice(0, currentEventIdx);
283
+ }
284
+ }
285
+
286
+ export { APILoggingProvider };
@@ -0,0 +1,100 @@
1
+ import { InputLogEvent } from '@aws-sdk/client-cloudwatch-logs';
2
+ import {
3
+ AWS_CLOUDWATCH_BASE_BUFFER_SIZE,
4
+ AWS_CLOUDWATCH_MAX_BATCH_EVENT_SIZE,
5
+ AWS_CLOUDWATCH_MAX_EVENT_SIZE,
6
+ } from '../../Util/Constants';
7
+ import { GenericLogEvent } from '../../types/types';
8
+ import { ConsoleLogger as Logger, getStringByteSize } from '../../';
9
+
10
+ const logger = new Logger('APILoggingProvider');
11
+ const TRUNCATE_MAX_LENGTH = 5000;
12
+
13
+ export const cloudWatchEventFromGeneric = (
14
+ event: GenericLogEvent
15
+ ): InputLogEvent => {
16
+ const {
17
+ context: { logTime: timestamp },
18
+ ...message
19
+ } = event;
20
+
21
+ return {
22
+ timestamp,
23
+ message: JSON.stringify(event),
24
+ };
25
+ };
26
+
27
+ export const truncateOversizedEvent = (event: InputLogEvent): InputLogEvent => {
28
+ const { timestamp, message } = event;
29
+
30
+ try {
31
+ const messageJson = JSON.parse(message);
32
+
33
+ const truncatedObj = {
34
+ level: messageJson.level,
35
+ class: messageJson.class,
36
+ message: messageJson.message.substring(0, TRUNCATE_MAX_LENGTH),
37
+ };
38
+
39
+ if (messageJson.data != null) {
40
+ truncatedObj[
41
+ 'data'
42
+ ] = `OBJECT SIZE EXCEEDS CLOUDWATCH EVENT LIMIT. Truncated: ${JSON.stringify(
43
+ messageJson.data
44
+ ).substring(0, TRUNCATE_MAX_LENGTH)}`;
45
+ }
46
+
47
+ return {
48
+ timestamp,
49
+ message: JSON.stringify(truncatedObj),
50
+ };
51
+ } catch (error) {
52
+ logger.warn('Could not truncate oversized event', error);
53
+
54
+ const truncated = JSON.stringify({
55
+ level: 'UNKNOWN',
56
+ class: 'Unknown',
57
+ message:
58
+ 'OBJECT SIZE EXCEEDS CLOUDWATCH EVENT LIMIT. Could not parse event to truncate',
59
+ });
60
+
61
+ return {
62
+ timestamp,
63
+ message: truncated,
64
+ };
65
+ }
66
+ };
67
+
68
+ export const cloudWatchLogEventBatch = (
69
+ buffer: InputLogEvent[]
70
+ ): InputLogEvent[] => {
71
+ let totalByteSize = 0;
72
+ let currentEventIdx = 0;
73
+
74
+ while (currentEventIdx < buffer.length) {
75
+ let currentEvent = buffer[currentEventIdx];
76
+ let eventSize =
77
+ getStringByteSize(currentEvent.message) + AWS_CLOUDWATCH_BASE_BUFFER_SIZE;
78
+
79
+ if (eventSize > AWS_CLOUDWATCH_MAX_EVENT_SIZE) {
80
+ const errString = `Log event exceeds maximum size for CloudWatch logs. Log size: ${eventSize}. Truncating log message.`;
81
+ logger.debug(errString);
82
+
83
+ currentEvent = truncateOversizedEvent(currentEvent);
84
+ buffer[currentEventIdx] = currentEvent;
85
+
86
+ eventSize =
87
+ new TextEncoder().encode(currentEvent.message).length +
88
+ AWS_CLOUDWATCH_BASE_BUFFER_SIZE;
89
+ }
90
+
91
+ if (totalByteSize + eventSize > AWS_CLOUDWATCH_MAX_BATCH_EVENT_SIZE) {
92
+ break;
93
+ }
94
+
95
+ totalByteSize += eventSize;
96
+ currentEventIdx += 1;
97
+ }
98
+
99
+ return buffer.slice(0, currentEventIdx);
100
+ };
@@ -0,0 +1,10 @@
1
+ export const postOptions = (body: object) => ({
2
+ method: 'POST',
3
+ mode: 'no-cors',
4
+ cache: 'no-cache',
5
+ credentials: 'same-origin',
6
+ headers: {
7
+ 'Content-Type': 'application/json',
8
+ },
9
+ body: JSON.stringify(body),
10
+ });
@@ -0,0 +1,4 @@
1
+ import { Reachability } from '../../..';
2
+ import { default as NetInfo } from '@react-native-community/netinfo';
3
+
4
+ export const ReachabilityMonitor = new Reachability().networkMonitor(NetInfo);
@@ -0,0 +1,2 @@
1
+ import { Reachability } from '../../../Util';
2
+ export const ReachabilityMonitor = new Reachability().networkMonitor();
@@ -0,0 +1 @@
1
+ export { APILoggingProvider } from './APILoggingProvider';
@@ -0,0 +1,49 @@
1
+ import Observable, { ZenObservable } from 'zen-observable-ts';
2
+ import { ReachabilityMonitor } from './LoggerReachability';
3
+
4
+ type ConnectionStatus = {
5
+ online: boolean;
6
+ };
7
+
8
+ // TODO: refactor this to a singleton that supports numerous observers
9
+ export default class LoggerConnectivity {
10
+ private connectionStatus: ConnectionStatus;
11
+ private observer: ZenObservable.SubscriptionObserver<ConnectionStatus>;
12
+ private subscription: ZenObservable.Subscription;
13
+ private timeout: ReturnType<typeof setTimeout>;
14
+ constructor() {
15
+ this.connectionStatus = {
16
+ online: false,
17
+ };
18
+ }
19
+
20
+ status(): Observable<ConnectionStatus> {
21
+ if (this.observer) {
22
+ throw new Error('Subscriber already exists');
23
+ }
24
+ return new Observable(observer => {
25
+ this.observer = observer;
26
+
27
+ this.subscription = ReachabilityMonitor.subscribe(({ online }) => {
28
+ this.connectionStatus.online = online;
29
+
30
+ const observerResult = { ...this.connectionStatus };
31
+
32
+ observer.next(observerResult);
33
+ });
34
+
35
+ return () => {
36
+ clearTimeout(this.timeout);
37
+ this.unsubscribe();
38
+ };
39
+ });
40
+ }
41
+
42
+ unsubscribe() {
43
+ if (this.subscription) {
44
+ clearTimeout(this.timeout);
45
+ this.subscription.unsubscribe();
46
+ this.observer = undefined;
47
+ }
48
+ }
49
+ }
@@ -218,7 +218,15 @@ class AWSCloudWatchProvider implements LoggingProvider {
218
218
 
219
219
  public pushLogs(logs: InputLogEvent[]): void {
220
220
  logger.debug('pushing log events to Cloudwatch...');
221
- this._dataTracker.logEvents = [...this._dataTracker.logEvents, ...logs];
221
+ const formattedLogs = logs.map(({ message, timestamp }) => ({
222
+ message,
223
+ timestamp,
224
+ }));
225
+
226
+ this._dataTracker.logEvents = [
227
+ ...this._dataTracker.logEvents,
228
+ ...formattedLogs,
229
+ ];
222
230
  }
223
231
 
224
232
  private async _validateLogGroupExistsAndCreate(
@@ -1 +1,2 @@
1
1
  export * from './AWSCloudWatchProvider';
2
+ export { APILoggingProvider } from './APIProvider';
@@ -22,6 +22,8 @@ const RETRY_ERROR_CODES = [
22
22
  'ResourceNotFoundException',
23
23
  'InvalidSequenceTokenException',
24
24
  ];
25
+ const API_LOGGING_PROVIDER_NAME = 'API';
26
+ const API_LOGGING_PROVIDER_CATEGORY = 'Logging';
25
27
 
26
28
  export {
27
29
  AWS_CLOUDWATCH_BASE_BUFFER_SIZE,
@@ -31,4 +33,6 @@ export {
31
33
  AWS_CLOUDWATCH_PROVIDER_NAME,
32
34
  NO_CREDS_ERROR_STRING,
33
35
  RETRY_ERROR_CODES,
36
+ API_LOGGING_PROVIDER_NAME,
37
+ API_LOGGING_PROVIDER_CATEGORY,
34
38
  };
@@ -1,4 +1,4 @@
1
- import { browserOrNode, isWebWorker } from '@aws-amplify/core';
1
+ import { browserOrNode, isWebWorker } from '../JS';
2
2
  import Observable, { ZenObservable } from 'zen-observable-ts';
3
3
 
4
4
  type NetworkStatus = {
@@ -32,9 +32,10 @@ export default class ReachabilityNavigator implements Reachability {
32
32
  globalObj.removeEventListener('online', notifyOnline);
33
33
  globalObj.removeEventListener('offline', notifyOffline);
34
34
 
35
- ReachabilityNavigator._observers = ReachabilityNavigator._observers.filter(
36
- _observer => _observer !== observer
37
- );
35
+ ReachabilityNavigator._observers =
36
+ ReachabilityNavigator._observers.filter(
37
+ _observer => _observer !== observer
38
+ );
38
39
  };
39
40
  });
40
41
  }
@@ -43,9 +44,10 @@ export default class ReachabilityNavigator implements Reachability {
43
44
  private static _observerOverride(status: NetworkStatus): void {
44
45
  for (const observer of ReachabilityNavigator._observers) {
45
46
  if (observer.closed) {
46
- ReachabilityNavigator._observers = ReachabilityNavigator._observers.filter(
47
- _observer => _observer !== observer
48
- );
47
+ ReachabilityNavigator._observers =
48
+ ReachabilityNavigator._observers.filter(
49
+ _observer => _observer !== observer
50
+ );
49
51
  continue;
50
52
  }
51
53
  observer.next(status);
package/src/Util/Retry.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DelayFunction } from '../types';
2
2
  import { ConsoleLogger as Logger } from '../Logger/ConsoleLogger';
3
- const logger = new Logger('Util');
3
+ const logger = new Logger('Retry');
4
4
 
5
5
  export class NonRetryableError extends Error {
6
6
  public readonly nonRetryable = true;
@@ -30,7 +30,7 @@ export async function retry(
30
30
  logger.debug(
31
31
  `${
32
32
  functionToRetry.name
33
- } attempt #${attempt} with this vars: ${JSON.stringify(args)}`
33
+ } attempt #${attempt} with these vars: ${JSON.stringify(args)}`
34
34
  );
35
35
 
36
36
  try {
@@ -1,12 +1,8 @@
1
+ import { browserOrNode } from '../../';
1
2
  export function urlSafeEncode(str: string) {
2
3
  return str
3
4
  .split('')
4
- .map(char =>
5
- char
6
- .charCodeAt(0)
7
- .toString(16)
8
- .padStart(2, '0')
9
- )
5
+ .map(char => char.charCodeAt(0).toString(16).padStart(2, '0'))
10
6
  .join('');
11
7
  }
12
8
 
@@ -16,3 +12,16 @@ export function urlSafeDecode(hex: string) {
16
12
  .map(char => String.fromCharCode(parseInt(char, 16)))
17
13
  .join('');
18
14
  }
15
+ export const getStringByteSize = (str: string): number => {
16
+ if (browserOrNode().isBrowser || Blob !== undefined) {
17
+ return new Blob([str]).size;
18
+ }
19
+
20
+ if (Buffer !== undefined) {
21
+ return Buffer.byteLength(str, 'utf8');
22
+ }
23
+
24
+ throw new Error(
25
+ 'Cannot compute string length. Blob and Buffer are undefined'
26
+ );
27
+ };