Swift Opentelemetry Instrumentation

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

Requirements

Swift

Send traces to SigNoz Cloud

Based on your application environment, you can choose the setup below to send traces to SigNoz Cloud.

From VMs, there are two ways to send data to SigNoz Cloud.

Send traces directly to SigNoz cloud

Here we will be sending traces to SigNoz cloud in 4 easy steps, if you want to send traces to self hosted SigNoz , you can refer to this.

Info

If you are using the sample swift application, then you just need to update the ingestion key and SigNoz endpoint after that you are good to go!

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: "<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: "."
        )
    ]
  • Set the <region> to match your SigNoz Cloud region

You also need to add the following imports to use the methods and functions from the packages/dependencies which you just imported in Package.swift file.

import Foundation
import GRPC
import NIO
import NIOSSL
import OpenTelemetryApi
import OpenTelemetryProtocolExporterCommon
import OpenTelemetryProtocolExporterGrpc
import OpenTelemetrySdk
import ResourceExtension
import SignPostIntegration
import StdoutExporter
import ZipkinExporter

Step 2: Initialize the tracer

To enable tracing and send traces to the SigNoz cloud, you need to initialize the tracer, to do that insert the following code snippet into your main.swift file

var resources = DefaultResources().get()

let instrumentationScopeName = "SwiftExample"
let instrumentationScopeVersion = "semver:0.1.0"

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.<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)
        .build()
)
  • Set the <region> to match your SigNoz Cloud region
  • Replace <your-ingestion-key> with your SigNoz ingestion key.

Step 3: Send Telemetry data to SigNoz

To send telemetry data to SigNoz, you can create a function to add spans and data. This is a sample function

let sampleKey = "sampleKey"
let sampleValue = "sampleValue"

func doWork() {
    let childSpan = tracer.spanBuilder(spanName: "doWork").setSpanKind(spanKind: .client).startSpan()
    childSpan.setAttribute(key: sampleKey, value: sampleValue)
    Thread.sleep(forTimeInterval: Double.random(in: 0 ..< 10) / 100)
    childSpan.end()
}

Step 4: Run app

Execute your application by issuing the following command in terminal:

swift run

Send traces via OTel Collector binary

Step 1 : Install OTel Collector OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.

📝 Note

You can find instructions to install OTel Collector binary here in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Swift application.

Step 2 : 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: "<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 name of your service

You also need to add the following imports to use the methods and functions from the packages/dependencies which you just imported in Package.swift file.

import Foundation
import GRPC
import NIO
import NIOSSL
import OpenTelemetryApi
import OpenTelemetryProtocolExporterCommon
import OpenTelemetryProtocolExporterGrpc
import OpenTelemetrySdk
import ResourceExtension
import SignPostIntegration
import StdoutExporter
import ZipkinExporter

Step 3: Initialize the tracer

Add these statements to initialize tracer in the main.swift file inside the main function or you can create another function for initializing the tracer and call it in some other block of code.

var resources = DefaultResources().get()

let instrumentationScopeName = "SwiftExample"
let instrumentationScopeVersion = "semver:0.1.0"

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

let grpcChannel = ClientConnection.usingPlatformAppropriateTLS(for: MultiThreadedEventLoopGroup(numberOfThreads:1)).connect(host: "http://localhost", port: 4317)

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)
        .build()
)

let tracer = OpenTelemetry.instance.tracerProvider.get(instrumentationName: instrumentationScopeName, instrumentationVersion: instrumentationScopeVersion)

Step 4: Send Telemetry data to SigNoz

To send telemetry data to SigNoz, you can create a function to add spans and data. This is a sample function

let sampleKey = "sampleKey"
let sampleValue = "sampleValue"

func doWork() {
    let childSpan = tracer.spanBuilder(spanName: "doWork").setSpanKind(spanKind: .client).startSpan()
    childSpan.setAttribute(key: sampleKey, value: sampleValue)
    Thread.sleep(forTimeInterval: Double.random(in: 0 ..< 10) / 100)
    childSpan.end()
}

Step 5: Run app

Run your app using the below command to send your traces:

swift run

Sample Swift Application

We have included a sample Swift application at Sample swift App Github Repo,

Was this page helpful?