diff --git a/plugins/node/instrumentation-react-native-navigation/README.md b/plugins/node/instrumentation-react-native-navigation/README.md
index a079c20c20..2f498aa596 100644
--- a/plugins/node/instrumentation-react-native-navigation/README.md
+++ b/plugins/node/instrumentation-react-native-navigation/README.md
@@ -162,7 +162,7 @@ As mentioned before, relies on `@react-native/navigation`
### Note
`useProvider` hook in this example returns an instance of a configured provided.
-It doesn't matter which provider you choose; you just need to pass down one (if needed) with all your configurations. To create that provider, you may want to refer to the official [OpenTelemetry JS documentation](https://github.com/open-telemetry/opentelemetry-js). You can also review our suggested implementation (`experimental/testUtils/hooks/useProvider.ts`), but keep in mind that this is the simplest provider with minimal configurations.
+It doesn't matter which provider you choose; you just need to pass down one (if needed) with all your configurations. To create that provider, you may want to refer to the official [OpenTelemetry JS documentation](https://github.com/open-telemetry/opentelemetry-js). You can also review our suggested implementation (`./test/hooks/useProvider.ts`), but keep in mind that this is the simplest provider with minimal configurations.
## Useful links
diff --git a/plugins/node/instrumentation-react-native-navigation/src/components/NativeNavigationTracker.tsx b/plugins/node/instrumentation-react-native-navigation/src/components/NativeNavigationTracker.tsx
index 2f3eaf61ee..111f8b8a25 100644
--- a/plugins/node/instrumentation-react-native-navigation/src/components/NativeNavigationTracker.tsx
+++ b/plugins/node/instrumentation-react-native-navigation/src/components/NativeNavigationTracker.tsx
@@ -16,7 +16,7 @@
import { forwardRef, ReactNode } from 'react';
import { TracerProvider } from '@opentelemetry/api';
-import useTraceRef from '../utils/hooks/useTracerRef';
+import useTracerRef from '../utils/hooks/useTracerRef';
import useNativeNavigationTracker, {
NativeNavRef,
} from '../hooks/useNativeNavigationTracker';
@@ -36,7 +36,7 @@ const NativeNavigationTracker = forwardRef<
NativeNavigationTrackerProps
>(({ children, provider, config }, ref) => {
// Initializing a Trace instance
- const tracer = useTraceRef(provider, config);
+ const tracer = useTracerRef(provider, config);
useNativeNavigationTracker(ref, tracer, config);
diff --git a/plugins/node/instrumentation-react-native-navigation/src/components/NavigationTracker.tsx b/plugins/node/instrumentation-react-native-navigation/src/components/NavigationTracker.tsx
index fc646c3a36..f783cf8529 100644
--- a/plugins/node/instrumentation-react-native-navigation/src/components/NavigationTracker.tsx
+++ b/plugins/node/instrumentation-react-native-navigation/src/components/NavigationTracker.tsx
@@ -16,7 +16,7 @@
import { forwardRef, ReactNode } from 'react';
import { TracerProvider } from '@opentelemetry/api';
-import useTraceRef from '../utils/hooks/useTracerRef';
+import useTracerRef from '../utils/hooks/useTracerRef';
import useNavigationTracker, { NavRef } from '../hooks/useNavigationTracker';
import { NavigationTrackerConfig } from '../types/navigation';
@@ -34,7 +34,7 @@ const NavigationTracker = forwardRef<
NavigationTrackerProps
>(({ children, provider, config }, ref) => {
// Initializing a Trace instance
- const tracer = useTraceRef(provider, config);
+ const tracer = useTracerRef(provider, config);
useNavigationTracker(ref, tracer, config);
diff --git a/plugins/node/instrumentation-react-native-navigation/src/hooks/useAppStateListener.ts b/plugins/node/instrumentation-react-native-navigation/src/hooks/useAppStateListener.ts
index 0e66913faf..f1173aa846 100644
--- a/plugins/node/instrumentation-react-native-navigation/src/hooks/useAppStateListener.ts
+++ b/plugins/node/instrumentation-react-native-navigation/src/hooks/useAppStateListener.ts
@@ -14,14 +14,40 @@
* limitations under the License.
*/
import { AppState, AppStateStatus } from 'react-native';
-import { useEffect } from 'react';
+import { MutableRefObject, useCallback, useEffect } from 'react';
+import { spanCreatorAppState } from '../utils/spanFactory';
+import { TracerRef } from '../utils/hooks/useTracerRef';
+import { SpanRef } from '../utils/hooks/useSpanRef';
+import { Attributes } from '@opentelemetry/api';
-type CallbackFn = (currentState: AppStateStatus) => void;
+const useAppStateListener = (
+ tracer: TracerRef,
+ span: SpanRef,
+ view: MutableRefObject,
+ attributes?: Attributes
+) => {
+ /**
+ * App State Span Factory
+ */
+ const initAppStateSpan = useCallback(
+ (currentState: AppStateStatus) => {
+ const appStateHandler = spanCreatorAppState(tracer, span, attributes);
-const useAppStateListener = (callback?: CallbackFn) => {
+ if (view?.current === null) {
+ return;
+ }
+
+ appStateHandler(view?.current, currentState);
+ },
+ [span, tracer, attributes]
+ );
+
+ /**
+ * App State Listener changes
+ */
useEffect(() => {
const handleAppStateChange = (currentState: AppStateStatus) => {
- callback?.(currentState);
+ initAppStateSpan(currentState);
};
const subscription = AppState.addEventListener(
@@ -32,7 +58,7 @@ const useAppStateListener = (callback?: CallbackFn) => {
return () => {
subscription.remove();
};
- }, [callback]);
+ }, [initAppStateSpan]);
};
export default useAppStateListener;
diff --git a/plugins/node/instrumentation-react-native-navigation/src/hooks/useNativeNavigationTracker.ts b/plugins/node/instrumentation-react-native-navigation/src/hooks/useNativeNavigationTracker.ts
index a233d49303..10aae52c23 100644
--- a/plugins/node/instrumentation-react-native-navigation/src/hooks/useNativeNavigationTracker.ts
+++ b/plugins/node/instrumentation-react-native-navigation/src/hooks/useNativeNavigationTracker.ts
@@ -14,13 +14,9 @@
* limitations under the License.
*/
-import { AppStateStatus } from 'react-native';
-import { ForwardedRef, useCallback, useEffect, useMemo, useRef } from 'react';
+import { ForwardedRef, useEffect, useMemo, useRef } from 'react';
-import spanCreator, {
- spanCreatorAppState,
- spanEnd,
-} from '../utils/spanCreator';
+import { spanCreator, spanEnd } from '../utils/spanFactory';
import { TracerRef } from '../utils/hooks/useTracerRef';
import useSpanRef from '../utils/hooks/useSpanRef';
import {
@@ -38,19 +34,29 @@ const useNativeNavigationTracker = (
tracer: TracerRef,
config?: NavigationTrackerConfig
) => {
- const { attributes: customAttributes, debug } = config ?? {};
- const console = useConsole(!!debug);
-
const navigationElRef = useMemo(() => {
const isMutableRef = ref !== null && typeof ref !== 'function';
return isMutableRef ? ref.current : undefined;
}, [ref]);
- const navView = useRef(null);
+ const { attributes: customAttributes, debug } = config ?? {};
+ const console = useConsole(!!debug);
- // Initializing a Span
+ const view = useRef(null);
const span = useSpanRef();
+ /**
+ * Navigation Span Factory
+ */
+ const initNativeNavigationSpan = useMemo(
+ () => spanCreator(tracer, span, view, customAttributes),
+ [customAttributes]
+ );
+
+ /**
+ * Registering the componentDidAppear and componentDidDisappear listeners
+ * to start and end spans depending on the navigation lifecycle
+ */
useEffect(() => {
if (!navigationElRef) {
console.warn(
@@ -71,7 +77,7 @@ const useNativeNavigationTracker = (
return;
}
- spanCreator(tracer, span, navView, componentName, customAttributes);
+ initNativeNavigationSpan(componentName);
});
navigationElRef.registerComponentDidDisappearListener(
@@ -88,35 +94,23 @@ const useNativeNavigationTracker = (
spanEnd(span);
}
);
- }, [navigationElRef, span, tracer, customAttributes]);
+ }, [navigationElRef, span, initNativeNavigationSpan]);
+ /**
+ * Start and end spans depending on the app state changes
+ */
+ useAppStateListener(tracer, span, view, customAttributes);
+
+ /**
+ * Ending the final span depending on the app lifecycle
+ */
useEffect(
() => () => {
// making sure the final span is ended when the app is unmounted
- const isFinalView = true;
- spanEnd(span, undefined, isFinalView);
+ spanEnd(span, undefined, true);
},
[span]
);
-
- const handleAppStateListener = useCallback(
- (currentState: AppStateStatus) => {
- const appStateHandler = spanCreatorAppState(
- tracer,
- span,
- customAttributes
- );
-
- if (navView?.current === null) {
- return;
- }
-
- appStateHandler(navView?.current, currentState);
- },
- [span, tracer, customAttributes]
- );
-
- useAppStateListener(handleAppStateListener);
};
export default useNativeNavigationTracker;
diff --git a/plugins/node/instrumentation-react-native-navigation/src/hooks/useNavigationTracker.ts b/plugins/node/instrumentation-react-native-navigation/src/hooks/useNavigationTracker.ts
index e11fb3321e..20e7bf77fe 100644
--- a/plugins/node/instrumentation-react-native-navigation/src/hooks/useNavigationTracker.ts
+++ b/plugins/node/instrumentation-react-native-navigation/src/hooks/useNavigationTracker.ts
@@ -14,13 +14,9 @@
* limitations under the License.
*/
-import { AppStateStatus } from 'react-native';
-import { ForwardedRef, useCallback, useEffect, useMemo, useRef } from 'react';
+import { ForwardedRef, useEffect, useMemo, useRef } from 'react';
-import spanCreator, {
- spanCreatorAppState,
- spanEnd,
-} from '../utils/spanCreator';
+import { spanCreator, spanEnd } from '../utils/spanFactory';
import { TracerRef } from '../utils/hooks/useTracerRef';
import useSpanRef from '../utils/hooks/useSpanRef';
import {
@@ -38,20 +34,29 @@ const useNavigationTracker = (
tracer: TracerRef,
config?: NavigationTrackerConfig
) => {
- const { attributes: customAttributes, debug } = config ?? {};
- const console = useConsole(!!debug);
-
const navigationElRef = useMemo(() => {
const isMutableRef = ref !== null && typeof ref !== 'function';
return isMutableRef ? ref.current : undefined;
}, [ref]);
- // tracking specific (no otel related)
- const navView = useRef(null);
+ const { attributes: customAttributes, debug } = config ?? {};
+ const console = useConsole(!!debug);
- // Initializing a Span
const span = useSpanRef();
+ const view = useRef(null);
+
+ /**
+ * Native Navigation Span Factory
+ */
+ const initNavigationSpan = useMemo(
+ () => spanCreator(tracer, span, view, customAttributes),
+ [customAttributes]
+ );
+ /**
+ * Registering the Navigation 'state' Listener
+ * to start and end spans depending on the navigation lifecycle
+ */
useEffect(() => {
if (!navigationElRef) {
console.warn(
@@ -74,38 +79,26 @@ const useNavigationTracker = (
return;
}
- spanCreator(tracer, span, navView, routeName, customAttributes);
+ initNavigationSpan(routeName);
});
}
- }, [navigationElRef, span, tracer, customAttributes]);
+ }, [navigationElRef, initNavigationSpan]);
+
+ /**
+ * Start and end spans depending on the app state changes
+ */
+ useAppStateListener(tracer, span, view, customAttributes);
+ /**
+ * Ending the final span depending on the app lifecycle
+ */
useEffect(
() => () => {
// making sure the final span is ended when the app is unmounted
- const isFinalView = true;
- spanEnd(span, undefined, isFinalView);
+ spanEnd(span, undefined, true);
},
[span]
);
-
- const handleAppStateListener = useCallback(
- (currentState: AppStateStatus) => {
- const appStateHandler = spanCreatorAppState(
- tracer,
- span,
- customAttributes
- );
-
- if (navView?.current === null) {
- return;
- }
-
- appStateHandler(navView?.current, currentState);
- },
- [span, tracer, customAttributes]
- );
-
- useAppStateListener(handleAppStateListener);
};
export default useNavigationTracker;
diff --git a/plugins/node/instrumentation-react-native-navigation/src/utils/hooks/useTracerRef.ts b/plugins/node/instrumentation-react-native-navigation/src/utils/hooks/useTracerRef.ts
index 4a36ef80f6..5b86ae3778 100644
--- a/plugins/node/instrumentation-react-native-navigation/src/utils/hooks/useTracerRef.ts
+++ b/plugins/node/instrumentation-react-native-navigation/src/utils/hooks/useTracerRef.ts
@@ -29,7 +29,6 @@ const useTracerRef = (
const tracerRef = useRef(null);
const console = useConsole(!!debug);
- // using the layout effect to make sure the tracer is initialized before the component is rendered
useEffect(() => {
if (tracerRef.current === null) {
if (!provider) {
diff --git a/plugins/node/instrumentation-react-native-navigation/src/utils/spanCreator.ts b/plugins/node/instrumentation-react-native-navigation/src/utils/spanFactory.ts
similarity index 67%
rename from plugins/node/instrumentation-react-native-navigation/src/utils/spanCreator.ts
rename to plugins/node/instrumentation-react-native-navigation/src/utils/spanFactory.ts
index 867dff506d..fe2681cef7 100644
--- a/plugins/node/instrumentation-react-native-navigation/src/utils/spanCreator.ts
+++ b/plugins/node/instrumentation-react-native-navigation/src/utils/spanFactory.ts
@@ -42,10 +42,12 @@ const spanStart = (
// Starting the span
span.current = tracer.current.startSpan(currentRouteName);
- // it should create the first span knowing there is not a previous view
- span.current.setAttribute(ATTRIBUTES.initialView, !!isLaunch);
- // it should set the view name in case it's useful have this as attr
- span.current.setAttribute(ATTRIBUTES.viewName, currentRouteName);
+ span.current.setAttributes({
+ // it should create the first span knowing there is not a previous view
+ [ATTRIBUTES.initialView]: !!isLaunch,
+ // it should set the view name in case it's useful have this as attr
+ [ATTRIBUTES.viewName]: currentRouteName,
+ });
if (customAttributes) {
span.current.setAttributes(customAttributes);
@@ -71,6 +73,35 @@ const spanEnd = (
}
};
+const spanCreator =
+ (
+ tracer: TracerRef,
+ span: SpanRef,
+ view: MutableRefObject,
+ customAttributes?: Attributes
+ ) =>
+ (currentRouteName: string) => {
+ if (!tracer.current) {
+ // do nothing in case for some reason the tracer is not initialized
+ return;
+ }
+
+ const isInitialView = view.current === null;
+
+ const shouldEndCurrentSpan =
+ view.current !== null && view.current !== currentRouteName;
+
+ // it means the view has changed and we are ending the previous span
+ if (shouldEndCurrentSpan) {
+ spanEnd(span);
+ }
+
+ spanStart(tracer, span, currentRouteName, customAttributes, isInitialView);
+
+ // last step before it changes the view
+ view.current = currentRouteName;
+ };
+
const spanCreatorAppState =
(tracer: TracerRef, span: SpanRef, customAttributes?: Attributes) =>
(currentRouteName: string, currentState: AppStateStatus) => {
@@ -85,33 +116,4 @@ const spanCreatorAppState =
}
};
-const spanCreator = (
- tracer: TracerRef,
- span: SpanRef,
- view: MutableRefObject,
- currentRouteName: string,
- customAttributes?: Attributes
-) => {
- if (!tracer.current) {
- // do nothing in case for some reason the tracer is not initialized
- return;
- }
-
- const isInitialView = view.current === null;
-
- const shouldEndCurrentSpan =
- view.current !== null && view.current !== currentRouteName;
-
- // it means the view has changed and we are ending the previous span
- if (shouldEndCurrentSpan) {
- spanEnd(span);
- }
-
- spanStart(tracer, span, currentRouteName, customAttributes, isInitialView);
-
- // last step before it changes the view
- view.current = currentRouteName;
-};
-
-export default spanCreator;
-export { spanStart, spanEnd, spanCreatorAppState, ATTRIBUTES };
+export { spanCreator, spanCreatorAppState, spanStart, spanEnd, ATTRIBUTES };
diff --git a/plugins/node/instrumentation-react-native-navigation/test/NativeNavigationTracker.test.tsx b/plugins/node/instrumentation-react-native-navigation/test/NativeNavigationTracker.test.tsx
index 09e4046fdc..03b96eaa60 100644
--- a/plugins/node/instrumentation-react-native-navigation/test/NativeNavigationTracker.test.tsx
+++ b/plugins/node/instrumentation-react-native-navigation/test/NativeNavigationTracker.test.tsx
@@ -16,7 +16,7 @@
import { AppState } from 'react-native';
import React, { FC, useRef } from 'react';
import { render } from '@testing-library/react';
-import { ATTRIBUTES } from '../src/utils/spanCreator';
+import { ATTRIBUTES } from '../src/utils/spanFactory';
import sinon from 'sinon';
import { NativeNavigationTracker } from '../src';
import useProvider from './hooks/useProvider';
diff --git a/plugins/node/instrumentation-react-native-navigation/test/NavigationTracker.test.tsx b/plugins/node/instrumentation-react-native-navigation/test/NavigationTracker.test.tsx
index 0a53244413..478c1dfbe3 100644
--- a/plugins/node/instrumentation-react-native-navigation/test/NavigationTracker.test.tsx
+++ b/plugins/node/instrumentation-react-native-navigation/test/NavigationTracker.test.tsx
@@ -19,7 +19,7 @@ import React, { render } from '@testing-library/react';
import useProvider from './hooks/useProvider';
import { NavRef } from '../src/hooks/useNavigationTracker';
-import { ATTRIBUTES } from '../src/utils/spanCreator';
+import { ATTRIBUTES } from '../src/utils/spanFactory';
import sinon from 'sinon';
import { NavigationTracker } from '../src';