Skip to content

Commit

Permalink
Merge branch 'feat/logging/default-remote-config' of https://github.c…
Browse files Browse the repository at this point in the history
…om/aws-amplify/amplify-flutter into feat/logging/default-remote-config
  • Loading branch information
khatruong2009 committed Sep 13, 2023
2 parents 5514bd8 + 5085ed1 commit 447deec
Show file tree
Hide file tree
Showing 19 changed files with 736 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:amplify_logging_cloudwatch/src/amplify_log_stream_name_provider.dart';
import 'package:aws_logging_cloudwatch/aws_logging_cloudwatch.dart';

/// {@macro aws_logging_cloudwatch.cloudwatch_logger_plugin}
class AmplifyCloudWatchLoggerPlugin extends CloudWatchLoggerPlugin {
/// {@macro aws_logging_cloudwatch.cloudwatch_logger_plugin}
AmplifyCloudWatchLoggerPlugin({
required super.credentialsProvider,
required super.pluginConfig,
}) : super(
logStreamProvider: DefaultCloudWatchLogStreamProvider(
credentialsProvider: credentialsProvider,
region: pluginConfig.region,
logGroupName: pluginConfig.logGroupName,
defaultLogStreamNameProvider:
AmplifyLogStreamNameProvider().defaultLogStreamName,
),
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_logging_cloudwatch/src/device_info/device_info.dart';
import 'package:intl/intl.dart';

const _guestUserId = 'guest';

/// {@template amplify_logging_cloudwatch.amplify_log_stream_name_provider}
/// It uses {mm-dd-yyyy}.{deviceId}.{userId|guest} format for log stream name.
///
/// It gets deviceId from platform inforamtion or uuid if it is `null`.
/// It gets userId from `Amplify.Auth.getCurrentUser()).userId` or uses `guest`
/// if userId is not available.
/// {@endtemplate}
class AmplifyLogStreamNameProvider {
/// {@macro amplify_logging_cloudwatch.amplify_log_stream_name_provider}
AmplifyLogStreamNameProvider();
static final DateFormat _dateFormat = DateFormat('yyyy-MM-dd');
String? _deviceID;

/// Returns log stream name in `{mm-dd-yyyy}.{deviceId}.{userId|guest}` format
Future<String> defaultLogStreamName() async {
_deviceID ??= await getDeviceId() ?? UUID.getUUID();
String userId;
userId = await _getUserId();
return '${_dateFormat.format(DateTime.timestamp())}.$_deviceID.$userId';
}

Future<String> _getUserId() async {
String userId;
try {
userId = (await Amplify.Auth.getCurrentUser()).userId;
} on Error {
userId = _guestUserId;
} on Exception {
userId = _guestUserId;
}
return userId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'device_info.stub.dart'
if (dart.library.io) 'device_info.vm.dart'
if (dart.library.html) 'device_info.web.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// {@template amplify_logging_cloudwatch.device_info}
/// Returns device Id from platform information on `vm`.
/// Returns a UUID across browser sessions for web.
/// {@endtemplate}
Future<String?> getDeviceId() {
throw UnimplementedError('getDeviceId() has not been implemented.');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';

/// {@macro amplify_logging_cloudwatch.device_info}
Future<String?> getDeviceId() async {
final deviceInfo = DeviceInfoPlugin();
String? deviceID;
try {
if (Platform.isAndroid) {
final androidInfo = await deviceInfo.androidInfo;
deviceID = androidInfo.id;
} else if (Platform.isIOS) {
final iosInfo = await deviceInfo.iosInfo;
deviceID = iosInfo.identifierForVendor ?? '';
} else if (Platform.isLinux) {
final linuxInfo = await deviceInfo.linuxInfo;
deviceID = linuxInfo.machineId ?? '';
} else if (Platform.isMacOS) {
final macInfo = await deviceInfo.macOsInfo;
deviceID = macInfo.systemGUID ?? '';
} else if (Platform.isWindows) {
final windowsInfo = await deviceInfo.windowsInfo;
deviceID = windowsInfo.deviceId;
}
} on Exception {
return null;
}
return deviceID;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'dart:html';

import 'package:amplify_core/amplify_core.dart';

const _localStorageKey = 'amplify-cloudwatch-logger-device-id';

/// {@macro amplify_logging_cloudwatch.device_info}
Future<String?> getDeviceId() async {
var deviceID = window.localStorage[_localStorageKey];
if (deviceID != null) {
return deviceID;
}
deviceID = UUID.getUUID();
window.localStorage.putIfAbsent(_localStorageKey, () => deviceID!);
return deviceID;
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class DartQueuedItemStore implements QueuedItemStore, Closeable {
}

@override
FutureOr<bool> isFull(int maxSizeInMB) {
bool isFull(int maxSizeInMB) {
throw UnimplementedError('isFull() has not been implemented.');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DartQueuedItemStore implements QueuedItemStore, Closeable {
}

@override
Future<bool> isFull(int maxSizeInMB) {
bool isFull(int maxSizeInMB) {
return _database.isFull(maxSizeInMB);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class DartQueuedItemStore
// ignore: avoid_unused_constructor_parameters
DartQueuedItemStore(String? storagePath);

late final Future<QueuedItemStore> _database = () async {
if (await IndexedDbAdapter.checkIsIndexedDBSupported()) {
late final QueuedItemStore _database = () {
if (IndexedDbAdapter.checkIsIndexedDBSupported()) {
return IndexedDbAdapter();
}
logger.warn(
Expand All @@ -34,8 +34,7 @@ class DartQueuedItemStore
String timestamp, {
bool enableQueueRotation = false,
}) async {
final db = await _database;
await db.addItem(
await _database.addItem(
string,
timestamp,
enableQueueRotation: enableQueueRotation,
Expand All @@ -44,34 +43,29 @@ class DartQueuedItemStore

@override
Future<void> deleteItems(Iterable<QueuedItem> items) async {
final db = await _database;
await db.deleteItems(items);
await _database.deleteItems(items);
}

@override
Future<Iterable<QueuedItem>> getCount(int count) async {
final db = await _database;
return db.getCount(count);
return _database.getCount(count);
}

@override
Future<Iterable<QueuedItem>> getAll() async {
final db = await _database;
return db.getAll();
return _database.getAll();
}

@override
Future<bool> isFull(int maxSizeInMB) async {
final db = await _database;
return db.isFull(maxSizeInMB);
bool isFull(int maxSizeInMB) {
return _database.isFull(maxSizeInMB);
}

/// Clear IndexedDB data.
@override
@visibleForTesting
Future<void> clear() async {
final db = await _database;
return db.clear();
return _database.clear();
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class DriftQueuedItemStore extends _$DriftQueuedItemStore
}

@override
Future<bool> isFull(int maxSizeInMB) async {
bool isFull(int maxSizeInMB) {
final maxBytes = maxSizeInMB * 1024 * 1024;
return _currentTotalByteSize >= maxBytes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class IndexedDbAdapter implements QueuedItemStore {
}

@override
Future<bool> isFull(int maxSizeInMB) async {
bool isFull(int maxSizeInMB) {
final maxBytes = maxSizeInMB * 1024 * 1024;
return _currentTotalByteSize >= maxBytes;
}
Expand All @@ -167,15 +167,14 @@ class IndexedDbAdapter implements QueuedItemStore {
void close() {}

/// Check that IndexDB will work on this device.
static Future<bool> checkIsIndexedDBSupported() async {
static bool checkIsIndexedDBSupported() {
if (indexedDB == null) {
return false;
}
// indexedDB will be non-null in Firefox private browsing,
// but will fail to open.
try {
final openRequest = indexedDB!.open('test', 1);
await openRequest.future;
indexedDB!.open('test', 1).result;
return true;
} on Object {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ dependencies:
aws_common: ">=0.6.0 <0.7.0"
aws_logging_cloudwatch: ^0.1.0
collection: ^1.15.0
device_info_plus: ^9.0.0
drift: ">=2.11.0 <2.12.0"
flutter:
sdk: flutter
intl: ">=0.18.0 <1.0.0"
meta: ^1.7.0
path_provider: ^2.0.0

Expand All @@ -27,4 +29,6 @@ dev_dependencies:
build_test: ^2.0.0
build_web_compilers: ^4.0.0
drift_dev: ^2.2.0+1
flutter_test:
sdk: flutter
test: ^1.22.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@TestOn('vm')

import 'package:amplify_logging_cloudwatch/src/amplify_log_stream_name_provider.dart';
import 'package:flutter_test/flutter_test.dart' as flutter;
import 'package:test/test.dart';

void main() {
flutter.TestWidgetsFlutterBinding.ensureInitialized();
test('it uses uuid and guest when their values are not provided', () async {
final logStreamNameProvider = AmplifyLogStreamNameProvider();
await expectLater(logStreamNameProvider.defaultLogStreamName(), completes);
});

test('it caches the device Id', () async {
final logStreamNameProvider = AmplifyLogStreamNameProvider();
final logStreamName1 = await logStreamNameProvider.defaultLogStreamName();
final logStreamName2 = await logStreamNameProvider.defaultLogStreamName();

expect(logStreamName1, logStreamName2);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,14 @@ void main() {
await db.addItem(largeItem, DateTime.now().toIso8601String());
}

var result = await db.isFull(capacityLimit);
var result = db.isFull(capacityLimit);
expect(result, isFalse);

for (var i = 0; i < 100; i++) {
await db.addItem(largeItem, DateTime.now().toIso8601String());
}

result = await db.isFull(capacityLimit);
result = db.isFull(capacityLimit);
expect(result, isTrue);
},
);
Expand Down
Loading

0 comments on commit 447deec

Please sign in to comment.