Skip to content

Commit

Permalink
[Demo] Add info about React Native app (#5704)
Browse files Browse the repository at this point in the history
Co-authored-by: Severin Neumann <[email protected]>
Co-authored-by: Tiffany Hrabusa <[email protected]>
  • Loading branch information
3 people authored Jan 7, 2025
1 parent f765d42 commit 333d350
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 2 deletions.
1 change: 1 addition & 0 deletions .cspell/en-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ quantile
quantiles
quarkus
quoteservice
react-native-app
recommendationservice
redis
relref
Expand Down
4 changes: 3 additions & 1 deletion content/en/docs/demo/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ here.
| C++ | | | [Currency Service](services/currency/) |
| Go | | [Checkout Service](services/checkout/), [Product Catalog Service](services/product-catalog/) | [Checkout Service](services/checkout/), [Product Catalog Service](services/product-catalog/) |
| Java | [Ad Service](services/ad/) | | [Ad Service](services/ad/) |
| JavaScript | | [Frontend](services/frontend/) | [Frontend](services/frontend/), [Payment Service](services/payment/) |
| JavaScript | | | [Payment Service](services/payment/) |
| TypeScript | | [Frontend](services/frontend/), [React Native App](services/react-native-app/) | [Frontend](services/frontend/) |
| Kotlin | | [Fraud Detection Service](services/fraud-detection/) | |
| PHP | | [Quote Service](services/quote/) | [Quote Service](services/quote/) |
| Python | [Recommendation Service](services/recommendation/) | | [Recommendation Service](services/recommendation/) |
Expand All @@ -54,6 +55,7 @@ found here:
- [Recommendation Service](services/recommendation/)
- [Shipping Service](services/shipping/)
- [Image Provider Service](services/imageprovider/)
- [React Native App](services/react-native-app/)

## Scenarios

Expand Down
3 changes: 3 additions & 0 deletions content/en/docs/demo/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ quoteservice(Quote Service):::php
recommendationservice(Recommendation Service):::python
shippingservice(Shipping Service):::rust
queue[(queue<br/>&#40Kafka&#41)]:::java
react-native-app(React Native App):::typescript
adservice ---->|gRPC| flagd
Expand Down Expand Up @@ -73,6 +74,8 @@ recommendationservice -->|gRPC| productcatalogservice
recommendationservice -->|gRPC| flagd
shippingservice -->|HTTP| quoteservice
react-native-app -->|HTTP| frontendproxy
end
classDef dotnet fill:#178600,color:white;
Expand Down
3 changes: 2 additions & 1 deletion content/en/docs/demo/services/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ To visualize request flows, see the [Service Diagram](../architecture/).
| [currencyservice](currency/) | C++ | Converts one money amount to another currency. Uses real values fetched from European Central Bank. It's the highest QPS service. |
| [emailservice](email/) | Ruby | Sends users an order confirmation email (mock/). |
| [frauddetectionservice](fraud-detection/) | Kotlin | Analyzes incoming orders and detects fraud attempts (mock/). |
| [frontend](frontend/) | JavaScript | Exposes an HTTP server to serve the website. Does not require sign up / login and generates session IDs for all users automatically. |
| [frontend](frontend/) | TypeScript | Exposes an HTTP server to serve the website. Does not require sign up / login and generates session IDs for all users automatically. |
| [loadgenerator](load-generator/) | Python/Locust | Continuously sends requests imitating realistic user shopping flows to the frontend. |
| [paymentservice](payment/) | JavaScript | Charges the given credit card info (mock/) with the given amount and returns a transaction ID. |
| [productcatalogservice](product-catalog/) | Go | Provides the list of products from a JSON file and ability to search products and get individual products. |
| [quoteservice](quote/) | PHP | Calculates the shipping costs, based on the number of items to be shipped. |
| [recommendationservice](recommendation/) | Python | Recommends other products based on what's given in the cart. |
| [shippingservice](shipping/) | Rust | Gives shipping cost estimates based on the shopping cart. Ships items to the given address (mock/). |
| [react-native-app](react-native-app/) | TypeScript | React Native mobile application that provides a UI on top of the shopping services. |
149 changes: 149 additions & 0 deletions content/en/docs/demo/services/react-native-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
title: React Native App
cSpell:ignore: typeof
---

The React Native app provides a mobile UI for users on Android and iOS devices
to interact with the demo's services. It is built with
[Expo](https://docs.expo.dev/get-started/introduction/) and uses Expo's
file-based routing to layout the screens for the app.

[React Native app source](https://github.com/open-telemetry/opentelemetry-demo/blob/main/src/react-native-app/)

## Instrumentation

The application uses the OpenTelemetry packages to instrument the application at
the JS layer.

{{% alert title="Important" color="warning" %}}

The JS OTel packages are supported for node and web environments. While they
work for React Native as well, they are not explicitly supported for that
environment, where they might break compatibility with minor version updates or
require workarounds. Building JS OTel package support for React Native is an
area of active development.

{{% /alert %}}

The main entry point for the application is `app/_layout.tsx` where a hook is
used to initialize the instrumentation and make sure it is loaded before
displaying the UI:

```typescript
import { useTracer } from '@/hooks/useTracer';

const { loaded: tracerLoaded } = useTracer();
```

`hooks/useTracer.ts` contains all the code for setting up instrumentation
including initializing a TracerProvider, establishing an OTLP export,
registering trace context propagators, and registering auto-instrumentation of
network requests.

```typescript
import {
CompositePropagator,
W3CBaggagePropagator,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { Resource } from '@opentelemetry/resources';
import {
ATTR_DEVICE_ID,
ATTR_OS_NAME,
ATTR_OS_VERSION,
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
} from '@opentelemetry/semantic-conventions/incubating';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import getLocalhost from '@/utils/Localhost';
import { useEffect, useState } from 'react';
import {
getDeviceId,
getSystemVersion,
getVersion,
} from 'react-native-device-info';
import { Platform } from 'react-native';
import { SessionIdProcessor } from '@/utils/SessionIdProcessor';

const Tracer = async () => {
const localhost = await getLocalhost();

const resource = new Resource({
[ATTR_SERVICE_NAME]: 'react-native-app',
[ATTR_OS_NAME]: Platform.OS,
[ATTR_OS_VERSION]: getSystemVersion(),
[ATTR_SERVICE_VERSION]: getVersion(),
[ATTR_DEVICE_ID]: getDeviceId(),
});

const provider = new WebTracerProvider({
resource,
spanProcessors: [
new BatchSpanProcessor(
new OTLPTraceExporter({
url: `http://${localhost}:${process.env.EXPO_PUBLIC_FRONTEND_PROXY_PORT}/otlp-http/v1/traces`,
}),
{
scheduledDelayMillis: 500,
},
),
new SessionIdProcessor(),
],
});

