Skip to content

Commit

Permalink
chore: dart FileStorage refactor and unit tests added
Browse files Browse the repository at this point in the history
  • Loading branch information
khatruong2009 committed Sep 13, 2023
1 parent 53ef002 commit 0506c77
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Files and directories created by pub.
.dart_tool/
.packages
.flutter-plugins
.flutter-plugins-dependencies

# Conventional directory for build outputs.
build/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

export 'file_storage.vm.dart' if (dart.library.html) 'file_storage.web.dart';
export 'file_storage_stub.dart'
if (dart.library.io) 'file_storage_vm.dart'
if (dart.library.html) 'file_storage_web.dart';

/// File storage interface for saving and loading constraint locally
abstract interface class FileStorage {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:amplify_core/amplify_core.dart';
import 'package:aws_logging_cloudwatch/src/file_storage/file_storage.dart';

/// File storage implementation for saving and loading constraint locally
class FileStorageImpl implements FileStorage {
/// File storage implementation for saving and loading constraint locally
FileStorageImpl(this.pathProvider);

/// Path provider to get the application support path
final AppPathProvider pathProvider;

@override
Future<String?> loadConstraint(String fileName) async {
throw UnimplementedError();
}

@override
Future<void> saveConstraintLocally(String fileName, String content) async {
throw UnimplementedError();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'package:aws_logging_cloudwatch/src/file_storage/file_storage.dart';
import 'package:path/path.dart' as p;

/// File storage implementation for saving and loading constraint locally
final class FileStorageImpl implements FileStorage {
class FileStorageImpl implements FileStorage {
/// File storage implementation for saving and loading constraint locally
FileStorageImpl(this.pathProvider);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:amplify_core/amplify_core.dart';
import 'package:aws_logging_cloudwatch/src/file_storage/file_storage.dart';

/// File storage implementation for saving and loading constraint locally
final class FileStorageImpl implements FileStorage {
class FileStorageImpl implements FileStorage {
/// File storage implementation for saving and loading constraint locally
// ignore: avoid_unused_constructor_parameters
FileStorageImpl(AppPathProvider pathProvider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,27 @@ class LoggingConstraint with AWSDebuggable {
factory LoggingConstraint.fromJson(Map<String, dynamic> json) =>
_$LoggingConstraintFromJson(json);

// /// Converts an [LoggingConstraint] instance to a [Map].
// Map<String, dynamic> toJson() => _$LoggingConstraintToJson(this);

/// Converts an [LoggingConstraint] instance to a [Map].
Map<String, dynamic> toJson() => _$LoggingConstraintToJson(this);
Map<String, dynamic> toJson() {
final jsonMap = <String, dynamic>{
'defaultLogLevel':
defaultLogLevel.toString().split('.').last, // Convert enum to string
'categoryLogLevel': categoryLogLevel?.map(
(key, value) => MapEntry(key, value.toString().split('.').last),
),
};

if (userLogLevel != null) {
jsonMap['userLogLevel'] = userLogLevel!.map(
(key, value) => MapEntry(key, value.toJson()),
);
}

return jsonMap;
}

/// The default [LogLevel] for sending logs to CloudWatch.
final LogLevel defaultLogLevel;
Expand Down Expand Up @@ -93,7 +112,18 @@ class UserLogLevel {
_$UserLogLevelFromJson(json);

/// Converts a [UserLogLevel] instance to a [Map].
Map<String, dynamic> toJson() => _$UserLogLevelToJson(this);
Map<String, dynamic> toJson() => {
'defaultLogLevel': defaultLogLevel
?.toString()
.split('.')
.last, // Convert enum to string
'categoryLogLevel': categoryLogLevel?.map(
(key, value) => MapEntry(
key,
value.toString().split('.').last,
), // Convert enum to string
),
};

/// The default [LogLevel] for sending logs to CloudWatch.
final LogLevel? defaultLogLevel;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import 'package:amplify_core/amplify_core.dart';

import 'package:aws_common/aws_common.dart';
import 'package:aws_logging_cloudwatch/aws_logging_cloudwatch.dart';
import 'package:aws_logging_cloudwatch/src/file_storage/file_storage.dart';
import 'package:aws_logging_cloudwatch/src/file_storage/file_storage_stub.dart'
if (dart.library.io) 'package:aws_logging_cloudwatch/src/file_storage/file_storage_vm.dart'
if (dart.library.html) 'package:aws_logging_cloudwatch/src/file_storage/file_storage_web.dart';
import 'package:aws_signature_v4/aws_signature_v4.dart';
import 'package:meta/meta.dart';

Expand All @@ -35,21 +37,23 @@ base class BaseRemoteLoggingConstraintProvider
BaseRemoteLoggingConstraintProvider({
required DefaultRemoteConfiguration config,
required AWSCredentialsProvider credentialsProvider,
FileStorage? fileStorage,
FileStorageImpl? fileStorage,
AWSHttpClient? awsHttpClient,
}) : _fileStorage = fileStorage,
_config = config,
_credentialsProvider = credentialsProvider {
init();
_credentialsProvider = credentialsProvider,
_awsHttpClient = awsHttpClient ?? AWSHttpClient() {
_init();
}

final FileStorage? _fileStorage;
final FileStorageImpl? _fileStorage;

final DefaultRemoteConfiguration _config;
final AWSCredentialsProvider _credentialsProvider;

LoggingConstraint? _loggingConstraint;

final AWSHttpClient _awsHttpClient = AWSHttpClient();
final AWSHttpClient _awsHttpClient;

// The timer to refresh the constraint periodically.
Timer? _timer;
Expand All @@ -64,20 +68,8 @@ base class BaseRemoteLoggingConstraintProvider
/// Initializes the [BaseRemoteLoggingConstraintProvider] by fetching
/// the constraint from the endpoint initially and then
/// starting the refresh timer afterwards.
Future<LoggingConstraint?> init() async {
// Check local storage first.
if (_fileStorage != null) {
final localConstraint =
await _fileStorage!.loadConstraint('remoteloggingconstraints.json');
if (localConstraint != null) {
_loggingConstraint = LoggingConstraint.fromJson(
jsonDecode(localConstraint) as Map<String, dynamic>,
);
}
}
await _fetchAndCacheConstraintFromEndpoint();
await _refreshConstraintPeriodically();
return null;
void _init() {
_refreshConstraintPeriodically();
}

/// Creates a request to fetch the constraint from the endpoint.
Expand Down Expand Up @@ -112,14 +104,18 @@ base class BaseRemoteLoggingConstraintProvider
jsonEncode(fetchedConstraint.toJson()),
);
}
} else {
await _loadConstraintFromLocalCache();
}
} on Exception catch (exception) {
throw Exception(
logger.debug(
'Failed to fetch logging constraint from ${_config.endpoint}: $exception',
);
} on Error catch (error) {
await _loadConstraintFromLocalCache();
} on Error catch (error, stackTrace) {
logger.error(
'Error while fetching logging constraint from ${_config.endpoint}: $error',
stackTrace,
);
}
}
Expand All @@ -128,8 +124,18 @@ base class BaseRemoteLoggingConstraintProvider
@override
LoggingConstraint? get loggingConstraint => _loggingConstraint;

Future<void> _loadConstraintFromLocalCache() async {
final localConstraint =
await _fileStorage!.loadConstraint('remoteloggingconstraints.json');
if (localConstraint != null) {
_loggingConstraint = LoggingConstraint.fromJson(
jsonDecode(localConstraint) as Map<String, dynamic>,
);
}
}

/// Refreshes the constraint from the endpoint periodically.
Future<void> _refreshConstraintPeriodically() async {
void _refreshConstraintPeriodically() {
if (_isRunning) {
return;
}
Expand All @@ -141,6 +147,7 @@ base class BaseRemoteLoggingConstraintProvider
_config.refreshInterval,
(_) => _fetchAndCacheConstraintFromEndpoint(),
);
Timer.run(_fetchAndCacheConstraintFromEndpoint);
}
}

Expand All @@ -155,6 +162,7 @@ final class DefaultRemoteLoggingConstraintProvider
required super.config,
required this.credentialsProvider,
super.fileStorage,
super.awsHttpClient,
}) : super(credentialsProvider: credentialsProvider);

/// The credentials provider to use for signing the request.
Expand Down
Loading

0 comments on commit 0506c77

Please sign in to comment.