From d8e84a6fd69f332081452ad9d47a389e4f9a8b64 Mon Sep 17 00:00:00 2001 From: Kha Truong <64438356+khatruong2009@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:51:36 -0700 Subject: [PATCH] feat(logging): default remote config --- .../lib/src/plugin_config.dart | 9 ++ .../lib/src/remote_constraint_provider.dart | 82 ++++++++++++++++++- .../aws_logging_cloudwatch/pubspec.yaml | 1 + 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/plugin_config.dart b/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/plugin_config.dart index 9fd10d18d0..6a1e9e5838 100644 --- a/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/plugin_config.dart +++ b/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/plugin_config.dart @@ -48,6 +48,15 @@ class CloudWatchLoggerPluginConfiguration with AWSDebuggable { /// The logging constraint for sending logs to CloudWatch. /// {@endtemplate} class LoggingConstraint with AWSDebuggable { + factory LoggingConstraint.fromJson(Map json) { + return LoggingConstraint( + defaultLogLevel: LogLevel.values.firstWhere( + (e) => e.toString() == 'LogLevel.${json['defaultLogLevel']}', + orElse: () => LogLevel.error, // Default value if not found + ), + ); + } + /// {@macro aws_logging_cloudwatch.logging_constraint} const LoggingConstraint({this.defaultLogLevel = LogLevel.error}); diff --git a/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/remote_constraint_provider.dart b/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/remote_constraint_provider.dart index 7a8a36332f..076efaba25 100644 --- a/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/remote_constraint_provider.dart +++ b/packages/logging_cloudwatch/aws_logging_cloudwatch/lib/src/remote_constraint_provider.dart @@ -1,11 +1,15 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +import 'dart:convert'; +import 'dart:io'; + // TODO(nikahsn): remove after implementing the get loggingConstraint. // ignore_for_file: unused_field import 'package:aws_common/aws_common.dart'; import 'package:aws_logging_cloudwatch/aws_logging_cloudwatch.dart'; +import 'package:http/http.dart' as http; /// {@template aws_logging_cloudwatch.remote_logging_constraint_provider} /// An Interface to provide custom implementation for @@ -33,9 +37,83 @@ class DefaultRemoteLoggingConstraintProvider final DefaultRemoteConfiguration _config; final AWSCredentialsProvider _credentialsProvider; + LoggingConstraint? _loggingConstraint; + DateTime? _lastUpdated; + + Future _saveConstraintLocally(LoggingConstraint constraint) async { + final file = File('logging_constraint.json'); + await file.writeAsString(jsonEncode(constraint)); + } + + Future _getConstraintFromLocalStorage() async { + final file = File('logging_constraint.json'); + if (await file.exists()) { + final content = await file.readAsString(); + return LoggingConstraint.fromJson( + jsonDecode(content) as Map, + ); + } + return null; + } + + Future _fetchAndCacheConstraintFromEndpoint() async { + try { + final constraint = await _fetchConstraintFromEndpoint(); + if (constraint != null) { + _loggingConstraint = constraint; + _lastUpdated = DateTime.now(); + } + } catch (error) { + print('Error fetching constraints: $error'); + } + } + + Future _fetchConstraintFromEndpoint() async { + final response = await http.get(Uri.parse(_config.endpoint)); + if (response.statusCode == 200) { + final fetchedConstraint = LoggingConstraint.fromJson( + jsonDecode(response.body) as Map, + ); + await _saveConstraintLocally(fetchedConstraint); + return fetchedConstraint; + } + throw Exception( + 'Failed to fetch logging constraint from ${_config.endpoint}', + ); + } + @override - // TODO(nikahsn): add implementation. - LoggingConstraint get loggingConstraint => throw UnimplementedError(); + LoggingConstraint? get loggingConstraint { + if (_loggingConstraint != null && + _lastUpdated != null && + DateTime.now().difference(_lastUpdated!).inSeconds <= + _config.refreshIntervalInSeconds.inSeconds) { + return _loggingConstraint; + } + // Load from local storage synchronously + final file = File('logging_constraint.json'); + if (file.existsSync()) { + final content = file.readAsStringSync(); + return LoggingConstraint.fromJson( + jsonDecode(content) as Map, + ); + } + return null; + } + + /// Initializes and starts the periodic fetch. + void initialize() { + _fetchAndCacheConstraintFromEndpoint(); // Fetch once immediately on initialize + _refreshConstraintPeriodically(); + } + + /// Refreshes the constraint from the endpoint periodically. + Future _refreshConstraintPeriodically() async { + while (true) { + await Future.delayed(_config.refreshIntervalInSeconds); + await _fetchAndCacheConstraintFromEndpoint(); + } + } } /// {@template aws_logging_cloudwatch.default_remote_configuration} diff --git a/packages/logging_cloudwatch/aws_logging_cloudwatch/pubspec.yaml b/packages/logging_cloudwatch/aws_logging_cloudwatch/pubspec.yaml index fa470e56ba..0e3d86fdf6 100644 --- a/packages/logging_cloudwatch/aws_logging_cloudwatch/pubspec.yaml +++ b/packages/logging_cloudwatch/aws_logging_cloudwatch/pubspec.yaml @@ -15,6 +15,7 @@ dependencies: built_collection: ^5.1.1 built_value: ">=8.6.0 <8.7.0" fixnum: ^1.1.0 + http: ^1.0.0 intl: ">=0.18.0 <1.0.0" meta: ^1.9.1 smithy: ^0.5.0+3