From 1ddc5e38a7a8ca5f6533f2b8b36db3765571853b Mon Sep 17 00:00:00 2001 From: Abdelhamid Nasser <38096011+abdelhamid-f-nasser@users.noreply.github.com> Date: Wed, 17 Jul 2024 19:26:49 +0530 Subject: [PATCH 001/104] feat(example): add apm screen (#1141) --- CHANGELOG.md | 9 ++ examples/default/ios/Podfile.lock | 12 ++ examples/default/package.json | 8 +- examples/default/src/App.tsx | 12 +- .../src/components/ClipboardTextInput.tsx | 36 +++++ .../default/src/components/CustomButton.tsx | 31 ++++ .../default/src/components/CustomImage.tsx | 17 ++ .../default/src/components/CustomText.tsx | 17 ++ .../default/src/components/InputField.tsx | 16 +- .../components/PasteFromClipboardButton.tsx | 24 +++ examples/default/src/navigation/HomeStack.tsx | 15 +- examples/default/src/screens/HomeScreen.tsx | 1 + .../default/src/screens/apm/APMScreen.tsx | 17 ++ .../default/src/screens/apm/FlowsScreen.tsx | 63 ++++++++ .../default/src/screens/apm/NetworkScreen.tsx | 110 +++++++++++++ .../default/src/screens/apm/TracesScreen.tsx | 70 ++++++++ examples/default/yarn.lock | 149 +++++++++++++++++- 17 files changed, 592 insertions(+), 15 deletions(-) create mode 100644 examples/default/src/components/ClipboardTextInput.tsx create mode 100644 examples/default/src/components/CustomButton.tsx create mode 100644 examples/default/src/components/CustomImage.tsx create mode 100644 examples/default/src/components/CustomText.tsx create mode 100644 examples/default/src/components/PasteFromClipboardButton.tsx create mode 100644 examples/default/src/screens/apm/APMScreen.tsx create mode 100644 examples/default/src/screens/apm/FlowsScreen.tsx create mode 100644 examples/default/src/screens/apm/NetworkScreen.tsx create mode 100644 examples/default/src/screens/apm/TracesScreen.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index ba9af205a5..fccae4fc43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,11 @@ - Adds symbol files upload script ([#1137](https://github.com/Instabug/Instabug-React-Native/pull/1137)) - Support enabling NDK crash capturing on Android ([#1132](https://github.com/Instabug/Instabug-React-Native/pull/1132)). +- Add support for App Flows APIs `APM.startFlow`, `APM.setFlowAttribute` and `APM.endFlow` ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). + +### Deprecated + +- Deprecate execution traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setFlowAttribute` in favor of the new app flow APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). ### Deprecated @@ -84,6 +89,10 @@ - Bump Instabug Android SDK to v12.8.0 ([#1149](https://github.com/Instabug/Instabug-React-Native/pull/1149)). [See release notes](https://github.com/Instabug/android/releases/tag/v12.8.0). +### Deprecated + +- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). + ## [12.7.1](https://github.com/Instabug/Instabug-React-Native/compare/v12.7.0...v12.7.1) (February 15, 2024) ### Changed diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index ee026b369c..dcaa1c6971 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -404,6 +404,8 @@ PODS: - React-jsinspector (0.72.3) - React-logger (0.72.3): - glog + - react-native-background-timer (2.4.1): + - React-Core - react-native-config (1.5.1): - react-native-config/App (= 1.5.1) - react-native-config/App (1.5.1): @@ -528,6 +530,8 @@ PODS: - React-jsi (= 0.72.3) - React-logger (= 0.72.3) - React-perflogger (= 0.72.3) + - RNCClipboard (1.5.1): + - React-Core - RNGestureHandler (2.13.4): - RCT-Folly (= 2021.07.22.00) - React-Core @@ -623,6 +627,7 @@ DEPENDENCIES: - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - react-native-background-timer (from `../node_modules/react-native-background-timer`) - react-native-config (from `../node_modules/react-native-config`) - react-native-google-maps (from `../node_modules/react-native-maps`) - react-native-maps (from `../node_modules/react-native-maps`) @@ -645,6 +650,7 @@ DEPENDENCIES: - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNInstabug (from `../node_modules/instabug-reactnative`) - RNReanimated (from `../node_modules/react-native-reanimated`) @@ -720,6 +726,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/jsinspector" React-logger: :path: "../node_modules/react-native/ReactCommon/logger" + react-native-background-timer: + :path: "../node_modules/react-native-background-timer" react-native-config: :path: "../node_modules/react-native-config" react-native-google-maps: @@ -764,6 +772,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/utils" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + RNCClipboard: + :path: "../node_modules/@react-native-community/clipboard" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNInstabug: @@ -818,6 +828,7 @@ SPEC CHECKSUMS: React-jsiexecutor: 59d1eb03af7d30b7d66589c410f13151271e8006 React-jsinspector: b511447170f561157547bc0bef3f169663860be7 React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95 + react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe react-native-config: 86038147314e2e6d10ea9972022aa171e6b1d4d8 react-native-google-maps: 1bcc1f9f13f798fcf230db7fe476f3566d0bc0a3 react-native-maps: 72a8a903f8a1b53e2c777ba79102078ab502e0bf @@ -840,6 +851,7 @@ SPEC CHECKSUMS: React-runtimescheduler: 837c1bebd2f84572db17698cd702ceaf585b0d9a React-utils: bcb57da67eec2711f8b353f6e3d33bd8e4b2efa3 ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 + RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee RNInstabug: 6fa68cd181533f83154df2ebba000d0c47ca7ba3 RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 diff --git a/examples/default/package.json b/examples/default/package.json index 5c6b173c17..529521802d 100644 --- a/examples/default/package.json +++ b/examples/default/package.json @@ -10,14 +10,19 @@ "postinstall": "patch-package" }, "dependencies": { + "@react-native-community/clipboard": "^1.5.1", "@react-native-community/slider": "^4.4.3", "@react-navigation/bottom-tabs": "^6.5.7", "@react-navigation/native": "^6.1.6", "@react-navigation/native-stack": "^6.9.12", + "graphql": "^16.8.1", + "graphql-request": "^6.1.0", "instabug-reactnative": "link:../..", + "instabug-reactnative-ndk": "github:https://github.com/Instabug/Instabug-React-Native-NDK", "native-base": "^3.4.28", "react": "18.2.0", "react-native": "0.72.3", + "react-native-background-timer": "^2.4.1", "react-native-config": "^1.5.1", "react-native-gesture-handler": "^2.13.4", "react-native-maps": "^1.10.3", @@ -26,7 +31,7 @@ "react-native-screens": "^3.20.0", "react-native-svg": "^13.9.0", "react-native-vector-icons": "^10.0.0", - "instabug-reactnative-ndk": "github:https://github.com/Instabug/Instabug-React-Native-NDK" + "react-query": "^3.39.3" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -35,6 +40,7 @@ "@react-native/metro-config": "^0.73.1", "@types/jest": "^29.2.1", "@types/react": "^18.0.24", + "@types/react-native-background-timer": "^2.0.2", "@types/react-native-vector-icons": "^6.4.13", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.2.1", diff --git a/examples/default/src/App.tsx b/examples/default/src/App.tsx index 4bc1447056..d92db633c1 100644 --- a/examples/default/src/App.tsx +++ b/examples/default/src/App.tsx @@ -15,6 +15,10 @@ import { RootTabNavigator } from './navigation/RootTab'; import { nativeBaseTheme } from './theme/nativeBaseTheme'; import { navigationTheme } from './theme/navigationTheme'; +import { QueryClient, QueryClientProvider } from 'react-query'; + +const queryClient = new QueryClient(); + export const App: React.FC = () => { useEffect(() => { Instabug.init({ @@ -32,9 +36,11 @@ export const App: React.FC = () => { return ( - - - + + + + + ); diff --git a/examples/default/src/components/ClipboardTextInput.tsx b/examples/default/src/components/ClipboardTextInput.tsx new file mode 100644 index 0000000000..05d9c35ec6 --- /dev/null +++ b/examples/default/src/components/ClipboardTextInput.tsx @@ -0,0 +1,36 @@ +import React, { PropsWithChildren } from 'react'; +import { StyleProp, StyleSheet, TextStyle } from 'react-native'; +import PasteFromClipboardButton from './PasteFromClipboardButton'; +import { HStack } from 'native-base'; +import { InputField } from './InputField'; + +interface ClipboardTextInputProps extends PropsWithChildren { + placeholder?: string; + onChangeText?: (text: string) => void; + value?: string; + selectTextOnFocus?: boolean; + style?: StyleProp; +} + +export const ClipboardTextInput: React.FC = ({ + onChangeText, + style, + ...restProps +}) => { + return ( + + + + + ); + + function handleClipboardPress(text: string) { + onChangeText?.call(undefined, text); + } +}; + +export const styles = StyleSheet.create({ + inputField: { + flex: 1, + }, +}); diff --git a/examples/default/src/components/CustomButton.tsx b/examples/default/src/components/CustomButton.tsx new file mode 100644 index 0000000000..07bcf9798c --- /dev/null +++ b/examples/default/src/components/CustomButton.tsx @@ -0,0 +1,31 @@ +import React, { PropsWithChildren } from 'react'; +import type { StyleProp, TextStyle } from 'react-native'; +import { Button } from 'native-base'; +import { CustomText } from './CustomText'; +import { StyleSheet } from 'react-native'; + +interface CustomButtonProps extends PropsWithChildren { + title?: string; + onPress?: () => void; + style?: StyleProp; +} + +export const CustomButton: React.FC = ({ + style, + title, + children, + ...restProps +}) => { + return ( + + ); +}; + +export const styles = StyleSheet.create({ + text: { + color: '#fff', + }, +}); diff --git a/examples/default/src/components/CustomImage.tsx b/examples/default/src/components/CustomImage.tsx new file mode 100644 index 0000000000..5c5d051ebe --- /dev/null +++ b/examples/default/src/components/CustomImage.tsx @@ -0,0 +1,17 @@ +import React, { PropsWithChildren } from 'react'; +import { StyleProp, StyleSheet, TextStyle, Text } from 'react-native'; + +interface CustomTextProps extends PropsWithChildren { + style?: StyleProp; +} + +export const CustomImage: React.FC = ({ style, children }) => { + return {children}; +}; + +export const styles = StyleSheet.create({ + text: { + fontSize: 16, + lineHeight: 24, + }, +}); diff --git a/examples/default/src/components/CustomText.tsx b/examples/default/src/components/CustomText.tsx new file mode 100644 index 0000000000..5e36221280 --- /dev/null +++ b/examples/default/src/components/CustomText.tsx @@ -0,0 +1,17 @@ +import React, { PropsWithChildren } from 'react'; +import { StyleProp, StyleSheet, TextStyle, Text } from 'react-native'; + +interface CustomTextProps extends PropsWithChildren { + style?: StyleProp; +} + +export const CustomText: React.FC = ({ style, children }) => { + return {children}; +}; + +export const styles = StyleSheet.create({ + text: { + fontSize: 16, + lineHeight: 24, + }, +}); diff --git a/examples/default/src/components/InputField.tsx b/examples/default/src/components/InputField.tsx index 1a5700c27c..feef8fd7b5 100644 --- a/examples/default/src/components/InputField.tsx +++ b/examples/default/src/components/InputField.tsx @@ -1,13 +1,22 @@ import React, { forwardRef } from 'react'; -import { KeyboardTypeOptions, StyleSheet, TextInput, View } from 'react-native'; +import { + KeyboardTypeOptions, + StyleProp, + StyleSheet, + TextInput, + ViewStyle, + View, +} from 'react-native'; import { Text } from 'native-base'; interface InputFieldProps { placeholder?: string; value?: string; + style?: StyleProp; onChangeText?: (text: string) => void; keyboardType?: KeyboardTypeOptions; + selectTextOnFocus?: boolean | undefined; errorText?: string; maxLength?: number; accessibilityLabel?: string; @@ -19,6 +28,7 @@ export const InputField = forwardRef( { placeholder, value, + style, onChangeText, accessibilityLabel, maxLength, @@ -33,7 +43,7 @@ export const InputField = forwardRef( void; + style?: StyleProp; +} + +const PasteFromClipboardButton: React.FC = ({ onPress, style }) => { + const handlePress = async () => { + const text = await Clipboard.getString(); + onPress?.call(undefined, text); // Using call to pass the text to the callback + }; + + return ( + + + + ); +}; + +export default PasteFromClipboardButton; diff --git a/examples/default/src/navigation/HomeStack.tsx b/examples/default/src/navigation/HomeStack.tsx index 184e36f03d..b4a8ca3e69 100644 --- a/examples/default/src/navigation/HomeStack.tsx +++ b/examples/default/src/navigation/HomeStack.tsx @@ -21,6 +21,10 @@ import { } from '../screens/user-steps/BackAndForthScreen'; import { GoogleMapsScreen } from '../screens/user-steps/GoogleMapsScreen'; import { LargeImageListScreen } from '../screens/user-steps/LargeImageListScreen'; +import { APMScreen } from '../screens/apm/APMScreen'; +import { TracesScreen } from '../screens/apm/TracesScreen'; +import { NetworkScreen } from '../screens/apm/NetworkScreen'; +import { FlowsScreen } from '../screens/apm/FlowsScreen'; import { SessionReplayScreen } from '../screens/SessionReplayScreen'; export type HomeStackParamList = { @@ -41,6 +45,12 @@ export type HomeStackParamList = { LargeImageList: undefined; SessionReplay: undefined; BackAndForthScreen: BackAndForthScreenProp; + + // APM // + APM: undefined; + NetworkTraces: undefined; + ExecutionTraces: undefined; + AppFlows: undefined; }; const HomeStack = createNativeStackNavigator(); @@ -65,7 +75,6 @@ export const HomeStackNavigator: React.FC = () => { options={{ title: 'Feature Requests' }} /> - { options={{ title: 'Large Image List' }} /> + + + + ); }; diff --git a/examples/default/src/screens/HomeScreen.tsx b/examples/default/src/screens/HomeScreen.tsx index 086dc0650f..690d41cc2d 100644 --- a/examples/default/src/screens/HomeScreen.tsx +++ b/examples/default/src/screens/HomeScreen.tsx @@ -17,6 +17,7 @@ export const HomeScreen: React.FC navigation.navigate('Replies')} /> navigation.navigate('Surveys')} /> navigation.navigate('UserSteps')} /> + navigation.navigate('APM')} /> navigation.navigate('SessionReplay')} /> ); diff --git a/examples/default/src/screens/apm/APMScreen.tsx b/examples/default/src/screens/apm/APMScreen.tsx new file mode 100644 index 0000000000..2bc4dbca0d --- /dev/null +++ b/examples/default/src/screens/apm/APMScreen.tsx @@ -0,0 +1,17 @@ +import type { NativeStackScreenProps } from '@react-navigation/native-stack'; +import type { HomeStackParamList } from '../../navigation/HomeStack'; +import React from 'react'; +import { ListTile } from '../../components/ListTile'; +import { Screen } from '../../components/Screen'; + +export const APMScreen: React.FC> = ({ + navigation, +}) => { + return ( + + navigation.navigate('NetworkTraces')} /> + navigation.navigate('ExecutionTraces')} /> + navigation.navigate('AppFlows')} /> + + ); +}; diff --git a/examples/default/src/screens/apm/FlowsScreen.tsx b/examples/default/src/screens/apm/FlowsScreen.tsx new file mode 100644 index 0000000000..be9b0fec70 --- /dev/null +++ b/examples/default/src/screens/apm/FlowsScreen.tsx @@ -0,0 +1,63 @@ +import React, { useState } from 'react'; +import { APM } from 'instabug-reactnative'; +import { ScrollView } from 'react-native'; +import { Section } from '../../components/Section'; +import { Screen } from '../../components/Screen'; +import { VStack } from 'native-base'; +import { InputField } from '../../components/InputField'; +import { CustomButton } from '../../components/CustomButton'; +import BackgroundTimer from 'react-native-background-timer'; + +export const FlowsScreen: React.FC = () => { + const [flowName, setFlowName] = useState(''); + const [flowAttributeKey, setFlowAttributeKey] = useState(''); + const [flowAttributeValue, setFlowAttributeValue] = useState(''); + + async function startFlow() { + return APM.startFlow(flowName); + } + + async function startDelayedFlow() { + return BackgroundTimer.setTimeout(() => { + APM.startFlow(flowName); + }, 5000); + } + + function setFlowAttribute() { + return APM.setFlowAttribute(flowName, flowAttributeKey, flowAttributeValue); + } + + function endFlow() { + APM.endFlow(flowName); + } + + return ( + + +
+ + setFlowName(text)} + value={flowName} + /> + + + setFlowAttributeKey(text)} + value={flowAttributeKey} + /> + setFlowAttributeValue(text)} + value={flowAttributeValue} + /> + + + +
+
+
+ ); +}; diff --git a/examples/default/src/screens/apm/NetworkScreen.tsx b/examples/default/src/screens/apm/NetworkScreen.tsx new file mode 100644 index 0000000000..467a621f21 --- /dev/null +++ b/examples/default/src/screens/apm/NetworkScreen.tsx @@ -0,0 +1,110 @@ +import React, { useState } from 'react'; +import { Image, ScrollView, StyleSheet, Text, useWindowDimensions, View } from 'react-native'; +import { Section } from '../../components/Section'; +import { Screen } from '../../components/Screen'; +import { ClipboardTextInput } from '../../components/ClipboardTextInput'; +import { useQuery } from 'react-query'; +import { HStack, VStack } from 'native-base'; +import { gql, request } from 'graphql-request'; +import { CustomButton } from '../../components/CustomButton'; + +export const NetworkScreen: React.FC = () => { + const [endpointUrl, setEndpointUrl] = useState(''); + const { width, height } = useWindowDimensions(); + const defaultRequestUrl = 'https://jsonplaceholder.typicode.com/posts/1'; + const imageUrls = [ + 'https://fastly.picsum.photos/id/57/200/300.jpg?hmac=l908G1qVr4r7dP947-tak2mY8Vvic_vEYzCXUCKKskY', + 'https://fastly.picsum.photos/id/619/200/300.jpg?hmac=WqBGwlGjuY9RCdpzRaG9G-rc9Fi7TGUINX_-klAL2kA', + ]; + + async function sendRequestToUrl() { + let urlToSend = ''; + + if (endpointUrl.trim() !== '') { + urlToSend = endpointUrl; + console.log('Sending request to: ', endpointUrl); + } else { + // Use json placeholder URL as a default if endpointUrl is empty + console.log('sending request to default json placeholder'); + urlToSend = defaultRequestUrl; + } + + try { + // Perform the request using the urlToSend + const response = await fetch(urlToSend); + const data = await response.json(); + + // Format the JSON response for better logging + const formattedData = JSON.stringify(data, null, 2); + + // Log the formatted response + console.log('Response:', formattedData); + } catch (error) { + // Handle errors appropriately + console.error('Error:', error); + } + } + + const fetchGraphQlData = async () => { + const document = gql` + query { + country(code: "EG") { + emoji + name + } + } + `; + + return request<{ country: { emoji: string; name: string } }>( + 'https://countries.trevorblades.com/graphql', + document, + ); + }; + + const { data, isError, isSuccess, isLoading, refetch } = useQuery('helloQuery', fetchGraphQlData); + + return ( + + +
+ + setEndpointUrl(text)} + selectTextOnFocus={true} + value={endpointUrl} + /> + + refetch} title="Reload GraphQL" /> + + {isLoading && Loading...} + {isSuccess && GraphQL Data: {data.country.emoji}} + {isError && Error!} + + +
+
+ + {imageUrls.map((imageUrl) => ( + + ))} + +
+
+
+ ); +}; +const styles = StyleSheet.create({ + image: { + resizeMode: 'contain', + }, + // Todo: Text Component + // Todo: Button Component + // Todo: Image Component +}); diff --git a/examples/default/src/screens/apm/TracesScreen.tsx b/examples/default/src/screens/apm/TracesScreen.tsx new file mode 100644 index 0000000000..bd3e41838a --- /dev/null +++ b/examples/default/src/screens/apm/TracesScreen.tsx @@ -0,0 +1,70 @@ +import React, { useState } from 'react'; +import { APM, Trace } from 'instabug-reactnative'; +import { ScrollView } from 'react-native'; +import { Section } from '../../components/Section'; +import { Screen } from '../../components/Screen'; +import { VStack } from 'native-base'; +import { InputField } from '../../components/InputField'; +import { CustomButton } from '../../components/CustomButton'; +import BackgroundTimer from 'react-native-background-timer'; + +export const TracesScreen: React.FC = () => { + const [traceName, setTraceName] = useState(''); + const [traceAttributeKey, setTraceAttributeKey] = useState(''); + const [traceAttributeValue, setTraceAttributeValue] = useState(''); + let executionTrace: Trace; + + async function startTrace() { + executionTrace = await APM.startExecutionTrace(traceName ?? ''); + } + + async function startDelayedTrace() { + return BackgroundTimer.setTimeout(async () => { + executionTrace = await APM.startExecutionTrace(traceName ?? ''); + }, 5000); + } + + function setTraceAttribute() { + if (!executionTrace) { + console.log('Please, start a trace before setting attributes.'); + } + return executionTrace.setAttribute(traceAttributeKey ?? '', traceAttributeValue ?? ''); + } + + function endExecutionTrace() { + if (!executionTrace) { + console.log('Please, start a trace before ending it.'); + } + return executionTrace.end(); + } + + return ( + + +
+ + setTraceName(text)} + value={traceName} + /> + + + setTraceAttributeKey(text)} + value={traceAttributeKey} + /> + setTraceAttributeValue(text)} + value={traceAttributeValue} + /> + + + +
+
+
+ ); +}; diff --git a/examples/default/yarn.lock b/examples/default/yarn.lock index e388f66821..74f7ce0e3b 100644 --- a/examples/default/yarn.lock +++ b/examples/default/yarn.lock @@ -1279,6 +1279,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.23.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2": + version "7.23.9" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" + integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.0.0", "@babel/template@^7.22.5", "@babel/template@^7.3.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -1391,6 +1398,11 @@ dependencies: tslib "^2.4.0" +"@graphql-typed-document-node/core@^3.2.0": + version "3.2.0" + resolved "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -2313,6 +2325,11 @@ prompts "^2.4.0" semver "^6.3.0" +"@react-native-community/clipboard@^1.5.1": + version "1.5.1" + resolved "https://registry.npmjs.org/@react-native-community/clipboard/-/clipboard-1.5.1.tgz#32abb3ea2eb91ee3f9c5fb1d32d5783253c9fabe" + integrity sha512-AHAmrkLEH5UtPaDiRqoULERHh3oNv7Dgs0bTC0hO5Z2GdNokAMPT5w8ci8aMcRemcwbtdHjxChgtjbeA38GBdA== + "@react-native-community/slider@^4.4.3": version "4.4.3" resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-4.4.3.tgz#9b9dc639b88f5bfda72bd72a9dff55cbf9f777ed" @@ -3018,6 +3035,11 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== +"@types/react-native-background-timer@^2.0.2": + version "2.0.2" + resolved "https://registry.npmjs.org/@types/react-native-background-timer/-/react-native-background-timer-2.0.2.tgz#22f9126124068a0ee6a812e16f98e270c2b9b2c7" + integrity sha512-cMAep0M5yqUHjiiRPvGiviqiJYdI45KSjbI5ufsIFSQGFwHwrHJC/8yawNhy0G3Gix6fufWLsEj6jC5niUNHiQ== + "@types/react-native-vector-icons@^6.4.13": version "6.4.13" resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.13.tgz#28b34d15094e040718beefb67cb3eff0c4994cb6" @@ -3366,6 +3388,11 @@ base64-js@^1.1.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +big-integer@^1.6.16: + version "1.6.52" + resolved "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -3407,6 +3434,20 @@ braces@^3.0.2: dependencies: fill-range "^7.0.1" +broadcast-channel@^3.4.1: + version "3.7.0" + resolved "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937" + integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg== + dependencies: + "@babel/runtime" "^7.7.2" + detect-node "^2.1.0" + js-sha3 "0.8.0" + microseconds "0.2.0" + nano-time "1.0.0" + oblivious-set "1.0.0" + rimraf "3.0.2" + unload "2.2.0" + browser-process-hrtime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" @@ -3780,6 +3821,13 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: js-yaml "^3.13.1" parse-json "^4.0.0" +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -3922,6 +3970,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +detect-node@^2.0.4, detect-node@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + detox@^20.9.0: version "20.11.2" resolved "https://registry.yarnpkg.com/detox/-/detox-20.11.2.tgz#7628ad7909b343069e164fbada428ac12464eb67" @@ -4415,6 +4468,19 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +graphql-request@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f" + integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + cross-fetch "^3.1.5" + +graphql@^16.8.1: + version "16.8.1" + resolved "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" + integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -5180,6 +5246,11 @@ js-queue@2.0.2: dependencies: easy-stack "^1.0.1" +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -5496,6 +5567,14 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +match-sorter@^6.0.2: + version "6.3.4" + resolved "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz#afa779d8e922c81971fbcb4781c7003ace781be7" + integrity sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg== + dependencies: + "@babel/runtime" "^7.23.8" + remove-accents "0.5.0" + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -6016,6 +6095,11 @@ micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" +microseconds@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" + integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== + mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -6116,6 +6200,13 @@ nan@^2.14.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== +nano-time@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" + integrity sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA== + dependencies: + big-integer "^1.6.16" + nanoid@^3.1.23: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" @@ -6206,6 +6297,13 @@ node-fetch@^2.2.0, node-fetch@^2.6.0: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -6279,6 +6377,11 @@ object-keys@^1.1.1: resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== +oblivious-set@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" + integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -6626,6 +6729,11 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-native-background-timer@^2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/react-native-background-timer/-/react-native-background-timer-2.4.1.tgz#a3bc1cafa8c1e3aeefd0611de120298b67978a0f" + integrity sha512-TE4Kiy7jUyv+hugxDxitzu38sW1NqjCk4uE5IgU2WevLv7sZacaBc6PZKOShNRPGirLl1NWkaG3LDEkdb9Um5g== + react-native-config@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/react-native-config/-/react-native-config-1.5.1.tgz#73c94f511493e9b7ff9350cdf351d203a1b05acc" @@ -6730,6 +6838,15 @@ react-native@0.72.3: ws "^6.2.2" yargs "^17.6.2" +react-query@^3.39.3: + version "3.39.3" + resolved "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz#4cea7127c6c26bdea2de5fb63e51044330b03f35" + integrity sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g== + dependencies: + "@babel/runtime" "^7.5.5" + broadcast-channel "^3.4.1" + match-sorter "^6.0.2" + react-refresh@^0.14.0: version "0.14.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" @@ -6818,6 +6935,11 @@ regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.2: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regenerator-transform@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" @@ -6844,6 +6966,11 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" +remove-accents@0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz#77991f37ba212afba162e375b627631315bed687" + integrity sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -6903,6 +7030,13 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== +rimraf@3.0.2, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rimraf@^2.6.3: version "2.7.1" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -6910,13 +7044,6 @@ rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - rimraf@~2.4.0: version "2.4.5" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" @@ -7490,6 +7617,14 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unload@2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" + integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== + dependencies: + "@babel/runtime" "^7.6.2" + detect-node "^2.0.4" + unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" From 0222c64f730ccd9f2dd8e29615a35c7da9ae3224 Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:58:56 +0300 Subject: [PATCH 002/104] fix(android): resolve an OOM in network logs (#1244) --- CHANGELOG.md | 6 + .../reactlibrary/RNInstabugAPMModule.java | 84 ++++--- .../RNInstabugReactnativeModule.java | 55 +++-- .../ios/InstabugTests/InstabugSampleTests.m | 56 +++++ ios/RNInstabug/InstabugReactBridge.h | 17 ++ ios/RNInstabug/InstabugReactBridge.m | 93 +++---- ios/RNInstabug/Util/IBGNetworkLogger+CP.h | 16 ++ src/modules/NetworkLogger.ts | 34 ++- src/native/NativeAPM.ts | 19 +- src/native/NativeInstabug.ts | 32 ++- src/utils/InstabugConstants.ts | 13 +- src/utils/InstabugUtils.ts | 72 ++++++ src/utils/XhrNetworkInterceptor.ts | 8 +- test/mocks/mockAPM.ts | 2 +- test/mocks/mockInstabug.ts | 3 +- test/mocks/mockInstabugUtils.ts | 2 + test/modules/NetworkLogger.spec.ts | 228 ++++++++++++------ test/utils/InstabugUtils.spec.ts | 98 +++++++- 18 files changed, 621 insertions(+), 217 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fccae4fc43..7ec9aad5b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...dev) + +### Fixed + +- Fix an OOM (out-of-memory) crash while saving network logs on Android ([#1244](https://github.com/Instabug/Instabug-React-Native/pull/1244)). + ## [13.2.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.1.1...v13.2.0) (July 7, 2024) ### Changed diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index d7662c6536..7ffaf4de73 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -5,6 +5,8 @@ import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -312,56 +314,58 @@ public void run() { }); } - /** - * Send Apm network log by Reflection - */ @ReactMethod - public void networkLog(String networkData) throws JSONException { - try{ - APMNetworkLogger apmNetworkLogger = new APMNetworkLogger(); - JSONObject jsonObject = new JSONObject(networkData); - final String requestUrl = (String) jsonObject.get("url"); - final String requestBody = (String) jsonObject.get("requestBody"); - final String responseBody = (String) jsonObject.get("responseBody"); - final String requestMethod = (String) jsonObject.get("method"); - //-------------------------------------------- - final String requestContentType = (String) jsonObject.get("requestContentType"); - final String responseContentType = (String) jsonObject.get("contentType"); - //-------------------------------------------- - final long requestBodySize = ((Number) jsonObject.get("requestBodySize")).longValue(); - final long responseBodySize = ((Number) jsonObject.get("responseBodySize")).longValue(); - //-------------------------------------------- - final String errorDomain = (String) jsonObject.get("errorDomain"); - final Integer statusCode = (Integer) jsonObject.get("responseCode"); - final long requestDuration = ((Number) jsonObject.get("duration")).longValue(); - final long requestStartTime = ((Number) jsonObject.get("startTime")).longValue() * 1000; - final String requestHeaders = (String) jsonObject.get("requestHeaders").toString(); - final String responseHeaders = (String) jsonObject.get("responseHeaders").toString(); - final String errorMessage; - if(errorDomain.equals("")) { - errorMessage = null; - } else { - errorMessage = errorDomain; - } - //-------------------------------------------- - String gqlQueryName = null; - if(jsonObject.has("gqlQueryName")){ - gqlQueryName = (String) jsonObject.get("gqlQueryName"); - } - final String serverErrorMessage = (String) jsonObject.get("serverErrorMessage"); + private void networkLogAndroid(final double requestStartTime, + final double requestDuration, + final String requestHeaders, + final String requestBody, + final double requestBodySize, + final String requestMethod, + final String requestUrl, + final String requestContentType, + final String responseHeaders, + final String responseBody, + final double responseBodySize, + final double statusCode, + final String responseContentType, + @Nullable final String errorDomain, + @Nullable final String gqlQueryName, + @Nullable final String serverErrorMessage) { + try { + APMNetworkLogger networkLogger = new APMNetworkLogger(); + + final boolean hasError = errorDomain != null && !errorDomain.isEmpty(); + final String errorMessage = hasError ? errorDomain : null; try { Method method = 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); if (method != null) { - method.invoke(apmNetworkLogger, requestStartTime, requestDuration, requestHeaders, requestBody, requestBodySize, requestMethod, requestUrl, requestContentType, responseHeaders, responseBody, responseBodySize, statusCode, responseContentType, errorMessage, gqlQueryName, serverErrorMessage); + method.invoke( + networkLogger, + requestStartTime, + requestDuration, + requestHeaders, + requestBody, + requestBodySize, + requestMethod, + requestUrl, + requestContentType, + responseHeaders, + responseBody, + responseBodySize, + statusCode, + responseContentType, + errorMessage, + gqlQueryName, + serverErrorMessage + ); } else { - Log.e("IB-CP-Bridge", "apmNetworkLogByReflection was not found by reflection"); + Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); } } catch (Throwable e) { e.printStackTrace(); } - } - catch(Throwable e) { + } catch(Throwable e) { e.printStackTrace(); } } diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index c056f15831..7d14656089 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -5,6 +5,7 @@ import android.app.Application; import android.graphics.Bitmap; import android.net.Uri; +import android.util.Log; import android.view.View; import androidx.annotation.UiThread; @@ -34,6 +35,7 @@ import com.instabug.library.model.NetworkLog; import com.instabug.library.model.Report; import com.instabug.library.ui.onboarding.WelcomeMessage; +import com.instabug.library.util.InstabugSDKLogger; import com.instabug.reactlibrary.utils.ArrayUtil; import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; @@ -60,7 +62,7 @@ */ public class RNInstabugReactnativeModule extends EventEmitterModule { - private static final String TAG = RNInstabugReactnativeModule.class.getSimpleName(); + private static final String TAG = "IBG-RN-Core"; private InstabugCustomTextPlaceHolder placeHolders; private static Report currentReport; @@ -895,27 +897,38 @@ public void run() { }); } - /** - * Extracts HTTP connection properties. Request method, Headers, Date, Url and Response code - * - * @param jsonObject the JSON object containing all HTTP connection properties - * @throws JSONException - */ @ReactMethod - public void networkLog(String jsonObject) throws JSONException { - NetworkLog networkLog = new NetworkLog(); - String date = System.currentTimeMillis()+""; - networkLog.setDate(date); - JSONObject newJSONObject = new JSONObject(jsonObject); - networkLog.setUrl(newJSONObject.getString("url")); - networkLog.setRequest(newJSONObject.getString("requestBody")); - networkLog.setResponse(newJSONObject.getString("responseBody")); - networkLog.setMethod(newJSONObject.getString("method")); - networkLog.setResponseCode(newJSONObject.getInt("responseCode")); - networkLog.setRequestHeaders(newJSONObject.getString("requestHeaders")); - networkLog.setResponseHeaders(newJSONObject.getString("responseHeaders")); - networkLog.setTotalDuration(newJSONObject.getLong("duration")); - networkLog.insert(); + public void networkLogAndroid(final String url, + final String requestBody, + final String responseBody, + final String method, + final double responseCode, + final String requestHeaders, + final String responseHeaders, + final double duration) { + try { + final String date = String.valueOf(System.currentTimeMillis()); + + NetworkLog networkLog = new NetworkLog(); + networkLog.setDate(date); + networkLog.setUrl(url); + networkLog.setMethod(method); + networkLog.setResponseCode((int) responseCode); + networkLog.setTotalDuration((long) duration); + + try { + networkLog.setRequest(requestBody); + networkLog.setResponse(responseBody); + networkLog.setRequestHeaders(requestHeaders); + networkLog.setResponseHeaders(responseHeaders); + } catch (OutOfMemoryError | Exception exception) { + Log.d(TAG, "Error: " + exception.getMessage() + "while trying to set network log contents (request body, response body, request headers, and response headers)."); + } + + networkLog.insert(); + } catch (OutOfMemoryError | Exception exception) { + Log.d(TAG, "Error: " + exception.getMessage() + "while trying to insert a network log"); + } } @UiThread diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index bf4edbd434..37990b450c 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -13,6 +13,7 @@ #import #import "IBGConstants.h" #import "RNInstabug.h" +#import @protocol InstabugCPTestProtocol /** @@ -313,6 +314,61 @@ - (void)testSetWelcomeMessageMode { OCMVerify([mock setWelcomeMessageMode:welcomeMessageMode]); } +- (void)testNetworkLogIOS { + id mIBGNetworkLogger = OCMClassMock([IBGNetworkLogger class]); + + NSString *url = @"https://api.instabug.com"; + NSString *method = @"GET"; + NSString *requestBody = @"requestBody"; + double requestBodySize = 10; + NSString *responseBody = @"responseBody"; + double responseBodySize = 15; + double responseCode = 200; + NSDictionary *requestHeaders = @{ @"accept": @"application/json" }; + NSDictionary *responseHeaders = @{ @"cache-control": @"no-store" }; + NSString *contentType = @"application/json"; + double errorCode = 0; + NSString *errorDomain = nil; + double startTime = 1719847101199; + double duration = 150; + NSString *gqlQueryName = nil; + NSString *serverErrorMessage = nil; + + [self.instabugBridge networkLogIOS:url + method:method + requestBody:requestBody + requestBodySize:requestBodySize + responseBody:responseBody + responseBodySize:responseBodySize + responseCode:responseCode + requestHeaders:requestHeaders + responseHeaders:responseHeaders + contentType:contentType + errorDomain:errorDomain + errorCode:errorCode + startTime:startTime + duration:duration + gqlQueryName:gqlQueryName + serverErrorMessage:serverErrorMessage]; + + OCMVerify([mIBGNetworkLogger addNetworkLogWithUrl:url + method:method + requestBody:requestBody + requestBodySize:requestBodySize + responseBody:responseBody + responseBodySize:responseBodySize + responseCode:responseCode + requestHeaders:requestHeaders + responseHeaders:responseHeaders + contentType:contentType + errorDomain:errorDomain + errorCode:errorCode + startTime:startTime * 1000 + duration:duration * 1000 + gqlQueryName:gqlQueryName + serverErrorMessage:serverErrorMessage]); +} + - (void)testSetFileAttachment { id mock = OCMClassMock([Instabug class]); NSString *fileLocation = @"test"; diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index 9e9a8db489..5da9b9cc71 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -107,6 +107,23 @@ - (void)setNetworkLoggingEnabled:(BOOL)isEnabled; +- (void)networkLogIOS:(NSString * _Nonnull)url + method:(NSString * _Nonnull)method + requestBody:(NSString * _Nonnull)requestBody + requestBodySize:(double)requestBodySize + responseBody:(NSString * _Nonnull)responseBody + responseBodySize:(double)responseBodySize + responseCode:(double)responseCode + requestHeaders:(NSDictionary * _Nonnull)requestHeaders + responseHeaders:(NSDictionary * _Nonnull)responseHeaders + contentType:(NSString * _Nonnull)contentType + errorDomain:(NSString * _Nullable)errorDomain + errorCode:(double)errorCode + startTime:(double)startTime + duration:(double)duration + gqlQueryName:(NSString * _Nullable)gqlQueryName + serverErrorMessage:(NSString * _Nullable)serverErrorMessage; + /* +------------------------------------------------------------------------+ | Experiments | diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index 01dd41aa87..2f2b24f27a 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -15,6 +15,7 @@ #import #import #import "RNInstabug.h" +#import "Util/IBGNetworkLogger+CP.h" @interface Instabug (PrivateWillSendAPI) + (void)setWillSendReportHandler_private:(void(^)(IBGReport *report, void(^reportCompletionHandler)(IBGReport *)))willSendReportHandler_private; @@ -283,66 +284,38 @@ - (dispatch_queue_t)methodQueue { } } -RCT_EXPORT_METHOD(networkLog:(NSDictionary *) networkData) { - NSString* url = networkData[@"url"]; - NSString* method = networkData[@"method"]; - NSString* requestBody = networkData[@"requestBody"]; - int64_t requestBodySize = [networkData[@"requestBodySize"] integerValue]; - NSString* responseBody = nil; - if (networkData[@"responseBody"] != [NSNull null]) { - responseBody = networkData[@"responseBody"]; - } - int64_t responseBodySize = [networkData[@"responseBodySize"] integerValue]; - int32_t responseCode = [networkData[@"responseCode"] integerValue]; - NSDictionary* requestHeaders = @{}; - if([networkData[@"requestHeaders"] isKindOfClass:[NSDictionary class]]){ - requestHeaders = networkData[@"requestHeaders"]; - } - NSDictionary* responseHeaders = @{}; - if([networkData[@"responseHeaders"] isKindOfClass:[NSDictionary class]]){ - responseHeaders = networkData[@"responseHeaders"]; - } - NSString* contentType = networkData[@"contentType"]; - NSString* errorDomain = networkData[@"errorDomain"]; - int32_t errorCode = [networkData[@"errorCode"] integerValue]; - int64_t startTime = [networkData[@"startTime"] integerValue] * 1000; - int64_t duration = [networkData[@"duration"] doubleValue] * 1000; - - NSString* gqlQueryName = nil; - NSString* serverErrorMessage = nil; - if (networkData[@"gqlQueryName"] != [NSNull null]) { - gqlQueryName = networkData[@"gqlQueryName"]; - } - if (networkData[@"serverErrorMessage"] != [NSNull null]) { - serverErrorMessage = networkData[@"serverErrorMessage"]; - } - - SEL networkLogSEL = NSSelectorFromString(@"addNetworkLogWithUrl:method:requestBody:requestBodySize:responseBody:responseBodySize:responseCode:requestHeaders:responseHeaders:contentType:errorDomain:errorCode:startTime:duration:gqlQueryName:serverErrorMessage:"); - - if([[IBGNetworkLogger class] respondsToSelector:networkLogSEL]) { - NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[[IBGNetworkLogger class] methodSignatureForSelector:networkLogSEL]]; - [inv setSelector:networkLogSEL]; - [inv setTarget:[IBGNetworkLogger class]]; - - [inv setArgument:&(url) atIndex:2]; - [inv setArgument:&(method) atIndex:3]; - [inv setArgument:&(requestBody) atIndex:4]; - [inv setArgument:&(requestBodySize) atIndex:5]; - [inv setArgument:&(responseBody) atIndex:6]; - [inv setArgument:&(responseBodySize) atIndex:7]; - [inv setArgument:&(responseCode) atIndex:8]; - [inv setArgument:&(requestHeaders) atIndex:9]; - [inv setArgument:&(responseHeaders) atIndex:10]; - [inv setArgument:&(contentType) atIndex:11]; - [inv setArgument:&(errorDomain) atIndex:12]; - [inv setArgument:&(errorCode) atIndex:13]; - [inv setArgument:&(startTime) atIndex:14]; - [inv setArgument:&(duration) atIndex:15]; - [inv setArgument:&(gqlQueryName) atIndex:16]; - [inv setArgument:&(serverErrorMessage) atIndex:17]; - - [inv invoke]; - } +RCT_EXPORT_METHOD(networkLogIOS:(NSString * _Nonnull)url + method:(NSString * _Nonnull)method + requestBody:(NSString * _Nonnull)requestBody + requestBodySize:(double)requestBodySize + responseBody:(NSString * _Nonnull)responseBody + responseBodySize:(double)responseBodySize + responseCode:(double)responseCode + requestHeaders:(NSDictionary * _Nonnull)requestHeaders + responseHeaders:(NSDictionary * _Nonnull)responseHeaders + contentType:(NSString * _Nonnull)contentType + errorDomain:(NSString * _Nullable)errorDomain + errorCode:(double)errorCode + startTime:(double)startTime + duration:(double)duration + gqlQueryName:(NSString * _Nullable)gqlQueryName + serverErrorMessage:(NSString * _Nullable)serverErrorMessage) { + [IBGNetworkLogger addNetworkLogWithUrl:url + method:method + requestBody:requestBody + requestBodySize:requestBodySize + responseBody:responseBody + responseBodySize:responseBodySize + responseCode:responseCode + requestHeaders:requestHeaders + responseHeaders:responseHeaders + contentType:contentType + errorDomain:errorDomain + errorCode:errorCode + startTime:startTime * 1000 + duration:duration * 1000 + gqlQueryName:gqlQueryName + serverErrorMessage:serverErrorMessage]; } RCT_EXPORT_METHOD(addPrivateView: (nonnull NSNumber *)reactTag) { diff --git a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h index ae5d32d669..5ae464785f 100644 --- a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h +++ b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h @@ -5,6 +5,22 @@ NS_ASSUME_NONNULL_BEGIN @interface IBGNetworkLogger (CP) + (void)disableAutomaticCapturingOfNetworkLogs; ++ (void)addNetworkLogWithUrl:(NSString *)url + method:(NSString *)method + requestBody:(NSString *)request + requestBodySize:(int64_t)requestBodySize + responseBody:(NSString *)response + responseBodySize:(int64_t)responseBodySize + responseCode:(int32_t)code + requestHeaders:(NSDictionary *)requestHeaders + responseHeaders:(NSDictionary *)responseHeaders + contentType:(NSString *)contentType + errorDomain:(NSString *)errorDomain + errorCode:(int32_t)errorCode + startTime:(int64_t)startTime + duration:(int64_t) duration + gqlQueryName:(NSString * _Nullable)gqlQueryName + serverErrorMessage:(NSString * _Nullable)serverErrorMessage; @end diff --git a/src/modules/NetworkLogger.ts b/src/modules/NetworkLogger.ts index 8e102e3ab3..67f3a54ccf 100644 --- a/src/modules/NetworkLogger.ts +++ b/src/modules/NetworkLogger.ts @@ -1,11 +1,8 @@ -import { Platform } from 'react-native'; - import type { RequestHandler } from '@apollo/client'; -import { NativeAPM } from '../native/NativeAPM'; -import { NativeInstabug } from '../native/NativeInstabug'; import InstabugConstants from '../utils/InstabugConstants'; import xhr, { NetworkData, ProgressCallback } from '../utils/XhrNetworkInterceptor'; +import { reportNetworkLog, isContentTypeNotAllowed } from '../utils/InstabugUtils'; export type { NetworkData }; @@ -30,12 +27,31 @@ export const setEnabled = (isEnabled: boolean) => { network = await _networkDataObfuscationHandler(network); } - if (Platform.OS === 'android') { - NativeInstabug.networkLog(JSON.stringify(network)); - NativeAPM.networkLog(JSON.stringify(network)); - } else { - NativeInstabug.networkLog(network); + if (network.requestBodySize > InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES) { + network.requestBody = InstabugConstants.MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE; + console.warn('IBG-RN:', InstabugConstants.MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE); + } + + if (network.responseBodySize > InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES) { + network.responseBody = InstabugConstants.MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE; + console.warn('IBG-RN:', InstabugConstants.MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE); + } + + if (network.requestBody && isContentTypeNotAllowed(network.requestContentType)) { + network.requestBody = `Body is omitted because content type ${network.requestContentType} isn't supported`; + console.warn( + `IBG-RN: The request body for the network request with URL ${network.url} has been omitted because the content type ${network.requestContentType} isn't supported.`, + ); + } + + if (network.responseBody && isContentTypeNotAllowed(network.contentType)) { + network.responseBody = `Body is omitted because content type ${network.contentType} isn't supported`; + console.warn( + `IBG-RN: The response body for the network request with URL ${network.url} has been omitted because the content type ${network.contentType} isn't supported.`, + ); } + + reportNetworkLog(network); } catch (e) { console.error(e); } diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 2c2121587c..b1981cfe37 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -7,7 +7,24 @@ export interface ApmNativeModule extends NativeModule { setEnabled(isEnabled: boolean): void; // Network APIs // - networkLog(data: string): void; + networkLogAndroid( + requestStartTime: number, + requestDuration: number, + requestHeaders: string, + requestBody: string, + requestBodySize: number, + requestMethod: string, + requestUrl: string, + requestContentType: string, + responseHeaders: string, + responseBody: string | null, + responseBodySize: number, + statusCode: number, + responseContentType: string, + errorDomain: string, + gqlQueryName?: string, + serverErrorMessage?: string, + ): void; // App Launches APIs // setAppLaunchEnabled(isEnabled: boolean): void; diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 3ff68de26b..3990da4c8b 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -10,7 +10,6 @@ import type { StringKey, WelcomeMessageMode, } from '../utils/Enums'; -import type { NetworkData } from '../utils/XhrNetworkInterceptor'; import type { NativeConstants } from './NativeConstants'; import { NativeModules } from './NativePackage'; @@ -40,7 +39,36 @@ export interface InstabugNativeModule extends NativeModule { setString(string: string, key: StringKey): void; // Network APIs // - networkLog(network: NetworkData | string): void; + networkLogAndroid( + url: string, + requestBody: string, + responseBody: string | null, + method: string, + responseCode: number, + requestHeaders: string, + responseHeaders: string, + duration: number, + ): void; + + networkLogIOS( + url: string, + method: string, + requestBody: string | null, + requestBodySize: number, + responseBody: string | null, + responseBodySize: number, + responseCode: number, + requestHeaders: Record, + responseHeaders: Record, + contentType: string, + errorDomain: string, + errorCode: number, + startTime: number, + duration: number, + gqlQueryName: string | undefined, + serverErrorMessage: string | undefined, + ): void; + setNetworkLoggingEnabled(isEnabled: boolean): void; // Repro Steps APIs // diff --git a/src/utils/InstabugConstants.ts b/src/utils/InstabugConstants.ts index c7b4988771..59bdb2324f 100644 --- a/src/utils/InstabugConstants.ts +++ b/src/utils/InstabugConstants.ts @@ -1,5 +1,12 @@ -enum InstabugConstants { - GRAPHQL_HEADER = 'ibg-graphql-header', -} +const InstabugConstants = { + GRAPHQL_HEADER: 'ibg-graphql-header', + + // TODO: dyanmically get the max size from the native SDK and update the error message to reflect the dynamic size. + MAX_NETWORK_BODY_SIZE_IN_BYTES: 1024 * 10, // 10 KB + MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE: + 'The response body has not been logged because it exceeds the maximum size of 10 Kb', + MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE: + 'The request body has not been logged because it exceeds the maximum size of 10 Kb', +}; export default InstabugConstants; diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index 6a8dfb7405..d4238f14f0 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -8,7 +8,10 @@ import type { NavigationState as NavigationStateV5, PartialState } from '@react- import type { NavigationState as NavigationStateV4 } from 'react-navigation'; import type { CrashData } from '../native/NativeCrashReporting'; +import type { NetworkData } from './XhrNetworkInterceptor'; import { NativeCrashReporting } from '../native/NativeCrashReporting'; +import { NativeInstabug } from '../native/NativeInstabug'; +import { NativeAPM } from '../native/NativeAPM'; export const parseErrorStack = (error: ExtendedError): StackFrame[] => { return parseErrorStackLib(error); @@ -124,6 +127,75 @@ export async function sendCrashReport( return remoteSenderCallback(jsonObject); } +export function isContentTypeNotAllowed(contentType: string) { + const allowed = [ + 'application/protobuf', + 'application/json', + 'application/xml', + 'text/xml', + 'text/html', + 'text/plain', + ]; + + return allowed.every((type) => !contentType.includes(type)); +} + +export function reportNetworkLog(network: NetworkData) { + if (Platform.OS === 'android') { + const requestHeaders = JSON.stringify(network.requestHeaders); + const responseHeaders = JSON.stringify(network.responseHeaders); + + NativeInstabug.networkLogAndroid( + network.url, + network.requestBody, + network.responseBody, + network.method, + network.responseCode, + requestHeaders, + responseHeaders, + network.duration, + ); + + NativeAPM.networkLogAndroid( + network.startTime, + network.duration, + requestHeaders, + network.requestBody, + network.requestBodySize, + network.method, + network.url, + network.requestContentType, + responseHeaders, + network.responseBody, + network.responseBodySize, + network.responseCode, + network.contentType, + network.errorDomain, + network.gqlQueryName, + network.serverErrorMessage, + ); + } else { + NativeInstabug.networkLogIOS( + network.url, + network.method, + network.requestBody, + network.requestBodySize, + network.responseBody, + network.responseBodySize, + network.responseCode, + network.requestHeaders, + network.responseHeaders, + network.contentType, + network.errorDomain, + network.errorCode, + network.startTime, + network.duration, + network.gqlQueryName, + network.serverErrorMessage, + ); + } +} + export default { parseErrorStack, captureJsErrors, diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index ad79f2d4fa..701533f15c 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -1,4 +1,5 @@ import InstabugConstants from './InstabugConstants'; +import { stringifyIfNotString } from './InstabugUtils'; export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend: number) => void; export type NetworkDataCallback = (data: NetworkData) => void; @@ -80,7 +81,12 @@ export default { }; XMLHttpRequest.prototype.setRequestHeader = function (header, value) { - network.requestHeaders[header] = typeof value === 'string' ? value : JSON.stringify(value); + // According to the HTTP RFC, headers are case-insensitive, so we convert + // them to lower-case to make accessing headers predictable. + // This avoid issues like failing to get the Content-Type header for a request + // because the header is set as 'Content-Type' instead of 'content-type'. + const key = header.toLowerCase(); + network.requestHeaders[key] = stringifyIfNotString(value); originalXHRSetRequestHeader.apply(this, [header, value]); }; diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts index ca9dd297de..27644c694a 100644 --- a/test/mocks/mockAPM.ts +++ b/test/mocks/mockAPM.ts @@ -16,7 +16,7 @@ const mockAPM: ApmNativeModule = { endUITrace: jest.fn(), endAppLaunch: jest.fn(), ibgSleep: jest.fn(), - networkLog: jest.fn(), + networkLogAndroid: jest.fn(), }; export default mockAPM; diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index bb69eda517..c2dac12b5a 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -52,7 +52,8 @@ const mockInstabug: InstabugNativeModule = { addExperiments: jest.fn(), removeExperiments: jest.fn(), clearAllExperiments: jest.fn(), - networkLog: jest.fn(), + networkLogIOS: jest.fn(), + networkLogAndroid: jest.fn(), appendTagToReport: jest.fn(), appendConsoleLogToReport: jest.fn(), setUserAttributeToReport: jest.fn(), diff --git a/test/mocks/mockInstabugUtils.ts b/test/mocks/mockInstabugUtils.ts index 335dd5c016..7d58be394e 100644 --- a/test/mocks/mockInstabugUtils.ts +++ b/test/mocks/mockInstabugUtils.ts @@ -10,5 +10,7 @@ jest.mock('../../src/utils/InstabugUtils', () => { sendCrashReport: jest.fn(), getStackTrace: jest.fn().mockReturnValue('javascriptStackTrace'), getFullRoute: jest.fn().mockImplementation(() => 'ScreenName'), + reportNetworkLog: jest.fn(), + isContentTypeNotAllowed: jest.fn(), }; }); diff --git a/test/modules/NetworkLogger.spec.ts b/test/modules/NetworkLogger.spec.ts index de121c636e..71dd2dd778 100644 --- a/test/modules/NetworkLogger.spec.ts +++ b/test/modules/NetworkLogger.spec.ts @@ -1,34 +1,40 @@ import '../mocks/mockXhrNetworkInterceptor'; - -import { Platform } from 'react-native'; +import '../mocks/mockInstabugUtils'; import waitForExpect from 'wait-for-expect'; import * as NetworkLogger from '../../src/modules/NetworkLogger'; -import { NativeAPM } from '../../src/native/NativeAPM'; -import { NativeInstabug } from '../../src/native/NativeInstabug'; import Interceptor from '../../src/utils/XhrNetworkInterceptor'; +import { isContentTypeNotAllowed, reportNetworkLog } from '../../src/utils/InstabugUtils'; +import InstabugConstants from '../../src/utils/InstabugConstants'; -const clone = (obj: any) => { +const clone = (obj: T): T => { return JSON.parse(JSON.stringify(obj)); }; describe('NetworkLogger Module', () => { - const network = { + const network: NetworkLogger.NetworkData = { url: 'https://api.instabug.com', requestBody: '', - requestHeaders: { 'Content-type': 'application/json' }, + requestHeaders: { 'content-type': 'application/json' }, method: 'GET', responseBody: '', responseCode: 200, - responseHeaders: '', + responseHeaders: { 'content-type': 'application/json' }, contentType: 'application/json', duration: 0, + requestBodySize: 0, + responseBodySize: 0, + errorDomain: '', + errorCode: 0, + startTime: 0, + serverErrorMessage: '', + requestContentType: 'application/json', }; beforeEach(() => { - // @ts-ignore NetworkLogger.setNetworkDataObfuscationHandler(null); + NetworkLogger.setRequestFilterExpression('false'); }); it('should set onProgressCallback with callback', () => { @@ -52,52 +58,18 @@ describe('NetworkLogger Module', () => { expect(Interceptor.disableInterception).toBeCalledTimes(1); }); - it('should send log network when Platform is ios', () => { - Platform.OS = 'ios'; + it('should report the network log', () => { Interceptor.setOnDoneCallback = jest .fn() .mockImplementation((callback) => callback(clone(network))); - NetworkLogger.setEnabled(true); - expect(NativeInstabug.networkLog).toBeCalledTimes(1); - expect(NativeInstabug.networkLog).toBeCalledWith(network); - }); - - it('should send log network when Platform is android', () => { - Platform.OS = 'android'; - Interceptor.setOnDoneCallback = jest - .fn() - .mockImplementation((callback) => callback(clone(network))); NetworkLogger.setEnabled(true); - expect(NativeInstabug.networkLog).toBeCalledWith(JSON.stringify(network)); - expect(NativeAPM.networkLog).toBeCalledWith(JSON.stringify(network)); - }); - - it('should not break if it fails to stringify to JSON on network log if platform is android', () => { - Platform.OS = 'android'; - - // Avoid the console.error to clutter the test log - const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - - // Make a circular object, this should make JSON.stringify fail - const networkResult = clone(network); - networkResult.responseBody = {}; - networkResult.responseBody.result = { body: networkResult.responseBody }; - - Interceptor.setOnDoneCallback = jest - .fn() - .mockImplementation((callback) => callback(networkResult)); - - expect(() => NetworkLogger.setEnabled(true)).not.toThrow(); - expect(NativeInstabug.networkLog).not.toBeCalled(); - expect(NativeAPM.networkLog).not.toBeCalled(); - - consoleSpy.mockRestore(); + expect(reportNetworkLog).toBeCalledTimes(1); + expect(reportNetworkLog).toBeCalledWith(network); }); - it('should send log network when setNetworkDataObfuscationHandler is set and Platform is ios', async () => { - Platform.OS = 'ios'; + it('should send log network when setNetworkDataObfuscationHandler is set', async () => { const randomString = '28930q938jqhd'; Interceptor.setOnDoneCallback = jest .fn() @@ -111,33 +83,11 @@ describe('NetworkLogger Module', () => { await waitForExpect(() => { const newData = clone(network); newData.requestHeaders.token = randomString; - expect(NativeInstabug.networkLog).toBeCalledWith(newData); + expect(reportNetworkLog).toBeCalledWith(newData); }); }); - it('should send log network when setNetworkDataObfuscationHandler is set and Platform is android', async () => { - Platform.OS = 'android'; - const randomString = '28930q938jqhd'; - Interceptor.setOnDoneCallback = jest - .fn() - .mockImplementation((callback) => callback(clone(network))); - NetworkLogger.setNetworkDataObfuscationHandler((networkData) => { - networkData.requestHeaders.token = randomString; - return Promise.resolve(networkData); - }); - NetworkLogger.setEnabled(true); - - await waitForExpect(() => { - const newData = clone(network); - newData.requestHeaders.token = randomString; - expect(NativeInstabug.networkLog).toBeCalledWith(JSON.stringify(newData)); - expect(NativeAPM.networkLog).toBeCalledWith(JSON.stringify(newData)); - }); - }); - - it('should not break if network data obfuscation fails when platform is android', async () => { - Platform.OS = 'android'; - + it('should not break if network data obfuscation fails', async () => { // Avoid the console.error to clutter the test log const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); @@ -152,8 +102,7 @@ describe('NetworkLogger Module', () => { NetworkLogger.setNetworkDataObfuscationHandler(handler); expect(() => NetworkLogger.setEnabled(true)).not.toThrow(); - expect(NativeInstabug.networkLog).not.toBeCalled(); - expect(NativeAPM.networkLog).not.toBeCalled(); + expect(reportNetworkLog).not.toBeCalled(); consoleSpy.mockRestore(); }); @@ -164,12 +113,11 @@ describe('NetworkLogger Module', () => { .mockImplementation((callback) => callback(clone(network))); NetworkLogger.setRequestFilterExpression( - "network.requestHeaders['Content-type'] === 'application/json'", + "network.requestHeaders['content-type'] === 'application/json'", ); NetworkLogger.setEnabled(true); - expect(NativeInstabug.networkLog).not.toBeCalled(); - expect(NativeAPM.networkLog).not.toBeCalled(); + expect(reportNetworkLog).not.toBeCalled(); }); it('should test that operationSetContext at apollo handler called', async () => { @@ -200,4 +148,132 @@ describe('NetworkLogger Module', () => { consoleSpy.mockRestore(); }); + + it('should omit request body if its content type is not allowed', () => { + const consoleWarn = jest.spyOn(console, 'warn').mockImplementation(); + jest.mocked(isContentTypeNotAllowed).mockReturnValueOnce(true); + + const networkData = { + ...network, + requestBody: 'some request body', + }; + + Interceptor.setOnDoneCallback = jest + .fn() + .mockImplementation((callback) => callback(networkData)); + + NetworkLogger.setEnabled(true); + + expect(reportNetworkLog).toHaveBeenCalledWith({ + ...networkData, + requestBody: expect.stringContaining('omitted'), + }); + + expect(consoleWarn).toBeCalledTimes(1); + + consoleWarn.mockRestore(); + }); + + it('should omit response body if its content type is not allowed', () => { + const consoleWarn = jest.spyOn(console, 'warn').mockImplementation(); + jest.mocked(isContentTypeNotAllowed).mockReturnValueOnce(true); + + const networkData = { + ...network, + responseBody: 'some response body', + }; + + Interceptor.setOnDoneCallback = jest + .fn() + .mockImplementation((callback) => callback(networkData)); + + NetworkLogger.setEnabled(true); + + expect(reportNetworkLog).toHaveBeenCalledWith({ + ...networkData, + responseBody: expect.stringContaining('omitted'), + }); + + expect(consoleWarn).toBeCalledTimes(1); + + consoleWarn.mockRestore(); + }); + + it('should omit request body if its size exceeds the maximum allowed size', () => { + const consoleWarn = jest.spyOn(console, 'warn').mockImplementation(); + + const networkData = { + ...network, + requestBodySize: InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES + 1, + }; + + Interceptor.setOnDoneCallback = jest + .fn() + .mockImplementation((callback) => callback(networkData)); + + NetworkLogger.setEnabled(true); + + expect(reportNetworkLog).toHaveBeenCalledWith({ + ...networkData, + requestBody: InstabugConstants.MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE, + }); + + expect(consoleWarn).toBeCalledTimes(1); + + consoleWarn.mockRestore(); + }); + + it('should not omit request body if its size does not exceed the maximum allowed size', () => { + const networkData = { + ...network, + requestBodySize: InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES, + }; + + Interceptor.setOnDoneCallback = jest + .fn() + .mockImplementation((callback) => callback(networkData)); + + NetworkLogger.setEnabled(true); + + expect(reportNetworkLog).toHaveBeenCalledWith(networkData); + }); + + it('should omit response body if its size exceeds the maximum allowed size', () => { + const consoleWarn = jest.spyOn(console, 'warn').mockImplementation(); + + const networkData = { + ...network, + responseBodySize: InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES + 1, + }; + + Interceptor.setOnDoneCallback = jest + .fn() + .mockImplementation((callback) => callback(networkData)); + + NetworkLogger.setEnabled(true); + + expect(reportNetworkLog).toHaveBeenCalledWith({ + ...networkData, + responseBody: InstabugConstants.MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE, + }); + + expect(consoleWarn).toBeCalledTimes(1); + + consoleWarn.mockRestore(); + }); + + it('should not omit response body if its size does not exceed the maximum allowed size', () => { + const networkData = { + ...network, + responseBodySize: InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES, + }; + + Interceptor.setOnDoneCallback = jest + .fn() + .mockImplementation((callback) => callback(networkData)); + + NetworkLogger.setEnabled(true); + + expect(reportNetworkLog).toHaveBeenCalledWith(networkData); + }); }); diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index 9ecb2332a2..becfccc0e9 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -5,8 +5,14 @@ import parseErrorStackLib from 'react-native/Libraries/Core/Devtools/parseErrorS import * as Instabug from '../../src/modules/Instabug'; import { NativeCrashReporting } from '../../src/native/NativeCrashReporting'; -import { InvocationEvent, NonFatalErrorLevel } from '../../src'; -import InstabugUtils, { getStackTrace, sendCrashReport } from '../../src/utils/InstabugUtils'; +import { InvocationEvent, NetworkData, NonFatalErrorLevel } from '../../src'; +import InstabugUtils, { + getStackTrace, + reportNetworkLog, + sendCrashReport, +} from '../../src/utils/InstabugUtils'; +import { NativeInstabug } from '../../src/native/NativeInstabug'; +import { NativeAPM } from '../../src/native/NativeAPM'; describe('Test global error handler', () => { beforeEach(() => { @@ -233,3 +239,91 @@ describe('Instabug Utils', () => { ); }); }); + +describe('reportNetworkLog', () => { + const network: NetworkData = { + url: 'https://api.instabug.com', + method: 'GET', + requestBody: 'requestBody', + requestHeaders: { request: 'header' }, + responseBody: 'responseBody', + responseCode: 200, + responseHeaders: { response: 'header' }, + contentType: 'application/json', + startTime: 1, + duration: 2, + requestBodySize: 3, + responseBodySize: 4, + errorCode: 5, + errorDomain: 'errorDomain', + serverErrorMessage: 'serverErrorMessage', + requestContentType: 'requestContentType', + }; + + it('reportNetworkLog should send network logs to native with the correct parameters on Android', () => { + Platform.OS = 'android'; + + const requestHeaders = JSON.stringify(network.requestHeaders); + const responseHeaders = JSON.stringify(network.responseHeaders); + + reportNetworkLog(network); + + expect(NativeInstabug.networkLogAndroid).toHaveBeenCalledTimes(1); + expect(NativeInstabug.networkLogAndroid).toHaveBeenCalledWith( + network.url, + network.requestBody, + network.responseBody, + network.method, + network.responseCode, + requestHeaders, + responseHeaders, + network.duration, + ); + + expect(NativeAPM.networkLogAndroid).toHaveBeenCalledTimes(1); + expect(NativeAPM.networkLogAndroid).toHaveBeenCalledWith( + network.startTime, + network.duration, + requestHeaders, + network.requestBody, + network.requestBodySize, + network.method, + network.url, + network.requestContentType, + responseHeaders, + network.responseBody, + network.responseBodySize, + network.responseCode, + network.contentType, + network.errorDomain, + network.gqlQueryName, + network.serverErrorMessage, + ); + }); + + it('reportNetworkLog should send network logs to native with the correct parameters on iOS', () => { + Platform.OS = 'ios'; + + reportNetworkLog(network); + + expect(NativeInstabug.networkLogIOS).toHaveBeenCalledTimes(1); + expect(NativeInstabug.networkLogIOS).toHaveBeenCalledWith( + network.url, + network.method, + network.requestBody, + network.requestBodySize, + network.responseBody, + network.responseBodySize, + network.responseCode, + network.requestHeaders, + network.responseHeaders, + network.contentType, + network.errorDomain, + network.errorCode, + network.startTime, + network.duration, + network.gqlQueryName, + network.serverErrorMessage, + ); + }); +}); From 635cd479e555c059c7f150f373a026c2f23a3adc Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 23 Jul 2024 10:15:55 +0300 Subject: [PATCH 003/104] fix(android): APM network logging(#1253) * fix(android): add W3C External Trace Attributes placeholder * chore: add CHANGLOG * chore: add CHANGLOG * fix: remove ios sub module --- CHANGELOG.md | 1 + .../reactlibrary/RNInstabugAPMModule.java | 42 ++++++++++--------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ec9aad5b6..4221fa8a26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Fix APM network logging on Android ([#1253](https://github.com/Instabug/Instabug-React-Native/pull/1253)). - Fix an OOM (out-of-memory) crash while saving network logs on Android ([#1244](https://github.com/Instabug/Instabug-React-Native/pull/1244)). ## [13.2.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.1.1...v13.2.0) (July 7, 2024) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 7ffaf4de73..70487f8cc5 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -14,6 +14,7 @@ import com.instabug.apm.APM; import com.instabug.apm.model.ExecutionTrace; import com.instabug.apm.networking.APMNetworkLogger; +import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; import com.instabug.reactlibrary.utils.MainThreadHandler; import org.json.JSONException; @@ -338,27 +339,28 @@ private void networkLogAndroid(final double requestStartTime, final String errorMessage = hasError ? errorDomain : null; try { - Method method = 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); + Method method = 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( - networkLogger, - requestStartTime, - requestDuration, - requestHeaders, - requestBody, - requestBodySize, - requestMethod, - requestUrl, - requestContentType, - responseHeaders, - responseBody, - responseBodySize, - statusCode, - responseContentType, - errorMessage, - gqlQueryName, - serverErrorMessage - ); + method.invoke( + networkLogger, + (long) requestStartTime, + (long) requestDuration, + requestHeaders, + requestBody, + (long) requestBodySize, + requestMethod, + requestUrl, + requestContentType, + responseHeaders, + responseBody, + (long)responseBodySize, + (int) statusCode, + responseContentType, + errorMessage, + gqlQueryName, + serverErrorMessage, + null + ); } else { Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); } From 4e8162110ae67310b5b5b974b5ad1244f071e7dd Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud <68241710+a7medev@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:19:40 +0300 Subject: [PATCH 004/104] fix: use correct diff link for v13.0.0, v12.9.0 releases (#1198) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4221fa8a26..449416d3a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ - Bump Instabug iOS SDK to v13.0.0 ([#1189](https://github.com/Instabug/Instabug-React-Native/pull/1189)). [See release notes](https://github.com/instabug/instabug-ios/releases/tag/13.0.0). - Bump Instabug Android SDK to v13.0.0 ([#1188](https://github.com/Instabug/Instabug-React-Native/pull/1188)). [See release notes](https://github.com/Instabug/android/releases/tag/v13.0.0). -## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...12.9.0)(April 2, 2024) +## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...v12.9.0) (April 2, 2024) ### Added From 3073554c9e9061d195c8fed08a34beeb759fd42a Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud <68241710+a7medev@users.noreply.github.com> Date: Mon, 13 May 2024 20:39:31 +0300 Subject: [PATCH 005/104] feat(ios): read env vars from .xcode.env in sourcemaps script (#1200) * feat(ios): read env vars from .xcode.env in sourcemaps script * chore: update xcode project * chore: update changelog --- examples/default/ios/InstabugExample.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj index afe4ffe605..2751593517 100644 --- a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj +++ b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ ); name = "[CP-User] [instabug-reactnative] Upload Sourcemap"; runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; + shellPath = /bin/sh; shellScript = "#!/bin/sh\n\nmain() {\n # Read environment variables from ios/.xcode.env if it exists\n env_path=\"$PODS_ROOT/../.xcode.env\"\n if [ -f \"$env_path\" ]; then\n source \"$env_path\"\n fi\n\n # Read environment variables from ios/.xcode.env.local if it exists\n local_env_path=\"${ENV_PATH}.local\"\n if [ -f \"$local_env_path\" ]; then\n source \"$local_env_path\"\n fi\n\n if [[ \"$INSTABUG_SOURCEMAPS_UPLOAD_DISABLE\" = true ]]; then\n echo \"[Info] \\`INSTABUG_SOURCEMAPS_UPLOAD_DISABLE\\` was set to true, skipping sourcemaps upload...\"\n exit 0\n fi\n\n if [[ \"$CONFIGURATION\" = \"Debug\" ]]; then\n echo \"[Info] Building in debug mode, skipping sourcemaps upload...\"\n exit 0\n fi\n\n if [[ -z \"$INFOPLIST_FILE\" ]] || [[ -z \"$PROJECT_DIR\" ]]; then\n echo \"[Error] Instabug sourcemaps script must be invoked by Xcode\"\n exit 0\n fi\n\n local source_map_file=$(generate_sourcemaps | tail -n 1)\n\n local js_project_dir=\"$PROJECT_DIR/..\"\n local instabug_dir=$(dirname $(node -p \"require.resolve('instabug-reactnative/package.json')\"))\n local inferred_token=$(cd $js_project_dir && source $instabug_dir/scripts/find-token.sh)\n local app_token=$(resolve_var \"App Token\" \"INSTABUG_APP_TOKEN\" \"$inferred_token\" | tail -n 1)\n\n local inferred_name=$(/usr/libexec/PlistBuddy -c 'print CFBundleShortVersionString' \"$PROJECT_DIR/$INFOPLIST_FILE\")\n local version_name=$(resolve_var \"Version Name\" \"INSTABUG_APP_VERSION_NAME\" \"$inferred_name\" | tail -n 1)\n\n local inferred_code=$(/usr/libexec/PlistBuddy -c 'print CFBundleVersion' \"$PROJECT_DIR/$INFOPLIST_FILE\")\n local version_code=$(resolve_var \"Version Code\" \"INSTABUG_APP_VERSION_CODE\" \"$inferred_code\" | tail -n 1)\n\n node $instabug_dir/bin/index.js upload-sourcemaps \\\n --platform ios \\\n --file $source_map_file \\\n --token $app_token \\\n --name $version_name \\\n --code $version_code\n}\n\ngenerate_sourcemaps() {\n local react_native_dir=$(dirname $(node -p \"require.resolve('react-native/package.json')\"))\n\n # Fixes an issue with react-native prior to v0.67.0\n # For more info: https://github.com/facebook/react-native/issues/32168\n export RN_DIR=$react_native_dir\n\n # Used withing `react-native-xcode.sh` to generate sourcemap file\n export SOURCEMAP_FILE=\"$(pwd)/main.jsbundle.map\";\n\n source \"$react_native_dir/scripts/react-native-xcode.sh\"\n\n if [[ ! -f \"$SOURCEMAP_FILE\" ]]; then\n echo \"[Error] Unable to find source map file at: $SOURCEMAP_FILE\"\n exit 0\n fi\n\n echo $SOURCEMAP_FILE\n}\n\nresolve_var() {\n local name=$1\n local env_key=$2\n local default_value=$3\n\n local env_value=\"${!env_key}\"\n\n if [[ -n \"$env_value\" ]] && [[ -n \"$default_value\" ]] && [[ \"$env_value\" != default_value ]]; then\n echo \"[Warning] Environment variable \\`$env_key\\` might have incorrect value, make sure this was intentional:\"\n echo \" Environment Value: $env_value\"\n echo \" Default Value: $default_value\"\n fi\n\n local value=\"${env_value:-$default_value}\"\n\n if [[ -z \"$value\" ]]; then\n echo \"[Error] Unable to find $name! Set the environment variable \\`$env_key\\` and try again.\"\n exit 0\n fi\n\n echo $value\n}\n\nmain \"$@\"; exit\n"; }; B77A7BA143DBD17E8AAFD0B4 /* [CP] Embed Pods Frameworks */ = { From 8d16747ca97736edd4dddc3a519f1bbf05cd4874 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 16 May 2024 18:45:20 +0300 Subject: [PATCH 006/104] chore/update-podfile.lock --- examples/default/ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index dcaa1c6971..cf767c0a50 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -864,4 +864,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: ad82a989387dcdb1ce80667f16b998a2644cf0b2 -COCOAPODS: 1.12.0 +COCOAPODS: 1.15.2 From e546e93d0a43862f2f46a8c30ed9ffaaf169fcf8 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 20 May 2024 19:48:40 +0300 Subject: [PATCH 007/104] feat: add w3c header generator --- src/utils/InstabugUtils.ts | 29 ++++++++++++++++ src/utils/XhrNetworkInterceptor.ts | 3 +- test/utils/InstabugUtils.spec.ts | 55 ++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index d4238f14f0..cd9cdeb768 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -126,6 +126,33 @@ export async function sendCrashReport( return remoteSenderCallback(jsonObject); } +/** + * Generate random 32 bit unsigned integer Hexadecimal (8 chars) lower case letters + * Should not return all zeros + */ +export const generateTracePartialId=()=> { + let hexString; + do { + let randomNumber = Math.floor(Math.random() * Math.pow(2, 32)); + hexString = randomNumber.toString(16).toLocaleLowerCase(); + while (hexString.length < 8) { + hexString = '0' + hexString; + } + } while (hexString === '00000000'); + + return hexString; +} +/** + * Generate W3C header + * @param networkStartTime + * @returns w3c header + */ +export const generateW3CHeader=(networkStartTime:number)=>{ + const hexaDigitsTimestamp=(Math.floor(networkStartTime.valueOf()/1000)).toString(16).toLowerCase(); + const partialId=generateTracePartialId(); + + return `${hexaDigitsTimestamp}${partialId}${hexaDigitsTimestamp}${partialId}` +} export function isContentTypeNotAllowed(contentType: string) { const allowed = [ @@ -204,4 +231,6 @@ export default { getStackTrace, stringifyIfNotString, sendCrashReport, + generateTracePartialId, + generateW3CHeader }; diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 701533f15c..02fe8a16d1 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -1,5 +1,5 @@ import InstabugConstants from './InstabugConstants'; -import { stringifyIfNotString } from './InstabugUtils'; +import { stringifyIfNotString, generateW3CHeader } from './InstabugUtils'; export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend: number) => void; export type NetworkDataCallback = (data: NetworkData) => void; @@ -212,6 +212,7 @@ export default { } cloneNetwork.startTime = Date.now(); + const w3cHeader = generateW3CHeader(cloneNetwork.startTime); originalXHRSend.apply(this, [data]); }; isInterceptorEnabled = true; diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index becfccc0e9..b347a2d500 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -10,6 +10,8 @@ import InstabugUtils, { getStackTrace, reportNetworkLog, sendCrashReport, + generateTracePartialId, + generateW3CHeader, } from '../../src/utils/InstabugUtils'; import { NativeInstabug } from '../../src/native/NativeInstabug'; import { NativeAPM } from '../../src/native/NativeAPM'; @@ -326,4 +328,57 @@ describe('reportNetworkLog', () => { network.serverErrorMessage, ); }); + + it('generateTracePartialId should generate a non-zero hex string', () => { + const mockMathRandom = jest.spyOn(global.Math, 'random'); + + mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0).mockReturnValueOnce(0.5); + + const hexString = generateTracePartialId(); + + expect(hexString).not.toBe('00000000'); + + mockMathRandom.mockRestore(); + }); + + it('generateTracePartialId should return 8 chars long generated hex string', () => { + const mockMathRandom = jest.spyOn(global.Math, 'random'); + mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0.5).mockReturnValueOnce(0.5); + const hexString = generateTracePartialId(); + + expect(hexString).toHaveLength(8); + + mockMathRandom.mockRestore(); + }); + + it('generateW3CHeader should return timestampidtimestampid format header', () => { + const mockMathRandom = jest.spyOn(global.Math, 'random'); + + mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0.5).mockReturnValueOnce(1); + + const mockedPartialId = '80000000'; + const date = 1716210104248; + const unixTimestamp = '664b49b8'; + const expectedHeader = `${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}`; + const generatedHeader = generateW3CHeader(date); + + expect(generatedHeader).toBe(expectedHeader); + + mockMathRandom.mockRestore(); + }); + it('generateW3CHeader should correctly floor the timestamp', () => { + const mockMathRandom = jest.spyOn(global.Math, 'random'); + + mockMathRandom.mockReturnValueOnce(0.1).mockReturnValueOnce(0.2).mockReturnValueOnce(0.3); + + const mockedPartialId = '19999999'; + const date = 1716222912145; + const unixTimestamp = '664b7bc0'; + const expectedHeader = `${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}`; + const generatedHeader = generateW3CHeader(date); + + expect(generatedHeader).toBe(expectedHeader); + + mockMathRandom.mockRestore(); + }); }); From b8c28726a4412e15fbc63d429e31cf1b83dbedec Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 21 May 2024 14:26:27 +0300 Subject: [PATCH 008/104] ci:fix lint --- src/utils/InstabugUtils.ts | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index cd9cdeb768..f04d126bcb 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -130,29 +130,31 @@ export async function sendCrashReport( * Generate random 32 bit unsigned integer Hexadecimal (8 chars) lower case letters * Should not return all zeros */ -export const generateTracePartialId=()=> { +export const generateTracePartialId = () => { let hexString; do { - let randomNumber = Math.floor(Math.random() * Math.pow(2, 32)); - hexString = randomNumber.toString(16).toLocaleLowerCase(); - while (hexString.length < 8) { - hexString = '0' + hexString; - } - } while (hexString === '00000000'); - + const randomNumber = Math.floor(Math.random() * Math.pow(2, 32)); + hexString = randomNumber.toString(16).toLocaleLowerCase(); + while (hexString.length < 8) { + hexString = '0' + hexString; + } + } while (hexString === '00000000'); + return hexString; -} +}; /** - * Generate W3C header - * @param networkStartTime + * Generate W3C header + * @param networkStartTime * @returns w3c header */ -export const generateW3CHeader=(networkStartTime:number)=>{ - const hexaDigitsTimestamp=(Math.floor(networkStartTime.valueOf()/1000)).toString(16).toLowerCase(); - const partialId=generateTracePartialId(); - - return `${hexaDigitsTimestamp}${partialId}${hexaDigitsTimestamp}${partialId}` -} +export const generateW3CHeader = (networkStartTime: number) => { + const hexaDigitsTimestamp = Math.floor(networkStartTime.valueOf() / 1000) + .toString(16) + .toLowerCase(); + const partialId = generateTracePartialId(); + + return `${hexaDigitsTimestamp}${partialId}${hexaDigitsTimestamp}${partialId}`; +}; export function isContentTypeNotAllowed(contentType: string) { const allowed = [ @@ -232,5 +234,5 @@ export default { stringifyIfNotString, sendCrashReport, generateTracePartialId, - generateW3CHeader + generateW3CHeader, }; From 3f1ac4ff3e6593cf8d9f88f3cec87c78ea62322b Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 21 May 2024 14:56:14 +0300 Subject: [PATCH 009/104] ci:fix ios tests --- examples/default/ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index cf767c0a50..dcaa1c6971 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -864,4 +864,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: ad82a989387dcdb1ce80667f16b998a2644cf0b2 -COCOAPODS: 1.15.2 +COCOAPODS: 1.12.0 From d08d3f21e8a927fd0de7518fad0adc6ec3e754bb Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 22 May 2024 16:45:58 +0300 Subject: [PATCH 010/104] feat:update header format --- src/utils/InstabugUtils.ts | 6 ++++-- src/utils/XhrNetworkInterceptor.ts | 3 +++ test/utils/InstabugUtils.spec.ts | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index f04d126bcb..f03411b394 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -143,7 +143,7 @@ export const generateTracePartialId = () => { return hexString; }; /** - * Generate W3C header + * Generate W3C header in the format of {version}-{trace-id}-{parent-id}-{trace-flag} * @param networkStartTime * @returns w3c header */ @@ -152,8 +152,10 @@ export const generateW3CHeader = (networkStartTime: number) => { .toString(16) .toLowerCase(); const partialId = generateTracePartialId(); + const traceId = `${hexaDigitsTimestamp}${partialId}${hexaDigitsTimestamp}${partialId}`; + const parentId = `4942472d${partialId}`; - return `${hexaDigitsTimestamp}${partialId}${hexaDigitsTimestamp}${partialId}`; + return `00-${traceId}-${parentId}-01`; }; export function isContentTypeNotAllowed(contentType: string) { diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 02fe8a16d1..93940f44b5 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -213,6 +213,9 @@ export default { cloneNetwork.startTime = Date.now(); const w3cHeader = generateW3CHeader(cloneNetwork.startTime); + const traceparent = generateW3CHeader(cloneNetwork.startTime); + const tracestate = 'instabug=4942472d'; + console.log(traceparent, tracestate); originalXHRSend.apply(this, [data]); }; isInterceptorEnabled = true; diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index b347a2d500..b99d86dad8 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -359,7 +359,7 @@ describe('reportNetworkLog', () => { const mockedPartialId = '80000000'; const date = 1716210104248; const unixTimestamp = '664b49b8'; - const expectedHeader = `${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}`; + const expectedHeader = `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`; const generatedHeader = generateW3CHeader(date); expect(generatedHeader).toBe(expectedHeader); @@ -374,7 +374,7 @@ describe('reportNetworkLog', () => { const mockedPartialId = '19999999'; const date = 1716222912145; const unixTimestamp = '664b7bc0'; - const expectedHeader = `${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}`; + const expectedHeader = `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`; const generatedHeader = generateW3CHeader(date); expect(generatedHeader).toBe(expectedHeader); From be7e75c3cb01d5dce10f531d63e5e8377167b541 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 22 May 2024 17:15:08 +0300 Subject: [PATCH 011/104] feat:update header format test case title --- test/utils/InstabugUtils.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index b99d86dad8..bdf499bb68 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -351,7 +351,7 @@ describe('reportNetworkLog', () => { mockMathRandom.mockRestore(); }); - it('generateW3CHeader should return timestampidtimestampid format header', () => { + it('generateW3CHeader should return {version}-{trace-id}-{parent-id}-{trace-flag} format header', () => { const mockMathRandom = jest.spyOn(global.Math, 'random'); mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0.5).mockReturnValueOnce(1); From 30321243d3387c28c09f0caafaf45be87d4ec67c Mon Sep 17 00:00:00 2001 From: kholood Date: Sun, 26 May 2024 14:35:18 +0300 Subject: [PATCH 012/104] feat:Inject the W3C Header to Network Requests --- src/utils/InstabugConstants.ts | 6 + src/utils/InstabugUtils.ts | 11 +- src/utils/XhrNetworkInterceptor.ts | 48 +++++ test/utils/InstabugUtils.spec.ts | 17 +- test/utils/XhrNetworkInterceptor.spec.ts | 213 ++++++++++++++++++++++- 5 files changed, 286 insertions(+), 9 deletions(-) diff --git a/src/utils/InstabugConstants.ts b/src/utils/InstabugConstants.ts index 59bdb2324f..f3daf1abac 100644 --- a/src/utils/InstabugConstants.ts +++ b/src/utils/InstabugConstants.ts @@ -9,4 +9,10 @@ const InstabugConstants = { 'The request body has not been logged because it exceeds the maximum size of 10 Kb', }; +export const MockedFeatureFlags = { + w3c_external_trace_id_enabled: false, + w3c_generated_header: true, + w3c_caught_header: true, +}; + export default InstabugConstants; diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index f03411b394..4c7f3f88bb 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -148,14 +148,17 @@ export const generateTracePartialId = () => { * @returns w3c header */ export const generateW3CHeader = (networkStartTime: number) => { - const hexaDigitsTimestamp = Math.floor(networkStartTime.valueOf() / 1000) - .toString(16) - .toLowerCase(); + const timestampInSeconds = Math.floor(networkStartTime.valueOf() / 1000); + const hexaDigitsTimestamp = timestampInSeconds.toString(16).toLowerCase(); const partialId = generateTracePartialId(); const traceId = `${hexaDigitsTimestamp}${partialId}${hexaDigitsTimestamp}${partialId}`; const parentId = `4942472d${partialId}`; - return `00-${traceId}-${parentId}-01`; + return { + timestampInSeconds, + partialId, + w3cHeader: `00-${traceId}-${parentId}-01`, + }; }; export function isContentTypeNotAllowed(contentType: string) { diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 93940f44b5..68fd7f454f 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -22,6 +22,11 @@ export interface NetworkData { gqlQueryName?: string; serverErrorMessage: string; requestContentType: string; + w3cc: boolean | null; + partialId: string | null; + etst: number | null; + wgeti: string | null; + wceti: string | null; } const XMLHttpRequest = global.XMLHttpRequest; @@ -53,9 +58,52 @@ const _reset = () => { gqlQueryName: '', serverErrorMessage: '', requestContentType: '', + w3cc: null, + partialId: null, + etst: null, + wgeti: null, + wceti: null, }; }; +export const injectHeaders = ( + network: NetworkData, + MockedFeatureFlags: { + w3c_external_trace_id_enabled: boolean; + w3c_generated_header: boolean; + w3c_caught_header: boolean; + }, +) => { + const { w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header } = + MockedFeatureFlags; + + if (!w3c_external_trace_id_enabled) { + return; + } + const headerFound = network.requestHeaders.traceparent != null; + network.w3cc = headerFound; + headerFound + ? IdentifyCaughtHeader(network, w3c_caught_header) + : injectGeneratedData(network, w3c_generated_header); +}; + +const IdentifyCaughtHeader = (network: NetworkData, w3c_caught_header: boolean) => { + w3c_caught_header && (network.wceti = network.requestHeaders.traceparent); +}; + +const injectGeneratedData = (network: NetworkData, w3c_generated_header: boolean) => { + const { timestampInSeconds, partialId, w3cHeader } = generateW3CHeader(network.startTime); + + if (w3c_generated_header) { + network.wgeti = w3cHeader; + network.requestHeaders['traceparent'] = w3cHeader; + network.requestHeaders['tracestate'] = 'instabug=4942472d'; + } + + network.partialId = partialId; + network.etst = timestampInSeconds; +}; + export default { setOnDoneCallback(callback: NetworkDataCallback) { onDoneCallback = callback; diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index bdf499bb68..fc42296bce 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -359,10 +359,14 @@ describe('reportNetworkLog', () => { const mockedPartialId = '80000000'; const date = 1716210104248; const unixTimestamp = '664b49b8'; - const expectedHeader = `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`; + const expectedHeader = { + timestampInSeconds: Math.floor(1716210104248 / 1000), + partialId: mockedPartialId, + w3cHeader: `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`, + }; const generatedHeader = generateW3CHeader(date); - expect(generatedHeader).toBe(expectedHeader); + expect(generatedHeader).toMatchObject(expectedHeader); mockMathRandom.mockRestore(); }); @@ -374,10 +378,15 @@ describe('reportNetworkLog', () => { const mockedPartialId = '19999999'; const date = 1716222912145; const unixTimestamp = '664b7bc0'; - const expectedHeader = `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`; + const expectedHeader = { + timestampInSeconds: Math.floor(1716222912145 / 1000), + partialId: mockedPartialId, + w3cHeader: `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`, + }; + const generatedHeader = generateW3CHeader(date); - expect(generatedHeader).toBe(expectedHeader); + expect(generatedHeader).toMatchObject(expectedHeader); mockMathRandom.mockRestore(); }); diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index b014bc9d9c..6b28a7c952 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -4,7 +4,7 @@ import nock from 'nock'; import waitForExpect from 'wait-for-expect'; import InstabugConstants from '../../src/utils/InstabugConstants'; -import Interceptor from '../../src/utils/XhrNetworkInterceptor'; +import Interceptor, { injectHeaders } from '../../src/utils/XhrNetworkInterceptor'; const url = 'http://api.instabug.com'; const method = 'GET'; @@ -293,3 +293,214 @@ describe('Network Interceptor', () => { FakeRequest.send(); }); }); + +describe('Network Interceptor W3C Headers', () => { + beforeEach(() => { + nock.cleanAll(); + }); + + it('should attach generated header if all flags are enabled on no header found', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: true, + w3c_generated_header: true, + w3c_caught_header: true, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(false); + expect(network.partialId).toHaveLength(8); + expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); + expect(network.wgeti).toHaveLength(55); + expect(network.wceti).toBe(null); + expect(network.requestHeaders['tracestate']).toBe('instabug=4942472d'); + expect(network.requestHeaders).toHaveProperty('traceparent'); + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + it('should attach generated header if key flag & generated header flags are enabled on no header found', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: true, + w3c_generated_header: true, + w3c_caught_header: false, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(false); + expect(network.partialId).toHaveLength(8); + expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); + expect(network.wgeti).toHaveLength(55); + expect(network.wceti).toBe(null); + expect(network.requestHeaders['tracestate']).toBe('instabug=4942472d'); + expect(network.requestHeaders).toHaveProperty('traceparent'); + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + + it('should not attach headers when key flag is disabled & generated, caught header flags are enabled', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: false, + w3c_generated_header: true, + w3c_caught_header: true, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(null); + expect(network.partialId).toBe(null); + expect(network.etst).toBe(null); + expect(network.wgeti).toBe(null); + expect(network.wceti).toBe(null); + expect(network.requestHeaders).not.toHaveProperty('traceparent'); + expect(network.requestHeaders).not.toHaveProperty('tracestate'); + + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + it('should not attach headers when all feature flags are disabled', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: false, + w3c_generated_header: false, + w3c_caught_header: false, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(null); + expect(network.partialId).toBe(null); + expect(network.etst).toBe(null); + expect(network.wgeti).toBe(null); + expect(network.wceti).toBe(null); + expect(network.requestHeaders).not.toHaveProperty('traceparent'); + expect(network.requestHeaders).not.toHaveProperty('tracestate'); + + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + it('should not attach headers when key & caught header flags are disabled and generated header flag is enabled', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: false, + w3c_generated_header: true, + w3c_caught_header: false, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(null); + expect(network.partialId).toBe(null); + expect(network.etst).toBe(null); + expect(network.wgeti).toBe(null); + expect(network.wceti).toBe(null); + expect(network.requestHeaders).not.toHaveProperty('traceparent'); + expect(network.requestHeaders).not.toHaveProperty('tracestate'); + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + it('should not attach headers when key & generated header flags are disabled and caught header flag is enabled', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: false, + w3c_generated_header: false, + w3c_caught_header: true, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(null); + expect(network.partialId).toBe(null); + expect(network.etst).toBe(null); + expect(network.wgeti).toBe(null); + expect(network.wceti).toBe(null); + expect(network.requestHeaders).not.toHaveProperty('traceparent'); + expect(network.requestHeaders).not.toHaveProperty('tracestate'); + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + it('should not attach headers when key flag is enabled & generated, caught header flags are disabled on header found', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: true, + w3c_generated_header: false, + w3c_caught_header: false, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + network.requestHeaders['traceparent'] = 'caught traceparent header'; + injectHeaders(network, featureFlags); + expect(network.w3cc).toEqual(true); + expect(network.partialId).toBe(null); + expect(network.etst).toBe(null); + expect(network.wgeti).toBe(null); + expect(network.wceti).toBe(null); + expect(network.requestHeaders).not.toHaveProperty('tracestate'); + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + + it('should attach caught header if all flags are enabled ', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: true, + w3c_generated_header: true, + w3c_caught_header: true, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + network.requestHeaders['traceparent'] = 'caught traceparent header'; + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(true); + expect(network.partialId).toBe(null); + expect(network.etst).toBe(null); + expect(network.wgeti).toBe(null); + expect(network.wceti).toBe('caught traceparent header'); + expect(network.requestHeaders).toHaveProperty('traceparent'); + expect(network.requestHeaders).not.toHaveProperty('tracestate'); + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); + it('should attach caught header if key & caught header flags are enabled and generated header flag is disabled', (done) => { + const featureFlags = { + w3c_external_trace_id_enabled: true, + w3c_generated_header: false, + w3c_caught_header: true, + }; + Interceptor.enableInterception(); + Interceptor.setOnDoneCallback((network) => { + network.requestHeaders['traceparent'] = 'caught traceparent header'; + injectHeaders(network, featureFlags); + expect(network.w3cc).toBe(true); + expect(network.partialId).toBe(null); + expect(network.etst).toBe(null); + expect(network.wgeti).toBe(null); + expect(network.wceti).toBe('caught traceparent header'); + expect(network.requestHeaders).toHaveProperty('traceparent'); + expect(network.requestHeaders).not.toHaveProperty('tracestate'); + done(); + }); + FakeRequest.mockResponse(request); + FakeRequest.open(method, url); + FakeRequest.send(); + }); +}); From 04b9248fa6106bb7ee1eb4f02da691e527177374 Mon Sep 17 00:00:00 2001 From: kholood Date: Sun, 26 May 2024 14:41:43 +0300 Subject: [PATCH 013/104] ci:fix lint --- src/utils/XhrNetworkInterceptor.ts | 32 ++++++++++++------------ test/utils/XhrNetworkInterceptor.spec.ts | 10 ++++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 68fd7f454f..11f0b2c68f 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -67,41 +67,41 @@ const _reset = () => { }; export const injectHeaders = ( - network: NetworkData, - MockedFeatureFlags: { + networkData: NetworkData, + mockedFeatureFlags: { w3c_external_trace_id_enabled: boolean; w3c_generated_header: boolean; w3c_caught_header: boolean; }, ) => { const { w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header } = - MockedFeatureFlags; + mockedFeatureFlags; if (!w3c_external_trace_id_enabled) { return; } - const headerFound = network.requestHeaders.traceparent != null; - network.w3cc = headerFound; + const headerFound = networkData.requestHeaders.traceparent != null; + networkData.w3cc = headerFound; headerFound - ? IdentifyCaughtHeader(network, w3c_caught_header) - : injectGeneratedData(network, w3c_generated_header); + ? IdentifyCaughtHeader(networkData, w3c_caught_header) + : injectGeneratedData(networkData, w3c_generated_header); }; -const IdentifyCaughtHeader = (network: NetworkData, w3c_caught_header: boolean) => { - w3c_caught_header && (network.wceti = network.requestHeaders.traceparent); +const IdentifyCaughtHeader = (networkData: NetworkData, w3c_caught_header: boolean) => { + w3c_caught_header && (networkData.wceti = networkData.requestHeaders.traceparent); }; -const injectGeneratedData = (network: NetworkData, w3c_generated_header: boolean) => { - const { timestampInSeconds, partialId, w3cHeader } = generateW3CHeader(network.startTime); +const injectGeneratedData = (networkData: NetworkData, w3c_generated_header: boolean) => { + const { timestampInSeconds, partialId, w3cHeader } = generateW3CHeader(networkData.startTime); if (w3c_generated_header) { - network.wgeti = w3cHeader; - network.requestHeaders['traceparent'] = w3cHeader; - network.requestHeaders['tracestate'] = 'instabug=4942472d'; + networkData.wgeti = w3cHeader; + networkData.requestHeaders.traceparent = w3cHeader; + networkData.requestHeaders.tracestate = 'instabug=4942472d'; } - network.partialId = partialId; - network.etst = timestampInSeconds; + networkData.partialId = partialId; + networkData.etst = timestampInSeconds; }; export default { diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index 6b28a7c952..d01cb0de36 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -313,7 +313,7 @@ describe('Network Interceptor W3C Headers', () => { expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); expect(network.wgeti).toHaveLength(55); expect(network.wceti).toBe(null); - expect(network.requestHeaders['tracestate']).toBe('instabug=4942472d'); + expect(network.requestHeaders.tracestate).toBe('instabug=4942472d'); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); @@ -335,7 +335,7 @@ describe('Network Interceptor W3C Headers', () => { expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); expect(network.wgeti).toHaveLength(55); expect(network.wceti).toBe(null); - expect(network.requestHeaders['tracestate']).toBe('instabug=4942472d'); + expect(network.requestHeaders.tracestate).toBe('instabug=4942472d'); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); @@ -442,7 +442,7 @@ describe('Network Interceptor W3C Headers', () => { }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { - network.requestHeaders['traceparent'] = 'caught traceparent header'; + network.requestHeaders.traceparent = 'caught traceparent header'; injectHeaders(network, featureFlags); expect(network.w3cc).toEqual(true); expect(network.partialId).toBe(null); @@ -465,7 +465,7 @@ describe('Network Interceptor W3C Headers', () => { }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { - network.requestHeaders['traceparent'] = 'caught traceparent header'; + network.requestHeaders.traceparent = 'caught traceparent header'; injectHeaders(network, featureFlags); expect(network.w3cc).toBe(true); expect(network.partialId).toBe(null); @@ -488,7 +488,7 @@ describe('Network Interceptor W3C Headers', () => { }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { - network.requestHeaders['traceparent'] = 'caught traceparent header'; + network.requestHeaders.traceparent = 'caught traceparent header'; injectHeaders(network, featureFlags); expect(network.w3cc).toBe(true); expect(network.partialId).toBe(null); From 3891e758da80b18f9272d571cee0ff6b60b57011 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 27 May 2024 11:08:15 +0300 Subject: [PATCH 014/104] feat:remove tracestate --- src/utils/XhrNetworkInterceptor.ts | 1 - test/utils/XhrNetworkInterceptor.spec.ts | 9 --------- 2 files changed, 10 deletions(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 11f0b2c68f..f070eba617 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -97,7 +97,6 @@ const injectGeneratedData = (networkData: NetworkData, w3c_generated_header: boo if (w3c_generated_header) { networkData.wgeti = w3cHeader; networkData.requestHeaders.traceparent = w3cHeader; - networkData.requestHeaders.tracestate = 'instabug=4942472d'; } networkData.partialId = partialId; diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index d01cb0de36..bbab249b06 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -313,7 +313,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); expect(network.wgeti).toHaveLength(55); expect(network.wceti).toBe(null); - expect(network.requestHeaders.tracestate).toBe('instabug=4942472d'); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); @@ -335,7 +334,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); expect(network.wgeti).toHaveLength(55); expect(network.wceti).toBe(null); - expect(network.requestHeaders.tracestate).toBe('instabug=4942472d'); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); @@ -359,7 +357,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.wgeti).toBe(null); expect(network.wceti).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); - expect(network.requestHeaders).not.toHaveProperty('tracestate'); done(); }); @@ -382,7 +379,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.wgeti).toBe(null); expect(network.wceti).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); - expect(network.requestHeaders).not.toHaveProperty('tracestate'); done(); }); @@ -405,7 +401,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.wgeti).toBe(null); expect(network.wceti).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); - expect(network.requestHeaders).not.toHaveProperty('tracestate'); done(); }); FakeRequest.mockResponse(request); @@ -427,7 +422,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.wgeti).toBe(null); expect(network.wceti).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); - expect(network.requestHeaders).not.toHaveProperty('tracestate'); done(); }); FakeRequest.mockResponse(request); @@ -449,7 +443,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.etst).toBe(null); expect(network.wgeti).toBe(null); expect(network.wceti).toBe(null); - expect(network.requestHeaders).not.toHaveProperty('tracestate'); done(); }); FakeRequest.mockResponse(request); @@ -473,7 +466,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.wgeti).toBe(null); expect(network.wceti).toBe('caught traceparent header'); expect(network.requestHeaders).toHaveProperty('traceparent'); - expect(network.requestHeaders).not.toHaveProperty('tracestate'); done(); }); FakeRequest.mockResponse(request); @@ -496,7 +488,6 @@ describe('Network Interceptor W3C Headers', () => { expect(network.wgeti).toBe(null); expect(network.wceti).toBe('caught traceparent header'); expect(network.requestHeaders).toHaveProperty('traceparent'); - expect(network.requestHeaders).not.toHaveProperty('tracestate'); done(); }); FakeRequest.mockResponse(request); From a3d5ae8694ea03dcce3040fc76c32729c5187ef5 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 3 Jun 2024 16:48:55 +0300 Subject: [PATCH 015/104] feat: get feature flags from IOS --- RNInstabug.podspec | 2 +- .../ios/InstabugTests/InstabugAPMTests.m | 59 +++++++++++++++++++ examples/default/ios/Podfile | 1 + examples/default/ios/Podfile.lock | 8 ++- ios/RNInstabug/InstabugAPMBridge.h | 4 +- ios/RNInstabug/InstabugAPMBridge.m | 22 +++++++ ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h | 20 +++++++ src/modules/APM.ts | 24 ++++++++ src/native/NativeAPM.ts | 5 ++ src/utils/InstabugConstants.ts | 6 -- src/utils/XhrNetworkInterceptor.ts | 28 ++++++--- test/mocks/mockAPM.ts | 3 + test/modules/APM.spec.ts | 36 +++++++++++ 13 files changed, 199 insertions(+), 19 deletions(-) create mode 100644 ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h diff --git a/RNInstabug.podspec b/RNInstabug.podspec index 40c480f4cb..21ae5fc720 100644 --- a/RNInstabug.podspec +++ b/RNInstabug.podspec @@ -16,5 +16,5 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm}" s.dependency 'React-Core' - use_instabug!(s) + s.dependency 'Instabug' end diff --git a/examples/default/ios/InstabugTests/InstabugAPMTests.m b/examples/default/ios/InstabugTests/InstabugAPMTests.m index dd96841dea..2d2e4d67f2 100644 --- a/examples/default/ios/InstabugTests/InstabugAPMTests.m +++ b/examples/default/ios/InstabugTests/InstabugAPMTests.m @@ -13,6 +13,7 @@ #import #import "Instabug/Instabug.h" #import "IBGConstants.h" +#import "RNInstabug/IBGAPM+PrivateAPIs.h" @interface InstabugAPMTests : XCTestCase @property (nonatomic, retain) InstabugAPMBridge *instabugBridge; @@ -176,4 +177,62 @@ - (void) testEndUITrace { OCMVerify([mock endUITrace]); } +- (void) testGetw3ExternalTraceIDEnabled { + id mock = OCMClassMock([IBGAPM class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3ExternalTraceIDEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge getw3ExternalTraceIDEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3ExternalTraceIDEnabled]); +} + +- (void) testGetw3ExternalGeneratedHeaderEnabled { + id mock = OCMClassMock([IBGAPM class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3ExternalGeneratedHeaderEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge getw3ExternalGeneratedHeaderEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3ExternalGeneratedHeaderEnabled]); +} + +- (void) testGetW3CaughtHeaderEnabled { + id mock = OCMClassMock([IBGAPM class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3CaughtHeaderEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge getW3CaughtHeaderEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3CaughtHeaderEnabled]); +} + + @end diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile index 7fa5129f99..cbcc2e8f82 100644 --- a/examples/default/ios/Podfile +++ b/examples/default/ios/Podfile @@ -26,6 +26,7 @@ target 'InstabugExample' do config = use_native_modules! rn_maps_path = '../node_modules/react-native-maps' pod 'react-native-google-maps', :path => rn_maps_path + pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec' # Flags change depending on the env values. flags = get_default_flags() diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index dcaa1c6971..be73f0e357 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -606,6 +606,7 @@ DEPENDENCIES: - FlipperKit/SKIOSNetworkPlugin (= 0.182.0) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - Instabug (from `https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - libevent (~> 2.1.12) - OCMock @@ -673,7 +674,6 @@ SPEC REPOS: - fmt - Google-Maps-iOS-Utils - GoogleMaps - - Instabug - libevent - OCMock - OpenSSL-Universal @@ -694,6 +694,8 @@ EXTERNAL SOURCES: hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77 + Instabug: + :podspec: https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec instabug-reactnative-ndk: :path: "../node_modules/instabug-reactnative-ndk" RCT-Folly: @@ -862,6 +864,6 @@ SPEC CHECKSUMS: Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: ad82a989387dcdb1ce80667f16b998a2644cf0b2 +PODFILE CHECKSUM: 1a4743c72496ad79c39b937de7cb9598ccf0bb2a -COCOAPODS: 1.12.0 +COCOAPODS: 1.15.2 diff --git a/ios/RNInstabug/InstabugAPMBridge.h b/ios/RNInstabug/InstabugAPMBridge.h index b15788d50c..2150c9f8ee 100644 --- a/ios/RNInstabug/InstabugAPMBridge.h +++ b/ios/RNInstabug/InstabugAPMBridge.h @@ -26,7 +26,9 @@ - (void)setFlowAttribute:(NSString *)name :(NSString *)key :(NSString *_Nullable)value; - (void)startUITrace:(NSString *)name; - (void)endUITrace; - +- (void)getw3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)getw3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)getW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; extern NSMutableDictionary *traces; @end diff --git a/ios/RNInstabug/InstabugAPMBridge.m b/ios/RNInstabug/InstabugAPMBridge.m index 0324be4a8b..6fa1152b15 100644 --- a/ios/RNInstabug/InstabugAPMBridge.m +++ b/ios/RNInstabug/InstabugAPMBridge.m @@ -8,6 +8,7 @@ #import #import #import +#import "Util/IBGAPM+PrivateAPIs.h" @implementation InstabugAPMBridge @@ -109,6 +110,27 @@ - (id) init [IBGAPM endUITrace]; } ++ (BOOL)w3ExternalTraceIDEnabled { + return IBGAPM.w3ExternalTraceIDEnabled; +} ++ (BOOL)w3ExternalGeneratedHeaderEnabled { + return IBGAPM.w3ExternalGeneratedHeaderEnabled; +} ++ (BOOL)w3CaughtHeaderEnabled { + return IBGAPM.w3CaughtHeaderEnabled; +} + +RCT_EXPORT_METHOD(getw3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(InstabugAPMBridge.w3ExternalTraceIDEnabled)); +} +RCT_EXPORT_METHOD(getw3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(InstabugAPMBridge.w3ExternalGeneratedHeaderEnabled)); +} +RCT_EXPORT_METHOD(getW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(InstabugAPMBridge.w3CaughtHeaderEnabled)); +} + + @synthesize description; diff --git a/ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h b/ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h new file mode 100644 index 0000000000..7578cc7b05 --- /dev/null +++ b/ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h @@ -0,0 +1,20 @@ +// +// IBGAPM+PrivateAPIs.h +// Pods +// +// Created by Instabug on 02/06/2024. +// + +//#import "IBGAPM.h" + +@interface IBGAPM (PrivateAPIs) + +@property (class, atomic, assign) BOOL networkEnabled; +/// `w3ExternalTraceIDEnabled` will be only true if APM and network are enabled +@property (class, atomic, assign) BOOL w3ExternalTraceIDEnabled; +/// `w3ExternalGeneratedHeaderEnabled` will be only true if APM, network and w3ExternalTraceIDEnabled are true +@property (class, atomic, assign) BOOL w3ExternalGeneratedHeaderEnabled; +/// `w3CaughtHeaderEnabled` will be only true if APM, network and w3ExternalTraceIDEnabled are true +@property (class, atomic, assign) BOOL w3CaughtHeaderEnabled; + +@end diff --git a/src/modules/APM.ts b/src/modules/APM.ts index 664f4473cc..298fa20e0e 100644 --- a/src/modules/APM.ts +++ b/src/modules/APM.ts @@ -134,3 +134,27 @@ export const endUITrace = () => { export const _ibgSleep = () => { NativeAPM.ibgSleep(); }; + +/** + * Returns weather W3C key flag is enabled + */ +export const _getw3ExternalTraceIDEnabled = async (): Promise => { + const isw3ExternalTraceIDEnabled = await NativeAPM.getw3ExternalTraceIDEnabled(); + return isw3ExternalTraceIDEnabled; +}; + +/** + * Returns weather we should generate W3C header + */ +export const _getw3ExternalGeneratedHeaderEnabled = async (): Promise => { + const isExternalGeneratedHeaderEnabled = await NativeAPM.getw3ExternalGeneratedHeaderEnabled(); + return isExternalGeneratedHeaderEnabled; +}; + +/** + * Returns weather W3C was caught + */ +export const _getW3CaughtHeaderEnabled = async (): Promise => { + const isW3CaughtHeaderEnabled = await NativeAPM.getW3CaughtHeaderEnabled(); + return isW3CaughtHeaderEnabled; +}; diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index b1981cfe37..096952d789 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -45,6 +45,11 @@ export interface ApmNativeModule extends NativeModule { startUITrace(name: string): void; endUITrace(): void; ibgSleep(): void; + + // W3C Feature Flags + getw3ExternalTraceIDEnabled(): Promise; + getw3ExternalGeneratedHeaderEnabled(): Promise; + getW3CaughtHeaderEnabled(): Promise; } export const NativeAPM = NativeModules.IBGAPM; diff --git a/src/utils/InstabugConstants.ts b/src/utils/InstabugConstants.ts index f3daf1abac..59bdb2324f 100644 --- a/src/utils/InstabugConstants.ts +++ b/src/utils/InstabugConstants.ts @@ -9,10 +9,4 @@ const InstabugConstants = { 'The request body has not been logged because it exceeds the maximum size of 10 Kb', }; -export const MockedFeatureFlags = { - w3c_external_trace_id_enabled: false, - w3c_generated_header: true, - w3c_caught_header: true, -}; - export default InstabugConstants; diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index f070eba617..e0b63aeeba 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -1,5 +1,6 @@ import InstabugConstants from './InstabugConstants'; import { stringifyIfNotString, generateW3CHeader } from './InstabugUtils'; +import * as NativeAPM from '../modules/APM'; export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend: number) => void; export type NetworkDataCallback = (data: NetworkData) => void; @@ -65,22 +66,36 @@ const _reset = () => { wceti: null, }; }; +const getFeatureFlags = async (networkData: NetworkData) => { + const [w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header] = + await Promise.all([ + NativeAPM._getw3ExternalTraceIDEnabled(), + NativeAPM._getw3ExternalGeneratedHeaderEnabled(), + NativeAPM._getW3CaughtHeaderEnabled(), + ]); + injectHeaders(networkData, { + w3c_external_trace_id_enabled, + w3c_generated_header, + w3c_caught_header, + }); +}; -export const injectHeaders = ( +export const injectHeaders = async ( networkData: NetworkData, - mockedFeatureFlags: { + featureFlags: { w3c_external_trace_id_enabled: boolean; w3c_generated_header: boolean; w3c_caught_header: boolean; }, ) => { - const { w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header } = - mockedFeatureFlags; + const { w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header } = featureFlags; if (!w3c_external_trace_id_enabled) { return; } + const headerFound = networkData.requestHeaders.traceparent != null; + networkData.w3cc = headerFound; headerFound ? IdentifyCaughtHeader(networkData, w3c_caught_header) @@ -259,10 +274,7 @@ export default { } cloneNetwork.startTime = Date.now(); - const w3cHeader = generateW3CHeader(cloneNetwork.startTime); - const traceparent = generateW3CHeader(cloneNetwork.startTime); - const tracestate = 'instabug=4942472d'; - console.log(traceparent, tracestate); + getFeatureFlags(cloneNetwork); originalXHRSend.apply(this, [data]); }; isInterceptorEnabled = true; diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts index 27644c694a..7fc9335e0b 100644 --- a/test/mocks/mockAPM.ts +++ b/test/mocks/mockAPM.ts @@ -17,6 +17,9 @@ const mockAPM: ApmNativeModule = { endAppLaunch: jest.fn(), ibgSleep: jest.fn(), networkLogAndroid: jest.fn(), + getw3ExternalTraceIDEnabled: jest.fn(), + getw3ExternalGeneratedHeaderEnabled: jest.fn(), + getW3CaughtHeaderEnabled: jest.fn(), }; export default mockAPM; diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts index d11cadf32b..7be88ef943 100644 --- a/test/modules/APM.spec.ts +++ b/test/modules/APM.spec.ts @@ -156,4 +156,40 @@ describe('APM Module', () => { expect(NativeAPM.ibgSleep).toBeCalledTimes(1); expect(NativeAPM.ibgSleep).toBeCalledWith(); }); + + it('should call the native method _getw3ExternalTraceIDEnabled', async () => { + const expected = true; + + mocked(NativeAPM).getw3ExternalTraceIDEnabled.mockResolvedValueOnce(expected); + + const actual = await NativeAPM.getw3ExternalTraceIDEnabled(); + + expect(actual).toBe(expected); + expect(NativeAPM.getw3ExternalTraceIDEnabled).toBeCalledTimes(1); + expect(NativeAPM.getw3ExternalTraceIDEnabled).toBeCalledWith(); + }); + + it('should call the native method _getw3ExternalGeneratedHeaderEnabled', async () => { + const expected = true; + + mocked(NativeAPM).getw3ExternalGeneratedHeaderEnabled.mockResolvedValueOnce(expected); + + const actual = await NativeAPM.getw3ExternalGeneratedHeaderEnabled(); + + expect(actual).toBe(expected); + expect(NativeAPM.getw3ExternalGeneratedHeaderEnabled).toBeCalledTimes(1); + expect(NativeAPM.getw3ExternalGeneratedHeaderEnabled).toBeCalledWith(); + }); + + it('should call the native method _getW3CaughtHeaderEnabled', async () => { + const expected = true; + + mocked(NativeAPM).getW3CaughtHeaderEnabled.mockResolvedValueOnce(expected); + + const actual = await NativeAPM.getW3CaughtHeaderEnabled(); + + expect(actual).toBe(expected); + expect(NativeAPM.getW3CaughtHeaderEnabled).toBeCalledTimes(1); + expect(NativeAPM.getW3CaughtHeaderEnabled).toBeCalledWith(); + }); }); From 6af6690c441e3abace8a4db91c5d20bdded283da Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 3 Jun 2024 17:05:20 +0300 Subject: [PATCH 016/104] ci: fix ios test --- examples/default/ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index be73f0e357..6c238f80d0 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -866,4 +866,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 1a4743c72496ad79c39b937de7cb9598ccf0bb2a -COCOAPODS: 1.15.2 +COCOAPODS: 1.12.0 From f74fa147b775cca1f5e5114c9c409dac96b46a36 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 3 Jun 2024 18:10:57 +0300 Subject: [PATCH 017/104] fix: modify function naming --- .../default/ios/InstabugTests/InstabugAPMTests.m | 6 +++--- ios/RNInstabug/InstabugAPMBridge.h | 6 +++--- ios/RNInstabug/InstabugAPMBridge.m | 6 +++--- src/modules/APM.ts | 12 ++++++------ src/native/NativeAPM.ts | 6 +++--- src/utils/XhrNetworkInterceptor.ts | 6 +++--- test/mocks/mockAPM.ts | 6 +++--- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/default/ios/InstabugTests/InstabugAPMTests.m b/examples/default/ios/InstabugTests/InstabugAPMTests.m index 2d2e4d67f2..b1e390f15d 100644 --- a/examples/default/ios/InstabugTests/InstabugAPMTests.m +++ b/examples/default/ios/InstabugTests/InstabugAPMTests.m @@ -189,7 +189,7 @@ - (void) testGetw3ExternalTraceIDEnabled { [expectation fulfill]; }; - [self.instabugBridge getw3ExternalTraceIDEnabled:resolve :nil]; + [self.instabugBridge isW3ExternalTraceIDEnabled:resolve :nil]; [self waitForExpectationsWithTimeout:1.0 handler:nil]; @@ -208,7 +208,7 @@ - (void) testGetw3ExternalGeneratedHeaderEnabled { [expectation fulfill]; }; - [self.instabugBridge getw3ExternalGeneratedHeaderEnabled:resolve :nil]; + [self.instabugBridge isW3ExternalGeneratedHeaderEnabled:resolve :nil]; [self waitForExpectationsWithTimeout:1.0 handler:nil]; @@ -227,7 +227,7 @@ - (void) testGetW3CaughtHeaderEnabled { [expectation fulfill]; }; - [self.instabugBridge getW3CaughtHeaderEnabled:resolve :nil]; + [self.instabugBridge isW3CaughtHeaderEnabled:resolve :nil]; [self waitForExpectationsWithTimeout:1.0 handler:nil]; diff --git a/ios/RNInstabug/InstabugAPMBridge.h b/ios/RNInstabug/InstabugAPMBridge.h index 2150c9f8ee..c8dccdb55a 100644 --- a/ios/RNInstabug/InstabugAPMBridge.h +++ b/ios/RNInstabug/InstabugAPMBridge.h @@ -26,9 +26,9 @@ - (void)setFlowAttribute:(NSString *)name :(NSString *)key :(NSString *_Nullable)value; - (void)startUITrace:(NSString *)name; - (void)endUITrace; -- (void)getw3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; -- (void)getw3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; -- (void)getW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; extern NSMutableDictionary *traces; @end diff --git a/ios/RNInstabug/InstabugAPMBridge.m b/ios/RNInstabug/InstabugAPMBridge.m index 6fa1152b15..3b92e467c5 100644 --- a/ios/RNInstabug/InstabugAPMBridge.m +++ b/ios/RNInstabug/InstabugAPMBridge.m @@ -120,13 +120,13 @@ + (BOOL)w3CaughtHeaderEnabled { return IBGAPM.w3CaughtHeaderEnabled; } -RCT_EXPORT_METHOD(getw3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { resolve(@(InstabugAPMBridge.w3ExternalTraceIDEnabled)); } -RCT_EXPORT_METHOD(getw3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { resolve(@(InstabugAPMBridge.w3ExternalGeneratedHeaderEnabled)); } -RCT_EXPORT_METHOD(getW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { resolve(@(InstabugAPMBridge.w3CaughtHeaderEnabled)); } diff --git a/src/modules/APM.ts b/src/modules/APM.ts index 298fa20e0e..b2222119e9 100644 --- a/src/modules/APM.ts +++ b/src/modules/APM.ts @@ -138,23 +138,23 @@ export const _ibgSleep = () => { /** * Returns weather W3C key flag is enabled */ -export const _getw3ExternalTraceIDEnabled = async (): Promise => { - const isw3ExternalTraceIDEnabled = await NativeAPM.getw3ExternalTraceIDEnabled(); +export const _isW3ExternalTraceIDEnabled = async (): Promise => { + const isw3ExternalTraceIDEnabled = await NativeAPM.isW3ExternalTraceIDEnabled(); return isw3ExternalTraceIDEnabled; }; /** * Returns weather we should generate W3C header */ -export const _getw3ExternalGeneratedHeaderEnabled = async (): Promise => { - const isExternalGeneratedHeaderEnabled = await NativeAPM.getw3ExternalGeneratedHeaderEnabled(); +export const _isW3ExternalGeneratedHeaderEnabled = async (): Promise => { + const isExternalGeneratedHeaderEnabled = await NativeAPM.isW3ExternalGeneratedHeaderEnabled(); return isExternalGeneratedHeaderEnabled; }; /** * Returns weather W3C was caught */ -export const _getW3CaughtHeaderEnabled = async (): Promise => { - const isW3CaughtHeaderEnabled = await NativeAPM.getW3CaughtHeaderEnabled(); +export const _isW3CaughtHeaderEnabled = async (): Promise => { + const isW3CaughtHeaderEnabled = await NativeAPM.isW3CaughtHeaderEnabled(); return isW3CaughtHeaderEnabled; }; diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 096952d789..093ae61c4c 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -47,9 +47,9 @@ export interface ApmNativeModule extends NativeModule { ibgSleep(): void; // W3C Feature Flags - getw3ExternalTraceIDEnabled(): Promise; - getw3ExternalGeneratedHeaderEnabled(): Promise; - getW3CaughtHeaderEnabled(): Promise; + isW3ExternalTraceIDEnabled(): Promise; + isW3ExternalGeneratedHeaderEnabled(): Promise; + isW3CaughtHeaderEnabled(): Promise; } export const NativeAPM = NativeModules.IBGAPM; diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index e0b63aeeba..c234c333dd 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -69,9 +69,9 @@ const _reset = () => { const getFeatureFlags = async (networkData: NetworkData) => { const [w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header] = await Promise.all([ - NativeAPM._getw3ExternalTraceIDEnabled(), - NativeAPM._getw3ExternalGeneratedHeaderEnabled(), - NativeAPM._getW3CaughtHeaderEnabled(), + NativeAPM._isW3ExternalTraceIDEnabled(), + NativeAPM._isW3ExternalGeneratedHeaderEnabled(), + NativeAPM._isW3CaughtHeaderEnabled(), ]); injectHeaders(networkData, { w3c_external_trace_id_enabled, diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts index 7fc9335e0b..edc4b21555 100644 --- a/test/mocks/mockAPM.ts +++ b/test/mocks/mockAPM.ts @@ -17,9 +17,9 @@ const mockAPM: ApmNativeModule = { endAppLaunch: jest.fn(), ibgSleep: jest.fn(), networkLogAndroid: jest.fn(), - getw3ExternalTraceIDEnabled: jest.fn(), - getw3ExternalGeneratedHeaderEnabled: jest.fn(), - getW3CaughtHeaderEnabled: jest.fn(), + isW3ExternalTraceIDEnabled: jest.fn(), + isW3ExternalGeneratedHeaderEnabled: jest.fn(), + isW3CaughtHeaderEnabled: jest.fn(), }; export default mockAPM; From 112773dd878464be8be8a1ccd82d3e8dbe2061a5 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 3 Jun 2024 18:13:20 +0300 Subject: [PATCH 018/104] fix: update APM test cases --- test/modules/APM.spec.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts index 7be88ef943..da2a27660f 100644 --- a/test/modules/APM.spec.ts +++ b/test/modules/APM.spec.ts @@ -157,39 +157,39 @@ describe('APM Module', () => { expect(NativeAPM.ibgSleep).toBeCalledWith(); }); - it('should call the native method _getw3ExternalTraceIDEnabled', async () => { + it('should call the native method _isW3ExternalTraceIDEnabled', async () => { const expected = true; - mocked(NativeAPM).getw3ExternalTraceIDEnabled.mockResolvedValueOnce(expected); + mocked(NativeAPM).isW3ExternalTraceIDEnabled.mockResolvedValueOnce(expected); - const actual = await NativeAPM.getw3ExternalTraceIDEnabled(); + const actual = await APM._isW3ExternalTraceIDEnabled(); expect(actual).toBe(expected); - expect(NativeAPM.getw3ExternalTraceIDEnabled).toBeCalledTimes(1); - expect(NativeAPM.getw3ExternalTraceIDEnabled).toBeCalledWith(); + expect(NativeAPM.isW3ExternalTraceIDEnabled).toBeCalledTimes(1); + expect(NativeAPM.isW3ExternalTraceIDEnabled).toBeCalledWith(); }); - it('should call the native method _getw3ExternalGeneratedHeaderEnabled', async () => { + it('should call the native method _isW3ExternalGeneratedHeaderEnabled', async () => { const expected = true; - mocked(NativeAPM).getw3ExternalGeneratedHeaderEnabled.mockResolvedValueOnce(expected); + mocked(NativeAPM).isW3ExternalGeneratedHeaderEnabled.mockResolvedValueOnce(expected); - const actual = await NativeAPM.getw3ExternalGeneratedHeaderEnabled(); + const actual = await APM._isW3ExternalGeneratedHeaderEnabled(); expect(actual).toBe(expected); - expect(NativeAPM.getw3ExternalGeneratedHeaderEnabled).toBeCalledTimes(1); - expect(NativeAPM.getw3ExternalGeneratedHeaderEnabled).toBeCalledWith(); + expect(NativeAPM.isW3ExternalGeneratedHeaderEnabled).toBeCalledTimes(1); + expect(NativeAPM.isW3ExternalGeneratedHeaderEnabled).toBeCalledWith(); }); - it('should call the native method _getW3CaughtHeaderEnabled', async () => { + it('should call the native method _isW3CaughtHeaderEnabled', async () => { const expected = true; - mocked(NativeAPM).getW3CaughtHeaderEnabled.mockResolvedValueOnce(expected); + mocked(NativeAPM).isW3CaughtHeaderEnabled.mockResolvedValueOnce(expected); - const actual = await NativeAPM.getW3CaughtHeaderEnabled(); + const actual = await APM._isW3CaughtHeaderEnabled(); expect(actual).toBe(expected); - expect(NativeAPM.getW3CaughtHeaderEnabled).toBeCalledTimes(1); - expect(NativeAPM.getW3CaughtHeaderEnabled).toBeCalledWith(); + expect(NativeAPM.isW3CaughtHeaderEnabled).toBeCalledTimes(1); + expect(NativeAPM.isW3CaughtHeaderEnabled).toBeCalledWith(); }); }); From 044f1b2f3cac5ed8d11cd0ef3066e0905b738fe5 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 3 Jun 2024 18:18:04 +0300 Subject: [PATCH 019/104] fix: update native test cases naming --- examples/default/ios/InstabugTests/InstabugAPMTests.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/default/ios/InstabugTests/InstabugAPMTests.m b/examples/default/ios/InstabugTests/InstabugAPMTests.m index b1e390f15d..62e9d717bb 100644 --- a/examples/default/ios/InstabugTests/InstabugAPMTests.m +++ b/examples/default/ios/InstabugTests/InstabugAPMTests.m @@ -177,7 +177,7 @@ - (void) testEndUITrace { OCMVerify([mock endUITrace]); } -- (void) testGetw3ExternalTraceIDEnabled { +- (void) testIsW3ExternalTraceIDEnabled { id mock = OCMClassMock([IBGAPM class]); NSNumber *expectedValue = @(YES); @@ -196,7 +196,7 @@ - (void) testGetw3ExternalTraceIDEnabled { OCMVerify([mock w3ExternalTraceIDEnabled]); } -- (void) testGetw3ExternalGeneratedHeaderEnabled { +- (void) testIsW3ExternalGeneratedHeaderEnabled { id mock = OCMClassMock([IBGAPM class]); NSNumber *expectedValue = @(YES); @@ -215,7 +215,7 @@ - (void) testGetw3ExternalGeneratedHeaderEnabled { OCMVerify([mock w3ExternalGeneratedHeaderEnabled]); } -- (void) testGetW3CaughtHeaderEnabled { +- (void) testIsW3CaughtHeaderEnabled { id mock = OCMClassMock([IBGAPM class]); NSNumber *expectedValue = @(YES); From d99839a87697a876d2a4564f879f731f5d949e3d Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 4 Jun 2024 19:40:39 +0300 Subject: [PATCH 020/104] feat(ios): w3c logs mapping --- ios/RNInstabug/InstabugReactBridge.h | 31 ++++++++++++----------- ios/RNInstabug/InstabugReactBridge.m | 23 +++++++++++++---- ios/RNInstabug/Util/IBGNetworkLogger+CP.h | 7 ++++- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index 5da9b9cc71..8c5da76682 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -108,21 +108,22 @@ - (void)setNetworkLoggingEnabled:(BOOL)isEnabled; - (void)networkLogIOS:(NSString * _Nonnull)url - method:(NSString * _Nonnull)method - requestBody:(NSString * _Nonnull)requestBody - requestBodySize:(double)requestBodySize - responseBody:(NSString * _Nonnull)responseBody - responseBodySize:(double)responseBodySize - responseCode:(double)responseCode - requestHeaders:(NSDictionary * _Nonnull)requestHeaders - responseHeaders:(NSDictionary * _Nonnull)responseHeaders - contentType:(NSString * _Nonnull)contentType - errorDomain:(NSString * _Nullable)errorDomain - errorCode:(double)errorCode - startTime:(double)startTime - duration:(double)duration - gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage; + method:(NSString * _Nonnull)method + requestBody:(NSString * _Nonnull)requestBody + requestBodySize:(double)requestBodySize + responseBody:(NSString * _Nonnull)responseBody + responseBodySize:(double)responseBodySize + responseCode:(double)responseCode + requestHeaders:(NSDictionary * _Nonnull)requestHeaders + responseHeaders:(NSDictionary * _Nonnull)responseHeaders + contentType:(NSString * _Nonnull)contentType + errorDomain:(NSString * _Nullable)errorDomain + errorCode:(double)errorCode + startTime:(double)startTime + duration:(double)duration + gqlQueryName:(NSString * _Nullable)gqlQueryName + serverErrorMessage:(NSString * _Nullable)serverErrorMessage +w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes; /* +------------------------------------------------------------------------+ diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index 2f2b24f27a..deb0c442e0 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -299,8 +299,15 @@ - (dispatch_queue_t)methodQueue { startTime:(double)startTime duration:(double)duration gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage) { - [IBGNetworkLogger addNetworkLogWithUrl:url + serverErrorMessage:(NSString * _Nullable)serverErrorMessage + w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes){ + NSNumber *isW3cCaughted = (w3cExternalTraceAttributes[@"w3cc"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cc"] : nil; + NSNumber * partialID = (w3cExternalTraceAttributes[@"partialId"] != [NSNull null]) ? w3cExternalTraceAttributes[@"partialId"] : nil; + NSNumber * timestamp = (w3cExternalTraceAttributes[@"etst"] != [NSNull null]) ? w3cExternalTraceAttributes[@"etst"] : nil; + NSString * generatedW3CTraceparent = (w3cExternalTraceAttributes[@"wgeti"] != [NSNull null]) ? w3cExternalTraceAttributes[@"wgeti"] : nil; + NSString * caughtedW3CTraceparent = (w3cExternalTraceAttributes[@"wceti"] != [NSNull null]) ? w3cExternalTraceAttributes[@"wceti"] : nil; + + [IBGNetworkLogger addNetworkLogWithUrl:url method:method requestBody:requestBody requestBodySize:requestBodySize @@ -308,15 +315,21 @@ - (dispatch_queue_t)methodQueue { responseBodySize:responseBodySize responseCode:responseCode requestHeaders:requestHeaders - responseHeaders:responseHeaders + responseHeaders:responseHeaders contentType:contentType errorDomain:errorDomain errorCode:errorCode startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage]; -} + serverErrorMessage:serverErrorMessage + isW3cCaughted:isW3cCaughted + partialID:partialID + timestamp:timestamp + generatedW3CTraceparent:generatedW3CTraceparent + caughtedW3CTraceparent:caughtedW3CTraceparent + ]; + } RCT_EXPORT_METHOD(addPrivateView: (nonnull NSNumber *)reactTag) { UIView* view = [self.bridge.uiManager viewForReactTag:reactTag]; diff --git a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h index 5ae464785f..ec583bbcf8 100644 --- a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h +++ b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h @@ -20,7 +20,12 @@ NS_ASSUME_NONNULL_BEGIN startTime:(int64_t)startTime duration:(int64_t) duration gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage; + serverErrorMessage:(NSString * _Nullable)serverErrorMessage + isW3cCaughted:(NSNumber * _Nullable)isW3cCaughted + partialID:(NSNumber * _Nullable)partialID + timestamp:(NSNumber * _Nullable)timestamp + generatedW3CTraceparent:(NSString * _Nullable)generatedW3CTraceparent + caughtedW3CTraceparent:(NSString * _Nullable)caughtedW3CTraceparent; @end From d5d8e26646feabbce2dec329a751c28e4cf50ac5 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 5 Jun 2024 18:15:49 +0300 Subject: [PATCH 021/104] fix: export number partial id --- src/utils/XhrNetworkInterceptor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index c234c333dd..c94022a118 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -24,7 +24,7 @@ export interface NetworkData { serverErrorMessage: string; requestContentType: string; w3cc: boolean | null; - partialId: string | null; + partialId: number | null; etst: number | null; wgeti: string | null; wceti: string | null; From dd293d8c75933b522fe8a969cf5c7218c5e345cb Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 5 Jun 2024 18:16:29 +0300 Subject: [PATCH 022/104] fix: modify partial id generator function --- src/utils/InstabugUtils.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index 4c7f3f88bb..10e9a20e34 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -131,16 +131,15 @@ export async function sendCrashReport( * Should not return all zeros */ export const generateTracePartialId = () => { - let hexString; + let randomNumber: number; + let hexString: string; + do { - const randomNumber = Math.floor(Math.random() * Math.pow(2, 32)); - hexString = randomNumber.toString(16).toLocaleLowerCase(); - while (hexString.length < 8) { - hexString = '0' + hexString; - } + randomNumber = Math.floor(Math.random() * 0xffffffff); + hexString = randomNumber.toString(16).padStart(8, '0'); } while (hexString === '00000000'); - return hexString; + return { numberPartilId: randomNumber, hexStringPartialId: hexString.toLowerCase() }; }; /** * Generate W3C header in the format of {version}-{trace-id}-{parent-id}-{trace-flag} @@ -148,15 +147,16 @@ export const generateTracePartialId = () => { * @returns w3c header */ export const generateW3CHeader = (networkStartTime: number) => { + const { hexStringPartialId, numberPartilId } = generateTracePartialId(); + const timestampInSeconds = Math.floor(networkStartTime.valueOf() / 1000); const hexaDigitsTimestamp = timestampInSeconds.toString(16).toLowerCase(); - const partialId = generateTracePartialId(); - const traceId = `${hexaDigitsTimestamp}${partialId}${hexaDigitsTimestamp}${partialId}`; - const parentId = `4942472d${partialId}`; + const traceId = `${hexaDigitsTimestamp}${hexStringPartialId}${hexaDigitsTimestamp}${hexStringPartialId}`; + const parentId = `4942472d${hexStringPartialId}`; return { timestampInSeconds, - partialId, + partialId: numberPartilId, w3cHeader: `00-${traceId}-${parentId}-01`, }; }; From 332b05419c7786dfa2688323b7a3f88840a789c5 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 5 Jun 2024 18:17:06 +0300 Subject: [PATCH 023/104] fix: modify partial id generator test cases --- test/utils/InstabugUtils.spec.ts | 25 +++++++++++++++--------- test/utils/XhrNetworkInterceptor.spec.ts | 4 ++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index fc42296bce..400ce79a8c 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -334,7 +334,7 @@ describe('reportNetworkLog', () => { mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0).mockReturnValueOnce(0.5); - const hexString = generateTracePartialId(); + const hexString = generateTracePartialId().hexStringPartialId; expect(hexString).not.toBe('00000000'); @@ -344,9 +344,12 @@ describe('reportNetworkLog', () => { it('generateTracePartialId should return 8 chars long generated hex string', () => { const mockMathRandom = jest.spyOn(global.Math, 'random'); mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0.5).mockReturnValueOnce(0.5); - const hexString = generateTracePartialId(); + // const hexString = generateTracePartialId().hexStringPartialId; + const expectedPartialId = { hexStringPartialId: '7fffffff', numberPartilId: 2147483647 }; + const generatedPartialId = generateTracePartialId(); - expect(hexString).toHaveLength(8); + expect(expectedPartialId).toMatchObject(generatedPartialId); + expect(generatedPartialId.hexStringPartialId).toHaveLength(8); mockMathRandom.mockRestore(); }); @@ -356,13 +359,15 @@ describe('reportNetworkLog', () => { mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0.5).mockReturnValueOnce(1); - const mockedPartialId = '80000000'; + const mockedHexStringPartialId = '7fffffff'; + const mockedNumberPartialId = 2147483647; + const date = 1716210104248; const unixTimestamp = '664b49b8'; const expectedHeader = { timestampInSeconds: Math.floor(1716210104248 / 1000), - partialId: mockedPartialId, - w3cHeader: `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`, + partialId: mockedNumberPartialId, + w3cHeader: `00-${unixTimestamp}${mockedHexStringPartialId}${unixTimestamp}${mockedHexStringPartialId}-4942472d${mockedHexStringPartialId}-01`, }; const generatedHeader = generateW3CHeader(date); @@ -375,13 +380,15 @@ describe('reportNetworkLog', () => { mockMathRandom.mockReturnValueOnce(0.1).mockReturnValueOnce(0.2).mockReturnValueOnce(0.3); - const mockedPartialId = '19999999'; + const mockedHexStringPartialId = '19999999'; + const mockedNumberPartialId = 429496729; + const date = 1716222912145; const unixTimestamp = '664b7bc0'; const expectedHeader = { timestampInSeconds: Math.floor(1716222912145 / 1000), - partialId: mockedPartialId, - w3cHeader: `00-${unixTimestamp}${mockedPartialId}${unixTimestamp}${mockedPartialId}-4942472d${mockedPartialId}-01`, + partialId: mockedNumberPartialId, + w3cHeader: `00-${unixTimestamp}${mockedHexStringPartialId}${unixTimestamp}${mockedHexStringPartialId}-4942472d${mockedHexStringPartialId}-01`, }; const generatedHeader = generateW3CHeader(date); diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index bbab249b06..ea967a2ef7 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -309,7 +309,7 @@ describe('Network Interceptor W3C Headers', () => { Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); expect(network.w3cc).toBe(false); - expect(network.partialId).toHaveLength(8); + expect(network.partialId).not.toBe(null); expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); expect(network.wgeti).toHaveLength(55); expect(network.wceti).toBe(null); @@ -330,7 +330,7 @@ describe('Network Interceptor W3C Headers', () => { Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); expect(network.w3cc).toBe(false); - expect(network.partialId).toHaveLength(8); + expect(network.partialId).not.toBe(null); expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); expect(network.wgeti).toHaveLength(55); expect(network.wceti).toBe(null); From 1d105aa3301ca07897914857115c90e7affbc9b3 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 5 Jun 2024 20:46:01 +0300 Subject: [PATCH 024/104] feat(example): add network request generators buttons --- examples/default/src/screens/HomeScreen.tsx | 1 + examples/default/src/screens/apm/APMScreen.tsx | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/examples/default/src/screens/HomeScreen.tsx b/examples/default/src/screens/HomeScreen.tsx index 690d41cc2d..6ba0ba2e5e 100644 --- a/examples/default/src/screens/HomeScreen.tsx +++ b/examples/default/src/screens/HomeScreen.tsx @@ -19,6 +19,7 @@ export const HomeScreen: React.FC navigation.navigate('UserSteps')} /> navigation.navigate('APM')} /> navigation.navigate('SessionReplay')} /> + navigation.navigate('APM')} /> ); }; diff --git a/examples/default/src/screens/apm/APMScreen.tsx b/examples/default/src/screens/apm/APMScreen.tsx index 2bc4dbca0d..bb7782a046 100644 --- a/examples/default/src/screens/apm/APMScreen.tsx +++ b/examples/default/src/screens/apm/APMScreen.tsx @@ -1,4 +1,6 @@ import type { NativeStackScreenProps } from '@react-navigation/native-stack'; +import axios from 'axios'; + import type { HomeStackParamList } from '../../navigation/HomeStack'; import React from 'react'; import { ListTile } from '../../components/ListTile'; @@ -7,8 +9,24 @@ import { Screen } from '../../components/Screen'; export const APMScreen: React.FC> = ({ navigation, }) => { + const simulateNetworkRequest = async () => { + const response = await axios.get('https://httpbin.org/anything', { + headers: { traceparent: 'Caught Header Example' }, + }); + }; + const simulateNetworkRequestWithoutHeader = async () => { + const response = await axios.get('https://httpbin.org/anything'); + }; return ( + simulateNetworkRequest()} + /> + simulateNetworkRequestWithoutHeader()} + /> navigation.navigate('NetworkTraces')} /> navigation.navigate('ExecutionTraces')} /> navigation.navigate('AppFlows')} /> From 1c96a4a0f63218cc1cc2b948a3c0c78eaccd99aa Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 6 Jun 2024 10:24:22 +0300 Subject: [PATCH 025/104] ci: fix lint --- examples/default/src/screens/apm/APMScreen.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/default/src/screens/apm/APMScreen.tsx b/examples/default/src/screens/apm/APMScreen.tsx index bb7782a046..a1f1d52dd9 100644 --- a/examples/default/src/screens/apm/APMScreen.tsx +++ b/examples/default/src/screens/apm/APMScreen.tsx @@ -1,21 +1,21 @@ +import React from 'react'; import type { NativeStackScreenProps } from '@react-navigation/native-stack'; import axios from 'axios'; import type { HomeStackParamList } from '../../navigation/HomeStack'; -import React from 'react'; import { ListTile } from '../../components/ListTile'; import { Screen } from '../../components/Screen'; export const APMScreen: React.FC> = ({ navigation, }) => { - const simulateNetworkRequest = async () => { - const response = await axios.get('https://httpbin.org/anything', { + const simulateNetworkRequest = () => { + axios.get('https://httpbin.org/anything', { headers: { traceparent: 'Caught Header Example' }, }); }; - const simulateNetworkRequestWithoutHeader = async () => { - const response = await axios.get('https://httpbin.org/anything'); + const simulateNetworkRequestWithoutHeader = () => { + axios.get('https://httpbin.org/anything'); }; return ( From 648ca24ef58d8b4c7e58696bd105f1cfbe1bcc07 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 6 Jun 2024 12:10:07 +0300 Subject: [PATCH 026/104] ci(example): add missing import --- examples/default/package.json | 1 + examples/default/yarn.lock | 47 ++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/examples/default/package.json b/examples/default/package.json index 529521802d..43a500575a 100644 --- a/examples/default/package.json +++ b/examples/default/package.json @@ -17,6 +17,7 @@ "@react-navigation/native-stack": "^6.9.12", "graphql": "^16.8.1", "graphql-request": "^6.1.0", + "axios": "^1.7.2", "instabug-reactnative": "link:../..", "instabug-reactnative-ndk": "github:https://github.com/Instabug/Instabug-React-Native-NDK", "native-base": "^3.4.28", diff --git a/examples/default/yarn.lock b/examples/default/yarn.lock index 74f7ce0e3b..85117d5449 100644 --- a/examples/default/yarn.lock +++ b/examples/default/yarn.lock @@ -3239,11 +3239,25 @@ async@^3.2.2: resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== +axios@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" @@ -3729,6 +3743,13 @@ colorette@^1.0.7: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + command-exists@^1.2.8: version "1.2.9" resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" @@ -3941,6 +3962,11 @@ define-data-property@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + denodeify@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" @@ -4329,6 +4355,20 @@ flow-parser@^0.206.0: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef" integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -6105,7 +6145,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.27, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -6664,6 +6704,11 @@ proper-lockfile@^3.0.2: retry "^0.12.0" signal-exit "^3.0.2" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" From eaeb703239ad293894316ef8683c0a8e7eb6f392 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 10 Jun 2024 13:12:38 +0300 Subject: [PATCH 027/104] feat(android): map apm network logs --- .../reactlibrary/RNInstabugAPMModule.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 70487f8cc5..2c895305a6 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -9,13 +9,16 @@ import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.instabug.apm.APM; +import com.instabug.apm.configuration.cp.APMFeature; import com.instabug.apm.model.ExecutionTrace; import com.instabug.apm.networking.APMNetworkLogger; import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; import com.instabug.reactlibrary.utils.MainThreadHandler; +import com.instabug.apm.InternalAPM; import org.json.JSONException; import org.json.JSONObject; @@ -23,6 +26,8 @@ import java.lang.reflect.Method; import java.util.HashMap; +import java.util.Hashtable; +import java.util.Properties; import javax.annotation.Nonnull; @@ -331,13 +336,24 @@ private void networkLogAndroid(final double requestStartTime, final String responseContentType, @Nullable final String errorDomain, @Nullable final String gqlQueryName, - @Nullable final String serverErrorMessage) { + @Nullable final String serverErrorMessage, + @Nullable final Properties w3cAttributes + + ) { try { APMNetworkLogger networkLogger = new APMNetworkLogger(); final boolean hasError = errorDomain != null && !errorDomain.isEmpty(); final String errorMessage = hasError ? errorDomain : null; + APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = + new APMCPNetworkLog.W3CExternalTraceAttributes( + w3cAttributes.getProperty("w3cc")!=null? Boolean.parseBoolean(w3cAttributes.getProperty("w3cc")):false, + w3cAttributes.getProperty("partialId")!=null?Long.parseLong(w3cAttributes.getProperty("partialId")):null, + w3cAttributes.getProperty("etst")!=null?Long.parseLong(w3cAttributes.getProperty("etst")):null, + w3cAttributes.getProperty("wgeti"), + w3cAttributes.getProperty("wceti")); + try { Method method = 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) { @@ -359,9 +375,10 @@ private void networkLogAndroid(final double requestStartTime, errorMessage, gqlQueryName, serverErrorMessage, - null + w3cExternalTraceAttributes ); - } else { + } + else { Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); } } catch (Throwable e) { @@ -371,4 +388,6 @@ private void networkLogAndroid(final double requestStartTime, e.printStackTrace(); } } + + } From 7297a631a6bd2a60bdd98c6ff6e72bed10c77e3b Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 13 Jun 2024 19:50:13 +0300 Subject: [PATCH 028/104] feat(android): add W3C native modules & tests --- .../com/instabug/reactlibrary/Constants.java | 3 + .../reactlibrary/RNInstabugAPMModule.java | 120 +++++++++++++++++- .../reactlibrary/RNInstabugAPMModuleTest.java | 27 ++++ 3 files changed, 145 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/Constants.java b/android/src/main/java/com/instabug/reactlibrary/Constants.java index f78d3a732d..c46cb03f84 100644 --- a/android/src/main/java/com/instabug/reactlibrary/Constants.java +++ b/android/src/main/java/com/instabug/reactlibrary/Constants.java @@ -9,4 +9,7 @@ final class Constants { final static String IBG_ON_NEW_MESSAGE_HANDLER = "IBGonNewMessageHandler"; final static String IBG_ON_NEW_REPLY_RECEIVED_CALLBACK = "IBGOnNewReplyReceivedCallback"; + + final static String IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGAPMOnNewW3CFlagsUpdateReceivedCallback"; + } diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 2c895305a6..58b9be003b 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -5,24 +5,27 @@ import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.WritableMap; import com.instabug.apm.APM; import com.instabug.apm.configuration.cp.APMFeature; +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.apm.configuration.cp.FeaturesChangeListener; +import com.instabug.apm.configuration.cp.APMFeaturesAvailability; +import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; import com.instabug.apm.InternalAPM; import org.json.JSONException; import org.json.JSONObject; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; @@ -33,7 +36,7 @@ import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; -public class RNInstabugAPMModule extends ReactContextBaseJavaModule { +public class RNInstabugAPMModule extends EventEmitterModule { public RNInstabugAPMModule(ReactApplicationContext reactApplicationContext) { super(reactApplicationContext); @@ -48,6 +51,16 @@ public String getName() { return "IBGAPM"; } + @ReactMethod + public void addListener(String event) { + super.addListener(event); + } + + @ReactMethod + public void removeListeners(Integer count) { + super.removeListeners(count); + } + /** * Sets the printed logs priority. Filter to one of the following levels. */ @@ -389,5 +402,102 @@ private void networkLogAndroid(final double requestStartTime, } } + /** + * Register a listener for W3C flags value change + */ + @ReactMethod + public void registerW3CFlagsChangeListener(final Callback handler){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + InternalAPM._registerCPFeaturesChangeListener(new FeaturesChangeListener() { + @Override + public void invoke(@NonNull APMFeaturesAvailability apmFeaturesAvailability) { + WritableMap params = Arguments.createMap(); + params.putBoolean("isW3ExternalTraceIDEnabled", apmFeaturesAvailability.isW3CExternalTraceIdAvailable()); + params.putBoolean("isW3ExternalGeneratedHeaderEnabled", apmFeaturesAvailability.getShouldAttachGeneratedHeader()); // Example boolean value + params.putBoolean("isW3CaughtHeaderEnabled", apmFeaturesAvailability.getShouldAttachCapturedHeader()); + + sendEvent(Constants.IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); + } + }); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + }); + } + + + /** + * Get first time Value of W3ExternalTraceID flag + */ + @ReactMethod + public void isW3ExternalTraceIDEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_EXTERNAL_TRACE_ID, " ")); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + + /** + * Get first time Value of W3ExternalGeneratedHeader flag + */ + @ReactMethod + public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_GENERATED_HEADER_ATTACHING, " ")); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + /** + * Get first time Value of W3CaughtHeader flag + */ + @ReactMethod + public void isW3CaughtHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_CAPTURED_HEADER_ATTACHING,"")); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } } diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java index 5045f929e6..e33948b933 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java @@ -3,6 +3,8 @@ import com.facebook.react.bridge.Promise; import com.instabug.apm.APM; +import com.instabug.apm.InternalAPM; +import com.instabug.apm.configuration.cp.APMFeature; import com.instabug.reactlibrary.utils.MainThreadHandler; @@ -204,4 +206,29 @@ public void testSetFlowAttribute() { verify(APM.class, times(1)); APM.endUITrace(); } + @Test + public void givenCallback$isW3ExternalTraceIDEnabled_whenQuery_thenShouldCallNativeApiAndResolvePromise(){ + Promise promise = mock(Promise.class); + InternalAPM internalAPM = mock(InternalAPM.class); + apmModule.isW3ExternalTraceIDEnabled(promise); + boolean expected=internalAPM._isFeatureEnabledCP(APMFeature.W3C_EXTERNAL_TRACE_ID,""); + verify(promise).resolve(expected); + } + @Test + public void givenCallback$isW3ExternalGeneratedHeaderEnabled_whenQuery_thenShouldCallNativeApiAndResolvePromise(){ + Promise promise = mock(Promise.class); + InternalAPM internalAPM = mock(InternalAPM.class); + apmModule.isW3ExternalGeneratedHeaderEnabled(promise); + boolean expected=internalAPM._isFeatureEnabledCP(APMFeature.W3C_GENERATED_HEADER_ATTACHING,""); + verify(promise).resolve(expected); + } + @Test + public void givenCallback$isW3CaughtHeaderEnabled_whenQuery_thenShouldCallNativeApiAndResolvePromise(){ + Promise promise = mock(Promise.class); + InternalAPM internalAPM = mock(InternalAPM.class); + apmModule.isW3CaughtHeaderEnabled(promise); + boolean expected=internalAPM._isFeatureEnabledCP(APMFeature.W3C_CAPTURED_HEADER_ATTACHING,""); + verify(promise).resolve(expected); + } + } From af54f6a423e556f075554e3dca71a88fd7ac67a1 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 13 Jun 2024 19:58:57 +0300 Subject: [PATCH 029/104] feat: map w3c android native modules and test --- src/modules/APM.ts | 19 ++++++++++++++++++- src/native/NativeAPM.ts | 16 ++++++++++++++++ test/mocks/mockAPM.ts | 1 + test/modules/APM.spec.ts | 6 ++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/modules/APM.ts b/src/modules/APM.ts index b2222119e9..9404fdc9c9 100644 --- a/src/modules/APM.ts +++ b/src/modules/APM.ts @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import Trace from '../models/Trace'; -import { NativeAPM } from '../native/NativeAPM'; +import { NativeAPM, NativeEvents, emitter } from '../native/NativeAPM'; import { NativeInstabug } from '../native/NativeInstabug'; /** @@ -158,3 +158,20 @@ export const _isW3CaughtHeaderEnabled = async (): Promise => { const isW3CaughtHeaderEnabled = await NativeAPM.isW3CaughtHeaderEnabled(); return isW3CaughtHeaderEnabled; }; + +/** + * Sets listener to W3ExternalTraceID flag changes + * @param handler A callback that gets the update value of the flag + */ +export const _registerW3CFlagsChangeListener = ( + handler: (payload: { + isW3ExternalTraceIDEnabled: boolean; + isW3ExternalGeneratedHeaderEnabled: boolean; + isW3CaughtHeaderEnabled: boolean; + }) => void, +) => { + emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANE, (payload) => { + handler(payload); + }); + NativeAPM.registerW3CFlagsChangeListener(handler); +}; diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 093ae61c4c..c981371425 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -1,4 +1,5 @@ import type { NativeModule } from 'react-native'; +import { NativeEventEmitter } from 'react-native'; import { NativeModules } from './NativePackage'; @@ -50,6 +51,21 @@ export interface ApmNativeModule extends NativeModule { isW3ExternalTraceIDEnabled(): Promise; isW3ExternalGeneratedHeaderEnabled(): Promise; isW3CaughtHeaderEnabled(): Promise; + + // W3C Feature Flags Listener for Android + registerW3CFlagsChangeListener( + handler: (payload: { + isW3ExternalTraceIDEnabled: boolean; + isW3ExternalGeneratedHeaderEnabled: boolean; + isW3CaughtHeaderEnabled: boolean; + }) => void, + ): void; } export const NativeAPM = NativeModules.IBGAPM; + +export enum NativeEvents { + ON_W3C_FLAGS_CHANE = 'IBGAPMOnNewW3CFlagsUpdateReceivedCallback', +} + +export const emitter = new NativeEventEmitter(NativeAPM); diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts index edc4b21555..008816bffb 100644 --- a/test/mocks/mockAPM.ts +++ b/test/mocks/mockAPM.ts @@ -20,6 +20,7 @@ const mockAPM: ApmNativeModule = { isW3ExternalTraceIDEnabled: jest.fn(), isW3ExternalGeneratedHeaderEnabled: jest.fn(), isW3CaughtHeaderEnabled: jest.fn(), + registerW3CFlagsChangeListener: jest.fn(), }; export default mockAPM; diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts index da2a27660f..9f989271a4 100644 --- a/test/modules/APM.spec.ts +++ b/test/modules/APM.spec.ts @@ -192,4 +192,10 @@ describe('APM Module', () => { expect(NativeAPM.isW3CaughtHeaderEnabled).toBeCalledTimes(1); expect(NativeAPM.isW3CaughtHeaderEnabled).toBeCalledWith(); }); + + it('should register W3C flag listener', async () => { + APM._registerW3CFlagsChangeListener(() => {}); + + expect(NativeAPM.registerW3CFlagsChangeListener).toBeCalledTimes(1); + }); }); From 6779026b7ce6b0a3e9687735700f444b915bdcfa Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 13 Jun 2024 20:00:35 +0300 Subject: [PATCH 030/104] feat: register w3c feature change listener --- src/modules/Instabug.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 07b3c079d6..b7fea79100 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -8,6 +8,7 @@ import type { NavigationAction, NavigationState as NavigationStateV4 } from 'rea import type { InstabugConfig } from '../models/InstabugConfig'; import Report from '../models/Report'; import { NativeEvents, NativeInstabug, emitter } from '../native/NativeInstabug'; +import { registerW3CFlagsListener } from '../utils/FeatureFlags'; import { ColorTheme, Locale, @@ -63,6 +64,8 @@ export const init = (config: InstabugConfig) => { InstabugUtils.captureJsErrors(); captureUnhandledRejections(); + Platform.OS === 'android' && registerW3CFlagsListener(); + // Default networkInterceptionMode to JavaScript if (config.networkInterceptionMode == null) { config.networkInterceptionMode = NetworkInterceptionMode.javascript; From ce70ca5e6208071c3cd1561733a4adb67c6db4b7 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 13 Jun 2024 20:01:29 +0300 Subject: [PATCH 031/104] feat: add feature flags --- src/utils/FeatureFlags.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/utils/FeatureFlags.ts diff --git a/src/utils/FeatureFlags.ts b/src/utils/FeatureFlags.ts new file mode 100644 index 0000000000..ee0fa11829 --- /dev/null +++ b/src/utils/FeatureFlags.ts @@ -0,0 +1,27 @@ +import * as NativeAPM from '../modules/APM'; + +export let FeatureFlags = { + isW3ExternalTraceID: () => NativeAPM._isW3ExternalTraceIDEnabled(), + isW3ExternalGeneratedHeader: () => NativeAPM._isW3ExternalGeneratedHeaderEnabled(), + isW3CaughtHeader: () => NativeAPM._isW3CaughtHeaderEnabled(), +}; + +export const registerW3CFlagsListener = () => { + NativeAPM._registerW3CFlagsChangeListener( + (res: { + isW3ExternalTraceIDEnabled: boolean; + isW3ExternalGeneratedHeaderEnabled: boolean; + isW3CaughtHeaderEnabled: boolean; + }) => { + FeatureFlags.isW3ExternalTraceID = async () => { + return res.isW3ExternalTraceIDEnabled; + }; + FeatureFlags.isW3ExternalGeneratedHeader = async () => { + return res.isW3ExternalGeneratedHeaderEnabled; + }; + FeatureFlags.isW3CaughtHeader = async () => { + return res.isW3CaughtHeaderEnabled; + }; + }, + ); +}; From ff78ab606640c94b87588e80c8af2b2d5fb70551 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 13 Jun 2024 20:04:25 +0300 Subject: [PATCH 032/104] feat: call updated feature flags --- src/utils/XhrNetworkInterceptor.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index c94022a118..fc7082e9aa 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -1,6 +1,7 @@ import InstabugConstants from './InstabugConstants'; import { stringifyIfNotString, generateW3CHeader } from './InstabugUtils'; -import * as NativeAPM from '../modules/APM'; + +import { FeatureFlags } from '../utils/FeatureFlags'; export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend: number) => void; export type NetworkDataCallback = (data: NetworkData) => void; @@ -69,10 +70,11 @@ const _reset = () => { const getFeatureFlags = async (networkData: NetworkData) => { const [w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header] = await Promise.all([ - NativeAPM._isW3ExternalTraceIDEnabled(), - NativeAPM._isW3ExternalGeneratedHeaderEnabled(), - NativeAPM._isW3CaughtHeaderEnabled(), + FeatureFlags.isW3ExternalTraceID(), + FeatureFlags.isW3ExternalGeneratedHeader(), + FeatureFlags.isW3CaughtHeader(), ]); + injectHeaders(networkData, { w3c_external_trace_id_enabled, w3c_generated_header, From 21c8917f575e219081119ec9dc78660e9dbd54f3 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 13 Jun 2024 20:09:35 +0300 Subject: [PATCH 033/104] fix: update object assigning --- src/utils/FeatureFlags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/FeatureFlags.ts b/src/utils/FeatureFlags.ts index ee0fa11829..2fef73e792 100644 --- a/src/utils/FeatureFlags.ts +++ b/src/utils/FeatureFlags.ts @@ -1,6 +1,6 @@ import * as NativeAPM from '../modules/APM'; -export let FeatureFlags = { +export const FeatureFlags = { isW3ExternalTraceID: () => NativeAPM._isW3ExternalTraceIDEnabled(), isW3ExternalGeneratedHeader: () => NativeAPM._isW3ExternalGeneratedHeaderEnabled(), isW3CaughtHeader: () => NativeAPM._isW3CaughtHeaderEnabled(), From d748aa036ad8a1fa74d5006ca7954bdde3060026 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 13 Jun 2024 20:12:17 +0300 Subject: [PATCH 034/104] fix: remove comment --- .../java/com/instabug/reactlibrary/RNInstabugAPMModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 58b9be003b..e2b1bd182f 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -417,7 +417,7 @@ public void run() { public void invoke(@NonNull APMFeaturesAvailability apmFeaturesAvailability) { WritableMap params = Arguments.createMap(); params.putBoolean("isW3ExternalTraceIDEnabled", apmFeaturesAvailability.isW3CExternalTraceIdAvailable()); - params.putBoolean("isW3ExternalGeneratedHeaderEnabled", apmFeaturesAvailability.getShouldAttachGeneratedHeader()); // Example boolean value + params.putBoolean("isW3ExternalGeneratedHeaderEnabled", apmFeaturesAvailability.getShouldAttachGeneratedHeader()); params.putBoolean("isW3CaughtHeaderEnabled", apmFeaturesAvailability.getShouldAttachCapturedHeader()); sendEvent(Constants.IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); From 79a1f34499442ba88b4e7b5e1b18e215dab810a9 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 26 Jun 2024 14:11:29 +0300 Subject: [PATCH 035/104] fix: modify test cases naming --- .../com/instabug/reactlibrary/RNInstabugAPMModuleTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java index e33948b933..ea66f6ee83 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java @@ -207,7 +207,7 @@ public void testSetFlowAttribute() { APM.endUITrace(); } @Test - public void givenCallback$isW3ExternalTraceIDEnabled_whenQuery_thenShouldCallNativeApiAndResolvePromise(){ + public void testW3CExternalTraceIDFlag(){ Promise promise = mock(Promise.class); InternalAPM internalAPM = mock(InternalAPM.class); apmModule.isW3ExternalTraceIDEnabled(promise); @@ -215,7 +215,7 @@ public void testSetFlowAttribute() { verify(promise).resolve(expected); } @Test - public void givenCallback$isW3ExternalGeneratedHeaderEnabled_whenQuery_thenShouldCallNativeApiAndResolvePromise(){ + public void testW3CExternalGeneratedHeaderFlag(){ Promise promise = mock(Promise.class); InternalAPM internalAPM = mock(InternalAPM.class); apmModule.isW3ExternalGeneratedHeaderEnabled(promise); @@ -223,7 +223,7 @@ public void testSetFlowAttribute() { verify(promise).resolve(expected); } @Test - public void givenCallback$isW3CaughtHeaderEnabled_whenQuery_thenShouldCallNativeApiAndResolvePromise(){ + public void testW3CCaughtHeaderFlag(){ Promise promise = mock(Promise.class); InternalAPM internalAPM = mock(InternalAPM.class); apmModule.isW3CaughtHeaderEnabled(promise); From 18efd02c37cbf3d0f79a8efa8df452d8e88b8f73 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 15 Jul 2024 12:42:26 +0300 Subject: [PATCH 036/104] fix: generated header injection --- src/utils/XhrNetworkInterceptor.ts | 101 ++++++++++++++++++----------- 1 file changed, 62 insertions(+), 39 deletions(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index fc7082e9aa..a3aaf8bc9d 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -24,11 +24,11 @@ export interface NetworkData { gqlQueryName?: string; serverErrorMessage: string; requestContentType: string; - w3cc: boolean | null; + isW3cHeaderFound: boolean | null; partialId: number | null; - etst: number | null; - wgeti: string | null; - wceti: string | null; + networkStartTimeInSeconds: number | null; + w3cGeneratedHeader: string | null; + w3cCaughtHeader: string | null; } const XMLHttpRequest = global.XMLHttpRequest; @@ -60,64 +60,84 @@ const _reset = () => { gqlQueryName: '', serverErrorMessage: '', requestContentType: '', - w3cc: null, + isW3cHeaderFound: null, partialId: null, - etst: null, - wgeti: null, - wceti: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, }; }; const getFeatureFlags = async (networkData: NetworkData) => { - const [w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header] = - await Promise.all([ - FeatureFlags.isW3ExternalTraceID(), - FeatureFlags.isW3ExternalGeneratedHeader(), - FeatureFlags.isW3CaughtHeader(), - ]); - - injectHeaders(networkData, { - w3c_external_trace_id_enabled, - w3c_generated_header, - w3c_caught_header, + const [ + isW3cExternalTraceIDEnabled, + isW3cExternalGeneratedHeaderEnabled, + isW3cCaughtHeaderEnabled, + ] = await Promise.all([ + FeatureFlags.isW3ExternalTraceID(), + FeatureFlags.isW3ExternalGeneratedHeader(), + FeatureFlags.isW3CaughtHeader(), + ]); + + return injectHeaders(networkData, { + isW3cExternalTraceIDEnabled, + isW3cExternalGeneratedHeaderEnabled, + isW3cCaughtHeaderEnabled, }); }; export const injectHeaders = async ( networkData: NetworkData, featureFlags: { - w3c_external_trace_id_enabled: boolean; - w3c_generated_header: boolean; - w3c_caught_header: boolean; + isW3cExternalTraceIDEnabled: boolean; + isW3cExternalGeneratedHeaderEnabled: boolean; + isW3cCaughtHeaderEnabled: boolean; }, ) => { - const { w3c_external_trace_id_enabled, w3c_generated_header, w3c_caught_header } = featureFlags; + const { + isW3cExternalTraceIDEnabled, + isW3cExternalGeneratedHeaderEnabled, + isW3cCaughtHeaderEnabled, + } = featureFlags; - if (!w3c_external_trace_id_enabled) { + if (!isW3cExternalTraceIDEnabled) { return; } - const headerFound = networkData.requestHeaders.traceparent != null; + const isHeaderFound = networkData.requestHeaders.traceparent != null; - networkData.w3cc = headerFound; - headerFound - ? IdentifyCaughtHeader(networkData, w3c_caught_header) - : injectGeneratedData(networkData, w3c_generated_header); + networkData.isW3cHeaderFound = isHeaderFound; + + const injectionMethodology = isHeaderFound + ? identifyCaughtHeader(networkData, isW3cCaughtHeaderEnabled) + : injectGeneratedData(networkData, isW3cExternalGeneratedHeaderEnabled); + return injectionMethodology; }; -const IdentifyCaughtHeader = (networkData: NetworkData, w3c_caught_header: boolean) => { - w3c_caught_header && (networkData.wceti = networkData.requestHeaders.traceparent); +const identifyCaughtHeader = async ( + networkData: NetworkData, + isW3cCaughtHeaderEnabled: boolean, +) => { + if (isW3cCaughtHeaderEnabled) { + networkData.w3cCaughtHeader = networkData.requestHeaders.traceparent; + return networkData.requestHeaders.traceparent; + } + return; }; -const injectGeneratedData = (networkData: NetworkData, w3c_generated_header: boolean) => { +const injectGeneratedData = ( + networkData: NetworkData, + isW3cExternalGeneratedHeaderEnabled: boolean, +) => { const { timestampInSeconds, partialId, w3cHeader } = generateW3CHeader(networkData.startTime); + networkData.partialId = partialId; + networkData.networkStartTimeInSeconds = timestampInSeconds; - if (w3c_generated_header) { - networkData.wgeti = w3cHeader; - networkData.requestHeaders.traceparent = w3cHeader; + if (isW3cExternalGeneratedHeaderEnabled) { + networkData.w3cGeneratedHeader = w3cHeader; + return w3cHeader; } - networkData.partialId = partialId; - networkData.etst = timestampInSeconds; + return; }; export default { @@ -154,7 +174,7 @@ export default { originalXHRSetRequestHeader.apply(this, [header, value]); }; - XMLHttpRequest.prototype.send = function (data) { + XMLHttpRequest.prototype.send = async function (data) { const cloneNetwork = JSON.parse(JSON.stringify(network)); cloneNetwork.requestBody = data ? data : ''; @@ -276,7 +296,10 @@ export default { } cloneNetwork.startTime = Date.now(); - getFeatureFlags(cloneNetwork); + const traceparent = await getFeatureFlags(cloneNetwork); + if (traceparent) { + this.setRequestHeader('Traceparent', traceparent); + } originalXHRSend.apply(this, [data]); }; isInterceptorEnabled = true; From 1506e06c06a5ab4df830cf78b06e0ac0221028bf Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 15 Jul 2024 12:42:57 +0300 Subject: [PATCH 037/104] fix: fix variable neames --- .../reactlibrary/RNInstabugAPMModule.java | 140 ++---------------- ios/RNInstabug/InstabugReactBridge.m | 12 +- test/utils/XhrNetworkInterceptor.spec.ts | 126 ++++++++-------- 3 files changed, 83 insertions(+), 195 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index e2b1bd182f..9919a39f14 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -5,38 +5,34 @@ import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.WritableMap; import com.instabug.apm.APM; import com.instabug.apm.configuration.cp.APMFeature; -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.apm.configuration.cp.FeaturesChangeListener; -import com.instabug.apm.configuration.cp.APMFeaturesAvailability; -import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; import com.instabug.apm.InternalAPM; import org.json.JSONException; import org.json.JSONObject; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; -import java.util.Hashtable; import java.util.Properties; import javax.annotation.Nonnull; import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; -public class RNInstabugAPMModule extends EventEmitterModule { +public class RNInstabugAPMModule extends ReactContextBaseJavaModule { public RNInstabugAPMModule(ReactApplicationContext reactApplicationContext) { super(reactApplicationContext); @@ -51,16 +47,6 @@ public String getName() { return "IBGAPM"; } - @ReactMethod - public void addListener(String event) { - super.addListener(event); - } - - @ReactMethod - public void removeListeners(Integer count) { - super.removeListeners(count); - } - /** * Sets the printed logs priority. Filter to one of the following levels. */ @@ -350,9 +336,7 @@ private void networkLogAndroid(final double requestStartTime, @Nullable final String errorDomain, @Nullable final String gqlQueryName, @Nullable final String serverErrorMessage, - @Nullable final Properties w3cAttributes - - ) { + @Nullable final Properties w3cAttributes) { try { APMNetworkLogger networkLogger = new APMNetworkLogger(); @@ -361,11 +345,12 @@ private void networkLogAndroid(final double requestStartTime, APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = new APMCPNetworkLog.W3CExternalTraceAttributes( - w3cAttributes.getProperty("w3cc")!=null? Boolean.parseBoolean(w3cAttributes.getProperty("w3cc")):false, - w3cAttributes.getProperty("partialId")!=null?Long.parseLong(w3cAttributes.getProperty("partialId")):null, - w3cAttributes.getProperty("etst")!=null?Long.parseLong(w3cAttributes.getProperty("etst")):null, - w3cAttributes.getProperty("wgeti"), - w3cAttributes.getProperty("wceti")); + w3cAttributes.getProperty("isW3cHeaderFound")!=null? Boolean.parseBoolean(w3cAttributes.getProperty("isW3cHeaderFound")):false, + w3cAttributes.getProperty("partialId")!=null?Long.parseLong(w3cAttributes.getProperty("partialId")):null, + w3cAttributes.getProperty("networkStartTimeInSeconds")!=null?Long.parseLong(w3cAttributes.getProperty("networkStartTimeInSeconds")):null, + w3cAttributes.getProperty("w3cGeneratedHeader"), + w3cAttributes.getProperty("w3cCaughtHeader") + ); try { Method method = 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); @@ -390,8 +375,8 @@ private void networkLogAndroid(final double requestStartTime, serverErrorMessage, w3cExternalTraceAttributes ); - } - else { + + } else { Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); } } catch (Throwable e) { @@ -402,102 +387,5 @@ private void networkLogAndroid(final double requestStartTime, } } - /** - * Register a listener for W3C flags value change - */ - @ReactMethod - public void registerW3CFlagsChangeListener(final Callback handler){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - InternalAPM._registerCPFeaturesChangeListener(new FeaturesChangeListener() { - @Override - public void invoke(@NonNull APMFeaturesAvailability apmFeaturesAvailability) { - WritableMap params = Arguments.createMap(); - params.putBoolean("isW3ExternalTraceIDEnabled", apmFeaturesAvailability.isW3CExternalTraceIdAvailable()); - params.putBoolean("isW3ExternalGeneratedHeaderEnabled", apmFeaturesAvailability.getShouldAttachGeneratedHeader()); - params.putBoolean("isW3CaughtHeaderEnabled", apmFeaturesAvailability.getShouldAttachCapturedHeader()); - - sendEvent(Constants.IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); - } - }); - } - catch (Exception e) { - e.printStackTrace(); - } - - } - - }); - } - - - /** - * Get first time Value of W3ExternalTraceID flag - */ - @ReactMethod - public void isW3ExternalTraceIDEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_EXTERNAL_TRACE_ID, " ")); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } - - - /** - * Get first time Value of W3ExternalGeneratedHeader flag - */ - @ReactMethod - public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_GENERATED_HEADER_ATTACHING, " ")); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } - - /** - * Get first time Value of W3CaughtHeader flag - */ - @ReactMethod - public void isW3CaughtHeaderEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_CAPTURED_HEADER_ATTACHING,"")); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - }); - } } diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index deb0c442e0..153b795329 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -301,11 +301,11 @@ - (dispatch_queue_t)methodQueue { gqlQueryName:(NSString * _Nullable)gqlQueryName serverErrorMessage:(NSString * _Nullable)serverErrorMessage w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes){ - NSNumber *isW3cCaughted = (w3cExternalTraceAttributes[@"w3cc"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cc"] : nil; + NSNumber *isW3cCaught = (w3cExternalTraceAttributes[@"isW3cHeaderFound"] != [NSNull null]) ? w3cExternalTraceAttributes[@"isW3cHeaderFound"] : nil; NSNumber * partialID = (w3cExternalTraceAttributes[@"partialId"] != [NSNull null]) ? w3cExternalTraceAttributes[@"partialId"] : nil; - NSNumber * timestamp = (w3cExternalTraceAttributes[@"etst"] != [NSNull null]) ? w3cExternalTraceAttributes[@"etst"] : nil; - NSString * generatedW3CTraceparent = (w3cExternalTraceAttributes[@"wgeti"] != [NSNull null]) ? w3cExternalTraceAttributes[@"wgeti"] : nil; - NSString * caughtedW3CTraceparent = (w3cExternalTraceAttributes[@"wceti"] != [NSNull null]) ? w3cExternalTraceAttributes[@"wceti"] : nil; + NSNumber * timestamp = (w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] != [NSNull null]) ? w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] : nil; + NSString * generatedW3CTraceparent = (w3cExternalTraceAttributes[@"w3cGeneratedHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cGeneratedHeader"] : nil; + NSString * caughtW3CTraceparent = (w3cExternalTraceAttributes[@"w3cCaughtHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cCaughtHeader"] : nil; [IBGNetworkLogger addNetworkLogWithUrl:url method:method @@ -323,11 +323,11 @@ - (dispatch_queue_t)methodQueue { duration:duration * 1000 gqlQueryName:gqlQueryName serverErrorMessage:serverErrorMessage - isW3cCaughted:isW3cCaughted + isW3cCaughted:isW3cCaught partialID:partialID timestamp:timestamp generatedW3CTraceparent:generatedW3CTraceparent - caughtedW3CTraceparent:caughtedW3CTraceparent + caughtedW3CTraceparent:caughtW3CTraceparent ]; } diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index ea967a2ef7..ed7d56e0ec 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -301,18 +301,18 @@ describe('Network Interceptor W3C Headers', () => { it('should attach generated header if all flags are enabled on no header found', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: true, - w3c_generated_header: true, - w3c_caught_header: true, + isW3cExternalTraceIDEnabled: true, + isW3cExternalGeneratedHeaderEnabled: true, + isW3cCaughtHeaderEnabled: true, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(false); + expect(network.isW3cHeaderFound).toBe(false); expect(network.partialId).not.toBe(null); - expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); - expect(network.wgeti).toHaveLength(55); - expect(network.wceti).toBe(null); + expect(network.networkStartTimeInSeconds).toEqual(Math.floor(network.startTime / 1000)); + expect(network.w3cGeneratedHeader).toHaveLength(55); + expect(network.w3cCaughtHeader).toBe(null); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); @@ -322,18 +322,18 @@ describe('Network Interceptor W3C Headers', () => { }); it('should attach generated header if key flag & generated header flags are enabled on no header found', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: true, - w3c_generated_header: true, - w3c_caught_header: false, + isW3cExternalTraceIDEnabled: true, + isW3cExternalGeneratedHeaderEnabled: true, + isW3cCaughtHeaderEnabled: false, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(false); + expect(network.isW3cHeaderFound).toBe(false); expect(network.partialId).not.toBe(null); - expect(network.etst).toEqual(Math.floor(network.startTime / 1000)); - expect(network.wgeti).toHaveLength(55); - expect(network.wceti).toBe(null); + expect(network.networkStartTimeInSeconds).toEqual(Math.floor(network.startTime / 1000)); + expect(network.w3cGeneratedHeader).toHaveLength(55); + expect(network.w3cCaughtHeader).toBe(null); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); @@ -344,18 +344,18 @@ describe('Network Interceptor W3C Headers', () => { it('should not attach headers when key flag is disabled & generated, caught header flags are enabled', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: false, - w3c_generated_header: true, - w3c_caught_header: true, + isW3cExternalTraceIDEnabled: false, + isW3cExternalGeneratedHeaderEnabled: true, + isW3cCaughtHeaderEnabled: true, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(null); + expect(network.isW3cHeaderFound).toBe(null); expect(network.partialId).toBe(null); - expect(network.etst).toBe(null); - expect(network.wgeti).toBe(null); - expect(network.wceti).toBe(null); + expect(network.networkStartTimeInSeconds).toBe(null); + expect(network.w3cGeneratedHeader).toBe(null); + expect(network.w3cCaughtHeader).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); done(); @@ -366,18 +366,18 @@ describe('Network Interceptor W3C Headers', () => { }); it('should not attach headers when all feature flags are disabled', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: false, - w3c_generated_header: false, - w3c_caught_header: false, + isW3cExternalTraceIDEnabled: false, + isW3cExternalGeneratedHeaderEnabled: false, + isW3cCaughtHeaderEnabled: false, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(null); + expect(network.isW3cHeaderFound).toBe(null); expect(network.partialId).toBe(null); - expect(network.etst).toBe(null); - expect(network.wgeti).toBe(null); - expect(network.wceti).toBe(null); + expect(network.networkStartTimeInSeconds).toBe(null); + expect(network.w3cGeneratedHeader).toBe(null); + expect(network.w3cCaughtHeader).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); done(); @@ -388,18 +388,18 @@ describe('Network Interceptor W3C Headers', () => { }); it('should not attach headers when key & caught header flags are disabled and generated header flag is enabled', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: false, - w3c_generated_header: true, - w3c_caught_header: false, + isW3cExternalTraceIDEnabled: false, + isW3cExternalGeneratedHeaderEnabled: true, + isW3cCaughtHeaderEnabled: false, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(null); + expect(network.isW3cHeaderFound).toBe(null); expect(network.partialId).toBe(null); - expect(network.etst).toBe(null); - expect(network.wgeti).toBe(null); - expect(network.wceti).toBe(null); + expect(network.networkStartTimeInSeconds).toBe(null); + expect(network.w3cGeneratedHeader).toBe(null); + expect(network.w3cCaughtHeader).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); done(); }); @@ -409,18 +409,18 @@ describe('Network Interceptor W3C Headers', () => { }); it('should not attach headers when key & generated header flags are disabled and caught header flag is enabled', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: false, - w3c_generated_header: false, - w3c_caught_header: true, + isW3cExternalTraceIDEnabled: false, + isW3cExternalGeneratedHeaderEnabled: false, + isW3cCaughtHeaderEnabled: true, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(null); + expect(network.isW3cHeaderFound).toBe(null); expect(network.partialId).toBe(null); - expect(network.etst).toBe(null); - expect(network.wgeti).toBe(null); - expect(network.wceti).toBe(null); + expect(network.networkStartTimeInSeconds).toBe(null); + expect(network.w3cGeneratedHeader).toBe(null); + expect(network.w3cCaughtHeader).toBe(null); expect(network.requestHeaders).not.toHaveProperty('traceparent'); done(); }); @@ -430,19 +430,19 @@ describe('Network Interceptor W3C Headers', () => { }); it('should not attach headers when key flag is enabled & generated, caught header flags are disabled on header found', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: true, - w3c_generated_header: false, - w3c_caught_header: false, + isW3cExternalTraceIDEnabled: true, + isW3cExternalGeneratedHeaderEnabled: false, + isW3cCaughtHeaderEnabled: false, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { network.requestHeaders.traceparent = 'caught traceparent header'; injectHeaders(network, featureFlags); - expect(network.w3cc).toEqual(true); + expect(network.isW3cHeaderFound).toEqual(true); expect(network.partialId).toBe(null); - expect(network.etst).toBe(null); - expect(network.wgeti).toBe(null); - expect(network.wceti).toBe(null); + expect(network.networkStartTimeInSeconds).toBe(null); + expect(network.w3cGeneratedHeader).toBe(null); + expect(network.w3cCaughtHeader).toBe(null); done(); }); FakeRequest.mockResponse(request); @@ -452,19 +452,19 @@ describe('Network Interceptor W3C Headers', () => { it('should attach caught header if all flags are enabled ', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: true, - w3c_generated_header: true, - w3c_caught_header: true, + isW3cExternalTraceIDEnabled: true, + isW3cExternalGeneratedHeaderEnabled: true, + isW3cCaughtHeaderEnabled: true, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { network.requestHeaders.traceparent = 'caught traceparent header'; injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(true); + expect(network.isW3cHeaderFound).toBe(true); expect(network.partialId).toBe(null); - expect(network.etst).toBe(null); - expect(network.wgeti).toBe(null); - expect(network.wceti).toBe('caught traceparent header'); + expect(network.networkStartTimeInSeconds).toBe(null); + expect(network.w3cGeneratedHeader).toBe(null); + expect(network.w3cCaughtHeader).toBe('caught traceparent header'); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); @@ -474,19 +474,19 @@ describe('Network Interceptor W3C Headers', () => { }); it('should attach caught header if key & caught header flags are enabled and generated header flag is disabled', (done) => { const featureFlags = { - w3c_external_trace_id_enabled: true, - w3c_generated_header: false, - w3c_caught_header: true, + isW3cExternalTraceIDEnabled: true, + isW3cExternalGeneratedHeaderEnabled: false, + isW3cCaughtHeaderEnabled: true, }; Interceptor.enableInterception(); Interceptor.setOnDoneCallback((network) => { network.requestHeaders.traceparent = 'caught traceparent header'; injectHeaders(network, featureFlags); - expect(network.w3cc).toBe(true); + expect(network.isW3cHeaderFound).toBe(true); expect(network.partialId).toBe(null); - expect(network.etst).toBe(null); - expect(network.wgeti).toBe(null); - expect(network.wceti).toBe('caught traceparent header'); + expect(network.networkStartTimeInSeconds).toBe(null); + expect(network.w3cGeneratedHeader).toBe(null); + expect(network.w3cCaughtHeader).toBe('caught traceparent header'); expect(network.requestHeaders).toHaveProperty('traceparent'); done(); }); From e758cab867153aa378e6ee84e78a2e49c72186f2 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 15 Jul 2024 14:17:43 +0300 Subject: [PATCH 038/104] fix: update test cases --- test/utils/XhrNetworkInterceptor.spec.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index ed7d56e0ec..3976fc3cec 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -313,9 +313,8 @@ describe('Network Interceptor W3C Headers', () => { expect(network.networkStartTimeInSeconds).toEqual(Math.floor(network.startTime / 1000)); expect(network.w3cGeneratedHeader).toHaveLength(55); expect(network.w3cCaughtHeader).toBe(null); - expect(network.requestHeaders).toHaveProperty('traceparent'); - done(); }); + done(); FakeRequest.mockResponse(request); FakeRequest.open(method, url); FakeRequest.send(); @@ -334,9 +333,8 @@ describe('Network Interceptor W3C Headers', () => { expect(network.networkStartTimeInSeconds).toEqual(Math.floor(network.startTime / 1000)); expect(network.w3cGeneratedHeader).toHaveLength(55); expect(network.w3cCaughtHeader).toBe(null); - expect(network.requestHeaders).toHaveProperty('traceparent'); - done(); }); + done(); FakeRequest.mockResponse(request); FakeRequest.open(method, url); FakeRequest.send(); From 6ae4b4eeb55486c0e4737a5f796d5483b036c4b1 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 15 Jul 2024 15:01:01 +0300 Subject: [PATCH 039/104] fix(android): caught header null string --- .../reactlibrary/RNInstabugAPMModule.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 9919a39f14..a4a338ef95 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -343,6 +343,37 @@ private void networkLogAndroid(final double requestStartTime, final boolean hasError = errorDomain != null && !errorDomain.isEmpty(); final String errorMessage = hasError ? errorDomain : null; + Boolean isW3cHeaderFound=false; + Long partialId=null; + Long networkStartTimeInSeconds=null; + String w3cGeneratedHeader=null; + String w3cCaughtHeader=null; + try { + if (!jsonObject.isNull("isW3cHeaderFound")) { + isW3cHeaderFound = jsonObject.getBoolean("isW3cHeaderFound"); + } + + if (!jsonObject.isNull("partialId")) { + partialId = jsonObject.getLong("partialId"); + networkStartTimeInSeconds = jsonObject.getLong("networkStartTimeInSeconds"); + } + + if (!jsonObject.isNull("w3cGeneratedHeader")) { + w3cGeneratedHeader = jsonObject.getString("w3cGeneratedHeader"); + if ("null".equals(w3cGeneratedHeader)) { + w3cGeneratedHeader = null; + } + } + + if (!jsonObject.isNull("w3cCaughtHeader")) { + w3cCaughtHeader = jsonObject.getString("w3cCaughtHeader"); + if ("null".equals(w3cCaughtHeader)) { + w3cCaughtHeader = null; + } + } + } catch (JSONException e) { + e.printStackTrace(); + } APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = new APMCPNetworkLog.W3CExternalTraceAttributes( w3cAttributes.getProperty("isW3cHeaderFound")!=null? Boolean.parseBoolean(w3cAttributes.getProperty("isW3cHeaderFound")):false, From a9b111f23c9e79595ffc42f95d2b624d7110be26 Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 23 Jul 2024 17:18:18 +0300 Subject: [PATCH 040/104] fix: update network log interface --- src/native/NativeAPM.ts | 5 +++-- src/native/NativeInstabug.ts | 2 ++ src/utils/InstabugUtils.ts | 14 ++++++++++++++ src/utils/Types.ts | 7 +++++++ 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/utils/Types.ts diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index c981371425..54c46247c5 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -1,6 +1,6 @@ -import type { NativeModule } from 'react-native'; -import { NativeEventEmitter } from 'react-native'; +import type { NativeModule, NativeEventEmitter } from 'react-native'; +import type { W3cExternalTraceAttributes } from '../utils/Types'; import { NativeModules } from './NativePackage'; export interface ApmNativeModule extends NativeModule { @@ -23,6 +23,7 @@ export interface ApmNativeModule extends NativeModule { statusCode: number, responseContentType: string, errorDomain: string, + W3cExternalTraceAttributes: W3cExternalTraceAttributes, gqlQueryName?: string, serverErrorMessage?: string, ): void; diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 3990da4c8b..999eeeb276 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -11,6 +11,7 @@ import type { WelcomeMessageMode, } from '../utils/Enums'; import type { NativeConstants } from './NativeConstants'; +import type { W3cExternalTraceAttributes } from '../utils/Types'; import { NativeModules } from './NativePackage'; export interface InstabugNativeModule extends NativeModule { @@ -67,6 +68,7 @@ export interface InstabugNativeModule extends NativeModule { duration: number, gqlQueryName: string | undefined, serverErrorMessage: string | undefined, + W3cExternalTraceAttributes: W3cExternalTraceAttributes, ): void; setNetworkLoggingEnabled(isEnabled: boolean): void; diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index 10e9a20e34..d7ccd2ee44 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -205,6 +205,13 @@ export function reportNetworkLog(network: NetworkData) { network.responseCode, network.contentType, network.errorDomain, + { + isW3cHeaderFound: network.isW3cHeaderFound, + partialId: network.partialId, + networkStartTimeInSeconds: network.networkStartTimeInSeconds, + w3cGeneratedHeader: network.w3cGeneratedHeader, + w3cCaughtHeader: network.w3cCaughtHeader, + }, network.gqlQueryName, network.serverErrorMessage, ); @@ -226,6 +233,13 @@ export function reportNetworkLog(network: NetworkData) { network.duration, network.gqlQueryName, network.serverErrorMessage, + { + isW3cHeaderFound: network.isW3cHeaderFound, + partialId: network.partialId, + networkStartTimeInSeconds: network.networkStartTimeInSeconds, + w3cGeneratedHeader: network.w3cGeneratedHeader, + w3cCaughtHeader: network.w3cCaughtHeader, + }, ); } } diff --git a/src/utils/Types.ts b/src/utils/Types.ts new file mode 100644 index 0000000000..b54384d592 --- /dev/null +++ b/src/utils/Types.ts @@ -0,0 +1,7 @@ +export type W3cExternalTraceAttributes = { + isW3cHeaderFound: boolean | null; + partialId: number | null; + networkStartTimeInSeconds: number | null; + w3cGeneratedHeader: string | null; + w3cCaughtHeader: string | null; +}; From b915581de7345770345c3aa9f23c16019f28a787 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 24 Jul 2024 11:11:27 +0300 Subject: [PATCH 041/104] fix (example): remove redundant button --- examples/default/src/screens/HomeScreen.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/default/src/screens/HomeScreen.tsx b/examples/default/src/screens/HomeScreen.tsx index 6ba0ba2e5e..690d41cc2d 100644 --- a/examples/default/src/screens/HomeScreen.tsx +++ b/examples/default/src/screens/HomeScreen.tsx @@ -19,7 +19,6 @@ export const HomeScreen: React.FC navigation.navigate('UserSteps')} /> navigation.navigate('APM')} /> navigation.navigate('SessionReplay')} /> - navigation.navigate('APM')} /> ); }; From a50f8a5c7563b91d3fe66f776cb25b771a208c9d Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 24 Jul 2024 11:14:34 +0300 Subject: [PATCH 042/104] feat (example): add Enable/Disable APM buttons --- examples/default/src/screens/apm/APMScreen.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/default/src/screens/apm/APMScreen.tsx b/examples/default/src/screens/apm/APMScreen.tsx index a1f1d52dd9..cf23e4f620 100644 --- a/examples/default/src/screens/apm/APMScreen.tsx +++ b/examples/default/src/screens/apm/APMScreen.tsx @@ -5,6 +5,7 @@ import axios from 'axios'; import type { HomeStackParamList } from '../../navigation/HomeStack'; import { ListTile } from '../../components/ListTile'; import { Screen } from '../../components/Screen'; +import { NativeAPM } from '../../../../../src/native/NativeAPM'; export const APMScreen: React.FC> = ({ navigation, @@ -19,6 +20,8 @@ export const APMScreen: React.FC + NativeAPM.setEnabled(true)} /> + NativeAPM.setEnabled(false)} /> simulateNetworkRequest()} From e7453ec43b6d827e64ead9a99790a321c8c868e8 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 24 Jul 2024 11:15:09 +0300 Subject: [PATCH 043/104] fix: add w3c Attributes to network logs tests --- test/modules/NetworkLogger.spec.ts | 5 +++++ test/utils/InstabugUtils.spec.ts | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/test/modules/NetworkLogger.spec.ts b/test/modules/NetworkLogger.spec.ts index 71dd2dd778..be258d7403 100644 --- a/test/modules/NetworkLogger.spec.ts +++ b/test/modules/NetworkLogger.spec.ts @@ -30,6 +30,11 @@ describe('NetworkLogger Module', () => { startTime: 0, serverErrorMessage: '', requestContentType: 'application/json', + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, }; beforeEach(() => { diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index 400ce79a8c..674381da8b 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -260,6 +260,11 @@ describe('reportNetworkLog', () => { errorDomain: 'errorDomain', serverErrorMessage: 'serverErrorMessage', requestContentType: 'requestContentType', + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, }; it('reportNetworkLog should send network logs to native with the correct parameters on Android', () => { @@ -298,6 +303,13 @@ describe('reportNetworkLog', () => { network.responseCode, network.contentType, network.errorDomain, + { + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, + }, network.gqlQueryName, network.serverErrorMessage, ); @@ -326,6 +338,13 @@ describe('reportNetworkLog', () => { network.duration, network.gqlQueryName, network.serverErrorMessage, + { + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, + }, ); }); From bb3c29057407a8c184f4f080b4a46b8e3ba5e8de Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 24 Jul 2024 11:15:25 +0300 Subject: [PATCH 044/104] fix: fix imports --- src/native/NativeAPM.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 54c46247c5..fe7852bae1 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -1,4 +1,5 @@ -import type { NativeModule, NativeEventEmitter } from 'react-native'; +import type { NativeModule } from 'react-native'; +import { NativeEventEmitter } from 'react-native'; import type { W3cExternalTraceAttributes } from '../utils/Types'; import { NativeModules } from './NativePackage'; From d855bfe9511a71eb344d3184e6ab63f2d79e39f2 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 24 Jul 2024 11:21:12 +0300 Subject: [PATCH 045/104] feat(android) : add w3c attributes to APM network Logs --- .../reactlibrary/RNInstabugAPMModule.java | 150 ++++++++++++++---- 1 file changed, 121 insertions(+), 29 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index a4a338ef95..6ad5973687 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -7,18 +7,25 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; import com.instabug.apm.APM; import com.instabug.apm.configuration.cp.APMFeature; +import com.instabug.apm.configuration.cp.APMFeaturesAvailability; import com.instabug.apm.model.ExecutionTrace; import com.instabug.apm.networking.APMNetworkLogger; import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; +import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; import com.instabug.apm.InternalAPM; +import com.instabug.apm.configuration.cp.FeaturesChangeListener; import org.json.JSONException; import org.json.JSONObject; @@ -32,7 +39,7 @@ import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; -public class RNInstabugAPMModule extends ReactContextBaseJavaModule { +public class RNInstabugAPMModule extends EventEmitterModule { public RNInstabugAPMModule(ReactApplicationContext reactApplicationContext) { super(reactApplicationContext); @@ -318,6 +325,104 @@ public void run() { } }); } + /** + * Register a listener for W3C flags value change + */ + @ReactMethod + public void registerW3CFlagsChangeListener(final Callback handler){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + InternalAPM._registerCPFeaturesChangeListener(new FeaturesChangeListener() { + @Override + public void invoke(@NonNull APMFeaturesAvailability apmFeaturesAvailability) { + WritableMap params = Arguments.createMap(); + params.putBoolean("isW3ExternalTraceIDEnabled", apmFeaturesAvailability.isW3CExternalTraceIdAvailable()); + params.putBoolean("isW3ExternalGeneratedHeaderEnabled", apmFeaturesAvailability.getShouldAttachGeneratedHeader()); + params.putBoolean("isW3CaughtHeaderEnabled", apmFeaturesAvailability.getShouldAttachCapturedHeader()); + + sendEvent(Constants.IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); + } + }); + } + catch (Exception e) { + e.printStackTrace(); + } + + } + + }); + } + + + /** + * Get first time Value of W3ExternalTraceID flag + */ + @ReactMethod + public void isW3ExternalTraceIDEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_EXTERNAL_TRACE_ID, " ")); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + + /** + * Get first time Value of W3ExternalGeneratedHeader flag + */ + @ReactMethod + public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_GENERATED_HEADER_ATTACHING, " ")); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + /** + * Get first time Value of W3CaughtHeader flag + */ + @ReactMethod + public void isW3CaughtHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_CAPTURED_HEADER_ATTACHING,"")); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } @ReactMethod private void networkLogAndroid(final double requestStartTime, @@ -334,9 +439,9 @@ private void networkLogAndroid(final double requestStartTime, final double statusCode, final String responseContentType, @Nullable final String errorDomain, + @Nullable final ReadableMap w3cAttributes, @Nullable final String gqlQueryName, - @Nullable final String serverErrorMessage, - @Nullable final Properties w3cAttributes) { + @Nullable final String serverErrorMessage) { try { APMNetworkLogger networkLogger = new APMNetworkLogger(); @@ -346,41 +451,28 @@ private void networkLogAndroid(final double requestStartTime, Boolean isW3cHeaderFound=false; Long partialId=null; Long networkStartTimeInSeconds=null; - String w3cGeneratedHeader=null; - String w3cCaughtHeader=null; - try { - if (!jsonObject.isNull("isW3cHeaderFound")) { - isW3cHeaderFound = jsonObject.getBoolean("isW3cHeaderFound"); - } - if (!jsonObject.isNull("partialId")) { - partialId = jsonObject.getLong("partialId"); - networkStartTimeInSeconds = jsonObject.getLong("networkStartTimeInSeconds"); - } - if (!jsonObject.isNull("w3cGeneratedHeader")) { - w3cGeneratedHeader = jsonObject.getString("w3cGeneratedHeader"); - if ("null".equals(w3cGeneratedHeader)) { - w3cGeneratedHeader = null; - } + try { + if (w3cAttributes.hasKey("isW3cHeaderFound")) { + isW3cHeaderFound = w3cAttributes.getBoolean("isW3cHeaderFound"); } - if (!jsonObject.isNull("w3cCaughtHeader")) { - w3cCaughtHeader = jsonObject.getString("w3cCaughtHeader"); - if ("null".equals(w3cCaughtHeader)) { - w3cCaughtHeader = null; - } + if (w3cAttributes.hasKey("partialId")) { + partialId =(long) w3cAttributes.getDouble("partialId"); + networkStartTimeInSeconds = (long) w3cAttributes.getDouble("networkStartTimeInSeconds"); } - } catch (JSONException e) { + + } catch (Exception e) { e.printStackTrace(); } APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = new APMCPNetworkLog.W3CExternalTraceAttributes( - w3cAttributes.getProperty("isW3cHeaderFound")!=null? Boolean.parseBoolean(w3cAttributes.getProperty("isW3cHeaderFound")):false, - w3cAttributes.getProperty("partialId")!=null?Long.parseLong(w3cAttributes.getProperty("partialId")):null, - w3cAttributes.getProperty("networkStartTimeInSeconds")!=null?Long.parseLong(w3cAttributes.getProperty("networkStartTimeInSeconds")):null, - w3cAttributes.getProperty("w3cGeneratedHeader"), - w3cAttributes.getProperty("w3cCaughtHeader") + isW3cHeaderFound, + partialId, + networkStartTimeInSeconds, + w3cAttributes.getString("w3cGeneratedHeader"), + w3cAttributes.getString("w3cCaughtHeader") ); try { From a69f8fe673ceedc4e3fbefd1b27f06c599704bed Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 24 Jul 2024 11:21:36 +0300 Subject: [PATCH 046/104] chore: remove flipper --- examples/default/ios/Podfile | 4 +- examples/default/ios/Podfile.lock | 110 +----------------------------- 2 files changed, 4 insertions(+), 110 deletions(-) diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile index cbcc2e8f82..9207b79a9a 100644 --- a/examples/default/ios/Podfile +++ b/examples/default/ios/Podfile @@ -14,7 +14,7 @@ prepare_react_native_project! # dependencies: { # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), # ``` -flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled +# flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled linkage = ENV['USE_FRAMEWORKS'] if linkage != nil @@ -41,7 +41,7 @@ target 'InstabugExample' do # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable the next line. - :flipper_configuration => flipper_config, + # :flipper_configuration => flipper_config, # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 6c238f80d0..09c85df1c3 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -1,6 +1,5 @@ PODS: - boost (1.76.0) - - CocoaAsyncSocket (7.6.5) - DoubleConversion (1.1.6) - FBLazyVector (0.72.3) - FBReactNativeSpec (0.72.3): @@ -10,64 +9,6 @@ PODS: - React-Core (= 0.72.3) - React-jsi (= 0.72.3) - ReactCommon/turbomodule/core (= 0.72.3) - - Flipper (0.182.0): - - Flipper-Folly (~> 2.6) - - Flipper-Boost-iOSX (1.76.0.1.11) - - Flipper-DoubleConversion (3.2.0.1) - - Flipper-Fmt (7.1.7) - - Flipper-Folly (2.6.10): - - Flipper-Boost-iOSX - - Flipper-DoubleConversion - - Flipper-Fmt (= 7.1.7) - - Flipper-Glog - - libevent (~> 2.1.12) - - OpenSSL-Universal (= 1.1.1100) - - Flipper-Glog (0.5.0.5) - - Flipper-PeerTalk (0.0.4) - - FlipperKit (0.182.0): - - FlipperKit/Core (= 0.182.0) - - FlipperKit/Core (0.182.0): - - Flipper (~> 0.182.0) - - FlipperKit/CppBridge - - FlipperKit/FBCxxFollyDynamicConvert - - FlipperKit/FBDefines - - FlipperKit/FKPortForwarding - - SocketRocket (~> 0.6.0) - - FlipperKit/CppBridge (0.182.0): - - Flipper (~> 0.182.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.182.0): - - Flipper-Folly (~> 2.6) - - FlipperKit/FBDefines (0.182.0) - - FlipperKit/FKPortForwarding (0.182.0): - - CocoaAsyncSocket (~> 7.6) - - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.182.0) - - FlipperKit/FlipperKitLayoutHelpers (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay - - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutIOSDescriptors (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay - - FlipperKit/FlipperKitLayoutHelpers - - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay - - FlipperKit/FlipperKitLayoutHelpers - - FlipperKit/FlipperKitLayoutIOSDescriptors - - FlipperKit/FlipperKitLayoutTextSearchable - - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutTextSearchable (0.182.0) - - FlipperKit/FlipperKitNetworkPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) - glog (0.3.5) - Google-Maps-iOS-Utils (4.2.2): @@ -103,7 +44,6 @@ PODS: - React-Core - libevent (2.1.12) - OCMock (3.9.3) - - OpenSSL-Universal (1.1.1100) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -576,41 +516,18 @@ PODS: - React-Core - SocketRocket (0.6.1) - Yoga (1.14.0) - - YogaKit (1.18.1): - - Yoga (~> 1.14) DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - - Flipper (= 0.182.0) - - Flipper-Boost-iOSX (= 1.76.0.1.11) - - Flipper-DoubleConversion (= 3.2.0.1) - - Flipper-Fmt (= 7.1.7) - - Flipper-Folly (= 2.6.10) - - Flipper-Glog (= 0.5.0.5) - - Flipper-PeerTalk (= 0.0.4) - - FlipperKit (= 0.182.0) - - FlipperKit/Core (= 0.182.0) - - FlipperKit/CppBridge (= 0.182.0) - - FlipperKit/FBCxxFollyDynamicConvert (= 0.182.0) - - FlipperKit/FBDefines (= 0.182.0) - - FlipperKit/FKPortForwarding (= 0.182.0) - - FlipperKit/FlipperKitHighlightOverlay (= 0.182.0) - - FlipperKit/FlipperKitLayoutPlugin (= 0.182.0) - - FlipperKit/FlipperKitLayoutTextSearchable (= 0.182.0) - - FlipperKit/FlipperKitNetworkPlugin (= 0.182.0) - - FlipperKit/FlipperKitReactPlugin (= 0.182.0) - - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.182.0) - - FlipperKit/SKIOSNetworkPlugin (= 0.182.0) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - Instabug (from `https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - libevent (~> 2.1.12) - OCMock - - OpenSSL-Universal (= 1.1.1100) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) @@ -618,7 +535,6 @@ DEPENDENCIES: - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - React-Codegen (from `build/generated/ios`) - React-Core (from `../node_modules/react-native/`) - - React-Core/DevSupport (from `../node_modules/react-native/`) - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) @@ -662,23 +578,12 @@ DEPENDENCIES: SPEC REPOS: trunk: - - CocoaAsyncSocket - - Flipper - - Flipper-Boost-iOSX - - Flipper-DoubleConversion - - Flipper-Fmt - - Flipper-Folly - - Flipper-Glog - - Flipper-PeerTalk - - FlipperKit - fmt - Google-Maps-iOS-Utils - GoogleMaps - libevent - OCMock - - OpenSSL-Universal - SocketRocket - - YogaKit EXTERNAL SOURCES: boost: @@ -793,18 +698,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7dcd2de282d72e344012f7d6564d024930a6a440 - CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: 4cce221dd782d3ff7c4172167bba09d58af67ccb FBReactNativeSpec: c6bd9e179757b3c0ecf815864fae8032377903ef - Flipper: 6edb735e6c3e332975d1b17956bcc584eccf5818 - Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c - Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 - Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b - Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 - Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 - Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a @@ -814,7 +710,6 @@ SPEC CHECKSUMS: instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 - OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18 RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3 @@ -862,8 +757,7 @@ SPEC CHECKSUMS: RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce - YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 1a4743c72496ad79c39b937de7cb9598ccf0bb2a +PODFILE CHECKSUM: 08bf47efd2faf96320ceaf855e2e82598bc7d1ae -COCOAPODS: 1.12.0 +COCOAPODS: 1.15.2 From 9e0afbba424a513e4ddc7e12acc5453ffcc460f4 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 24 Jul 2024 11:53:02 +0300 Subject: [PATCH 047/104] fix: adjust spacing --- ios/RNInstabug/InstabugReactBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index 153b795329..8f81f49a70 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -315,7 +315,7 @@ - (dispatch_queue_t)methodQueue { responseBodySize:responseBodySize responseCode:responseCode requestHeaders:requestHeaders - responseHeaders:responseHeaders + responseHeaders:responseHeaders contentType:contentType errorDomain:errorDomain errorCode:errorCode From 7893846c212169bf4d7a193b0b9c36ec4ec667a0 Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 25 Jul 2024 13:58:37 +0300 Subject: [PATCH 048/104] fix: update test case --- test/modules/APM.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts index 9f989271a4..96fc85a607 100644 --- a/test/modules/APM.spec.ts +++ b/test/modules/APM.spec.ts @@ -194,8 +194,10 @@ describe('APM Module', () => { }); it('should register W3C flag listener', async () => { - APM._registerW3CFlagsChangeListener(() => {}); + const callback = jest.fn(); + APM._registerW3CFlagsChangeListener(callback); expect(NativeAPM.registerW3CFlagsChangeListener).toBeCalledTimes(1); + expect(NativeAPM.registerW3CFlagsChangeListener).toBeCalledWith(callback); }); }); From 20ca10b16f121dc494658f123ba9a91b16388985 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 25 Jul 2024 17:39:44 +0300 Subject: [PATCH 049/104] feat: migrate-Feature-Flag-APM-method-to-Core --- android/native.gradle | 2 +- .../reactlibrary/RNInstabugAPMModule.java | 111 ------------------ .../RNInstabugReactnativeModule.java | 106 +++++++++++++++++ src/modules/APM.ts | 43 +------ src/modules/Instabug.ts | 42 ++++++- src/native/NativeAPM.ts | 18 --- src/native/NativeInstabug.ts | 17 +++ src/utils/FeatureFlags.ts | 10 +- 8 files changed, 170 insertions(+), 179 deletions(-) diff --git a/android/native.gradle b/android/native.gradle index 916c957e59..ca8c4fc3ea 100644 --- a/android/native.gradle +++ b/android/native.gradle @@ -1,5 +1,5 @@ project.ext.instabug = [ - version: '13.2.0' + version: '13.2.0.6091772-SNAPSHOT' ] dependencies { diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 6ad5973687..6d604b6a94 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -7,33 +7,20 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; import com.instabug.apm.APM; -import com.instabug.apm.configuration.cp.APMFeature; -import com.instabug.apm.configuration.cp.APMFeaturesAvailability; import com.instabug.apm.model.ExecutionTrace; import com.instabug.apm.networking.APMNetworkLogger; import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; -import com.instabug.apm.InternalAPM; -import com.instabug.apm.configuration.cp.FeaturesChangeListener; -import org.json.JSONException; -import org.json.JSONObject; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; -import java.util.Properties; import javax.annotation.Nonnull; @@ -325,104 +312,6 @@ public void run() { } }); } - /** - * Register a listener for W3C flags value change - */ - @ReactMethod - public void registerW3CFlagsChangeListener(final Callback handler){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - InternalAPM._registerCPFeaturesChangeListener(new FeaturesChangeListener() { - @Override - public void invoke(@NonNull APMFeaturesAvailability apmFeaturesAvailability) { - WritableMap params = Arguments.createMap(); - params.putBoolean("isW3ExternalTraceIDEnabled", apmFeaturesAvailability.isW3CExternalTraceIdAvailable()); - params.putBoolean("isW3ExternalGeneratedHeaderEnabled", apmFeaturesAvailability.getShouldAttachGeneratedHeader()); - params.putBoolean("isW3CaughtHeaderEnabled", apmFeaturesAvailability.getShouldAttachCapturedHeader()); - - sendEvent(Constants.IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); - } - }); - } - catch (Exception e) { - e.printStackTrace(); - } - - } - - }); - } - - - /** - * Get first time Value of W3ExternalTraceID flag - */ - @ReactMethod - public void isW3ExternalTraceIDEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_EXTERNAL_TRACE_ID, " ")); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } - - - /** - * Get first time Value of W3ExternalGeneratedHeader flag - */ - @ReactMethod - public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_GENERATED_HEADER_ATTACHING, " ")); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } - - /** - * Get first time Value of W3CaughtHeader flag - */ - @ReactMethod - public void isW3CaughtHeaderEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalAPM._isFeatureEnabledCP(APMFeature.W3C_CAPTURED_HEADER_ATTACHING,"")); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } @ReactMethod private void networkLogAndroid(final double requestStartTime, diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 7d14656089..8d20544fc1 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -8,6 +8,7 @@ import android.util.Log; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.facebook.react.bridge.Arguments; @@ -21,6 +22,8 @@ import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.UIManagerModule; +import com.instabug.apm.InternalAPM; +import com.instabug.apm.configuration.cp.APMFeature; import com.instabug.library.Feature; import com.instabug.library.Instabug; import com.instabug.library.InstabugColorTheme; @@ -29,6 +32,10 @@ import com.instabug.library.LogLevel; import com.instabug.library.ReproConfigurations; import com.instabug.library.core.InstabugCore; +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.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; import com.instabug.library.logging.InstabugLog; @@ -1082,6 +1089,105 @@ public void run() { } }); } + /** + * Register a listener for W3C flags value change + */ + @ReactMethod + public void registerW3CFlagsChangeListener(final Callback handler){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + InternalCore.INSTANCE._setFeaturesStateListener(new FeaturesStateListener() { + @Override + public void invoke(@NonNull CoreFeaturesState featuresState) { + WritableMap params = Arguments.createMap(); + params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled()); + params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled()); + params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled()); + + sendEvent(Constants.IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); + } + }); + } + catch (Exception e) { + e.printStackTrace(); + } + + } + + }); + } + + + /** + * Get first time Value of W3ExternalTraceID flag + */ + @ReactMethod + public void isW3ExternalTraceIDEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID)); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + + /** + * Get first time Value of W3ExternalGeneratedHeader flag + */ + @ReactMethod + public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER)); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + /** + * Get first time Value of W3CaughtHeader flag + */ + @ReactMethod + public void isW3CaughtHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER)); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + /** * Map between the exported JS constant and the arg key in {@link ArgsRegistry}. diff --git a/src/modules/APM.ts b/src/modules/APM.ts index 9404fdc9c9..664f4473cc 100644 --- a/src/modules/APM.ts +++ b/src/modules/APM.ts @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import Trace from '../models/Trace'; -import { NativeAPM, NativeEvents, emitter } from '../native/NativeAPM'; +import { NativeAPM } from '../native/NativeAPM'; import { NativeInstabug } from '../native/NativeInstabug'; /** @@ -134,44 +134,3 @@ export const endUITrace = () => { export const _ibgSleep = () => { NativeAPM.ibgSleep(); }; - -/** - * Returns weather W3C key flag is enabled - */ -export const _isW3ExternalTraceIDEnabled = async (): Promise => { - const isw3ExternalTraceIDEnabled = await NativeAPM.isW3ExternalTraceIDEnabled(); - return isw3ExternalTraceIDEnabled; -}; - -/** - * Returns weather we should generate W3C header - */ -export const _isW3ExternalGeneratedHeaderEnabled = async (): Promise => { - const isExternalGeneratedHeaderEnabled = await NativeAPM.isW3ExternalGeneratedHeaderEnabled(); - return isExternalGeneratedHeaderEnabled; -}; - -/** - * Returns weather W3C was caught - */ -export const _isW3CaughtHeaderEnabled = async (): Promise => { - const isW3CaughtHeaderEnabled = await NativeAPM.isW3CaughtHeaderEnabled(); - return isW3CaughtHeaderEnabled; -}; - -/** - * Sets listener to W3ExternalTraceID flag changes - * @param handler A callback that gets the update value of the flag - */ -export const _registerW3CFlagsChangeListener = ( - handler: (payload: { - isW3ExternalTraceIDEnabled: boolean; - isW3ExternalGeneratedHeaderEnabled: boolean; - isW3CaughtHeaderEnabled: boolean; - }) => void, -) => { - emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANE, (payload) => { - handler(payload); - }); - NativeAPM.registerW3CFlagsChangeListener(handler); -}; diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index b7fea79100..d0e2d08d61 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -1,5 +1,5 @@ import type React from 'react'; -import { Platform, findNodeHandle, processColor } from 'react-native'; +import { findNodeHandle, Platform, processColor } from 'react-native'; import type { NavigationState as NavigationStateV5 } from '@react-navigation/native'; import type { ComponentDidAppearEvent } from 'react-native-navigation'; @@ -7,7 +7,7 @@ import type { NavigationAction, NavigationState as NavigationStateV4 } from 'rea import type { InstabugConfig } from '../models/InstabugConfig'; import Report from '../models/Report'; -import { NativeEvents, NativeInstabug, emitter } from '../native/NativeInstabug'; +import { emitter, NativeEvents, NativeInstabug } from '../native/NativeInstabug'; import { registerW3CFlagsListener } from '../utils/FeatureFlags'; import { ColorTheme, @@ -569,6 +569,44 @@ export const willRedirectToStore = () => { NativeInstabug.willRedirectToStore(); }; +/** + * Returns weather W3C key flag is enabled + */ +export const _isW3ExternalTraceIDEnabled = async (): Promise => { + return await NativeInstabug.isW3ExternalTraceIDEnabled(); +}; + +/** + * Returns weather we should generate W3C header + */ +export const _isW3ExternalGeneratedHeaderEnabled = async (): Promise => { + return await NativeInstabug.isW3ExternalGeneratedHeaderEnabled(); +}; + +/** + * Returns weather W3C was caught + */ +export const _isW3CaughtHeaderEnabled = async (): Promise => { + return await NativeInstabug.isW3CaughtHeaderEnabled(); +}; + +/** + * Sets listener to W3ExternalTraceID flag changes + * @param handler A callback that gets the update value of the flag + */ +export const _registerW3CFlagsChangeListener = ( + handler: (payload: { + isW3ExternalTraceIDEnabled: boolean; + isW3ExternalGeneratedHeaderEnabled: boolean; + isW3CaughtHeaderEnabled: boolean; + }) => void, +) => { + emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANE, (payload) => { + handler(payload); + }); + NativeInstabug.registerW3CFlagsChangeListener(handler); +}; + export const componentDidAppearListener = (event: ComponentDidAppearEvent) => { if (_isFirstScreen) { _lastScreen = event.componentName; diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index fe7852bae1..285fe05d09 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -48,26 +48,8 @@ export interface ApmNativeModule extends NativeModule { startUITrace(name: string): void; endUITrace(): void; ibgSleep(): void; - - // W3C Feature Flags - isW3ExternalTraceIDEnabled(): Promise; - isW3ExternalGeneratedHeaderEnabled(): Promise; - isW3CaughtHeaderEnabled(): Promise; - - // W3C Feature Flags Listener for Android - registerW3CFlagsChangeListener( - handler: (payload: { - isW3ExternalTraceIDEnabled: boolean; - isW3ExternalGeneratedHeaderEnabled: boolean; - isW3CaughtHeaderEnabled: boolean; - }) => void, - ): void; } export const NativeAPM = NativeModules.IBGAPM; -export enum NativeEvents { - ON_W3C_FLAGS_CHANE = 'IBGAPMOnNewW3CFlagsUpdateReceivedCallback', -} - export const emitter = new NativeEventEmitter(NativeAPM); diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 999eeeb276..7c7a4c2af2 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -136,12 +136,29 @@ export interface InstabugNativeModule extends NativeModule { addFileAttachmentWithURLToReport(url: string, filename?: string): void; addFileAttachmentWithDataToReport(data: string, filename?: string): void; willRedirectToStore(): void; + + // W3C Feature Flags + isW3ExternalTraceIDEnabled(): Promise; + + isW3ExternalGeneratedHeaderEnabled(): Promise; + + isW3CaughtHeaderEnabled(): Promise; + + // W3C Feature Flags Listener for Android + registerW3CFlagsChangeListener( + handler: (payload: { + isW3ExternalTraceIDEnabled: boolean; + isW3ExternalGeneratedHeaderEnabled: boolean; + isW3CaughtHeaderEnabled: boolean; + }) => void, + ): void; } export const NativeInstabug = NativeModules.Instabug; export enum NativeEvents { PRESENDING_HANDLER = 'IBGpreSendingHandler', + ON_W3C_FLAGS_CHANE = 'IBGAPMOnNewW3CFlagsUpdateReceivedCallback', } export const emitter = new NativeEventEmitter(NativeInstabug); diff --git a/src/utils/FeatureFlags.ts b/src/utils/FeatureFlags.ts index 2fef73e792..e28fd25f37 100644 --- a/src/utils/FeatureFlags.ts +++ b/src/utils/FeatureFlags.ts @@ -1,13 +1,13 @@ -import * as NativeAPM from '../modules/APM'; +import { NativeInstabug } from '../native/NativeInstabug'; export const FeatureFlags = { - isW3ExternalTraceID: () => NativeAPM._isW3ExternalTraceIDEnabled(), - isW3ExternalGeneratedHeader: () => NativeAPM._isW3ExternalGeneratedHeaderEnabled(), - isW3CaughtHeader: () => NativeAPM._isW3CaughtHeaderEnabled(), + isW3ExternalTraceID: () => NativeInstabug.isW3ExternalTraceIDEnabled(), + isW3ExternalGeneratedHeader: () => NativeInstabug.isW3ExternalGeneratedHeaderEnabled(), + isW3CaughtHeader: () => NativeInstabug.isW3CaughtHeaderEnabled(), }; export const registerW3CFlagsListener = () => { - NativeAPM._registerW3CFlagsChangeListener( + NativeInstabug.registerW3CFlagsChangeListener( (res: { isW3ExternalTraceIDEnabled: boolean; isW3ExternalGeneratedHeaderEnabled: boolean; From 807c544a291f36e9f306fab57f850e4579800512 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 25 Jul 2024 17:55:48 +0300 Subject: [PATCH 050/104] fix: js testcases --- src/modules/Instabug.ts | 38 ------------------------------ test/mocks/mockAPM.ts | 4 ---- test/mocks/mockInstabug.ts | 4 ++++ test/modules/APM.spec.ts | 44 ----------------------------------- test/modules/Instabug.spec.ts | 3 ++- 5 files changed, 6 insertions(+), 87 deletions(-) diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index d0e2d08d61..57b4428173 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -569,44 +569,6 @@ export const willRedirectToStore = () => { NativeInstabug.willRedirectToStore(); }; -/** - * Returns weather W3C key flag is enabled - */ -export const _isW3ExternalTraceIDEnabled = async (): Promise => { - return await NativeInstabug.isW3ExternalTraceIDEnabled(); -}; - -/** - * Returns weather we should generate W3C header - */ -export const _isW3ExternalGeneratedHeaderEnabled = async (): Promise => { - return await NativeInstabug.isW3ExternalGeneratedHeaderEnabled(); -}; - -/** - * Returns weather W3C was caught - */ -export const _isW3CaughtHeaderEnabled = async (): Promise => { - return await NativeInstabug.isW3CaughtHeaderEnabled(); -}; - -/** - * Sets listener to W3ExternalTraceID flag changes - * @param handler A callback that gets the update value of the flag - */ -export const _registerW3CFlagsChangeListener = ( - handler: (payload: { - isW3ExternalTraceIDEnabled: boolean; - isW3ExternalGeneratedHeaderEnabled: boolean; - isW3CaughtHeaderEnabled: boolean; - }) => void, -) => { - emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANE, (payload) => { - handler(payload); - }); - NativeInstabug.registerW3CFlagsChangeListener(handler); -}; - export const componentDidAppearListener = (event: ComponentDidAppearEvent) => { if (_isFirstScreen) { _lastScreen = event.componentName; diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts index 008816bffb..27644c694a 100644 --- a/test/mocks/mockAPM.ts +++ b/test/mocks/mockAPM.ts @@ -17,10 +17,6 @@ const mockAPM: ApmNativeModule = { endAppLaunch: jest.fn(), ibgSleep: jest.fn(), networkLogAndroid: jest.fn(), - isW3ExternalTraceIDEnabled: jest.fn(), - isW3ExternalGeneratedHeaderEnabled: jest.fn(), - isW3CaughtHeaderEnabled: jest.fn(), - registerW3CFlagsChangeListener: jest.fn(), }; export default mockAPM; diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index c2dac12b5a..d532ebe2d5 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -66,6 +66,10 @@ const mockInstabug: InstabugNativeModule = { addFileAttachmentWithDataToReport: jest.fn(), setNetworkLoggingEnabled: jest.fn(), willRedirectToStore: jest.fn(), + isW3ExternalTraceIDEnabled: jest.fn(), + isW3ExternalGeneratedHeaderEnabled: jest.fn(), + isW3CaughtHeaderEnabled: jest.fn(), + registerW3CFlagsChangeListener: jest.fn(), }; export default mockInstabug; diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts index 96fc85a607..d11cadf32b 100644 --- a/test/modules/APM.spec.ts +++ b/test/modules/APM.spec.ts @@ -156,48 +156,4 @@ describe('APM Module', () => { expect(NativeAPM.ibgSleep).toBeCalledTimes(1); expect(NativeAPM.ibgSleep).toBeCalledWith(); }); - - it('should call the native method _isW3ExternalTraceIDEnabled', async () => { - const expected = true; - - mocked(NativeAPM).isW3ExternalTraceIDEnabled.mockResolvedValueOnce(expected); - - const actual = await APM._isW3ExternalTraceIDEnabled(); - - expect(actual).toBe(expected); - expect(NativeAPM.isW3ExternalTraceIDEnabled).toBeCalledTimes(1); - expect(NativeAPM.isW3ExternalTraceIDEnabled).toBeCalledWith(); - }); - - it('should call the native method _isW3ExternalGeneratedHeaderEnabled', async () => { - const expected = true; - - mocked(NativeAPM).isW3ExternalGeneratedHeaderEnabled.mockResolvedValueOnce(expected); - - const actual = await APM._isW3ExternalGeneratedHeaderEnabled(); - - expect(actual).toBe(expected); - expect(NativeAPM.isW3ExternalGeneratedHeaderEnabled).toBeCalledTimes(1); - expect(NativeAPM.isW3ExternalGeneratedHeaderEnabled).toBeCalledWith(); - }); - - it('should call the native method _isW3CaughtHeaderEnabled', async () => { - const expected = true; - - mocked(NativeAPM).isW3CaughtHeaderEnabled.mockResolvedValueOnce(expected); - - const actual = await APM._isW3CaughtHeaderEnabled(); - - expect(actual).toBe(expected); - expect(NativeAPM.isW3CaughtHeaderEnabled).toBeCalledTimes(1); - expect(NativeAPM.isW3CaughtHeaderEnabled).toBeCalledWith(); - }); - - it('should register W3C flag listener', async () => { - const callback = jest.fn(); - APM._registerW3CFlagsChangeListener(callback); - - expect(NativeAPM.registerW3CFlagsChangeListener).toBeCalledTimes(1); - expect(NativeAPM.registerW3CFlagsChangeListener).toBeCalledWith(callback); - }); }); diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index f2e52099f9..9b2e06936e 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -9,7 +9,7 @@ import waitForExpect from 'wait-for-expect'; import Report from '../../src/models/Report'; import * as Instabug from '../../src/modules/Instabug'; import * as NetworkLogger from '../../src/modules/NetworkLogger'; -import { NativeEvents, NativeInstabug, emitter } from '../../src/native/NativeInstabug'; +import { NativeEvents, emitter } from '../../src/native/NativeInstabug'; import { ColorTheme, InvocationEvent, @@ -21,6 +21,7 @@ import { WelcomeMessageMode, } from '../../src/utils/Enums'; import InstabugUtils from '../../src/utils/InstabugUtils'; +import { NativeInstabug } from '../../src/native/NativeInstabug'; describe('Instabug Module', () => { beforeEach(() => { From efc0e8dde5ca2d5425f23fd2cfb8a74bf0766ab7 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 25 Jul 2024 18:03:38 +0300 Subject: [PATCH 051/104] fix: js testcases --- examples/default/ios/Podfile.lock | 76 +++++++++++-------------------- 1 file changed, 27 insertions(+), 49 deletions(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 09c85df1c3..a5b1f5d465 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,7 +38,7 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.2.0) + - Instabug (13.1.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core @@ -346,9 +346,9 @@ PODS: - glog - react-native-background-timer (2.4.1): - React-Core - - react-native-config (1.5.1): - - react-native-config/App (= 1.5.1) - - react-native-config/App (1.5.1): + - react-native-config (1.5.2): + - react-native-config/App (= 1.5.2) + - react-native-config/App (1.5.2): - React-Core - react-native-google-maps (1.10.3): - Google-Maps-iOS-Utils (= 4.2.2) @@ -356,9 +356,10 @@ PODS: - React-Core - react-native-maps (1.10.3): - React-Core - - react-native-safe-area-context (4.7.1): + - react-native-safe-area-context (4.10.8): - React-Core - - react-native-slider (4.4.3): + - react-native-slider (4.5.2): + - RCT-Folly (= 2021.07.22.00) - React-Core - React-NativeModulesApple (0.72.3): - hermes-engine @@ -472,47 +473,24 @@ PODS: - React-perflogger (= 0.72.3) - RNCClipboard (1.5.1): - React-Core - - RNGestureHandler (2.13.4): + - RNGestureHandler (2.17.1): - RCT-Folly (= 2021.07.22.00) - React-Core - RNInstabug (13.2.0): - - Instabug (= 13.2.0) + - Instabug - React-Core - - RNReanimated (3.5.4): - - DoubleConversion - - FBLazyVector - - glog - - hermes-engine - - RCT-Folly - - RCTRequired - - RCTTypeSafety - - React-callinvoker + - RNReanimated (3.14.0): + - RCT-Folly (= 2021.07.22.00) - React-Core - - React-Core/DevSupport - - React-Core/RCTWebSocket - - React-CoreModules - - React-cxxreact - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-RCTActionSheet - - React-RCTAnimation - - React-RCTAppDelegate - - React-RCTBlob - - React-RCTImage - - React-RCTLinking - - React-RCTNetwork - - React-RCTSettings - - React-RCTText - ReactCommon/turbomodule/core - - Yoga - - RNScreens (3.24.0): + - RNScreens (3.32.0): + - RCT-Folly (= 2021.07.22.00) - React-Core - React-RCTImage - - RNSVG (13.10.0): + - RNSVG (13.14.1): - React-Core - - RNVectorIcons (10.0.0): + - RNVectorIcons (10.1.0): + - RCT-Folly (= 2021.07.22.00) - React-Core - SocketRocket (0.6.1) - Yoga (1.14.0) @@ -706,7 +684,7 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: aee76898789d17c55b36c7fbaa697e443effe3b1 + Instabug: 0095861b71aeadc1f5356d078ca44ccc5b32d0d3 instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 @@ -726,11 +704,11 @@ SPEC CHECKSUMS: React-jsinspector: b511447170f561157547bc0bef3f169663860be7 React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95 react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe - react-native-config: 86038147314e2e6d10ea9972022aa171e6b1d4d8 + react-native-config: d7d8a0c65f7fa523197879f6b777997abbfc987e react-native-google-maps: 1bcc1f9f13f798fcf230db7fe476f3566d0bc0a3 react-native-maps: 72a8a903f8a1b53e2c777ba79102078ab502e0bf - react-native-safe-area-context: 9697629f7b2cda43cf52169bb7e0767d330648c2 - react-native-slider: 1cdd6ba29675df21f30544253bf7351d3c2d68c4 + react-native-safe-area-context: b7daa1a8df36095a032dff095a1ea8963cb48371 + react-native-slider: 593253eb5fbc6ea519290e812bd477fc6abafd5a React-NativeModulesApple: c57f3efe0df288a6532b726ad2d0322a9bf38472 React-perflogger: 6bd153e776e6beed54c56b0847e1220a3ff92ba5 React-RCTActionSheet: c0b62af44e610e69d9a2049a682f5dba4e9dff17 @@ -749,15 +727,15 @@ SPEC CHECKSUMS: React-utils: bcb57da67eec2711f8b353f6e3d33bd8e4b2efa3 ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 - RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: 6fa68cd181533f83154df2ebba000d0c47ca7ba3 - RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 - RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 - RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 - RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9 + RNGestureHandler: bbb8e17b10afdafc5cc5746e8f60772236e7e2ca + RNInstabug: e515e490416a20b604e27bdbbebf5316ff3a2012 + RNReanimated: 158b2f80fdb043ab5a645ba047209badbd7eb9a9 + RNScreens: 0bd9eec783bed1032e02a4db9976dae1664a5c7b + RNSVG: af3907ac5d4fa26a862b75a16d8f15bc74f2ceda + RNVectorIcons: bfb663f3f7b37340cd90120151b720641523dc84 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce PODFILE CHECKSUM: 08bf47efd2faf96320ceaf855e2e82598bc7d1ae -COCOAPODS: 1.15.2 +COCOAPODS: 1.12.0 From 4b90955225cfe8c82e331870ecf8185555bc1a03 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 25 Jul 2024 18:10:43 +0300 Subject: [PATCH 052/104] fix: js testcases --- examples/default/ios/Podfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index a5b1f5d465..a39f95ecf8 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -43,7 +43,7 @@ PODS: - RCT-Folly (= 2021.07.22.00) - React-Core - libevent (2.1.12) - - OCMock (3.9.3) + - OCMock (3.9.4) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -687,7 +687,7 @@ SPEC CHECKSUMS: Instabug: 0095861b71aeadc1f5356d078ca44ccc5b32d0d3 instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 + OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18 RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3 From c3a62d36a0a6b839f3d17bb0e0e30b133a4f02ba Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Sun, 28 Jul 2024 18:05:13 +0300 Subject: [PATCH 053/104] feat: add migrate APM into core in ios section --- .../InstabugExample.xcodeproj/project.pbxproj | 2 +- .../ios/InstabugTests/InstabugAPMTests.m | 56 ------------- .../ios/InstabugTests/InstabugSampleTests.m | 80 ++++++++++++++++++- .../ios/InstabugTests/RNInstabugTests.m | 2 +- examples/default/ios/Podfile | 2 +- examples/default/ios/Podfile.lock | 10 +-- ios/RNInstabug/InstabugAPMBridge.h | 4 +- ios/RNInstabug/InstabugAPMBridge.m | 18 ----- ios/RNInstabug/InstabugReactBridge.h | 4 +- ios/RNInstabug/InstabugReactBridge.m | 11 +++ ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h | 7 +- ios/RNInstabug/Util/IBGNetworkLogger+CP.h | 6 ++ 12 files changed, 106 insertions(+), 96 deletions(-) diff --git a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj index 2751593517..afe4ffe605 100644 --- a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj +++ b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ ); name = "[CP-User] [instabug-reactnative] Upload Sourcemap"; runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; + shellPath = /bin/sh; shellScript = "#!/bin/sh\n\nmain() {\n # Read environment variables from ios/.xcode.env if it exists\n env_path=\"$PODS_ROOT/../.xcode.env\"\n if [ -f \"$env_path\" ]; then\n source \"$env_path\"\n fi\n\n # Read environment variables from ios/.xcode.env.local if it exists\n local_env_path=\"${ENV_PATH}.local\"\n if [ -f \"$local_env_path\" ]; then\n source \"$local_env_path\"\n fi\n\n if [[ \"$INSTABUG_SOURCEMAPS_UPLOAD_DISABLE\" = true ]]; then\n echo \"[Info] \\`INSTABUG_SOURCEMAPS_UPLOAD_DISABLE\\` was set to true, skipping sourcemaps upload...\"\n exit 0\n fi\n\n if [[ \"$CONFIGURATION\" = \"Debug\" ]]; then\n echo \"[Info] Building in debug mode, skipping sourcemaps upload...\"\n exit 0\n fi\n\n if [[ -z \"$INFOPLIST_FILE\" ]] || [[ -z \"$PROJECT_DIR\" ]]; then\n echo \"[Error] Instabug sourcemaps script must be invoked by Xcode\"\n exit 0\n fi\n\n local source_map_file=$(generate_sourcemaps | tail -n 1)\n\n local js_project_dir=\"$PROJECT_DIR/..\"\n local instabug_dir=$(dirname $(node -p \"require.resolve('instabug-reactnative/package.json')\"))\n local inferred_token=$(cd $js_project_dir && source $instabug_dir/scripts/find-token.sh)\n local app_token=$(resolve_var \"App Token\" \"INSTABUG_APP_TOKEN\" \"$inferred_token\" | tail -n 1)\n\n local inferred_name=$(/usr/libexec/PlistBuddy -c 'print CFBundleShortVersionString' \"$PROJECT_DIR/$INFOPLIST_FILE\")\n local version_name=$(resolve_var \"Version Name\" \"INSTABUG_APP_VERSION_NAME\" \"$inferred_name\" | tail -n 1)\n\n local inferred_code=$(/usr/libexec/PlistBuddy -c 'print CFBundleVersion' \"$PROJECT_DIR/$INFOPLIST_FILE\")\n local version_code=$(resolve_var \"Version Code\" \"INSTABUG_APP_VERSION_CODE\" \"$inferred_code\" | tail -n 1)\n\n node $instabug_dir/bin/index.js upload-sourcemaps \\\n --platform ios \\\n --file $source_map_file \\\n --token $app_token \\\n --name $version_name \\\n --code $version_code\n}\n\ngenerate_sourcemaps() {\n local react_native_dir=$(dirname $(node -p \"require.resolve('react-native/package.json')\"))\n\n # Fixes an issue with react-native prior to v0.67.0\n # For more info: https://github.com/facebook/react-native/issues/32168\n export RN_DIR=$react_native_dir\n\n # Used withing `react-native-xcode.sh` to generate sourcemap file\n export SOURCEMAP_FILE=\"$(pwd)/main.jsbundle.map\";\n\n source \"$react_native_dir/scripts/react-native-xcode.sh\"\n\n if [[ ! -f \"$SOURCEMAP_FILE\" ]]; then\n echo \"[Error] Unable to find source map file at: $SOURCEMAP_FILE\"\n exit 0\n fi\n\n echo $SOURCEMAP_FILE\n}\n\nresolve_var() {\n local name=$1\n local env_key=$2\n local default_value=$3\n\n local env_value=\"${!env_key}\"\n\n if [[ -n \"$env_value\" ]] && [[ -n \"$default_value\" ]] && [[ \"$env_value\" != default_value ]]; then\n echo \"[Warning] Environment variable \\`$env_key\\` might have incorrect value, make sure this was intentional:\"\n echo \" Environment Value: $env_value\"\n echo \" Default Value: $default_value\"\n fi\n\n local value=\"${env_value:-$default_value}\"\n\n if [[ -z \"$value\" ]]; then\n echo \"[Error] Unable to find $name! Set the environment variable \\`$env_key\\` and try again.\"\n exit 0\n fi\n\n echo $value\n}\n\nmain \"$@\"; exit\n"; }; B77A7BA143DBD17E8AAFD0B4 /* [CP] Embed Pods Frameworks */ = { diff --git a/examples/default/ios/InstabugTests/InstabugAPMTests.m b/examples/default/ios/InstabugTests/InstabugAPMTests.m index 62e9d717bb..5945b2b791 100644 --- a/examples/default/ios/InstabugTests/InstabugAPMTests.m +++ b/examples/default/ios/InstabugTests/InstabugAPMTests.m @@ -177,62 +177,6 @@ - (void) testEndUITrace { OCMVerify([mock endUITrace]); } -- (void) testIsW3ExternalTraceIDEnabled { - id mock = OCMClassMock([IBGAPM class]); - NSNumber *expectedValue = @(YES); - - OCMStub([mock w3ExternalTraceIDEnabled]).andReturn([expectedValue boolValue]); - - XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; - RCTPromiseResolveBlock resolve = ^(NSNumber *result) { - XCTAssertEqualObjects(result, expectedValue); - [expectation fulfill]; - }; - - [self.instabugBridge isW3ExternalTraceIDEnabled:resolve :nil]; - - [self waitForExpectationsWithTimeout:1.0 handler:nil]; - - OCMVerify([mock w3ExternalTraceIDEnabled]); -} - -- (void) testIsW3ExternalGeneratedHeaderEnabled { - id mock = OCMClassMock([IBGAPM class]); - NSNumber *expectedValue = @(YES); - - OCMStub([mock w3ExternalGeneratedHeaderEnabled]).andReturn([expectedValue boolValue]); - - XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; - RCTPromiseResolveBlock resolve = ^(NSNumber *result) { - XCTAssertEqualObjects(result, expectedValue); - [expectation fulfill]; - }; - - [self.instabugBridge isW3ExternalGeneratedHeaderEnabled:resolve :nil]; - - [self waitForExpectationsWithTimeout:1.0 handler:nil]; - - OCMVerify([mock w3ExternalGeneratedHeaderEnabled]); -} - -- (void) testIsW3CaughtHeaderEnabled { - id mock = OCMClassMock([IBGAPM class]); - NSNumber *expectedValue = @(YES); - - OCMStub([mock w3CaughtHeaderEnabled]).andReturn([expectedValue boolValue]); - - XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; - RCTPromiseResolveBlock resolve = ^(NSNumber *result) { - XCTAssertEqualObjects(result, expectedValue); - [expectation fulfill]; - }; - - [self.instabugBridge isW3CaughtHeaderEnabled:resolve :nil]; - - [self waitForExpectationsWithTimeout:1.0 handler:nil]; - - OCMVerify([mock w3CaughtHeaderEnabled]); -} @end diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index 37990b450c..102b0bb0aa 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -14,7 +14,6 @@ #import "IBGConstants.h" #import "RNInstabug.h" #import - @protocol InstabugCPTestProtocol /** * This protocol helps in correctly mapping Instabug mocked methods @@ -333,7 +332,12 @@ - (void)testNetworkLogIOS { double duration = 150; NSString *gqlQueryName = nil; NSString *serverErrorMessage = nil; - + NSDictionary* w3cExternalTraceAttributes = nil; + NSNumber *isW3cCaughted = nil; + NSNumber *partialID = nil; + NSNumber *timestamp= nil; + NSString *generatedW3CTraceparent= nil; + NSString *caughtedW3CTraceparent= nil; [self.instabugBridge networkLogIOS:url method:method requestBody:requestBody @@ -349,7 +353,9 @@ - (void)testNetworkLogIOS { startTime:startTime duration:duration gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage]; + serverErrorMessage:serverErrorMessage + w3cExternalTraceAttributes:nil + ]; OCMVerify([mIBGNetworkLogger addNetworkLogWithUrl:url method:method @@ -366,7 +372,14 @@ - (void)testNetworkLogIOS { startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage]); + serverErrorMessage:serverErrorMessage + isW3cCaughted:nil + partialID:nil + timestamp:nil + generatedW3CTraceparent:nil + caughtedW3CTraceparent:nil + + ]); } - (void)testSetFileAttachment { @@ -498,4 +511,63 @@ - (void)testClearAllExperiments { OCMVerify([mock clearAllExperiments]); } + +- (void) testIsW3ExternalTraceIDEnabled { + id mock = OCMClassMock([IBGNetworkLogger class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3ExternalTraceIDEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge isW3ExternalTraceIDEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3ExternalTraceIDEnabled]); +} + +- (void) testIsW3ExternalGeneratedHeaderEnabled { + id mock = OCMClassMock([IBGNetworkLogger class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3ExternalGeneratedHeaderEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge isW3ExternalGeneratedHeaderEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3ExternalGeneratedHeaderEnabled]); +} + +- (void) testIsW3CaughtHeaderEnabled { + id mock = OCMClassMock([IBGNetworkLogger class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3CaughtHeaderEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge isW3CaughtHeaderEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3CaughtHeaderEnabled]); +} + + @end diff --git a/examples/default/ios/InstabugTests/RNInstabugTests.m b/examples/default/ios/InstabugTests/RNInstabugTests.m index 0df2fd8430..70320a4cf0 100644 --- a/examples/default/ios/InstabugTests/RNInstabugTests.m +++ b/examples/default/ios/InstabugTests/RNInstabugTests.m @@ -70,7 +70,7 @@ - (void)testInitWithLogsLevel { - (void) testSetCodePushVersion { NSString *codePushVersion = @"1.0.0(1)"; [RNInstabug setCodePushVersion:codePushVersion]; - + OCMVerify([self.mInstabug setCodePushVersion:codePushVersion]); } diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile index 9207b79a9a..31b9b5396b 100644 --- a/examples/default/ios/Podfile +++ b/examples/default/ios/Podfile @@ -26,7 +26,7 @@ target 'InstabugExample' do config = use_native_modules! rn_maps_path = '../node_modules/react-native-maps' pod 'react-native-google-maps', :path => rn_maps_path - pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec' + pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/feature-w3c-header-cp-support/13.2.0/Instabug.podspec' # Flags change depending on the env values. flags = get_default_flags() diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index a39f95ecf8..639e49319d 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,7 +38,7 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.1.0) + - Instabug (13.2.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core @@ -502,7 +502,7 @@ DEPENDENCIES: - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - Instabug (from `https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec`) + - Instabug (from `https://ios-releases.instabug.com/custom/feature-w3c-header-cp-support/13.2.0/Instabug.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - libevent (~> 2.1.12) - OCMock @@ -578,7 +578,7 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77 Instabug: - :podspec: https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec + :podspec: https://ios-releases.instabug.com/custom/feature-w3c-header-cp-support/13.2.0/Instabug.podspec instabug-reactnative-ndk: :path: "../node_modules/instabug-reactnative-ndk" RCT-Folly: @@ -684,7 +684,7 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: 0095861b71aeadc1f5356d078ca44ccc5b32d0d3 + Instabug: 39f85204dd860ae2f9be0ca652beb82319710325 instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 @@ -736,6 +736,6 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce -PODFILE CHECKSUM: 08bf47efd2faf96320ceaf855e2e82598bc7d1ae +PODFILE CHECKSUM: 1db49a5b43158a40ec1d906287420c29aaeab7ee COCOAPODS: 1.12.0 diff --git a/ios/RNInstabug/InstabugAPMBridge.h b/ios/RNInstabug/InstabugAPMBridge.h index c8dccdb55a..b15788d50c 100644 --- a/ios/RNInstabug/InstabugAPMBridge.h +++ b/ios/RNInstabug/InstabugAPMBridge.h @@ -26,9 +26,7 @@ - (void)setFlowAttribute:(NSString *)name :(NSString *)key :(NSString *_Nullable)value; - (void)startUITrace:(NSString *)name; - (void)endUITrace; -- (void)isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; -- (void)isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; -- (void)isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; + extern NSMutableDictionary *traces; @end diff --git a/ios/RNInstabug/InstabugAPMBridge.m b/ios/RNInstabug/InstabugAPMBridge.m index 3b92e467c5..daea8b4c1a 100644 --- a/ios/RNInstabug/InstabugAPMBridge.m +++ b/ios/RNInstabug/InstabugAPMBridge.m @@ -110,25 +110,7 @@ - (id) init [IBGAPM endUITrace]; } -+ (BOOL)w3ExternalTraceIDEnabled { - return IBGAPM.w3ExternalTraceIDEnabled; -} -+ (BOOL)w3ExternalGeneratedHeaderEnabled { - return IBGAPM.w3ExternalGeneratedHeaderEnabled; -} -+ (BOOL)w3CaughtHeaderEnabled { - return IBGAPM.w3CaughtHeaderEnabled; -} -RCT_EXPORT_METHOD(isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { - resolve(@(InstabugAPMBridge.w3ExternalTraceIDEnabled)); -} -RCT_EXPORT_METHOD(isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { - resolve(@(InstabugAPMBridge.w3ExternalGeneratedHeaderEnabled)); -} -RCT_EXPORT_METHOD(isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { - resolve(@(InstabugAPMBridge.w3CaughtHeaderEnabled)); -} diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index 8c5da76682..2a96b8bad3 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -106,7 +106,9 @@ */ - (void)setNetworkLoggingEnabled:(BOOL)isEnabled; - +- (void)isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; - (void)networkLogIOS:(NSString * _Nonnull)url method:(NSString * _Nonnull)method requestBody:(NSString * _Nonnull)requestBody diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index 8f81f49a70..c09d0a038b 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -372,6 +372,17 @@ - (dispatch_queue_t)methodQueue { [Instabug willRedirectToAppStore]; } +RCT_EXPORT_METHOD(isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(IBGNetworkLogger.w3ExternalTraceIDEnabled)); +} +RCT_EXPORT_METHOD(isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(IBGNetworkLogger.w3ExternalGeneratedHeaderEnabled)); +} +RCT_EXPORT_METHOD(isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(IBGNetworkLogger.w3CaughtHeaderEnabled)); +} + + - (NSDictionary *)constantsToExport { return ArgsRegistry.getAll; } diff --git a/ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h b/ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h index 7578cc7b05..a451a0ad50 100644 --- a/ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h +++ b/ios/RNInstabug/Util/IBGAPM+PrivateAPIs.h @@ -10,11 +10,6 @@ @interface IBGAPM (PrivateAPIs) @property (class, atomic, assign) BOOL networkEnabled; -/// `w3ExternalTraceIDEnabled` will be only true if APM and network are enabled -@property (class, atomic, assign) BOOL w3ExternalTraceIDEnabled; -/// `w3ExternalGeneratedHeaderEnabled` will be only true if APM, network and w3ExternalTraceIDEnabled are true -@property (class, atomic, assign) BOOL w3ExternalGeneratedHeaderEnabled; -/// `w3CaughtHeaderEnabled` will be only true if APM, network and w3ExternalTraceIDEnabled are true -@property (class, atomic, assign) BOOL w3CaughtHeaderEnabled; + @end diff --git a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h index ec583bbcf8..c0bd0a75b8 100644 --- a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h +++ b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h @@ -4,7 +4,13 @@ NS_ASSUME_NONNULL_BEGIN @interface IBGNetworkLogger (CP) +@property (class, atomic, assign) BOOL w3ExternalTraceIDEnabled; +@property (class, atomic, assign) BOOL w3ExternalGeneratedHeaderEnabled; +@property (class, atomic, assign) BOOL w3CaughtHeaderEnabled; + + + (void)disableAutomaticCapturingOfNetworkLogs; + + (void)addNetworkLogWithUrl:(NSString *)url method:(NSString *)method requestBody:(NSString *)request From 16c7a03bbf51558e9df013a64e0c71992526fdfa Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 25 Jul 2024 17:59:41 +0300 Subject: [PATCH 054/104] fix: js testcases --- examples/default/ios/Podfile.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 639e49319d..a5b1f5d465 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,12 +38,12 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.2.0) + - Instabug (13.1.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core - libevent (2.1.12) - - OCMock (3.9.4) + - OCMock (3.9.3) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -502,7 +502,7 @@ DEPENDENCIES: - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - Instabug (from `https://ios-releases.instabug.com/custom/feature-w3c-header-cp-support/13.2.0/Instabug.podspec`) + - Instabug (from `https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - libevent (~> 2.1.12) - OCMock @@ -578,7 +578,7 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77 Instabug: - :podspec: https://ios-releases.instabug.com/custom/feature-w3c-header-cp-support/13.2.0/Instabug.podspec + :podspec: https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec instabug-reactnative-ndk: :path: "../node_modules/instabug-reactnative-ndk" RCT-Folly: @@ -684,10 +684,10 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: 39f85204dd860ae2f9be0ca652beb82319710325 + Instabug: 0095861b71aeadc1f5356d078ca44ccc5b32d0d3 instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 + OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18 RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3 @@ -736,6 +736,6 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce -PODFILE CHECKSUM: 1db49a5b43158a40ec1d906287420c29aaeab7ee +PODFILE CHECKSUM: 08bf47efd2faf96320ceaf855e2e82598bc7d1ae COCOAPODS: 1.12.0 From 6abe2439fd4616c8a84620d39e829542d7b4c997 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Sun, 28 Jul 2024 19:53:58 +0300 Subject: [PATCH 055/104] feat: add migrate APM into core in ios section --- examples/default/ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index a5b1f5d465..ea4b3a440c 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,7 +38,7 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.1.0) + - Instabug (13.2.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core From e757c07ff317a6feea3f81ff16d4e35154e96487 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Sun, 28 Jul 2024 20:40:30 +0300 Subject: [PATCH 056/104] feat: add migrate APM into core in ios section --- examples/default/ios/Podfile.lock | 66 ++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index ea4b3a440c..75e4da4daa 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -346,9 +346,9 @@ PODS: - glog - react-native-background-timer (2.4.1): - React-Core - - react-native-config (1.5.2): - - react-native-config/App (= 1.5.2) - - react-native-config/App (1.5.2): + - react-native-config (1.5.1): + - react-native-config/App (= 1.5.1) + - react-native-config/App (1.5.1): - React-Core - react-native-google-maps (1.10.3): - Google-Maps-iOS-Utils (= 4.2.2) @@ -356,10 +356,9 @@ PODS: - React-Core - react-native-maps (1.10.3): - React-Core - - react-native-safe-area-context (4.10.8): + - react-native-safe-area-context (4.7.1): - React-Core - - react-native-slider (4.5.2): - - RCT-Folly (= 2021.07.22.00) + - react-native-slider (4.4.3): - React-Core - React-NativeModulesApple (0.72.3): - hermes-engine @@ -473,24 +472,47 @@ PODS: - React-perflogger (= 0.72.3) - RNCClipboard (1.5.1): - React-Core - - RNGestureHandler (2.17.1): + - RNGestureHandler (2.13.4): - RCT-Folly (= 2021.07.22.00) - React-Core - RNInstabug (13.2.0): - Instabug - React-Core - - RNReanimated (3.14.0): - - RCT-Folly (= 2021.07.22.00) + - RNReanimated (3.5.4): + - DoubleConversion + - FBLazyVector + - glog + - hermes-engine + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-callinvoker - React-Core + - React-Core/DevSupport + - React-Core/RCTWebSocket + - React-CoreModules + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-RCTActionSheet + - React-RCTAnimation + - React-RCTAppDelegate + - React-RCTBlob + - React-RCTImage + - React-RCTLinking + - React-RCTNetwork + - React-RCTSettings + - React-RCTText - ReactCommon/turbomodule/core - - RNScreens (3.32.0): - - RCT-Folly (= 2021.07.22.00) + - Yoga + - RNScreens (3.24.0): - React-Core - React-RCTImage - - RNSVG (13.14.1): + - RNSVG (13.10.0): - React-Core - - RNVectorIcons (10.1.0): - - RCT-Folly (= 2021.07.22.00) + - RNVectorIcons (10.0.0): - React-Core - SocketRocket (0.6.1) - Yoga (1.14.0) @@ -704,11 +726,11 @@ SPEC CHECKSUMS: React-jsinspector: b511447170f561157547bc0bef3f169663860be7 React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95 react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe - react-native-config: d7d8a0c65f7fa523197879f6b777997abbfc987e + react-native-config: 86038147314e2e6d10ea9972022aa171e6b1d4d8 react-native-google-maps: 1bcc1f9f13f798fcf230db7fe476f3566d0bc0a3 react-native-maps: 72a8a903f8a1b53e2c777ba79102078ab502e0bf - react-native-safe-area-context: b7daa1a8df36095a032dff095a1ea8963cb48371 - react-native-slider: 593253eb5fbc6ea519290e812bd477fc6abafd5a + react-native-safe-area-context: 9697629f7b2cda43cf52169bb7e0767d330648c2 + react-native-slider: 1cdd6ba29675df21f30544253bf7351d3c2d68c4 React-NativeModulesApple: c57f3efe0df288a6532b726ad2d0322a9bf38472 React-perflogger: 6bd153e776e6beed54c56b0847e1220a3ff92ba5 React-RCTActionSheet: c0b62af44e610e69d9a2049a682f5dba4e9dff17 @@ -727,12 +749,12 @@ SPEC CHECKSUMS: React-utils: bcb57da67eec2711f8b353f6e3d33bd8e4b2efa3 ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 - RNGestureHandler: bbb8e17b10afdafc5cc5746e8f60772236e7e2ca + RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee RNInstabug: e515e490416a20b604e27bdbbebf5316ff3a2012 - RNReanimated: 158b2f80fdb043ab5a645ba047209badbd7eb9a9 - RNScreens: 0bd9eec783bed1032e02a4db9976dae1664a5c7b - RNSVG: af3907ac5d4fa26a862b75a16d8f15bc74f2ceda - RNVectorIcons: bfb663f3f7b37340cd90120151b720641523dc84 + RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 + RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 + RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 + RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce From d878c35f2cdab126518199a807499718d24eeb38 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 29 Jul 2024 23:54:55 +0300 Subject: [PATCH 057/104] fix: Pr comments --- android/src/main/java/com/instabug/reactlibrary/Constants.java | 2 +- .../com/instabug/reactlibrary/RNInstabugReactnativeModule.java | 2 +- src/native/NativeInstabug.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/Constants.java b/android/src/main/java/com/instabug/reactlibrary/Constants.java index c46cb03f84..c8b164162a 100644 --- a/android/src/main/java/com/instabug/reactlibrary/Constants.java +++ b/android/src/main/java/com/instabug/reactlibrary/Constants.java @@ -10,6 +10,6 @@ final class Constants { final static String IBG_ON_NEW_MESSAGE_HANDLER = "IBGonNewMessageHandler"; final static String IBG_ON_NEW_REPLY_RECEIVED_CALLBACK = "IBGOnNewReplyReceivedCallback"; - final static String IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGAPMOnNewW3CFlagsUpdateReceivedCallback"; + final static String IBGCore_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGCoreOnNewW3CFlagsUpdateReceivedCallback"; } diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 8d20544fc1..2bf38ffa36 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -1107,7 +1107,7 @@ public void invoke(@NonNull CoreFeaturesState featuresState) { params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled()); params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled()); - sendEvent(Constants.IBGAPM_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); + sendEvent(Constants.IBGCore_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); } }); } diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 7c7a4c2af2..a6218e20b7 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -158,7 +158,7 @@ export const NativeInstabug = NativeModules.Instabug; export enum NativeEvents { PRESENDING_HANDLER = 'IBGpreSendingHandler', - ON_W3C_FLAGS_CHANE = 'IBGAPMOnNewW3CFlagsUpdateReceivedCallback', + ON_W3C_FLAGS_CHANE = 'IBGCoreOnNewW3CFlagsUpdateReceivedCallback', } export const emitter = new NativeEventEmitter(NativeInstabug); From 1bd75697f0ea4ad8885253e2598d4076be8e36e9 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 1 Aug 2024 16:02:20 +0300 Subject: [PATCH 058/104] fix: PR comment --- .../com/instabug/reactlibrary/Constants.java | 2 +- .../RNInstabugReactnativeModule.java | 2 +- src/modules/Instabug.ts | 17 +++++++++++++++++ src/native/NativeInstabug.ts | 2 +- test/modules/Instabug.spec.ts | 17 +++++++++++++++++ 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/Constants.java b/android/src/main/java/com/instabug/reactlibrary/Constants.java index c8b164162a..f00d4475c4 100644 --- a/android/src/main/java/com/instabug/reactlibrary/Constants.java +++ b/android/src/main/java/com/instabug/reactlibrary/Constants.java @@ -10,6 +10,6 @@ final class Constants { final static String IBG_ON_NEW_MESSAGE_HANDLER = "IBGonNewMessageHandler"; final static String IBG_ON_NEW_REPLY_RECEIVED_CALLBACK = "IBGOnNewReplyReceivedCallback"; - final static String IBGCore_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGCoreOnNewW3CFlagsUpdateReceivedCallback"; + final static String IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGOnNewW3CFlagsUpdateReceivedCallback"; } diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 2bf38ffa36..267b79f472 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -1107,7 +1107,7 @@ public void invoke(@NonNull CoreFeaturesState featuresState) { params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled()); params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled()); - sendEvent(Constants.IBGCore_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); + sendEvent(Constants.IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); } }); } diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 57b4428173..2af14fa728 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -580,3 +580,20 @@ export const componentDidAppearListener = (event: ComponentDidAppearEvent) => { _lastScreen = event.componentName; } }; + +/** + * Sets listener to W3ExternalTraceID flag changes + * @param handler A callback that gets the update value of the flag + */ +export const _registerW3CFlagsChangeListener = ( + handler: (payload: { + isW3ExternalTraceIDEnabled: boolean; + isW3ExternalGeneratedHeaderEnabled: boolean; + isW3CaughtHeaderEnabled: boolean; + }) => void, +) => { + emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANE, (payload) => { + handler(payload); + }); + NativeInstabug.registerW3CFlagsChangeListener(handler); +}; diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index a6218e20b7..7902d0a42e 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -158,7 +158,7 @@ export const NativeInstabug = NativeModules.Instabug; export enum NativeEvents { PRESENDING_HANDLER = 'IBGpreSendingHandler', - ON_W3C_FLAGS_CHANE = 'IBGCoreOnNewW3CFlagsUpdateReceivedCallback', + ON_W3C_FLAGS_CHANE = 'IBGOnNewW3CFlagsUpdateReceivedCallback', } export const emitter = new NativeEventEmitter(NativeInstabug); diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index 9b2e06936e..123f5e3135 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -775,4 +775,21 @@ describe('Instabug Module', () => { Instabug.willRedirectToStore(); expect(NativeInstabug.willRedirectToStore).toBeCalledTimes(1); }); + + it('should register W3C flag listener', async () => { + const callback = jest.fn(); + Instabug._registerW3CFlagsChangeListener(callback); + + expect(NativeInstabug.registerW3CFlagsChangeListener).toBeCalledTimes(1); + expect(NativeInstabug.registerW3CFlagsChangeListener).toBeCalledWith(callback); + }); + + it('should invoke callback on emitting the event IBGOnNewW3CFlagsUpdateReceivedCallback', () => { + const callback = jest.fn(); + Instabug._registerW3CFlagsChangeListener(callback); + emitter.emit(NativeEvents.ON_W3C_FLAGS_CHANE); + + expect(emitter.listenerCount(NativeEvents.ON_W3C_FLAGS_CHANE)).toBe(1); + expect(callback).toHaveBeenCalled(); + }); }); From 9bf4bbd0fa5f3df1fee2da3ab7f9def771165d90 Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:14:49 +0300 Subject: [PATCH 059/104] fix: Pr comments --- .../com/instabug/reactlibrary/RNInstabugReactnativeModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 267b79f472..3c252fb3ae 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -1093,7 +1093,7 @@ public void run() { * Register a listener for W3C flags value change */ @ReactMethod - public void registerW3CFlagsChangeListener(final Callback handler){ + public void registerW3CFlagsChangeListener(){ MainThreadHandler.runOnMainThread(new Runnable() { @Override From a09e8e1a2f4515ae31c81ef1e400c8873eb263d9 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Wed, 11 Sep 2024 23:48:42 +0300 Subject: [PATCH 060/104] fix: added changelog item --- android/native.gradle | 2 +- .../reactlibrary/RNInstabugAPMModuleTest.java | 27 +------------------ .../RNInstabugReactnativeModuleTest.java | 26 ++++++++++++++++++ examples/default/ios/Podfile | 1 - examples/default/ios/Podfile.lock | 14 +++++----- ios/native.rb | 2 +- 6 files changed, 35 insertions(+), 37 deletions(-) diff --git a/android/native.gradle b/android/native.gradle index ca8c4fc3ea..39034d6035 100644 --- a/android/native.gradle +++ b/android/native.gradle @@ -1,5 +1,5 @@ project.ext.instabug = [ - version: '13.2.0.6091772-SNAPSHOT' + version: '13.4.0' ] dependencies { diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java index ea66f6ee83..85ca1384d1 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java @@ -3,8 +3,6 @@ import com.facebook.react.bridge.Promise; import com.instabug.apm.APM; -import com.instabug.apm.InternalAPM; -import com.instabug.apm.configuration.cp.APMFeature; import com.instabug.reactlibrary.utils.MainThreadHandler; @@ -206,29 +204,6 @@ public void testSetFlowAttribute() { verify(APM.class, times(1)); APM.endUITrace(); } - @Test - public void testW3CExternalTraceIDFlag(){ - Promise promise = mock(Promise.class); - InternalAPM internalAPM = mock(InternalAPM.class); - apmModule.isW3ExternalTraceIDEnabled(promise); - boolean expected=internalAPM._isFeatureEnabledCP(APMFeature.W3C_EXTERNAL_TRACE_ID,""); - verify(promise).resolve(expected); - } - @Test - public void testW3CExternalGeneratedHeaderFlag(){ - Promise promise = mock(Promise.class); - InternalAPM internalAPM = mock(InternalAPM.class); - apmModule.isW3ExternalGeneratedHeaderEnabled(promise); - boolean expected=internalAPM._isFeatureEnabledCP(APMFeature.W3C_GENERATED_HEADER_ATTACHING,""); - verify(promise).resolve(expected); - } - @Test - public void testW3CCaughtHeaderFlag(){ - Promise promise = mock(Promise.class); - InternalAPM internalAPM = mock(InternalAPM.class); - apmModule.isW3CaughtHeaderEnabled(promise); - boolean expected=internalAPM._isFeatureEnabledCP(APMFeature.W3C_CAPTURED_HEADER_ATTACHING,""); - verify(promise).resolve(expected); - } + } diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java index beee65c4bf..2eedf0fa85 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java @@ -18,6 +18,8 @@ import com.instabug.library.IssueType; import com.instabug.library.ReproConfigurations; import com.instabug.library.ReproMode; +import com.instabug.library.internal.crossplatform.CoreFeature; +import com.instabug.library.internal.crossplatform.InternalCore; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.ui.onboarding.WelcomeMessage; import com.instabug.reactlibrary.utils.MainThreadHandler; @@ -585,4 +587,28 @@ public void testWillRedirectToStore() { // then mockInstabug.verify(() -> Instabug.willRedirectToStore()); } + @Test + public void testW3CExternalTraceIDFlag(){ + Promise promise = mock(Promise.class); + InternalCore internalAPM = mock(InternalCore.class); + rnModule.isW3ExternalTraceIDEnabled(promise); + boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID); + verify(promise).resolve(expected); + } + @Test + public void testW3CExternalGeneratedHeaderFlag(){ + Promise promise = mock(Promise.class); + InternalCore internalAPM = mock(InternalCore.class); + rnModule.isW3ExternalGeneratedHeaderEnabled(promise); + boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER); + verify(promise).resolve(expected); + } + @Test + public void testW3CCaughtHeaderFlag(){ + Promise promise = mock(Promise.class); + InternalCore internalAPM = mock(InternalCore.class); + rnModule.isW3CaughtHeaderEnabled(promise); + boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER); + verify(promise).resolve(expected); + } } diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile index 31b9b5396b..63c0029932 100644 --- a/examples/default/ios/Podfile +++ b/examples/default/ios/Podfile @@ -26,7 +26,6 @@ target 'InstabugExample' do config = use_native_modules! rn_maps_path = '../node_modules/react-native-maps' pod 'react-native-google-maps', :path => rn_maps_path - pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/feature-w3c-header-cp-support/13.2.0/Instabug.podspec' # Flags change depending on the env values. flags = get_default_flags() diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 75e4da4daa..e6b560a9da 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,12 +38,12 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.2.0) + - Instabug (13.4.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core - libevent (2.1.12) - - OCMock (3.9.3) + - OCMock (3.9.4) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -524,7 +524,6 @@ DEPENDENCIES: - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - Instabug (from `https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - libevent (~> 2.1.12) - OCMock @@ -581,6 +580,7 @@ SPEC REPOS: - fmt - Google-Maps-iOS-Utils - GoogleMaps + - Instabug - libevent - OCMock - SocketRocket @@ -599,8 +599,6 @@ EXTERNAL SOURCES: hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77 - Instabug: - :podspec: https://ios-releases.instabug.com/custom/feature-add-w3c-header-base-cp/13.1.0/Instabug.podspec instabug-reactnative-ndk: :path: "../node_modules/instabug-reactnative-ndk" RCT-Folly: @@ -706,10 +704,10 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: 0095861b71aeadc1f5356d078ca44ccc5b32d0d3 + Instabug: 183aa1e038d01ddc000f06835f46a9ea1f6c992b instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 + OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18 RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3 @@ -758,6 +756,6 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce -PODFILE CHECKSUM: 08bf47efd2faf96320ceaf855e2e82598bc7d1ae +PODFILE CHECKSUM: 26b8b1f0273d40b2b21568157bd5df0421935faa COCOAPODS: 1.12.0 diff --git a/ios/native.rb b/ios/native.rb index 0047a90883..c46209b912 100644 --- a/ios/native.rb +++ b/ios/native.rb @@ -1,4 +1,4 @@ -$instabug = { :version => '13.2.0' } +$instabug = { :version => '13.4.0' } def use_instabug! (spec = nil) version = $instabug[:version] From e0fd17fb06b6f9b598fa59edbdd82bd71c35bb6b Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 12 Sep 2024 01:00:35 +0300 Subject: [PATCH 061/104] fix: feature flag listener --- src/modules/Instabug.ts | 4 ++-- src/native/NativeInstabug.ts | 10 ++-------- src/utils/FeatureFlags.ts | 3 ++- test/modules/Instabug.spec.ts | 4 ++-- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 2af14fa728..0a177b296f 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -592,8 +592,8 @@ export const _registerW3CFlagsChangeListener = ( isW3CaughtHeaderEnabled: boolean; }) => void, ) => { - emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANE, (payload) => { + emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANGE, (payload) => { handler(payload); }); - NativeInstabug.registerW3CFlagsChangeListener(handler); + NativeInstabug.registerW3CFlagsChangeListener(); }; diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 7902d0a42e..c42f4af531 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -145,20 +145,14 @@ export interface InstabugNativeModule extends NativeModule { isW3CaughtHeaderEnabled(): Promise; // W3C Feature Flags Listener for Android - registerW3CFlagsChangeListener( - handler: (payload: { - isW3ExternalTraceIDEnabled: boolean; - isW3ExternalGeneratedHeaderEnabled: boolean; - isW3CaughtHeaderEnabled: boolean; - }) => void, - ): void; + registerW3CFlagsChangeListener(): void; } export const NativeInstabug = NativeModules.Instabug; export enum NativeEvents { PRESENDING_HANDLER = 'IBGpreSendingHandler', - ON_W3C_FLAGS_CHANE = 'IBGOnNewW3CFlagsUpdateReceivedCallback', + ON_W3C_FLAGS_CHANGE = 'IBGOnNewW3CFlagsUpdateReceivedCallback', } export const emitter = new NativeEventEmitter(NativeInstabug); diff --git a/src/utils/FeatureFlags.ts b/src/utils/FeatureFlags.ts index e28fd25f37..479ab7ba47 100644 --- a/src/utils/FeatureFlags.ts +++ b/src/utils/FeatureFlags.ts @@ -1,4 +1,5 @@ import { NativeInstabug } from '../native/NativeInstabug'; +import { _registerW3CFlagsChangeListener } from '../modules/Instabug'; export const FeatureFlags = { isW3ExternalTraceID: () => NativeInstabug.isW3ExternalTraceIDEnabled(), @@ -7,7 +8,7 @@ export const FeatureFlags = { }; export const registerW3CFlagsListener = () => { - NativeInstabug.registerW3CFlagsChangeListener( + _registerW3CFlagsChangeListener( (res: { isW3ExternalTraceIDEnabled: boolean; isW3ExternalGeneratedHeaderEnabled: boolean; diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index 123f5e3135..befa934556 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -787,9 +787,9 @@ describe('Instabug Module', () => { it('should invoke callback on emitting the event IBGOnNewW3CFlagsUpdateReceivedCallback', () => { const callback = jest.fn(); Instabug._registerW3CFlagsChangeListener(callback); - emitter.emit(NativeEvents.ON_W3C_FLAGS_CHANE); + emitter.emit(NativeEvents.ON_W3C_FLAGS_CHANGE); - expect(emitter.listenerCount(NativeEvents.ON_W3C_FLAGS_CHANE)).toBe(1); + expect(emitter.listenerCount(NativeEvents.ON_W3C_FLAGS_CHANGE)).toBe(1); expect(callback).toHaveBeenCalled(); }); }); From ec23cfa0d06911d5e936433a517fa1b0218eaec7 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 12 Sep 2024 01:09:55 +0300 Subject: [PATCH 062/104] fix: feature flag listener --- test/modules/Instabug.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index befa934556..aa25179573 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -781,7 +781,6 @@ describe('Instabug Module', () => { Instabug._registerW3CFlagsChangeListener(callback); expect(NativeInstabug.registerW3CFlagsChangeListener).toBeCalledTimes(1); - expect(NativeInstabug.registerW3CFlagsChangeListener).toBeCalledWith(callback); }); it('should invoke callback on emitting the event IBGOnNewW3CFlagsUpdateReceivedCallback', () => { From a34fafc4b64865fa0d1c7891ac006eafee5f3817 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 16 Sep 2024 14:02:36 +0300 Subject: [PATCH 063/104] feat: migrate w3c flags to APM core --- .circleci/config.yml | 343 +++++++++++------- .gitignore | 2 + CHANGELOG.md | 38 +- android/build.gradle | 2 +- android/src/main/AndroidManifest.xml | 2 +- .../reactlibrary/RNInstabugAPMModule.java | 7 +- .../RNInstabugReactnativeModule.java | 66 ++++ .../RNInstabugReactnativeModuleTest.java | 54 ++- cli/UploadSoFiles.ts | 88 ----- cli/UploadSourcemaps.ts | 89 ----- cli/commands/UploadSoFiles.ts | 38 ++ cli/commands/UploadSourcemaps.ts | 40 ++ cli/index.ts | 4 +- cli/upload/index.ts | 2 + cli/upload/uploadSoFiles.ts | 112 ++++++ cli/upload/uploadSourcemaps.ts | 73 ++++ examples/default/android/app/build.gradle | 6 - .../react/example/ReactNativeFlipper.java | 75 ---- .../react/example/MainApplication.java | 1 - .../RNInstabugExampleReactnativePackage.java | 8 - .../app/src/main/res/raw/instabug_config.json | 4 + .../instabugexample/ReactNativeFlipper.java | 20 - examples/default/android/build.gradle | 8 + examples/default/android/gradle.properties | 3 - .../InstabugExample.xcodeproj/project.pbxproj | 4 + .../ios/InstabugExample/Instabug.plist | Bin 0 -> 157 bytes .../ios/InstabugTests/InstabugSampleTests.m | 51 ++- .../ios/InstabugTests/RNInstabugTests.m | 1 - examples/default/ios/Podfile | 16 - examples/default/ios/Podfile.lock | 8 +- examples/default/src/App.tsx | 11 +- .../default/src/screens/SettingsScreen.tsx | 76 ++++ ios/RNInstabug/InstabugReactBridge.h | 4 +- ios/RNInstabug/InstabugReactBridge.m | 39 +- package.json | 2 +- rollup.config.js | 39 +- scripts/customize-ios-endpoints.sh | 28 ++ scripts/dream-11-delete-unused-features.sh | 70 ++-- scripts/replace.js | 24 +- scripts/snapshot-branch.sh | 30 -- scripts/snapshot-comment.md | 4 +- scripts/snapshot-version.sh | 11 + src/models/FeatureFlag.ts | 12 + src/modules/Instabug.ts | 65 +++- src/native/NativeInstabug.ts | 6 + test/mocks/mockInstabug.ts | 3 + test/modules/Instabug.spec.ts | 89 +++++ tsconfig.upload.json | 10 + upload/package.json | 5 + 49 files changed, 1150 insertions(+), 543 deletions(-) delete mode 100755 cli/UploadSoFiles.ts delete mode 100755 cli/UploadSourcemaps.ts create mode 100755 cli/commands/UploadSoFiles.ts create mode 100755 cli/commands/UploadSourcemaps.ts create mode 100644 cli/upload/index.ts create mode 100755 cli/upload/uploadSoFiles.ts create mode 100644 cli/upload/uploadSourcemaps.ts delete mode 100644 examples/default/android/app/src/debug/java/com/instabug/react/example/ReactNativeFlipper.java create mode 100644 examples/default/android/app/src/main/res/raw/instabug_config.json delete mode 100644 examples/default/android/app/src/release/java/com/instabugexample/ReactNativeFlipper.java create mode 100644 examples/default/ios/InstabugExample/Instabug.plist create mode 100755 scripts/customize-ios-endpoints.sh mode change 100644 => 100755 scripts/dream-11-delete-unused-features.sh delete mode 100755 scripts/snapshot-branch.sh create mode 100755 scripts/snapshot-version.sh create mode 100644 src/models/FeatureFlag.ts create mode 100644 tsconfig.upload.json create mode 100644 upload/package.json diff --git a/.circleci/config.yml b/.circleci/config.yml index c218cf7e93..efca5acab3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,6 +17,12 @@ references: - e2e_ios - e2e_android + dream11_prepare_config: &dream11_prepare_config + prepare_steps: + - prepare_dream11 + requires: + - hold_test_dream11 + commands: install_node_modules: parameters: @@ -36,15 +42,28 @@ commands: parameters: working_directory: type: string + deployment: + type: boolean + default: false steps: - restore_cache: name: Restore Pods Cache keys: - v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} - - run: - name: Install Pods - working_directory: << parameters.working_directory >> - command: pod install --deployment + - when: + condition: << parameters.deployment >> + steps: + - run: + name: Install Pods + working_directory: << parameters.working_directory >> + command: pod install --deployment + - unless: + condition: << parameters.deployment >> + steps: + - run: + name: Install Pods + working_directory: << parameters.working_directory >> + command: pod install - save_cache: name: Save Pods Cache key: v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} @@ -59,10 +78,72 @@ commands: type: string replace: type: string + working_directory: + type: string + default: ~/project steps: - run: name: Find and Replace in << parameters.files >> command: node ~/project/scripts/replace.js << parameters.search >> << parameters.replace >> << parameters.files >> + working_directory: << parameters.working_directory >> + + prepare_custom_package: + parameters: + npm_package: + type: string + android_package: + type: string + api_endpoint: + type: string + working_directory: + type: string + default: ~/project + steps: + - run: + name: Remove README.md file + command: rm README.md + working_directory: << parameters.working_directory >> + - find_and_replace: + files: package.json android/sourcemaps.gradle ios/sourcemaps.sh + search: instabug-reactnative + replace: << parameters.npm_package >> + working_directory: << parameters.working_directory >> + - find_and_replace: + files: cli/upload/uploadSourcemaps.ts cli/upload/uploadSoFiles.ts + search: api.instabug.com + replace: << parameters.api_endpoint >> + working_directory: << parameters.working_directory >> + - find_and_replace: + files: android/native.gradle + search: 'com.instabug.library:instabug:' + replace: 'com.instabug.library-<< parameters.android_package >>:instabug:' + working_directory: << parameters.working_directory >> + + prepare_dream11: + parameters: + working_directory: + type: string + default: ~/project + steps: + - install_node_modules + - prepare_custom_package: + npm_package: '@instabug/instabug-reactnative-dream11' + android_package: dream11 + api_endpoint: st001012dream11.instabug.com + working_directory: << parameters.working_directory >> + - run: + name: Give execute permission to Dream11 script + command: chmod +x ./scripts/dream-11-delete-unused-features.sh + working_directory: << parameters.working_directory >> + - run: + name: Remove unused features + command: ./scripts/dream-11-delete-unused-features.sh + working_directory: << parameters.working_directory >> + # Remove the NDK package to avoid dependency conflicts on Android. + - run: + name: Remove the NDK package + command: yarn remove instabug-reactnative-ndk + working_directory: << parameters.working_directory >>/examples/default notify_github: parameters: @@ -101,20 +182,38 @@ jobs: command: yarn lint:ci test_module: + parameters: + prepare_steps: + type: steps + default: [] + collect_coverage: + type: boolean + default: false executor: name: node/default steps: - advanced-checkout/shallow-checkout + - steps: << parameters.prepare_steps >> - install_node_modules - run: name: Run Tests command: yarn test - - persist_to_workspace: - root: coverage - paths: - - lcov.info + - when: + condition: << parameters.collect_coverage >> + steps: + - persist_to_workspace: + root: coverage + paths: + - lcov.info test_android: + parameters: + prepare_steps: + type: steps + default: [] + collect_coverage: + type: boolean + default: false executor: name: android/android-machine tag: '2024.01.1' @@ -123,15 +222,18 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - # - node/install-yarn + - steps: << parameters.prepare_steps >> - install_node_modules - android/run-tests: working-directory: android test-command: ./gradlew test - - persist_to_workspace: - root: ~/project/android/build/reports/jacoco/jacocoTestReport - paths: - - jacocoTestReport.xml + - when: + condition: << parameters.collect_coverage >> + steps: + - persist_to_workspace: + root: ~/project/android/build/reports/jacoco/jacocoTestReport + paths: + - jacocoTestReport.xml validate_shell_files: machine: @@ -160,10 +262,18 @@ jobs: app-dir: examples/default - install_pods: working_directory: examples/default/ios + deployment: true - run: git --no-pager diff - run: git diff-index HEAD --exit-code -p -I EXCLUDED_ARCHS # Ignore Arch Changes test_ios: + parameters: + prepare_steps: + type: steps + default: [] + collect_coverage: + type: boolean + default: false macos: xcode: 13.4.1 resource_class: macos.m1.medium.gen1 @@ -172,6 +282,7 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout + - steps: << parameters.prepare_steps >> - install_node_modules - install_pods: working_directory: ios @@ -186,16 +297,23 @@ jobs: -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 13 Pro Max,OS=15.5' \ test | xcpretty - - run: - name: Convert xcresult into JSON report - working_directory: ios/coverage - command: xcrun xccov view --report --json result.xcresult > xcode.json - - persist_to_workspace: - root: ios/coverage - paths: - - xcode.json + - when: + condition: << parameters.collect_coverage >> + steps: + - run: + name: Convert xcresult into JSON report + working_directory: ios/coverage + command: xcrun xccov view --report --json result.xcresult > xcode.json + - persist_to_workspace: + root: ios/coverage + paths: + - xcode.json e2e_ios: + parameters: + prepare_steps: + type: steps + default: [] macos: xcode: 13.4.1 resource_class: macos.m1.medium.gen1 @@ -203,6 +321,7 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout + - steps: << parameters.prepare_steps >> - install_node_modules - node/install-packages: pkg-manager: yarn @@ -219,6 +338,11 @@ jobs: name: Rebuild Detox.framework Cache working_directory: examples/default command: detox clean-framework-cache && detox build-framework-cache + # This is a workaround until the iOS SDK is updated to prioritize the custom + # Instabug.plist over the internal Config.plist. + - run: + name: Customize API Endpoints + command: ./scripts/customize-ios-endpoints.sh - run: name: Detox - Build Release App working_directory: examples/default @@ -229,6 +353,10 @@ jobs: command: detox test --configuration ios.sim.release --cleanup e2e_android: + parameters: + prepare_steps: + type: steps + default: [] executor: name: android/android-machine tag: '2024.01.1' @@ -237,7 +365,7 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - # - node/install-yarn + - steps: << parameters.prepare_steps >> - install_node_modules - node/install-packages: pkg-manager: yarn @@ -264,33 +392,16 @@ jobs: release_custom_package: parameters: - npm_package: - type: string - android_package: - type: string - api_endpoint: - type: string + prepare_steps: + type: steps + default: [] working_directory: ~/project executor: name: node/default steps: - advanced-checkout/shallow-checkout + - steps: << parameters.prepare_steps >> - install_node_modules - - run: - name: Remove README.md file - command: rm README.md - - find_and_replace: - files: package.json android/sourcemaps.gradle ios/sourcemaps.sh - search: instabug-reactnative - replace: << parameters.npm_package >> - - find_and_replace: - files: cli/UploadSourcemaps.ts cli/UploadSoFiles.ts - search: api.instabug.com - replace: << parameters.api_endpoint >> - - find_and_replace: - files: android/native.gradle - search: 'com.instabug.library:instabug:' - replace: 'com.instabug.library-<< parameters.android_package >>:instabug:' - run: name: Build the SDK command: yarn build @@ -301,45 +412,6 @@ jobs: name: Publish new enterprise version command: npm publish - # Automate the enterprise D11 sdk changes - release_d11: - working_directory: ~/project - executor: - name: node/default - steps: - - advanced-checkout/shallow-checkout - - install_node_modules - - run: - name: Remove README.md file - command: rm README.md - - find_and_replace: - files: package.json ios/sourcemaps.sh android/sourcemaps.gradle - search: instabug-reactnative - replace: '@instabug/instabug-reactnative-dream11' - - find_and_replace: - files: cli/UploadSourcemaps.ts cli/UploadSoFiles.ts - search: api.instabug.com - replace: st001012dream11.instabug.com - - find_and_replace: - files: android/native.gradle - search: com.instabug.library:instabug - replace: 'com.instabug.library-dream11:instabug' - - run: - name: give exec permssion to d11 script - command: chmod +x ./scripts/dream-11-delete-unused-features.sh - - run: - name: remove un-required features - command: ./scripts/dream-11-delete-unused-features.sh - - run: - name: Build the SDK - command: yarn build - - run: - name: Authorize with npm - command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc - - run: - name: Publish new enterprise version - command: npm publish - publish: macos: xcode: 13.4.1 @@ -397,35 +469,22 @@ jobs: - run: yarn build - run: yarn remove @instabug/danger-plugin-coverage - run: - name: Remove build files from .gitignore - command: sed -i '/dist/d' .gitignore && sed -i '/bin/d' .gitignore - - run: - name: Get snapshot branch name + name: Get snapshot version command: | - source scripts/snapshot-branch.sh - echo "export SNAPSHOT_BRANCH=$SNAPSHOT_BRANCH" >> "$BASH_ENV" + source scripts/snapshot-version.sh + echo "export SNAPSHOT_VERSION=$SNAPSHOT_VERSION" >> "$BASH_ENV" - run: - name: Setup Git - command: | - git config --global user.name "Instabug-CP-CI" - git config --global user.email github-ci+cp@instabug.com - - run: - name: Create snapshot branch - command: git checkout -b $SNAPSHOT_BRANCH - - run: - name: Commit changes - command: | - git add . - git commit -m "chore: add generate files" - - run: - name: Push snapshot - command: git push --force origin $SNAPSHOT_BRANCH + name: Authorize with NPM + command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc + - run: npm version $SNAPSHOT_VERSION --no-git-tag-version + - run: npm publish --tag snapshot - run: name: Install jq command: sudo apt-get update && sudo apt-get install -y jq - - run: - name: Replace snapshot branch in comment template - command: sed -i "s|{BRANCH}|$SNAPSHOT_BRANCH|g" scripts/snapshot-comment.md + - find_and_replace: + files: scripts/snapshot-comment.md + search: '{VERSION}' + replace: $SNAPSHOT_VERSION - notify_github: data: "$(jq -Rcs '{ body: . }' scripts/snapshot-comment.md)" @@ -438,11 +497,14 @@ workflows: - test_android - test_ios - lint - - test_module - - test_android + - test_module: + collect_coverage: true + - test_android: + collect_coverage: true + - test_ios: + collect_coverage: true - validate_shell_files - sync_generated_files - - test_ios - e2e_ios - e2e_android - hold_generate_snapshot: @@ -463,12 +525,6 @@ workflows: filters: branches: only: master - - hold_release_d11: - requires: *release_dependencies - type: approval - filters: - branches: - only: dream11 - publish: requires: - hold_publish @@ -481,6 +537,7 @@ workflows: filters: branches: only: master + - hold_release_nn: requires: *release_dependencies type: approval @@ -494,9 +551,12 @@ workflows: filters: branches: only: master - npm_package: '@instabug/react-native-nn' - android_package: nn - api_endpoint: st001009nn.instabug.com + prepare_steps: + - prepare_custom_package: + npm_package: '@instabug/react-native-nn' + android_package: nn + api_endpoint: st001009nn.instabug.com + - hold_release_injazat: requires: *release_dependencies type: approval @@ -510,12 +570,49 @@ workflows: filters: branches: only: master - npm_package: '@instabug/react-native-injazat' - android_package: injazat - api_endpoint: st001013mec1.instabug.com - - release_d11: + prepare_steps: + - prepare_custom_package: + npm_package: '@instabug/react-native-injazat' + android_package: injazat + api_endpoint: st001013mec1.instabug.com + + # Dream11 tests + - hold_test_dream11: + type: approval + - test_module: + name: test_module_dream11 + <<: *dream11_prepare_config + - test_android: + name: test_android_dream11 + <<: *dream11_prepare_config + - test_ios: + name: test_ios_dream11 + <<: *dream11_prepare_config + - e2e_android: + name: e2e_android_dream11 + <<: *dream11_prepare_config + - e2e_ios: + name: e2e_ios_dream11 + <<: *dream11_prepare_config + + # Dream11 release + - hold_release_dream11: + requires: + - test_module_dream11 + - test_android_dream11 + - test_ios_dream11 + - e2e_android_dream11 + - e2e_ios_dream11 + type: approval + filters: + branches: + only: dream11 + - release_custom_package: + name: release_dream11 requires: - - hold_release_d11 + - hold_release_dream11 filters: branches: only: dream11 + prepare_steps: + - prepare_dream11 diff --git a/.gitignore b/.gitignore index 50fb3439f9..4033aaa3b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Distribution dist/ bin/ +upload/* +!upload/package.json # NodeJS node_modules/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 449416d3a8..2e36e808d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,26 @@ # Changelog -## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...dev) +## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.3.0...dev) + +### Added + +- Add support for Expo Router navigation tracking ([#1270](https://github.com/Instabug/Instabug-React-Native/pull/1270)). + +## [13.3.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...v13.3.0) (August 4, 2024) + +### Added + +- Add support for Feature Flags APIs `Instabug.addFeatureFlags`, `Instabug.removeFeatureFlags` and `Instabug.clearAllFeatureFlags` ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). +- Export `uploadSourcemaps` and `uploadSoFiles` utilities in the `instabug-reactnative/upload` sub-package for usage in custom Node.js upload scripts ([#1252](https://github.com/Instabug/Instabug-React-Native/pull/1252)). + +### Changed + +- Bump Instabug Android SDK to v13.3.0 ([#1261](https://github.com/Instabug/Instabug-React-Native/pull/1261)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v13.3.0). +- Bump Instabug iOS SDK to v13.3.0 ([#1262](https://github.com/Instabug/Instabug-React-Native/pull/1262)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/13.3.0). + +### Deprecated + +- Deprecate Experiments APIs `Instabug.addExperiments`, `Instabug.removeExperiments` and `Instabug.clearAllExperiments` in favor of the new Feature Flags APIs ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). ### Fixed @@ -59,8 +79,20 @@ - Bump Instabug iOS SDK to v13.0.0 ([#1189](https://github.com/Instabug/Instabug-React-Native/pull/1189)). [See release notes](https://github.com/instabug/instabug-ios/releases/tag/13.0.0). - Bump Instabug Android SDK to v13.0.0 ([#1188](https://github.com/Instabug/Instabug-React-Native/pull/1188)). [See release notes](https://github.com/Instabug/android/releases/tag/v13.0.0). +<<<<<<< HEAD + ## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...v12.9.0) (April 2, 2024) +======= + +### Deprecated + +- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). + +## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...12.9.0)(April 2, 2024) + +> > > > > > > origin/dev + ### Added - Adds symbol files upload script ([#1137](https://github.com/Instabug/Instabug-React-Native/pull/1137)) @@ -71,10 +103,6 @@ - Deprecate execution traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setFlowAttribute` in favor of the new app flow APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). -### Deprecated - -- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). - ### Changed - Bump Instabug Android SDK to v12.9.0 ([#1168](https://github.com/Instabug/Instabug-React-Native/pull/1168)). [See release notes](https://github.com/Instabug/android/releases/tag/v12.9.0). diff --git a/android/build.gradle b/android/build.gradle index 2d3eceb239..ffd71b5f87 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -57,7 +57,7 @@ android { minSdkVersion getExtOrDefault('minSdkVersion').toInteger() targetSdkVersion getExtOrDefault('targetSdkVersion').toInteger() versionCode 1 - versionName "13.2.0" + versionName "13.3.0" multiDexEnabled true ndk { abiFilters "armeabi-v7a", "x86" diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 44ad85bcd7..9af27fbd31 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 6d604b6a94..d9f72fc2ca 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -330,10 +330,10 @@ private void networkLogAndroid(final double requestStartTime, @Nullable final String errorDomain, @Nullable final ReadableMap w3cAttributes, @Nullable final String gqlQueryName, - @Nullable final String serverErrorMessage) { + @Nullable final String serverErrorMessage + ) { try { APMNetworkLogger networkLogger = new APMNetworkLogger(); - final boolean hasError = errorDomain != null && !errorDomain.isEmpty(); final String errorMessage = hasError ? errorDomain : null; @@ -363,13 +363,12 @@ private void networkLogAndroid(final double requestStartTime, w3cAttributes.getString("w3cGeneratedHeader"), w3cAttributes.getString("w3cCaughtHeader") ); - try { Method method = 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( networkLogger, - (long) requestStartTime, + (long) requestStartTime * 1000, (long) requestDuration, requestHeaders, requestBody, diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 3c252fb3ae..000a8e054e 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -17,6 +17,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeArray; @@ -36,6 +37,7 @@ 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.featuresflags.model.IBGFeatureFlag; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; import com.instabug.library.logging.InstabugLog; @@ -48,6 +50,7 @@ import com.instabug.reactlibrary.utils.MainThreadHandler; import com.instabug.reactlibrary.utils.RNTouchedViewExtractor; + import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; @@ -57,6 +60,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -1030,6 +1034,9 @@ public void run() { }); } + /** + * @deprecated see @link #addFeatureFlags(ReadableArray) + */ @ReactMethod public void addExperiments(final ReadableArray experiments) { MainThreadHandler.runOnMainThread(new Runnable() { @@ -1046,6 +1053,9 @@ public void run() { }); } + /** + * @deprecated see {@link #removeFeatureFlags(ReadableArray)} + */ @ReactMethod public void removeExperiments(final ReadableArray experiments) { MainThreadHandler.runOnMainThread(new Runnable() { @@ -1062,6 +1072,9 @@ public void run() { }); } + /** + * @deprecated see {@link #removeAllFeatureFlags()} + */ @ReactMethod public void clearAllExperiments() { MainThreadHandler.runOnMainThread(new Runnable() { @@ -1076,6 +1089,59 @@ public void run() { }); } + @ReactMethod + public void addFeatureFlags(final ReadableMap featureFlagsMap) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + Iterator> iterator = featureFlagsMap.getEntryIterator(); + ArrayList featureFlags = new ArrayList<>(); + while (iterator.hasNext()) { + Map.Entry item = iterator.next(); + String variant = (String) item.getValue(); + String name = item.getKey(); + featureFlags.add(new IBGFeatureFlag(name, variant.isEmpty() ? null : variant)); + } + if (!featureFlags.isEmpty()) { + Instabug.addFeatureFlags(featureFlags); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @ReactMethod + public void removeFeatureFlags(final ReadableArray featureFlags) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + ArrayList stringArray = ArrayUtil.parseReadableArrayOfStrings(featureFlags); + Instabug.removeFeatureFlag(stringArray); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @ReactMethod + public void removeAllFeatureFlags() { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + Instabug.removeAllFeatureFlags(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + @ReactMethod public void willRedirectToStore() { MainThreadHandler.runOnMainThread(new Runnable() { diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java index 2eedf0fa85..d1349f431b 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java @@ -20,6 +20,7 @@ import com.instabug.library.ReproMode; import com.instabug.library.internal.crossplatform.CoreFeature; import com.instabug.library.internal.crossplatform.InternalCore; +import com.instabug.library.featuresflags.model.IBGFeatureFlag; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.ui.onboarding.WelcomeMessage; import com.instabug.reactlibrary.utils.MainThreadHandler; @@ -40,6 +41,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -569,8 +571,6 @@ public void testIdentifyUserWithId() { @Test public void given$clearAllExperiments_whenQuery_thenShouldCallNativeApi() { - // given - // when rnModule.clearAllExperiments(); @@ -579,6 +579,56 @@ public void testIdentifyUserWithId() { Instabug.clearAllExperiments(); } + @Test + public void testAddFeatureFlags() { + // given + JavaOnlyMap map = new JavaOnlyMap(); + map.putString("key1", "value1"); + map.putString("key2", "value2"); + + // when + rnModule.addFeatureFlags(map); + + // then + Iterator> iterator = map.getEntryIterator(); + ArrayList featureFlags = new ArrayList<>(); + while (iterator.hasNext()) { + Map.Entry item = iterator.next(); + featureFlags.add(new IBGFeatureFlag(item.getKey(), (String) item.getValue())); + } + + mockInstabug.verify(() -> Instabug.addFeatureFlags(featureFlags)); + + } + + @Test + public void testRemoveFeatureFlags() { + // given + JavaOnlyArray array = new JavaOnlyArray(); + array.pushString("exp1"); + array.pushString("exp2"); + + // when + rnModule.removeFeatureFlags(array); + + // then + List expectedList = new ArrayList(); + for (Object o : array.toArrayList()) { + expectedList.add((String) o); + } + mockInstabug.verify(() -> Instabug.removeFeatureFlag(expectedList)); + + } + + @Test + public void testRemoveAllFeatureFlags() { + // when + rnModule.removeAllFeatureFlags(); + + // then + mockInstabug.verify(() -> Instabug.removeAllFeatureFlags()); + } + @Test public void testWillRedirectToStore() { // when diff --git a/cli/UploadSoFiles.ts b/cli/UploadSoFiles.ts deleted file mode 100755 index 6329f4d27f..0000000000 --- a/cli/UploadSoFiles.ts +++ /dev/null @@ -1,88 +0,0 @@ -import axios from 'axios'; -import { Command, Option } from 'commander'; -import FormData from 'form-data'; -import fs from 'fs'; - -interface UploadSoFilesOptions { - arch: 'x86' | 'x86_64' | 'arm64-v8a' | 'armeabi-v7a'; - file: string; - token: string; - name: string; - api_key: string; -} -/** - * This script uploads .so files to the specified endpoint used in NDK crash reporting. - * Usage: node upload-so-files.js --arch --file --api_key --token --name - */ - -export const UploadSoFilesCommand = new Command(); - -UploadSoFilesCommand.name('upload-so-files') - .addOption( - new Option('-arch, --arch ', 'arch') - .choices(['x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a']) - .makeOptionMandatory(), - ) - .addOption( - new Option( - '-f, --file ', - 'The path of the symbol files in Zip format', - ).makeOptionMandatory(), - ) - .addOption(new Option('--api_key ', 'Your App key').makeOptionMandatory()) - .addOption( - new Option('-t, --token ', 'Your App Token') - .env('INSTABUG_APP_TOKEN') - .makeOptionMandatory(), - ) - .addOption( - new Option('-n, --name ', 'The app version name') - .env('INSTABUG_APP_VERSION_NAME') - .makeOptionMandatory(), - ) - .action(function (this: Command) { - const options = this.opts(); - UploadSoFiles(options); - }) - .showHelpAfterError(); - -const UploadSoFiles = async (opts: UploadSoFilesOptions) => { - const fileName = opts.file; - if (fileName == null) { - console.error('Failed to upload So Files: invalid file path'); - process.exit(1); - } - - if (fs.existsSync(fileName) === false) { - console.error('Failed to upload So Files: File not found'); - process.exit(1); - } - var fileExt = fileName.split('.').pop(); - - if (fileExt !== 'zip') { - console.error('Failed to upload So Files: You can only upload ZIP files'); - process.exit(1); - } - - const fileBlob = fs.readFileSync(opts.file); - - const form = new FormData(); - form.append('app_version', opts.name); - form.append('so_file', fileBlob, fileName); - form.append('application_token', opts.token); - form.append('api_key', opts.api_key); - form.append('arch', opts.arch); - - console.log('Uploading So files...'); - const uploadEndpoint = 'https://api.instabug.com/api/web/public/so_files'; - try { - await axios.post(uploadEndpoint, form, { - headers: form.getHeaders(), - }); - - console.log(`Successfully uploaded So Files for version: ${opts.name} with arch ${opts.arch}`); - } catch (err) { - console.error('Failed to upload So Files:', axios.isAxiosError(err) ? err.response?.data : err); - process.exit(1); - } -}; diff --git a/cli/UploadSourcemaps.ts b/cli/UploadSourcemaps.ts deleted file mode 100755 index 939629cb5f..0000000000 --- a/cli/UploadSourcemaps.ts +++ /dev/null @@ -1,89 +0,0 @@ -import axios from 'axios'; -import { Command, Option } from 'commander'; -import FormData from 'form-data'; -import fs from 'fs'; - -interface UploadSourcemapsOptions { - platform: 'android' | 'ios'; - file: string; - token: string; - name: string; - code: string; - label?: string; -} - -export const uploadSourcemapsCommand = new Command(); - -uploadSourcemapsCommand - .name('upload-sourcemaps') - .addOption( - new Option('-p, --platform ', 'Platform') - .choices(['ios', 'android']) - .makeOptionMandatory(), - ) - .addOption( - new Option('-f, --file ', 'The path of the source map file').makeOptionMandatory(), - ) - .addOption( - new Option('-t, --token ', 'Your App Token') - .env('INSTABUG_APP_TOKEN') - .makeOptionMandatory(), - ) - .addOption( - new Option('-n, --name ', 'The app version name') - .env('INSTABUG_APP_VERSION_NAME') - .makeOptionMandatory(), - ) - .addOption( - new Option('-c, --code ', 'The app version code') - .env('INSTABUG_APP_VERSION_CODE') - .makeOptionMandatory(), - ) - .addOption( - new Option('-l, --label ', "The CodePush label if it's a CodePush release").env( - 'INSTABUG_APP_VERSION_LABEL', - ), - ) - .action(function (this: Command) { - const options = this.opts(); - uploadSourcemaps(options); - }) - .showHelpAfterError(); - -const uploadSourcemaps = async (opts: UploadSourcemapsOptions) => { - const fileName = `${opts.platform}-sourcemap.json`; - const fileBlob = fs.readFileSync(opts.file); - - const version = { - code: opts.code, - name: opts.name, - codepush: opts.label, - }; - - const form = new FormData(); - form.append('app_version', JSON.stringify(version)); - form.append('symbols_file', fileBlob, fileName); - form.append('application_token', opts.token); - form.append('platform', 'react_native'); - form.append('os', opts.platform); - - console.log('Uploading Source map file...'); - - try { - const response = await axios.post('https://api.instabug.com/api/sdk/v3/symbols_files', form, { - headers: form.getHeaders(), - }); - - const appVersion = version.codepush - ? `${version.name} (${version.code})+codepush:${version.codepush}` - : `${version.name} (${version.code})`; - - console.log(`Successfully uploaded Source maps for version: ${appVersion}`); - console.log(response.data); - } catch (err) { - console.error( - 'Failed to upload source maps:', - axios.isAxiosError(err) ? err.response?.data : err, - ); - } -}; diff --git a/cli/commands/UploadSoFiles.ts b/cli/commands/UploadSoFiles.ts new file mode 100755 index 0000000000..99b23e3e4c --- /dev/null +++ b/cli/commands/UploadSoFiles.ts @@ -0,0 +1,38 @@ +import { Command, Option } from 'commander'; +import { uploadSoFiles, UploadSoFilesOptions } from '../upload/uploadSoFiles'; + +/** + * This script uploads .so files to the specified endpoint used in NDK crash reporting. + * Usage: node upload-so-files.js --arch --file --api_key --token --name + */ + +export const UploadSoFilesCommand = new Command(); + +UploadSoFilesCommand.name('upload-so-files') + .addOption( + new Option('-arch, --arch ', 'arch') + .choices(['x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a']) + .makeOptionMandatory(), + ) + .addOption( + new Option( + '-f, --file ', + 'The path of the symbol files in Zip format', + ).makeOptionMandatory(), + ) + .addOption(new Option('--api_key ', 'Your App key').makeOptionMandatory()) + .addOption( + new Option('-t, --token ', 'Your App Token') + .env('INSTABUG_APP_TOKEN') + .makeOptionMandatory(), + ) + .addOption( + new Option('-n, --name ', 'The app version name') + .env('INSTABUG_APP_VERSION_NAME') + .makeOptionMandatory(), + ) + .action(function (this: Command) { + const options = this.opts(); + uploadSoFiles(options); + }) + .showHelpAfterError(); diff --git a/cli/commands/UploadSourcemaps.ts b/cli/commands/UploadSourcemaps.ts new file mode 100755 index 0000000000..5199693e77 --- /dev/null +++ b/cli/commands/UploadSourcemaps.ts @@ -0,0 +1,40 @@ +import { Command, Option } from 'commander'; +import { uploadSourcemaps, UploadSourcemapsOptions } from '../upload/uploadSourcemaps'; + +export const uploadSourcemapsCommand = new Command(); + +uploadSourcemapsCommand + .name('upload-sourcemaps') + .addOption( + new Option('-p, --platform ', 'Platform') + .choices(['ios', 'android']) + .makeOptionMandatory(), + ) + .addOption( + new Option('-f, --file ', 'The path of the source map file').makeOptionMandatory(), + ) + .addOption( + new Option('-t, --token ', 'Your App Token') + .env('INSTABUG_APP_TOKEN') + .makeOptionMandatory(), + ) + .addOption( + new Option('-n, --name ', 'The app version name') + .env('INSTABUG_APP_VERSION_NAME') + .makeOptionMandatory(), + ) + .addOption( + new Option('-c, --code ', 'The app version code') + .env('INSTABUG_APP_VERSION_CODE') + .makeOptionMandatory(), + ) + .addOption( + new Option('-l, --label ', "The CodePush label if it's a CodePush release").env( + 'INSTABUG_APP_VERSION_LABEL', + ), + ) + .action(function (this: Command) { + const options = this.opts(); + uploadSourcemaps(options); + }) + .showHelpAfterError(); diff --git a/cli/index.ts b/cli/index.ts index c1731d67a5..8df747e75e 100644 --- a/cli/index.ts +++ b/cli/index.ts @@ -1,8 +1,8 @@ #!/usr/bin/env node import { Command } from 'commander'; -import { uploadSourcemapsCommand } from './UploadSourcemaps'; -import { UploadSoFilesCommand } from './UploadSoFiles'; +import { uploadSourcemapsCommand } from './commands/UploadSourcemaps'; +import { UploadSoFilesCommand } from './commands/UploadSoFiles'; const program = new Command(); diff --git a/cli/upload/index.ts b/cli/upload/index.ts new file mode 100644 index 0000000000..b09f4b243b --- /dev/null +++ b/cli/upload/index.ts @@ -0,0 +1,2 @@ +export * from './uploadSourcemaps'; +export * from './uploadSoFiles'; diff --git a/cli/upload/uploadSoFiles.ts b/cli/upload/uploadSoFiles.ts new file mode 100755 index 0000000000..fb25f60632 --- /dev/null +++ b/cli/upload/uploadSoFiles.ts @@ -0,0 +1,112 @@ +import axios from 'axios'; +import FormData from 'form-data'; +import fs from 'fs'; + +export interface UploadSoFilesOptions { + arch: 'x86' | 'x86_64' | 'arm64-v8a' | 'armeabi-v7a'; + file: string; + token: string; + name: string; + api_key: string; + + /** + * Disables logging to the console and prevents process exit on error. + * + * @default false + * */ + silent?: boolean; +} + +/** + * Uploads NDK `.so` files to Instabug. + * + * @param opts Options for the `.so` files upload process. + * @returns A promise that resolves to a boolean indicating whether the upload was successful. + */ +export const uploadSoFiles = async (opts: UploadSoFilesOptions): Promise => { + const fileName = opts.file; + + const validFilePath = assert( + fileName != null, + 'Failed to upload So Files: invalid file path', + opts.silent, + ); + + if (!validFilePath) { + return false; + } + + const fileExists = assert( + fs.existsSync(fileName), + 'Failed to upload So Files: File not found', + opts.silent, + ); + + if (!fileExists) { + return false; + } + + const fileExt = fileName.split('.').pop(); + + const isZipFile = assert( + fileExt === 'zip', + 'Failed to upload So Files: You can only upload ZIP files', + opts.silent, + ); + + if (!isZipFile) { + return false; + } + + const fileBlob = fs.readFileSync(opts.file); + + const form = new FormData(); + form.append('app_version', opts.name); + form.append('so_file', fileBlob, fileName); + form.append('application_token', opts.token); + form.append('api_key', opts.api_key); + form.append('arch', opts.arch); + + if (!opts.silent) { + console.log('Uploading So files...'); + } + + const uploadEndpoint = 'https://api.instabug.com/api/web/public/so_files'; + try { + await axios.post(uploadEndpoint, form, { + headers: form.getHeaders(), + }); + + if (!opts.silent) { + console.log( + `Successfully uploaded So Files for version: ${opts.name} with arch ${opts.arch}`, + ); + } + + return true; + } catch (err) { + if (!opts.silent) { + console.error( + 'Failed to upload So Files:', + axios.isAxiosError(err) ? err.response?.data : err, + ); + + process.exit(1); + } + + return false; + } +}; + +export const assert = (condition: unknown, message: string, silent?: boolean): boolean => { + if (silent) { + return Boolean(condition); + } + + if (!condition) { + console.error(message); + process.exit(1); + } + + return true; +}; diff --git a/cli/upload/uploadSourcemaps.ts b/cli/upload/uploadSourcemaps.ts new file mode 100644 index 0000000000..701ce9ead8 --- /dev/null +++ b/cli/upload/uploadSourcemaps.ts @@ -0,0 +1,73 @@ +import axios from 'axios'; +import FormData from 'form-data'; +import fs from 'fs'; + +export interface UploadSourcemapsOptions { + platform: 'android' | 'ios'; + file: string; + token: string; + name: string; + code: string; + label?: string; + + /** + * Disables logging to the console and prevents process exit on error. + * + * @default false + * */ + silent?: boolean; +} + +/** + * Uploads JavaScript sourcemaps to Instabug. + * + * @param opts Options for the sourcemaps upload process. + * @returns A promise that resolves to a boolean indicating whether the upload was successful. + */ +export const uploadSourcemaps = async (opts: UploadSourcemapsOptions): Promise => { + const fileName = `${opts.platform}-sourcemap.json`; + const fileBlob = fs.readFileSync(opts.file); + + const version = { + code: opts.code, + name: opts.name, + codepush: opts.label, + }; + + const form = new FormData(); + form.append('app_version', JSON.stringify(version)); + form.append('symbols_file', fileBlob, fileName); + form.append('application_token', opts.token); + form.append('platform', 'react_native'); + form.append('os', opts.platform); + + if (!opts.silent) { + console.log('Uploading Source map file...'); + } + + try { + const response = await axios.post('https://api.instabug.com/api/sdk/v3/symbols_files', form, { + headers: form.getHeaders(), + }); + + const appVersion = version.codepush + ? `${version.name} (${version.code})+codepush:${version.codepush}` + : `${version.name} (${version.code})`; + + if (!opts.silent) { + console.log(`Successfully uploaded Source maps for version: ${appVersion}`); + console.log(response.data); + } + + return true; + } catch (err) { + if (!opts.silent) { + console.error( + 'Failed to upload source maps:', + axios.isAxiosError(err) ? err.response?.data : err, + ); + } + + return false; + } +}; diff --git a/examples/default/android/app/build.gradle b/examples/default/android/app/build.gradle index f556607edc..c3d5374954 100644 --- a/examples/default/android/app/build.gradle +++ b/examples/default/android/app/build.gradle @@ -171,12 +171,6 @@ dependencies { implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") - debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { - exclude group:'com.squareup.okhttp3', module:'okhttp' - } - - debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") if (hermesEnabled.toBoolean()) { implementation("com.facebook.react:hermes-android") } else { diff --git a/examples/default/android/app/src/debug/java/com/instabug/react/example/ReactNativeFlipper.java b/examples/default/android/app/src/debug/java/com/instabug/react/example/ReactNativeFlipper.java deleted file mode 100644 index a769aa68fc..0000000000 --- a/examples/default/android/app/src/debug/java/com/instabug/react/example/ReactNativeFlipper.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.instabug.react.example; - -import android.content.Context; -import com.facebook.flipper.android.AndroidFlipperClient; -import com.facebook.flipper.android.utils.FlipperUtils; -import com.facebook.flipper.core.FlipperClient; -import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; -import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; -import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; -import com.facebook.flipper.plugins.inspector.DescriptorMapping; -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; -import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; -import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; -import com.facebook.react.ReactInstanceEventListener; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.modules.network.NetworkingModule; -import okhttp3.OkHttpClient; - -/** - * Class responsible of loading Flipper inside your React Native application. This is the debug - * flavor of it. Here you can add your own plugins and customize the Flipper setup. - */ -public class ReactNativeFlipper { - public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (FlipperUtils.shouldEnableFlipper(context)) { - final FlipperClient client = AndroidFlipperClient.getInstance(context); - - client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); - client.addPlugin(new DatabasesFlipperPlugin(context)); - client.addPlugin(new SharedPreferencesFlipperPlugin(context)); - client.addPlugin(CrashReporterPlugin.getInstance()); - - NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); - NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { - @Override - public void apply(OkHttpClient.Builder builder) { - builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); - } - }); - client.addPlugin(networkFlipperPlugin); - client.start(); - - // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized - // Hence we run if after all native modules have been initialized - ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); - if (reactContext == null) { - reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceEventListener() { - @Override - public void onReactContextInitialized(ReactContext reactContext) { - reactInstanceManager.removeReactInstanceEventListener(this); - reactContext.runOnNativeModulesQueueThread( - new Runnable() { - @Override - public void run() { - client.addPlugin(new FrescoFlipperPlugin()); - } - }); - } - }); - } else { - client.addPlugin(new FrescoFlipperPlugin()); - } - } - } -} diff --git a/examples/default/android/app/src/main/java/com/instabug/react/example/MainApplication.java b/examples/default/android/app/src/main/java/com/instabug/react/example/MainApplication.java index a988f0a841..a5b32db53f 100644 --- a/examples/default/android/app/src/main/java/com/instabug/react/example/MainApplication.java +++ b/examples/default/android/app/src/main/java/com/instabug/react/example/MainApplication.java @@ -56,6 +56,5 @@ public void onCreate() { // If you opted-in for the New Architecture, we load the native entry point for this app. DefaultNewArchitectureEntryPoint.load(); } - ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); } } diff --git a/examples/default/android/app/src/main/java/com/instabug/react/example/RNInstabugExampleReactnativePackage.java b/examples/default/android/app/src/main/java/com/instabug/react/example/RNInstabugExampleReactnativePackage.java index 304ab68704..977afa782e 100644 --- a/examples/default/android/app/src/main/java/com/instabug/react/example/RNInstabugExampleReactnativePackage.java +++ b/examples/default/android/app/src/main/java/com/instabug/react/example/RNInstabugExampleReactnativePackage.java @@ -6,14 +6,6 @@ import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; -import com.instabug.reactlibrary.RNInstabugAPMModule; -import com.instabug.reactlibrary.RNInstabugBugReportingModule; -import com.instabug.reactlibrary.RNInstabugCrashReportingModule; -import com.instabug.reactlibrary.RNInstabugFeatureRequestsModule; -import com.instabug.reactlibrary.RNInstabugReactnativeModule; -import com.instabug.reactlibrary.RNInstabugRepliesModule; -import com.instabug.reactlibrary.RNInstabugSessionReplayModule; -import com.instabug.reactlibrary.RNInstabugSurveysModule; import java.util.ArrayList; import java.util.Collections; diff --git a/examples/default/android/app/src/main/res/raw/instabug_config.json b/examples/default/android/app/src/main/res/raw/instabug_config.json new file mode 100644 index 0000000000..86b3a7a225 --- /dev/null +++ b/examples/default/android/app/src/main/res/raw/instabug_config.json @@ -0,0 +1,4 @@ +{ + "instabug-domain": "api.instabug.com", + "apm-domain": "api-apm.instabug.com" +} diff --git a/examples/default/android/app/src/release/java/com/instabugexample/ReactNativeFlipper.java b/examples/default/android/app/src/release/java/com/instabugexample/ReactNativeFlipper.java deleted file mode 100644 index 34e4708ab0..0000000000 --- a/examples/default/android/app/src/release/java/com/instabugexample/ReactNativeFlipper.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.instabug.react.example; - -import android.content.Context; -import com.facebook.react.ReactInstanceManager; - -/** - * Class responsible of loading Flipper inside your React Native application. This is the release - * flavor of it so it's empty as we don't want to load Flipper. - */ -public class ReactNativeFlipper { - public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - // Do nothing as we don't want to initialize Flipper on Release. - } -} diff --git a/examples/default/android/build.gradle b/examples/default/android/build.gradle index 0336ff851f..7fa616eb1b 100644 --- a/examples/default/android/build.gradle +++ b/examples/default/android/build.gradle @@ -27,5 +27,13 @@ allprojects { maven { url("$rootDir/../node_modules/detox/Detox-android") } + + maven { + credentials { + username System.getenv("DREAM11_MAVEN_USERNAME") + password System.getenv("DREAM11_MAVEN_PASSWORD") + } + url "https://mvn.instabug.com/nexus/repository/dream-11" + } } } diff --git a/examples/default/android/gradle.properties b/examples/default/android/gradle.properties index d1a632d51f..6a35482a52 100644 --- a/examples/default/android/gradle.properties +++ b/examples/default/android/gradle.properties @@ -24,9 +24,6 @@ android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true -# Version of flipper SDK to use with React Native -FLIPPER_VERSION=0.182.0 - # Use this property to specify which architecture you want to build. # You can also override it from the CLI using # ./gradlew -PreactNativeArchitectures=x86_64 diff --git a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj index afe4ffe605..3b05a8f1e0 100644 --- a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj +++ b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ CC3DF8932A1DFC9A003E9914 /* InstabugSurveysTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3DF88B2A1DFC99003E9914 /* InstabugSurveysTests.m */; }; CC3DF8942A1DFC9A003E9914 /* InstabugAPMTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3DF88C2A1DFC99003E9914 /* InstabugAPMTests.m */; }; CC3DF8952A1DFC9A003E9914 /* IBGConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3DF88D2A1DFC9A003E9914 /* IBGConstants.m */; }; + CC487A9C2C71FCFC0021F680 /* Instabug.plist in Resources */ = {isa = PBXBuildFile; fileRef = CC487A9B2C71FCFC0021F680 /* Instabug.plist */; }; CCF1E4092B022CF20024802D /* RNInstabugTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCF1E4082B022CF20024802D /* RNInstabugTests.m */; }; CD36F4707EA1F435D2CC7A15 /* libPods-InstabugExample-InstabugTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF7A6E02D40E0CEEA833CC4 /* libPods-InstabugExample-InstabugTests.a */; }; F7BF47401EF3A435254C97BB /* libPods-InstabugExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BAED0D0441A708AE2390E153 /* libPods-InstabugExample.a */; }; @@ -64,6 +65,7 @@ CC3DF88B2A1DFC99003E9914 /* InstabugSurveysTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugSurveysTests.m; sourceTree = ""; }; CC3DF88C2A1DFC99003E9914 /* InstabugAPMTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugAPMTests.m; sourceTree = ""; }; CC3DF88D2A1DFC9A003E9914 /* IBGConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IBGConstants.m; sourceTree = ""; }; + CC487A9B2C71FCFC0021F680 /* Instabug.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = Instabug.plist; path = InstabugExample/Instabug.plist; sourceTree = ""; }; CCF1E4082B022CF20024802D /* RNInstabugTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNInstabugTests.m; sourceTree = ""; }; DBCB1B1D023646D84146C91E /* Pods-InstabugExample-InstabugTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InstabugExample-InstabugTests.release.xcconfig"; path = "Target Support Files/Pods-InstabugExample-InstabugTests/Pods-InstabugExample-InstabugTests.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; @@ -120,6 +122,7 @@ 13B07FAE1A68108700A75B9A /* InstabugExample */ = { isa = PBXGroup; children = ( + CC487A9B2C71FCFC0021F680 /* Instabug.plist */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.mm */, 13B07FB51A68108700A75B9A /* Images.xcassets */, @@ -296,6 +299,7 @@ buildActionMask = 2147483647; files = ( 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + CC487A9C2C71FCFC0021F680 /* Instabug.plist in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/examples/default/ios/InstabugExample/Instabug.plist b/examples/default/ios/InstabugExample/Instabug.plist new file mode 100644 index 0000000000000000000000000000000000000000..24d035f427616a1490762b3e7c6b8861c863c4a4 GIT binary patch literal 157 zcmYc)$jK}&F)+Bq$i&PN=b2Yrl9*JQ?ik=38srlV;{w_70_qthB?ZM+`ud3lnYxJu vxq6vU#d^v4xgbIP;*@OtGUIpwWh9ljRB`aiXaq5U0V5-XW?+TVFscFo;^Zpb literal 0 HcmV?d00001 diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index 102b0bb0aa..88db2c4be9 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -8,12 +8,12 @@ #import #import "OCMock/OCMock.h" #import "Instabug/Instabug.h" -#import "Instabug/IBGSurvey.h" #import "InstabugReactBridge.h" #import #import "IBGConstants.h" #import "RNInstabug.h" #import + @protocol InstabugCPTestProtocol /** * This protocol helps in correctly mapping Instabug mocked methods @@ -72,7 +72,7 @@ - (void)testInit { NSArray *invocationEvents = [NSArray arrayWithObjects:[NSNumber numberWithInteger:floatingButtonInvocationEvent], nil]; BOOL useNativeNetworkInterception = YES; IBGSDKDebugLogsLevel sdkDebugLogsLevel = IBGSDKDebugLogsLevelDebug; - + OCMStub([mock setCodePushVersion:codePushVersion]); [self.instabugBridge init:appToken invocationEvents:invocationEvents debugLogsLevel:sdkDebugLogsLevel useNativeNetworkInterception:useNativeNetworkInterception codePushVersion:codePushVersion]; @@ -84,9 +84,9 @@ - (void)testInit { - (void)testSetCodePushVersion { id mock = OCMClassMock([Instabug class]); NSString *codePushVersion = @"123"; - + [self.instabugBridge setCodePushVersion:codePushVersion]; - + OCMVerify([mock setCodePushVersion:codePushVersion]); } @@ -353,8 +353,7 @@ - (void)testNetworkLogIOS { startTime:startTime duration:duration gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage - w3cExternalTraceAttributes:nil + w3cExternalTraceAttributes:nil ]; OCMVerify([mIBGNetworkLogger addNetworkLogWithUrl:url @@ -372,7 +371,6 @@ - (void)testNetworkLogIOS { startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage isW3cCaughted:nil partialID:nil timestamp:nil @@ -570,4 +568,43 @@ - (void) testIsW3CaughtHeaderEnabled { } +- (void)testAddFeatureFlags { + id mock = OCMClassMock([Instabug class]); + NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"}; + + OCMStub([mock addFeatureFlags :[OCMArg any]]); + [self.instabugBridge addFeatureFlags:featureFlagsMap]; + OCMVerify([mock addFeatureFlags: [OCMArg checkWithBlock:^(id value) { + NSArray *featureFlags = value; + NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name; + NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ; + if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ + return YES; + } + return NO; + }]]); +} + +- (void)testRemoveFeatureFlags { + id mock = OCMClassMock([Instabug class]); + NSArray *featureFlags = @[@"exp1", @"exp2"]; + [self.instabugBridge removeFeatureFlags:featureFlags]; + OCMVerify([mock removeFeatureFlags: [OCMArg checkWithBlock:^(id value) { + NSArray *featureFlagsObJ = value; + NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name; + NSString* firstFeatureFlagKey = [featureFlags firstObject] ; + if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ + return YES; + } + return NO; + }]]); +} + +- (void)testRemoveAllFeatureFlags { + id mock = OCMClassMock([Instabug class]); + OCMStub([mock removeAllFeatureFlags]); + [self.instabugBridge removeAllFeatureFlags]; + OCMVerify([mock removeAllFeatureFlags]); +} + @end diff --git a/examples/default/ios/InstabugTests/RNInstabugTests.m b/examples/default/ios/InstabugTests/RNInstabugTests.m index 70320a4cf0..930da52ca5 100644 --- a/examples/default/ios/InstabugTests/RNInstabugTests.m +++ b/examples/default/ios/InstabugTests/RNInstabugTests.m @@ -1,7 +1,6 @@ #import #import "OCMock/OCMock.h" #import "Instabug/Instabug.h" -#import "Instabug/IBGSurvey.h" #import #import "RNInstabug.h" #import "RNInstabug/Instabug+CP.h" diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile index 63c0029932..3d0c8ceedb 100644 --- a/examples/default/ios/Podfile +++ b/examples/default/ios/Podfile @@ -5,17 +5,6 @@ require_relative '../node_modules/@react-native-community/cli-platform-ios/nativ platform :ios, '13.4' prepare_react_native_project! -# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. -# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded -# -# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` -# ```js -# module.exports = { -# dependencies: { -# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), -# ``` -# flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled - linkage = ENV['USE_FRAMEWORKS'] if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green @@ -36,11 +25,6 @@ target 'InstabugExample' do # we make it explicit here to aid in the React Native upgrade process. :hermes_enabled => flags[:hermes_enabled], :fabric_enabled => flags[:fabric_enabled], - # Enables Flipper. - # - # Note that if you have use_frameworks! enabled, Flipper will not work and - # you should disable the next line. - # :flipper_configuration => flipper_config, # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index e6b560a9da..2993610539 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -475,7 +475,7 @@ PODS: - RNGestureHandler (2.13.4): - RCT-Folly (= 2021.07.22.00) - React-Core - - RNInstabug (13.2.0): + - RNInstabug (13.3.0): - Instabug - React-Core - RNReanimated (3.5.4): @@ -748,7 +748,7 @@ SPEC CHECKSUMS: ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: e515e490416a20b604e27bdbbebf5316ff3a2012 + RNInstabug: 80b369d623a473c31ff3b8b8ea1d17daaca44132 RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 @@ -756,6 +756,6 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce -PODFILE CHECKSUM: 26b8b1f0273d40b2b21568157bd5df0421935faa +PODFILE CHECKSUM: 281036e04bd4b9e7c2cc03a503b3245d3f1dd0dd -COCOAPODS: 1.12.0 +COCOAPODS: 1.15.2 diff --git a/examples/default/src/App.tsx b/examples/default/src/App.tsx index d92db633c1..33a3c34f94 100644 --- a/examples/default/src/App.tsx +++ b/examples/default/src/App.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from 'react'; import { StyleSheet } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; -import { NavigationContainer } from '@react-navigation/native'; +import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; import Instabug, { CrashReporting, InvocationEvent, @@ -20,6 +20,7 @@ import { QueryClient, QueryClientProvider } from 'react-query'; const queryClient = new QueryClient(); export const App: React.FC = () => { + const navigationRef = useNavigationContainerRef(); useEffect(() => { Instabug.init({ token: 'deb1910a7342814af4e4c9210c786f35', @@ -33,11 +34,17 @@ export const App: React.FC = () => { }); }, []); + useEffect(() => { + const unregisterListener = Instabug.setNavigationListener(navigationRef); + + return unregisterListener; + }, [navigationRef]); + return ( - + diff --git a/examples/default/src/screens/SettingsScreen.tsx b/examples/default/src/screens/SettingsScreen.tsx index 618de54a22..6390bb7a0a 100644 --- a/examples/default/src/screens/SettingsScreen.tsx +++ b/examples/default/src/screens/SettingsScreen.tsx @@ -17,8 +17,12 @@ export const SettingsScreen: React.FC = () => { const [userID, setUserID] = useState(''); const [userAttributeKey, setUserAttributeKey] = useState(''); const [userAttributeValue, setUserAttributeValue] = useState(''); + const [featureFlagName, setFeatureFlagName] = useState(''); + const [featureFlagVariant, setfeatureFlagVariant] = useState(''); + const toast = useToast(); const [userAttributesFormError, setUserAttributesFormError] = useState({}); + const [featureFlagFormError, setFeatureFlagFormError] = useState({}); const validateUserAttributeForm = () => { const errors: any = {}; @@ -31,6 +35,15 @@ export const SettingsScreen: React.FC = () => { setUserAttributesFormError(errors); return Object.keys(errors).length === 0; }; + const validateFeatureFlagForm = () => { + const errors: any = {}; + if (featureFlagName.length === 0) { + errors.featureFlagName = 'Value is required'; + } + setFeatureFlagFormError(errors); + return Object.keys(errors).length === 0; + }; + const styles = StyleSheet.create({ inputWrapper: { padding: 4, @@ -60,6 +73,37 @@ export const SettingsScreen: React.FC = () => { setUserAttributeValue(''); } }; + const saveFeatureFlags = () => { + if (validateFeatureFlagForm()) { + Instabug.addFeatureFlag({ + name: featureFlagName, + variant: featureFlagVariant, + }); + toast.show({ + description: 'Feature Flag added successfully', + }); + setFeatureFlagName(''); + setfeatureFlagVariant(''); + } + }; + const removeFeatureFlags = () => { + if (validateFeatureFlagForm()) { + Instabug.removeFeatureFlag(featureFlagName); + toast.show({ + description: 'Feature Flag removed successfully', + }); + setFeatureFlagName(''); + setfeatureFlagVariant(''); + } + }; + const removeAllFeatureFlags = () => { + Instabug.removeAllFeatureFlags(); + toast.show({ + description: 'Feature Flags removed successfully', + }); + setFeatureFlagName(''); + setfeatureFlagVariant(''); + }; const logout = () => { Instabug.logOut(); @@ -215,6 +259,38 @@ export const SettingsScreen: React.FC = () => { + + + + + setFeatureFlagName(key)} + value={featureFlagName} + errorText={featureFlagFormError.featureFlagName} + /> + + + setfeatureFlagVariant(value)} + value={featureFlagVariant} + /> + + + + + + + + + ); diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index 2a96b8bad3..195a69b1f2 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -12,7 +12,6 @@ #import #import #import -#import #import #import #import "ArgsRegistry.h" @@ -137,4 +136,7 @@ w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes; - (void)removeExperiments:(NSArray *)experiments; - (void)clearAllExperiments; +- (void)addFeatureFlags:(NSDictionary *)featureFlagsMap; +- (void)removeFeatureFlags:(NSArray *)featureFlags; +- (void)removeAllFeatureFlags; @end diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index c09d0a038b..38320913f4 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -8,7 +8,6 @@ #import #import #import -#import #import #import #import @@ -299,15 +298,15 @@ - (dispatch_queue_t)methodQueue { startTime:(double)startTime duration:(double)duration gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage + serverErrorMessage:(NSString * _Nullable)serverErrorMessage w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes){ NSNumber *isW3cCaught = (w3cExternalTraceAttributes[@"isW3cHeaderFound"] != [NSNull null]) ? w3cExternalTraceAttributes[@"isW3cHeaderFound"] : nil; NSNumber * partialID = (w3cExternalTraceAttributes[@"partialId"] != [NSNull null]) ? w3cExternalTraceAttributes[@"partialId"] : nil; NSNumber * timestamp = (w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] != [NSNull null]) ? w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] : nil; NSString * generatedW3CTraceparent = (w3cExternalTraceAttributes[@"w3cGeneratedHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cGeneratedHeader"] : nil; NSString * caughtW3CTraceparent = (w3cExternalTraceAttributes[@"w3cCaughtHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cCaughtHeader"] : nil; - - [IBGNetworkLogger addNetworkLogWithUrl:url + + [IBGNetworkLogger addNetworkLogWithUrl:url method:method requestBody:requestBody requestBodySize:requestBodySize @@ -368,6 +367,38 @@ - (dispatch_queue_t)methodQueue { [Instabug clearAllExperiments]; } +RCT_EXPORT_METHOD(addFeatureFlags:(NSDictionary *)featureFlagsMap) { + NSMutableArray *featureFlags = [NSMutableArray array]; + for(id key in featureFlagsMap){ + NSString* variant =[featureFlagsMap objectForKey:key]; + if ([variant length]==0) { + [featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key]]; + } else{ + [featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key variant:variant]]; + } + } + + [Instabug addFeatureFlags:featureFlags]; +} + +RCT_EXPORT_METHOD(removeFeatureFlags:(NSArray *)featureFlags) { + NSMutableArray *features = [NSMutableArray array]; + for(id item in featureFlags){ + [features addObject:[[IBGFeatureFlag alloc] initWithName:item]]; + } + + @try { + [Instabug removeFeatureFlags:features]; + } + @catch (NSException *exception) { + NSLog(@"%@", exception); + } +} + +RCT_EXPORT_METHOD(removeAllFeatureFlags) { + [Instabug removeAllFeatureFlags]; +} + RCT_EXPORT_METHOD(willRedirectToStore){ [Instabug willRedirectToAppStore]; } diff --git a/package.json b/package.json index cd62475f6a..d641ecad65 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "instabug-reactnative", "description": "React Native plugin for integrating the Instabug SDK", - "version": "13.2.0", + "version": "13.3.0", "author": "Instabug (https://instabug.com)", "repository": "github:Instabug/Instabug-React-Native", "homepage": "https://www.instabug.com/platforms/react-native", diff --git a/rollup.config.js b/rollup.config.js index 9b3068d89e..ae91a89060 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,19 +5,30 @@ import typescript from '@rollup/plugin-typescript'; import cleanup from 'rollup-plugin-cleanup'; import shebang from 'rollup-plugin-preserve-shebang'; +const commonPlugins = [ + shebang(), + json(), + nodeResolve({ preferBuiltins: true }), + commonjs(), + cleanup(), +]; + /** @type import('rollup').RollupOptions */ -export default { - input: ['cli/index.ts'], - output: { - dir: 'bin', - format: 'cjs', +export default [ + { + input: ['cli/index.ts'], + output: { + dir: 'bin', + format: 'cjs', + }, + plugins: [...commonPlugins, typescript({ tsconfig: './tsconfig.cli.json' })], + }, + { + input: ['cli/upload/index.ts'], + output: { + dir: 'upload', + format: 'cjs', + }, + plugins: [...commonPlugins, typescript({ tsconfig: './tsconfig.upload.json' })], }, - plugins: [ - typescript({ tsconfig: './tsconfig.cli.json' }), - shebang(), - json(), - nodeResolve({ preferBuiltins: true }), - commonjs(), - cleanup(), - ], -}; +]; diff --git a/scripts/customize-ios-endpoints.sh b/scripts/customize-ios-endpoints.sh new file mode 100755 index 0000000000..2fecd9d729 --- /dev/null +++ b/scripts/customize-ios-endpoints.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Replaces the internal Config.plist file inside the Instabug iOS SDK with the +# Instabug.plist file in the example app. +# +# This is a workaround until the iOS SDK is updated to prioritize the custom +# Instabug.plist over the internal Config.plist. + +instabug_plist=examples/default/ios/InstabugExample/Instabug.plist + +if [ ! -f $instabug_plist ]; then + echo "Instabug.plist not found" + exit 1 +fi + +for dir in examples/default/ios/Pods/Instabug/Instabug.xcframework/ios-*/ +do + echo "Replacing Config.plist in $dir" + + config_path=$dir/Instabug.framework/InstabugResources.bundle/Config.plist + + if [ ! -f $config_path ]; then + echo "Config.plist not found in $dir" + exit 1 + fi + + cp -f $instabug_plist $config_path +done diff --git a/scripts/dream-11-delete-unused-features.sh b/scripts/dream-11-delete-unused-features.sh old mode 100644 new mode 100755 index 58ab392885..fa10a9181e --- a/scripts/dream-11-delete-unused-features.sh +++ b/scripts/dream-11-delete-unused-features.sh @@ -2,47 +2,61 @@ # remove survey and featureRequest features in JavaScript files deletedFeaturesFilesInJavaScript=("Surveys" "FeatureRequests" "Survey") -for feature in "${deletedFeaturesFilesInJavaScript[@]}"; - do - echo "$feature" -rm -f src/modules/"$feature".ts -rm -f test/mocks/mock"$feature".ts -sed -i "s/import..*$feature';//g" src/index.ts -sed -i "s/$feature,//g" src/index.ts - +for feature in "${deletedFeaturesFilesInJavaScript[@]}"; do + echo "$feature" + + rm -f src/modules/"$feature".ts + rm -f src/native/Native"$feature".ts + rm -f test/mocks/mock"$feature".ts + rm -f test/modules/"$feature".spec.ts + + node scripts/replace.js --pattern "import.+$feature';" "" src/index.ts + node scripts/replace.js --pattern "$feature," "" src/index.ts + node scripts/replace.js --pattern ".*$feature.*" "" src/native/NativePackage.ts + node scripts/replace.js --pattern ".*$feature.*" "" test/mocks/mockNativeModules.ts done -npx eslint src/index.ts --fix + +npx eslint src/index.ts --fix # remove survey and featureRequest features in Android files deletedFeaturesFilesInAndroidApp=("RNInstabugSurveysModule" "RNInstabugFeatureRequestsModule") -for feature in "${deletedFeaturesFilesInAndroidApp[@]}"; - do - echo "$feature" - -rm -f android/src/main/java/com/instabug/reactlibrary/"$feature".java -rm -f android/src/test/java/com/instabug/reactlibrary/"$feature"Test.java -sed -i "s/modules.add(new $feature(reactContext));//g" android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java +for feature in "${deletedFeaturesFilesInAndroidApp[@]}"; do + echo "$feature" + rm -f android/src/main/java/com/instabug/reactlibrary/"$feature".java + rm -f android/src/test/java/com/instabug/reactlibrary/"$feature"Test.java + node scripts/replace.js "modules.add(new $feature(reactContext));" "" android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java done # remove survey and featureRequest features in IOS files deletedFeaturesFilesInIosApp=("InstabugSurveysBridge" "InstabugFeatureRequestsBridge") -for feature in "${deletedFeaturesFilesInIosApp[@]}"; - do - echo "$feature" -rm -f ios/RNInstabug/"$feature".h -rm -f ios/RNInstabug/"$feature".m +for feature in "${deletedFeaturesFilesInIosApp[@]}"; do + echo "$feature" + rm -f ios/RNInstabug/"$feature".h + rm -f ios/RNInstabug/"$feature".m done -sed -i "s/\#import //g" ios/RNInstabug/InstabugReactBridge.m -sed -i "s/\#import //g" ios/RNInstabug/InstabugReactBridge.h +# Remove unused features iOS test files +iosTestFiles=("InstabugSurveysTests.m" "InstabugFeatureRequestsTests.m") +for file in "${iosTestFiles[@]}"; do + echo "Deleting $file" + + rm -f examples/default/ios/InstabugTests/"$file" + node scripts/replace.js --pattern ".*$file.*" "" examples/default/ios/InstabugExample.xcodeproj/project.pbxproj +done -# remove all locales except English locale -sed -i -E '/english/!s/.*constants.locale.*//g' src/utils/Enums.ts -npx eslint src/index.ts --fix src/utils/Enums.ts +node scripts/replace.js "#import " "" ios/RNInstabug/InstabugReactBridge.m +node scripts/replace.js "#import " "" ios/RNInstabug/InstabugReactBridge.h -sed -i "s/return (major == 7 && minor >= 3) || major >= 8/return false/g" android/build.gradle +# Remove all locales except for English +# This ugly regular expression matches all lines not containing "english" and containing "constants.locale" +node scripts/replace.js --pattern "^(?!.*english).+constants\.locale.*" "" src/utils/Enums.ts +npx eslint src/index.ts --fix src/utils/Enums.ts -sed -i "s/static boolean supportsNamespace() {/static boolean supportsNamespace() { \n return false/g" android/build.gradle +node scripts/replace.js "return (major == 7 && minor >= 3) || major >= 8" "return false" android/build.gradle +# Note: printf is used here as the string contains a newline character which would be escaped otherwise. +node scripts/replace.js "static boolean supportsNamespace() {" "$(printf "static boolean supportsNamespace() {\n return false")" android/build.gradle +# Add Dream11 custom iOS build podspec to Podfile +node scripts/replace.js "target 'InstabugExample' do" "$(printf "target 'InstabugExample' do\n pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/dream11/Instabug.podspec'")" examples/default/ios/Podfile diff --git a/scripts/replace.js b/scripts/replace.js index 5682b47265..aeb483ae8f 100644 --- a/scripts/replace.js +++ b/scripts/replace.js @@ -10,10 +10,25 @@ const fs = require('fs'); const path = require('path'); +const { parseArgs } = require('util'); -const [search, replace, ...files] = process.argv.slice(2); +const { values, positionals } = parseArgs({ + allowPositionals: true, + options: { + pattern: { + type: 'boolean', + default: false, + short: 'p', + }, + }, +}); -if (!search || !replace || !files.length) { +const [search, replace, ...files] = positionals; + +/** Whether to replace the search string as a regular expression or as a literal string. */ +const isPattern = values.pattern; + +if (search == null || replace == null || !files.length) { // The path of the script relative to the directory where the user ran the // script to be used in the error message demonstrating the usage. const scriptPath = path.relative(process.cwd(), __filename); @@ -21,7 +36,7 @@ if (!search || !replace || !files.length) { console.error('Missing arguments.'); console.table({ search, replace, files }); - console.error(`Usage: node ${scriptPath} `); + console.error(`Usage: node ${scriptPath} [-p | --pattern] `); process.exit(1); } @@ -31,7 +46,8 @@ for (const file of files) { const fileContent = fs.readFileSync(filePath, 'utf8'); - const newContent = fileContent.replaceAll(search, replace); + const searchPattern = isPattern ? new RegExp(search, 'gm') : search; + const newContent = fileContent.replaceAll(searchPattern, replace); fs.writeFileSync(filePath, newContent); } catch (error) { diff --git a/scripts/snapshot-branch.sh b/scripts/snapshot-branch.sh deleted file mode 100755 index 652dd1bb98..0000000000 --- a/scripts/snapshot-branch.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -pr_url="https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pulls?head=$CIRCLE_PROJECT_USERNAME:$CIRCLE_BRANCH&state=open" -pr_response=$(curl --location --request GET "$pr_url" --header "Authorization: Bearer $RELEASE_GITHUB_TOKEN") - -if [ $(echo "$pr_response" | jq length) -eq 0 ]; then - echo "No PR found, proceeding with branch name instead" - - SNAPSHOT_BRANCH="snapshot/$CIRCLE_BRANCH" -else - pr_description=$(echo "$pr_response" | jq -r '.[].body') - - # The `sed "s/\r//g"` is used to remove the carriage return character \r from the end of the string - SNAPSHOT_BRANCH=$(echo -E "$pr_description" | grep 'Snapshot name:' | cut -d ':' -f 2 | xargs echo -n | sed "s/\r//g" || echo -n) - - if [ -z "$SNAPSHOT_BRANCH" ]; then - echo "No custom snapshot name found, proceeding with default snapshot naming convention" - - version=$(jq -r '.version' package.json) - jira_id=$(echo -E "$pr_description" | grep 'Jira ID:' | grep -Eo '[A-Z]+-[0-9]+' || echo -n) - - if [ -z "$jira_id" ]; then - echo "No Jira ID found, proceeding with branch name instead" - - SNAPSHOT_BRANCH="snapshot/$CIRCLE_BRANCH" - else - SNAPSHOT_BRANCH="snapshot/$version-$jira_id" - fi - fi -fi diff --git a/scripts/snapshot-comment.md b/scripts/snapshot-comment.md index 25ee16227b..6acb6d7267 100644 --- a/scripts/snapshot-comment.md +++ b/scripts/snapshot-comment.md @@ -5,11 +5,11 @@ Your snapshot has been generated! :rocket: You can install the snapshot through NPM: ```sh -npm install https://github.com/Instabug/Instabug-React-Native\#{BRANCH} +npm install instabug-reactnative@{VERSION} ``` or Yarn: ```sh -yarn add https://github.com/Instabug/Instabug-React-Native\#{BRANCH} +yarn add instabug-reactnative@{VERSION} ``` diff --git a/scripts/snapshot-version.sh b/scripts/snapshot-version.sh new file mode 100755 index 0000000000..7ba0a0fd58 --- /dev/null +++ b/scripts/snapshot-version.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Generates a snapshot version following the format {version}-{pr}{random-3-digit}-SNAPSHOT +# Example: 13.3.0-502861-SNAPSHOT + +pr=$(basename $CIRCLE_PULL_REQUEST) +random=$(($RANDOM % 900 + 100)) +version=$(jq -r '.version' package.json) +suffix="SNAPSHOT" + +SNAPSHOT_VERSION="$version-$pr$random-$suffix" diff --git a/src/models/FeatureFlag.ts b/src/models/FeatureFlag.ts new file mode 100644 index 0000000000..d2fd58e0f6 --- /dev/null +++ b/src/models/FeatureFlag.ts @@ -0,0 +1,12 @@ +export interface FeatureFlag { + /** + * the name of feature flag + */ + name: string; + + /** + * The variant of the feature flag. + * Leave it `undefined` for boolean (kill switch) feature flags. + */ + variant?: string; +} diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 0a177b296f..0cf1a2a0f7 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -1,7 +1,10 @@ import type React from 'react'; import { findNodeHandle, Platform, processColor } from 'react-native'; -import type { NavigationState as NavigationStateV5 } from '@react-navigation/native'; +import type { + NavigationContainerRefWithCurrent, + NavigationState as NavigationStateV5, +} from '@react-navigation/native'; import type { ComponentDidAppearEvent } from 'react-native-navigation'; import type { NavigationAction, NavigationState as NavigationStateV4 } from 'react-navigation'; @@ -22,6 +25,7 @@ import InstabugUtils, { stringifyIfNotString } from '../utils/InstabugUtils'; import * as NetworkLogger from './NetworkLogger'; import { captureUnhandledRejections } from '../utils/UnhandledRejectionTracking'; import type { ReproConfig } from '../models/ReproConfig'; +import type { FeatureFlag } from '../models/FeatureFlag'; let _currentScreen: string | null = null; let _lastScreen: string | null = null; @@ -535,6 +539,19 @@ export const onStateChange = (state?: NavigationStateV5) => { }, 1000); }; +/** + * Sets a listener for screen change + * @param navigationRef a refrence of a navigation container + * + */ +export const setNavigationListener = ( + navigationRef: NavigationContainerRefWithCurrent, +) => { + return navigationRef.addListener('state', () => { + onStateChange(navigationRef.getRootState()); + }); +}; + export const reportScreenChange = (screenName: string) => { NativeInstabug.reportScreenChange(screenName); }; @@ -542,6 +559,8 @@ export const reportScreenChange = (screenName: string) => { /** * Add experiments to next report. * @param experiments An array of experiments to add to the next report. + * + * @deprecated Please migrate to the new Feature Flags APIs: {@link addFeatureFlags}. */ export const addExperiments = (experiments: string[]) => { NativeInstabug.addExperiments(experiments); @@ -550,6 +569,8 @@ export const addExperiments = (experiments: string[]) => { /** * Remove experiments from next report. * @param experiments An array of experiments to remove from the next report. + * + * @deprecated Please migrate to the new Feature Flags APIs: {@link removeFeatureFlags}. */ export const removeExperiments = (experiments: string[]) => { NativeInstabug.removeExperiments(experiments); @@ -557,11 +578,53 @@ export const removeExperiments = (experiments: string[]) => { /** * Clear all experiments + * + * @deprecated Please migrate to the new Feature Flags APIs: {@link removeAllFeatureFlags}. */ export const clearAllExperiments = () => { NativeInstabug.clearAllExperiments(); }; +/** + * Add feature flags to the next report. + * @param featureFlags An array of feature flags to add to the next report. + */ +export const addFeatureFlags = (featureFlags: FeatureFlag[]) => { + const entries = featureFlags.map((item) => [item.name, item.variant || '']); + const flags = Object.fromEntries(entries); + NativeInstabug.addFeatureFlags(flags); +}; + +/** + * Add a feature flag to the to next report. + */ +export const addFeatureFlag = (featureFlag: FeatureFlag) => { + addFeatureFlags([featureFlag]); +}; + +/** + * Remove feature flags from the next report. + * @param featureFlags An array of feature flags to remove from the next report. + */ +export const removeFeatureFlags = (featureFlags: string[]) => { + NativeInstabug.removeFeatureFlags(featureFlags); +}; + +/** + * Remove a feature flag from the next report. + * @param name the name of the feature flag to remove from the next report. + */ +export const removeFeatureFlag = (name: string) => { + removeFeatureFlags([name]); +}; + +/** + * Clear all feature flags + */ +export const removeAllFeatureFlags = () => { + NativeInstabug.removeAllFeatureFlags(); +}; + /** * This API has to be call when using custom app rating prompt */ diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index c42f4af531..ef5fd2f25b 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -120,6 +120,12 @@ export interface InstabugNativeModule extends NativeModule { removeExperiments(experiments: string[]): void; clearAllExperiments(): void; + addFeatureFlags(featureFlags: Record): void; + + removeFeatureFlags(featureFlags: string[]): void; + + removeAllFeatureFlags(): void; + // Files APIs // setFileAttachment(filePath: string, fileName?: string): void; diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index d532ebe2d5..7b3cf2e695 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -54,6 +54,9 @@ const mockInstabug: InstabugNativeModule = { clearAllExperiments: jest.fn(), networkLogIOS: jest.fn(), networkLogAndroid: jest.fn(), + addFeatureFlags: jest.fn(), + removeFeatureFlags: jest.fn(), + removeAllFeatureFlags: jest.fn(), appendTagToReport: jest.fn(), appendConsoleLogToReport: jest.fn(), setUserAttributeToReport: jest.fn(), diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index aa25179573..099bc4344c 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -2,6 +2,7 @@ import '../mocks/mockInstabugUtils'; import '../mocks/mockNetworkLogger'; import { Platform, findNodeHandle, processColor } from 'react-native'; +import type { NavigationContainerRefWithCurrent } from '@react-navigation/native'; // Import the hook import { mocked } from 'jest-mock'; import waitForExpect from 'wait-for-expect'; @@ -22,6 +23,7 @@ import { } from '../../src/utils/Enums'; import InstabugUtils from '../../src/utils/InstabugUtils'; import { NativeInstabug } from '../../src/native/NativeInstabug'; +import type { FeatureFlag } from '../../src/models/FeatureFlag'; describe('Instabug Module', () => { beforeEach(() => { @@ -236,6 +238,42 @@ describe('Instabug Module', () => { await waitForExpect(() => expect(NativeInstabug.reportScreenChange).toBeCalledTimes(2)); }); + it('setNavigationListener should call the onStateChange on a screen change', async () => { + const mockedState = { routes: [{ name: 'ScreenName' }], index: 0 }; + + const mockNavigationContainerRef = { + current: null, + navigate: jest.fn(), + reset: jest.fn(), + goBack: jest.fn(), + dispatch: jest.fn(), + getRootState: () => mockedState, + canGoBack: jest.fn(), + + addListener: jest.fn((event, callback) => { + expect(event).toBe('state'); + callback(mockedState); + return jest.fn(); + }), + removeListener: jest.fn(), + } as unknown as NavigationContainerRefWithCurrent; + + const onStateChangeMock = jest.fn(); + + jest.spyOn(Instabug, 'onStateChange').mockImplementation(onStateChangeMock); + + Instabug.setNavigationListener(mockNavigationContainerRef); + + expect(mockNavigationContainerRef.addListener).toBeCalledTimes(1); + expect(mockNavigationContainerRef.addListener).toHaveBeenCalledWith( + 'state', + expect.any(Function), + ); + + expect(onStateChangeMock).toBeCalledTimes(1); + expect(onStateChangeMock).toHaveBeenCalledWith(mockNavigationContainerRef.getRootState()); + }); + it('should call the native method init', () => { const instabugConfig = { token: 'some-token', @@ -771,6 +809,57 @@ describe('Instabug Module', () => { expect(NativeInstabug.clearAllExperiments).toBeCalledTimes(1); }); + it('should call native addFeatureFlags method', () => { + const featureFlags: Array = [ + { + name: 'key1', + variant: 'variant1', + }, + { + name: 'key2', + variant: 'variant2', + }, + ]; + const expected: Record = {}; + expected.key1 = 'variant1'; + expected.key2 = 'variant2'; + + Instabug.addFeatureFlags(featureFlags); + expect(NativeInstabug.addFeatureFlags).toBeCalledTimes(1); + expect(NativeInstabug.addFeatureFlags).toBeCalledWith(expected); + }); + + it('should call native addFeatureFlag method', () => { + const featureFlag: FeatureFlag = { + name: 'key1', + variant: 'variant2', + }; + const expected: Record = {}; + expected.key1 = 'variant2'; + + Instabug.addFeatureFlag(featureFlag); + expect(NativeInstabug.addFeatureFlags).toBeCalledTimes(1); + expect(NativeInstabug.addFeatureFlags).toBeCalledWith(expected); + }); + it('should call native removeFeatureFlags method', () => { + const featureFlags = ['exp1', 'exp2']; + Instabug.removeFeatureFlags(featureFlags); + expect(NativeInstabug.removeFeatureFlags).toBeCalledTimes(1); + expect(NativeInstabug.removeFeatureFlags).toBeCalledWith(featureFlags); + }); + + it('should call native removeFeatureFlag method', () => { + const featureFlag = 'exp1'; + Instabug.removeFeatureFlag(featureFlag); + expect(NativeInstabug.removeFeatureFlags).toBeCalledTimes(1); + expect(NativeInstabug.removeFeatureFlags).toBeCalledWith([featureFlag]); + }); + + it('should call native removeAllFeatureFlags method', () => { + Instabug.removeAllFeatureFlags(); + expect(NativeInstabug.removeAllFeatureFlags).toBeCalledTimes(1); + }); + it('should call the native willRedirectToStore method', () => { Instabug.willRedirectToStore(); expect(NativeInstabug.willRedirectToStore).toBeCalledTimes(1); diff --git a/tsconfig.upload.json b/tsconfig.upload.json new file mode 100644 index 0000000000..5ade7ea9a7 --- /dev/null +++ b/tsconfig.upload.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "include": ["cli/upload/**/*"], + "exclude": [], + "compilerOptions": { + "lib": ["dom"], + "outDir": "upload", + "module": "esnext" + } +} diff --git a/upload/package.json b/upload/package.json new file mode 100644 index 0000000000..778c7ebf51 --- /dev/null +++ b/upload/package.json @@ -0,0 +1,5 @@ +{ + "main": "index.js", + "module": "index.mjs", + "types": "index.d.ts" +} From efea1a81b8bccc701bfc992db7d32749cc72dd8a Mon Sep 17 00:00:00 2001 From: Abdelhamid Nasser <38096011+abdelhamid-f-nasser@users.noreply.github.com> Date: Wed, 17 Jul 2024 19:26:49 +0530 Subject: [PATCH 064/104] feat(example): add apm screen (#1141) --- CHANGELOG.md | 43 ++----------------- examples/default/package.json | 1 - examples/default/src/App.tsx | 11 +---- .../default/src/screens/apm/APMScreen.tsx | 23 +--------- 4 files changed, 7 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e36e808d0..fccae4fc43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,5 @@ # Changelog -## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.3.0...dev) - -### Added - -- Add support for Expo Router navigation tracking ([#1270](https://github.com/Instabug/Instabug-React-Native/pull/1270)). - -## [13.3.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...v13.3.0) (August 4, 2024) - -### Added - -- Add support for Feature Flags APIs `Instabug.addFeatureFlags`, `Instabug.removeFeatureFlags` and `Instabug.clearAllFeatureFlags` ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). -- Export `uploadSourcemaps` and `uploadSoFiles` utilities in the `instabug-reactnative/upload` sub-package for usage in custom Node.js upload scripts ([#1252](https://github.com/Instabug/Instabug-React-Native/pull/1252)). - -### Changed - -- Bump Instabug Android SDK to v13.3.0 ([#1261](https://github.com/Instabug/Instabug-React-Native/pull/1261)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v13.3.0). -- Bump Instabug iOS SDK to v13.3.0 ([#1262](https://github.com/Instabug/Instabug-React-Native/pull/1262)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/13.3.0). - -### Deprecated - -- Deprecate Experiments APIs `Instabug.addExperiments`, `Instabug.removeExperiments` and `Instabug.clearAllExperiments` in favor of the new Feature Flags APIs ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). - -### Fixed - -- Fix APM network logging on Android ([#1253](https://github.com/Instabug/Instabug-React-Native/pull/1253)). -- Fix an OOM (out-of-memory) crash while saving network logs on Android ([#1244](https://github.com/Instabug/Instabug-React-Native/pull/1244)). - ## [13.2.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.1.1...v13.2.0) (July 7, 2024) ### Changed @@ -79,20 +52,8 @@ - Bump Instabug iOS SDK to v13.0.0 ([#1189](https://github.com/Instabug/Instabug-React-Native/pull/1189)). [See release notes](https://github.com/instabug/instabug-ios/releases/tag/13.0.0). - Bump Instabug Android SDK to v13.0.0 ([#1188](https://github.com/Instabug/Instabug-React-Native/pull/1188)). [See release notes](https://github.com/Instabug/android/releases/tag/v13.0.0). -<<<<<<< HEAD - -## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...v12.9.0) (April 2, 2024) - -======= - -### Deprecated - -- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). - ## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...12.9.0)(April 2, 2024) -> > > > > > > origin/dev - ### Added - Adds symbol files upload script ([#1137](https://github.com/Instabug/Instabug-React-Native/pull/1137)) @@ -103,6 +64,10 @@ - Deprecate execution traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setFlowAttribute` in favor of the new app flow APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). +### Deprecated + +- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). + ### Changed - Bump Instabug Android SDK to v12.9.0 ([#1168](https://github.com/Instabug/Instabug-React-Native/pull/1168)). [See release notes](https://github.com/Instabug/android/releases/tag/v12.9.0). diff --git a/examples/default/package.json b/examples/default/package.json index 43a500575a..529521802d 100644 --- a/examples/default/package.json +++ b/examples/default/package.json @@ -17,7 +17,6 @@ "@react-navigation/native-stack": "^6.9.12", "graphql": "^16.8.1", "graphql-request": "^6.1.0", - "axios": "^1.7.2", "instabug-reactnative": "link:../..", "instabug-reactnative-ndk": "github:https://github.com/Instabug/Instabug-React-Native-NDK", "native-base": "^3.4.28", diff --git a/examples/default/src/App.tsx b/examples/default/src/App.tsx index 33a3c34f94..d92db633c1 100644 --- a/examples/default/src/App.tsx +++ b/examples/default/src/App.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from 'react'; import { StyleSheet } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; -import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; +import { NavigationContainer } from '@react-navigation/native'; import Instabug, { CrashReporting, InvocationEvent, @@ -20,7 +20,6 @@ import { QueryClient, QueryClientProvider } from 'react-query'; const queryClient = new QueryClient(); export const App: React.FC = () => { - const navigationRef = useNavigationContainerRef(); useEffect(() => { Instabug.init({ token: 'deb1910a7342814af4e4c9210c786f35', @@ -34,17 +33,11 @@ export const App: React.FC = () => { }); }, []); - useEffect(() => { - const unregisterListener = Instabug.setNavigationListener(navigationRef); - - return unregisterListener; - }, [navigationRef]); - return ( - + diff --git a/examples/default/src/screens/apm/APMScreen.tsx b/examples/default/src/screens/apm/APMScreen.tsx index cf23e4f620..2bc4dbca0d 100644 --- a/examples/default/src/screens/apm/APMScreen.tsx +++ b/examples/default/src/screens/apm/APMScreen.tsx @@ -1,35 +1,14 @@ -import React from 'react'; import type { NativeStackScreenProps } from '@react-navigation/native-stack'; -import axios from 'axios'; - import type { HomeStackParamList } from '../../navigation/HomeStack'; +import React from 'react'; import { ListTile } from '../../components/ListTile'; import { Screen } from '../../components/Screen'; -import { NativeAPM } from '../../../../../src/native/NativeAPM'; export const APMScreen: React.FC> = ({ navigation, }) => { - const simulateNetworkRequest = () => { - axios.get('https://httpbin.org/anything', { - headers: { traceparent: 'Caught Header Example' }, - }); - }; - const simulateNetworkRequestWithoutHeader = () => { - axios.get('https://httpbin.org/anything'); - }; return ( - NativeAPM.setEnabled(true)} /> - NativeAPM.setEnabled(false)} /> - simulateNetworkRequest()} - /> - simulateNetworkRequestWithoutHeader()} - /> navigation.navigate('NetworkTraces')} /> navigation.navigate('ExecutionTraces')} /> navigation.navigate('AppFlows')} /> From fec8b0c3e6e50e48e38253b02f015f31a60f0a6a Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:58:56 +0300 Subject: [PATCH 065/104] fix(android): resolve an OOM in network logs (#1244) --- CHANGELOG.md | 6 + .../reactlibrary/RNInstabugAPMModule.java | 84 ++++-------- .../ios/InstabugTests/InstabugSampleTests.m | 123 +----------------- ios/RNInstabug/InstabugReactBridge.h | 17 +++ ios/RNInstabug/InstabugReactBridge.m | 63 +-------- ios/RNInstabug/Util/IBGNetworkLogger+CP.h | 16 +++ src/native/NativeAPM.ts | 5 - src/native/NativeInstabug.ts | 19 --- src/utils/InstabugUtils.ts | 69 ++++++++++ src/utils/XhrNetworkInterceptor.ts | 92 +------------ test/mocks/mockInstabug.ts | 7 - test/modules/NetworkLogger.spec.ts | 5 - test/utils/InstabugUtils.spec.ts | 90 ------------- 13 files changed, 148 insertions(+), 448 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fccae4fc43..7ec9aad5b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...dev) + +### Fixed + +- Fix an OOM (out-of-memory) crash while saving network logs on Android ([#1244](https://github.com/Instabug/Instabug-React-Native/pull/1244)). + ## [13.2.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.1.1...v13.2.0) (July 7, 2024) ### Changed diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index d9f72fc2ca..7ffaf4de73 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -9,15 +9,16 @@ import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableMap; import com.instabug.apm.APM; import com.instabug.apm.model.ExecutionTrace; import com.instabug.apm.networking.APMNetworkLogger; -import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; -import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; +import org.json.JSONException; +import org.json.JSONObject; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; @@ -26,7 +27,7 @@ import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; -public class RNInstabugAPMModule extends EventEmitterModule { +public class RNInstabugAPMModule extends ReactContextBaseJavaModule { public RNInstabugAPMModule(ReactApplicationContext reactApplicationContext) { super(reactApplicationContext); @@ -328,65 +329,36 @@ private void networkLogAndroid(final double requestStartTime, final double statusCode, final String responseContentType, @Nullable final String errorDomain, - @Nullable final ReadableMap w3cAttributes, @Nullable final String gqlQueryName, - @Nullable final String serverErrorMessage - ) { + @Nullable final String serverErrorMessage) { try { APMNetworkLogger networkLogger = new APMNetworkLogger(); + final boolean hasError = errorDomain != null && !errorDomain.isEmpty(); final String errorMessage = hasError ? errorDomain : null; - Boolean isW3cHeaderFound=false; - Long partialId=null; - Long networkStartTimeInSeconds=null; - - try { - if (w3cAttributes.hasKey("isW3cHeaderFound")) { - isW3cHeaderFound = w3cAttributes.getBoolean("isW3cHeaderFound"); - } - - if (w3cAttributes.hasKey("partialId")) { - partialId =(long) w3cAttributes.getDouble("partialId"); - networkStartTimeInSeconds = (long) w3cAttributes.getDouble("networkStartTimeInSeconds"); - } - - } catch (Exception e) { - e.printStackTrace(); - } - APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = - new APMCPNetworkLog.W3CExternalTraceAttributes( - isW3cHeaderFound, - partialId, - networkStartTimeInSeconds, - w3cAttributes.getString("w3cGeneratedHeader"), - w3cAttributes.getString("w3cCaughtHeader") - ); - try { - Method method = 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); + Method method = 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); if (method != null) { - method.invoke( - networkLogger, - (long) requestStartTime * 1000, - (long) requestDuration, - requestHeaders, - requestBody, - (long) requestBodySize, - requestMethod, - requestUrl, - requestContentType, - responseHeaders, - responseBody, - (long)responseBodySize, - (int) statusCode, - responseContentType, - errorMessage, - gqlQueryName, - serverErrorMessage, - w3cExternalTraceAttributes - ); - + method.invoke( + networkLogger, + requestStartTime, + requestDuration, + requestHeaders, + requestBody, + requestBodySize, + requestMethod, + requestUrl, + requestContentType, + responseHeaders, + responseBody, + responseBodySize, + statusCode, + responseContentType, + errorMessage, + gqlQueryName, + serverErrorMessage + ); } else { Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); } @@ -397,6 +369,4 @@ private void networkLogAndroid(final double requestStartTime, e.printStackTrace(); } } - - } diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index 88db2c4be9..37990b450c 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -8,6 +8,7 @@ #import #import "OCMock/OCMock.h" #import "Instabug/Instabug.h" +#import "Instabug/IBGSurvey.h" #import "InstabugReactBridge.h" #import #import "IBGConstants.h" @@ -72,7 +73,7 @@ - (void)testInit { NSArray *invocationEvents = [NSArray arrayWithObjects:[NSNumber numberWithInteger:floatingButtonInvocationEvent], nil]; BOOL useNativeNetworkInterception = YES; IBGSDKDebugLogsLevel sdkDebugLogsLevel = IBGSDKDebugLogsLevelDebug; - + OCMStub([mock setCodePushVersion:codePushVersion]); [self.instabugBridge init:appToken invocationEvents:invocationEvents debugLogsLevel:sdkDebugLogsLevel useNativeNetworkInterception:useNativeNetworkInterception codePushVersion:codePushVersion]; @@ -84,9 +85,9 @@ - (void)testInit { - (void)testSetCodePushVersion { id mock = OCMClassMock([Instabug class]); NSString *codePushVersion = @"123"; - + [self.instabugBridge setCodePushVersion:codePushVersion]; - + OCMVerify([mock setCodePushVersion:codePushVersion]); } @@ -332,12 +333,7 @@ - (void)testNetworkLogIOS { double duration = 150; NSString *gqlQueryName = nil; NSString *serverErrorMessage = nil; - NSDictionary* w3cExternalTraceAttributes = nil; - NSNumber *isW3cCaughted = nil; - NSNumber *partialID = nil; - NSNumber *timestamp= nil; - NSString *generatedW3CTraceparent= nil; - NSString *caughtedW3CTraceparent= nil; + [self.instabugBridge networkLogIOS:url method:method requestBody:requestBody @@ -353,8 +349,7 @@ - (void)testNetworkLogIOS { startTime:startTime duration:duration gqlQueryName:gqlQueryName - w3cExternalTraceAttributes:nil - ]; + serverErrorMessage:serverErrorMessage]; OCMVerify([mIBGNetworkLogger addNetworkLogWithUrl:url method:method @@ -371,13 +366,7 @@ - (void)testNetworkLogIOS { startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - isW3cCaughted:nil - partialID:nil - timestamp:nil - generatedW3CTraceparent:nil - caughtedW3CTraceparent:nil - - ]); + serverErrorMessage:serverErrorMessage]); } - (void)testSetFileAttachment { @@ -509,102 +498,4 @@ - (void)testClearAllExperiments { OCMVerify([mock clearAllExperiments]); } - -- (void) testIsW3ExternalTraceIDEnabled { - id mock = OCMClassMock([IBGNetworkLogger class]); - NSNumber *expectedValue = @(YES); - - OCMStub([mock w3ExternalTraceIDEnabled]).andReturn([expectedValue boolValue]); - - XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; - RCTPromiseResolveBlock resolve = ^(NSNumber *result) { - XCTAssertEqualObjects(result, expectedValue); - [expectation fulfill]; - }; - - [self.instabugBridge isW3ExternalTraceIDEnabled:resolve :nil]; - - [self waitForExpectationsWithTimeout:1.0 handler:nil]; - - OCMVerify([mock w3ExternalTraceIDEnabled]); -} - -- (void) testIsW3ExternalGeneratedHeaderEnabled { - id mock = OCMClassMock([IBGNetworkLogger class]); - NSNumber *expectedValue = @(YES); - - OCMStub([mock w3ExternalGeneratedHeaderEnabled]).andReturn([expectedValue boolValue]); - - XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; - RCTPromiseResolveBlock resolve = ^(NSNumber *result) { - XCTAssertEqualObjects(result, expectedValue); - [expectation fulfill]; - }; - - [self.instabugBridge isW3ExternalGeneratedHeaderEnabled:resolve :nil]; - - [self waitForExpectationsWithTimeout:1.0 handler:nil]; - - OCMVerify([mock w3ExternalGeneratedHeaderEnabled]); -} - -- (void) testIsW3CaughtHeaderEnabled { - id mock = OCMClassMock([IBGNetworkLogger class]); - NSNumber *expectedValue = @(YES); - - OCMStub([mock w3CaughtHeaderEnabled]).andReturn([expectedValue boolValue]); - - XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; - RCTPromiseResolveBlock resolve = ^(NSNumber *result) { - XCTAssertEqualObjects(result, expectedValue); - [expectation fulfill]; - }; - - [self.instabugBridge isW3CaughtHeaderEnabled:resolve :nil]; - - [self waitForExpectationsWithTimeout:1.0 handler:nil]; - - OCMVerify([mock w3CaughtHeaderEnabled]); -} - - -- (void)testAddFeatureFlags { - id mock = OCMClassMock([Instabug class]); - NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"}; - - OCMStub([mock addFeatureFlags :[OCMArg any]]); - [self.instabugBridge addFeatureFlags:featureFlagsMap]; - OCMVerify([mock addFeatureFlags: [OCMArg checkWithBlock:^(id value) { - NSArray *featureFlags = value; - NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name; - NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ; - if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ - return YES; - } - return NO; - }]]); -} - -- (void)testRemoveFeatureFlags { - id mock = OCMClassMock([Instabug class]); - NSArray *featureFlags = @[@"exp1", @"exp2"]; - [self.instabugBridge removeFeatureFlags:featureFlags]; - OCMVerify([mock removeFeatureFlags: [OCMArg checkWithBlock:^(id value) { - NSArray *featureFlagsObJ = value; - NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name; - NSString* firstFeatureFlagKey = [featureFlags firstObject] ; - if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ - return YES; - } - return NO; - }]]); -} - -- (void)testRemoveAllFeatureFlags { - id mock = OCMClassMock([Instabug class]); - OCMStub([mock removeAllFeatureFlags]); - [self.instabugBridge removeAllFeatureFlags]; - OCMVerify([mock removeAllFeatureFlags]); -} - @end diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index 195a69b1f2..a851ba25d3 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -126,6 +126,23 @@ serverErrorMessage:(NSString * _Nullable)serverErrorMessage w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes; +- (void)networkLogIOS:(NSString * _Nonnull)url + method:(NSString * _Nonnull)method + requestBody:(NSString * _Nonnull)requestBody + requestBodySize:(double)requestBodySize + responseBody:(NSString * _Nonnull)responseBody + responseBodySize:(double)responseBodySize + responseCode:(double)responseCode + requestHeaders:(NSDictionary * _Nonnull)requestHeaders + responseHeaders:(NSDictionary * _Nonnull)responseHeaders + contentType:(NSString * _Nonnull)contentType + errorDomain:(NSString * _Nullable)errorDomain + errorCode:(double)errorCode + startTime:(double)startTime + duration:(double)duration + gqlQueryName:(NSString * _Nullable)gqlQueryName + serverErrorMessage:(NSString * _Nullable)serverErrorMessage; + /* +------------------------------------------------------------------------+ | Experiments | diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index 38320913f4..2f2b24f27a 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -8,6 +8,7 @@ #import #import #import +#import #import #import #import @@ -298,14 +299,7 @@ - (dispatch_queue_t)methodQueue { startTime:(double)startTime duration:(double)duration gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage - w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes){ - NSNumber *isW3cCaught = (w3cExternalTraceAttributes[@"isW3cHeaderFound"] != [NSNull null]) ? w3cExternalTraceAttributes[@"isW3cHeaderFound"] : nil; - NSNumber * partialID = (w3cExternalTraceAttributes[@"partialId"] != [NSNull null]) ? w3cExternalTraceAttributes[@"partialId"] : nil; - NSNumber * timestamp = (w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] != [NSNull null]) ? w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] : nil; - NSString * generatedW3CTraceparent = (w3cExternalTraceAttributes[@"w3cGeneratedHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cGeneratedHeader"] : nil; - NSString * caughtW3CTraceparent = (w3cExternalTraceAttributes[@"w3cCaughtHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cCaughtHeader"] : nil; - + serverErrorMessage:(NSString * _Nullable)serverErrorMessage) { [IBGNetworkLogger addNetworkLogWithUrl:url method:method requestBody:requestBody @@ -321,14 +315,8 @@ - (dispatch_queue_t)methodQueue { startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage - isW3cCaughted:isW3cCaught - partialID:partialID - timestamp:timestamp - generatedW3CTraceparent:generatedW3CTraceparent - caughtedW3CTraceparent:caughtW3CTraceparent - ]; - } + serverErrorMessage:serverErrorMessage]; +} RCT_EXPORT_METHOD(addPrivateView: (nonnull NSNumber *)reactTag) { UIView* view = [self.bridge.uiManager viewForReactTag:reactTag]; @@ -367,53 +355,10 @@ - (dispatch_queue_t)methodQueue { [Instabug clearAllExperiments]; } -RCT_EXPORT_METHOD(addFeatureFlags:(NSDictionary *)featureFlagsMap) { - NSMutableArray *featureFlags = [NSMutableArray array]; - for(id key in featureFlagsMap){ - NSString* variant =[featureFlagsMap objectForKey:key]; - if ([variant length]==0) { - [featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key]]; - } else{ - [featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key variant:variant]]; - } - } - - [Instabug addFeatureFlags:featureFlags]; -} - -RCT_EXPORT_METHOD(removeFeatureFlags:(NSArray *)featureFlags) { - NSMutableArray *features = [NSMutableArray array]; - for(id item in featureFlags){ - [features addObject:[[IBGFeatureFlag alloc] initWithName:item]]; - } - - @try { - [Instabug removeFeatureFlags:features]; - } - @catch (NSException *exception) { - NSLog(@"%@", exception); - } -} - -RCT_EXPORT_METHOD(removeAllFeatureFlags) { - [Instabug removeAllFeatureFlags]; -} - RCT_EXPORT_METHOD(willRedirectToStore){ [Instabug willRedirectToAppStore]; } -RCT_EXPORT_METHOD(isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { - resolve(@(IBGNetworkLogger.w3ExternalTraceIDEnabled)); -} -RCT_EXPORT_METHOD(isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { - resolve(@(IBGNetworkLogger.w3ExternalGeneratedHeaderEnabled)); -} -RCT_EXPORT_METHOD(isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { - resolve(@(IBGNetworkLogger.w3CaughtHeaderEnabled)); -} - - - (NSDictionary *)constantsToExport { return ArgsRegistry.getAll; } diff --git a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h index c0bd0a75b8..9cd158a60d 100644 --- a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h +++ b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h @@ -10,6 +10,22 @@ NS_ASSUME_NONNULL_BEGIN + (void)disableAutomaticCapturingOfNetworkLogs; ++ (void)addNetworkLogWithUrl:(NSString *)url + method:(NSString *)method + requestBody:(NSString *)request + requestBodySize:(int64_t)requestBodySize + responseBody:(NSString *)response + responseBodySize:(int64_t)responseBodySize + responseCode:(int32_t)code + requestHeaders:(NSDictionary *)requestHeaders + responseHeaders:(NSDictionary *)responseHeaders + contentType:(NSString *)contentType + errorDomain:(NSString *)errorDomain + errorCode:(int32_t)errorCode + startTime:(int64_t)startTime + duration:(int64_t) duration + gqlQueryName:(NSString * _Nullable)gqlQueryName + serverErrorMessage:(NSString * _Nullable)serverErrorMessage; + (void)addNetworkLogWithUrl:(NSString *)url method:(NSString *)method diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 285fe05d09..b1981cfe37 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -1,7 +1,5 @@ import type { NativeModule } from 'react-native'; -import { NativeEventEmitter } from 'react-native'; -import type { W3cExternalTraceAttributes } from '../utils/Types'; import { NativeModules } from './NativePackage'; export interface ApmNativeModule extends NativeModule { @@ -24,7 +22,6 @@ export interface ApmNativeModule extends NativeModule { statusCode: number, responseContentType: string, errorDomain: string, - W3cExternalTraceAttributes: W3cExternalTraceAttributes, gqlQueryName?: string, serverErrorMessage?: string, ): void; @@ -51,5 +48,3 @@ export interface ApmNativeModule extends NativeModule { } export const NativeAPM = NativeModules.IBGAPM; - -export const emitter = new NativeEventEmitter(NativeAPM); diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index ef5fd2f25b..3990da4c8b 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -11,7 +11,6 @@ import type { WelcomeMessageMode, } from '../utils/Enums'; import type { NativeConstants } from './NativeConstants'; -import type { W3cExternalTraceAttributes } from '../utils/Types'; import { NativeModules } from './NativePackage'; export interface InstabugNativeModule extends NativeModule { @@ -68,7 +67,6 @@ export interface InstabugNativeModule extends NativeModule { duration: number, gqlQueryName: string | undefined, serverErrorMessage: string | undefined, - W3cExternalTraceAttributes: W3cExternalTraceAttributes, ): void; setNetworkLoggingEnabled(isEnabled: boolean): void; @@ -120,12 +118,6 @@ export interface InstabugNativeModule extends NativeModule { removeExperiments(experiments: string[]): void; clearAllExperiments(): void; - addFeatureFlags(featureFlags: Record): void; - - removeFeatureFlags(featureFlags: string[]): void; - - removeAllFeatureFlags(): void; - // Files APIs // setFileAttachment(filePath: string, fileName?: string): void; @@ -142,23 +134,12 @@ export interface InstabugNativeModule extends NativeModule { addFileAttachmentWithURLToReport(url: string, filename?: string): void; addFileAttachmentWithDataToReport(data: string, filename?: string): void; willRedirectToStore(): void; - - // W3C Feature Flags - isW3ExternalTraceIDEnabled(): Promise; - - isW3ExternalGeneratedHeaderEnabled(): Promise; - - isW3CaughtHeaderEnabled(): Promise; - - // W3C Feature Flags Listener for Android - registerW3CFlagsChangeListener(): void; } export const NativeInstabug = NativeModules.Instabug; export enum NativeEvents { PRESENDING_HANDLER = 'IBGpreSendingHandler', - ON_W3C_FLAGS_CHANGE = 'IBGOnNewW3CFlagsUpdateReceivedCallback', } export const emitter = new NativeEventEmitter(NativeInstabug); diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index d7ccd2ee44..a089b20f2e 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -244,6 +244,75 @@ export function reportNetworkLog(network: NetworkData) { } } +export function isContentTypeNotAllowed(contentType: string) { + const allowed = [ + 'application/protobuf', + 'application/json', + 'application/xml', + 'text/xml', + 'text/html', + 'text/plain', + ]; + + return allowed.every((type) => !contentType.includes(type)); +} + +export function reportNetworkLog(network: NetworkData) { + if (Platform.OS === 'android') { + const requestHeaders = JSON.stringify(network.requestHeaders); + const responseHeaders = JSON.stringify(network.responseHeaders); + + NativeInstabug.networkLogAndroid( + network.url, + network.requestBody, + network.responseBody, + network.method, + network.responseCode, + requestHeaders, + responseHeaders, + network.duration, + ); + + NativeAPM.networkLogAndroid( + network.startTime, + network.duration, + requestHeaders, + network.requestBody, + network.requestBodySize, + network.method, + network.url, + network.requestContentType, + responseHeaders, + network.responseBody, + network.responseBodySize, + network.responseCode, + network.contentType, + network.errorDomain, + network.gqlQueryName, + network.serverErrorMessage, + ); + } else { + NativeInstabug.networkLogIOS( + network.url, + network.method, + network.requestBody, + network.requestBodySize, + network.responseBody, + network.responseBodySize, + network.responseCode, + network.requestHeaders, + network.responseHeaders, + network.contentType, + network.errorDomain, + network.errorCode, + network.startTime, + network.duration, + network.gqlQueryName, + network.serverErrorMessage, + ); + } +} + export default { parseErrorStack, captureJsErrors, diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index a3aaf8bc9d..701533f15c 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -1,7 +1,5 @@ import InstabugConstants from './InstabugConstants'; -import { stringifyIfNotString, generateW3CHeader } from './InstabugUtils'; - -import { FeatureFlags } from '../utils/FeatureFlags'; +import { stringifyIfNotString } from './InstabugUtils'; export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend: number) => void; export type NetworkDataCallback = (data: NetworkData) => void; @@ -24,11 +22,6 @@ export interface NetworkData { gqlQueryName?: string; serverErrorMessage: string; requestContentType: string; - isW3cHeaderFound: boolean | null; - partialId: number | null; - networkStartTimeInSeconds: number | null; - w3cGeneratedHeader: string | null; - w3cCaughtHeader: string | null; } const XMLHttpRequest = global.XMLHttpRequest; @@ -60,85 +53,8 @@ const _reset = () => { gqlQueryName: '', serverErrorMessage: '', requestContentType: '', - isW3cHeaderFound: null, - partialId: null, - networkStartTimeInSeconds: null, - w3cGeneratedHeader: null, - w3cCaughtHeader: null, }; }; -const getFeatureFlags = async (networkData: NetworkData) => { - const [ - isW3cExternalTraceIDEnabled, - isW3cExternalGeneratedHeaderEnabled, - isW3cCaughtHeaderEnabled, - ] = await Promise.all([ - FeatureFlags.isW3ExternalTraceID(), - FeatureFlags.isW3ExternalGeneratedHeader(), - FeatureFlags.isW3CaughtHeader(), - ]); - - return injectHeaders(networkData, { - isW3cExternalTraceIDEnabled, - isW3cExternalGeneratedHeaderEnabled, - isW3cCaughtHeaderEnabled, - }); -}; - -export const injectHeaders = async ( - networkData: NetworkData, - featureFlags: { - isW3cExternalTraceIDEnabled: boolean; - isW3cExternalGeneratedHeaderEnabled: boolean; - isW3cCaughtHeaderEnabled: boolean; - }, -) => { - const { - isW3cExternalTraceIDEnabled, - isW3cExternalGeneratedHeaderEnabled, - isW3cCaughtHeaderEnabled, - } = featureFlags; - - if (!isW3cExternalTraceIDEnabled) { - return; - } - - const isHeaderFound = networkData.requestHeaders.traceparent != null; - - networkData.isW3cHeaderFound = isHeaderFound; - - const injectionMethodology = isHeaderFound - ? identifyCaughtHeader(networkData, isW3cCaughtHeaderEnabled) - : injectGeneratedData(networkData, isW3cExternalGeneratedHeaderEnabled); - return injectionMethodology; -}; - -const identifyCaughtHeader = async ( - networkData: NetworkData, - isW3cCaughtHeaderEnabled: boolean, -) => { - if (isW3cCaughtHeaderEnabled) { - networkData.w3cCaughtHeader = networkData.requestHeaders.traceparent; - return networkData.requestHeaders.traceparent; - } - return; -}; - -const injectGeneratedData = ( - networkData: NetworkData, - isW3cExternalGeneratedHeaderEnabled: boolean, -) => { - const { timestampInSeconds, partialId, w3cHeader } = generateW3CHeader(networkData.startTime); - networkData.partialId = partialId; - networkData.networkStartTimeInSeconds = timestampInSeconds; - - if (isW3cExternalGeneratedHeaderEnabled) { - networkData.w3cGeneratedHeader = w3cHeader; - return w3cHeader; - } - - return; -}; export default { setOnDoneCallback(callback: NetworkDataCallback) { @@ -174,7 +90,7 @@ export default { originalXHRSetRequestHeader.apply(this, [header, value]); }; - XMLHttpRequest.prototype.send = async function (data) { + XMLHttpRequest.prototype.send = function (data) { const cloneNetwork = JSON.parse(JSON.stringify(network)); cloneNetwork.requestBody = data ? data : ''; @@ -296,10 +212,6 @@ export default { } cloneNetwork.startTime = Date.now(); - const traceparent = await getFeatureFlags(cloneNetwork); - if (traceparent) { - this.setRequestHeader('Traceparent', traceparent); - } originalXHRSend.apply(this, [data]); }; isInterceptorEnabled = true; diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index 7b3cf2e695..c2dac12b5a 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -54,9 +54,6 @@ const mockInstabug: InstabugNativeModule = { clearAllExperiments: jest.fn(), networkLogIOS: jest.fn(), networkLogAndroid: jest.fn(), - addFeatureFlags: jest.fn(), - removeFeatureFlags: jest.fn(), - removeAllFeatureFlags: jest.fn(), appendTagToReport: jest.fn(), appendConsoleLogToReport: jest.fn(), setUserAttributeToReport: jest.fn(), @@ -69,10 +66,6 @@ const mockInstabug: InstabugNativeModule = { addFileAttachmentWithDataToReport: jest.fn(), setNetworkLoggingEnabled: jest.fn(), willRedirectToStore: jest.fn(), - isW3ExternalTraceIDEnabled: jest.fn(), - isW3ExternalGeneratedHeaderEnabled: jest.fn(), - isW3CaughtHeaderEnabled: jest.fn(), - registerW3CFlagsChangeListener: jest.fn(), }; export default mockInstabug; diff --git a/test/modules/NetworkLogger.spec.ts b/test/modules/NetworkLogger.spec.ts index be258d7403..71dd2dd778 100644 --- a/test/modules/NetworkLogger.spec.ts +++ b/test/modules/NetworkLogger.spec.ts @@ -30,11 +30,6 @@ describe('NetworkLogger Module', () => { startTime: 0, serverErrorMessage: '', requestContentType: 'application/json', - isW3cHeaderFound: null, - partialId: null, - networkStartTimeInSeconds: null, - w3cGeneratedHeader: null, - w3cCaughtHeader: null, }; beforeEach(() => { diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index 674381da8b..becfccc0e9 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -10,8 +10,6 @@ import InstabugUtils, { getStackTrace, reportNetworkLog, sendCrashReport, - generateTracePartialId, - generateW3CHeader, } from '../../src/utils/InstabugUtils'; import { NativeInstabug } from '../../src/native/NativeInstabug'; import { NativeAPM } from '../../src/native/NativeAPM'; @@ -260,11 +258,6 @@ describe('reportNetworkLog', () => { errorDomain: 'errorDomain', serverErrorMessage: 'serverErrorMessage', requestContentType: 'requestContentType', - isW3cHeaderFound: null, - partialId: null, - networkStartTimeInSeconds: null, - w3cGeneratedHeader: null, - w3cCaughtHeader: null, }; it('reportNetworkLog should send network logs to native with the correct parameters on Android', () => { @@ -303,13 +296,6 @@ describe('reportNetworkLog', () => { network.responseCode, network.contentType, network.errorDomain, - { - isW3cHeaderFound: null, - partialId: null, - networkStartTimeInSeconds: null, - w3cGeneratedHeader: null, - w3cCaughtHeader: null, - }, network.gqlQueryName, network.serverErrorMessage, ); @@ -338,82 +324,6 @@ describe('reportNetworkLog', () => { network.duration, network.gqlQueryName, network.serverErrorMessage, - { - isW3cHeaderFound: null, - partialId: null, - networkStartTimeInSeconds: null, - w3cGeneratedHeader: null, - w3cCaughtHeader: null, - }, ); }); - - it('generateTracePartialId should generate a non-zero hex string', () => { - const mockMathRandom = jest.spyOn(global.Math, 'random'); - - mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0).mockReturnValueOnce(0.5); - - const hexString = generateTracePartialId().hexStringPartialId; - - expect(hexString).not.toBe('00000000'); - - mockMathRandom.mockRestore(); - }); - - it('generateTracePartialId should return 8 chars long generated hex string', () => { - const mockMathRandom = jest.spyOn(global.Math, 'random'); - mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0.5).mockReturnValueOnce(0.5); - // const hexString = generateTracePartialId().hexStringPartialId; - const expectedPartialId = { hexStringPartialId: '7fffffff', numberPartilId: 2147483647 }; - const generatedPartialId = generateTracePartialId(); - - expect(expectedPartialId).toMatchObject(generatedPartialId); - expect(generatedPartialId.hexStringPartialId).toHaveLength(8); - - mockMathRandom.mockRestore(); - }); - - it('generateW3CHeader should return {version}-{trace-id}-{parent-id}-{trace-flag} format header', () => { - const mockMathRandom = jest.spyOn(global.Math, 'random'); - - mockMathRandom.mockReturnValueOnce(0).mockReturnValueOnce(0.5).mockReturnValueOnce(1); - - const mockedHexStringPartialId = '7fffffff'; - const mockedNumberPartialId = 2147483647; - - const date = 1716210104248; - const unixTimestamp = '664b49b8'; - const expectedHeader = { - timestampInSeconds: Math.floor(1716210104248 / 1000), - partialId: mockedNumberPartialId, - w3cHeader: `00-${unixTimestamp}${mockedHexStringPartialId}${unixTimestamp}${mockedHexStringPartialId}-4942472d${mockedHexStringPartialId}-01`, - }; - const generatedHeader = generateW3CHeader(date); - - expect(generatedHeader).toMatchObject(expectedHeader); - - mockMathRandom.mockRestore(); - }); - it('generateW3CHeader should correctly floor the timestamp', () => { - const mockMathRandom = jest.spyOn(global.Math, 'random'); - - mockMathRandom.mockReturnValueOnce(0.1).mockReturnValueOnce(0.2).mockReturnValueOnce(0.3); - - const mockedHexStringPartialId = '19999999'; - const mockedNumberPartialId = 429496729; - - const date = 1716222912145; - const unixTimestamp = '664b7bc0'; - const expectedHeader = { - timestampInSeconds: Math.floor(1716222912145 / 1000), - partialId: mockedNumberPartialId, - w3cHeader: `00-${unixTimestamp}${mockedHexStringPartialId}${unixTimestamp}${mockedHexStringPartialId}-4942472d${mockedHexStringPartialId}-01`, - }; - - const generatedHeader = generateW3CHeader(date); - - expect(generatedHeader).toMatchObject(expectedHeader); - - mockMathRandom.mockRestore(); - }); }); From cc8a2cc1a0069b0d276c27f561165e0a30e0a2b9 Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 23 Jul 2024 10:15:55 +0300 Subject: [PATCH 066/104] fix(android): APM network logging(#1253) * fix(android): add W3C External Trace Attributes placeholder * chore: add CHANGLOG * chore: add CHANGLOG * fix: remove ios sub module --- CHANGELOG.md | 1 + .../reactlibrary/RNInstabugAPMModule.java | 42 ++++++++++--------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ec9aad5b6..4221fa8a26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Fix APM network logging on Android ([#1253](https://github.com/Instabug/Instabug-React-Native/pull/1253)). - Fix an OOM (out-of-memory) crash while saving network logs on Android ([#1244](https://github.com/Instabug/Instabug-React-Native/pull/1244)). ## [13.2.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.1.1...v13.2.0) (July 7, 2024) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 7ffaf4de73..70487f8cc5 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -14,6 +14,7 @@ import com.instabug.apm.APM; import com.instabug.apm.model.ExecutionTrace; import com.instabug.apm.networking.APMNetworkLogger; +import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; import com.instabug.reactlibrary.utils.MainThreadHandler; import org.json.JSONException; @@ -338,27 +339,28 @@ private void networkLogAndroid(final double requestStartTime, final String errorMessage = hasError ? errorDomain : null; try { - Method method = 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); + Method method = 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( - networkLogger, - requestStartTime, - requestDuration, - requestHeaders, - requestBody, - requestBodySize, - requestMethod, - requestUrl, - requestContentType, - responseHeaders, - responseBody, - responseBodySize, - statusCode, - responseContentType, - errorMessage, - gqlQueryName, - serverErrorMessage - ); + method.invoke( + networkLogger, + (long) requestStartTime, + (long) requestDuration, + requestHeaders, + requestBody, + (long) requestBodySize, + requestMethod, + requestUrl, + requestContentType, + responseHeaders, + responseBody, + (long)responseBodySize, + (int) statusCode, + responseContentType, + errorMessage, + gqlQueryName, + serverErrorMessage, + null + ); } else { Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); } From da392c06213623022d209aa1f479b0964411d6e3 Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:28:42 +0300 Subject: [PATCH 067/104] feat: export upload utils (#1252) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4221fa8a26..1035a998d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...dev) +### Added + +- Export `uploadSourcemaps` and `uploadSoFiles` utilities in the `instabug-reactnative/upload` sub-package for usage in custom Node.js upload scripts ([#1252](https://github.com/Instabug/Instabug-React-Native/pull/1252)). + ### Fixed - Fix APM network logging on Android ([#1253](https://github.com/Instabug/Instabug-React-Native/pull/1253)). From 7ebfe661345beb1e88d4b1a07844d221b41aeb95 Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:50:42 +0300 Subject: [PATCH 068/104] chore(example): remove flipper (#1259) --- examples/default/ios/Podfile.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 2993610539..543a31b57a 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,12 +38,12 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.4.0) + - Instabug (13.2.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core - libevent (2.1.12) - - OCMock (3.9.4) + - OCMock (3.9.3) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -475,8 +475,8 @@ PODS: - RNGestureHandler (2.13.4): - RCT-Folly (= 2021.07.22.00) - React-Core - - RNInstabug (13.3.0): - - Instabug + - RNInstabug (13.2.0): + - Instabug (= 13.2.0) - React-Core - RNReanimated (3.5.4): - DoubleConversion @@ -704,10 +704,10 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: 183aa1e038d01ddc000f06835f46a9ea1f6c992b + Instabug: aee76898789d17c55b36c7fbaa697e443effe3b1 instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 + OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18 RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3 @@ -748,7 +748,7 @@ SPEC CHECKSUMS: ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: 80b369d623a473c31ff3b8b8ea1d17daaca44132 + RNInstabug: 6fa68cd181533f83154df2ebba000d0c47ca7ba3 RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 @@ -758,4 +758,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 281036e04bd4b9e7c2cc03a503b3245d3f1dd0dd -COCOAPODS: 1.15.2 +COCOAPODS: 1.12.0 From 5fcd6c1e4bc529f3b991d0cb9bb7243e04498107 Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:54:38 +0300 Subject: [PATCH 069/104] fix(android): pass network start time in microseconds (#1260) * fix: network timestamp in android side * fix: PR comments Co-authored-by: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> --------- Co-authored-by: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> --- .../java/com/instabug/reactlibrary/RNInstabugAPMModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 70487f8cc5..e2ff10b991 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -343,7 +343,7 @@ private void networkLogAndroid(final double requestStartTime, if (method != null) { method.invoke( networkLogger, - (long) requestStartTime, + (long) requestStartTime * 1000, (long) requestDuration, requestHeaders, requestBody, From 4ed034aa7599417b99bceb8bce13d4f06b59cd44 Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Fri, 2 Aug 2024 19:07:10 +0300 Subject: [PATCH 070/104] feat: support feature flags with variants (#1230) Jira ID: MOB-14684 --------- Co-authored-by: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> --- CHANGELOG.md | 5 + .../RNInstabugReactnativeModule.java | 108 +----------------- .../RNInstabugReactnativeModuleTest.java | 26 ----- .../ios/InstabugTests/InstabugSampleTests.m | 45 +++++++- ios/RNInstabug/InstabugReactBridge.h | 22 +--- ios/RNInstabug/InstabugReactBridge.m | 32 ++++++ src/native/NativeInstabug.ts | 6 + test/mocks/mockInstabug.ts | 3 + test/modules/Instabug.spec.ts | 56 +-------- 9 files changed, 91 insertions(+), 212 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1035a998d0..f277b26077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,13 @@ ### Added +- Add support for Feature Flags APIs `Instabug.addFeatureFlags`, `Instabug.removeFeatureFlags` and `Instabug.clearAllFeatureFlags` ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). - Export `uploadSourcemaps` and `uploadSoFiles` utilities in the `instabug-reactnative/upload` sub-package for usage in custom Node.js upload scripts ([#1252](https://github.com/Instabug/Instabug-React-Native/pull/1252)). +### Deprecated + +- Deprecate Experiments APIs `Instabug.addExperiments`, `Instabug.removeExperiments` and `Instabug.clearAllExperiments` in favor of the new Feature Flags APIs ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). + ### Fixed - Fix APM network logging on Android ([#1253](https://github.com/Instabug/Instabug-React-Native/pull/1253)). diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 000a8e054e..f936eaa12e 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -8,7 +8,6 @@ import android.util.Log; import android.view.View; -import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.facebook.react.bridge.Arguments; @@ -23,8 +22,6 @@ import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.UIManagerModule; -import com.instabug.apm.InternalAPM; -import com.instabug.apm.configuration.cp.APMFeature; import com.instabug.library.Feature; import com.instabug.library.Instabug; import com.instabug.library.InstabugColorTheme; @@ -33,10 +30,6 @@ import com.instabug.library.LogLevel; import com.instabug.library.ReproConfigurations; import com.instabug.library.core.InstabugCore; -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.featuresflags.model.IBGFeatureFlag; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; @@ -1035,7 +1028,7 @@ public void run() { } /** - * @deprecated see @link #addFeatureFlags(ReadableArray) + * @deprecated see {@link #addFeatureFlags(ReadableArray)} */ @ReactMethod public void addExperiments(final ReadableArray experiments) { @@ -1155,105 +1148,6 @@ public void run() { } }); } - /** - * Register a listener for W3C flags value change - */ - @ReactMethod - public void registerW3CFlagsChangeListener(){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - InternalCore.INSTANCE._setFeaturesStateListener(new FeaturesStateListener() { - @Override - public void invoke(@NonNull CoreFeaturesState featuresState) { - WritableMap params = Arguments.createMap(); - params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled()); - params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled()); - params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled()); - - sendEvent(Constants.IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); - } - }); - } - catch (Exception e) { - e.printStackTrace(); - } - - } - - }); - } - - - /** - * Get first time Value of W3ExternalTraceID flag - */ - @ReactMethod - public void isW3ExternalTraceIDEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID)); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } - - - /** - * Get first time Value of W3ExternalGeneratedHeader flag - */ - @ReactMethod - public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER)); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } - - /** - * Get first time Value of W3CaughtHeader flag - */ - @ReactMethod - public void isW3CaughtHeaderEnabled(Promise promise){ - - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER)); - } - catch (Exception e) { - e.printStackTrace(); - promise.resolve(null); - } - - } - - }); - } - /** * Map between the exported JS constant and the arg key in {@link ArgsRegistry}. diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java index d1349f431b..b9bf2308cc 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java @@ -18,8 +18,6 @@ import com.instabug.library.IssueType; import com.instabug.library.ReproConfigurations; import com.instabug.library.ReproMode; -import com.instabug.library.internal.crossplatform.CoreFeature; -import com.instabug.library.internal.crossplatform.InternalCore; import com.instabug.library.featuresflags.model.IBGFeatureFlag; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.ui.onboarding.WelcomeMessage; @@ -637,28 +635,4 @@ public void testWillRedirectToStore() { // then mockInstabug.verify(() -> Instabug.willRedirectToStore()); } - @Test - public void testW3CExternalTraceIDFlag(){ - Promise promise = mock(Promise.class); - InternalCore internalAPM = mock(InternalCore.class); - rnModule.isW3ExternalTraceIDEnabled(promise); - boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID); - verify(promise).resolve(expected); - } - @Test - public void testW3CExternalGeneratedHeaderFlag(){ - Promise promise = mock(Promise.class); - InternalCore internalAPM = mock(InternalCore.class); - rnModule.isW3ExternalGeneratedHeaderEnabled(promise); - boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER); - verify(promise).resolve(expected); - } - @Test - public void testW3CCaughtHeaderFlag(){ - Promise promise = mock(Promise.class); - InternalCore internalAPM = mock(InternalCore.class); - rnModule.isW3CaughtHeaderEnabled(promise); - boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER); - verify(promise).resolve(expected); - } } diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index 37990b450c..565a21b1a7 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -73,7 +73,7 @@ - (void)testInit { NSArray *invocationEvents = [NSArray arrayWithObjects:[NSNumber numberWithInteger:floatingButtonInvocationEvent], nil]; BOOL useNativeNetworkInterception = YES; IBGSDKDebugLogsLevel sdkDebugLogsLevel = IBGSDKDebugLogsLevelDebug; - + OCMStub([mock setCodePushVersion:codePushVersion]); [self.instabugBridge init:appToken invocationEvents:invocationEvents debugLogsLevel:sdkDebugLogsLevel useNativeNetworkInterception:useNativeNetworkInterception codePushVersion:codePushVersion]; @@ -85,9 +85,9 @@ - (void)testInit { - (void)testSetCodePushVersion { id mock = OCMClassMock([Instabug class]); NSString *codePushVersion = @"123"; - + [self.instabugBridge setCodePushVersion:codePushVersion]; - + OCMVerify([mock setCodePushVersion:codePushVersion]); } @@ -498,4 +498,43 @@ - (void)testClearAllExperiments { OCMVerify([mock clearAllExperiments]); } +- (void)testAddFeatureFlags { + id mock = OCMClassMock([Instabug class]); + NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"}; + + OCMStub([mock addFeatureFlags :[OCMArg any]]); + [self.instabugBridge addFeatureFlags:featureFlagsMap]; + OCMVerify([mock addFeatureFlags: [OCMArg checkWithBlock:^(id value) { + NSArray *featureFlags = value; + NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name; + NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ; + if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ + return YES; + } + return NO; + }]]); +} + +- (void)testRemoveFeatureFlags { + id mock = OCMClassMock([Instabug class]); + NSArray *featureFlags = @[@"exp1", @"exp2"]; + [self.instabugBridge removeFeatureFlags:featureFlags]; + OCMVerify([mock removeFeatureFlags: [OCMArg checkWithBlock:^(id value) { + NSArray *featureFlagsObJ = value; + NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name; + NSString* firstFeatureFlagKey = [featureFlags firstObject] ; + if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ + return YES; + } + return NO; + }]]); +} + +- (void)testRemoveAllFeatureFlags { + id mock = OCMClassMock([Instabug class]); + OCMStub([mock removeAllFeatureFlags]); + [self.instabugBridge removeAllFeatureFlags]; + OCMVerify([mock removeAllFeatureFlags]); +} + @end diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index a851ba25d3..c2accc9955 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -12,6 +12,7 @@ #import #import #import +#import #import #import #import "ArgsRegistry.h" @@ -105,26 +106,6 @@ */ - (void)setNetworkLoggingEnabled:(BOOL)isEnabled; -- (void)isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; -- (void)isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; -- (void)isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; -- (void)networkLogIOS:(NSString * _Nonnull)url - method:(NSString * _Nonnull)method - requestBody:(NSString * _Nonnull)requestBody - requestBodySize:(double)requestBodySize - responseBody:(NSString * _Nonnull)responseBody - responseBodySize:(double)responseBodySize - responseCode:(double)responseCode - requestHeaders:(NSDictionary * _Nonnull)requestHeaders - responseHeaders:(NSDictionary * _Nonnull)responseHeaders - contentType:(NSString * _Nonnull)contentType - errorDomain:(NSString * _Nullable)errorDomain - errorCode:(double)errorCode - startTime:(double)startTime - duration:(double)duration - gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage -w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes; - (void)networkLogIOS:(NSString * _Nonnull)url method:(NSString * _Nonnull)method @@ -152,7 +133,6 @@ w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes; - (void)addExperiments:(NSArray *)experiments; - (void)removeExperiments:(NSArray *)experiments; - (void)clearAllExperiments; - - (void)addFeatureFlags:(NSDictionary *)featureFlagsMap; - (void)removeFeatureFlags:(NSArray *)featureFlags; - (void)removeAllFeatureFlags; diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index 2f2b24f27a..a6f56109c2 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -355,6 +355,38 @@ - (dispatch_queue_t)methodQueue { [Instabug clearAllExperiments]; } +RCT_EXPORT_METHOD(addFeatureFlags:(NSDictionary *)featureFlagsMap) { + NSMutableArray *featureFlags = [NSMutableArray array]; + for(id key in featureFlagsMap){ + NSString* variant =[featureFlagsMap objectForKey:key]; + if ([variant length]==0) { + [featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key]]; + } else{ + [featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key variant:variant]]; + } + } + + [Instabug addFeatureFlags:featureFlags]; +} + +RCT_EXPORT_METHOD(removeFeatureFlags:(NSArray *)featureFlags) { + NSMutableArray *features = [NSMutableArray array]; + for(id item in featureFlags){ + [features addObject:[[IBGFeatureFlag alloc] initWithName:item]]; + } + + @try { + [Instabug removeFeatureFlags:features]; + } + @catch (NSException *exception) { + NSLog(@"%@", exception); + } +} + +RCT_EXPORT_METHOD(removeAllFeatureFlags) { + [Instabug removeAllFeatureFlags]; +} + RCT_EXPORT_METHOD(willRedirectToStore){ [Instabug willRedirectToAppStore]; } diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 3990da4c8b..3b72f5951f 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -118,6 +118,12 @@ export interface InstabugNativeModule extends NativeModule { removeExperiments(experiments: string[]): void; clearAllExperiments(): void; + addFeatureFlags(featureFlags: Record): void; + + removeFeatureFlags(featureFlags: string[]): void; + + removeAllFeatureFlags(): void; + // Files APIs // setFileAttachment(filePath: string, fileName?: string): void; diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index c2dac12b5a..5139afcde3 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -54,6 +54,9 @@ const mockInstabug: InstabugNativeModule = { clearAllExperiments: jest.fn(), networkLogIOS: jest.fn(), networkLogAndroid: jest.fn(), + addFeatureFlags: jest.fn(), + removeFeatureFlags: jest.fn(), + removeAllFeatureFlags: jest.fn(), appendTagToReport: jest.fn(), appendConsoleLogToReport: jest.fn(), setUserAttributeToReport: jest.fn(), diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index 099bc4344c..fdbdcae64e 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -2,7 +2,6 @@ import '../mocks/mockInstabugUtils'; import '../mocks/mockNetworkLogger'; import { Platform, findNodeHandle, processColor } from 'react-native'; -import type { NavigationContainerRefWithCurrent } from '@react-navigation/native'; // Import the hook import { mocked } from 'jest-mock'; import waitForExpect from 'wait-for-expect'; @@ -10,7 +9,7 @@ import waitForExpect from 'wait-for-expect'; import Report from '../../src/models/Report'; import * as Instabug from '../../src/modules/Instabug'; import * as NetworkLogger from '../../src/modules/NetworkLogger'; -import { NativeEvents, emitter } from '../../src/native/NativeInstabug'; +import { NativeEvents, NativeInstabug, emitter } from '../../src/native/NativeInstabug'; import { ColorTheme, InvocationEvent, @@ -22,7 +21,6 @@ import { WelcomeMessageMode, } from '../../src/utils/Enums'; import InstabugUtils from '../../src/utils/InstabugUtils'; -import { NativeInstabug } from '../../src/native/NativeInstabug'; import type { FeatureFlag } from '../../src/models/FeatureFlag'; describe('Instabug Module', () => { @@ -238,42 +236,6 @@ describe('Instabug Module', () => { await waitForExpect(() => expect(NativeInstabug.reportScreenChange).toBeCalledTimes(2)); }); - it('setNavigationListener should call the onStateChange on a screen change', async () => { - const mockedState = { routes: [{ name: 'ScreenName' }], index: 0 }; - - const mockNavigationContainerRef = { - current: null, - navigate: jest.fn(), - reset: jest.fn(), - goBack: jest.fn(), - dispatch: jest.fn(), - getRootState: () => mockedState, - canGoBack: jest.fn(), - - addListener: jest.fn((event, callback) => { - expect(event).toBe('state'); - callback(mockedState); - return jest.fn(); - }), - removeListener: jest.fn(), - } as unknown as NavigationContainerRefWithCurrent; - - const onStateChangeMock = jest.fn(); - - jest.spyOn(Instabug, 'onStateChange').mockImplementation(onStateChangeMock); - - Instabug.setNavigationListener(mockNavigationContainerRef); - - expect(mockNavigationContainerRef.addListener).toBeCalledTimes(1); - expect(mockNavigationContainerRef.addListener).toHaveBeenCalledWith( - 'state', - expect.any(Function), - ); - - expect(onStateChangeMock).toBeCalledTimes(1); - expect(onStateChangeMock).toHaveBeenCalledWith(mockNavigationContainerRef.getRootState()); - }); - it('should call the native method init', () => { const instabugConfig = { token: 'some-token', @@ -864,20 +826,4 @@ describe('Instabug Module', () => { Instabug.willRedirectToStore(); expect(NativeInstabug.willRedirectToStore).toBeCalledTimes(1); }); - - it('should register W3C flag listener', async () => { - const callback = jest.fn(); - Instabug._registerW3CFlagsChangeListener(callback); - - expect(NativeInstabug.registerW3CFlagsChangeListener).toBeCalledTimes(1); - }); - - it('should invoke callback on emitting the event IBGOnNewW3CFlagsUpdateReceivedCallback', () => { - const callback = jest.fn(); - Instabug._registerW3CFlagsChangeListener(callback); - emitter.emit(NativeEvents.ON_W3C_FLAGS_CHANGE); - - expect(emitter.listenerCount(NativeEvents.ON_W3C_FLAGS_CHANGE)).toBe(1); - expect(callback).toHaveBeenCalled(); - }); }); From 4fde2fd67039d959d0f0af815e6c9f00211b63d8 Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Sun, 4 Aug 2024 15:29:53 +0300 Subject: [PATCH 071/104] chore(android): bump android sdk to v13.3.0 (#1261) --- CHANGELOG.md | 4 ++++ android/native.gradle | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f277b26077..21e5ecaea5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Add support for Feature Flags APIs `Instabug.addFeatureFlags`, `Instabug.removeFeatureFlags` and `Instabug.clearAllFeatureFlags` ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). - Export `uploadSourcemaps` and `uploadSoFiles` utilities in the `instabug-reactnative/upload` sub-package for usage in custom Node.js upload scripts ([#1252](https://github.com/Instabug/Instabug-React-Native/pull/1252)). +### Changed + +- Bump Instabug Android SDK to v13.3.0 ([#1261](https://github.com/Instabug/Instabug-React-Native/pull/1261)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v13.3.0). + ### Deprecated - Deprecate Experiments APIs `Instabug.addExperiments`, `Instabug.removeExperiments` and `Instabug.clearAllExperiments` in favor of the new Feature Flags APIs ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)). diff --git a/android/native.gradle b/android/native.gradle index 39034d6035..0e86a4edff 100644 --- a/android/native.gradle +++ b/android/native.gradle @@ -1,5 +1,5 @@ project.ext.instabug = [ - version: '13.4.0' + version: '13.3.0' ] dependencies { From e200d6ee7dc0edfa5f30407fc099dacf74283daa Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Sun, 4 Aug 2024 15:31:14 +0300 Subject: [PATCH 072/104] chore(ios): bump sdk to v13.3.0 (#1262) --- CHANGELOG.md | 1 + examples/default/ios/Podfile.lock | 8 ++++---- ios/native.rb | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21e5ecaea5..7301cb18fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Changed - Bump Instabug Android SDK to v13.3.0 ([#1261](https://github.com/Instabug/Instabug-React-Native/pull/1261)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v13.3.0). +- Bump Instabug iOS SDK to v13.3.0 ([#1262](https://github.com/Instabug/Instabug-React-Native/pull/1262)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/13.3.0). ### Deprecated diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 543a31b57a..d84aab147f 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,7 +38,7 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.2.0) + - Instabug (13.3.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core @@ -476,7 +476,7 @@ PODS: - RCT-Folly (= 2021.07.22.00) - React-Core - RNInstabug (13.2.0): - - Instabug (= 13.2.0) + - Instabug (= 13.3.0) - React-Core - RNReanimated (3.5.4): - DoubleConversion @@ -704,7 +704,7 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: aee76898789d17c55b36c7fbaa697e443effe3b1 + Instabug: 4f26295103a330ec0236918359eef7ccaa74e2fa instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 @@ -748,7 +748,7 @@ SPEC CHECKSUMS: ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: 6fa68cd181533f83154df2ebba000d0c47ca7ba3 + RNInstabug: 2fbe75c9903c0a7d070d6d6a9b5c2a389f0b6862 RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 diff --git a/ios/native.rb b/ios/native.rb index c46209b912..c5188a3a73 100644 --- a/ios/native.rb +++ b/ios/native.rb @@ -1,4 +1,4 @@ -$instabug = { :version => '13.4.0' } +$instabug = { :version => '13.3.0' } def use_instabug! (spec = nil) version = $instabug[:version] From 3a15d98a56c938ea673abe46ad209b07606348df Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Sun, 4 Aug 2024 15:56:00 +0300 Subject: [PATCH 073/104] release: v13.3.0 (#1263) --- CHANGELOG.md | 2 +- examples/default/ios/Podfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7301cb18fc..026fafd2e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...dev) +## [13.3.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...v13.3.0) (August 4, 2024) ### Added diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index d84aab147f..1da6e558ee 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -475,7 +475,7 @@ PODS: - RNGestureHandler (2.13.4): - RCT-Folly (= 2021.07.22.00) - React-Core - - RNInstabug (13.2.0): + - RNInstabug (13.3.0): - Instabug (= 13.3.0) - React-Core - RNReanimated (3.5.4): @@ -748,7 +748,7 @@ SPEC CHECKSUMS: ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: 2fbe75c9903c0a7d070d6d6a9b5c2a389f0b6862 + RNInstabug: a4ac0bd09123f6be7d58be541dc220acbaff8dc3 RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 From f8f76eeb6aca30eb0dcfab50ad4a4c832614708f Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Sun, 4 Aug 2024 16:10:45 +0300 Subject: [PATCH 074/104] chore: remove duplicate app flows entries in changelog (#1264) --- CHANGELOG.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 026fafd2e1..96695f29c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,21 +73,16 @@ - Bump Instabug iOS SDK to v13.0.0 ([#1189](https://github.com/Instabug/Instabug-React-Native/pull/1189)). [See release notes](https://github.com/instabug/instabug-ios/releases/tag/13.0.0). - Bump Instabug Android SDK to v13.0.0 ([#1188](https://github.com/Instabug/Instabug-React-Native/pull/1188)). [See release notes](https://github.com/Instabug/android/releases/tag/v13.0.0). +### Deprecated + +- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). + ## [12.9.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.8.0...12.9.0)(April 2, 2024) ### Added - Adds symbol files upload script ([#1137](https://github.com/Instabug/Instabug-React-Native/pull/1137)) - Support enabling NDK crash capturing on Android ([#1132](https://github.com/Instabug/Instabug-React-Native/pull/1132)). -- Add support for App Flows APIs `APM.startFlow`, `APM.setFlowAttribute` and `APM.endFlow` ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). - -### Deprecated - -- Deprecate execution traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setFlowAttribute` in favor of the new app flow APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). - -### Deprecated - -- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). ### Changed From a76874dd1716e35e4af0b5e2190e7d1b2f75ed53 Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Sun, 4 Aug 2024 16:22:29 +0300 Subject: [PATCH 075/104] chore: remove duplicate execution traces deprecation in changelog (#1265) --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96695f29c0..9400332650 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,10 +105,6 @@ - Bump Instabug Android SDK to v12.8.0 ([#1149](https://github.com/Instabug/Instabug-React-Native/pull/1149)). [See release notes](https://github.com/Instabug/android/releases/tag/v12.8.0). -### Deprecated - -- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). - ## [12.7.1](https://github.com/Instabug/Instabug-React-Native/compare/v12.7.0...v12.7.1) (February 15, 2024) ### Changed From 6d4991f8023dc574fbcd213c2aa4b335b88af119 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 12 Aug 2024 14:10:34 +0300 Subject: [PATCH 076/104] feat: navigation tracking support with expo router (#1270) * feat: add screen tracker on screen change listener and tests * feat (example): add screen change listener --- examples/default/src/App.tsx | 9 +++++++-- src/modules/Instabug.ts | 26 +++----------------------- test/modules/Instabug.spec.ts | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/examples/default/src/App.tsx b/examples/default/src/App.tsx index d92db633c1..ae548f97c5 100644 --- a/examples/default/src/App.tsx +++ b/examples/default/src/App.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from 'react'; import { StyleSheet } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; -import { NavigationContainer } from '@react-navigation/native'; +import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; import Instabug, { CrashReporting, InvocationEvent, @@ -20,6 +20,7 @@ import { QueryClient, QueryClientProvider } from 'react-query'; const queryClient = new QueryClient(); export const App: React.FC = () => { + const navigationRef = useNavigationContainerRef(); useEffect(() => { Instabug.init({ token: 'deb1910a7342814af4e4c9210c786f35', @@ -33,11 +34,15 @@ export const App: React.FC = () => { }); }, []); + useEffect(() => { + Instabug.setNavigationListener(navigationRef); + }, [navigationRef]); + return ( - + diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 0cf1a2a0f7..b0a05032c4 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -1,5 +1,5 @@ import type React from 'react'; -import { findNodeHandle, Platform, processColor } from 'react-native'; +import { Platform, findNodeHandle, processColor } from 'react-native'; import type { NavigationContainerRefWithCurrent, @@ -10,8 +10,7 @@ import type { NavigationAction, NavigationState as NavigationStateV4 } from 'rea import type { InstabugConfig } from '../models/InstabugConfig'; import Report from '../models/Report'; -import { emitter, NativeEvents, NativeInstabug } from '../native/NativeInstabug'; -import { registerW3CFlagsListener } from '../utils/FeatureFlags'; +import { NativeEvents, NativeInstabug, emitter } from '../native/NativeInstabug'; import { ColorTheme, Locale, @@ -68,8 +67,6 @@ export const init = (config: InstabugConfig) => { InstabugUtils.captureJsErrors(); captureUnhandledRejections(); - Platform.OS === 'android' && registerW3CFlagsListener(); - // Default networkInterceptionMode to JavaScript if (config.networkInterceptionMode == null) { config.networkInterceptionMode = NetworkInterceptionMode.javascript; @@ -547,7 +544,7 @@ export const onStateChange = (state?: NavigationStateV5) => { export const setNavigationListener = ( navigationRef: NavigationContainerRefWithCurrent, ) => { - return navigationRef.addListener('state', () => { + navigationRef.addListener('state', () => { onStateChange(navigationRef.getRootState()); }); }; @@ -643,20 +640,3 @@ export const componentDidAppearListener = (event: ComponentDidAppearEvent) => { _lastScreen = event.componentName; } }; - -/** - * Sets listener to W3ExternalTraceID flag changes - * @param handler A callback that gets the update value of the flag - */ -export const _registerW3CFlagsChangeListener = ( - handler: (payload: { - isW3ExternalTraceIDEnabled: boolean; - isW3ExternalGeneratedHeaderEnabled: boolean; - isW3CaughtHeaderEnabled: boolean; - }) => void, -) => { - emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANGE, (payload) => { - handler(payload); - }); - NativeInstabug.registerW3CFlagsChangeListener(); -}; diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index fdbdcae64e..518e53ce93 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -2,6 +2,7 @@ import '../mocks/mockInstabugUtils'; import '../mocks/mockNetworkLogger'; import { Platform, findNodeHandle, processColor } from 'react-native'; +import type { NavigationContainerRefWithCurrent } from '@react-navigation/native'; // Import the hook import { mocked } from 'jest-mock'; import waitForExpect from 'wait-for-expect'; @@ -236,6 +237,23 @@ describe('Instabug Module', () => { await waitForExpect(() => expect(NativeInstabug.reportScreenChange).toBeCalledTimes(2)); }); + it('setNavigationListener should call the onStateChange on a screen change', async () => { + const mockNavigationContainerRef = { + current: null, + navigate: jest.fn(), + reset: jest.fn(), + goBack: jest.fn(), + dispatch: jest.fn(), + getRootState: jest.fn(), + canGoBack: jest.fn(), + addListener: jest.fn(), + removeListener: jest.fn(), + } as unknown as NavigationContainerRefWithCurrent; + + Instabug.setNavigationListener(mockNavigationContainerRef); + expect(mockNavigationContainerRef.addListener).toBeCalledTimes(1); + }); + it('should call the native method init', () => { const instabugConfig = { token: 'some-token', From 79088f37f7a9dad58f1363ac681dca4872e64ded Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 13 Aug 2024 17:37:27 +0300 Subject: [PATCH 077/104] chore: enhance expo router tracking support (#1272) --- CHANGELOG.md | 6 ++++++ examples/default/src/App.tsx | 4 +++- src/modules/Instabug.ts | 2 +- test/modules/Instabug.spec.ts | 23 +++++++++++++++++++++-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9400332650..acb003486f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v13.3.0...dev) + +### Added + +- Add support for Expo Router navigation tracking ([#1270](https://github.com/Instabug/Instabug-React-Native/pull/1270)). + ## [13.3.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...v13.3.0) (August 4, 2024) ### Added diff --git a/examples/default/src/App.tsx b/examples/default/src/App.tsx index ae548f97c5..33a3c34f94 100644 --- a/examples/default/src/App.tsx +++ b/examples/default/src/App.tsx @@ -35,7 +35,9 @@ export const App: React.FC = () => { }, []); useEffect(() => { - Instabug.setNavigationListener(navigationRef); + const unregisterListener = Instabug.setNavigationListener(navigationRef); + + return unregisterListener; }, [navigationRef]); return ( diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index b0a05032c4..29ff1d27c9 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -544,7 +544,7 @@ export const onStateChange = (state?: NavigationStateV5) => { export const setNavigationListener = ( navigationRef: NavigationContainerRefWithCurrent, ) => { - navigationRef.addListener('state', () => { + return navigationRef.addListener('state', () => { onStateChange(navigationRef.getRootState()); }); }; diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index 518e53ce93..fdc1b91b24 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -238,20 +238,39 @@ describe('Instabug Module', () => { }); it('setNavigationListener should call the onStateChange on a screen change', async () => { + const mockedState = { routes: [{ name: 'ScreenName' }], index: 0 }; + const mockNavigationContainerRef = { current: null, navigate: jest.fn(), reset: jest.fn(), goBack: jest.fn(), dispatch: jest.fn(), - getRootState: jest.fn(), + getRootState: () => mockedState, canGoBack: jest.fn(), - addListener: jest.fn(), + + addListener: jest.fn((event, callback) => { + expect(event).toBe('state'); + callback(mockedState); + return jest.fn(); + }), removeListener: jest.fn(), } as unknown as NavigationContainerRefWithCurrent; + const onStateChangeMock = jest.fn(); + + jest.spyOn(Instabug, 'onStateChange').mockImplementation(onStateChangeMock); + Instabug.setNavigationListener(mockNavigationContainerRef); + expect(mockNavigationContainerRef.addListener).toBeCalledTimes(1); + expect(mockNavigationContainerRef.addListener).toHaveBeenCalledWith( + 'state', + expect.any(Function), + ); + + expect(onStateChangeMock).toBeCalledTimes(1); + expect(onStateChangeMock).toHaveBeenCalledWith(mockNavigationContainerRef.getRootState()); }); it('should call the native method init', () => { From daa78bbe3b655c93f6e3fcb99b337ee8c3fa6d8b Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:38:04 +0300 Subject: [PATCH 078/104] ci: generalize enterprise releases (#1275) --- .circleci/config.yml | 186 ++++++++++++------------------------------- 1 file changed, 50 insertions(+), 136 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index efca5acab3..64a6b4013a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,12 +17,6 @@ references: - e2e_ios - e2e_android - dream11_prepare_config: &dream11_prepare_config - prepare_steps: - - prepare_dream11 - requires: - - hold_test_dream11 - commands: install_node_modules: parameters: @@ -42,28 +36,15 @@ commands: parameters: working_directory: type: string - deployment: - type: boolean - default: false steps: - restore_cache: name: Restore Pods Cache keys: - v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} - - when: - condition: << parameters.deployment >> - steps: - - run: - name: Install Pods - working_directory: << parameters.working_directory >> - command: pod install --deployment - - unless: - condition: << parameters.deployment >> - steps: - - run: - name: Install Pods - working_directory: << parameters.working_directory >> - command: pod install + - run: + name: Install Pods + working_directory: << parameters.working_directory >> + command: pod install --deployment - save_cache: name: Save Pods Cache key: v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} @@ -139,11 +120,6 @@ commands: name: Remove unused features command: ./scripts/dream-11-delete-unused-features.sh working_directory: << parameters.working_directory >> - # Remove the NDK package to avoid dependency conflicts on Android. - - run: - name: Remove the NDK package - command: yarn remove instabug-reactnative-ndk - working_directory: << parameters.working_directory >>/examples/default notify_github: parameters: @@ -182,38 +158,20 @@ jobs: command: yarn lint:ci test_module: - parameters: - prepare_steps: - type: steps - default: [] - collect_coverage: - type: boolean - default: false executor: name: node/default steps: - advanced-checkout/shallow-checkout - - steps: << parameters.prepare_steps >> - install_node_modules - run: name: Run Tests command: yarn test - - when: - condition: << parameters.collect_coverage >> - steps: - - persist_to_workspace: - root: coverage - paths: - - lcov.info + - persist_to_workspace: + root: coverage + paths: + - lcov.info test_android: - parameters: - prepare_steps: - type: steps - default: [] - collect_coverage: - type: boolean - default: false executor: name: android/android-machine tag: '2024.01.1' @@ -222,18 +180,15 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - - steps: << parameters.prepare_steps >> + # - node/install-yarn - install_node_modules - android/run-tests: working-directory: android test-command: ./gradlew test - - when: - condition: << parameters.collect_coverage >> - steps: - - persist_to_workspace: - root: ~/project/android/build/reports/jacoco/jacocoTestReport - paths: - - jacocoTestReport.xml + - persist_to_workspace: + root: ~/project/android/build/reports/jacoco/jacocoTestReport + paths: + - jacocoTestReport.xml validate_shell_files: machine: @@ -262,18 +217,10 @@ jobs: app-dir: examples/default - install_pods: working_directory: examples/default/ios - deployment: true - run: git --no-pager diff - run: git diff-index HEAD --exit-code -p -I EXCLUDED_ARCHS # Ignore Arch Changes test_ios: - parameters: - prepare_steps: - type: steps - default: [] - collect_coverage: - type: boolean - default: false macos: xcode: 13.4.1 resource_class: macos.m1.medium.gen1 @@ -282,7 +229,6 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - - steps: << parameters.prepare_steps >> - install_node_modules - install_pods: working_directory: ios @@ -297,23 +243,16 @@ jobs: -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 13 Pro Max,OS=15.5' \ test | xcpretty - - when: - condition: << parameters.collect_coverage >> - steps: - - run: - name: Convert xcresult into JSON report - working_directory: ios/coverage - command: xcrun xccov view --report --json result.xcresult > xcode.json - - persist_to_workspace: - root: ios/coverage - paths: - - xcode.json + - run: + name: Convert xcresult into JSON report + working_directory: ios/coverage + command: xcrun xccov view --report --json result.xcresult > xcode.json + - persist_to_workspace: + root: ios/coverage + paths: + - xcode.json e2e_ios: - parameters: - prepare_steps: - type: steps - default: [] macos: xcode: 13.4.1 resource_class: macos.m1.medium.gen1 @@ -321,7 +260,6 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - - steps: << parameters.prepare_steps >> - install_node_modules - node/install-packages: pkg-manager: yarn @@ -338,11 +276,6 @@ jobs: name: Rebuild Detox.framework Cache working_directory: examples/default command: detox clean-framework-cache && detox build-framework-cache - # This is a workaround until the iOS SDK is updated to prioritize the custom - # Instabug.plist over the internal Config.plist. - - run: - name: Customize API Endpoints - command: ./scripts/customize-ios-endpoints.sh - run: name: Detox - Build Release App working_directory: examples/default @@ -353,10 +286,6 @@ jobs: command: detox test --configuration ios.sim.release --cleanup e2e_android: - parameters: - prepare_steps: - type: steps - default: [] executor: name: android/android-machine tag: '2024.01.1' @@ -365,7 +294,7 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - - steps: << parameters.prepare_steps >> + # - node/install-yarn - install_node_modules - node/install-packages: pkg-manager: yarn @@ -469,22 +398,35 @@ jobs: - run: yarn build - run: yarn remove @instabug/danger-plugin-coverage - run: - name: Get snapshot version + name: Remove build files from .gitignore + command: sed -i '/dist/d' .gitignore && sed -i '/bin/d' .gitignore + - run: + name: Get snapshot branch name command: | - source scripts/snapshot-version.sh - echo "export SNAPSHOT_VERSION=$SNAPSHOT_VERSION" >> "$BASH_ENV" + source scripts/snapshot-branch.sh + echo "export SNAPSHOT_BRANCH=$SNAPSHOT_BRANCH" >> "$BASH_ENV" - run: - name: Authorize with NPM - command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc - - run: npm version $SNAPSHOT_VERSION --no-git-tag-version - - run: npm publish --tag snapshot + name: Setup Git + command: | + git config --global user.name "Instabug-CP-CI" + git config --global user.email github-ci+cp@instabug.com + - run: + name: Create snapshot branch + command: git checkout -b $SNAPSHOT_BRANCH + - run: + name: Commit changes + command: | + git add . + git commit -m "chore: add generate files" + - run: + name: Push snapshot + command: git push --force origin $SNAPSHOT_BRANCH - run: name: Install jq command: sudo apt-get update && sudo apt-get install -y jq - - find_and_replace: - files: scripts/snapshot-comment.md - search: '{VERSION}' - replace: $SNAPSHOT_VERSION + - run: + name: Replace snapshot branch in comment template + command: sed -i "s|{BRANCH}|$SNAPSHOT_BRANCH|g" scripts/snapshot-comment.md - notify_github: data: "$(jq -Rcs '{ body: . }' scripts/snapshot-comment.md)" @@ -497,14 +439,11 @@ workflows: - test_android - test_ios - lint - - test_module: - collect_coverage: true - - test_android: - collect_coverage: true - - test_ios: - collect_coverage: true + - test_module + - test_android - validate_shell_files - sync_generated_files + - test_ios - e2e_ios - e2e_android - hold_generate_snapshot: @@ -576,33 +515,8 @@ workflows: android_package: injazat api_endpoint: st001013mec1.instabug.com - # Dream11 tests - - hold_test_dream11: - type: approval - - test_module: - name: test_module_dream11 - <<: *dream11_prepare_config - - test_android: - name: test_android_dream11 - <<: *dream11_prepare_config - - test_ios: - name: test_ios_dream11 - <<: *dream11_prepare_config - - e2e_android: - name: e2e_android_dream11 - <<: *dream11_prepare_config - - e2e_ios: - name: e2e_ios_dream11 - <<: *dream11_prepare_config - - # Dream11 release - hold_release_dream11: - requires: - - test_module_dream11 - - test_android_dream11 - - test_ios_dream11 - - e2e_android_dream11 - - e2e_ios_dream11 + requires: *release_dependencies type: approval filters: branches: From 6da1d7b60fd6e6df3e5eb1242f879423703e7067 Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:02:11 +0300 Subject: [PATCH 079/104] ci: run tests before enterprise releases (#1271) --- .circleci/config.yml | 151 +++++++++++++++--- .../ios/InstabugTests/InstabugSampleTests.m | 1 - ios/RNInstabug/InstabugReactBridge.h | 1 - ios/RNInstabug/InstabugReactBridge.m | 1 - 4 files changed, 125 insertions(+), 29 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 64a6b4013a..d8334f0b32 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,6 +17,12 @@ references: - e2e_ios - e2e_android + dream11_prepare_config: &dream11_prepare_config + prepare_steps: + - prepare_dream11 + requires: + - hold_test_dream11 + commands: install_node_modules: parameters: @@ -36,15 +42,28 @@ commands: parameters: working_directory: type: string + deployment: + type: boolean + default: false steps: - restore_cache: name: Restore Pods Cache keys: - v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} - - run: - name: Install Pods - working_directory: << parameters.working_directory >> - command: pod install --deployment + - when: + condition: << parameters.deployment >> + steps: + - run: + name: Install Pods + working_directory: << parameters.working_directory >> + command: pod install --deployment + - unless: + condition: << parameters.deployment >> + steps: + - run: + name: Install Pods + working_directory: << parameters.working_directory >> + command: pod install - save_cache: name: Save Pods Cache key: v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} @@ -120,6 +139,11 @@ commands: name: Remove unused features command: ./scripts/dream-11-delete-unused-features.sh working_directory: << parameters.working_directory >> + # Remove the NDK package to avoid dependency conflicts on Android. + - run: + name: Remove the NDK package + command: yarn remove instabug-reactnative-ndk + working_directory: << parameters.working_directory >>/examples/default notify_github: parameters: @@ -158,20 +182,38 @@ jobs: command: yarn lint:ci test_module: + parameters: + prepare_steps: + type: steps + default: [] + collect_coverage: + type: boolean + default: false executor: name: node/default steps: - advanced-checkout/shallow-checkout + - steps: << parameters.prepare_steps >> - install_node_modules - run: name: Run Tests command: yarn test - - persist_to_workspace: - root: coverage - paths: - - lcov.info + - when: + condition: << parameters.collect_coverage >> + steps: + - persist_to_workspace: + root: coverage + paths: + - lcov.info test_android: + parameters: + prepare_steps: + type: steps + default: [] + collect_coverage: + type: boolean + default: false executor: name: android/android-machine tag: '2024.01.1' @@ -180,15 +222,18 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - # - node/install-yarn + - steps: << parameters.prepare_steps >> - install_node_modules - android/run-tests: working-directory: android test-command: ./gradlew test - - persist_to_workspace: - root: ~/project/android/build/reports/jacoco/jacocoTestReport - paths: - - jacocoTestReport.xml + - when: + condition: << parameters.collect_coverage >> + steps: + - persist_to_workspace: + root: ~/project/android/build/reports/jacoco/jacocoTestReport + paths: + - jacocoTestReport.xml validate_shell_files: machine: @@ -217,10 +262,18 @@ jobs: app-dir: examples/default - install_pods: working_directory: examples/default/ios + deployment: true - run: git --no-pager diff - run: git diff-index HEAD --exit-code -p -I EXCLUDED_ARCHS # Ignore Arch Changes test_ios: + parameters: + prepare_steps: + type: steps + default: [] + collect_coverage: + type: boolean + default: false macos: xcode: 13.4.1 resource_class: macos.m1.medium.gen1 @@ -229,6 +282,7 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout + - steps: << parameters.prepare_steps >> - install_node_modules - install_pods: working_directory: ios @@ -243,16 +297,23 @@ jobs: -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 13 Pro Max,OS=15.5' \ test | xcpretty - - run: - name: Convert xcresult into JSON report - working_directory: ios/coverage - command: xcrun xccov view --report --json result.xcresult > xcode.json - - persist_to_workspace: - root: ios/coverage - paths: - - xcode.json + - when: + condition: << parameters.collect_coverage >> + steps: + - run: + name: Convert xcresult into JSON report + working_directory: ios/coverage + command: xcrun xccov view --report --json result.xcresult > xcode.json + - persist_to_workspace: + root: ios/coverage + paths: + - xcode.json e2e_ios: + parameters: + prepare_steps: + type: steps + default: [] macos: xcode: 13.4.1 resource_class: macos.m1.medium.gen1 @@ -260,6 +321,7 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout + - steps: << parameters.prepare_steps >> - install_node_modules - node/install-packages: pkg-manager: yarn @@ -276,6 +338,11 @@ jobs: name: Rebuild Detox.framework Cache working_directory: examples/default command: detox clean-framework-cache && detox build-framework-cache + # This is a workaround until the iOS SDK is updated to prioritize the custom + # Instabug.plist over the internal Config.plist. + - run: + name: Customize API Endpoints + command: ./scripts/customize-ios-endpoints.sh - run: name: Detox - Build Release App working_directory: examples/default @@ -286,6 +353,10 @@ jobs: command: detox test --configuration ios.sim.release --cleanup e2e_android: + parameters: + prepare_steps: + type: steps + default: [] executor: name: android/android-machine tag: '2024.01.1' @@ -294,7 +365,7 @@ jobs: INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - advanced-checkout/shallow-checkout - # - node/install-yarn + - steps: << parameters.prepare_steps >> - install_node_modules - node/install-packages: pkg-manager: yarn @@ -439,11 +510,14 @@ workflows: - test_android - test_ios - lint - - test_module - - test_android + - test_module: + collect_coverage: true + - test_android: + collect_coverage: true + - test_ios: + collect_coverage: true - validate_shell_files - sync_generated_files - - test_ios - e2e_ios - e2e_android - hold_generate_snapshot: @@ -515,8 +589,33 @@ workflows: android_package: injazat api_endpoint: st001013mec1.instabug.com + # Dream11 tests + - hold_test_dream11: + type: approval + - test_module: + name: test_module_dream11 + <<: *dream11_prepare_config + - test_android: + name: test_android_dream11 + <<: *dream11_prepare_config + - test_ios: + name: test_ios_dream11 + <<: *dream11_prepare_config + - e2e_android: + name: e2e_android_dream11 + <<: *dream11_prepare_config + - e2e_ios: + name: e2e_ios_dream11 + <<: *dream11_prepare_config + + # Dream11 release - hold_release_dream11: - requires: *release_dependencies + requires: + - test_module_dream11 + - test_android_dream11 + - test_ios_dream11 + - e2e_android_dream11 + - e2e_ios_dream11 type: approval filters: branches: diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index 565a21b1a7..70ef410258 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -8,7 +8,6 @@ #import #import "OCMock/OCMock.h" #import "Instabug/Instabug.h" -#import "Instabug/IBGSurvey.h" #import "InstabugReactBridge.h" #import #import "IBGConstants.h" diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index c2accc9955..a3cfc21c13 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -12,7 +12,6 @@ #import #import #import -#import #import #import #import "ArgsRegistry.h" diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index a6f56109c2..dd18513163 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -8,7 +8,6 @@ #import #import #import -#import #import #import #import From c4a62ceab895a2203a4768323fd38db4a0cce802 Mon Sep 17 00:00:00 2001 From: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:35:40 +0300 Subject: [PATCH 080/104] ci: publish snapshots to npm (#1274) --- .circleci/config.yml | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d8334f0b32..efca5acab3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -469,35 +469,22 @@ jobs: - run: yarn build - run: yarn remove @instabug/danger-plugin-coverage - run: - name: Remove build files from .gitignore - command: sed -i '/dist/d' .gitignore && sed -i '/bin/d' .gitignore - - run: - name: Get snapshot branch name - command: | - source scripts/snapshot-branch.sh - echo "export SNAPSHOT_BRANCH=$SNAPSHOT_BRANCH" >> "$BASH_ENV" - - run: - name: Setup Git - command: | - git config --global user.name "Instabug-CP-CI" - git config --global user.email github-ci+cp@instabug.com - - run: - name: Create snapshot branch - command: git checkout -b $SNAPSHOT_BRANCH - - run: - name: Commit changes + name: Get snapshot version command: | - git add . - git commit -m "chore: add generate files" + source scripts/snapshot-version.sh + echo "export SNAPSHOT_VERSION=$SNAPSHOT_VERSION" >> "$BASH_ENV" - run: - name: Push snapshot - command: git push --force origin $SNAPSHOT_BRANCH + name: Authorize with NPM + command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc + - run: npm version $SNAPSHOT_VERSION --no-git-tag-version + - run: npm publish --tag snapshot - run: name: Install jq command: sudo apt-get update && sudo apt-get install -y jq - - run: - name: Replace snapshot branch in comment template - command: sed -i "s|{BRANCH}|$SNAPSHOT_BRANCH|g" scripts/snapshot-comment.md + - find_and_replace: + files: scripts/snapshot-comment.md + search: '{VERSION}' + replace: $SNAPSHOT_VERSION - notify_github: data: "$(jq -Rcs '{ body: . }' scripts/snapshot-comment.md)" From ba2b40a2a3ad69447d5a63b2127c1a017c693e43 Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:02:15 +0300 Subject: [PATCH 081/104] fix(ios): network log empty response body (#1273) --- CHANGELOG.md | 4 ++++ src/utils/XhrNetworkInterceptor.ts | 2 +- test/utils/XhrNetworkInterceptor.spec.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index acb003486f..5d81354bd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - Add support for Expo Router navigation tracking ([#1270](https://github.com/Instabug/Instabug-React-Native/pull/1270)). +### Fixed + +- Fix APM network logging on iOS when the response body is missing or empty. ([#1273](https://github.com/Instabug/Instabug-React-Native/pull/1273)). + ## [13.3.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...v13.3.0) (August 4, 2024) ### Added diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 701533f15c..9423064689 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -152,7 +152,7 @@ export default { const _response = this._response; cloneNetwork.requestBody = typeof _response === 'string' ? _response : JSON.stringify(_response); - cloneNetwork.responseBody = null; + cloneNetwork.responseBody = ''; } if (this.response) { diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index 3976fc3cec..ec7210bb2b 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -236,7 +236,7 @@ describe('Network Interceptor', () => { expect.objectContaining({ errorDomain: 'ClientError', errorCode: 0, - responseBody: null, + responseBody: '', }), ); }); From 25f6aaeca26be9075003b400086580aaff369090 Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:55:55 +0300 Subject: [PATCH 082/104] fix: drop non-error objects when reporting errors (#1279) * Fix: omitted non-error objects when logging errors * ci: publish snapshots to npm (#1274) * Fix: omitted non-error objects when logging errors * fix: use warn instead of logs Co-authored-by: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> * Update CHANGELOG.md Co-authored-by: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> * fix: merge issues --------- Co-authored-by: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> --- CHANGELOG.md | 1 + src/modules/CrashReporting.ts | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d81354bd9..ba449b9fbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixed +- Drop non-error objects reported as crashes since they don't have a stack trace ([#1279](https://github.com/Instabug/Instabug-React-Native/pull/1279)). - Fix APM network logging on iOS when the response body is missing or empty. ([#1273](https://github.com/Instabug/Instabug-React-Native/pull/1273)). ## [13.3.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.2.0...v13.3.0) (August 4, 2024) diff --git a/src/modules/CrashReporting.ts b/src/modules/CrashReporting.ts index 9ae743cadb..c374c7d772 100644 --- a/src/modules/CrashReporting.ts +++ b/src/modules/CrashReporting.ts @@ -21,18 +21,25 @@ export const setEnabled = (isEnabled: boolean) => { * @param nonFatalOptions extra config for the non-fatal error sent with Error Object */ export const reportError = (error: ExtendedError, nonFatalOptions: NonFatalOptions = {}) => { - let level = NonFatalErrorLevel.error; - if (nonFatalOptions.level != null) { - level = nonFatalOptions.level; + if (error instanceof Error) { + let level = NonFatalErrorLevel.error; + if (nonFatalOptions.level != null) { + level = nonFatalOptions.level; + } + return InstabugUtils.sendCrashReport(error, (data) => + NativeCrashReporting.sendHandledJSCrash( + data, + nonFatalOptions.userAttributes, + nonFatalOptions.fingerprint, + level, + ), + ); + } else { + console.warn( + `IBG-RN: The error ${error} has been omitted because only error type is supported.`, + ); + return; } - return InstabugUtils.sendCrashReport(error, (data) => - NativeCrashReporting.sendHandledJSCrash( - data, - nonFatalOptions.userAttributes, - nonFatalOptions.fingerprint, - level, - ), - ); }; /** From ee85f5951b8a9c916e07953ef22d08ab9642a9c8 Mon Sep 17 00:00:00 2001 From: ahmed alaa <154802748+ahmedAlaaInstabug@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:46:30 +0300 Subject: [PATCH 083/104] feat: capture client error in the network interceptor (#1257) * feat/support-capture-client-error-in-xhr-requests --------- Co-authored-by: Abdelhamid Nasser <38096011+abdelhamid-f-nasser@users.noreply.github.com> Co-authored-by: Ahmed Elrefaey <68241710+a7medev@users.noreply.github.com> Co-authored-by: kholood --- CHANGELOG.md | 1 + examples/default/package.json | 1 + .../default/src/screens/apm/NetworkScreen.tsx | 32 +++++++++++++++++++ examples/default/yarn.lock | 11 ++++--- src/utils/XhrNetworkInterceptor.ts | 18 +++++++++-- test/utils/XhrNetworkInterceptor.spec.ts | 2 +- 6 files changed, 57 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba449b9fbc..b050ce8c4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - Add support for Expo Router navigation tracking ([#1270](https://github.com/Instabug/Instabug-React-Native/pull/1270)). +- Enhance the network interceptor to capture more client error messages ([#1257](https://github.com/Instabug/Instabug-React-Native/pull/1257)). ### Fixed diff --git a/examples/default/package.json b/examples/default/package.json index 529521802d..a618c2811c 100644 --- a/examples/default/package.json +++ b/examples/default/package.json @@ -16,6 +16,7 @@ "@react-navigation/native": "^6.1.6", "@react-navigation/native-stack": "^6.9.12", "graphql": "^16.8.1", + "axios": "^1.7.4", "graphql-request": "^6.1.0", "instabug-reactnative": "link:../..", "instabug-reactnative-ndk": "github:https://github.com/Instabug/Instabug-React-Native-NDK", diff --git a/examples/default/src/screens/apm/NetworkScreen.tsx b/examples/default/src/screens/apm/NetworkScreen.tsx index 467a621f21..40ad2b5faf 100644 --- a/examples/default/src/screens/apm/NetworkScreen.tsx +++ b/examples/default/src/screens/apm/NetworkScreen.tsx @@ -7,6 +7,7 @@ import { useQuery } from 'react-query'; import { HStack, VStack } from 'native-base'; import { gql, request } from 'graphql-request'; import { CustomButton } from '../../components/CustomButton'; +import axios from 'axios'; export const NetworkScreen: React.FC = () => { const [endpointUrl, setEndpointUrl] = useState(''); @@ -45,6 +46,32 @@ export const NetworkScreen: React.FC = () => { } } + async function sendRequestToUrlUsingAxios() { + let urlToSend = ''; + + if (endpointUrl.trim() !== '') { + urlToSend = endpointUrl; + console.log('Sending request to: ', endpointUrl); + } else { + // Use json placeholder URL as a default if endpointUrl is empty + console.log('sending request to default json placeholder'); + urlToSend = defaultRequestUrl; + } + + try { + // Perform the request using the urlToSend + const response = await axios.get(urlToSend); + // Format the JSON response for better logging + const formattedData = JSON.stringify(response.data, null, 2); + + // Log the formatted response + console.log('Response:', formattedData); + } catch (error) { + // Handle errors appropriately + console.error('Error:', error); + } + } + const fetchGraphQlData = async () => { const document = gql` query { @@ -75,6 +102,11 @@ export const NetworkScreen: React.FC = () => { value={endpointUrl} /> + + refetch} title="Reload GraphQL" /> {isLoading && Loading...} diff --git a/examples/default/yarn.lock b/examples/default/yarn.lock index 85117d5449..10aaed1cd9 100644 --- a/examples/default/yarn.lock +++ b/examples/default/yarn.lock @@ -3249,10 +3249,10 @@ at-least-node@^1.0.0: resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -axios@^1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" - integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== +axios@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" + integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -4690,7 +4690,8 @@ inline-style-prefixer@^6.0.1: resolved "https://codeload.github.com/Instabug/Instabug-React-Native-NDK/tar.gz/3b0bac281253133852d32f52aa50cc805dd0b570" "instabug-reactnative@link:../..": - version "13.0.5" + version "0.0.0" + uid "" intl-messageformat@^10.1.0: version "10.5.0" diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 9423064689..98c5ef9cc5 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -72,7 +72,8 @@ export default { originalXHROpen = XMLHttpRequest.prototype.open; originalXHRSend = XMLHttpRequest.prototype.send; originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader; - + // An error code that signifies an issue with the RN client. + const clientErrorCode = 9876; XMLHttpRequest.prototype.open = function (method, url, ...args) { _reset(); network.url = url; @@ -145,7 +146,7 @@ export default { // @ts-ignore if (this._hasError) { - cloneNetwork.errorCode = 0; + cloneNetwork.errorCode = clientErrorCode; cloneNetwork.errorDomain = 'ClientError'; // @ts-ignore @@ -153,6 +154,16 @@ export default { cloneNetwork.requestBody = typeof _response === 'string' ? _response : JSON.stringify(_response); cloneNetwork.responseBody = ''; + + // Detect a more descriptive error message. + if (typeof _response === 'string' && _response.length > 0) { + cloneNetwork.errorDomain = _response; + } + + // @ts-ignore + } else if (this._timedOut) { + cloneNetwork.errorCode = clientErrorCode; + cloneNetwork.errorDomain = 'TimeOutError'; } if (this.response) { @@ -162,6 +173,9 @@ export default { } else if (['text', '', 'json'].includes(this.responseType)) { cloneNetwork.responseBody = JSON.stringify(this.response); } + } else { + cloneNetwork.responseBody = ''; + cloneNetwork.contentType = 'text/plain'; } cloneNetwork.requestBodySize = cloneNetwork.requestBody.length; diff --git a/test/utils/XhrNetworkInterceptor.spec.ts b/test/utils/XhrNetworkInterceptor.spec.ts index ec7210bb2b..dfb9e7f43b 100644 --- a/test/utils/XhrNetworkInterceptor.spec.ts +++ b/test/utils/XhrNetworkInterceptor.spec.ts @@ -235,7 +235,7 @@ describe('Network Interceptor', () => { expect(callback).toBeCalledWith( expect.objectContaining({ errorDomain: 'ClientError', - errorCode: 0, + errorCode: 9876, responseBody: '', }), ); From 8910500897a7a352cb6af073375656ffd35d3ae4 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 16 Sep 2024 16:04:04 +0300 Subject: [PATCH 084/104] fix: merge issues --- .../reactlibrary/RNInstabugAPMModule.java | 42 ++++++-- .../default/src/screens/apm/NetworkScreen.tsx | 18 +++- ios/RNInstabug/InstabugReactBridge.h | 3 +- src/native/NativeAPM.ts | 5 + src/native/NativeInstabug.ts | 13 +++ src/utils/InstabugUtils.ts | 73 +------------ src/utils/XhrNetworkInterceptor.ts | 100 +++++++++++++++++- 7 files changed, 172 insertions(+), 82 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index e2ff10b991..84706e94dc 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -9,17 +9,16 @@ import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; import com.instabug.apm.APM; import com.instabug.apm.model.ExecutionTrace; import com.instabug.apm.networking.APMNetworkLogger; import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; +import com.instabug.reactlibrary.utils.EventEmitterModule; +import com.instabug.apm.networkinterception.cp.APMCPNetworkLog; import com.instabug.reactlibrary.utils.MainThreadHandler; -import org.json.JSONException; -import org.json.JSONObject; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; @@ -28,7 +27,7 @@ import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; -public class RNInstabugAPMModule extends ReactContextBaseJavaModule { +public class RNInstabugAPMModule extends EventEmitterModule { public RNInstabugAPMModule(ReactApplicationContext reactApplicationContext) { super(reactApplicationContext); @@ -331,13 +330,41 @@ private void networkLogAndroid(final double requestStartTime, final String responseContentType, @Nullable final String errorDomain, @Nullable final String gqlQueryName, - @Nullable final String serverErrorMessage) { + @Nullable final String serverErrorMessage, + @Nullable final ReadableMap w3cAttributes + + ) { try { APMNetworkLogger networkLogger = new APMNetworkLogger(); final boolean hasError = errorDomain != null && !errorDomain.isEmpty(); final String errorMessage = hasError ? errorDomain : null; + Boolean isW3cHeaderFound=false; + Long partialId=null; + Long networkStartTimeInSeconds=null; + + try { + if (w3cAttributes.hasKey("isW3cHeaderFound")) { + isW3cHeaderFound = w3cAttributes.getBoolean("isW3cHeaderFound"); + } + + if (w3cAttributes.hasKey("partialId")) { + partialId =(long) w3cAttributes.getDouble("partialId"); + networkStartTimeInSeconds = (long) w3cAttributes.getDouble("networkStartTimeInSeconds"); + } + + } catch (Exception e) { + e.printStackTrace(); + } + APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = + new APMCPNetworkLog.W3CExternalTraceAttributes( + isW3cHeaderFound, + partialId, + networkStartTimeInSeconds, + w3cAttributes.getString("w3cGeneratedHeader"), + w3cAttributes.getString("w3cCaughtHeader") + ); try { Method method = 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) { @@ -359,7 +386,8 @@ private void networkLogAndroid(final double requestStartTime, errorMessage, gqlQueryName, serverErrorMessage, - null + w3cExternalTraceAttributes + ); } else { Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); diff --git a/examples/default/src/screens/apm/NetworkScreen.tsx b/examples/default/src/screens/apm/NetworkScreen.tsx index 40ad2b5faf..422f16254b 100644 --- a/examples/default/src/screens/apm/NetworkScreen.tsx +++ b/examples/default/src/screens/apm/NetworkScreen.tsx @@ -8,6 +8,7 @@ import { HStack, VStack } from 'native-base'; import { gql, request } from 'graphql-request'; import { CustomButton } from '../../components/CustomButton'; import axios from 'axios'; +import { ListTile } from '../../components/ListTile'; export const NetworkScreen: React.FC = () => { const [endpointUrl, setEndpointUrl] = useState(''); @@ -89,6 +90,14 @@ export const NetworkScreen: React.FC = () => { }; const { data, isError, isSuccess, isLoading, refetch } = useQuery('helloQuery', fetchGraphQlData); + const simulateNetworkRequest = () => { + axios.get('https://httpbin.org/anything', { + headers: { traceparent: 'Caught Header Example' }, + }); + }; + const simulateNetworkRequestWithoutHeader = () => { + axios.get('https://httpbin.org/anything'); + }; return ( @@ -106,7 +115,14 @@ export const NetworkScreen: React.FC = () => { onPress={sendRequestToUrlUsingAxios} title="Send Request To Url Using Axios" /> - + simulateNetworkRequest()} + /> + simulateNetworkRequestWithoutHeader()} + /> refetch} title="Reload GraphQL" /> {isLoading && Loading...} diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index a3cfc21c13..035f63b0f9 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -121,7 +121,8 @@ startTime:(double)startTime duration:(double)duration gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage; + serverErrorMessage:(NSString * _Nullable)serverErrorMessage +w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes; /* +------------------------------------------------------------------------+ diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index b1981cfe37..48da26a36e 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -1,5 +1,7 @@ import type { NativeModule } from 'react-native'; +import { NativeEventEmitter } from 'react-native'; +import type { W3cExternalTraceAttributes } from '../utils/Types'; import { NativeModules } from './NativePackage'; export interface ApmNativeModule extends NativeModule { @@ -24,6 +26,7 @@ export interface ApmNativeModule extends NativeModule { errorDomain: string, gqlQueryName?: string, serverErrorMessage?: string, + w3cExternalTraceAttributes?: W3cExternalTraceAttributes, ): void; // App Launches APIs // @@ -48,3 +51,5 @@ export interface ApmNativeModule extends NativeModule { } export const NativeAPM = NativeModules.IBGAPM; + +export const emitter = new NativeEventEmitter(NativeAPM); diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 3b72f5951f..ef5fd2f25b 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -11,6 +11,7 @@ import type { WelcomeMessageMode, } from '../utils/Enums'; import type { NativeConstants } from './NativeConstants'; +import type { W3cExternalTraceAttributes } from '../utils/Types'; import { NativeModules } from './NativePackage'; export interface InstabugNativeModule extends NativeModule { @@ -67,6 +68,7 @@ export interface InstabugNativeModule extends NativeModule { duration: number, gqlQueryName: string | undefined, serverErrorMessage: string | undefined, + W3cExternalTraceAttributes: W3cExternalTraceAttributes, ): void; setNetworkLoggingEnabled(isEnabled: boolean): void; @@ -140,12 +142,23 @@ export interface InstabugNativeModule extends NativeModule { addFileAttachmentWithURLToReport(url: string, filename?: string): void; addFileAttachmentWithDataToReport(data: string, filename?: string): void; willRedirectToStore(): void; + + // W3C Feature Flags + isW3ExternalTraceIDEnabled(): Promise; + + isW3ExternalGeneratedHeaderEnabled(): Promise; + + isW3CaughtHeaderEnabled(): Promise; + + // W3C Feature Flags Listener for Android + registerW3CFlagsChangeListener(): void; } export const NativeInstabug = NativeModules.Instabug; export enum NativeEvents { PRESENDING_HANDLER = 'IBGpreSendingHandler', + ON_W3C_FLAGS_CHANGE = 'IBGOnNewW3CFlagsUpdateReceivedCallback', } export const emitter = new NativeEventEmitter(NativeInstabug); diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index a089b20f2e..ce8e39bb77 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -205,6 +205,8 @@ export function reportNetworkLog(network: NetworkData) { network.responseCode, network.contentType, network.errorDomain, + network.gqlQueryName, + network.serverErrorMessage, { isW3cHeaderFound: network.isW3cHeaderFound, partialId: network.partialId, @@ -212,8 +214,6 @@ export function reportNetworkLog(network: NetworkData) { w3cGeneratedHeader: network.w3cGeneratedHeader, w3cCaughtHeader: network.w3cCaughtHeader, }, - network.gqlQueryName, - network.serverErrorMessage, ); } else { NativeInstabug.networkLogIOS( @@ -244,75 +244,6 @@ export function reportNetworkLog(network: NetworkData) { } } -export function isContentTypeNotAllowed(contentType: string) { - const allowed = [ - 'application/protobuf', - 'application/json', - 'application/xml', - 'text/xml', - 'text/html', - 'text/plain', - ]; - - return allowed.every((type) => !contentType.includes(type)); -} - -export function reportNetworkLog(network: NetworkData) { - if (Platform.OS === 'android') { - const requestHeaders = JSON.stringify(network.requestHeaders); - const responseHeaders = JSON.stringify(network.responseHeaders); - - NativeInstabug.networkLogAndroid( - network.url, - network.requestBody, - network.responseBody, - network.method, - network.responseCode, - requestHeaders, - responseHeaders, - network.duration, - ); - - NativeAPM.networkLogAndroid( - network.startTime, - network.duration, - requestHeaders, - network.requestBody, - network.requestBodySize, - network.method, - network.url, - network.requestContentType, - responseHeaders, - network.responseBody, - network.responseBodySize, - network.responseCode, - network.contentType, - network.errorDomain, - network.gqlQueryName, - network.serverErrorMessage, - ); - } else { - NativeInstabug.networkLogIOS( - network.url, - network.method, - network.requestBody, - network.requestBodySize, - network.responseBody, - network.responseBodySize, - network.responseCode, - network.requestHeaders, - network.responseHeaders, - network.contentType, - network.errorDomain, - network.errorCode, - network.startTime, - network.duration, - network.gqlQueryName, - network.serverErrorMessage, - ); - } -} - export default { parseErrorStack, captureJsErrors, diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 98c5ef9cc5..26deeb37a9 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -1,5 +1,7 @@ import InstabugConstants from './InstabugConstants'; -import { stringifyIfNotString } from './InstabugUtils'; +import { stringifyIfNotString, generateW3CHeader } from './InstabugUtils'; + +import { FeatureFlags } from '../utils/FeatureFlags'; export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend: number) => void; export type NetworkDataCallback = (data: NetworkData) => void; @@ -22,6 +24,11 @@ export interface NetworkData { gqlQueryName?: string; serverErrorMessage: string; requestContentType: string; + isW3cHeaderFound: boolean | null; + partialId: number | null; + networkStartTimeInSeconds: number | null; + w3cGeneratedHeader: string | null; + w3cCaughtHeader: string | null; } const XMLHttpRequest = global.XMLHttpRequest; @@ -53,8 +60,93 @@ const _reset = () => { gqlQueryName: '', serverErrorMessage: '', requestContentType: '', + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, }; }; +const getFeatureFlags = async (networkData: NetworkData) => { + const [ + isW3cExternalTraceIDEnabled, + isW3cExternalGeneratedHeaderEnabled, + isW3cCaughtHeaderEnabled, + ] = await Promise.all([ + FeatureFlags.isW3ExternalTraceID(), + FeatureFlags.isW3ExternalGeneratedHeader(), + FeatureFlags.isW3CaughtHeader(), + ]); + + return injectHeaders(networkData, { + isW3cExternalTraceIDEnabled, + isW3cExternalGeneratedHeaderEnabled, + isW3cCaughtHeaderEnabled, + }); +}; + +export const injectHeaders = async ( + networkData: NetworkData, + featureFlags: { + isW3cExternalTraceIDEnabled: boolean; + isW3cExternalGeneratedHeaderEnabled: boolean; + isW3cCaughtHeaderEnabled: boolean; + }, +) => { + const { + isW3cExternalTraceIDEnabled, + isW3cExternalGeneratedHeaderEnabled, + isW3cCaughtHeaderEnabled, + } = featureFlags; + + console.log('isW3cExternalTraceIDEnabled', isW3cCaughtHeaderEnabled); + console.log('isW3cCaughtHeaderEnabled', isW3cCaughtHeaderEnabled); + console.log('isW3cExternalGeneratedHeaderEnabled', isW3cExternalGeneratedHeaderEnabled); + + if (!isW3cExternalTraceIDEnabled) { + return; + } + + const isHeaderFound = networkData.requestHeaders.traceparent != null; + + networkData.isW3cHeaderFound = isHeaderFound; + + console.log('isW3cExternalTraceIDEnabled', isW3cCaughtHeaderEnabled); + console.log('isW3cCaughtHeaderEnabled', isW3cCaughtHeaderEnabled); + console.log('isW3cExternalGeneratedHeaderEnabled', isW3cExternalGeneratedHeaderEnabled); + + const injectionMethodology = isHeaderFound + ? identifyCaughtHeader(networkData, isW3cCaughtHeaderEnabled) + : injectGeneratedData(networkData, isW3cExternalGeneratedHeaderEnabled); + return injectionMethodology; +}; + +const identifyCaughtHeader = async ( + networkData: NetworkData, + isW3cCaughtHeaderEnabled: boolean, +) => { + if (isW3cCaughtHeaderEnabled) { + networkData.w3cCaughtHeader = networkData.requestHeaders.traceparent; + return networkData.requestHeaders.traceparent; + } + return; +}; + +const injectGeneratedData = ( + networkData: NetworkData, + isW3cExternalGeneratedHeaderEnabled: boolean, +) => { + const { timestampInSeconds, partialId, w3cHeader } = generateW3CHeader(networkData.startTime); + networkData.partialId = partialId; + networkData.networkStartTimeInSeconds = timestampInSeconds; + + if (isW3cExternalGeneratedHeaderEnabled) { + networkData.w3cGeneratedHeader = w3cHeader; + return w3cHeader; + } + + return; +}; export default { setOnDoneCallback(callback: NetworkDataCallback) { @@ -91,7 +183,7 @@ export default { originalXHRSetRequestHeader.apply(this, [header, value]); }; - XMLHttpRequest.prototype.send = function (data) { + XMLHttpRequest.prototype.send = async function (data) { const cloneNetwork = JSON.parse(JSON.stringify(network)); cloneNetwork.requestBody = data ? data : ''; @@ -226,6 +318,10 @@ export default { } cloneNetwork.startTime = Date.now(); + const traceparent = await getFeatureFlags(cloneNetwork); + if (traceparent) { + this.setRequestHeader('Traceparent', traceparent); + } originalXHRSend.apply(this, [data]); }; isInterceptorEnabled = true; From aba89d87f24166421c5c8663ae0cb1e9bb58e2ab Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 16 Sep 2024 15:48:16 +0300 Subject: [PATCH 085/104] fix: networkLogIOS test case --- .../ios/InstabugTests/InstabugSampleTests.m | 83 ++++++++++++++++++- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index 70ef410258..97392502ab 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -332,7 +332,12 @@ - (void)testNetworkLogIOS { double duration = 150; NSString *gqlQueryName = nil; NSString *serverErrorMessage = nil; - + NSDictionary* w3cExternalTraceAttributes = nil; + NSNumber *isW3cCaughted = nil; + NSNumber *partialID = nil; + NSNumber *timestamp= nil; + NSString *generatedW3CTraceparent= nil; + NSString *caughtedW3CTraceparent= nil; [self.instabugBridge networkLogIOS:url method:method requestBody:requestBody @@ -348,7 +353,13 @@ - (void)testNetworkLogIOS { startTime:startTime duration:duration gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage]; + serverErrorMessage:serverErrorMessage + isW3cCaughted:nil + partialID:nil + timestamp:nil + generatedW3CTraceparent:nil + caughtedW3CTraceparent:nil + ]; OCMVerify([mIBGNetworkLogger addNetworkLogWithUrl:url method:method @@ -365,7 +376,14 @@ - (void)testNetworkLogIOS { startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage]); + serverErrorMessage:serverErrorMessage + isW3cCaughted:nil + partialID:nil + timestamp:nil + generatedW3CTraceparent:nil + caughtedW3CTraceparent:nil + + ]); } - (void)testSetFileAttachment { @@ -497,6 +515,65 @@ - (void)testClearAllExperiments { OCMVerify([mock clearAllExperiments]); } + +- (void) testIsW3ExternalTraceIDEnabled { + id mock = OCMClassMock([IBGNetworkLogger class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3ExternalTraceIDEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge isW3ExternalTraceIDEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3ExternalTraceIDEnabled]); +} + +- (void) testIsW3ExternalGeneratedHeaderEnabled { + id mock = OCMClassMock([IBGNetworkLogger class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3ExternalGeneratedHeaderEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge isW3ExternalGeneratedHeaderEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3ExternalGeneratedHeaderEnabled]); +} + +- (void) testIsW3CaughtHeaderEnabled { + id mock = OCMClassMock([IBGNetworkLogger class]); + NSNumber *expectedValue = @(YES); + + OCMStub([mock w3CaughtHeaderEnabled]).andReturn([expectedValue boolValue]); + + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; + RCTPromiseResolveBlock resolve = ^(NSNumber *result) { + XCTAssertEqualObjects(result, expectedValue); + [expectation fulfill]; + }; + + [self.instabugBridge isW3CaughtHeaderEnabled:resolve :nil]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; + + OCMVerify([mock w3CaughtHeaderEnabled]); +} + + - (void)testAddFeatureFlags { id mock = OCMClassMock([Instabug class]); NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"}; From de98c73f64990042ca846fd96fb279f94631a5a5 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 16 Sep 2024 16:07:49 +0300 Subject: [PATCH 086/104] fix: merge issues --- RNInstabug.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RNInstabug.podspec b/RNInstabug.podspec index 21ae5fc720..40c480f4cb 100644 --- a/RNInstabug.podspec +++ b/RNInstabug.podspec @@ -16,5 +16,5 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm}" s.dependency 'React-Core' - s.dependency 'Instabug' + use_instabug!(s) end From 43eb29355f07408e0f8968f3bcbcca907762801b Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 16 Sep 2024 16:24:38 +0300 Subject: [PATCH 087/104] fix: merge issues --- android/native.gradle | 2 +- .../RNInstabugReactnativeModule.java | 107 ++++++++++++++++++ .../RNInstabugReactnativeModuleTest.java | 27 +++++ .../ios/InstabugTests/InstabugSampleTests.m | 95 +++++++++++----- examples/default/ios/Podfile.lock | 12 +- ios/RNInstabug/InstabugReactBridge.h | 4 +- ios/RNInstabug/InstabugReactBridge.m | 32 +++++- ios/native.rb | 2 +- src/modules/Instabug.ts | 22 +++- src/utils/InstabugUtils.ts | 69 ----------- test/mocks/mockInstabug.ts | 4 + test/modules/Instabug.spec.ts | 16 +++ test/modules/NetworkLogger.spec.ts | 5 + test/utils/InstabugUtils.spec.ts | 5 + 14 files changed, 289 insertions(+), 113 deletions(-) diff --git a/android/native.gradle b/android/native.gradle index 0e86a4edff..39034d6035 100644 --- a/android/native.gradle +++ b/android/native.gradle @@ -1,5 +1,5 @@ project.ext.instabug = [ - version: '13.3.0' + version: '13.4.0' ] dependencies { diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index f936eaa12e..2a9b5474a3 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -8,6 +8,7 @@ import android.util.Log; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.facebook.react.bridge.Arguments; @@ -22,6 +23,8 @@ import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.UIManagerModule; +import com.instabug.apm.InternalAPM; +import com.instabug.apm.configuration.cp.APMFeature; import com.instabug.library.Feature; import com.instabug.library.Instabug; import com.instabug.library.InstabugColorTheme; @@ -30,6 +33,11 @@ import com.instabug.library.LogLevel; import com.instabug.library.ReproConfigurations; import com.instabug.library.core.InstabugCore; +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.featuresflags.model.IBGFeatureFlag; import com.instabug.library.featuresflags.model.IBGFeatureFlag; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; @@ -1148,6 +1156,105 @@ public void run() { } }); } + /** + * Register a listener for W3C flags value change + */ + @ReactMethod + public void registerW3CFlagsChangeListener(){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + InternalCore.INSTANCE._setFeaturesStateListener(new FeaturesStateListener() { + @Override + public void invoke(@NonNull CoreFeaturesState featuresState) { + WritableMap params = Arguments.createMap(); + params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled()); + params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled()); + params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled()); + + sendEvent(Constants.IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); + } + }); + } + catch (Exception e) { + e.printStackTrace(); + } + + } + + }); + } + + + /** + * Get first time Value of W3ExternalTraceID flag + */ + @ReactMethod + public void isW3ExternalTraceIDEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID)); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + + /** + * Get first time Value of W3ExternalGeneratedHeader flag + */ + @ReactMethod + public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER)); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + + /** + * Get first time Value of W3CaughtHeader flag + */ + @ReactMethod + public void isW3CaughtHeaderEnabled(Promise promise){ + + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER)); + } + catch (Exception e) { + e.printStackTrace(); + promise.resolve(null); + } + + } + + }); + } + /** * Map between the exported JS constant and the arg key in {@link ArgsRegistry}. diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java index b9bf2308cc..e8aad5b0c5 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java @@ -18,6 +18,9 @@ import com.instabug.library.IssueType; import com.instabug.library.ReproConfigurations; import com.instabug.library.ReproMode; +import com.instabug.library.internal.crossplatform.CoreFeature; +import com.instabug.library.internal.crossplatform.InternalCore; +import com.instabug.library.featuresflags.model.IBGFeatureFlag; import com.instabug.library.featuresflags.model.IBGFeatureFlag; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.ui.onboarding.WelcomeMessage; @@ -635,4 +638,28 @@ public void testWillRedirectToStore() { // then mockInstabug.verify(() -> Instabug.willRedirectToStore()); } + @Test + public void testW3CExternalTraceIDFlag(){ + Promise promise = mock(Promise.class); + InternalCore internalAPM = mock(InternalCore.class); + rnModule.isW3ExternalTraceIDEnabled(promise); + boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID); + verify(promise).resolve(expected); + } + @Test + public void testW3CExternalGeneratedHeaderFlag(){ + Promise promise = mock(Promise.class); + InternalCore internalAPM = mock(InternalCore.class); + rnModule.isW3ExternalGeneratedHeaderEnabled(promise); + boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER); + verify(promise).resolve(expected); + } + @Test + public void testW3CCaughtHeaderFlag(){ + Promise promise = mock(Promise.class); + InternalCore internalAPM = mock(InternalCore.class); + rnModule.isW3CaughtHeaderEnabled(promise); + boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER); + verify(promise).resolve(expected); + } } diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index 97392502ab..fbb1a5d59f 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -315,7 +315,7 @@ - (void)testSetWelcomeMessageMode { - (void)testNetworkLogIOS { id mIBGNetworkLogger = OCMClassMock([IBGNetworkLogger class]); - + NSString *url = @"https://api.instabug.com"; NSString *method = @"GET"; NSString *requestBody = @"requestBody"; @@ -354,13 +354,10 @@ - (void)testNetworkLogIOS { duration:duration gqlQueryName:gqlQueryName serverErrorMessage:serverErrorMessage - isW3cCaughted:nil - partialID:nil - timestamp:nil - generatedW3CTraceparent:nil - caughtedW3CTraceparent:nil + w3cExternalTraceAttributes:nil + ]; - + OCMVerify([mIBGNetworkLogger addNetworkLogWithUrl:url method:method requestBody:requestBody @@ -376,14 +373,13 @@ - (void)testNetworkLogIOS { startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage - isW3cCaughted:nil - partialID:nil - timestamp:nil - generatedW3CTraceparent:nil - caughtedW3CTraceparent:nil - - ]); + serverErrorMessage:serverErrorMessage + isW3cCaughted:nil + partialID:nil + timestamp:nil + generatedW3CTraceparent:nil + caughtedW3CTraceparent:nil + ]); } - (void)testSetFileAttachment { @@ -515,61 +511,100 @@ - (void)testClearAllExperiments { OCMVerify([mock clearAllExperiments]); } +- (void)testAddFeatureFlags { + id mock = OCMClassMock([Instabug class]); + NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"}; + + OCMStub([mock addFeatureFlags :[OCMArg any]]); + [self.instabugBridge addFeatureFlags:featureFlagsMap]; + OCMVerify([mock addFeatureFlags: [OCMArg checkWithBlock:^(id value) { + NSArray *featureFlags = value; + NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name; + NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ; + if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ + return YES; + } + return NO; + }]]); +} + +- (void)testRemoveFeatureFlags { + id mock = OCMClassMock([Instabug class]); + NSArray *featureFlags = @[@"exp1", @"exp2"]; + [self.instabugBridge removeFeatureFlags:featureFlags]; + OCMVerify([mock removeFeatureFlags: [OCMArg checkWithBlock:^(id value) { + NSArray *featureFlagsObJ = value; + NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name; + NSString* firstFeatureFlagKey = [featureFlags firstObject] ; + if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ + return YES; + } + return NO; + }]]); +} + +- (void)testRemoveAllFeatureFlags { + id mock = OCMClassMock([Instabug class]); + OCMStub([mock removeAllFeatureFlags]); + [self.instabugBridge removeAllFeatureFlags]; + OCMVerify([mock removeAllFeatureFlags]); +} + - (void) testIsW3ExternalTraceIDEnabled { id mock = OCMClassMock([IBGNetworkLogger class]); NSNumber *expectedValue = @(YES); - + OCMStub([mock w3ExternalTraceIDEnabled]).andReturn([expectedValue boolValue]); - + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; RCTPromiseResolveBlock resolve = ^(NSNumber *result) { XCTAssertEqualObjects(result, expectedValue); [expectation fulfill]; }; - + [self.instabugBridge isW3ExternalTraceIDEnabled:resolve :nil]; - + [self waitForExpectationsWithTimeout:1.0 handler:nil]; - + OCMVerify([mock w3ExternalTraceIDEnabled]); } - (void) testIsW3ExternalGeneratedHeaderEnabled { id mock = OCMClassMock([IBGNetworkLogger class]); NSNumber *expectedValue = @(YES); - + OCMStub([mock w3ExternalGeneratedHeaderEnabled]).andReturn([expectedValue boolValue]); - + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; RCTPromiseResolveBlock resolve = ^(NSNumber *result) { XCTAssertEqualObjects(result, expectedValue); [expectation fulfill]; }; - + [self.instabugBridge isW3ExternalGeneratedHeaderEnabled:resolve :nil]; - + [self waitForExpectationsWithTimeout:1.0 handler:nil]; - + OCMVerify([mock w3ExternalGeneratedHeaderEnabled]); } - (void) testIsW3CaughtHeaderEnabled { id mock = OCMClassMock([IBGNetworkLogger class]); NSNumber *expectedValue = @(YES); - + OCMStub([mock w3CaughtHeaderEnabled]).andReturn([expectedValue boolValue]); - + XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; RCTPromiseResolveBlock resolve = ^(NSNumber *result) { XCTAssertEqualObjects(result, expectedValue); [expectation fulfill]; }; - + [self.instabugBridge isW3CaughtHeaderEnabled:resolve :nil]; - + [self waitForExpectationsWithTimeout:1.0 handler:nil]; - + OCMVerify([mock w3CaughtHeaderEnabled]); } diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 1da6e558ee..c1e706171c 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -38,12 +38,12 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.3.0) + - Instabug (13.4.0) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core - libevent (2.1.12) - - OCMock (3.9.3) + - OCMock (3.9.4) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -476,7 +476,7 @@ PODS: - RCT-Folly (= 2021.07.22.00) - React-Core - RNInstabug (13.3.0): - - Instabug (= 13.3.0) + - Instabug (= 13.4.0) - React-Core - RNReanimated (3.5.4): - DoubleConversion @@ -704,10 +704,10 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: 4f26295103a330ec0236918359eef7ccaa74e2fa + Instabug: 183aa1e038d01ddc000f06835f46a9ea1f6c992b instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 + OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18 RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3 @@ -748,7 +748,7 @@ SPEC CHECKSUMS: ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: a4ac0bd09123f6be7d58be541dc220acbaff8dc3 + RNInstabug: 98a04a3cf14303bc172a49079fee36c5158b1799 RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index 035f63b0f9..bca04ddfd0 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -105,7 +105,9 @@ */ - (void)setNetworkLoggingEnabled:(BOOL)isEnabled; - +- (void)isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; +- (void)isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject; - (void)networkLogIOS:(NSString * _Nonnull)url method:(NSString * _Nonnull)method requestBody:(NSString * _Nonnull)requestBody diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index dd18513163..e7ca15600e 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -298,7 +298,14 @@ - (dispatch_queue_t)methodQueue { startTime:(double)startTime duration:(double)duration gqlQueryName:(NSString * _Nullable)gqlQueryName - serverErrorMessage:(NSString * _Nullable)serverErrorMessage) { + serverErrorMessage:(NSString * _Nullable)serverErrorMessage + w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes){ + NSNumber *isW3cCaught = (w3cExternalTraceAttributes[@"isW3cHeaderFound"] != [NSNull null]) ? w3cExternalTraceAttributes[@"isW3cHeaderFound"] : nil; + NSNumber * partialID = (w3cExternalTraceAttributes[@"partialId"] != [NSNull null]) ? w3cExternalTraceAttributes[@"partialId"] : nil; + NSNumber * timestamp = (w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] != [NSNull null]) ? w3cExternalTraceAttributes[@"networkStartTimeInSeconds"] : nil; + NSString * generatedW3CTraceparent = (w3cExternalTraceAttributes[@"w3cGeneratedHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cGeneratedHeader"] : nil; + NSString * caughtW3CTraceparent = (w3cExternalTraceAttributes[@"w3cCaughtHeader"] != [NSNull null]) ? w3cExternalTraceAttributes[@"w3cCaughtHeader"] : nil; + [IBGNetworkLogger addNetworkLogWithUrl:url method:method requestBody:requestBody @@ -314,7 +321,13 @@ - (dispatch_queue_t)methodQueue { startTime:startTime * 1000 duration:duration * 1000 gqlQueryName:gqlQueryName - serverErrorMessage:serverErrorMessage]; + serverErrorMessage:serverErrorMessage + isW3cCaughted:isW3cCaught + partialID:partialID + timestamp:timestamp + generatedW3CTraceparent:generatedW3CTraceparent + caughtedW3CTraceparent:caughtW3CTraceparent + ]; } RCT_EXPORT_METHOD(addPrivateView: (nonnull NSNumber *)reactTag) { @@ -364,7 +377,7 @@ - (dispatch_queue_t)methodQueue { [featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key variant:variant]]; } } - + [Instabug addFeatureFlags:featureFlags]; } @@ -373,7 +386,7 @@ - (dispatch_queue_t)methodQueue { for(id item in featureFlags){ [features addObject:[[IBGFeatureFlag alloc] initWithName:item]]; } - + @try { [Instabug removeFeatureFlags:features]; } @@ -390,6 +403,17 @@ - (dispatch_queue_t)methodQueue { [Instabug willRedirectToAppStore]; } +RCT_EXPORT_METHOD(isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(IBGNetworkLogger.w3ExternalTraceIDEnabled)); +} +RCT_EXPORT_METHOD(isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(IBGNetworkLogger.w3ExternalGeneratedHeaderEnabled)); +} +RCT_EXPORT_METHOD(isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { + resolve(@(IBGNetworkLogger.w3CaughtHeaderEnabled)); +} + + - (NSDictionary *)constantsToExport { return ArgsRegistry.getAll; } diff --git a/ios/native.rb b/ios/native.rb index c5188a3a73..c46209b912 100644 --- a/ios/native.rb +++ b/ios/native.rb @@ -1,4 +1,4 @@ -$instabug = { :version => '13.3.0' } +$instabug = { :version => '13.4.0' } def use_instabug! (spec = nil) version = $instabug[:version] diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 29ff1d27c9..31645c152d 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -10,7 +10,8 @@ import type { NavigationAction, NavigationState as NavigationStateV4 } from 'rea import type { InstabugConfig } from '../models/InstabugConfig'; import Report from '../models/Report'; -import { NativeEvents, NativeInstabug, emitter } from '../native/NativeInstabug'; +import { emitter, NativeEvents, NativeInstabug } from '../native/NativeInstabug'; +import { registerW3CFlagsListener } from '../utils/FeatureFlags'; import { ColorTheme, Locale, @@ -67,6 +68,8 @@ export const init = (config: InstabugConfig) => { InstabugUtils.captureJsErrors(); captureUnhandledRejections(); + Platform.OS === 'android' && registerW3CFlagsListener(); + // Default networkInterceptionMode to JavaScript if (config.networkInterceptionMode == null) { config.networkInterceptionMode = NetworkInterceptionMode.javascript; @@ -640,3 +643,20 @@ export const componentDidAppearListener = (event: ComponentDidAppearEvent) => { _lastScreen = event.componentName; } }; + +/** + * Sets listener to W3ExternalTraceID flag changes + * @param handler A callback that gets the update value of the flag + */ +export const _registerW3CFlagsChangeListener = ( + handler: (payload: { + isW3ExternalTraceIDEnabled: boolean; + isW3ExternalGeneratedHeaderEnabled: boolean; + isW3CaughtHeaderEnabled: boolean; + }) => void, +) => { + emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANGE, (payload) => { + handler(payload); + }); + NativeInstabug.registerW3CFlagsChangeListener(); +}; diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index 21bc444f62..ce8e39bb77 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -244,75 +244,6 @@ export function reportNetworkLog(network: NetworkData) { } } -export function isContentTypeNotAllowed(contentType: string) { - const allowed = [ - 'application/protobuf', - 'application/json', - 'application/xml', - 'text/xml', - 'text/html', - 'text/plain', - ]; - - return allowed.every((type) => !contentType.includes(type)); -} - -export function reportNetworkLog(network: NetworkData) { - if (Platform.OS === 'android') { - const requestHeaders = JSON.stringify(network.requestHeaders); - const responseHeaders = JSON.stringify(network.responseHeaders); - - NativeInstabug.networkLogAndroid( - network.url, - network.requestBody, - network.responseBody, - network.method, - network.responseCode, - requestHeaders, - responseHeaders, - network.duration, - ); - - NativeAPM.networkLogAndroid( - network.startTime, - network.duration, - requestHeaders, - network.requestBody, - network.requestBodySize, - network.method, - network.url, - network.requestContentType, - responseHeaders, - network.responseBody, - network.responseBodySize, - network.responseCode, - network.contentType, - network.errorDomain, - network.gqlQueryName, - network.serverErrorMessage, - ); - } else { - NativeInstabug.networkLogIOS( - network.url, - network.method, - network.requestBody, - network.requestBodySize, - network.responseBody, - network.responseBodySize, - network.responseCode, - network.requestHeaders, - network.responseHeaders, - network.contentType, - network.errorDomain, - network.errorCode, - network.startTime, - network.duration, - network.gqlQueryName, - network.serverErrorMessage, - ); - } -} - export default { parseErrorStack, captureJsErrors, diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index 5139afcde3..7b3cf2e695 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -69,6 +69,10 @@ const mockInstabug: InstabugNativeModule = { addFileAttachmentWithDataToReport: jest.fn(), setNetworkLoggingEnabled: jest.fn(), willRedirectToStore: jest.fn(), + isW3ExternalTraceIDEnabled: jest.fn(), + isW3ExternalGeneratedHeaderEnabled: jest.fn(), + isW3CaughtHeaderEnabled: jest.fn(), + registerW3CFlagsChangeListener: jest.fn(), }; export default mockInstabug; diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index fdc1b91b24..ae02a8916d 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -863,4 +863,20 @@ describe('Instabug Module', () => { Instabug.willRedirectToStore(); expect(NativeInstabug.willRedirectToStore).toBeCalledTimes(1); }); + + it('should register W3C flag listener', async () => { + const callback = jest.fn(); + Instabug._registerW3CFlagsChangeListener(callback); + + expect(NativeInstabug.registerW3CFlagsChangeListener).toBeCalledTimes(1); + }); + + it('should invoke callback on emitting the event IBGOnNewW3CFlagsUpdateReceivedCallback', () => { + const callback = jest.fn(); + Instabug._registerW3CFlagsChangeListener(callback); + emitter.emit(NativeEvents.ON_W3C_FLAGS_CHANGE); + + expect(emitter.listenerCount(NativeEvents.ON_W3C_FLAGS_CHANGE)).toBe(1); + expect(callback).toHaveBeenCalled(); + }); }); diff --git a/test/modules/NetworkLogger.spec.ts b/test/modules/NetworkLogger.spec.ts index 71dd2dd778..be258d7403 100644 --- a/test/modules/NetworkLogger.spec.ts +++ b/test/modules/NetworkLogger.spec.ts @@ -30,6 +30,11 @@ describe('NetworkLogger Module', () => { startTime: 0, serverErrorMessage: '', requestContentType: 'application/json', + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, }; beforeEach(() => { diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index becfccc0e9..0267e52956 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -258,6 +258,11 @@ describe('reportNetworkLog', () => { errorDomain: 'errorDomain', serverErrorMessage: 'serverErrorMessage', requestContentType: 'requestContentType', + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, }; it('reportNetworkLog should send network logs to native with the correct parameters on Android', () => { From 51d03028286162c2b07e9d2fd92538bbcf870dd8 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 16 Sep 2024 16:25:21 +0300 Subject: [PATCH 088/104] fix: merge issues --- test/utils/InstabugUtils.spec.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index 0267e52956..9e1a97242f 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -303,6 +303,13 @@ describe('reportNetworkLog', () => { network.errorDomain, network.gqlQueryName, network.serverErrorMessage, + { + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, + }, ); }); @@ -329,6 +336,13 @@ describe('reportNetworkLog', () => { network.duration, network.gqlQueryName, network.serverErrorMessage, + { + isW3cHeaderFound: null, + partialId: null, + networkStartTimeInSeconds: null, + w3cGeneratedHeader: null, + w3cCaughtHeader: null, + }, ); }); }); From 7ca2f154061b78a0254affd42f8caea094fa7bd4 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 16 Sep 2024 16:31:14 +0300 Subject: [PATCH 089/104] fix: merge issues --- src/utils/XhrNetworkInterceptor.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 26deeb37a9..0cf87adf55 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -99,10 +99,6 @@ export const injectHeaders = async ( isW3cCaughtHeaderEnabled, } = featureFlags; - console.log('isW3cExternalTraceIDEnabled', isW3cCaughtHeaderEnabled); - console.log('isW3cCaughtHeaderEnabled', isW3cCaughtHeaderEnabled); - console.log('isW3cExternalGeneratedHeaderEnabled', isW3cExternalGeneratedHeaderEnabled); - if (!isW3cExternalTraceIDEnabled) { return; } From 2d25cdac0db4189df7364d5a767faa00da091580 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 16 Sep 2024 16:47:21 +0300 Subject: [PATCH 090/104] fix: merge issues --- .../ios/InstabugTests/InstabugSampleTests.m | 51 +++---------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index fbb1a5d59f..8744ce4eb8 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -354,7 +354,7 @@ - (void)testNetworkLogIOS { duration:duration gqlQueryName:gqlQueryName serverErrorMessage:serverErrorMessage - w3cExternalTraceAttributes:nil + w3cExternalTraceAttributes:w3cExternalTraceAttributes ]; @@ -374,11 +374,11 @@ - (void)testNetworkLogIOS { duration:duration * 1000 gqlQueryName:gqlQueryName serverErrorMessage:serverErrorMessage - isW3cCaughted:nil - partialID:nil - timestamp:nil - generatedW3CTraceparent:nil - caughtedW3CTraceparent:nil + isW3cCaughted:isW3cCaughted + partialID:partialID + timestamp:timestamp + generatedW3CTraceparent:generatedW3CTraceparent + caughtedW3CTraceparent:caughtedW3CTraceparent ]); } @@ -609,43 +609,4 @@ - (void) testIsW3CaughtHeaderEnabled { } -- (void)testAddFeatureFlags { - id mock = OCMClassMock([Instabug class]); - NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"}; - - OCMStub([mock addFeatureFlags :[OCMArg any]]); - [self.instabugBridge addFeatureFlags:featureFlagsMap]; - OCMVerify([mock addFeatureFlags: [OCMArg checkWithBlock:^(id value) { - NSArray *featureFlags = value; - NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name; - NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ; - if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ - return YES; - } - return NO; - }]]); -} - -- (void)testRemoveFeatureFlags { - id mock = OCMClassMock([Instabug class]); - NSArray *featureFlags = @[@"exp1", @"exp2"]; - [self.instabugBridge removeFeatureFlags:featureFlags]; - OCMVerify([mock removeFeatureFlags: [OCMArg checkWithBlock:^(id value) { - NSArray *featureFlagsObJ = value; - NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name; - NSString* firstFeatureFlagKey = [featureFlags firstObject] ; - if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){ - return YES; - } - return NO; - }]]); -} - -- (void)testRemoveAllFeatureFlags { - id mock = OCMClassMock([Instabug class]); - OCMStub([mock removeAllFeatureFlags]); - [self.instabugBridge removeAllFeatureFlags]; - OCMVerify([mock removeAllFeatureFlags]); -} - @end From 0ff5cbaf5c36b3526ddc27e1425b239e4d99b3a8 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 16 Sep 2024 17:45:17 +0300 Subject: [PATCH 091/104] fix: remove logs --- src/utils/XhrNetworkInterceptor.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 0cf87adf55..c7cb096b4a 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -107,10 +107,6 @@ export const injectHeaders = async ( networkData.isW3cHeaderFound = isHeaderFound; - console.log('isW3cExternalTraceIDEnabled', isW3cCaughtHeaderEnabled); - console.log('isW3cCaughtHeaderEnabled', isW3cCaughtHeaderEnabled); - console.log('isW3cExternalGeneratedHeaderEnabled', isW3cExternalGeneratedHeaderEnabled); - const injectionMethodology = isHeaderFound ? identifyCaughtHeader(networkData, isW3cCaughtHeaderEnabled) : injectGeneratedData(networkData, isW3cExternalGeneratedHeaderEnabled); From 9f816f1b5b026037550f47c2758df99e5760a84f Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 16 Sep 2024 17:51:48 +0300 Subject: [PATCH 092/104] fix: refactore networkLogAndroid arguments --- .../java/com/instabug/reactlibrary/RNInstabugAPMModule.java | 6 ++---- src/native/NativeAPM.ts | 2 +- src/utils/InstabugUtils.ts | 4 ++-- test/utils/InstabugUtils.spec.ts | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 84706e94dc..7a73e1f649 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -329,10 +329,9 @@ private void networkLogAndroid(final double requestStartTime, final double statusCode, final String responseContentType, @Nullable final String errorDomain, + @Nullable final ReadableMap w3cAttributes, @Nullable final String gqlQueryName, - @Nullable final String serverErrorMessage, - @Nullable final ReadableMap w3cAttributes - + @Nullable final String serverErrorMessage ) { try { APMNetworkLogger networkLogger = new APMNetworkLogger(); @@ -387,7 +386,6 @@ private void networkLogAndroid(final double requestStartTime, gqlQueryName, serverErrorMessage, w3cExternalTraceAttributes - ); } else { Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection"); diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 48da26a36e..7f9ea4e1a9 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -24,9 +24,9 @@ export interface ApmNativeModule extends NativeModule { statusCode: number, responseContentType: string, errorDomain: string, + w3cExternalTraceAttributes: W3cExternalTraceAttributes, gqlQueryName?: string, serverErrorMessage?: string, - w3cExternalTraceAttributes?: W3cExternalTraceAttributes, ): void; // App Launches APIs // diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index ce8e39bb77..d7ccd2ee44 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -205,8 +205,6 @@ export function reportNetworkLog(network: NetworkData) { network.responseCode, network.contentType, network.errorDomain, - network.gqlQueryName, - network.serverErrorMessage, { isW3cHeaderFound: network.isW3cHeaderFound, partialId: network.partialId, @@ -214,6 +212,8 @@ export function reportNetworkLog(network: NetworkData) { w3cGeneratedHeader: network.w3cGeneratedHeader, w3cCaughtHeader: network.w3cCaughtHeader, }, + network.gqlQueryName, + network.serverErrorMessage, ); } else { NativeInstabug.networkLogIOS( diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index 9e1a97242f..fd389d7f0b 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -301,8 +301,6 @@ describe('reportNetworkLog', () => { network.responseCode, network.contentType, network.errorDomain, - network.gqlQueryName, - network.serverErrorMessage, { isW3cHeaderFound: null, partialId: null, @@ -310,6 +308,8 @@ describe('reportNetworkLog', () => { w3cGeneratedHeader: null, w3cCaughtHeader: null, }, + network.gqlQueryName, + network.serverErrorMessage, ); }); From c1160e58624243f7e952d43e8653dfd0f420924a Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Tue, 17 Sep 2024 15:44:32 +0300 Subject: [PATCH 093/104] fix: merge issues --- examples/default/e2e/reportBug.e2e.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/default/e2e/reportBug.e2e.ts b/examples/default/e2e/reportBug.e2e.ts index 08757b7884..9ecc753818 100644 --- a/examples/default/e2e/reportBug.e2e.ts +++ b/examples/default/e2e/reportBug.e2e.ts @@ -13,8 +13,9 @@ it('reports a bug', async () => { const floatingButton = getElement('floatingButton'); await waitFor(floatingButton).toBeVisible().withTimeout(30000); await floatingButton.tap(); - - await getElement('reportBugMenuItem').tap(); + const reportBugMenuItemButton = getElement('reportBugMenuItem'); + await waitFor(reportBugMenuItemButton).toBeVisible().withTimeout(30000); + await reportBugMenuItemButton.tap(); await getElement('emailField').typeText(mockData.email); await getElement('commentField').typeText(mockData.bugComment); From 71ee382860e16f7aa30a2dfc034c95490330fed4 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Tue, 17 Sep 2024 16:24:21 +0300 Subject: [PATCH 094/104] fix: merge issues --- .../default/ios/InstabugTests/InstabugCrashReportingTests.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m b/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m index 0d5ac73482..64aa48b7f7 100644 --- a/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m +++ b/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m @@ -19,11 +19,13 @@ - (void)setUp { } - (void)testSetEnabled { + + [self.bridge setEnabled:NO]; + XCTAssertFalse(IBGCrashReporting.enabled); + [self.bridge setEnabled:YES]; XCTAssertTrue(IBGCrashReporting.enabled); - [self.bridge setEnabled:NO]; - XCTAssertFalse(IBGCrashReporting.enabled); } - (void)testSendNonFatalErrorJsonCrash { From a8c50a7c7807fcc63dd2f9c2965360562f8a5c73 Mon Sep 17 00:00:00 2001 From: kholood Date: Tue, 17 Sep 2024 18:13:56 +0300 Subject: [PATCH 095/104] fix: move W3cExternalTraceAttributes to models --- src/models/W3cExternalTraceAttributes.ts | 22 ++++++++++++++++++++++ src/native/NativeAPM.ts | 2 +- src/native/NativeInstabug.ts | 2 +- src/utils/Types.ts | 7 ------- 4 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 src/models/W3cExternalTraceAttributes.ts delete mode 100644 src/utils/Types.ts diff --git a/src/models/W3cExternalTraceAttributes.ts b/src/models/W3cExternalTraceAttributes.ts new file mode 100644 index 0000000000..f4e7ab6a45 --- /dev/null +++ b/src/models/W3cExternalTraceAttributes.ts @@ -0,0 +1,22 @@ +export type W3cExternalTraceAttributes = { + /** + * A key that determines if the traceparent header was found + */ + isW3cHeaderFound: boolean | null; + /** + * A unique identifier for the trace generated by the SDK in case of no cought header found + */ + partialId: number | null; + /** + * The start time of the network request + */ + networkStartTimeInSeconds: number | null; + /** + * The traceparent header generated by the SDK + */ + w3cGeneratedHeader: string | null; + /** + * The traceparent header received by the server + */ + w3cCaughtHeader: string | null; +}; diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 7f9ea4e1a9..9fa30b702c 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -1,7 +1,7 @@ import type { NativeModule } from 'react-native'; import { NativeEventEmitter } from 'react-native'; -import type { W3cExternalTraceAttributes } from '../utils/Types'; +import type { W3cExternalTraceAttributes } from '../models/W3cExternalTraceAttributes'; import { NativeModules } from './NativePackage'; export interface ApmNativeModule extends NativeModule { diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index ef5fd2f25b..5f0628ef71 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -11,7 +11,7 @@ import type { WelcomeMessageMode, } from '../utils/Enums'; import type { NativeConstants } from './NativeConstants'; -import type { W3cExternalTraceAttributes } from '../utils/Types'; +import type { W3cExternalTraceAttributes } from '../models/W3cExternalTraceAttributes'; import { NativeModules } from './NativePackage'; export interface InstabugNativeModule extends NativeModule { diff --git a/src/utils/Types.ts b/src/utils/Types.ts deleted file mode 100644 index b54384d592..0000000000 --- a/src/utils/Types.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type W3cExternalTraceAttributes = { - isW3cHeaderFound: boolean | null; - partialId: number | null; - networkStartTimeInSeconds: number | null; - w3cGeneratedHeader: string | null; - w3cCaughtHeader: string | null; -}; From dadcfe4f6e6ff7a183055d8180152cbd4bc6c1ed Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 18 Sep 2024 12:28:42 +0300 Subject: [PATCH 096/104] fix: return expected value type from bridge --- .../com/instabug/reactlibrary/RNInstabugReactnativeModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 2a9b5474a3..6b83151948 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -1202,7 +1202,7 @@ public void run() { } catch (Exception e) { e.printStackTrace(); - promise.resolve(null); + promise.resolve(false); } } From 34ff4b488f2d69111b3c8943ed7836384ddf4265 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 18 Sep 2024 12:29:19 +0300 Subject: [PATCH 097/104] fix: refactor method call --- src/modules/Instabug.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 31645c152d..0df4d3145e 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -68,7 +68,9 @@ export const init = (config: InstabugConfig) => { InstabugUtils.captureJsErrors(); captureUnhandledRejections(); - Platform.OS === 'android' && registerW3CFlagsListener(); + if (Platform.OS === 'android') { + registerW3CFlagsListener(); + } // Default networkInterceptionMode to JavaScript if (config.networkInterceptionMode == null) { From 8590e9414a27090ea063ad39c92afca774c6f9d2 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 18 Sep 2024 12:35:03 +0300 Subject: [PATCH 098/104] fix: refactor method name --- src/utils/XhrNetworkInterceptor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index c7cb096b4a..4443940362 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -67,7 +67,7 @@ const _reset = () => { w3cCaughtHeader: null, }; }; -const getFeatureFlags = async (networkData: NetworkData) => { +const getTraceparentHeader = async (networkData: NetworkData) => { const [ isW3cExternalTraceIDEnabled, isW3cExternalGeneratedHeaderEnabled, @@ -310,7 +310,7 @@ export default { } cloneNetwork.startTime = Date.now(); - const traceparent = await getFeatureFlags(cloneNetwork); + const traceparent = await getTraceparentHeader(cloneNetwork); if (traceparent) { this.setRequestHeader('Traceparent', traceparent); } From c9a30e7df702c90cf5ef6e06c1f6c288079ba638 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 18 Sep 2024 14:02:11 +0300 Subject: [PATCH 099/104] fix: return expected value types of w3c flags --- .../instabug/reactlibrary/RNInstabugReactnativeModule.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 6b83151948..9c901cb7a5 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -1225,7 +1225,7 @@ public void run() { } catch (Exception e) { e.printStackTrace(); - promise.resolve(null); + promise.resolve(false); } } @@ -1247,7 +1247,7 @@ public void run() { } catch (Exception e) { e.printStackTrace(); - promise.resolve(null); + promise.resolve(false); } } From b24213e1ec98547fcea7383f1e1c0f768e15fd99 Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 18 Sep 2024 14:13:22 +0300 Subject: [PATCH 100/104] chore: refactor constant names --- src/utils/InstabugUtils.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index d7ccd2ee44..df19f0d42a 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -149,15 +149,19 @@ export const generateTracePartialId = () => { export const generateW3CHeader = (networkStartTime: number) => { const { hexStringPartialId, numberPartilId } = generateTracePartialId(); + const TRACESTATE = '4942472d'; + const VERSION = '00'; + const TRACE_FLAG = '01'; + const timestampInSeconds = Math.floor(networkStartTime.valueOf() / 1000); const hexaDigitsTimestamp = timestampInSeconds.toString(16).toLowerCase(); const traceId = `${hexaDigitsTimestamp}${hexStringPartialId}${hexaDigitsTimestamp}${hexStringPartialId}`; - const parentId = `4942472d${hexStringPartialId}`; + const parentId = `${TRACESTATE}${hexStringPartialId}`; return { timestampInSeconds, partialId: numberPartilId, - w3cHeader: `00-${traceId}-${parentId}-01`, + w3cHeader: `${VERSION}-${traceId}-${parentId}-${TRACE_FLAG}`, }; }; From 3a53200102fe0bc958a3704c40a2adfb0914b49b Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Mon, 18 Nov 2024 13:51:33 +0200 Subject: [PATCH 101/104] fix: pod file --- examples/default/ios/Podfile.lock | 2183 +++++++++++++++++++++++------ 1 file changed, 1747 insertions(+), 436 deletions(-) diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index c1e706171c..81ba100a5a 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -1,15 +1,8 @@ PODS: - - boost (1.76.0) + - boost (1.84.0) - DoubleConversion (1.1.6) - - FBLazyVector (0.72.3) - - FBReactNativeSpec (0.72.3): - - RCT-Folly (= 2021.07.22.00) - - RCTRequired (= 0.72.3) - - RCTTypeSafety (= 0.72.3) - - React-Core (= 0.72.3) - - React-jsi (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - fmt (6.2.1) + - FBLazyVector (0.75.4) + - fmt (9.1.0) - glog (0.3.5) - Google-Maps-iOS-Utils (4.2.2): - Google-Maps-iOS-Utils/Clustering (= 4.2.2) @@ -35,538 +28,1791 @@ PODS: - GoogleMaps/Base (7.4.0) - GoogleMaps/Maps (7.4.0): - GoogleMaps/Base - - hermes-engine (0.72.3): - - hermes-engine/Pre-built (= 0.72.3) - - hermes-engine/Pre-built (0.72.3) - - Instabug (13.4.0) + - hermes-engine (0.75.4): + - hermes-engine/Pre-built (= 0.75.4) + - hermes-engine/Pre-built (0.75.4) + - Instabug (14.0.0) - instabug-reactnative-ndk (0.1.0): - - RCT-Folly (= 2021.07.22.00) + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety - React-Core - - libevent (2.1.12) + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - OCMock (3.9.4) - - RCT-Folly (2021.07.22.00): + - RCT-Folly (2024.01.01.00): - boost - DoubleConversion - - fmt (~> 6.2.1) + - fmt (= 9.1.0) - glog - - RCT-Folly/Default (= 2021.07.22.00) - - RCT-Folly/Default (2021.07.22.00): + - RCT-Folly/Default (= 2024.01.01.00) + - RCT-Folly/Default (2024.01.01.00): - boost - DoubleConversion - - fmt (~> 6.2.1) + - fmt (= 9.1.0) - glog - - RCT-Folly/Futures (2021.07.22.00): + - RCT-Folly/Fabric (2024.01.01.00): - boost - DoubleConversion - - fmt (~> 6.2.1) - - glog - - libevent - - RCTRequired (0.72.3) - - RCTTypeSafety (0.72.3): - - FBLazyVector (= 0.72.3) - - RCTRequired (= 0.72.3) - - React-Core (= 0.72.3) - - React (0.72.3): - - React-Core (= 0.72.3) - - React-Core/DevSupport (= 0.72.3) - - React-Core/RCTWebSocket (= 0.72.3) - - React-RCTActionSheet (= 0.72.3) - - React-RCTAnimation (= 0.72.3) - - React-RCTBlob (= 0.72.3) - - React-RCTImage (= 0.72.3) - - React-RCTLinking (= 0.72.3) - - React-RCTNetwork (= 0.72.3) - - React-RCTSettings (= 0.72.3) - - React-RCTText (= 0.72.3) - - React-RCTVibration (= 0.72.3) - - React-callinvoker (0.72.3) - - React-Codegen (0.72.3): - - DoubleConversion - - FBReactNativeSpec + - fmt (= 9.1.0) + - glog + - RCTDeprecation (0.75.4) + - RCTRequired (0.75.4) + - RCTTypeSafety (0.75.4): + - FBLazyVector (= 0.75.4) + - RCTRequired (= 0.75.4) + - React-Core (= 0.75.4) + - React (0.75.4): + - React-Core (= 0.75.4) + - React-Core/DevSupport (= 0.75.4) + - React-Core/RCTWebSocket (= 0.75.4) + - React-RCTActionSheet (= 0.75.4) + - React-RCTAnimation (= 0.75.4) + - React-RCTBlob (= 0.75.4) + - React-RCTImage (= 0.75.4) + - React-RCTLinking (= 0.75.4) + - React-RCTNetwork (= 0.75.4) + - React-RCTSettings (= 0.75.4) + - React-RCTText (= 0.75.4) + - React-RCTVibration (= 0.75.4) + - React-callinvoker (0.75.4) + - React-Core (0.75.4): - glog - hermes-engine - - RCT-Folly - - RCTRequired - - RCTTypeSafety - - React-Core + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default (= 0.75.4) + - React-cxxreact + - React-featureflags + - React-hermes - React-jsi - React-jsiexecutor - - React-NativeModulesApple - - React-rncore - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - React-Core (0.72.3): + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/CoreModulesHeaders (0.75.4): - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.72.3) + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default - React-cxxreact + - React-featureflags - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/Default (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/DevSupport (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default (= 0.75.4) + - React-Core/RCTWebSocket (= 0.75.4) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler - React-utils - - SocketRocket (= 0.6.1) + - SocketRocket (= 0.7.0) - Yoga - - React-Core/CoreModulesHeaders (0.72.3): + - React-Core/RCTActionSheetHeaders (0.75.4): - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation - React-Core/Default - React-cxxreact + - React-featureflags - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTAnimationHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTBlobHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTImageHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTLinkingHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTNetworkHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTSettingsHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTTextHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTVibrationHeaders (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-Core/RCTWebSocket (0.75.4): + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTDeprecation + - React-Core/Default (= 0.75.4) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.0) + - Yoga + - React-CoreModules (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - RCT-Folly (= 2024.01.01.00) + - RCTTypeSafety (= 0.75.4) + - React-Core/CoreModulesHeaders (= 0.75.4) + - React-jsi (= 0.75.4) + - React-jsinspector + - React-NativeModulesApple + - React-RCTBlob + - React-RCTImage (= 0.75.4) + - ReactCodegen + - ReactCommon + - SocketRocket (= 0.7.0) + - React-cxxreact (0.75.4): + - boost + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - React-callinvoker (= 0.75.4) + - React-debug (= 0.75.4) + - React-jsi (= 0.75.4) + - React-jsinspector + - React-logger (= 0.75.4) + - React-perflogger (= 0.75.4) + - React-runtimeexecutor (= 0.75.4) + - React-debug (0.75.4) + - React-defaultsnativemodule (0.75.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-domnativemodule + - React-Fabric + - React-featureflags + - React-featureflagsnativemodule + - React-graphics + - React-idlecallbacksnativemodule + - React-ImageManager + - React-microtasksnativemodule + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - React-domnativemodule (0.75.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-FabricComponents + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug - React-utils - - SocketRocket (= 0.6.1) + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core - Yoga - - React-Core/Default (0.72.3): + - React-Fabric (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/animations (= 0.75.4) + - React-Fabric/attributedstring (= 0.75.4) + - React-Fabric/componentregistry (= 0.75.4) + - React-Fabric/componentregistrynative (= 0.75.4) + - React-Fabric/components (= 0.75.4) + - React-Fabric/core (= 0.75.4) + - React-Fabric/dom (= 0.75.4) + - React-Fabric/imagemanager (= 0.75.4) + - React-Fabric/leakchecker (= 0.75.4) + - React-Fabric/mounting (= 0.75.4) + - React-Fabric/observers (= 0.75.4) + - React-Fabric/scheduler (= 0.75.4) + - React-Fabric/telemetry (= 0.75.4) + - React-Fabric/templateprocessor (= 0.75.4) + - React-Fabric/uimanager (= 0.75.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/animations (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/attributedstring (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/componentregistry (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/componentregistrynative (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/components/legacyviewmanagerinterop (= 0.75.4) + - React-Fabric/components/root (= 0.75.4) + - React-Fabric/components/view (= 0.75.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components/legacyviewmanagerinterop (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components/root (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components/view (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-Fabric/core (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/dom (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/imagemanager (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/leakchecker (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/mounting (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/observers (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events (= 0.75.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/observers/events (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/scheduler (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-performancetimeline + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/telemetry (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/templateprocessor (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/uimanager (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/uimanager/consistency (= 0.75.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/uimanager/consistency (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-FabricComponents (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components (= 0.75.4) + - React-FabricComponents/textlayoutmanager (= 0.75.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components/inputaccessory (= 0.75.4) + - React-FabricComponents/components/iostextinput (= 0.75.4) + - React-FabricComponents/components/modal (= 0.75.4) + - React-FabricComponents/components/rncore (= 0.75.4) + - React-FabricComponents/components/safeareaview (= 0.75.4) + - React-FabricComponents/components/scrollview (= 0.75.4) + - React-FabricComponents/components/text (= 0.75.4) + - React-FabricComponents/components/textinput (= 0.75.4) + - React-FabricComponents/components/unimplementedview (= 0.75.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/inputaccessory (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/iostextinput (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/modal (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/rncore (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/safeareaview (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/scrollview (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/text (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/textinput (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/unimplementedview (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/textlayoutmanager (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/core + - Yoga + - React-FabricImage (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.01.01.00) + - RCTRequired (= 0.75.4) + - RCTTypeSafety (= 0.75.4) + - React-Fabric + - React-graphics + - React-ImageManager + - React-jsi + - React-jsiexecutor (= 0.75.4) + - React-logger + - React-rendererdebug + - React-utils + - ReactCommon + - Yoga + - React-featureflags (0.75.4) + - React-featureflagsnativemodule (0.75.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - React-graphics (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - RCT-Folly/Fabric (= 2024.01.01.00) + - React-jsi + - React-jsiexecutor + - React-utils + - React-hermes (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - React-cxxreact (= 0.75.4) + - React-jsi + - React-jsiexecutor (= 0.75.4) + - React-jsinspector + - React-perflogger (= 0.75.4) + - React-runtimeexecutor + - React-idlecallbacksnativemodule (0.75.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - React-ImageManager (0.75.4): + - glog + - RCT-Folly/Fabric + - React-Core/Default + - React-debug + - React-Fabric + - React-graphics + - React-rendererdebug + - React-utils + - React-jserrorhandler (0.75.4): + - RCT-Folly/Fabric (= 2024.01.01.00) + - React-debug + - React-jsi + - React-jsi (0.75.4): + - boost + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - React-jsiexecutor (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - React-cxxreact (= 0.75.4) + - React-jsi (= 0.75.4) + - React-jsinspector + - React-perflogger (= 0.75.4) + - React-jsinspector (0.75.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - React-featureflags + - React-jsi + - React-runtimeexecutor (= 0.75.4) + - React-jsitracing (0.75.4): + - React-jsi + - React-logger (0.75.4): + - glog + - React-Mapbuffer (0.75.4): + - glog + - React-debug + - React-microtasksnativemodule (0.75.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - react-native-background-timer (2.4.1): + - React-Core + - react-native-config (1.5.3): + - react-native-config/App (= 1.5.3) + - react-native-config/App (1.5.3): + - React-Core + - react-native-google-maps (1.10.3): + - Google-Maps-iOS-Utils (= 4.2.2) + - GoogleMaps (= 7.4.0) + - React-Core + - react-native-maps (1.10.3): + - React-Core + - react-native-safe-area-context (4.12.0): + - React-Core + - react-native-slider (4.5.5): + - DoubleConversion - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-cxxreact - - React-hermes - - React-jsi - - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug - React-utils - - SocketRocket (= 0.6.1) + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core - Yoga - - React-Core/DevSupport (0.72.3): + - React-nativeconfig (0.75.4) + - React-NativeModulesApple (0.75.4): - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.72.3) - - React-Core/RCTWebSocket (= 0.72.3) + - React-callinvoker + - React-Core - React-cxxreact - - React-hermes - React-jsi - - React-jsiexecutor - - React-jsinspector (= 0.72.3) - - React-perflogger + - React-jsinspector - React-runtimeexecutor - - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTActionSheetHeaders (0.72.3): - - glog - - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - React-perflogger (0.75.4) + - React-performancetimeline (0.75.4): + - RCT-Folly (= 2024.01.01.00) - React-cxxreact - - React-hermes + - React-RCTActionSheet (0.75.4): + - React-Core/RCTActionSheetHeaders (= 0.75.4) + - React-RCTAnimation (0.75.4): + - RCT-Folly (= 2024.01.01.00) + - RCTTypeSafety + - React-Core/RCTAnimationHeaders - React-jsi - - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor + - React-NativeModulesApple + - ReactCodegen + - ReactCommon + - React-RCTAppDelegate (0.75.4): + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-CoreModules + - React-debug + - React-defaultsnativemodule + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-nativeconfig + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-RCTNetwork + - React-rendererdebug + - React-RuntimeApple + - React-RuntimeCore + - React-RuntimeHermes + - React-runtimescheduler - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTAnimationHeaders (0.72.3): - - glog + - ReactCodegen + - ReactCommon + - React-RCTBlob (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default - - React-cxxreact - - React-hermes + - RCT-Folly (= 2024.01.01.00) + - React-Core/RCTBlobHeaders + - React-Core/RCTWebSocket - React-jsi - - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor - - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTBlobHeaders (0.72.3): + - React-jsinspector + - React-NativeModulesApple + - React-RCTNetwork + - ReactCodegen + - ReactCommon + - React-RCTFabric (0.75.4): - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default - - React-cxxreact - - React-hermes + - RCT-Folly/Fabric (= 2024.01.01.00) + - React-Core + - React-debug + - React-Fabric + - React-FabricComponents + - React-FabricImage + - React-featureflags + - React-graphics + - React-ImageManager - React-jsi - - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor + - React-jsinspector + - React-nativeconfig + - React-performancetimeline + - React-RCTImage + - React-RCTText + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler - React-utils - - SocketRocket (= 0.6.1) - Yoga - - React-Core/RCTImageHeaders (0.72.3): - - glog - - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default - - React-cxxreact - - React-hermes + - React-RCTImage (0.75.4): + - RCT-Folly (= 2024.01.01.00) + - RCTTypeSafety + - React-Core/RCTImageHeaders - React-jsi - - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor - - React-utils - - SocketRocket (= 0.6.1) + - React-NativeModulesApple + - React-RCTNetwork + - ReactCodegen + - ReactCommon + - React-RCTLinking (0.75.4): + - React-Core/RCTLinkingHeaders (= 0.75.4) + - React-jsi (= 0.75.4) + - React-NativeModulesApple + - ReactCodegen + - ReactCommon + - ReactCommon/turbomodule/core (= 0.75.4) + - React-RCTNetwork (0.75.4): + - RCT-Folly (= 2024.01.01.00) + - RCTTypeSafety + - React-Core/RCTNetworkHeaders + - React-jsi + - React-NativeModulesApple + - ReactCodegen + - ReactCommon + - React-RCTSettings (0.75.4): + - RCT-Folly (= 2024.01.01.00) + - RCTTypeSafety + - React-Core/RCTSettingsHeaders + - React-jsi + - React-NativeModulesApple + - ReactCodegen + - ReactCommon + - React-RCTText (0.75.4): + - React-Core/RCTTextHeaders (= 0.75.4) - Yoga - - React-Core/RCTLinkingHeaders (0.72.3): - - glog + - React-RCTVibration (0.75.4): + - RCT-Folly (= 2024.01.01.00) + - React-Core/RCTVibrationHeaders + - React-jsi + - React-NativeModulesApple + - ReactCodegen + - ReactCommon + - React-rendererconsistency (0.75.4) + - React-rendererdebug (0.75.4): + - DoubleConversion + - fmt (= 9.1.0) + - RCT-Folly (= 2024.01.01.00) + - React-debug + - React-rncore (0.75.4) + - React-RuntimeApple (0.75.4): - hermes-engine - - RCT-Folly (= 2021.07.22.00) + - RCT-Folly/Fabric (= 2024.01.01.00) + - React-callinvoker - React-Core/Default + - React-CoreModules - React-cxxreact - - React-hermes + - React-jserrorhandler - React-jsi - React-jsiexecutor - - React-perflogger + - React-jsinspector + - React-Mapbuffer + - React-NativeModulesApple + - React-RCTFabric + - React-RuntimeCore - React-runtimeexecutor + - React-RuntimeHermes + - React-runtimescheduler - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTNetworkHeaders (0.72.3): + - React-RuntimeCore (0.75.4): - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default + - RCT-Folly/Fabric (= 2024.01.01.00) - React-cxxreact - - React-hermes + - React-featureflags + - React-jserrorhandler - React-jsi - React-jsiexecutor - - React-perflogger + - React-jsinspector - React-runtimeexecutor + - React-runtimescheduler - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTSettingsHeaders (0.72.3): - - glog + - React-runtimeexecutor (0.75.4): + - React-jsi (= 0.75.4) + - React-RuntimeHermes (0.75.4): - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default - - React-cxxreact + - RCT-Folly/Fabric (= 2024.01.01.00) + - React-featureflags - React-hermes - React-jsi - - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor + - React-jsinspector + - React-jsitracing + - React-nativeconfig + - React-RuntimeCore - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTTextHeaders (0.72.3): + - React-runtimescheduler (0.75.4): - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default + - RCT-Folly (= 2024.01.01.00) + - React-callinvoker - React-cxxreact - - React-hermes + - React-debug + - React-featureflags - React-jsi - - React-jsiexecutor - - React-perflogger + - React-rendererconsistency + - React-rendererdebug - React-runtimeexecutor - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTVibrationHeaders (0.72.3): + - React-utils (0.75.4): - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default - - React-cxxreact - - React-hermes - - React-jsi - - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor - - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-Core/RCTWebSocket (0.72.3): + - RCT-Folly (= 2024.01.01.00) + - React-debug + - React-jsi (= 0.75.4) + - ReactCodegen (0.75.4): + - DoubleConversion - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.72.3) - - React-cxxreact - - React-hermes + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-FabricImage + - React-featureflags + - React-graphics - React-jsi - React-jsiexecutor - - React-perflogger - - React-runtimeexecutor + - React-NativeModulesApple + - React-rendererdebug - React-utils - - SocketRocket (= 0.6.1) - - Yoga - - React-CoreModules (0.72.3): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.72.3) - - React-Codegen (= 0.72.3) - - React-Core/CoreModulesHeaders (= 0.72.3) - - React-jsi (= 0.72.3) - - React-RCTBlob - - React-RCTImage (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - SocketRocket (= 0.6.1) - - React-cxxreact (0.72.3): - - boost (= 1.76.0) + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - ReactCommon (0.75.4): + - ReactCommon/turbomodule (= 0.75.4) + - ReactCommon/turbomodule (0.75.4): - DoubleConversion + - fmt (= 9.1.0) - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.72.3) - - React-debug (= 0.72.3) - - React-jsi (= 0.72.3) - - React-jsinspector (= 0.72.3) - - React-logger (= 0.72.3) - - React-perflogger (= 0.72.3) - - React-runtimeexecutor (= 0.72.3) - - React-debug (0.72.3) - - React-hermes (0.72.3): + - RCT-Folly (= 2024.01.01.00) + - React-callinvoker (= 0.75.4) + - React-cxxreact (= 0.75.4) + - React-jsi (= 0.75.4) + - React-logger (= 0.75.4) + - React-perflogger (= 0.75.4) + - ReactCommon/turbomodule/bridging (= 0.75.4) + - ReactCommon/turbomodule/core (= 0.75.4) + - ReactCommon/turbomodule/bridging (0.75.4): - DoubleConversion + - fmt (= 9.1.0) - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - RCT-Folly/Futures (= 2021.07.22.00) - - React-cxxreact (= 0.72.3) - - React-jsi - - React-jsiexecutor (= 0.72.3) - - React-jsinspector (= 0.72.3) - - React-perflogger (= 0.72.3) - - React-jsi (0.72.3): - - boost (= 1.76.0) + - RCT-Folly (= 2024.01.01.00) + - React-callinvoker (= 0.75.4) + - React-cxxreact (= 0.75.4) + - React-jsi (= 0.75.4) + - React-logger (= 0.75.4) + - React-perflogger (= 0.75.4) + - ReactCommon/turbomodule/core (0.75.4): - DoubleConversion + - fmt (= 9.1.0) - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-jsiexecutor (0.72.3): + - RCT-Folly (= 2024.01.01.00) + - React-callinvoker (= 0.75.4) + - React-cxxreact (= 0.75.4) + - React-debug (= 0.75.4) + - React-featureflags (= 0.75.4) + - React-jsi (= 0.75.4) + - React-logger (= 0.75.4) + - React-perflogger (= 0.75.4) + - React-utils (= 0.75.4) + - RNCClipboard (1.14.3): + - React-Core + - RNGestureHandler (2.20.2): - DoubleConversion - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.72.3) - - React-jsi (= 0.72.3) - - React-perflogger (= 0.72.3) - - React-jsinspector (0.72.3) - - React-logger (0.72.3): - - glog - - react-native-background-timer (2.4.1): - - React-Core - - react-native-config (1.5.1): - - react-native-config/App (= 1.5.1) - - react-native-config/App (1.5.1): - - React-Core - - react-native-google-maps (1.10.3): - - Google-Maps-iOS-Utils (= 4.2.2) - - GoogleMaps (= 7.4.0) - - React-Core - - react-native-maps (1.10.3): - - React-Core - - react-native-safe-area-context (4.7.1): + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety - React-Core - - react-native-slider (4.4.3): + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNInstabug (14.0.0): + - Instabug (= 14.0.0) - React-Core - - React-NativeModulesApple (0.72.3): + - RNReanimated (3.16.1): + - DoubleConversion + - glog - hermes-engine - - React-callinvoker + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety - React-Core - - React-cxxreact - - React-jsi - - React-runtimeexecutor + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-perflogger (0.72.3) - - React-RCTActionSheet (0.72.3): - - React-Core/RCTActionSheetHeaders (= 0.72.3) - - React-RCTAnimation (0.72.3): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.72.3) - - React-Codegen (= 0.72.3) - - React-Core/RCTAnimationHeaders (= 0.72.3) - - React-jsi (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - React-RCTAppDelegate (0.72.3): - - RCT-Folly + - RNReanimated/reanimated (= 3.16.1) + - RNReanimated/worklets (= 3.16.1) + - Yoga + - RNReanimated/reanimated (3.16.1): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) - RCTRequired - RCTTypeSafety - React-Core - - React-CoreModules - - React-hermes + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager - React-NativeModulesApple - - React-RCTImage - - React-RCTNetwork - - React-runtimescheduler + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-RCTBlob (0.72.3): - - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.72.3) - - React-Core/RCTBlobHeaders (= 0.72.3) - - React-Core/RCTWebSocket (= 0.72.3) - - React-jsi (= 0.72.3) - - React-RCTNetwork (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - React-RCTImage (0.72.3): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.72.3) - - React-Codegen (= 0.72.3) - - React-Core/RCTImageHeaders (= 0.72.3) - - React-jsi (= 0.72.3) - - React-RCTNetwork (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - React-RCTLinking (0.72.3): - - React-Codegen (= 0.72.3) - - React-Core/RCTLinkingHeaders (= 0.72.3) - - React-jsi (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - React-RCTNetwork (0.72.3): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.72.3) - - React-Codegen (= 0.72.3) - - React-Core/RCTNetworkHeaders (= 0.72.3) - - React-jsi (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - React-RCTSettings (0.72.3): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.72.3) - - React-Codegen (= 0.72.3) - - React-Core/RCTSettingsHeaders (= 0.72.3) - - React-jsi (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - React-RCTText (0.72.3): - - React-Core/RCTTextHeaders (= 0.72.3) - - React-RCTVibration (0.72.3): - - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.72.3) - - React-Core/RCTVibrationHeaders (= 0.72.3) - - React-jsi (= 0.72.3) - - ReactCommon/turbomodule/core (= 0.72.3) - - React-rncore (0.72.3) - - React-runtimeexecutor (0.72.3): - - React-jsi (= 0.72.3) - - React-runtimescheduler (0.72.3): - - glog - - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-callinvoker - - React-debug - - React-jsi - - React-runtimeexecutor - - React-utils (0.72.3): - - glog - - RCT-Folly (= 2021.07.22.00) - - React-debug - - ReactCommon/turbomodule/bridging (0.72.3): + - RNReanimated/reanimated/apple (= 3.16.1) + - Yoga + - RNReanimated/reanimated/apple (3.16.1): - DoubleConversion - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.72.3) - - React-cxxreact (= 0.72.3) - - React-jsi (= 0.72.3) - - React-logger (= 0.72.3) - - React-perflogger (= 0.72.3) - - ReactCommon/turbomodule/core (0.72.3): + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNReanimated/worklets (3.16.1): - DoubleConversion - glog - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.72.3) - - React-cxxreact (= 0.72.3) - - React-jsi (= 0.72.3) - - React-logger (= 0.72.3) - - React-perflogger (= 0.72.3) - - RNCClipboard (1.5.1): - - React-Core - - RNGestureHandler (2.13.4): - - RCT-Folly (= 2021.07.22.00) - - React-Core - - RNInstabug (13.3.0): - - Instabug (= 13.4.0) + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety - React-Core - - RNReanimated (3.5.4): + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNScreens (3.35.0): - DoubleConversion - - FBLazyVector - glog - hermes-engine - - RCT-Folly + - RCT-Folly (= 2024.01.01.00) - RCTRequired - RCTTypeSafety - - React-callinvoker - React-Core - - React-Core/DevSupport - - React-Core/RCTWebSocket - - React-CoreModules - - React-cxxreact - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-RCTActionSheet - - React-RCTAnimation - - React-RCTAppDelegate - - React-RCTBlob + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric - React-RCTImage - - React-RCTLinking - - React-RCTNetwork - - React-RCTSettings - - React-RCTText + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - RNScreens (3.24.0): + - RNSVG (15.8.0): - React-Core - - React-RCTImage - - RNSVG (13.10.0): - - React-Core - - RNVectorIcons (10.0.0): + - RNVectorIcons (10.2.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety - React-Core - - SocketRocket (0.6.1) - - Yoga (1.14.0) + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - SocketRocket (0.7.0) + - Yoga (0.0.0) DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) + - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - - libevent (~> 2.1.12) - OCMock - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) + - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) + - RCTRequired (from `../node_modules/react-native/Libraries/Required`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) - React (from `../node_modules/react-native/`) - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - - React-Codegen (from `build/generated/ios`) - React-Core (from `../node_modules/react-native/`) - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) + - React-defaultsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) + - React-domnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/dom`) + - React-Fabric (from `../node_modules/react-native/ReactCommon`) + - React-FabricComponents (from `../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../node_modules/react-native/ReactCommon/react/featureflags`) + - React-featureflagsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) + - React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`) - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) + - React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) + - React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`) - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) + - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) - react-native-background-timer (from `../node_modules/react-native-background-timer`) - react-native-config (from `../node_modules/react-native-config`) - react-native-google-maps (from `../node_modules/react-native-maps`) - react-native-maps (from `../node_modules/react-native-maps`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - "react-native-slider (from `../node_modules/@react-native-community/slider`)" + - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) + - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../node_modules/react-native/React`) - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) - React-RCTText (from `../node_modules/react-native/Libraries/Text`) - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) - React-rncore (from `../node_modules/react-native/ReactCommon`) + - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../node_modules/react-native/ReactCommon/react/runtime`) - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) + - ReactCodegen (from `build/generated/ios`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - - "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)" + - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNInstabug (from `../node_modules/instabug-reactnative`) - RNReanimated (from `../node_modules/react-native-reanimated`) @@ -577,11 +1823,9 @@ DEPENDENCIES: SPEC REPOS: trunk: - - fmt - Google-Maps-iOS-Utils - GoogleMaps - Instabug - - libevent - OCMock - SocketRocket @@ -592,27 +1836,27 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" FBLazyVector: :path: "../node_modules/react-native/Libraries/FBLazyVector" - FBReactNativeSpec: - :path: "../node_modules/react-native/React/FBReactNativeSpec" + fmt: + :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" glog: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" - :tag: hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77 + :tag: hermes-2024-08-15-RNv0.75.1-4b3bf912cc0f705b51b71ce1a5b8bd79b93a451b instabug-reactnative-ndk: :path: "../node_modules/instabug-reactnative-ndk" RCT-Folly: :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTDeprecation: + :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" RCTRequired: - :path: "../node_modules/react-native/Libraries/RCTRequired" + :path: "../node_modules/react-native/Libraries/Required" RCTTypeSafety: :path: "../node_modules/react-native/Libraries/TypeSafety" React: :path: "../node_modules/react-native/" React-callinvoker: :path: "../node_modules/react-native/ReactCommon/callinvoker" - React-Codegen: - :path: build/generated/ios React-Core: :path: "../node_modules/react-native/" React-CoreModules: @@ -621,16 +1865,44 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/cxxreact" React-debug: :path: "../node_modules/react-native/ReactCommon/react/debug" + React-defaultsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/defaults" + React-domnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/dom" + React-Fabric: + :path: "../node_modules/react-native/ReactCommon" + React-FabricComponents: + :path: "../node_modules/react-native/ReactCommon" + React-FabricImage: + :path: "../node_modules/react-native/ReactCommon" + React-featureflags: + :path: "../node_modules/react-native/ReactCommon/react/featureflags" + React-featureflagsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" + React-graphics: + :path: "../node_modules/react-native/ReactCommon/react/renderer/graphics" React-hermes: :path: "../node_modules/react-native/ReactCommon/hermes" + React-idlecallbacksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" + React-ImageManager: + :path: "../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + React-jserrorhandler: + :path: "../node_modules/react-native/ReactCommon/jserrorhandler" React-jsi: :path: "../node_modules/react-native/ReactCommon/jsi" React-jsiexecutor: :path: "../node_modules/react-native/ReactCommon/jsiexecutor" React-jsinspector: - :path: "../node_modules/react-native/ReactCommon/jsinspector" + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" + React-jsitracing: + :path: "../node_modules/react-native/ReactCommon/hermes/executor/" React-logger: :path: "../node_modules/react-native/ReactCommon/logger" + React-Mapbuffer: + :path: "../node_modules/react-native/ReactCommon" + React-microtasksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" react-native-background-timer: :path: "../node_modules/react-native-background-timer" react-native-config: @@ -643,10 +1915,14 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-safe-area-context" react-native-slider: :path: "../node_modules/@react-native-community/slider" + React-nativeconfig: + :path: "../node_modules/react-native/ReactCommon" React-NativeModulesApple: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-perflogger: :path: "../node_modules/react-native/ReactCommon/reactperflogger" + React-performancetimeline: + :path: "../node_modules/react-native/ReactCommon/react/performance/timeline" React-RCTActionSheet: :path: "../node_modules/react-native/Libraries/ActionSheetIOS" React-RCTAnimation: @@ -655,6 +1931,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/AppDelegate" React-RCTBlob: :path: "../node_modules/react-native/Libraries/Blob" + React-RCTFabric: + :path: "../node_modules/react-native/React" React-RCTImage: :path: "../node_modules/react-native/Libraries/Image" React-RCTLinking: @@ -667,18 +1945,30 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/Text" React-RCTVibration: :path: "../node_modules/react-native/Libraries/Vibration" + React-rendererconsistency: + :path: "../node_modules/react-native/ReactCommon/react/renderer/consistency" + React-rendererdebug: + :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" React-rncore: :path: "../node_modules/react-native/ReactCommon" + React-RuntimeApple: + :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + React-RuntimeCore: + :path: "../node_modules/react-native/ReactCommon/react/runtime" React-runtimeexecutor: :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + React-RuntimeHermes: + :path: "../node_modules/react-native/ReactCommon/react/runtime" React-runtimescheduler: :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" React-utils: :path: "../node_modules/react-native/ReactCommon/react/utils" + ReactCodegen: + :path: build/generated/ios ReactCommon: :path: "../node_modules/react-native/ReactCommon" RNCClipboard: - :path: "../node_modules/@react-native-community/clipboard" + :path: "../node_modules/@react-native-clipboard/clipboard" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNInstabug: @@ -695,67 +1985,88 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - boost: 7dcd2de282d72e344012f7d6564d024930a6a440 - DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 - FBLazyVector: 4cce221dd782d3ff7c4172167bba09d58af67ccb - FBReactNativeSpec: c6bd9e179757b3c0ecf815864fae8032377903ef - fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 - glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b + boost: 4cb898d0bf20404aab1850c656dcea009429d6c1 + DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 + FBLazyVector: 430e10366de01d1e3d57374500b1b150fe482e6d + fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 + glog: 69ef571f3de08433d766d614c73a9838a06bf7eb Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac - hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: 183aa1e038d01ddc000f06835f46a9ea1f6c992b - instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 - libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 + hermes-engine: ea92f60f37dba025e293cbe4b4a548fd26b610a0 + Instabug: a0beffc01658773e2fac549845782f8937707dc4 + instabug-reactnative-ndk: d765ac289d56e8896398d02760d9abf2562fc641 OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 - RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 - RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18 - RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3 - React: 13109005b5353095c052f26af37413340ccf7a5d - React-callinvoker: c8c87bce983aa499c13cb06d4447c025a35274d6 - React-Codegen: 712d523524d89d71f1cf7cc624854941be983c4d - React-Core: 688f88b7f3a3d30b4848036223f8b07102c687e5 - React-CoreModules: 63c063a3ade8fb3b1bec5fd9a50f17b0421558c6 - React-cxxreact: 37765b4975541105b2a3322a4b473417c158c869 - React-debug: 51f11ef8db14b47f24e71c42a4916d4192972156 - React-hermes: 935ae71fb3d7654e947beba8498835cd5e479707 - React-jsi: ec628dc7a15ffea969f237b0ea6d2fde212b19dd - React-jsiexecutor: 59d1eb03af7d30b7d66589c410f13151271e8006 - React-jsinspector: b511447170f561157547bc0bef3f169663860be7 - React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95 + RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740 + RCTDeprecation: 726d24248aeab6d7180dac71a936bbca6a994ed1 + RCTRequired: a94e7febda6db0345d207e854323c37e3a31d93b + RCTTypeSafety: 28e24a6e44f5cbf912c66dde6ab7e07d1059a205 + React: c2830fa483b0334bda284e46a8579ebbe0c5447e + React-callinvoker: 4aecde929540c26b841a4493f70ebf6016691eb8 + React-Core: 9c059899f00d46b5cec3ed79251f77d9c469553d + React-CoreModules: 9fac2d31803c0ed03e4ddaa17f1481714f8633a5 + React-cxxreact: a979810a3ca4045ceb09407a17563046a7f71494 + React-debug: 3d21f69d8def0656f8b8ec25c0f05954f4d862c5 + React-defaultsnativemodule: 2fa2bdb7bd03ff9764facc04aa8520ebf14febae + React-domnativemodule: 986e6fe7569e1383dce452a7b013b6c843a752df + React-Fabric: 3bc7be9e3a6b7581fc828dc2aa041e107fc8ffb8 + React-FabricComponents: 668e0cb02344c2942e4c8921a643648faa6dc364 + React-FabricImage: 3f44dd25a2b020ed5215d4438a1bb1f3461cd4f1 + React-featureflags: ee1abd6f71555604a36cda6476e3c502ca9a48e5 + React-featureflagsnativemodule: 7ccc0cd666c2a6257401dceb7920818ac2b42803 + React-graphics: d7dd9c8d75cad5af19e19911fa370f78f2febd96 + React-hermes: 2069b08e965e48b7f8aa2c0ca0a2f383349ed55d + React-idlecallbacksnativemodule: e211b2099b6dced97959cb58257bab2b2de4d7ef + React-ImageManager: ab7a7d17dd0ff1ef1d4e1e88197d1119da9957ce + React-jserrorhandler: d9e867bb83b868472f3f7601883f0403b3e3942d + React-jsi: d68f1d516e5120a510afe356647a6a1e1f98f2db + React-jsiexecutor: 6366a08a0fc01c9b65736f8deacd47c4a397912a + React-jsinspector: 0ac947411f0c73b34908800cc7a6a31d8f93e1a8 + React-jsitracing: 0e8c0aadb1fcec6b1e4f2a66ee3b0da80f0f8615 + React-logger: d79b704bf215af194f5213a6b7deec50ba8e6a9b + React-Mapbuffer: b982d5bba94a8bc073bda48f0d27c9b28417fae3 + React-microtasksnativemodule: 2b73e68f0462f3175f98782db08896f8501afd20 react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe - react-native-config: 86038147314e2e6d10ea9972022aa171e6b1d4d8 + react-native-config: 8f7283449bbb048902f4e764affbbf24504454af react-native-google-maps: 1bcc1f9f13f798fcf230db7fe476f3566d0bc0a3 react-native-maps: 72a8a903f8a1b53e2c777ba79102078ab502e0bf - react-native-safe-area-context: 9697629f7b2cda43cf52169bb7e0767d330648c2 - react-native-slider: 1cdd6ba29675df21f30544253bf7351d3c2d68c4 - React-NativeModulesApple: c57f3efe0df288a6532b726ad2d0322a9bf38472 - React-perflogger: 6bd153e776e6beed54c56b0847e1220a3ff92ba5 - React-RCTActionSheet: c0b62af44e610e69d9a2049a682f5dba4e9dff17 - React-RCTAnimation: f9bf9719258926aea9ecb8a2aa2595d3ff9a6022 - React-RCTAppDelegate: e5ac35d4dbd1fae7df3a62b47db04b6a8d151592 - React-RCTBlob: c4f1e69a6ef739aa42586b876d637dab4e3b5bed - React-RCTImage: e5798f01aba248416c02a506cf5e6dfcba827638 - React-RCTLinking: f5b6227c879e33206f34e68924c458f57bbb96d9 - React-RCTNetwork: d5554fbfac1c618da3c8fa29933108ea22837788 - React-RCTSettings: 189c71e3e6146ba59f4f7e2cbeb494cf2ad42afa - React-RCTText: 19425aea9d8b6ccae55a27916355b17ab577e56e - React-RCTVibration: 388ac0e1455420895d1ca2548401eed964b038a6 - React-rncore: 755a331dd67b74662108f2d66a384454bf8dc1a1 - React-runtimeexecutor: 369ae9bb3f83b65201c0c8f7d50b72280b5a1dbc - React-runtimescheduler: 837c1bebd2f84572db17698cd702ceaf585b0d9a - React-utils: bcb57da67eec2711f8b353f6e3d33bd8e4b2efa3 - ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 - RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 - RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: 98a04a3cf14303bc172a49079fee36c5158b1799 - RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 - RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 - RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 - RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9 - SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 - Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce + react-native-safe-area-context: 142fade490cbebbe428640b8cbdb09daf17e8191 + react-native-slider: 4a0f3386a38fc3d2d955efc515aef7096f7d1ee4 + React-nativeconfig: 8c83d992b9cc7d75b5abe262069eaeea4349f794 + React-NativeModulesApple: 9f7920224a3b0c7d04d77990067ded14cee3c614 + React-perflogger: 59e1a3182dca2cee7b9f1f7aab204018d46d1914 + React-performancetimeline: a9d05533ff834c6aa1f532e05e571f3fd2e3c1ed + React-RCTActionSheet: d80e68d3baa163e4012a47c1f42ddd8bcd9672cc + React-RCTAnimation: bde981f6bd7f8493696564da9b3bd05721d3b3cc + React-RCTAppDelegate: 0176615c51476c88212bf3edbafb840d39ea7631 + React-RCTBlob: 520a0382bf8e89b9153d60e3c6293e51615834e9 + React-RCTFabric: c9da097b19b30017a99498b8c66a69c72f3ce689 + React-RCTImage: 90448d2882464af6015ed57c98f463f8748be465 + React-RCTLinking: 1bd95d0a704c271d21d758e0f0388cced768d77d + React-RCTNetwork: 218af6e63eb9b47935cc5a775b7a1396cf10ff91 + React-RCTSettings: e10b8e42b0fce8a70fbf169de32a2ae03243ef6b + React-RCTText: e7bf9f4997a1a0b45c052d4ad9a0fe653061cf29 + React-RCTVibration: 5b70b7f11e48d1c57e0d4832c2097478adbabe93 + React-rendererconsistency: f620c6e003e3c4593e6349d8242b8aeb3d4633f0 + React-rendererdebug: e697680f4dd117becc5daf9ea9800067abcee91c + React-rncore: c22bd84cc2f38947f0414fab6646db22ff4f80cd + React-RuntimeApple: de0976836b90b484305638616898cbc665c67c13 + React-RuntimeCore: 3c4a5aa63d9e7a3c17b7fb23f32a72a8bcfccf57 + React-runtimeexecutor: ea90d8e3a9e0f4326939858dafc6ab17c031a5d3 + React-RuntimeHermes: c6b0afdf1f493621214eeb6517fb859ce7b21b81 + React-runtimescheduler: 84f0d876d254bce6917a277b3930eb9bc29df6c7 + React-utils: cbe8b8b3d7b2ac282e018e46f0e7b25cdc87c5a0 + ReactCodegen: 4bcb34e6b5ebf6eef5cee34f55aa39991ea1c1f1 + ReactCommon: 6a952e50c2a4b694731d7682aaa6c79bc156e4ad + RNCClipboard: 2821ac938ef46f736a8de0c8814845dde2dcbdfb + RNGestureHandler: 511250b190a284388f9dd0d2e56c1df76f14cfb8 + RNInstabug: eaa8cde2bcd3c8e757c6dd5c0d33a20814f9658a + RNReanimated: f42a5044d121d68e91680caacb0293f4274228eb + RNScreens: c7ceced6a8384cb9be5e7a5e88e9e714401fd958 + RNSVG: 8b1a777d54096b8c2a0fd38fc9d5a454332bbb4d + RNVectorIcons: 6382277afab3c54658e9d555ee0faa7a37827136 + SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d + Yoga: 055f92ad73f8c8600a93f0e25ac0b2344c3b07e6 -PODFILE CHECKSUM: 281036e04bd4b9e7c2cc03a503b3245d3f1dd0dd +PODFILE CHECKSUM: 63bf073bef3872df95ea45e7c9c023a331ebb3c3 -COCOAPODS: 1.12.0 +COCOAPODS: 1.14.0 From c110d1eabfe456bd8d139d3a09c4b7683a5524de Mon Sep 17 00:00:00 2001 From: kholood Date: Thu, 21 Nov 2024 16:33:19 +0200 Subject: [PATCH 102/104] fix(android): fix w3c caught header --- .../java/com/instabug/reactlibrary/RNInstabugAPMModule.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index 7a73e1f649..a2f2709f04 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -338,7 +338,7 @@ private void networkLogAndroid(final double requestStartTime, final boolean hasError = errorDomain != null && !errorDomain.isEmpty(); final String errorMessage = hasError ? errorDomain : null; - Boolean isW3cHeaderFound=false; + Boolean isW3cHeaderFound=false; Long partialId=null; Long networkStartTimeInSeconds=null; @@ -348,7 +348,7 @@ private void networkLogAndroid(final double requestStartTime, isW3cHeaderFound = w3cAttributes.getBoolean("isW3cHeaderFound"); } - if (w3cAttributes.hasKey("partialId")) { + if (!w3cAttributes.isNull("partialId")) { partialId =(long) w3cAttributes.getDouble("partialId"); networkStartTimeInSeconds = (long) w3cAttributes.getDouble("networkStartTimeInSeconds"); } From ff81603e4f527bc19ca3dc6a07cf8c8173a279b9 Mon Sep 17 00:00:00 2001 From: kholood Date: Mon, 25 Nov 2024 13:05:25 +0200 Subject: [PATCH 103/104] fix (android): reporting network logs upon disabling w3c main feature flag --- .../java/com/instabug/reactlibrary/RNInstabugAPMModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index a2f2709f04..8b3c3206eb 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -344,7 +344,7 @@ private void networkLogAndroid(final double requestStartTime, try { - if (w3cAttributes.hasKey("isW3cHeaderFound")) { + if (!w3cAttributes.isNull("isW3cHeaderFound")) { isW3cHeaderFound = w3cAttributes.getBoolean("isW3cHeaderFound"); } From e46f78941d3fbe7b53134ffed865d1e35a9fdc3b Mon Sep 17 00:00:00 2001 From: kholood Date: Wed, 27 Nov 2024 12:57:15 +0200 Subject: [PATCH 104/104] chore: add changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd73c1b3f..cbb007c46a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v14.0.0...dev) + +### Added + +- Add support for tracing network requests from Instabug to services like Datadog and New Relic ([#1288](https://github.com/Instabug/Instabug-React-Native/pull/1288)) + ## [14.0.0](https://github.com/Instabug/Instabug-React-Native/compare/v13.4.0...14.0.0) (November 11, 2024) ### Added