mirror of
https://github.com/hanskokx/arcane_framework.git
synced 2026-08-12 06:10:55 +02:00
v2.0.2: Fix ArcaneLogger LoggerName mixin to be runtime safe (#9)
* Enhance reset method in ArcaneLogger to clear interceptors along with metadata and interfaces Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com> * Update Logging feature to replace @LoggingFeature annotation with LoggerName mixin for runtime accessibility Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com> * Bump version to 2.0.2 in pubspec.yaml and update CHANGELOG to reflect the new version Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com> * Add migration steps for replacing @LoggingFeature annotation with LoggerName mixin in CHANGELOG Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com> * Add TestLoggerWithLoggerName class to enhance logging functionality and verify LoggerName mixin behavior Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com> * Fix class declaration in migration example for LoggerName mixin Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com> --------- Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,3 +1,33 @@
|
||||
## 2.0.2
|
||||
|
||||
### Logging Service
|
||||
|
||||
- [BREAKING] Replaced the `@LoggingFeature(...)` annotation (compile-time only,
|
||||
not readable at runtime in Flutter) with the `LoggerName` mixin.
|
||||
Mix `LoggerName` into a `LoggingInterface` subclass and override
|
||||
`name` to expose a runtime-accessible name inside `log()`.
|
||||
|
||||
#### Migration Steps (LoggingFeature)
|
||||
|
||||
1. Replace any `@LoggingFeature("...")` annotation with `with LoggerName` and
|
||||
add an `@override String get name => '...';` getter to the class body.
|
||||
|
||||
Before:
|
||||
|
||||
```dart
|
||||
@LoggingFeature("my-feature")
|
||||
class MyLogger extends LoggingInterface {...}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```dart
|
||||
class MyLogger extends LoggingInterface with LoggerName {
|
||||
@override
|
||||
String get name => "my-feature";
|
||||
}
|
||||
```
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Arcane Framework
|
||||
|
||||
@@ -514,12 +514,13 @@ class ExternalLogger extends LoggingInterface with LoggingInitialization {
|
||||
}
|
||||
```
|
||||
|
||||
If you want to tag a destination, annotate the interface with
|
||||
`@LoggingFeature(...)`:
|
||||
If you want to give a destination a name and access it at runtime,
|
||||
mix in `LoggerName` and override `name`:
|
||||
|
||||
```dart
|
||||
@LoggingFeature("Analytics")
|
||||
class AnalyticsLogger extends LoggingInterface {
|
||||
class AnalyticsLogger extends LoggingInterface with LoggerName {
|
||||
@override
|
||||
String get name => 'Analytics';
|
||||
|
||||
@override
|
||||
void log(
|
||||
@@ -529,6 +530,7 @@ class AnalyticsLogger extends LoggingInterface {
|
||||
StackTrace? stackTrace,
|
||||
Object? extra,
|
||||
}) {
|
||||
// name is accessible here at runtime.
|
||||
// Forward to analytics pipeline.
|
||||
}
|
||||
}
|
||||
@@ -545,12 +547,14 @@ Arcane.logger.interceptors.add(
|
||||
);
|
||||
```
|
||||
|
||||
You can use this tag as source-level documentation and keep destination routing
|
||||
You can use `name` inside `log()` and keep destination routing
|
||||
explicit in interceptors.
|
||||
|
||||
```dart
|
||||
@LoggingFeature("auth")
|
||||
class AuthLogger extends LoggingInterface {
|
||||
class AuthLogger extends LoggingInterface with LoggerName {
|
||||
@override
|
||||
String get name => 'auth';
|
||||
|
||||
@override
|
||||
void log(
|
||||
String message, {
|
||||
|
||||
@@ -41,13 +41,24 @@ mixin LoggingInitialization implements LoggingInitializable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Annotation used to tag a logging destination with a feature name.
|
||||
/// Opt-in mixin that exposes a [name] string on a [LoggingInterface].
|
||||
///
|
||||
/// Mix this into a concrete logger to declare what [name] should be associated
|
||||
/// with this logging interface.
|
||||
///
|
||||
/// Example:
|
||||
/// `@LoggingFeature("analytics")`
|
||||
final class LoggingFeature {
|
||||
const LoggingFeature(this.value);
|
||||
|
||||
/// The feature name associated with this logging destination.
|
||||
final String value;
|
||||
/// ```dart
|
||||
/// class MyLogger extends LoggingInterface with LoggerName {
|
||||
/// @override
|
||||
/// String get name => 'my-feature';
|
||||
///
|
||||
/// @override
|
||||
/// void log(String message, {...}) {
|
||||
/// print('[$name] $message');
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
mixin LoggerName on LoggingInterface {
|
||||
/// The name associated with this logging interface.
|
||||
String get name;
|
||||
}
|
||||
|
||||
@@ -470,8 +470,8 @@ class ArcaneLogger {
|
||||
void clearPersistentMetadata() => _additionalMetadata.clear();
|
||||
|
||||
/// Resets the Arcane logging service by clearing all persistent metadata,
|
||||
/// clearing all registered [LoggingInterface]s and marking the logging
|
||||
/// service as no longer being initialized.
|
||||
/// clearing all registered [LoggingInterface]s, clearing all interceptors,
|
||||
/// and marking the logging service as no longer being initialized.
|
||||
void reset() {
|
||||
dispose();
|
||||
I._interfaceRegistrations.clear();
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
name: arcane_framework
|
||||
description: "Agnostic Reusable Component Architecture for New Ecosystems: a
|
||||
modern framework for bootstrapping new applications"
|
||||
version: 2.0.1
|
||||
version: 2.0.2
|
||||
repository: https://github.com/hanskokx/arcane_framework
|
||||
issue_tracker: https://github.com/hanskokx/arcane_framework/issues
|
||||
|
||||
|
||||
@@ -110,9 +110,37 @@ class RedactingLogInterceptor implements LogInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
class TestLoggerWithLoggerName extends LoggingInterface with LoggerName {
|
||||
@override
|
||||
String get name => "test-logger";
|
||||
|
||||
final List<LogEvent> events = [];
|
||||
|
||||
@override
|
||||
void log(
|
||||
String message, {
|
||||
Map<String, Object?>? metadata,
|
||||
Level? level,
|
||||
StackTrace? stackTrace,
|
||||
Object? extra,
|
||||
}) {
|
||||
events.add(
|
||||
LogEvent(
|
||||
message: message,
|
||||
metadata: metadata == null ? null : Map<String, Object?>.from(metadata),
|
||||
level: level,
|
||||
stackTrace: stackTrace,
|
||||
extra: extra,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
late TestLoggingInterface myInterface;
|
||||
late LogInterceptor prefixInterceptor;
|
||||
final TestLoggerWithLoggerName loggerWithLoggerName =
|
||||
TestLoggerWithLoggerName();
|
||||
|
||||
setUp(() {
|
||||
Arcane.logger.reset();
|
||||
@@ -677,4 +705,12 @@ void main() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("LoggerName mixin exposes name at runtime", () {
|
||||
expect(loggerWithLoggerName.name, "test-logger");
|
||||
|
||||
loggerWithLoggerName.log("Test message");
|
||||
expect(loggerWithLoggerName.events.length, 1);
|
||||
expect(loggerWithLoggerName.events.first.message, "Test message");
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user