Skip to content

grafana/faro-otel-swift-exporter

Faro OpenTelemetry-Swift Exporter

Grafana Faro logo

The Faro Exporter is an OpenTelemetry exporter that sends telemetry data to Grafana Faro, an open-source frontend application monitoring solution. This exporter supports both traces and logs in a single instance with automatic session management, allowing you to monitor your iOS applications using either Grafana Cloud or your own self-hosted infrastructure using Grafana Alloy as your collector.

Note: Grafana Frontend Observability is built for web applications — there is currently no official mobile observability product from Grafana.

This SDK was created as a proof-of-concept to explore mobile telemetry collection using OpenTelemetry and the Faro protocol. It can work well for basic use cases, but please be aware that it is maintained on a best-effort basis and does not come with official support or SLAs.

What you can expect:

  • Session tracking and error monitoring may work similarly to web applications
  • Telemetry data is stored in Loki/Tempo, allowing you to build custom dashboards and run queries in Grafana
  • Data can be forwarded to Grafana Alloy (with faro receiver enabled) and routed to any observability backend of your choice

If you run into issues, feel free to open a GitHub issue — we'll do our best to help on a best-effort basis, but please understand this project is not actively maintained as a product.

Installation

Swift Package Manager

Add the package dependency to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/grafana/faro-otel-swift-exporter.git", from: "1.0.0")
]

Or in Xcode:

  1. Go to File > Add Packages...
  2. Enter the package URL: https://github.com/grafana/faro-otel-swift-exporter.git
  3. Select the version or branch you want to use
  4. Click "Add Package"

Usage

Configuration

Create a FaroExporterOptions instance with your configuration:

Note: For Grafana Cloud users, you can find your collector URL in the Frontend Observability configuration section of your Grafana Cloud instance. For self-hosted setups using Grafana Alloy, refer to the Quick Start Guide for detailed setup instructions.

let faroOptions = FaroExporterOptions(
    collectorUrl: "http://your-faro-collector.net/collect/YOUR_API_KEY",
    appName: "your-app-name",
    appVersion: "1.0.0",
    appEnvironment: "production"
)

Traces Setup

To use the Faro exporter for traces:

// Create the Faro exporter
let faroExporter = try! FaroExporter(options: faroOptions)

// Create a span processor with the Faro exporter
let faroProcessor = BatchSpanProcessor(spanExporter: faroExporter)

// Configure the tracer provider
let tracerProvider = TracerProviderBuilder()
    .add(spanProcessor: faroProcessor)
    ...
    .build()

Logs Setup

To use the Faro exporter for logs:

// Create the Faro exporter (or reuse the one from traces)
let faroExporter = try! FaroExporter(options: faroOptions)

// Create a log processor with the Faro exporter
let faroProcessor = BatchLogRecordProcessor(logRecordExporter: faroExporter)

// Configure the logger provider
let loggerProvider = LoggerProviderBuilder()
    .with(processors: [faroProcessor])
    ...
    .build()

User Context

Faro supports defining a user for a session, which helps correlate telemetry data with specific users. Since OpenTelemetry doesn't currently have a native concept of user context, the Faro exporter implements a workaround using specialized log records.

To set the current user for your session:

// Import to access constants
import FaroOtelExporter

// Get a logger instance
let logger = loggerProvider.get(instrumentationScopeName: "your-scope-name")

// Set the current user by sending a special log with user attributes
logger.logRecordBuilder()
    .setBody(OpenTelemetryApi.AttributeValue.string(FaroOtelConstants.ChangeUser.otelBody))
    .setAttributes([
        FaroOtelConstants.ChangeUser.AttributeKeys.username: OpenTelemetryApi.AttributeValue.string("some_user"),
        FaroOtelConstants.ChangeUser.AttributeKeys.userEmail: OpenTelemetryApi.AttributeValue.string("some_user@example.com"),
        FaroOtelConstants.ChangeUser.AttributeKeys.userId: OpenTelemetryApi.AttributeValue.string("12345")
    ])
    .emit()

When the Faro exporter detects a log with the body text FaroOtelConstants.ChangeUser.otelBody ("otel_change_user"), it will:

  1. Extract the user information from the attributes
  2. Set this as the current user for the session
  3. Not forward this message as a regular log
  4. Any other attributes added to the regular log will be ignored
  5. The log severity does not matter, it will be ignored

This approach allows you to maintain user context across your application's telemetry data without requiring changes to the OpenTelemetry protocol.

Note: The example above uses constants from the FaroOtelConstants class for clean, maintainable code. You can also use string literals directly if preferred:

logger.logRecordBuilder()
   .setBody(OpenTelemetryApi.AttributeValue.string("otel_change_user"))
   .setAttributes([
       "username": OpenTelemetryApi.AttributeValue.string("some_user"),
       "user_email": OpenTelemetryApi.AttributeValue.string("some_user@example.com"),
       "user_id": OpenTelemetryApi.AttributeValue.string("12345")
   ])
   .emit()

Privacy

This exporter utilizes certain APIs that require privacy declarations as mandated by Apple:

  • Device Identification: The SDK uses identifierForVendor (via UIDevice.current.identifierForVendor or WKInterfaceDevice.current().identifierForVendor) and UserDefaults as a complementary mechanism to generate and persist a unique device identifier. This helps correlate telemetry data within your application's sessions without relying on personally identifiable information. On platforms where identifierForVendor might be unavailable (e.g., on macOS), UserDefaults with a generated UUID serves as a fallback mechanism to maintain consistent device identification.

A PrivacyInfo.xcprivacy file is included in this package (located at Sources/FaroOtelExporter/PrivacyInfo.xcprivacy), declaring the usage of these APIs. When you integrate this SDK into your application, this manifest will be bundled, contributing to your app's overall privacy report. Please review Apple's documentation on Privacy Manifests to understand how this impacts your app submission process.

Additional Resources

Contributing

Please see CONTRIBUTING.md for details on how to contribute to this project, including setting up your development environment and guidelines for code style.

About

The Faro OpenTelemetry-Swift Exporter, part of the Grafana Faro project, is an OpenTelemetry exporter for Swift. It instruments iOS applications to send trace and log telemetry to Grafana Faro, enabling real user monitoring (RUM) and contributing to full-stack observability.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages