iOS App in Swift UI Instrumentation

This documentation contains instructions on how to set up OpenTelemetry(OTel) instrumentation in your iOS mobile application built using Swift UI. OpenTelemetry, also known as OTel for short, is an open-source observability framework that can help you generate and collect telemetry data - traces, metrics, and logs from your Swift UI application.

Once the telemetry data is generated, you can configure an exporter to send the data to SigNoz for monitoring and visualization.

There are three major steps to using OpenTelemetry:

  • Instrumenting your iOS application with OpenTelemetry
  • Configuring the exporter to send data to SigNoz
  • Validating the configuration to ensure that data is being sent as expected.

In this tutorial, we will instrument a Swift Mobile application for traces and send it to SigNoz.

Requirements

Swift

Send traces directly to SigNoz cloud

Info

You can test sample application for Swift UI

Step 1 : Instrument your application with OpenTelemetry

To configure your Swift application to send traces to OpenTelemetry you need to install opentelemetry-swift and grpc-swift as dependency in your project.

For that, paste the following inside Package.swift of your project.

 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: "<NAME_OF_APP>",
            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: "."
        )
    ]

Replace NAME_OF_APP with the name of app, you will see this name in SigNoz Services section.

Step 2: Initialize the tracer

To enable tracing and send traces to the SigNoz cloud, you need to initialize the tracer, to do that create a new file named OpentelemetrySetup.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("<YOUR_APP_NAME>"), 
        ]))
        
        let otlpConfiguration: OtlpConfiguration = OtlpConfiguration(timeout: TimeInterval(10), headers: [("signoz-ingestion-key", "<SIGNOZ_INGESTION_KEY>")])
        
        let grpcChannel = ClientConnection.usingPlatformAppropriateTLS(for: MultiThreadedEventLoopGroup(numberOfThreads: 1)).connect(host: "ingest.[REGION].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()
        )
    }
}

Ensure to replace <SIGNOZ_INGESTION_KEY>, <PORT>, and <REGION> with your actual SigNoz ingestion key, Port, and region, respectively.

You can find your Ingestion Key in the following places:

  • mail which you recieved from SigNoz after signing up.
  • inside settings on SigNoz dashboard

Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.

RegionEndpoint
USingest.us.signoz.cloud:443/v1/traces
INingest.in.signoz.cloud:443/v1/traces
EUingest.eu.signoz.cloud:443/v1/traces

These are the variables you need to replace :

PlaceholderDescription
<SIGNOZ_INGESTION_KEY>Your SigNoz ingestion key
<PORT>Port (default: 443)
<REGION>Region for SigNoz ingestion

Once you replace the content of the file, you need to add init in the <project_name>.swift file

init() {
        OpenTelemetrySetup.configureOpenTelemetry()
    }

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

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 app

Run your application from X Code to see the output & you can verify the sent span in SigNoz .

Was this page helpful?