Skip to content

Release: v14.0.0 #533

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 5 commits into from
Nov 18, 2024
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## [14.0.0](https://github.com/Instabug/Instabug-Flutter/compare/v13.4.0...v14.0.0) (November 18, 2024)

### Added

- Add support for tracing network requests from Instabug to services like Datadog and New Relic ([#481](https://github.com/Instabug/Instabug-Flutter/pull/481)).

### Changed

- Bump Instabug Android SDK to v14.0.0 ([#532](https://github.com/Instabug/Instabug-Flutter/pull/532)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v14.0.0).
- Bump Instabug iOS SDK to v14.0.0 ([#532](https://github.com/Instabug/Instabug-Flutter/pull/532)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/14.0.0),

## [13.4.0](https://github.com/Instabug/Instabug-Flutter/compare/v13.3.0...v13.4.0) (September 29, 2024)

### Added
Expand Down
12 changes: 8 additions & 4 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group 'com.instabug.flutter'
version '13.4.0'
version '14.0.0'

buildscript {
repositories {
Expand All @@ -22,7 +22,10 @@ rootProject.allprojects {
apply plugin: 'com.android.library'

android {
compileSdkVersion 28
if (project.android.hasProperty("namespace")) {
namespace "com.instabug.flutter"
}
compileSdkVersion 33

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
Expand All @@ -41,10 +44,11 @@ android {
}

dependencies {
api 'com.instabug.library:instabug:13.4.1'

api 'com.instabug.library:instabug:14.0.0'
testImplementation 'junit:junit:4.13.2'
testImplementation "org.mockito:mockito-inline:3.12.1"
testImplementation "io.mockk:mockk:1.13.13"

}

// add upload_symbols task
Expand Down
3 changes: 1 addition & 2 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.instabug.flutter">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application>
<meta-data
Expand Down
63 changes: 53 additions & 10 deletions android/src/main/java/com/instabug/flutter/modules/ApmApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@
import com.instabug.apm.configuration.cp.FeatureAvailabilityCallback;
import com.instabug.apm.model.ExecutionTrace;
import com.instabug.apm.networking.APMNetworkLogger;
import com.instabug.apm.networkinterception.cp.APMCPNetworkLog;
import com.instabug.flutter.generated.ApmPigeon;
import com.instabug.flutter.util.Reflection;
import com.instabug.flutter.util.ThreadManager;
import com.instabug.apm.networkinterception.cp.APMCPNetworkLog;

import io.flutter.plugin.common.BinaryMessenger;

import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;

import java.lang.reflect.Method;
Expand Down Expand Up @@ -210,18 +209,62 @@ public void networkLogAndroid(@NonNull Map<String, Object> data) {
if (data.containsKey("serverErrorMessage")) {
serverErrorMessage = (String) data.get("serverErrorMessage");
}
Boolean isW3cHeaderFound = null;
Number partialId = null;
Number networkStartTimeInSeconds = null;
String w3CGeneratedHeader = null;
String w3CCaughtHeader = null;

if (data.containsKey("isW3cHeaderFound")) {
isW3cHeaderFound = (Boolean) data.get("isW3cHeaderFound");
}

if (data.containsKey("partialId")) {


partialId = ((Number) data.get("partialId"));

Method method = Reflection.getMethod(Class.forName("com.instabug.apm.networking.APMNetworkLogger"), "log", long.class, long.class, String.class, String.class, long.class, String.class, String.class, String.class, String.class, String.class, long.class, int.class, String.class, String.class, String.class, String.class, APMCPNetworkLog.W3CExternalTraceAttributes.class);
if (method != null) {
method.invoke(apmNetworkLogger, requestStartTime, requestDuration, requestHeaders, requestBody, requestBodySize, requestMethod, requestUrl, requestContentType, responseHeaders, responseBody, responseBodySize, statusCode, responseContentType, errorMessage, gqlQueryName, serverErrorMessage, null);
} else {
Log.e(TAG, "APMNetworkLogger.log was not found by reflection");
}
if (data.containsKey("networkStartTimeInSeconds")) {
networkStartTimeInSeconds = ((Number) data.get("networkStartTimeInSeconds"));
}

} catch (Exception e) {
e.printStackTrace();
if (data.containsKey("w3CGeneratedHeader")) {

w3CGeneratedHeader = (String) data.get("w3CGeneratedHeader");


}
if (data.containsKey("w3CCaughtHeader")) {
w3CCaughtHeader = (String) data.get("w3CCaughtHeader");

}


APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes =
null;
if (isW3cHeaderFound != null) {
w3cExternalTraceAttributes = new APMCPNetworkLog.W3CExternalTraceAttributes(
isW3cHeaderFound, partialId == null ? null : partialId.longValue(),
networkStartTimeInSeconds == null ? null : networkStartTimeInSeconds.longValue(),
w3CGeneratedHeader, w3CCaughtHeader

);
}

Method method = Reflection.getMethod(Class.forName("com.instabug.apm.networking.APMNetworkLogger"), "log", long.class, long.class, String.class, String.class, long.class, String.class, String.class, String.class, String.class, String.class, long.class, int.class, String.class, String.class, String.class, String.class, APMCPNetworkLog.W3CExternalTraceAttributes.class);
if (method != null) {
method.invoke(apmNetworkLogger, requestStartTime, requestDuration, requestHeaders, requestBody, requestBodySize, requestMethod, requestUrl, requestContentType, responseHeaders, responseBody, responseBodySize, statusCode, responseContentType, errorMessage, gqlQueryName, serverErrorMessage, w3cExternalTraceAttributes);
} else {
Log.e(TAG, "APMNetworkLogger.log was not found by reflection");
}

} catch(Exception e){
e.printStackTrace();
}
}
}




@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
import com.instabug.flutter.util.ArgsRegistry;
import com.instabug.flutter.util.Reflection;
import com.instabug.flutter.util.ThreadManager;
import com.instabug.library.internal.crossplatform.CoreFeature;
import com.instabug.library.internal.crossplatform.CoreFeaturesState;
import com.instabug.library.internal.crossplatform.FeaturesStateListener;
import com.instabug.library.internal.crossplatform.InternalCore;
import com.instabug.library.Feature;
import com.instabug.library.Instabug;
import com.instabug.library.InstabugColorTheme;
Expand Down Expand Up @@ -48,14 +52,19 @@ public class InstabugApi implements InstabugPigeon.InstabugHostApi {
private final Callable<Bitmap> screenshotProvider;
private final InstabugCustomTextPlaceHolder placeHolder = new InstabugCustomTextPlaceHolder();

private final InstabugPigeon.FeatureFlagsFlutterApi featureFlagsFlutterApi;

public static void init(BinaryMessenger messenger, Context context, Callable<Bitmap> screenshotProvider) {
final InstabugApi api = new InstabugApi(context, screenshotProvider);
final InstabugPigeon.FeatureFlagsFlutterApi flutterApi = new InstabugPigeon.FeatureFlagsFlutterApi(messenger);

final InstabugApi api = new InstabugApi(context, screenshotProvider, flutterApi);
InstabugPigeon.InstabugHostApi.setup(messenger, api);
}

public InstabugApi(Context context, Callable<Bitmap> screenshotProvider) {
public InstabugApi(Context context, Callable<Bitmap> screenshotProvider, InstabugPigeon.FeatureFlagsFlutterApi featureFlagsFlutterApi) {
this.context = context;
this.screenshotProvider = screenshotProvider;
this.featureFlagsFlutterApi = featureFlagsFlutterApi;
}

@VisibleForTesting
Expand Down Expand Up @@ -437,6 +446,48 @@ public void networkLog(@NonNull Map<String, Object> data) {
}
}

@Override
public void registerFeatureFlagChangeListener() {

try {
InternalCore.INSTANCE._setFeaturesStateListener(new FeaturesStateListener() {
@Override
public void invoke(@NonNull CoreFeaturesState featuresState) {
ThreadManager.runOnMainThread(new Runnable() {
@Override
public void run() {
featureFlagsFlutterApi.onW3CFeatureFlagChange(featuresState.isW3CExternalTraceIdEnabled(),
featuresState.isAttachingGeneratedHeaderEnabled(),
featuresState.isAttachingCapturedHeaderEnabled(),
new InstabugPigeon.FeatureFlagsFlutterApi.Reply<Void>() {
@Override
public void reply(Void reply) {

}
});
}
});
}

});
} catch (Exception e) {
e.printStackTrace();
}

}

@NonNull
@Override
public Map<String, Boolean> isW3CFeatureFlagsEnabled() {
Map<String, Boolean> params = new HashMap<String, Boolean>();
params.put("isW3cExternalTraceIDEnabled", InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID));
params.put("isW3cExternalGeneratedHeaderEnabled", InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER));
params.put("isW3cCaughtHeaderEnabled", InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER));


return params;
}

@Override
public void willRedirectToStore() {
Instabug.willRedirectToStore();
Expand Down
13 changes: 13 additions & 0 deletions android/src/test/java/com/instabug/flutter/ApmApiTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
package com.instabug.flutter;

import static com.instabug.flutter.util.GlobalMocks.reflected;
import static com.instabug.flutter.util.MockResult.makeResult;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.instabug.apm.APM;
import com.instabug.apm.InternalAPM;
import com.instabug.apm.configuration.cp.APMFeature;
Expand Down
57 changes: 51 additions & 6 deletions android/src/test/java/com/instabug/flutter/InstabugApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import static io.mockk.MockKKt.every;
import static io.mockk.MockKKt.mockkObject;

import io.mockk.*;

import android.app.Application;
import android.graphics.Bitmap;
import android.net.Uri;

import com.instabug.apm.InternalAPM;
import com.instabug.bug.BugReporting;
import com.instabug.flutter.generated.InstabugPigeon;
import com.instabug.flutter.modules.InstabugApi;
Expand All @@ -36,9 +42,15 @@
import com.instabug.library.ReproConfigurations;
import com.instabug.library.ReproMode;
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
import com.instabug.library.internal.crossplatform.CoreFeature;
import com.instabug.library.internal.crossplatform.FeaturesStateListener;
import com.instabug.library.internal.crossplatform.InternalCore;
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
import com.instabug.library.invocation.InstabugInvocationEvent;
import com.instabug.library.model.NetworkLog;
import com.instabug.library.ui.onboarding.WelcomeMessage;
import com.instabug.survey.Surveys;
import com.instabug.survey.callbacks.OnShowCallback;

import org.json.JSONObject;
import org.junit.After;
Expand All @@ -56,9 +68,16 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;

import io.flutter.plugin.common.BinaryMessenger;
import kotlin.jvm.functions.Function1;

import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.mockito.verification.VerificationMode;
import org.mockito.verification.VerificationMode;

public class InstabugApiTest {
Expand All @@ -69,11 +88,15 @@ public class InstabugApiTest {
private MockedStatic<BugReporting> mBugReporting;
private MockedConstruction<InstabugCustomTextPlaceHolder> mCustomTextPlaceHolder;
private MockedStatic<InstabugPigeon.InstabugHostApi> mHostApi;

private InternalCore internalCore;
@Before
public void setUp() throws NoSuchMethodException {
mCustomTextPlaceHolder = mockConstruction(InstabugCustomTextPlaceHolder.class);
api = spy(new InstabugApi(mContext, screenshotProvider));
internalCore=spy(InternalCore.INSTANCE);

BinaryMessenger mMessenger = mock(BinaryMessenger.class);
final InstabugPigeon.FeatureFlagsFlutterApi flutterApi = new InstabugPigeon.FeatureFlagsFlutterApi(mMessenger);
api = spy(new InstabugApi(mContext, screenshotProvider, flutterApi));
mInstabug = mockStatic(Instabug.class);
mBugReporting = mockStatic(BugReporting.class);
mHostApi = mockStatic(InstabugPigeon.InstabugHostApi.class);
Expand All @@ -87,6 +110,7 @@ public void cleanUp() {
mBugReporting.close();
mHostApi.close();
GlobalMocks.close();

}

@Test
Expand Down Expand Up @@ -349,11 +373,11 @@ public void testClearAllExperiments() {

@Test
public void testAddFeatureFlags() {
Map<String,String > featureFlags = new HashMap<>();
featureFlags.put("key1","variant1");
Map<String, String> featureFlags = new HashMap<>();
featureFlags.put("key1", "variant1");
api.addFeatureFlags(featureFlags);
List<IBGFeatureFlag> flags=new ArrayList<IBGFeatureFlag>();
flags.add(new IBGFeatureFlag("key1","variant1"));
List<IBGFeatureFlag> flags = new ArrayList<IBGFeatureFlag>();
flags.add(new IBGFeatureFlag("key1", "variant1"));
mInstabug.verify(() -> Instabug.addFeatureFlags(flags));
}

Expand Down Expand Up @@ -598,4 +622,25 @@ public void testWillRedirectToStore() {
api.willRedirectToStore();
mInstabug.verify(Instabug::willRedirectToStore);
}


@Test
public void isW3CFeatureFlagsEnabled() {
mockkObject(new InternalCore[]{InternalCore.INSTANCE},false);
Random random=new Random();
Boolean isW3cExternalGeneratedHeaderEnabled = random.nextBoolean();
Boolean isW3cExternalTraceIDEnabled = random.nextBoolean();
Boolean isW3cCaughtHeaderEnabled = random.nextBoolean();

every((Function1<MockKMatcherScope, Boolean>) mockKMatcherScope -> InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER)).returns(isW3cExternalGeneratedHeaderEnabled);
every((Function1<MockKMatcherScope, Boolean>) mockKMatcherScope -> InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID)).returns(isW3cExternalTraceIDEnabled);
every((Function1<MockKMatcherScope, Boolean>) mockKMatcherScope -> InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER)).returns(isW3cCaughtHeaderEnabled);


Map<String, Boolean> flags = api.isW3CFeatureFlagsEnabled();
assertEquals(isW3cExternalGeneratedHeaderEnabled, flags.get("isW3cExternalGeneratedHeaderEnabled"));
assertEquals(isW3cExternalTraceIDEnabled, flags.get("isW3cExternalTraceIDEnabled"));
assertEquals(isW3cCaughtHeaderEnabled, flags.get("isW3cCaughtHeaderEnabled"));

}
}
7 changes: 4 additions & 3 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion flutter.compileSdkVersion
compileSdkVersion 34
ndkVersion flutter.ndkVersion

compileOptions {
Expand All @@ -44,8 +44,8 @@ android {

defaultConfig {
applicationId "com.instabug.flutter.example"
minSdkVersion flutter.minSdkVersion
targetSdkVersion 30
minSdkVersion 21
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand All @@ -59,6 +59,7 @@ android {
signingConfig signingConfigs.debug
}
}
namespace 'com.instabug.flutter.example'

configurations.all {
resolutionStrategy.force 'org.hamcrest:hamcrest-core:1.3'
Expand Down
3 changes: 1 addition & 2 deletions example/android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.instabug.flutter.example">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
Expand Down
Loading