Skip to content

feat: respect BE network body limit #593

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

Open
wants to merge 13 commits into
base: dev
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ android/gradlew.bat
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*

# Project specific
/PRDs/

# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Added

- Add support for respecting backend network body size limits. ([#593](https://github.com/Instabug/Instabug-Flutter/pull/593))

- Add support for xCode 16. ([#574](https://github.com/Instabug/Instabug-Flutter/pull/574))

- Add support for BugReporting user consents. ([#573](https://github.com/Instabug/Instabug-Flutter/pull/573))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,11 @@ public void reply(Void reply) {

}
});

featureFlagsFlutterApi.onNetworkLogBodyMaxSizeChange(
(long) featuresState.getNetworkLogCharLimit(),
reply -> {}
);
}
});
}
Expand Down Expand Up @@ -509,4 +514,21 @@ public void setNetworkLogBodyEnabled(@NonNull Boolean isEnabled) {
e.printStackTrace();
}
}

@Override
public void getNetworkBodyMaxSize(@NonNull InstabugPigeon.Result<Double> result) {
ThreadManager.runOnMainThread(
new Runnable() {
@Override
public void run() {
try {
double networkCharLimit = InternalCore.INSTANCE.get_networkLogCharLimit();
result.success(networkCharLimit);
} catch (Exception e) {
e.printStackTrace();
}
}
}
);
}
}
11 changes: 11 additions & 0 deletions android/src/test/java/com/instabug/flutter/InstabugApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -658,4 +658,15 @@ public void testSetNetworkLogBodyDisabled() {

mInstabug.verify(() -> Instabug.setNetworkLogBodyEnabled(false));
}

@Test
public void testGetNetworkBodyMaxSize() {
double expected = 10240;
InstabugPigeon.Result<Double> result = makeResult((actual) -> assertEquals((Double) expected, actual));

mockkObject(new InternalCore[]{InternalCore.INSTANCE}, false);
every(mockKMatcherScope -> InternalCore.INSTANCE.get_networkLogCharLimit()).returns((int) expected);

api.getNetworkBodyMaxSize(result);
}
}
3 changes: 3 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ app.*.symbols

# Obfuscation related
app.*.map.json

# Android related
/android/app/.cxx/
16 changes: 16 additions & 0 deletions example/ios/InstabugTests/InstabugApiTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -611,4 +611,20 @@ - (void)testisW3CFeatureFlagsEnabled {

}

- (void)testGetNetworkBodyMaxSize {
double expectedValue = 10240.0;
XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"];

OCMStub([self.mNetworkLogger getNetworkBodyMaxSize]).andReturn(expectedValue);

[self.api getNetworkBodyMaxSizeWithCompletion:^(NSNumber *actual, FlutterError *error) {
[expectation fulfill];
XCTAssertEqual(actual.doubleValue, expectedValue);
XCTAssertNil(error);
}];

OCMVerify([self.mNetworkLogger getNetworkBodyMaxSize]);
[self waitForExpectations:@[expectation] timeout:5.0];
}

@end
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PODS:
- Flutter (1.0.0)
- Instabug (15.1.1)
- instabug_flutter (15.0.1):
- instabug_flutter (15.1.1):
- Flutter
- Instabug (= 15.1.1)
- OCMock (3.6)
Expand All @@ -25,7 +25,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
Instabug: 3e7af445c14d7823fcdecba223f09b5f7c0c6ce1
instabug_flutter: e4e366434313bab3a2db123c1501ca6247dc950b
instabug_flutter: 30aec1138f5d9c99d175e4f4ad49189ed844b72a
OCMock: 5ea90566be239f179ba766fd9fbae5885040b992

PODFILE CHECKSUM: 4d0aaaf6a444f68024f992999ff2c2ee26baa6ec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
Expand Down
5 changes: 5 additions & 0 deletions ios/Classes/Modules/InstabugApi.m
Original file line number Diff line number Diff line change
Expand Up @@ -396,4 +396,9 @@ - (void)setNetworkLogBodyEnabledIsEnabled:(NSNumber *)isEnabled
IBGNetworkLogger.logBodyEnabled = [isEnabled boolValue];
}

