Skip to main content

OTLP export

OTLP export​

You can export traces and logs from the Embrace SDK to any OTLP-compatible backend, either alongside Embrace or instead of it.

The OpenTelemetry Protocol (OTLP) is an open standard for sending observability data, such as traces and logs, to monitoring and analytics backends. Because OTLP uses a consistent format, you can send the same telemetry to multiple backends.

To export telemetry, add OTLP exporters to the native Android and iOS SDKs when you start Embrace. For more on how custom export works in the native SDKs, see the OpenTelemetry integration guide.

info

You must add exporters before the Embrace SDK starts. If you start Embrace from JavaScript, first move SDK startup to native code as described in Start Embrace SDK in the native side.

Initializing in the native layer​

The following examples export traces and logs to Grafana Cloud over HTTP. Replace the endpoints and Authorization header with the values for your backend. For details on Grafana's OTLP endpoints, see their docs.

  1. Add the OpenTelemetry Swift OTLP HTTP exporter to your app target. If you use CocoaPods, add the following to your app target in your Podfile, then run pod install:

    pod 'OpenTelemetry-Swift-Protocol-Exporter-Http', '~> 2.1'

    If you source the Embrace Apple SDK from Swift Package Manager, add the OpenTelemetryProtocolExporterHTTP product from https://github.com/open-telemetry/opentelemetry-swift to your app target in Xcode instead.

    The Embrace Apple SDK works with version 2.1 or newer of OpenTelemetry Swift.

  2. In your EmbraceInitializer.swift file, pass the exporters through the otel option:

    import Foundation
    import EmbraceIO
    import OpenTelemetryProtocolExporterHttp

    @objcMembers class EmbraceInitializer: NSObject {
    static func start() -> Void {
    let grafanaToken = "__GRAFANA_TOKEN__" // `grafana_instance:token` converted into a base64 string
    let urlConfig = URLSessionConfiguration.default
    urlConfig.httpAdditionalHeaders = ["Authorization": "Basic \(grafanaToken)"]
    let httpClient = BaseHTTPClient(session: URLSession(configuration: urlConfig))

    let spanExporter = OtlpHttpTraceExporter(
    endpoint: URL(string: "https://otlp-gateway-prod-us-central-0.grafana.net/otlp/v1/traces")!,
    httpClient: httpClient
    )
    let logExporter = OtlpHttpLogExporter(
    endpoint: URL(string: "https://otlp-gateway-prod-us-central-0.grafana.net/otlp/v1/logs")!,
    httpClient: httpClient
    )

    do {
    try EmbraceIO.setup(
    options: .withAppId(
    "__APP_ID__", // 5 digits string
    platform: .reactNative,
    otel: EmbraceIO.OTelOptions(
    spanExporter: spanExporter,
    logExporter: logExporter
    )
    )
    )
    try EmbraceIO.shared.start()
    } catch let e {
    print("Error starting Embrace \(e.localizedDescription)")
    }
    }
    }

If you provide an app ID, Embrace keeps receiving your telemetry alongside your backend. To send telemetry only to your backend, see Use without an Embrace account.

For custom exporters, processors, and other options, see the native SDK docs:

Disable tracing for the OTLP export network requests​

Embrace automatically creates spans for network requests. Because OTLP export also makes network requests, each export can create a span that is then exported, which creates another span, and so on.

To avoid this loop, configure Embrace to ignore your export endpoint on both Android and iOS:

In your EmbraceInitializer.swift file, add the endpoint to ignoredURLs and pass the capture services through the captureServices option. For the Grafana example above:

let captureServices = CaptureServicesOptionsBuilder()
.addUrlSessionCaptureService(withOptions: URLSessionCaptureService.Options(
ignoredURLs: ["grafana.net"]
))
.addDefaults()
.build()

try EmbraceIO.setup(
options: .withAppId(
"__APP_ID__", // 5 digits string
platform: .reactNative,
captureServices: captureServices,
otel: EmbraceIO.OTelOptions(
spanExporter: spanExporter,
logExporter: logExporter
)
)
)
try EmbraceIO.shared.start()

If you still start Embrace from JavaScript, add disabledUrlPatterns: ["grafana.net"] to sdkConfig.ios instead.

Configure export in JavaScript (deprecated)​

warning

@embrace-io/react-native-otlp is deprecated and will be removed in the next major release. It only works when you start the Embrace SDK from JavaScript, which is also deprecated. Use native export instead.

Install the package​

npm:

npm install @embrace-io/react-native-otlp

yarn:

yarn add @embrace-io/react-native-otlp

For iOS you will also need to install or update pods for the application:

cd ios && USE_FRAMEWORKS=dynamic pod install --repo-update

If you are not using Expo, you need to update your Metro configuration before running the application. To do this, open your metro.config.js file and set transformer.unstable_allowRequireContext to true:

// metro.config.js
module.exports = {
transformer: {
unstable_allowRequireContext: true,
// ... other configuration
},
};

This update is required because, under the hood, we check at runtime whether the @embrace-io/react-native-otlp package is installed. This package is mandatory if the OTLP feature is needed.

Expo applications use the @expo/metro-config package, which applies a default Metro configuration that enables this flag by default. As a result, this step is not necessary for Expo projects.

Implementation​

For this example we will use Grafana Cloud in terms of redirecting telemetry data over there using OTLP endpoints. For more information about this please visit their online docs.

import React, { useEffect, useMemo, useState } from 'react';
import { useEmbrace } from '@embrace-io/react-native';
import { View, Text } from 'react-native';
import { Stack } from 'expo-router';

const GRAFANA_TOKEN = '__GRAFANA_TOKEN__'; // `grafana_instance:token` converted into a base64 string.
const EXPORTER_CONFIG = {
logExporter: {
endpoint: 'https://otlp-gateway-prod-us-central-0.grafana.net/otlp/v1/logs',
headers: [
{
key: 'Authorization',
token: `Basic ${GRAFANA_TOKEN}`,
},
],
},
traceExporter: {
endpoint:
'https://otlp-gateway-prod-us-central-0.grafana.net/otlp/v1/traces',
headers: [
{
key: 'Authorization',
token: `Basic ${GRAFANA_TOKEN}`,
},
],
},
};

// iOS is configurable through code, Android configuration happens at build time
const IOS_SDK_CONFIG = { appId: '__APP_ID__' };

function RootLayout() {
const { isPending, isStarted } = useEmbrace({
ios: IOS_SDK_CONFIG,
exporters: EXPORTER_CONFIG,
});

if (isPending) {
return (
<View>
<Text>Loading Embrace</Text>
</View>
);
} else {
if (!isStarted) {
console.log('An error occurred during Embrace initialization');
}
}

// regular content of the application
return (
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
</Stack>
);
}

export default RootLayout;

In case you want to avoid sending telemetry into Embrace you could do it by removing the app_id/token values from each Platform configuration. For more information please see our guide on how to use Embrace without an account.