Skip to content

feat: support network logs omission #382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Added

- Add network logs obfuscation support using the new `NetworkLogger.obfuscateLog` API ([#380](https://github.com/Instabug/Instabug-Flutter/pull/380)).
- Add network logs omission support using the new `NetworkLogger.omitLog` API ([#382](https://github.com/Instabug/Instabug-Flutter/pull/382)).

### Changed

Expand Down
26 changes: 26 additions & 0 deletions lib/src/modules/network_logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,33 @@ class NetworkLogger {
_manager.setObfuscateLogCallback(callback);
}

/// Registers a callback to selectively omit network log data.
///
/// Use this method to set a callback function that determines whether
/// specific network log data should be excluded before recording it.
///
/// The [callback] function takes a [NetworkData] object as its argument and
/// should return a boolean value indicating whether the data should be omitted
/// (`true`) or included (`false`).
///
/// Example:
///
/// ```dart
/// NetworkLogger.omitLog((data) {
/// // Implement logic to decide whether to omit the data.
/// // For example, ignore requests to a specific URL:
/// return data.url.startsWith('https://example.com');
/// });
/// ```
static void omitLog(OmitLogCallback callback) {
_manager.setOmitLogCallback(callback);
}

Future<void> networkLog(NetworkData data) async {
final omit = await _manager.omitLog(data);

if (omit) return;

final obfuscated = await _manager.obfuscateLog(data);

await _host.networkLog(obfuscated.toJson());
Expand Down
15 changes: 15 additions & 0 deletions lib/src/utils/network_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,37 @@ import 'dart:async';
import 'package:instabug_flutter/instabug_flutter.dart';

typedef ObfuscateLogCallback = FutureOr<NetworkData> Function(NetworkData data);
typedef OmitLogCallback = FutureOr<bool> Function(NetworkData data);

/// Mockable [NetworkManager] responsible for processing network logs
/// before they are sent to the native SDKs.
class NetworkManager {
ObfuscateLogCallback? _obfuscateLogCallback;
OmitLogCallback? _omitLogCallback;

// ignore: use_setters_to_change_properties
void setObfuscateLogCallback(ObfuscateLogCallback callback) {
_obfuscateLogCallback = callback;
}

// ignore: use_setters_to_change_properties
void setOmitLogCallback(OmitLogCallback callback) {
_omitLogCallback = callback;
}

FutureOr<NetworkData> obfuscateLog(NetworkData data) {
if (_obfuscateLogCallback == null) {
return data;
}

return _obfuscateLogCallback!(data);
}

FutureOr<bool> omitLog(NetworkData data) {
if (_omitLogCallback == null) {
return false;
}

return _omitLogCallback!(data);
}
}
35 changes: 35 additions & 0 deletions test/network_logger_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void main() {
test('[networkLog] should call 1 host method on iOS', () async {
when(mBuildInfo.isAndroid).thenReturn(false);
when(mManager.obfuscateLog(data)).thenReturn(data);
when(mManager.omitLog(data)).thenReturn(false);

await logger.networkLog(data);

Expand All @@ -66,6 +67,7 @@ void main() {
test('[networkLog] should call 2 host methods on Android', () async {
when(mBuildInfo.isAndroid).thenReturn(true);
when(mManager.obfuscateLog(data)).thenReturn(data);
when(mManager.omitLog(data)).thenReturn(false);

await logger.networkLog(data);

Expand All @@ -83,6 +85,7 @@ void main() {

when(mBuildInfo.isAndroid).thenReturn(true);
when(mManager.obfuscateLog(data)).thenReturn(obfuscated);
when(mManager.omitLog(data)).thenReturn(false);

await logger.networkLog(data);

Expand All @@ -99,6 +102,28 @@ void main() {
).called(1);
});

test('[networkLog] should not log data if it should be omitted', () async {
const omit = true;

when(mBuildInfo.isAndroid).thenReturn(true);
when(mManager.obfuscateLog(data)).thenReturn(data);
when(mManager.omitLog(data)).thenReturn(omit);

await logger.networkLog(data);

verify(
mManager.omitLog(data),
).called(1);

verifyNever(
mInstabugHost.networkLog(data.toJson()),
);

verifyNever(
mApmHost.networkLogAndroid(data.toJson()),
);
});

test('[obfuscateLog] should set obfuscation callback on manager', () async {
FutureOr<NetworkData> callback(NetworkData data) => data;

Expand All @@ -108,4 +133,14 @@ void main() {
mManager.setObfuscateLogCallback(callback),
).called(1);
});

test('[omitLog] should set omission callback on manager', () async {
FutureOr<bool> callback(NetworkData data) => true;

NetworkLogger.omitLog(callback);

verify(
mManager.setOmitLogCallback(callback),
).called(1);
});
}
29 changes: 29 additions & 0 deletions test/network_manager_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,33 @@ void main() {

expect(result, equals(obfuscated));
});

test('[omitLog] should return false when no omit log callback', () async {
const expected = false;

final result = await manager.omitLog(data);

expect(result, equals(expected));
});

test(
'[omitLog] should use omit callback when [setOmitLogCallback] has set a callback',
() async {
const omit = true;
final completer = Completer<NetworkData>();
FutureOr<bool> callback(NetworkData data) {
completer.complete(data);
return omit;
}

manager.setOmitLogCallback(callback);

final result = await manager.omitLog(data);

expect(completer.isCompleted, isTrue);

expect(await completer.future, data);

expect(result, equals(omit));
});
}