- (void)getNetworkBodyMaxSizeWithCompletion:(nonnull void (^)(NSNumber * _Nullable, FlutterError * _Nullable))completion {
completion(@(IBGNetworkLogger.getNetworkBodyMaxSize), nil);
}


@end
2 changes: 2 additions & 0 deletions ios/Classes/Util/IBGNetworkLogger+CP.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ NS_ASSUME_NONNULL_BEGIN
duration:(int64_t) duration
gqlQueryName:(NSString * _Nullable)gqlQueryName;

+ (double)getNetworkBodyMaxSize;

@end

NS_ASSUME_NONNULL_END
2 changes: 1 addition & 1 deletion ios/instabug_flutter.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'instabug_flutter'
s.version = '15.0.1'
s.version = '15.1.1'
s.summary = 'Flutter plugin for integrating the Instabug SDK.'
s.author = 'Instabug'
s.homepage = 'https://www.instabug.com/platforms/flutter'
Expand Down
2 changes: 1 addition & 1 deletion lib/src/modules/instabug.dart
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class Instabug {
invocationEvents.mapToString(),
debugLogsLevel.toString(),
);
return FeatureFlagsManager().registerW3CFlagsListener();
return FeatureFlagsManager().registerFeatureFlagsListener();
}

/// Sets a [callback] to be called wehenever a screen name is captured to mask
Expand Down
33 changes: 32 additions & 1 deletion lib/src/modules/network_logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import 'package:instabug_flutter/src/models/network_data.dart';
import 'package:instabug_flutter/src/models/w3c_header.dart';
import 'package:instabug_flutter/src/modules/apm.dart';
import 'package:instabug_flutter/src/utils/feature_flags_manager.dart';
import 'package:instabug_flutter/src/utils/instabug_constants.dart';
import 'package:instabug_flutter/src/utils/instabug_logger.dart';
import 'package:instabug_flutter/src/utils/iterable_ext.dart';
import 'package:instabug_flutter/src/utils/network_manager.dart';
import 'package:instabug_flutter/src/utils/w3c_header_utils.dart';
Expand Down Expand Up @@ -86,7 +88,36 @@ class NetworkLogger {
Future<void> networkLogInternal(NetworkData data) async {
final omit = await _manager.omitLog(data);
if (omit) return;
final obfuscated = await _manager.obfuscateLog(data);

// Check size limits early to avoid processing large bodies
final requestExceeds = await _manager.didRequestBodyExceedSizeLimit(data);
final responseExceeds = await _manager.didResponseBodyExceedSizeLimit(data);

var processedData = data;
if (requestExceeds || responseExceeds) {
// Replace bodies with warning messages
processedData = data.copyWith(
requestBody: requestExceeds
? InstabugConstants.getRequestBodyReplacementMessage(
data.requestBodySize,
)
: data.requestBody,
responseBody: responseExceeds
? InstabugConstants.getResponseBodyReplacementMessage(
data.responseBodySize,
)
: data.responseBody,
);

// Log the truncation event.
final isBothExceeds = requestExceeds && responseExceeds;
InstabugLogger.I.e(
"Truncated network ${isBothExceeds ? 'request and response' : requestExceeds ? 'request' : 'response'} body",
tag: InstabugConstants.networkLoggerTag,
);
}

final obfuscated = await _manager.obfuscateLog(processedData);
await _host.networkLog(obfuscated.toJson());
await APM.networkLogAndroid(obfuscated);
}
Expand Down
30 changes: 29 additions & 1 deletion lib/src/utils/feature_flags_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ typedef OnW3CFeatureFlagChange = void Function(
bool isW3cCaughtHeaderEnabled,
);

typedef OnNetworkBodyMaxSizeChangeCallback = void Function();

class FeatureFlagsManager implements FeatureFlagsFlutterApi {
// Access the singleton instance
factory FeatureFlagsManager() {
Expand All @@ -23,6 +25,10 @@ class FeatureFlagsManager implements FeatureFlagsFlutterApi {
// Host API instance
static InstabugHostApi _host = InstabugHostApi();

// Callback for network body max size changes
static OnNetworkBodyMaxSizeChangeCallback?
_onNetworkBodyMaxSizeChangeCallback;

/// @nodoc
@visibleForTesting
// Setter for the host API
Expand All @@ -38,10 +44,21 @@ class FeatureFlagsManager implements FeatureFlagsFlutterApi {
// since it breaks the singleton pattern
}

/// Sets the callback for network body max size changes
// ignore: avoid_setters_without_getters
set onNetworkBodyMaxSizeChangeCallback(
OnNetworkBodyMaxSizeChangeCallback callback,
) {
_onNetworkBodyMaxSizeChangeCallback = callback;
}

// Internal state flags
bool _isAndroidW3CExternalTraceID = false;
bool _isAndroidW3CExternalGeneratedHeader = false;
bool _isAndroidW3CCaughtHeader = false;
int _networkBodyMaxSize = 0;

int get networkBodyMaxSize => _networkBodyMaxSize;

Future<W3cFeatureFlags> getW3CFeatureFlagsHeader() async {
if (IBGBuildInfo.instance.isAndroid) {
Expand All @@ -64,9 +81,10 @@ class FeatureFlagsManager implements FeatureFlagsFlutterApi {
);
}

Future<void> registerW3CFlagsListener() async {
Future<void> registerFeatureFlagsListener() async {
FeatureFlagsFlutterApi.setup(this); // Use 'this' instead of _instance

// W3C Feature Flags
final featureFlags = await _host.isW3CFeatureFlagsEnabled();
_isAndroidW3CCaughtHeader =
featureFlags['isW3cCaughtHeaderEnabled'] ?? false;
Expand All @@ -75,6 +93,10 @@ class FeatureFlagsManager implements FeatureFlagsFlutterApi {
_isAndroidW3CExternalGeneratedHeader =
featureFlags['isW3cExternalGeneratedHeaderEnabled'] ?? false;

// Network Body Max Size
final networkBodyMaxSize = await _host.getNetworkBodyMaxSize();
_networkBodyMaxSize = networkBodyMaxSize?.toInt() ?? 0;

return _host.registerFeatureFlagChangeListener();
}

Expand All @@ -89,4 +111,10 @@ class FeatureFlagsManager implements FeatureFlagsFlutterApi {
_isAndroidW3CExternalTraceID = isW3cExternalTraceIDEnabled;
_isAndroidW3CExternalGeneratedHeader = isW3cExternalGeneratedHeaderEnabled;
}

@override
void onNetworkLogBodyMaxSizeChange(int networkBodyMaxSize) {
_networkBodyMaxSize = networkBodyMaxSize;
_onNetworkBodyMaxSizeChangeCallback?.call();
}
}
31 changes: 31 additions & 0 deletions lib/src/utils/instabug_constants.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// Constants used throughout the Instabug Flutter SDK
class InstabugConstants {
InstabugConstants._();

// Network logging constants
static const String networkLoggerTag = 'NetworkLogger';
static const String networkManagerTag = 'NetworkManager';

// Network body replacement messages
static const String requestBodyReplacedPrefix = '[REQUEST_BODY_REPLACED]';
static const String responseBodyReplacedPrefix = '[RESPONSE_BODY_REPLACED]';
static const String exceedsLimitSuffix = 'exceeds limit';

/// Generates a request body replacement message
static String getRequestBodyReplacementMessage(int size) {
return '$requestBodyReplacedPrefix - Size: $size $exceedsLimitSuffix';
}

/// Generates a response body replacement message
static String getResponseBodyReplacementMessage(int size) {
return '$responseBodyReplacedPrefix - Size: $size $exceedsLimitSuffix';
}

/// Generates a network body size limit exceeded log message
static String getNetworkBodyLimitExceededMessage({
required String type,
required int bodySize,
}) {
return 'Network body size limit exceeded for $type - Size: $bodySize';
}
}
Loading