@@ -6,8 +6,6 @@ import 'dart:math';
6
6
7
7
import 'package:aws_common/aws_common.dart' ;
8
8
import 'package:aws_logging_cloudwatch/aws_logging_cloudwatch.dart' ;
9
- import 'package:aws_logging_cloudwatch/src/queued_item_store/in_memory_queued_item_store.dart' ;
10
- import 'package:aws_logging_cloudwatch/src/queued_item_store/queued_item_store.dart' ;
11
9
import 'package:aws_logging_cloudwatch/src/sdk/cloud_watch_logs.dart' ;
12
10
import 'package:aws_logging_cloudwatch/src/stoppable_timer.dart' ;
13
11
import 'package:fixnum/fixnum.dart' ;
@@ -32,7 +30,7 @@ import 'package:meta/meta.dart';
32
30
// The maximum number of log events in a batch is 10,000.
33
31
34
32
const int _maxNumberOfLogEventsInBatch = 10000 ;
35
- const int _maxLogEventsTimeSpanInBatch = 24 * 3600 ;
33
+ const int _maxLogEventsTimeSpanInBatch = 24 * 3600 * 1000 ;
36
34
const int _maxLogEventsBatchSize = 1048576 ;
37
35
const int _baseBufferSize = 26 ;
38
36
const int _maxLogEventSize = 256000 ;
@@ -138,51 +136,26 @@ class CloudWatchLoggerPlugin extends AWSLoggerPlugin
138
136
139
137
Future <void > _startSyncingIfNotInProgress () async {
140
138
Future <void > startSyncing () async {
141
- String logStream;
142
- try {
143
- logStream = await _logStreamProvider.logStream;
144
- } on Exception catch (e) {
145
- if (await _logStore.isFull (_pluginConfig.localStoreMaxSizeInMB)) {
146
- await _logStore.clear ();
147
- logger.warn (
148
- 'Reached local store max size of: '
149
- '${_pluginConfig .localStoreMaxSizeInMB }.Hence logs are deleted from '
150
- 'local store.' ,
151
- );
152
- }
153
- logger.error ('Failed to create CloudWatch log stream' , e);
154
- return ;
155
- }
156
-
157
139
final batcheStream = _getLogBatchesToSync ();
158
140
await for (final (logs, events) in batcheStream) {
159
- try {
160
- final response = await _sendToCloudWatch (events, logStream);
161
- if (response.rejectedLogEventsInfo? .tooNewLogEventStartIndex !=
162
- null ) {
163
- break ;
164
- }
165
- await _logStore.deleteItems (logs);
166
- } on Exception catch (e) {
167
- if (await _logStore.isFull (_pluginConfig.localStoreMaxSizeInMB)) {
168
- await _logStore.deleteItems (logs);
169
- logger.warn (
170
- 'Reached local store max size of: '
171
- '${_pluginConfig .localStoreMaxSizeInMB }.Hence logs are deleted '
172
- 'from local store.' ,
173
- );
174
- }
175
- logger.error ('Failed to sync batched logs to CloudWatch' , e);
141
+ final response = await _sendToCloudWatch (events);
142
+ if (response.rejectedLogEventsInfo? .tooNewLogEventStartIndex != null ) {
143
+ throw _TooNewLogEventException (
144
+ 'logs can not be more than 2 hours in the future' ,
145
+ );
176
146
}
147
+ await _logStore.deleteItems (logs);
177
148
}
178
149
}
179
150
180
151
if (! _syncing) {
152
+ // TODO(nikahsn): disable log rotation.
181
153
_syncing = true ;
182
154
try {
183
155
await startSyncing ();
184
156
} on Exception catch (e) {
185
157
logger.error ('Failed to sync logs to CloudWatch.' , e);
158
+ // TODO(nikahsn): enable log rotation if the log store is full
186
159
} finally {
187
160
_syncing = false ;
188
161
}
@@ -200,43 +173,49 @@ class CloudWatchLoggerPlugin extends AWSLoggerPlugin
200
173
201
174
Future <PutLogEventsResponse > _sendToCloudWatch (
202
175
List <InputLogEvent > logEvents,
203
- String logStreamName,
204
176
) async {
177
+ final logStreamName = await _logStreamProvider.logStream;
205
178
final request = PutLogEventsRequest (
206
179
logGroupName: _pluginConfig.logGroupName,
207
180
logStreamName: logStreamName,
208
181
logEvents: logEvents,
209
182
);
210
- return _client.putLogEvents (request).result;
183
+ try {
184
+ return _client.putLogEvents (request).result;
185
+ } on ResourceNotFoundException {
186
+ await _logStreamProvider.createLogStream (logStreamName);
187
+ return _client.putLogEvents (request).result;
188
+ } on Exception {
189
+ rethrow ;
190
+ }
211
191
}
212
192
213
193
Stream <_LogBatch > _getLogBatchesToSync () async * {
214
194
final queuedLogs = (await _logStore.getAll ()).toList ();
215
- if (queuedLogs.isEmpty) {
216
- yield ([], []);
217
- }
218
- final logEvents = < InputLogEvent > [];
219
- final logQueues = < QueuedItem > [];
220
- var totalByteSize = 0 ;
221
-
222
- for (final currentLog in queuedLogs) {
223
- final currentLogEvent = currentLog.toInputLogEvent ();
224
- final size = currentLogEvent.message.length + _baseBufferSize;
225
- if (totalByteSize + size >= _maxLogEventsBatchSize ||
226
- logEvents.length >= _maxNumberOfLogEventsInBatch ||
227
- (logEvents.length > 1 &&
228
- currentLogEvent.timestamp - logEvents.first.timestamp >=
229
- _maxLogEventsTimeSpanInBatch)) {
230
- yield (logQueues, logEvents);
231
- totalByteSize = 0 ;
232
- logEvents.clear ();
233
- logQueues.clear ();
195
+ if (queuedLogs.isNotEmpty) {
196
+ final logEvents = < InputLogEvent > [];
197
+ final logQueues = < QueuedItem > [];
198
+ var totalByteSize = 0 ;
199
+
200
+ for (final currentLog in queuedLogs) {
201
+ final currentLogEvent = currentLog.toInputLogEvent ();
202
+ final size = currentLogEvent.message.length + _baseBufferSize;
203
+ if (totalByteSize + size >= _maxLogEventsBatchSize ||
204
+ logEvents.length >= _maxNumberOfLogEventsInBatch ||
205
+ (logEvents.length > 1 &&
206
+ currentLogEvent.timestamp - logEvents.first.timestamp >=
207
+ _maxLogEventsTimeSpanInBatch)) {
208
+ yield (logQueues, logEvents);
209
+ totalByteSize = 0 ;
210
+ logEvents.clear ();
211
+ logQueues.clear ();
212
+ }
213
+ totalByteSize += size;
214
+ logEvents.add (currentLogEvent);
215
+ logQueues.add (currentLog);
234
216
}
235
- totalByteSize += size;
236
- logEvents.add (currentLogEvent);
237
- logQueues.add (currentLog);
217
+ yield (logQueues, logEvents);
238
218
}
239
- yield (logQueues, logEvents);
240
219
}
241
220
242
221
/// Whether a [logEntry] should be logged by this plugin.
@@ -314,3 +293,8 @@ extension on LogEntry {
314
293
);
315
294
}
316
295
}
296
+
297
+ class _TooNewLogEventException implements Exception {
298
+ _TooNewLogEventException (this .message);
299
+ final String message;
300
+ }
0 commit comments