provider.register({
propagator: new CompositePropagator({
propagators: [
new W3CBaggagePropagator(),
new W3CTraceContextPropagator(),
],
}),
});

registerInstrumentations({
instrumentations: [
// Some tiptoeing required here, propagateTraceHeaderCorsUrls is required to make the instrumentation
// work in the context of a mobile app even though we are not making CORS requests. `clearTimingResources` must
// be turned off to avoid using the web-only Performance API
new FetchInstrumentation({
propagateTraceHeaderCorsUrls: /.*/,
clearTimingResources: false,
}),

// The React Native implementation of fetch is simply a polyfill on top of XMLHttpRequest:
// https://github.com/facebook/react-native/blob/7ccc5934d0f341f9bc8157f18913a7b340f5db2d/packages/react-native/Libraries/Network/fetch.js#L17
// Because of this when making requests using `fetch` there will an additional span created for the underlying
// request made with XMLHttpRequest. Since in this demo calls to /api/ are made using fetch, turn off
// instrumentation for that path to avoid the extra spans.
new XMLHttpRequestInstrumentation({
ignoreUrls: [/\/api\/.*/],
}),
],
});
};

export interface TracerResult {
loaded: boolean;
}

export const useTracer = (): TracerResult => {
const [loaded, setLoaded] = useState<boolean>(false);

useEffect(() => {
if (!loaded) {
Tracer()
.catch(() => console.warn('failed to setup tracer'))
.finally(() => setLoaded(true));
}
}, [loaded]);

return {
loaded,
};
};
```
4 changes: 4 additions & 0 deletions static/refcache.json
Original file line number Diff line number Diff line change
Expand Up @@ -2583,6 +2583,10 @@
"StatusCode": 206,
"LastSeen": "2024-01-30T16:04:54.134692-05:00"
},
"https://docs.expo.dev/get-started/introduction/": {
"StatusCode": 206,
"LastSeen": "2025-01-07T10:55:21.674477-05:00"
},
"https://docs.fluentbit.io/manual/pipeline/inputs/opentelemetry/": {
"StatusCode": 206,
"LastSeen": "2024-01-30T06:05:58.662694-05:00"
Expand Down

0 comments on commit 333d350

Please sign in to comment.