# iOS app in SwiftUI instrumentation

## Overview

This document contains instructions on how to set up OpenTelemetry instrumentation in your iOS applications built using Swift and view your application traces in SigNoz.

## Prerequisites

- A SwiftUI-based iOS application in Xcode.
- Swift toolchain installed; see [Swift getting started](https://www.swift.org/getting-started/#installing-swift).
- Access to a SigNoz Cloud account or self-hosted SigNoz instance.

## Send traces to SigNoz

### Step 1: Add OpenTelemetry dependencies

Install [opentelemetry-swift](https://github.com/open-telemetry/opentelemetry-swift.git) and [grpc-swift](https://github.com/grpc/grpc-swift) in `Package.swift`.

```swift
dependencies: [\
      .package(url: "https://github.com/open-telemetry/opentelemetry-swift.git", .upToNextMajor(from: "1.9.1")),\
      .package(url: "https://github.com/grpc/grpc-swift", from: "1.15.0"),\
  ],\
  targets: [\
      .executableTarget(\
          name: "<service_name>",\
          dependencies: [\
              .product(name: "OpenTelemetryApi", package: "opentelemetry-swift"),\
              .product(name: "OpenTelemetrySdk", package: "opentelemetry-swift"),\
              .product(name: "StdoutExporter", package: "opentelemetry-swift"),\
              .product(name: "ResourceExtension", package: "opentelemetry-swift"),\
              .product(name: "ZipkinExporter", package: "opentelemetry-swift"),\
              .product(name: "OpenTelemetryProtocolExporter", package: "opentelemetry-swift"),\
              .product(name: "SignPostIntegration", package: "opentelemetry-swift"),\
              .product(name: "GRPC", package: "grpc-swift")\
          ],\
          path: "."\
      )\
  ]
```

`<service_name>` is the name of your service.

### Step 2: Initialize the tracer

Create `OpentelemetrySetup.swift` and configure the exporter.

```swift
// OpenTelemetrySetup.swift
import Foundation
import GRPC
import NIO
import NIOSSL
import OpenTelemetryApi
import OpenTelemetryProtocolExporterCommon
import OpenTelemetryProtocolExporterGrpc
import OpenTelemetrySdk
import ResourceExtension
import StdoutExporter

struct OpenTelemetrySetup {
    static func configureOpenTelemetry() {
        let resource = DefaultResources().get().merging(other: Resource(attributes: [\
            "service.name": AttributeValue.string("<service_name>"),\
            "service.version": AttributeValue.string("<service_version>"),\
        ]))

let otlpConfiguration: OtlpConfiguration = OtlpConfiguration(timeout: TimeInterval(10), headers: [("signoz-ingestion-key", "<your-ingestion-key>")])

let grpcChannel = ClientConnection.usingPlatformAppropriateTLS(for: MultiThreadedEventLoopGroup(numberOfThreads: 1)).connect(host: "ingest.us.signoz.cloud", port: 443)

let otlpTraceExporter = OtlpTraceExporter(channel: grpcChannel, config: otlpConfiguration)
        let stdoutExporter = StdoutExporter()

let spanExporter = MultiSpanExporter(spanExporters: [otlpTraceExporter, stdoutExporter])

let spanProcessor = SimpleSpanProcessor(spanExporter: spanExporter)

OpenTelemetry.registerTracerProvider(tracerProvider:
            TracerProviderBuilder()
                .add(spanProcessor: spanProcessor)
                .with(resource: resource)
                .build()
        )
    }
}
```

Verify these values:

- `<service_name>`: logical name of your iOS service; this is what you will see in SigNoz.
- `<service_version>` (optional): Your release version, image tag, or git SHA (e.g., `1.4.2`, `a01dbef8`).
- `<your-ingestion-key>`: Your SigNoz [ingestion key](/content/docs/ingestion/signoz-cloud/keys/index.html)
- `us`: Your [SigNoz Cloud region](/content/docs/ingestion/signoz-cloud/overview/#endpoint/index.html)

Recommended: Set service.version for Deployment Markers

Set `service.version` to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

- **Bash / shell**: `service.version=$(git rev-parse --short HEAD)`
- **GitHub Actions**: `service.version=${{ github.sha }}`
- **GitLab CI**: `service.version=$CI_COMMIT_SHORT_SHA`
- **Kubernetes**: inject from your Helm chart image tag or CI variable

### Step 3: Send telemetry data to SigNoz

To send telemetry data to SigNoz, you can create a function to add spans and data. But prior to that you need to import `OpenTelemetryApi` & create instance of tracer, using the following snippet.

```swift
import OpenTelemetryApi // Import OpenTelemetryApi for the tracer

//this should be inside ContentView Struct
let tracer = OpenTelemetry.instance.tracerProvider.get(instrumentationName: "SwiftExample", instrumentationVersion: "semver:0.1.0")

// Function to simulate work and create a span
    func doWork() {
        let sampleKey = "sampleKey"
        let sampleValue = "sampleValue"

// Start a new span named "doWork"
        let childSpan = tracer.spanBuilder(spanName: "doWork")
            .setSpanKind(spanKind: .client)
            .startSpan()

// Set an attribute on the span
        childSpan.setAttribute(key: sampleKey, value: sampleValue)

// Simulate some work by sleeping for a random interval
        Thread.sleep(forTimeInterval: Double.random(in: 0 ..< 10) / 100)

// End the span
        childSpan.end()
    }

```

### Step 4: Run the app

Run your application from Xcode.

## Validate

- In SigNoz, go to **Traces Explorer** and confirm that the traces for your service (for example `<service_name>`) are present.
- Open a recent trace and verify that spans from your iOS app are present with the attributes you set.

## Troubleshooting

- If you do not see your iOS service in SigNoz, confirm the endpoint/port is reachable from the simulator or device and that the ingestion key (for Cloud) is correct.

## Next steps

- Explore your mobile traces in the [Trace Explorer](/content/docs/userguide/traces/index.html).
- Create latency and error alerts for your service using [Alert Management](/content/docs/alerts-management/trace-based-alerts/index.html).
