@luciq/react-native 19.6.0 → 19.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [19.7.0](https://github.com/luciqai/luciq-reactnative-sdk/compare/v19.7.0...19.6.0)
4
+
5
+ ### Fixed
6
+
7
+ - Fix NetworkLogger late initialization on Android.
8
+
9
+ ### Changed
10
+
11
+ - Bump Luciq iOS SDK to v19.7.0 ([#54](https://github.com/luciqai/luciq-reactnative-sdk/pull/49)). [See release notes](https://github.com/luciqai/luciq-ios-sdk/releases/tag/19.7.0).
12
+
13
+ - Bump Luciq Android SDK to v19.7.0 ([#54](https://github.com/luciqai/luciq-reactnative-sdk/pull/49)). [See release notes](https://github.com/luciqai/luciq-android-sdk/releases/tag/v19.7.0).
14
+
3
15
  ## [19.6.0](https://github.com/luciqai/luciq-reactnative-sdk/compare/v19.6.0...19.4.0)
4
16
 
5
17
  ### Added
package/README.md CHANGED
@@ -1,48 +1,82 @@
1
- # Luciq for React Native
1
+ <div align="center">
2
+ <img src=".github/assets/luciq-logo.png" alt="Luciq" width="120" />
2
3
 
3
- [![npm](https://img.shields.io/npm/v/@luciq/react-native.svg)](https://www.npmjs.com/package/@luciq/react-native)
4
- [![npm](https://img.shields.io/npm/dt/@luciq/react-native.svg)](https://www.npmjs.com/package/@luciq/react-native)
5
- [![npm](https://img.shields.io/npm/l/@luciq/react-native.svg)](https://github.com/luciqai/luciq-reactnative-sdk/blob/master/LICENSE)
6
- [![Twitter](https://img.shields.io/badge/twitter-@Luciq-blue.svg)](https://twitter.com/Luciqai)
7
- [![Analytics](https://luciq-ga.appspot.com/UA-41982088-6/github/Luciq/@luciq/react-native?pixel)](https://luciq.ai)
4
+ <p><strong>🚀 The Agentic Observability Platform built for Mobile</strong></p>
8
5
 
9
- Luciq is the Agentic Observability Platform built for Mobile.
6
+ [![npm version](https://img.shields.io/npm/v/@luciq/react-native.svg?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@luciq/react-native)
7
+ [![npm downloads](https://img.shields.io/npm/dt/@luciq/react-native.svg?style=for-the-badge)](https://www.npmjs.com/package/@luciq/react-native)
8
+ [![Platform](https://img.shields.io/badge/platform-iOS%20%7C%20Android-lightgrey.svg?style=for-the-badge)](https://www.npmjs.com/package/@luciq/react-native)
9
+ [![License](https://img.shields.io/npm/l/@luciq/react-native.svg?style=for-the-badge)](https://github.com/luciqai/luciq-reactnative-sdk/blob/master/LICENSE)
10
10
 
11
- Our intelligent AI agents help you capture rich, contextual data for every issue, including full session replays, console logs, and detailed network requests, to proactively detect, prioritize, and resolve problems automatically. From traditional bug reporting to proactive resolution, Luciq equips you with the building blocks to your app’s success.
11
+ <br />
12
12
 
13
- Ship faster, deliver frustration-free user sessions, and focus on building what matters.
13
+ Our intelligent AI agents help you capture rich, contextual data for every issue, including full session replays, console logs, and detailed network requests, to proactively detect, prioritize, and resolve problems automatically.
14
14
 
15
- For more info, visit Luciq.ai.
15
+ <strong>Ship faster, deliver frustration-free user sessions, and focus on building what matters.</strong>
16
16
 
17
- ## Installation
17
+ </div>
18
18
 
19
- 1. In Terminal, navigate to your React Native directory and install the `@luciq/react-native` package:
19
+ ---
20
20
 
21
- ```bash
22
- npm install @luciq/react-native
23
- ```
21
+ ## Table of Contents
22
+
23
+ - [Requirements](#requirements)
24
+ - [Installation](#installation)
25
+ - [Initializing Luciq](#initializing-luciq)
26
+ - [iOS Usage Descriptions](#ios-usage-descriptions)
27
+ - [Source Map Uploads for Crash Reports](#source-map-uploads-for-crash-reports)
28
+ - [Network Logging](#network-logging)
29
+ - [Repro Steps](#repro-steps)
30
+ - [React Navigation](#react-navigation)
31
+ - [React Native Navigation (Wix)](#react-native-navigation-wix)
32
+ - [Manual screen reporting](#manual-screen-reporting)
33
+ - [Disabling Repro Steps](#disabling-repro-steps)
34
+ - [Custom Spans (APM)](#custom-spans-apm)
35
+ - [Start / end a span](#start--end-a-span)
36
+ - [Record a completed span](#record-a-completed-span)
37
+ - [Behavior](#behavior)
38
+ - [API reference](#api-reference)
39
+ - [TypeScript](#typescript)
40
+ - [Support](#support)
41
+
42
+ ---
24
43
 
25
- Or if you prefer to use Yarn instead of npm:
44
+ ## Requirements
45
+
46
+ - React Native `>= 0.72.3`
47
+ - iOS `>= 13.4`
48
+ - Android `minSdkVersion >= 21`
49
+
50
+ ## Installation
51
+
52
+ 1. Install the package:
26
53
 
27
54
  ```bash
55
+ npm install @luciq/react-native
56
+ # or
28
57
  yarn add @luciq/react-native
29
58
  ```
30
59
 
31
- 2. if you are using expo you need to add `@luciq/react-native` plugin to `app.json`:
60
+ 2. **Expo only.** Add the Luciq config plugin to `app.json`:
32
61
 
33
62
  ```json
34
- "plugins" : [
63
+ {
64
+ "expo": {
65
+ "plugins": [
35
66
  [
36
67
  "@luciq/react-native",
37
68
  {
38
- // optional that add Mic,Photo permission on iOS and FOREGROUND_SERVICE_MEDIA_PROJECTION on android
39
69
  "addScreenRecordingBugReportingPermission": true
40
70
  }
41
71
  ]
42
- ]
72
+ ]
73
+ }
74
+ }
43
75
  ```
44
76
 
45
- 3. CocoaPods on iOS needs this extra step:
77
+ `addScreenRecordingBugReportingPermission` is optional — when `true`, the plugin adds the iOS microphone & photo-library usage descriptions and the Android `FOREGROUND_SERVICE_MEDIA_PROJECTION` permission required for screen recording in bug reports.
78
+
79
+ 3. **iOS only.** Install CocoaPods:
46
80
 
47
81
  ```bash
48
82
  cd ios && pod install && cd ..
@@ -50,184 +84,213 @@ For more info, visit Luciq.ai.
50
84
 
51
85
  ## Initializing Luciq
52
86
 
53
- To start using Luciq, import it as follows, then initialize it in the `constructor` or `componentWillMount`. This line will let the SDK work with the default behavior. The SDK will be invoked when the device is shaken. You can customize this behavior through the APIs.
87
+ Call `Luciq.init` once, as early as possible at the top of your entry file (`index.js` or `App.tsx`), outside any component. `InvocationEvent` is a named export, not a property on the default `Luciq` namespace.
54
88
 
55
- ```javascript
56
- import Luciq from '@luciq/react-native';
89
+ ```ts
90
+ import Luciq, { InvocationEvent } from '@luciq/react-native';
57
91
 
58
92
  Luciq.init({
59
93
  token: 'APP_TOKEN',
60
- invocationEvents: [Luciq.invocationEvent.shake],
94
+ invocationEvents: [InvocationEvent.shake],
61
95
  });
62
96
  ```
63
97
 
64
- _You can find your app token by selecting the SDK tab from your [**Luciq dashboard**](https://dashboard.luciq.ai)._
98
+ You can combine multiple invocation events:
99
+
100
+ ```ts
101
+ Luciq.init({
102
+ token: 'APP_TOKEN',
103
+ invocationEvents: [
104
+ InvocationEvent.shake,
105
+ InvocationEvent.screenshot,
106
+ InvocationEvent.floatingButton,
107
+ ],
108
+ });
109
+ ```
65
110
 
66
- ## Microphone and Photo Library Usage Description (iOS Only)
111
+ Available `InvocationEvent` values: `shake`, `screenshot`, `twoFingersSwipe`, `floatingButton`, `none`.
67
112
 
68
- Luciq needs access to the microphone and photo library to be able to let users add audio and video attachments. Starting from iOS 10, apps that don’t provide a usage description for those 2 permissions would be rejected when submitted to the App Store.
113
+ Find your app token in your [**Luciq dashboard**](https://dashboard.luciq.ai) under **Settings SDK Integration**.
69
114
 
70
- For your app not to be rejected, you’ll need to add the following 2 keys to your app’s info.plist file with text explaining to the user why those permissions are needed:
115
+ ## iOS Usage Descriptions
116
+
117
+ Luciq needs microphone access to capture audio during screen recordings, and photo-library access to let users attach images to bug reports. Apple rejects apps that omit usage descriptions for either, so add the following keys to your app's `Info.plist`:
71
118
 
72
119
  - `NSMicrophoneUsageDescription`
73
120
  - `NSPhotoLibraryUsageDescription`
74
121
 
75
- If your app doesn’t already access the microphone or photo library, we recommend using a usage description like:
122
+ Suggested copy:
76
123
 
77
- - "`<app name>` needs access to the microphone to be able to attach voice notes."
78
- - "`<app name>` needs access to your photo library for you to be able to attach images."
124
+ - _"`<app name>` needs microphone access to record audio with screen recordings attached to bug reports."_
125
+ - _"`<app name>` needs photo-library access to attach images to bug reports."_
79
126
 
80
- **The permission alert for accessing the microphone/photo library will NOT appear unless users attempt to attach a voice note/photo while using Luciq.**
127
+ The permission prompts only appear when a user actually starts a screen recording or attaches a photo from the Luciq UI.
81
128
 
82
- ## Uploading Source Map Files for Crash Reports
129
+ ## Source Map Uploads for Crash Reports
83
130
 
84
- For your app crashes to show up with a fully symbolicated stack trace, we will automatically generate the source map files and upload them to your dashboard on release build. To do so, we rely on your app token being explicitly added to `Luciq.init({token: 'YOUR_APP_TOKEN'})` in JavaScript.
131
+ For your app crashes to show fully symbolicated stack traces, the build scripts in `@luciq/react-native` will generate and upload source maps to your dashboard on release builds. The uploader reads your app token from the `Luciq.init({ token: 'YOUR_APP_TOKEN' })` call in JavaScript.
85
132
 
86
- If your app token is defined as a constant, you can set an environment variable `LUCIQ_APP_TOKEN` to be used instead.
87
- We also automatically read your `versionName` and `versionCode` to upload your sourcemap file. alternatively, can also set the environment variables `LUCIQ_APP_VERSION_NAME` and `LUCIQ_APP_VERSION_CODE` to be used instead.
133
+ If your token is defined as a constant or imported from elsewhere, override the lookup with environment variables:
88
134
 
89
- To disable the automatic upload, you can set the environment variable `LUCIQ_SOURCEMAPS_UPLOAD_DISABLE` to TRUE.
135
+ | Variable | Purpose |
136
+ | --------------------------------- | ------------------------------------- |
137
+ | `LUCIQ_APP_TOKEN` | App token used for the upload |
138
+ | `LUCIQ_APP_VERSION_NAME` | Overrides the inferred `versionName` |
139
+ | `LUCIQ_APP_VERSION_CODE` | Overrides the inferred `versionCode` |
140
+ | `LUCIQ_SOURCEMAPS_UPLOAD_DISABLE` | Set to `TRUE` to skip the upload step |
90
141
 
91
142
  ## Network Logging
92
143
 
93
- Luciq network logging is enabled by default. It intercepts any requests performed with `fetch` or `XMLHttpRequest` and attaches them to the report that will be sent to the dashboard. To disable network logs:
144
+ Network logging is enabled by default. It intercepts `fetch` and `XMLHttpRequest` calls and attaches them to outgoing reports. Disable it with:
94
145
 
95
- ```javascript
146
+ ```ts
96
147
  import { NetworkLogger } from '@luciq/react-native';
97
- ```
98
148
 
99
- ```javascript
100
149
  NetworkLogger.setEnabled(false);
101
150
  ```
102
151
 
103
152
  ## Repro Steps
104
153
 
105
- Luciq Repro Steps are enabled by default. It captures a screenshot of each screen the user navigates to. These screens are attached to the BugReport when sent.
154
+ Luciq Repro Steps record the screens a user visits. Each screen is attached to a bug report when it's sent. Repro Steps are enabled by default.
106
155
 
107
- We support the two most popular React Native navigation libraries:
156
+ ### React Navigation
108
157
 
109
- - **[react-navigation](https://github.com/react-navigation/react-navigation)**
110
- - **v5**
111
- set the `onStateChange` to `Luciq.onStateChange` in your NavigationContainer as follows:
158
+ **v5+** — pass `Luciq.onStateChange` to your `NavigationContainer`:
112
159
 
113
- ```javascript
114
- <NavigationContainer onStateChange={Luciq.onStateChange} />
115
- ```
160
+ ```tsx
161
+ import { NavigationContainer } from '@react-navigation/native';
162
+ import Luciq from '@luciq/react-native';
116
163
 
117
- - **<=v4**
118
- set the `onNavigationStateChange` to `Luciq.onNavigationStateChange` in your App wrapper as follows:
164
+ <NavigationContainer onStateChange={Luciq.onStateChange}>{/* ... */}</NavigationContainer>;
165
+ ```
119
166
 
120
- ```javascript
121
- export default () => <App onNavigationStateChange={Luciq.onNavigationStateChange} />;
122
- ```
167
+ **v4 and below** — wire `Luciq.onNavigationStateChange` to the root app:
123
168
 
124
- - **[react-native-navigation](https://github.com/wix/react-native-navigation)**
169
+ ```tsx
170
+ export default () => <App onNavigationStateChange={Luciq.onNavigationStateChange} />;
171
+ ```
125
172
 
126
- Register `luciq.aiponentDidAppearListener` listener using:
173
+ ### React Native Navigation (Wix)
127
174
 
128
- ```javascript
129
- Navigation.events().registerComponentDidAppearListener(luciq.aiponentDidAppearListener);
130
- ```
175
+ Register `Luciq.componentDidAppearListener`:
131
176
 
132
- Alternatively, you can report your screen changes manually using the following API
177
+ ```ts
178
+ import { Navigation } from 'react-native-navigation';
179
+ import Luciq from '@luciq/react-native';
180
+
181
+ Navigation.events().registerComponentDidAppearListener(Luciq.componentDidAppearListener);
182
+ ```
133
183
 
134
- ```javascript
135
- Luciq.reportScreenChange('screenName');
184
+ ### Manual screen reporting
185
+
186
+ For custom navigation, report screen changes yourself:
187
+
188
+ ```ts
189
+ Luciq.reportScreenChange('CheckoutScreen');
136
190
  ```
137
191
 
138
- You can disable Repro Steps using the following API:
192
+ ### Disabling Repro Steps
193
+
194
+ ```ts
195
+ import Luciq, { ReproStepsMode } from '@luciq/react-native';
139
196
 
140
- ```javascript
141
197
  Luciq.setReproStepsConfig({ all: ReproStepsMode.disabled });
142
198
  ```
143
199
 
144
- ## Custom Spans
200
+ `ReproStepsMode` values: `enabled`, `enabledWithNoScreenshots`, `disabled`.
145
201
 
146
- Custom spans allow you to manually instrument arbitrary code paths for performance tracking. This feature enables tracking of operations not covered by automatic instrumentation.
202
+ ## Custom Spans (APM)
147
203
 
148
- ### Starting and Ending a Span
204
+ Custom spans let you manually instrument arbitrary code paths for performance tracking — useful for operations that aren't covered by the automatic instrumentation.
149
205
 
150
- ```javascript
206
+ ### Start / end a span
207
+
208
+ ```ts
151
209
  import { APM } from '@luciq/react-native';
152
210
 
153
- // Start a custom span
154
211
  const span = await APM.startCustomSpan('Load User Profile');
155
212
 
156
213
  if (span) {
157
214
  try {
158
- // Perform your operation
159
215
  await loadUserProfile();
160
216
  } finally {
161
- // Always end the span, even if operation fails
162
217
  await span.end();
163
218
  }
164
219
  }
165
220
  ```
166
221
 
167
- ### Recording a Completed Span
222
+ ### Record a completed span
223
+
224
+ ```ts
225
+ import { APM } from '@luciq/react-native';
168
226
 
169
- ```javascript
170
- const start = new Date();
171
- // ... operation already completed ...
227
+ const start = new Date(Date.now() - 1500);
172
228
  const end = new Date();
173
229
 
174
230
  await APM.addCompletedCustomSpan('Cache Lookup', start, end);
175
231
  ```
176
232
 
177
- ### Important Notes
233
+ ### Behavior
178
234
 
179
- - **Span Limit**: Maximum of 100 concurrent spans at any time
180
- - **Name Length**: Span names are truncated to 150 characters
181
- - **Validation**: Empty names or invalid timestamps will be rejected
182
- - **Idempotent**: Calling `span.end()` multiple times is safe
183
- - **Feature Flags**: Spans are only created when SDK is initialized, APM is enabled, and custom spans feature is enabled
235
+ - **Limit:** up to 100 concurrent spans at a time.
236
+ - **Name length:** truncated to 150 characters; empty names are rejected.
237
+ - **Timestamps:** `endDate` must be after `startDate`; otherwise the span is rejected.
238
+ - **Idempotent:** calling `span.end()` more than once is safe.
239
+ - **Gating:** spans are only created when the SDK is initialized, APM is enabled, and the custom-spans feature is enabled for your account.
184
240
 
185
- ### API Reference
241
+ ### API reference
186
242
 
187
243
  #### `APM.startCustomSpan(name: string): Promise<CustomSpan | null>`
188
244
 
189
- Starts a custom span for performance tracking.
245
+ Starts a custom span. Returns the span object, or `null` if the span couldn't be created (e.g. feature disabled, span cap reached, invalid name).
246
+
247
+ #### `CustomSpan.end(): Promise<void>`
190
248
 
191
- **Parameters:**
249
+ Ends the span and reports it. Idempotent.
192
250
 
193
- - `name` (string): The name of the span. Cannot be empty. Max 150 characters.
251
+ #### `APM.addCompletedCustomSpan(name: string, startDate: Date, endDate: Date): Promise<void>`
194
252
 
195
- **Returns:**
253
+ Records a span whose start and end times are already known.
196
254
 
197
- - `Promise<CustomSpan | null>`: The span object to end later, or `null` if the span could not be created.
255
+ ## TypeScript
198
256
 
199
- **Example:**
257
+ The package ships with type definitions. The public surface is exposed as:
200
258
 
201
- ```javascript
202
- const span = await APM.startCustomSpan('Database Query');
203
- if (span) {
204
- // ... perform operation ...
205
- await span.end();
206
- }
259
+ - `Luciq` (default export) — top-level SDK actions: `init`, `onStateChange`, `onNavigationStateChange`, `componentDidAppearListener`, `reportScreenChange`, `setReproStepsConfig`, and many more.
260
+ - Named modules: `APM`, `BugReporting`, `CrashReporting`, `FeatureRequests`, `NetworkLogger`, `Replies`, `SessionReplay`, `Surveys`.
261
+ - Named enums: `InvocationEvent`, `ReproStepsMode`, `LogLevel`, `NetworkInterceptionMode`, `Locale`, `ColorTheme`, `WelcomeMessageMode`, `ExtendedBugReportMode`, `NonFatalErrorLevel`, and more.
262
+ - Named types: `LuciqConfig`, `ThemeConfig`, `NetworkData`, `Survey`, `SessionMetadata`.
263
+
264
+ ```ts
265
+ import Luciq, {
266
+ APM,
267
+ BugReporting,
268
+ CrashReporting,
269
+ InvocationEvent,
270
+ NetworkLogger,
271
+ ReproStepsMode,
272
+ type LuciqConfig,
273
+ } from '@luciq/react-native';
207
274
  ```
208
275
 
209
- #### `CustomSpan.end(): Promise<void>`
276
+ ## Support
210
277
 
211
- Ends the custom span and reports it to the SDK. This method is idempotent.
278
+ <div align="center">
212
279
 
213
- #### `APM.addCompletedCustomSpan(name: string, startDate: Date, endDate: Date): Promise<void>`
280
+ ### Need Help?
214
281
 
215
- Records a completed custom span with pre-recorded timestamps.
282
+ 🌐 **[Visit our website](https://luciq.ai)** 📖 **[Read the docs](https://docs.luciq.ai/)** • 💬 **[Get help](https://help.luciq.ai)**
216
283
 
217
- **Parameters:**
284
+ ### Contact Us
218
285
 
219
- - `name` (string): The name of the span. Cannot be empty. Max 150 characters.
220
- - `startDate` (Date): The start time of the operation.
221
- - `endDate` (Date): The end time of the operation (must be after startDate).
286
+ **Primary Contact Email:** [support@luciq.ai](mailto:support@luciq.ai)
222
287
 
223
- **Example:**
288
+ **LinkedIn:** [linkedin.com/company/luciq](https://linkedin.com/company/luciq)
224
289
 
225
- ```javascript
226
- const start = new Date(Date.now() - 1500);
227
- const end = new Date();
228
- await APM.addCompletedCustomSpan('Background Task', start, end);
229
- ```
290
+ ---
291
+
292
+ <p>Made with ❤️ by the Luciq team</p>
230
293
 
231
- ## Documentation
294
+ <img src=".github/assets/luciq-logo.png" alt="Luciq" width="60" />
232
295
 
233
- For more details about the supported APIs and how to use them, check our [**Documentation**](https://docs.luciq.ai/docs/react-native-overview).
296
+ </div>
@@ -1,5 +1,5 @@
1
1
  project.ext.luciq = [
2
- version: '19.6.0'
2
+ version: '19.7.0'
3
3
  ]
4
4
 
5
5
  dependencies {
@@ -1 +1 @@
1
- -keep class com.luciq.** {*;}
1
+ -keep class ai.luciq.** {*;}
@@ -17,4 +17,7 @@ final class Constants {
17
17
 
18
18
  final static String LCQ_SESSION_REPLAY_ON_SYNC_CALLBACK_INVOCATION = "LCQSessionReplayOnSyncCallback";
19
19
 
20
+ final static String NET_TAG = "LCQ-RN-NET";
21
+ final static String Bridge_TAG = "LCQ-CP-Bridge";
22
+
20
23
  }
@@ -1,9 +1,10 @@
1
1
  package ai.luciq.reactlibrary;
2
2
 
3
+ import static ai.luciq.reactlibrary.Constants.Bridge_TAG;
4
+ import static ai.luciq.reactlibrary.Constants.NET_TAG;
3
5
  import static ai.luciq.reactlibrary.utils.LuciqUtil.getMethod;
4
6
 
5
7
  import android.os.SystemClock;
6
- import android.util.Log;
7
8
 
8
9
  import androidx.annotation.NonNull;
9
10
  import androidx.annotation.Nullable;
@@ -27,6 +28,7 @@ import ai.luciq.apm.configuration.cp.FeatureAvailabilityCallback;
27
28
  import ai.luciq.apm.networking.APMNetworkLogger;
28
29
  import ai.luciq.apm.networkinterception.cp.APMCPNetworkLog;
29
30
  import ai.luciq.reactlibrary.utils.EventEmitterModule;
31
+ import ai.luciq.reactlibrary.utils.LuciqRNLogger;
30
32
  import ai.luciq.reactlibrary.utils.MainThreadHandler;
31
33
 
32
34
  public class RNLuciqAPMModule extends EventEmitterModule {
@@ -328,6 +330,7 @@ public class RNLuciqAPMModule extends EventEmitterModule {
328
330
  @Nullable final String gqLCQueryName,
329
331
  @Nullable final String serverErrorMessage
330
332
  ) {
333
+ LuciqRNLogger.d(NET_TAG, "[networkLogAndroid-APM] Received from JS: " + requestMethod + " " + requestUrl + ", status=" + (int) statusCode + ", duration=" + (long) requestDuration + "ms, startTime=" + (long) requestStartTime + ", error=" + errorDomain + ", gqlQuery=" + gqLCQueryName);
331
334
  try {
332
335
  APMNetworkLogger networkLogger = new APMNetworkLogger();
333
336
 
@@ -349,8 +352,10 @@ public class RNLuciqAPMModule extends EventEmitterModule {
349
352
  }
350
353
 
351
354
  } catch (Exception e) {
355
+ LuciqRNLogger.e(NET_TAG, "[networkLogAndroid-APM] Error parsing W3C attributes for " + requestMethod + " " + requestUrl, e);
352
356
  e.printStackTrace();
353
357
  }
358
+ LuciqRNLogger.d(NET_TAG, "[networkLogAndroid-APM] W3C attrs — isW3cHeaderFound=" + isW3cHeaderFound + ", partialId=" + partialId + ", networkStartTimeInSeconds=" + networkStartTimeInSeconds + ", generatedHeader=" + (w3cAttributes != null && !w3cAttributes.isNull("w3cGeneratedHeader") ? w3cAttributes.getString("w3cGeneratedHeader") : "null") + ", caughtHeader=" + (w3cAttributes != null && !w3cAttributes.isNull("w3cCaughtHeader") ? w3cAttributes.getString("w3cCaughtHeader") : "null"));
354
359
  APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = new APMCPNetworkLog.W3CExternalTraceAttributes(isW3cHeaderFound, partialId, networkStartTimeInSeconds, w3cAttributes.getString("w3cGeneratedHeader"), w3cAttributes.getString("w3cCaughtHeader"));
355
360
  try {
356
361
  Method method = getMethod(Class.forName("ai.luciq.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);
@@ -375,13 +380,16 @@ public class RNLuciqAPMModule extends EventEmitterModule {
375
380
  serverErrorMessage,
376
381
  w3cExternalTraceAttributes
377
382
  );
383
+ LuciqRNLogger.d(NET_TAG, "[networkLogAndroid-APM] Successfully invoked APMNetworkLogger.log via reflection: " + requestMethod + " " + requestUrl);
378
384
  } else {
379
- Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection");
385
+ LuciqRNLogger.e(NET_TAG, "[networkLogAndroid-APM] APMNetworkLogger.log method NOT found by reflection — network log will be lost: " + requestMethod + " " + requestUrl);
380
386
  }
381
387
  } catch (Throwable e) {
388
+ LuciqRNLogger.e(NET_TAG, "[networkLogAndroid-APM] Exception invoking APMNetworkLogger.log: " + e.getMessage() + " for " + requestMethod + " " + requestUrl, e);
382
389
  e.printStackTrace();
383
390
  }
384
391
  } catch (Throwable e) {
392
+ LuciqRNLogger.e(NET_TAG, "[networkLogAndroid-APM] Top-level exception: " + e.getMessage() + " for " + requestMethod + " " + requestUrl, e);
385
393
  e.printStackTrace();
386
394
  }
387
395
  }
@@ -430,7 +438,7 @@ public class RNLuciqAPMModule extends EventEmitterModule {
430
438
 
431
439
  promise.resolve(true);
432
440
  } catch (Exception e) {
433
- Log.e("IB-CP-Bridge", "Error syncing span", e);
441
+ LuciqRNLogger.e(Bridge_TAG, "Error syncing span", e);
434
442
  promise.resolve(false);
435
443
  }
436
444
  }
@@ -455,7 +463,7 @@ public class RNLuciqAPMModule extends EventEmitterModule {
455
463
  }
456
464
  });
457
465
  } catch (Exception e) {
458
- Log.e("IB-CP-Bridge", "Error checking feature flag", e);
466
+ LuciqRNLogger.e(Bridge_TAG, "Error checking feature flag", e);
459
467
  promise.resolve(false);
460
468
  }
461
469
  }
@@ -480,7 +488,7 @@ public class RNLuciqAPMModule extends EventEmitterModule {
480
488
  }
481
489
  });
482
490
  } catch (Exception e) {
483
- Log.e("IB-CP-Bridge", "Error checking APM enabled", e);
491
+ LuciqRNLogger.e(Bridge_TAG, "Error checking APM enabled", e);
484
492
  promise.resolve(false);
485
493
  }
486
494
  }