newrelic / newrelic-react-native-agent

New Relic Mobile Agent SDK for React-Native Applications
Apache License 2.0
16 stars 21 forks source link

Mutation of agentConfiguration in Development Mode Causes Error with deepFreezeAndThrowOnMutationInDev #187

Open Jojr opened 2 months ago

Jojr commented 2 months ago

Description

I encountered an issue when setting the customerConfiguration properties while in development mode. The deepFreezeAndThrowOnMutationInDev function from React Native is detecting and handling the mutation of the agentConfiguration object, resulting in console errors.

Steps to Reproduce

  1. In a development environment, set the properties of customerConfiguration.

example:

...
type AnyFunction = (...args: any[]) => any
...
this.agentConfiguration = {
      analyticsEventEnabled: Platform.OS === 'android',
      crashReportingEnabled: true,
      interactionTracingEnabled: true,
      networkRequestEnabled: true,
      networkErrorRequestEnabled: true,
      httpRequestBodyCaptureEnabled: true,
      loggingEnabled: true,
      webViewInstrumentation: true,
      offlineStorageEnabled: true,
    }
    this.enableAgentInDev = true
  }

  supressException =
    <Func extends AnyFunction>(fn: Func): ((...args: Parameters<Func>) => ReturnType<Func>) =>
    (...args: Parameters<Func>): ReturnType<Func> => {
      try {
        return fn(...args)
      } catch (error) {
        console.error(error)
      }
    }

  start = supressException(() => {
    if (this.enableAgentInDev) {
      NewRelic.startAgent(this.appKey, this.agentConfiguration)
    }
  })
...
  1. Run the application.

  2. Observe that the deepFreezeAndThrowOnMutationInDev function generates a console error with the message:

You attempted to set the key 'analyticsEventEnabled' with the value 'false' on an object that is meant to be immutable and has been frozen.

  1. The error is repeated for any altered property of the agentConfiguration object.

Expected Behavior

The agentConfiguration object should be updated with the properties from customerConfiguration without causing errors or warnings from deepFreezeAndThrowOnMutationInDev.

The system should handle configuration changes gracefully in development mode, without alerting about immutability violations.

Relevant Logs / Console output

deepFreezeAndThrowOnMutationInDev path: node_modules/react-native/Libraries/Utilities/deepFreezeAndThrowOnMutationInDev.js

Simulator Screenshot - iPhone 15 Pro - 2024-08-13 at 10 27 24

Proposed Solution:

To avoid these errors, I modified the code to use the spread operator, which creates a shallow copy of the objects:

From this.config = Object.assign(this.agentConfiguration, customerConfiguration); To this.config = {...this.agentConfiguration, ...customerConfiguration};

I would like to understand if there is a specific reason for the current implementation and if there is a recommended approach for handling state immutability in development mode. I am looking for a solution that allows setting agent configuration properties without triggering the deepFreezeAndThrowOnMutationInDev function.

Your Environment

React Native NewRelicAgent: 1.4.1 iOS NewRelicAgent: 7.5.0 Android NewRelicAgent: 7.5.0

React Native: 0.72.9

Thank you for your assistance!

duraz0rz commented 2 months ago

Yeah, this is pretty annoying in development mode. Object.assign mutates the original object (this.agentConfiguration), so this error gets thrown even if you don't change customer configuration.

ndesai-newrelic commented 2 months ago

@duraz0rz can you provide sample app for this issue? we are unable to reproduce the issue

duraz0rz commented 2 months ago

@ndesai-newrelic I couldn't quite replicate it on a fresh app using npx create-expo-app ... I think you have to trigger a full reload when making a change (instead of a fast refresh).